]> git.ipfire.org Git - people/ms/dnsmasq.git/commitdiff
Add --dns-rr option.
authorSimon Kelley <simon@thekelleys.org.uk>
Mon, 28 May 2012 20:39:57 +0000 (21:39 +0100)
committerSimon Kelley <simon@thekelleys.org.uk>
Mon, 28 May 2012 20:39:57 +0000 (21:39 +0100)
CHANGELOG
man/dnsmasq.8
src/dnsmasq.h
src/option.c
src/rfc1035.c
src/util.c

index 11d4c7fba70922ea156011a7dd5714807c5c05d7..13586259456a4ba4afb2a469ab8d7bf0cd2c63d3 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -16,6 +16,8 @@ version 2.62
            router-advertisement configured, but DHCPv6 not
            configured. Thanks to Marien Zwart for the patch.
 
+           Add --dns-rr, to allow arbitrary DNS resource records.
+
 
 version 2.61
            Re-write interface discovery code on *BSD to use
index 0a3b5df4a6013e70bb8ed33d69704f5c8ac86000..3c51f788b66121f4f7dc213e18e97c4683c2d5ef 100644 (file)
@@ -454,6 +454,12 @@ hosts files) or from DHCP. If the target does not satisfy this
 criteria, the whole cname is ignored. The cname must be unique, but it
 is permissable to have more than one cname pointing to the same target.
 .TP
+.B --dns-rr=<name>,<RR-number>,[<hex data>]
+Return an arbitrary DNS Resource Record. The number is the type of the
+record (which is always in the C_IN class). The value of the record is
+given by the hex data, which may be of the for 01:23:45 or 01 23 45 or
+012345 or any mixture of these.
+.TP
 .B --interface-name=<name>,<interface>
 Return a DNS record associating the name with the primary address on
 the given interface. This flag specifies an A record for the given
index 445efad360eaebf57df1a33718d996b7829fed14..4b24acc49b5884c19840f2c46adc33dab93f05e8 100644 (file)
@@ -732,7 +732,7 @@ extern struct daemon {
   time_t last_resolv;
   struct mx_srv_record *mxnames;
   struct naptr *naptr;
-  struct txt_record *txt;
+  struct txt_record *txt, *rr;
   struct ptr_record *ptr;
   struct host_record *host_records, *host_records_tail;
   struct cname *cnames;
index 5cb7d7b1cc5c33b533567656961ca610834c80d9..34485327a54ae8b489730c111f2156c4aac89d39 100644 (file)
@@ -118,6 +118,7 @@ struct myoption {
 #define LOPT_DUID      307
 #define LOPT_HOST_REC  308
 #define LOPT_TFTP_LC   309
+#define LOPT_RR        310
 
 #ifdef HAVE_GETOPT_LONG
 static const struct option opts[] =  
@@ -181,6 +182,7 @@ static const struct myoption opts[] =
     { "srv-host", 1, 0, 'W' },
     { "localise-queries", 0, 0, 'y' },
     { "txt-record", 1, 0, 'Y' },
+    { "dns-rr", 1, 0, LOPT_RR },
     { "enable-dbus", 0, 0, '1' },
     { "bootp-dynamic", 2, 0, '3' },
     { "dhcp-mac", 1, 0, '4' },
@@ -371,6 +373,7 @@ static struct {
   { LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
   { LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
   { LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
+  { LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
   { 0, 0, NULL, NULL, NULL }
 }; 
 
@@ -2214,6 +2217,7 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
                        }
 
                      if (len == -1)
+
                        problem = _("bad hex constant");
                      else if ((new->clid = opt_malloc(len)))
                        {
@@ -2931,7 +2935,42 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
          }
        break;
       }
-       
+
+    case LOPT_RR: /* dns-rr */
+      {
+               struct txt_record *new;
+       size_t len;
+       char *data;
+       int val;
+
+       comma = split(arg);
+       data = split(comma);
+               
+       new = opt_malloc(sizeof(struct txt_record));
+       new->next = daemon->rr;
+       daemon->rr = new;
+       
+       if (!atoi_check(comma, &val) || 
+           !(new->name = canonicalise_opt(arg)) ||
+           (data && (len = parse_hex(data, (unsigned char *)data, -1, NULL, NULL)) == -1))
+         {
+           problem = _("bad RR record");
+           break;
+         }
+       
+       new->class = val;
+       new->len = 0;
+       
+       if (data)
+         {
+           new->txt=opt_malloc(len);
+           new->len = len;
+           memcpy(new->txt, data, len);
+         }
+       
+       break;
+      }
+
     case 'Y':  /* --txt-record */
       {
        struct txt_record *new;
index 9b84101d3b93f47716440e7de6bb2019ea56a795..67325ca513c6e220106facb075acb42cbda03764 100644 (file)
@@ -1250,7 +1250,8 @@ static int add_resource_record(struct dns_header *header, char *limit, int *trun
       case 't':
        usval = va_arg(ap, int);
        sval = va_arg(ap, char *);
-       memcpy(p, sval, usval);
+       if (usval != 0)
+         memcpy(p, sval, usval);
        p += usval;
        break;
 
@@ -1393,6 +1394,22 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
 
       if (qclass == C_IN)
        {
+         struct txt_record *t;
+
+         for (t = daemon->rr; t; t = t->next)
+           if ((t->class == qtype || qtype == T_ANY) && hostname_isequal(name, t->name))
+             {
+               ans = 1;
+               if (!dryrun)
+                 {
+                   log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
+                   if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, 
+                                           daemon->local_ttl, NULL,
+                                           t->class, C_IN, "t", t->len, t->txt))
+                     anscount ++;
+                 }
+             }
+               
          if (qtype == T_PTR || qtype == T_ANY)
            {
              /* see if it's w.z.y.z.in-addr.arpa format */
index 07f0338c9a5156b941a04f307ce9c221e3c817a8..a1d47d6dd0c7e35902b16b1ae0c70185bb53ca21 100644 (file)
@@ -426,7 +426,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
   
   while (maxlen == -1 || i < maxlen)
     {
-      for (r = in; *r != 0 && *r != ':' && *r != '-'; r++)
+      for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
        if (*r != '*' && !isxdigit((unsigned char)*r))
          return -1;
       
@@ -444,12 +444,29 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
          else
            {
              *r = 0;
-             mask = mask << 1;
              if (strcmp(in, "*") == 0)
-               mask |= 1;
+               {
+                 mask = (mask << 1) | 1;
+                 i++;
+               }
              else
-               out[i] = strtol(in, NULL, 16);
-             i++;
+               {
+                 int j, bytes = (1 + (r - in))/2;
+                 for (j = 0; j < bytes; j++)
+                   { 
+                     char sav;
+                     if (j < bytes - 1)
+                       {
+                         sav = in[(j+1)*2];
+                         in[(j+1)*2] = 0;
+                       }
+                     out[i] = strtol(&in[j*2], NULL, 16);
+                     mask = mask << 1;
+                     i++;
+                     if (j < bytes - 1)
+                       in[(j+1)*2] = sav;
+                   }
+               }
            }
        }
       in = r+1;