| diff -Nur dnsmasq-2.39-orig/bld/Makefile dnsmasq-2.39/bld/Makefile |
| --- dnsmasq-2.39-orig/bld/Makefile 2007-02-17 14:37:06.000000000 +0100 |
| +++ dnsmasq-2.39/bld/Makefile 2007-05-20 18:23:44.000000000 +0200 |
| @@ -2,7 +2,7 @@ |
| PKG_CONFIG ?= pkg-config |
| |
| |
| -OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \ |
| +OBJS = cache.o rfc1035.o rfc1876.o util.o option.o forward.o isc.o network.o \ |
| dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ |
| helper.o tftp.o log.o |
| |
| diff -Nur dnsmasq-2.39-orig/src/dnsmasq.h dnsmasq-2.39/src/dnsmasq.h |
| --- dnsmasq-2.39-orig/src/dnsmasq.h 2007-04-20 12:53:38.000000000 +0200 |
| +++ dnsmasq-2.39/src/dnsmasq.h 2007-05-20 19:50:37.000000000 +0200 |
| @@ -162,6 +162,12 @@ |
| struct interface_name *next; |
| }; |
| |
| +struct loc_record { |
| + char *name, loc[16]; |
| + unsigned short class; |
| + struct loc_record *next; |
| +}; |
| + |
| union bigname { |
| char name[MAXDNAME]; |
| union bigname *next; /* freelist */ |
| @@ -476,6 +482,7 @@ |
| struct mx_srv_record *mxnames; |
| struct txt_record *txt; |
| struct ptr_record *ptr; |
| + struct loc_record *loc; |
| struct interface_name *int_names; |
| char *mxtarget; |
| char *lease_file; |
| @@ -725,3 +732,6 @@ |
| void tftp_request(struct listener *listen, struct daemon *daemon, time_t now); |
| void check_tftp_listeners(struct daemon *daemon, fd_set *rset, time_t now); |
| #endif |
| + |
| +/* rfc1876 */ |
| +u_int32_t loc_aton(const char *ascii, u_char *binary); |
| diff -Nur dnsmasq-2.39-orig/src/option.c dnsmasq-2.39/src/option.c |
| --- dnsmasq-2.39-orig/src/option.c 2007-04-19 23:34:49.000000000 +0200 |
| +++ dnsmasq-2.39/src/option.c 2007-05-20 20:15:15.000000000 +0200 |
| @@ -43,6 +43,7 @@ |
| #define LOPT_REMOTE 269 |
| #define LOPT_SUBSCR 270 |
| #define LOPT_INTNAME 271 |
| +#define LOPT_LOC 272 |
| |
| #ifdef HAVE_GETOPT_LONG |
| static const struct option opts[] = |
| @@ -122,6 +123,7 @@ |
| {"tftp-root", 1, 0, LOPT_PREFIX }, |
| {"tftp-max", 1, 0, LOPT_TFTP_MAX }, |
| {"ptr-record", 1, 0, LOPT_PTR }, |
| + {"loc-record", 1, 0, LOPT_LOC }, |
| #if defined(__FreeBSD__) || defined(__DragonFly__) |
| {"bridge-interface", 1, 0 , LOPT_BRIDGE }, |
| #endif |
| @@ -235,6 +237,7 @@ |
| { "-y, --localise-queries", gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL }, |
| { "-Y --txt-record=name,txt....", gettext_noop("Specify TXT DNS record."), NULL }, |
| { " --ptr-record=name,target", gettext_noop("Specify PTR DNS record."), NULL }, |
| + { " --loc-record=name,lat lon alt", gettext_noop("Specify LOC DNS record."), NULL }, |
| { " --interface-name=name,interface", gettext_noop("Give DNS name to IPv4 address of interface."), NULL }, |
| { "-z, --bind-interfaces", gettext_noop("Bind only to interfaces in use."), NULL }, |
| { "-Z, --read-ethers", gettext_noop("Read DHCP static host information from %s."), ETHERSFILE }, |
| @@ -1835,6 +1838,37 @@ |
| new->intr = safe_string_alloc(comma); |
| break; |
| } |
| + |
| + case LOPT_LOC: |
| + { |
| + struct loc_record *new; |
| + unsigned char *p, *q; |
| + |
| + comma = split(arg); |
| + |
| + if (!canonicalise_opt(arg)) |
| + { |
| + option = '?'; |
| + problem = _("bad LOC record"); |
| + break; |
| + } |
| + |
| + new = safe_malloc(sizeof(struct loc_record)); |
| + new->next = daemon->loc; |
| + daemon->loc = new; |
| + new->class = C_IN; |
| + if (!comma || loc_aton(comma,new->loc)!=16) |
| + { |
| + option = '?'; |
| + problem = _("bad LOC record"); |
| + break; |
| + } |
| + |
| + if (comma) |
| + *comma = 0; |
| + new->name = safe_string_alloc(arg); |
| + break; |
| + } |
| |
| case LOPT_PTR: /* --ptr-record */ |
| { |
| diff -Nur dnsmasq-2.39-orig/src/rfc1035.c dnsmasq-2.39/src/rfc1035.c |
| --- dnsmasq-2.39-orig/src/rfc1035.c 2007-04-20 12:54:26.000000000 +0200 |
| +++ dnsmasq-2.39/src/rfc1035.c 2007-05-20 18:22:46.000000000 +0200 |
| @@ -1112,6 +1112,27 @@ |
| } |
| } |
| |
| + if (qtype == T_LOC || qtype == T_ANY) |
| + { |
| + struct loc_record *t; |
| + for(t = daemon->loc; t ; t = t->next) |
| + { |
| + if (t->class == qclass && hostname_isequal(name, t->name)) |
| + { |
| + ans = 1; |
| + if (!dryrun) |
| + { |
| + log_query(F_CNAME | F_FORWARD | F_CONFIG | F_NXDOMAIN, name, NULL, 0, NULL, 0); |
| + if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, |
| + daemon->local_ttl, NULL, |
| + T_LOC, t->class, "t", 16, t->loc)) |
| + anscount++; |
| + |
| + } |
| + } |
| + } |
| + } |
| + |
| if (qclass == C_IN) |
| { |
| if (qtype == T_PTR || qtype == T_ANY) |
| diff -Nur dnsmasq-2.39-orig/src/rfc1876.c dnsmasq-2.39/src/rfc1876.c |
| --- dnsmasq-2.39-orig/src/rfc1876.c 1970-01-01 01:00:00.000000000 +0100 |
| +++ dnsmasq-2.39/src/rfc1876.c 2007-05-20 19:50:10.000000000 +0200 |
| @@ -0,0 +1,379 @@ |
| +/* |
| + * routines to convert between on-the-wire RR format and zone file |
| + * format. Does not contain conversion to/from decimal degrees; |
| + * divide or multiply by 60*60*1000 for that. |
| + */ |
| + |
| +#include "dnsmasq.h" |
| + |
| +static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, |
| + 1000000,10000000,100000000,1000000000}; |
| + |
| +/* takes an XeY precision/size value, returns a string representation.*/ |
| +static const char * |
| +precsize_ntoa(u_int8_t prec) |
| +{ |
| + static char retbuf[sizeof("90000000.00")]; |
| + unsigned long val; |
| + int mantissa, exponent; |
| + |
| + mantissa = (int)((prec >> 4) & 0x0f) % 10; |
| + exponent = (int)((prec >> 0) & 0x0f) % 10; |
| + |
| + val = mantissa * poweroften[exponent]; |
| + |
| + (void) sprintf(retbuf,"%d.%.2d", val/100, val%100); |
| + return (retbuf); |
| +} |
| + |
| +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer.*/ |
| +static u_int8_t |
| +precsize_aton(char **strptr) |
| +{ |
| + unsigned int mval = 0, cmval = 0; |
| + u_int8_t retval = 0; |
| + register char *cp; |
| + register int exponent; |
| + register int mantissa; |
| + |
| + cp = *strptr; |
| + |
| + while (isdigit(*cp)) |
| + mval = mval * 10 + (*cp++ - '0'); |
| + |
| + if (*cp == '.') { /* centimeters */ |
| + cp++; |
| + if (isdigit(*cp)) { |
| + cmval = (*cp++ - '0') * 10; |
| + if (isdigit(*cp)) { |
| + cmval += (*cp++ - '0'); |
| + } |
| + } |
| + } |
| + cmval = (mval * 100) + cmval; |
| + |
| + for (exponent = 0; exponent < 9; exponent++) |
| + if (cmval < poweroften[exponent+1]) |
| + break; |
| + |
| + mantissa = cmval / poweroften[exponent]; |
| + if (mantissa > 9) |
| + mantissa = 9; |
| + |
| + retval = (mantissa << 4) | exponent; |
| + |
| + *strptr = cp; |
| + |
| + return (retval); |
| +} |
| + |
| +/* converts ascii lat/lon to unsigned encoded 32-bit number. |
| + * moves pointer. */ |
| +static u_int32_t |
| +latlon2ul(char **latlonstrptr,int *which) |
| +{ |
| + register char *cp; |
| + u_int32_t retval; |
| + int deg = 0, min = 0, secs = 0, secsfrac = 0; |
| + |
| + cp = *latlonstrptr; |
| + |
| + while (isdigit(*cp)) |
| + deg = deg * 10 + (*cp++ - '0'); |
| + |
| + while (isspace(*cp)) |
| + cp++; |
| + |
| + if (!(isdigit(*cp))) |
| + goto fndhemi; |
| + |
| + while (isdigit(*cp)) |
| + min = min * 10 + (*cp++ - '0'); |
| + while (isspace(*cp)) |
| + cp++; |
| + |
| + if (!(isdigit(*cp))) |
| + goto fndhemi; |
| + |
| + while (isdigit(*cp)) |
| + secs = secs * 10 + (*cp++ - '0'); |
| + |
| + if (*cp == '.') { /* decimal seconds */ |
| + cp++; |
| + if (isdigit(*cp)) { |
| + secsfrac = (*cp++ - '0') * 100; |
| + if (isdigit(*cp)) { |
| + secsfrac += (*cp++ - '0') * 10; |
| + if (isdigit(*cp)) { |
| + secsfrac += (*cp++ - '0'); |
| + } |
| + } |
| + } |
| + } |
| + |
| + while (!isspace(*cp)) /* if any trailing garbage */ |
| + cp++; |
| + |
| + while (isspace(*cp)) |
| + cp++; |
| + |
| + fndhemi: |
| + switch (*cp) { |
| + case 'N': case 'n': |
| + case 'E': case 'e': |
| + retval = ((unsigned)1<<31) |
| + + (((((deg * 60) + min) * 60) + secs) * 1000) |
| + + secsfrac; |
| + break; |
| + case 'S': case 's': |
| + case 'W': case 'w': |
| + retval = ((unsigned)1<<31) |
| + - (((((deg * 60) + min) * 60) + secs) * 1000) |
| + - secsfrac; |
| + break; |
| + default: |
| + retval = 0; /* invalid value -- indicates error */ |
| + break; |
| + } |
| + |
| + switch (*cp) { |
| + case 'N': case 'n': |
| + case 'S': case 's': |
| + *which = 1; /* latitude */ |
| + break; |
| + case 'E': case 'e': |
| + case 'W': case 'w': |
| + *which = 2; /* longitude */ |
| + break; |
| + default: |
| + *which = 0; /* error */ |
| + break; |
| + } |
| + |
| + cp++; /* skip the hemisphere */ |
| + |
| + while (!isspace(*cp)) /* if any trailing garbage */ |
| + cp++; |
| + |
| + while (isspace(*cp)) /* move to next field */ |
| + cp++; |
| + |
| + *latlonstrptr = cp; |
| + |
| + return (retval); |
| +} |
| + |
| +/* converts a zone file representation in a string to an RDATA |
| + * on-the-wire representation. */ |
| +u_int32_t |
| +loc_aton(const char *ascii, u_char *binary) |
| +{ |
| + const char *cp, *maxcp; |
| + u_char *bcp; |
| + |
| + u_int32_t latit = 0, longit = 0, alt = 0; |
| + u_int32_t lltemp1 = 0, lltemp2 = 0; |
| + int altmeters = 0, altfrac = 0, altsign = 1; |
| + u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ |
| + u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ |
| + u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ |
| + int which1 = 0, which2 = 0; |
| + |
| + cp = ascii; |
| + maxcp = cp + strlen(ascii); |
| + |
| + lltemp1 = latlon2ul(&cp, &which1); |
| + lltemp2 = latlon2ul(&cp, &which2); |
| + |
| + switch (which1 + which2) { |
| + case 3: /* 1 + 2, the only valid combination */ |
| + if ((which1 == 1) && (which2 == 2)) { /* normal case */ |
| + latit = lltemp1; |
| + longit = lltemp2; |
| + } else if ((which1 == 2) && (which2 == 1)) {/*reversed*/ |
| + longit = lltemp1; |
| + latit = lltemp2; |
| + } else { /* some kind of brokenness */ |
| + return 0; |
| + } |
| + break; |
| + default: /* we didn't get one of each */ |
| + return 0; |
| + } |
| + |
| + /* altitude */ |
| + if (*cp == '-') { |
| + altsign = -1; |
| + cp++; |
| + } |
| + |
| + if (*cp == '+') |
| + cp++; |
| + |
| + while (isdigit(*cp)) |
| + altmeters = altmeters * 10 + (*cp++ - '0'); |
| + |
| + if (*cp == '.') { /* decimal meters */ |
| + cp++; |
| + if (isdigit(*cp)) { |
| + altfrac = (*cp++ - '0') * 10; |
| + if (isdigit(*cp)) { |
| + altfrac += (*cp++ - '0'); |
| + } |
| + } |
| + } |
| + |
| + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); |
| + |
| + while (!isspace(*cp) && (cp < maxcp)) |
| + /* if trailing garbage or m */ |
| + cp++; |
| + |
| + while (isspace(*cp) && (cp < maxcp)) |
| + cp++; |
| + if (cp >= maxcp) |
| + goto defaults; |
| + |
| + siz = precsize_aton(&cp); |
| + |
| + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ |
| + cp++; |
| + |
| + while (isspace(*cp) && (cp < maxcp)) |
| + cp++; |
| + |
| + if (cp >= maxcp) |
| + goto defaults; |
| + |
| + hp = precsize_aton(&cp); |
| + |
| + while (!isspace(*cp) && (cp < maxcp))/*if trailing garbage or m*/ |
| + cp++; |
| + |
| + while (isspace(*cp) && (cp < maxcp)) |
| + cp++; |
| + |
| + if (cp >= maxcp) |
| + goto defaults; |
| + |
| + vp = precsize_aton(&cp); |
| + |
| + defaults: |
| + |
| + bcp = binary; |
| + *bcp++ = (u_int8_t) 0; /* version byte */ |
| + *bcp++ = siz; |
| + *bcp++ = hp; |
| + *bcp++ = vp; |
| + PUTLONG(latit,bcp); |
| + PUTLONG(longit,bcp); |
| + PUTLONG(alt,bcp); |
| + |
| + return (16); /* size of RR in octets */ |
| +} |
| + |
| +/* takes an on-the-wire LOC RR and prints it in zone file |
| + * (human readable) format. */ |
| +char * |
| +loc_ntoa(const u_char *binary,char *ascii) |
| +{ |
| + static char tmpbuf[255*3]; |
| + |
| + register char *cp; |
| + register const u_char *rcp; |
| + |
| + int latdeg, latmin, latsec, latsecfrac; |
| + int longdeg, longmin, longsec, longsecfrac; |
| + char northsouth, eastwest; |
| + int altmeters, altfrac, altsign; |
| + |
| + const int referencealt = 100000 * 100; |
| + |
| + int32_t latval, longval, altval; |
| + u_int32_t templ; |
| + u_int8_t sizeval, hpval, vpval, versionval; |
| + |
| + char *sizestr, *hpstr, *vpstr; |
| + |
| + rcp = binary; |
| + if (ascii) |
| + cp = ascii; |
| + else { |
| + cp = tmpbuf; |
| + } |
| + |
| + versionval = *rcp++; |
| + |
| + if (versionval) { |
| + sprintf(cp,"; error: unknown LOC RR version"); |
| + return (cp); |
| + } |
| + |
| + sizeval = *rcp++; |
| + |
| + hpval = *rcp++; |
| + vpval = *rcp++; |
| + |
| + GETLONG(templ,rcp); |
| + latval = (templ - ((unsigned)1<<31)); |
| + |
| + GETLONG(templ,rcp); |
| + longval = (templ - ((unsigned)1<<31)); |
| + |
| + GETLONG(templ,rcp); |
| + if (templ < referencealt) { /* below WGS 84 spheroid */ |
| + altval = referencealt - templ; |
| + altsign = -1; |
| + } else { |
| + altval = templ - referencealt; |
| + altsign = 1; |
| + } |
| + |
| + if (latval < 0) { |
| + northsouth = 'S'; |
| + latval = -latval; |
| + } |
| + else |
| + northsouth = 'N'; |
| + |
| + latsecfrac = latval % 1000; |
| + latval = latval / 1000; |
| + latsec = latval % 60; |
| + latval = latval / 60; |
| + latmin = latval % 60; |
| + latval = latval / 60; |
| + latdeg = latval; |
| + |
| + if (longval < 0) { |
| + eastwest = 'W'; |
| + longval = -longval; |
| + } |
| + else |
| + eastwest = 'E'; |
| + |
| + longsecfrac = longval % 1000; |
| + longval = longval / 1000; |
| + longsec = longval % 60; |
| + longval = longval / 60; |
| + longmin = longval % 60; |
| + longval = longval / 60; |
| + longdeg = longval; |
| + |
| + altfrac = altval % 100; |
| + altmeters = (altval / 100) * altsign; |
| + |
| + sizestr = strdup(precsize_ntoa(sizeval)); |
| + hpstr = strdup(precsize_ntoa(hpval)); |
| + vpstr = strdup(precsize_ntoa(vpval)); |
| + |
| + sprintf(cp, |
| + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm", |
| + latdeg, latmin, latsec, latsecfrac, northsouth, |
| + longdeg, longmin, longsec, longsecfrac, eastwest, |
| + altmeters, altfrac, sizestr, hpstr, vpstr); |
| + free(sizestr); |
| + free(hpstr); |
| + free(vpstr); |
| + |
| + return (cp); |
| +} |