1diff -Nur dnsmasq-2.39-orig/bld/Makefile dnsmasq-2.39/bld/Makefile 2--- dnsmasq-2.39-orig/bld/Makefile 2007-02-17 14:37:06.000000000 +0100 3+++ dnsmasq-2.39/bld/Makefile 2007-05-20 18:23:44.000000000 +0200 4@@ -2,7 +2,7 @@ 5 PKG_CONFIG ?= pkg-config 6 7 8-OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \ 9+OBJS = cache.o rfc1035.o rfc1876.o util.o option.o forward.o isc.o network.o \ 10 dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ 11 helper.o tftp.o log.o 12 13diff -Nur dnsmasq-2.39-orig/src/dnsmasq.h dnsmasq-2.39/src/dnsmasq.h 14--- dnsmasq-2.39-orig/src/dnsmasq.h 2007-04-20 12:53:38.000000000 +0200 15+++ dnsmasq-2.39/src/dnsmasq.h 2007-05-20 19:50:37.000000000 +0200 16@@ -162,6 +162,12 @@ 17 struct interface_name *next; 18 }; 19 20+struct loc_record { 21+ char *name, loc[16]; 22+ unsigned short class; 23+ struct loc_record *next; 24+}; 25+ 26 union bigname { 27 char name[MAXDNAME]; 28 union bigname *next; /* freelist */ 29@@ -476,6 +482,7 @@ 30 struct mx_srv_record *mxnames; 31 struct txt_record *txt; 32 struct ptr_record *ptr; 33+ struct loc_record *loc; 34 struct interface_name *int_names; 35 char *mxtarget; 36 char *lease_file; 37@@ -725,3 +732,6 @@ 38 void tftp_request(struct listener *listen, struct daemon *daemon, time_t now); 39 void check_tftp_listeners(struct daemon *daemon, fd_set *rset, time_t now); 40 #endif 41+ 42+/* rfc1876 */ 43+u_int32_t loc_aton(const char *ascii, u_char *binary); 44diff -Nur dnsmasq-2.39-orig/src/option.c dnsmasq-2.39/src/option.c 45--- dnsmasq-2.39-orig/src/option.c 2007-04-19 23:34:49.000000000 +0200 46+++ dnsmasq-2.39/src/option.c 2007-05-20 20:15:15.000000000 +0200 47@@ -43,6 +43,7 @@ 48 #define LOPT_REMOTE 269 49 #define LOPT_SUBSCR 270 50 #define LOPT_INTNAME 271 51+#define LOPT_LOC 272 52 53 #ifdef HAVE_GETOPT_LONG 54 static const struct option opts[] = 55@@ -122,6 +123,7 @@ 56 {"tftp-root", 1, 0, LOPT_PREFIX }, 57 {"tftp-max", 1, 0, LOPT_TFTP_MAX }, 58 {"ptr-record", 1, 0, LOPT_PTR }, 59+ {"loc-record", 1, 0, LOPT_LOC }, 60 #if defined(__FreeBSD__) || defined(__DragonFly__) 61 {"bridge-interface", 1, 0 , LOPT_BRIDGE }, 62 #endif 63@@ -235,6 +237,7 @@ 64 { "-y, --localise-queries", gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL }, 65 { "-Y --txt-record=name,txt....", gettext_noop("Specify TXT DNS record."), NULL }, 66 { " --ptr-record=name,target", gettext_noop("Specify PTR DNS record."), NULL }, 67+ { " --loc-record=name,lat lon alt", gettext_noop("Specify LOC DNS record."), NULL }, 68 { " --interface-name=name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL }, 69 { "-z, --bind-interfaces", gettext_noop("Bind only to interfaces in use."), NULL }, 70 { "-Z, --read-ethers", gettext_noop("Read DHCP static host information from %s."), ETHERSFILE }, 71@@ -1835,6 +1838,37 @@ 72 new->intr = safe_string_alloc(comma); 73 break; 74 } 75+ 76+ case LOPT_LOC: 77+ { 78+ struct loc_record *new; 79+ unsigned char *p, *q; 80+ 81+ comma = split(arg); 82+ 83+ if (!canonicalise_opt(arg)) 84+ { 85+ option = '?'; 86+ problem = _("bad LOC record"); 87+ break; 88+ } 89+ 90+ new = safe_malloc(sizeof(struct loc_record)); 91+ new->next = daemon->loc; 92+ daemon->loc = new; 93+ new->class = C_IN; 94+ if (!comma || loc_aton(comma,new->loc)!=16) 95+ { 96+ option = '?'; 97+ problem = _("bad LOC record"); 98+ break; 99+ } 100+ 101+ if (comma) 102+ *comma = 0; 103+ new->name = safe_string_alloc(arg); 104+ break; 105+ } 106 107 case LOPT_PTR: /* --ptr-record */ 108 { 109diff -Nur dnsmasq-2.39-orig/src/rfc1035.c dnsmasq-2.39/src/rfc1035.c 110--- dnsmasq-2.39-orig/src/rfc1035.c 2007-04-20 12:54:26.000000000 +0200 111+++ dnsmasq-2.39/src/rfc1035.c 2007-05-20 18:22:46.000000000 +0200 112@@ -1112,6 +1112,27 @@ 113 } 114 } 115 116+ if (qtype == T_LOC || qtype == T_ANY) 117+ { 118+ struct loc_record *t; 119+ for(t = daemon->loc; t ; t = t->next) 120+ { 121+ if (t->class == qclass && hostname_isequal(name, t->name)) 122+ { 123+ ans = 1; 124+ if (!dryrun) 125+ { 126+ log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, 0, NULL, 0); 127+ if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 128+ daemon->local_ttl, NULL, 129+ T_LOC, t->class, "t", 16, t->loc)) 130+ anscount++; 131+ 132+ } 133+ } 134+ } 135+ } 136+ 137 if (qclass == C_IN) 138 { 139 if (qtype == T_PTR || qtype == T_ANY) 140diff -Nur dnsmasq-2.39-orig/src/rfc1876.c dnsmasq-2.39/src/rfc1876.c 141--- dnsmasq-2.39-orig/src/rfc1876.c 1970-01-01 01:00:00.000000000 +0100 142+++ dnsmasq-2.39/src/rfc1876.c 2007-05-20 19:50:10.000000000 +0200 143@@ -0,0 +1,379 @@ 144+/* 145+ * routines to convert between on-the-wire RR format and zone file 146+ * format. Does not contain conversion to/from decimal degrees; 147+ * divide or multiply by 60*60*1000 for that. 148+ */ 149+ 150+#include "dnsmasq.h" 151+ 152+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, 153+ 1000000,10000000,100000000,1000000000}; 154+ 155+/* takes an XeY precision/size value, returns a string representation.*/ 156+static const char * 157+precsize_ntoa(u_int8_t prec) 158+{ 159+ static char retbuf[sizeof("90000000.00")]; 160+ unsigned long val; 161+ int mantissa, exponent; 162+ 163+ mantissa = (int)((prec >> 4) & 0x0f) % 10; 164+ exponent = (int)((prec >> 0) & 0x0f) % 10; 165+ 166+ val = mantissa * poweroften[exponent]; 167+ 168+ (void) sprintf(retbuf,"%d.%.2d", val/100, val%100); 169+ return (retbuf); 170+} 171+ 172+/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/ 173+static u_int8_t 174+precsize_aton(char **strptr) 175+{ 176+ unsigned int mval = 0, cmval = 0; 177+ u_int8_t retval = 0; 178+ register char *cp; 179+ register int exponent; 180+ register int mantissa; 181+ 182+ cp = *strptr; 183+ 184+ while (isdigit(*cp)) 185+ mval = mval * 10 + (*cp++ - '0'); 186+ 187+ if (*cp == '.') { /* centimeters */ 188+ cp++; 189+ if (isdigit(*cp)) { 190+ cmval = (*cp++ - '0') * 10; 191+ if (isdigit(*cp)) { 192+ cmval += (*cp++ - '0'); 193+ } 194+ } 195+ } 196+ cmval = (mval * 100) + cmval; 197+ 198+ for (exponent = 0; exponent < 9; exponent++) 199+ if (cmval < poweroften[exponent+1]) 200+ break; 201+ 202+ mantissa = cmval / poweroften[exponent]; 203+ if (mantissa > 9) 204+ mantissa = 9; 205+ 206+ retval = (mantissa << 4) | exponent; 207+ 208+ *strptr = cp; 209+ 210+ return (retval); 211+} 212+ 213+/* converts ascii lat/lon to unsigned encoded 32-bit number. 214+ * moves pointer. */ 215+static u_int32_t 216+latlon2ul(char **latlonstrptr,int *which) 217+{ 218+ register char *cp; 219+ u_int32_t retval; 220+ int deg = 0, min = 0, secs = 0, secsfrac = 0; 221+ 222+ cp = *latlonstrptr; 223+ 224+ while (isdigit(*cp)) 225+ deg = deg * 10 + (*cp++ - '0'); 226+ 227+ while (isspace(*cp)) 228+ cp++; 229+ 230+ if (!(isdigit(*cp))) 231+ goto fndhemi; 232+ 233+ while (isdigit(*cp)) 234+ min = min * 10 + (*cp++ - '0'); 235+ while (isspace(*cp)) 236+ cp++; 237+ 238+ if (!(isdigit(*cp))) 239+ goto fndhemi; 240+ 241+ while (isdigit(*cp)) 242+ secs = secs * 10 + (*cp++ - '0'); 243+ 244+ if (*cp == '.') { /* decimal seconds */ 245+ cp++; 246+ if (isdigit(*cp)) { 247+ secsfrac = (*cp++ - '0') * 100; 248+ if (isdigit(*cp)) { 249+ secsfrac += (*cp++ - '0') * 10; 250+ if (isdigit(*cp)) { 251+ secsfrac += (*cp++ - '0'); 252+ } 253+ } 254+ } 255+ } 256+ 257+ while (!isspace(*cp)) /* if any trailing garbage */ 258+ cp++; 259+ 260+ while (isspace(*cp)) 261+ cp++; 262+ 263+ fndhemi: 264+ switch (*cp) { 265+ case 'N': case 'n': 266+ case 'E': case 'e': 267+ retval = ((unsigned)1<<31) 268+ + (((((deg * 60) + min) * 60) + secs) * 1000) 269+ + secsfrac; 270+ break; 271+ case 'S': case 's': 272+ case 'W': case 'w': 273+ retval = ((unsigned)1<<31) 274+ - (((((deg * 60) + min) * 60) + secs) * 1000) 275+ - secsfrac; 276+ break; 277+ default: 278+ retval = 0; /* invalid value -- indicates error */ 279+ break; 280+ } 281+ 282+ switch (*cp) { 283+ case 'N': case 'n': 284+ case 'S': case 's': 285+ *which = 1; /* latitude */ 286+ break; 287+ case 'E': case 'e': 288+ case 'W': case 'w': 289+ *which = 2; /* longitude */ 290+ break; 291+ default: 292+ *which = 0; /* error */ 293+ break; 294+ } 295+ 296+ cp++; /* skip the hemisphere */ 297+ 298+ while (!isspace(*cp)) /* if any trailing garbage */ 299+ cp++; 300+ 301+ while (isspace(*cp)) /* move to next field */ 302+ cp++; 303+ 304+ *latlonstrptr = cp; 305+ 306+ return (retval); 307+} 308+ 309+/* converts a zone file representation in a string to an RDATA 310+ * on-the-wire representation. */ 311+u_int32_t 312+loc_aton(const char *ascii, u_char *binary) 313+{ 314+ const char *cp, *maxcp; 315+ u_char *bcp; 316+ 317+ u_int32_t latit = 0, longit = 0, alt = 0; 318+ u_int32_t lltemp1 = 0, lltemp2 = 0; 319+ int altmeters = 0, altfrac = 0, altsign = 1; 320+ u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ 321+ u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ 322+ u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ 323+ int which1 = 0, which2 = 0; 324+ 325+ cp = ascii; 326+ maxcp = cp + strlen(ascii); 327+ 328+ lltemp1 = latlon2ul(&cp, &which1); 329+ lltemp2 = latlon2ul(&cp, &which2); 330+ 331+ switch (which1 + which2) { 332+ case 3: /* 1 + 2, the only valid combination */ 333+ if ((which1 == 1) && (which2 == 2)) { /* normal case */ 334+ latit = lltemp1; 335+ longit = lltemp2; 336+ } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/ 337+ longit = lltemp1; 338+ latit = lltemp2; 339+ } else { /* some kind of brokenness */ 340+ return 0; 341+ } 342+ break; 343+ default: /* we didn't get one of each */ 344+ return 0; 345+ } 346+ 347+ /* altitude */ 348+ if (*cp == '-') { 349+ altsign = -1; 350+ cp++; 351+ } 352+ 353+ if (*cp == '+') 354+ cp++; 355+ 356+ while (isdigit(*cp)) 357+ altmeters = altmeters * 10 + (*cp++ - '0'); 358+ 359+ if (*cp == '.') { /* decimal meters */ 360+ cp++; 361+ if (isdigit(*cp)) { 362+ altfrac = (*cp++ - '0') * 10; 363+ if (isdigit(*cp)) { 364+ altfrac += (*cp++ - '0'); 365+ } 366+ } 367+ } 368+ 369+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); 370+ 371+ while (!isspace(*cp) && (cp < maxcp)) 372+ /* if trailing garbage or m */ 373+ cp++; 374+ 375+ while (isspace(*cp) && (cp < maxcp)) 376+ cp++; 377+ if (cp >= maxcp) 378+ goto defaults; 379+ 380+ siz = precsize_aton(&cp); 381+ 382+ while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ 383+ cp++; 384+ 385+ while (isspace(*cp) && (cp < maxcp)) 386+ cp++; 387+ 388+ if (cp >= maxcp) 389+ goto defaults; 390+ 391+ hp = precsize_aton(&cp); 392+ 393+ while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ 394+ cp++; 395+ 396+ while (isspace(*cp) && (cp < maxcp)) 397+ cp++; 398+ 399+ if (cp >= maxcp) 400+ goto defaults; 401+ 402+ vp = precsize_aton(&cp); 403+ 404+ defaults: 405+ 406+ bcp = binary; 407+ *bcp++ = (u_int8_t) 0; /* version byte */ 408+ *bcp++ = siz; 409+ *bcp++ = hp; 410+ *bcp++ = vp; 411+ PUTLONG(latit,bcp); 412+ PUTLONG(longit,bcp); 413+ PUTLONG(alt,bcp); 414+ 415+ return (16); /* size of RR in octets */ 416+} 417+ 418+/* takes an on-the-wire LOC RR and prints it in zone file 419+ * (human readable) format. */ 420+char * 421+loc_ntoa(const u_char *binary,char *ascii) 422+{ 423+ static char tmpbuf[255*3]; 424+ 425+ register char *cp; 426+ register const u_char *rcp; 427+ 428+ int latdeg, latmin, latsec, latsecfrac; 429+ int longdeg, longmin, longsec, longsecfrac; 430+ char northsouth, eastwest; 431+ int altmeters, altfrac, altsign; 432+ 433+ const int referencealt = 100000 * 100; 434+ 435+ int32_t latval, longval, altval; 436+ u_int32_t templ; 437+ u_int8_t sizeval, hpval, vpval, versionval; 438+ 439+ char *sizestr, *hpstr, *vpstr; 440+ 441+ rcp = binary; 442+ if (ascii) 443+ cp = ascii; 444+ else { 445+ cp = tmpbuf; 446+ } 447+ 448+ versionval = *rcp++; 449+ 450+ if (versionval) { 451+ sprintf(cp,"; error: unknown LOC RR version"); 452+ return (cp); 453+ } 454+ 455+ sizeval = *rcp++; 456+ 457+ hpval = *rcp++; 458+ vpval = *rcp++; 459+ 460+ GETLONG(templ,rcp); 461+ latval = (templ - ((unsigned)1<<31)); 462+ 463+ GETLONG(templ,rcp); 464+ longval = (templ - ((unsigned)1<<31)); 465+ 466+ GETLONG(templ,rcp); 467+ if (templ < referencealt) { /* below WGS 84 spheroid */ 468+ altval = referencealt - templ; 469+ altsign = -1; 470+ } else { 471+ altval = templ - referencealt; 472+ altsign = 1; 473+ } 474+ 475+ if (latval < 0) { 476+ northsouth = 'S'; 477+ latval = -latval; 478+ } 479+ else 480+ northsouth = 'N'; 481+ 482+ latsecfrac = latval % 1000; 483+ latval = latval / 1000; 484+ latsec = latval % 60; 485+ latval = latval / 60; 486+ latmin = latval % 60; 487+ latval = latval / 60; 488+ latdeg = latval; 489+ 490+ if (longval < 0) { 491+ eastwest = 'W'; 492+ longval = -longval; 493+ } 494+ else 495+ eastwest = 'E'; 496+ 497+ longsecfrac = longval % 1000; 498+ longval = longval / 1000; 499+ longsec = longval % 60; 500+ longval = longval / 60; 501+ longmin = longval % 60; 502+ longval = longval / 60; 503+ longdeg = longval; 504+ 505+ altfrac = altval % 100; 506+ altmeters = (altval / 100) * altsign; 507+ 508+ sizestr = strdup(precsize_ntoa(sizeval)); 509+ hpstr = strdup(precsize_ntoa(hpval)); 510+ vpstr = strdup(precsize_ntoa(vpval)); 511+ 512+ sprintf(cp, 513+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm", 514+ latdeg, latmin, latsec, latsecfrac, northsouth, 515+ longdeg, longmin, longsec, longsecfrac, eastwest, 516+ altmeters, altfrac, sizestr, hpstr, vpstr); 517+ free(sizestr); 518+ free(hpstr); 519+ free(vpstr); 520+ 521+ return (cp); 522+} 523