1 diff -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 13 diff -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); 44 diff -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 { 109 diff -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) 140 diff -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