Source code upload
[framework/connectivity/dnsmasq.git] / contrib / dns-loc / dnsmasq2-loc-rfc1876.patch
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 +}