Annotation of embedaddon/dnsmasq/src/dhcp-common.c, revision 1.1.1.1

1.1       misho       1: /* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
                      2: 
                      3:    This program is free software; you can redistribute it and/or modify
                      4:    it under the terms of the GNU General Public License as published by
                      5:    the Free Software Foundation; version 2 dated June, 1991, or
                      6:    (at your option) version 3 dated 29 June, 2007.
                      7:  
                      8:    This program is distributed in the hope that it will be useful,
                      9:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     10:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     11:    GNU General Public License for more details.
                     12:      
                     13:    You should have received a copy of the GNU General Public License
                     14:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
                     15: */
                     16: 
                     17: #include "dnsmasq.h"
                     18: 
                     19: #ifdef HAVE_DHCP
                     20: 
                     21: void dhcp_common_init(void)
                     22: {
                     23:     /* These each hold a DHCP option max size 255
                     24:        and get a terminating zero added */
                     25:   daemon->dhcp_buff = safe_malloc(256);
                     26:   daemon->dhcp_buff2 = safe_malloc(256); 
                     27:   daemon->dhcp_buff3 = safe_malloc(256);
                     28:   
                     29:   /* dhcp_packet is used by v4 and v6, outpacket only by v6 
                     30:      sizeof(struct dhcp_packet) is as good an initial size as any,
                     31:      even for v6 */
                     32:   expand_buf(&daemon->dhcp_packet, sizeof(struct dhcp_packet));
                     33: #ifdef HAVE_DHCP6
                     34:   if (daemon->dhcp6)
                     35:     expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
                     36: #endif
                     37: }
                     38: 
                     39: ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
                     40: {  
                     41:   ssize_t sz;
                     42:  
                     43:   while (1)
                     44:     {
                     45:       msg->msg_flags = 0;
                     46:       while ((sz = recvmsg(fd, msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR);
                     47:       
                     48:       if (sz == -1)
                     49:        return -1;
                     50:       
                     51:       if (!(msg->msg_flags & MSG_TRUNC))
                     52:        break;
                     53: 
                     54:       /* Very new Linux kernels return the actual size needed, 
                     55:         older ones always return truncated size */
                     56:       if ((size_t)sz == msg->msg_iov->iov_len)
                     57:        {
                     58:          if (!expand_buf(msg->msg_iov, sz + 100))
                     59:            return -1;
                     60:        }
                     61:       else
                     62:        {
                     63:          expand_buf(msg->msg_iov, sz);
                     64:          break;
                     65:        }
                     66:     }
                     67:   
                     68:   while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
                     69:   
                     70:   return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
                     71: }
                     72: 
                     73: struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
                     74: {
                     75:   struct tag_if *exprs;
                     76:   struct dhcp_netid_list *list;
                     77: 
                     78:   for (exprs = daemon->tag_if; exprs; exprs = exprs->next)
                     79:     if (match_netid(exprs->tag, tags, 1))
                     80:       for (list = exprs->set; list; list = list->next)
                     81:        {
                     82:          list->list->next = tags;
                     83:          tags = list->list;
                     84:        }
                     85: 
                     86:   return tags;
                     87: }
                     88: 
                     89: 
                     90: struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags, struct dhcp_opt *opts)
                     91: {
                     92:   struct dhcp_netid *tagif = run_tag_if(tags);
                     93:   struct dhcp_opt *opt;
                     94:   struct dhcp_opt *tmp;  
                     95: 
                     96:   /* flag options which are valid with the current tag set (sans context tags) */
                     97:   for (opt = opts; opt; opt = opt->next)
                     98:     {
                     99:       opt->flags &= ~DHOPT_TAGOK;
                    100:       if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
                    101:          match_netid(opt->netid, tagif, 0))
                    102:        opt->flags |= DHOPT_TAGOK;
                    103:     }
                    104: 
                    105:   /* now flag options which are valid, including the context tags,
                    106:      otherwise valid options are inhibited if we found a higher priority one above */
                    107:   if (context_tags)
                    108:     {
                    109:       struct dhcp_netid *last_tag;
                    110: 
                    111:       for (last_tag = context_tags; last_tag->next; last_tag = last_tag->next);
                    112:       last_tag->next = tags;
                    113:       tagif = run_tag_if(context_tags);
                    114:       
                    115:       /* reset stuff with tag:!<tag> which now matches. */
                    116:       for (opt = opts; opt; opt = opt->next)
                    117:        if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925)) &&
                    118:            (opt->flags & DHOPT_TAGOK) &&
                    119:            !match_netid(opt->netid, tagif, 0))
                    120:          opt->flags &= ~DHOPT_TAGOK;
                    121: 
                    122:       for (opt = opts; opt; opt = opt->next)
                    123:        if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) &&
                    124:            match_netid(opt->netid, tagif, 0))
                    125:          {
                    126:            struct dhcp_opt *tmp;  
                    127:            for (tmp = opts; tmp; tmp = tmp->next) 
                    128:              if (tmp->opt == opt->opt && opt->netid && (tmp->flags & DHOPT_TAGOK))
                    129:                break;
                    130:            if (!tmp)
                    131:              opt->flags |= DHOPT_TAGOK;
                    132:          }      
                    133:     }
                    134:   
                    135:   /* now flag untagged options which are not overridden by tagged ones */
                    136:   for (opt = opts; opt; opt = opt->next)
                    137:     if (!(opt->flags & (DHOPT_ENCAPSULATE | DHOPT_VENDOR | DHOPT_RFC3925 | DHOPT_TAGOK)) && !opt->netid)
                    138:       {
                    139:        for (tmp = opts; tmp; tmp = tmp->next) 
                    140:          if (tmp->opt == opt->opt && (tmp->flags & DHOPT_TAGOK))
                    141:            break;
                    142:        if (!tmp)
                    143:          opt->flags |= DHOPT_TAGOK;
                    144:        else if (!tmp->netid)
                    145:          my_syslog(MS_DHCP | LOG_WARNING, _("Ignoring duplicate dhcp-option %d"), tmp->opt); 
                    146:       }
                    147: 
                    148:   /* Finally, eliminate duplicate options later in the chain, and therefore earlier in the config file. */
                    149:   for (opt = opts; opt; opt = opt->next)
                    150:     if (opt->flags & DHOPT_TAGOK)
                    151:       for (tmp = opt->next; tmp; tmp = tmp->next) 
                    152:        if (tmp->opt == opt->opt)
                    153:          tmp->flags &= ~DHOPT_TAGOK;
                    154:   
                    155:   return tagif;
                    156: }
                    157:        
                    158: /* Is every member of check matched by a member of pool? 
                    159:    If tagnotneeded, untagged is OK */
                    160: int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded)
                    161: {
                    162:   struct dhcp_netid *tmp1;
                    163:   
                    164:   if (!check && !tagnotneeded)
                    165:     return 0;
                    166: 
                    167:   for (; check; check = check->next)
                    168:     {
                    169:       /* '#' for not is for backwards compat. */
                    170:       if (check->net[0] != '!' && check->net[0] != '#')
                    171:        {
                    172:          for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
                    173:            if (strcmp(check->net, tmp1->net) == 0)
                    174:              break;
                    175:          if (!tmp1)
                    176:            return 0;
                    177:        }
                    178:       else
                    179:        for (tmp1 = pool; tmp1; tmp1 = tmp1->next)
                    180:          if (strcmp((check->net)+1, tmp1->net) == 0)
                    181:            return 0;
                    182:     }
                    183:   return 1;
                    184: }
                    185: 
                    186: /* return domain or NULL if none. */
                    187: char *strip_hostname(char *hostname)
                    188: {
                    189:   char *dot = strchr(hostname, '.');
                    190:  
                    191:   if (!dot)
                    192:     return NULL;
                    193:   
                    194:   *dot = 0; /* truncate */
                    195:   if (strlen(dot+1) != 0)
                    196:     return dot+1;
                    197:   
                    198:   return NULL;
                    199: }
                    200: 
                    201: void log_tags(struct dhcp_netid *netid, u32 xid)
                    202: {
                    203:   if (netid && option_bool(OPT_LOG_OPTS))
                    204:     {
                    205:       char *s = daemon->namebuff;
                    206:       for (*s = 0; netid; netid = netid->next)
                    207:        {
                    208:          /* kill dupes. */
                    209:          struct dhcp_netid *n;
                    210:          
                    211:          for (n = netid->next; n; n = n->next)
                    212:            if (strcmp(netid->net, n->net) == 0)
                    213:              break;
                    214:          
                    215:          if (!n)
                    216:            {
                    217:              strncat (s, netid->net, (MAXDNAME-1) - strlen(s));
                    218:              if (netid->next)
                    219:                strncat (s, ", ", (MAXDNAME-1) - strlen(s));
                    220:            }
                    221:        }
                    222:       my_syslog(MS_DHCP | LOG_INFO, _("%u tags: %s"), xid, s);
                    223:     } 
                    224: }   
                    225:   
                    226: int match_bytes(struct dhcp_opt *o, unsigned char *p, int len)
                    227: {
                    228:   int i;
                    229:   
                    230:   if (o->len > len)
                    231:     return 0;
                    232:   
                    233:   if (o->len == 0)
                    234:     return 1;
                    235:      
                    236:   if (o->flags & DHOPT_HEX)
                    237:     { 
                    238:       if (memcmp_masked(o->val, p, o->len, o->u.wildcard_mask))
                    239:        return 1;
                    240:     }
                    241:   else 
                    242:     for (i = 0; i <= (len - o->len); ) 
                    243:       {
                    244:        if (memcmp(o->val, p + i, o->len) == 0)
                    245:          return 1;
                    246:            
                    247:        if (o->flags & DHOPT_STRING)
                    248:          i++;
                    249:        else
                    250:          i += o->len;
                    251:       }
                    252:   
                    253:   return 0;
                    254: }
                    255: 
                    256: void dhcp_update_configs(struct dhcp_config *configs)
                    257: {
                    258:   /* Some people like to keep all static IP addresses in /etc/hosts.
                    259:      This goes through /etc/hosts and sets static addresses for any DHCP config
                    260:      records which don't have an address and whose name matches. 
                    261:      We take care to maintain the invariant that any IP address can appear
                    262:      in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP, 
                    263:      restore the status-quo ante first. */
                    264:   
                    265:   struct dhcp_config *config, *conf_tmp;
                    266:   struct crec *crec;
                    267:   int prot = AF_INET;
                    268: 
                    269:   for (config = configs; config; config = config->next)
                    270:     if (config->flags & CONFIG_ADDR_HOSTS)
                    271:       config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS);
                    272: 
                    273: #ifdef HAVE_DHCP6 
                    274:  again:  
                    275: #endif
                    276: 
                    277:   if (daemon->port != 0)
                    278:     for (config = configs; config; config = config->next)
                    279:       {
                    280:        int conflags = CONFIG_ADDR;
                    281:        int cacheflags = F_IPV4;
                    282: 
                    283: #ifdef HAVE_DHCP6
                    284:        if (prot == AF_INET6)
                    285:          {
                    286:            conflags = CONFIG_ADDR6;
                    287:            cacheflags = F_IPV6;
                    288:          }
                    289: #endif
                    290:        if (!(config->flags & conflags) &&
                    291:            (config->flags & CONFIG_NAME) && 
                    292:            (crec = cache_find_by_name(NULL, config->hostname, 0, cacheflags)) &&
                    293:            (crec->flags & F_HOSTS))
                    294:          {
                    295:            if (cache_find_by_name(crec, config->hostname, 0, cacheflags))
                    296:              {
                    297:                /* use primary (first) address */
                    298:              while (crec && !(crec->flags & F_REVERSE))
                    299:                crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
                    300:              if (!crec)
                    301:                continue; /* should be never */
                    302:              inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
                    303:              my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), 
                    304:                        config->hostname, daemon->addrbuff);
                    305:              }
                    306:            
                    307:            if (prot == AF_INET && 
                    308:                (!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
                    309:              {
                    310:                config->addr = crec->addr.addr.addr.addr4;
                    311:                config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
                    312:                continue;
                    313:              }
                    314: 
                    315: #ifdef HAVE_DHCP6
                    316:            if (prot == AF_INET6 && 
                    317:                (!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
                    318:              {
                    319:                memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
                    320:                config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
                    321:                continue;
                    322:              }
                    323: #endif
                    324: 
                    325:            inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
                    326:            my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), 
                    327:                      daemon->addrbuff, config->hostname);
                    328:            
                    329:            
                    330:          }
                    331:       }
                    332: 
                    333: #ifdef HAVE_DHCP6
                    334:   if (prot == AF_INET)
                    335:     {
                    336:       prot = AF_INET6;
                    337:       goto again;
                    338:     }
                    339: #endif
                    340: 
                    341: }
                    342: 
                    343: #ifdef HAVE_LINUX_NETWORK 
                    344: void bindtodevice(int fd)
                    345: {
                    346:   /* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
                    347:      to that device. This is for the use case of  (eg) OpenStack, which runs a new
                    348:      dnsmasq instance for each VLAN interface it creates. Without the BINDTODEVICE, 
                    349:      individual processes don't always see the packets they should.
                    350:      SO_BINDTODEVICE is only available Linux. */
                    351:   
                    352:   struct irec *iface, *found;
                    353:   
                    354:   for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
                    355:     if (iface->dhcp_ok)
                    356:       {
                    357:        if (!found)
                    358:          found = iface;
                    359:        else if (strcmp(found->name, iface->name) != 0) 
                    360:          {
                    361:            /* more than one. */
                    362:            found = NULL;
                    363:            break;
                    364:          }
                    365:       }
                    366:   
                    367:   if (found)
                    368:     {
                    369:       struct ifreq ifr;
                    370:       strcpy(ifr.ifr_name, found->name);
                    371:       /* only allowed by root. */
                    372:       if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
                    373:          errno != EPERM)
                    374:        die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
                    375:     }
                    376: }
                    377: #endif
                    378: 
                    379: static const struct opttab_t {
                    380:   char *name;
                    381:   u16 val, size;
                    382: } opttab[] = {
                    383:   { "netmask", 1, OT_ADDR_LIST },
                    384:   { "time-offset", 2, 4 },
                    385:   { "router", 3, OT_ADDR_LIST  },
                    386:   { "dns-server", 6, OT_ADDR_LIST },
                    387:   { "log-server", 7, OT_ADDR_LIST },
                    388:   { "lpr-server", 9, OT_ADDR_LIST },
                    389:   { "hostname", 12, OT_INTERNAL | OT_NAME },
                    390:   { "boot-file-size", 13, 2 | OT_DEC },
                    391:   { "domain-name", 15, OT_NAME },
                    392:   { "swap-server", 16, OT_ADDR_LIST },
                    393:   { "root-path", 17, OT_NAME },
                    394:   { "extension-path", 18, OT_NAME },
                    395:   { "ip-forward-enable", 19, 1 },
                    396:   { "non-local-source-routing", 20, 1 },
                    397:   { "policy-filter", 21, OT_ADDR_LIST },
                    398:   { "max-datagram-reassembly", 22, 2 | OT_DEC },
                    399:   { "default-ttl", 23, 1 | OT_DEC },
                    400:   { "mtu", 26, 2 | OT_DEC },
                    401:   { "all-subnets-local", 27, 1 },
                    402:   { "broadcast", 28, OT_INTERNAL | OT_ADDR_LIST },
                    403:   { "router-discovery", 31, 1 },
                    404:   { "router-solicitation", 32, OT_ADDR_LIST },
                    405:   { "static-route", 33, OT_ADDR_LIST },
                    406:   { "trailer-encapsulation", 34, 1 },
                    407:   { "arp-timeout", 35, 4 | OT_DEC },
                    408:   { "ethernet-encap", 36, 1 },
                    409:   { "tcp-ttl", 37, 1 },
                    410:   { "tcp-keepalive", 38, 4 | OT_DEC },
                    411:   { "nis-domain", 40, OT_NAME },
                    412:   { "nis-server", 41, OT_ADDR_LIST },
                    413:   { "ntp-server", 42, OT_ADDR_LIST },
                    414:   { "vendor-encap", 43, OT_INTERNAL },
                    415:   { "netbios-ns", 44, OT_ADDR_LIST },
                    416:   { "netbios-dd", 45, OT_ADDR_LIST },
                    417:   { "netbios-nodetype", 46, 1 },
                    418:   { "netbios-scope", 47, 0 },
                    419:   { "x-windows-fs", 48, OT_ADDR_LIST },
                    420:   { "x-windows-dm", 49, OT_ADDR_LIST },
                    421:   { "requested-address", 50, OT_INTERNAL | OT_ADDR_LIST },
                    422:   { "lease-time", 51, OT_INTERNAL | OT_TIME },
                    423:   { "option-overload", 52, OT_INTERNAL },
                    424:   { "message-type", 53, OT_INTERNAL | OT_DEC },
                    425:   { "server-identifier", 54, OT_INTERNAL | OT_ADDR_LIST },
                    426:   { "parameter-request", 55, OT_INTERNAL },
                    427:   { "message", 56, OT_INTERNAL },
                    428:   { "max-message-size", 57, OT_INTERNAL },
                    429:   { "T1", 58, OT_INTERNAL | OT_TIME},
                    430:   { "T2", 59, OT_INTERNAL | OT_TIME},
                    431:   { "vendor-class", 60, 0 },
                    432:   { "client-id", 61, OT_INTERNAL },
                    433:   { "nis+-domain", 64, OT_NAME },
                    434:   { "nis+-server", 65, OT_ADDR_LIST },
                    435:   { "tftp-server", 66, OT_NAME },
                    436:   { "bootfile-name", 67, OT_NAME },
                    437:   { "mobile-ip-home", 68, OT_ADDR_LIST }, 
                    438:   { "smtp-server", 69, OT_ADDR_LIST }, 
                    439:   { "pop3-server", 70, OT_ADDR_LIST }, 
                    440:   { "nntp-server", 71, OT_ADDR_LIST }, 
                    441:   { "irc-server", 74, OT_ADDR_LIST }, 
                    442:   { "user-class", 77, 0 },
                    443:   { "FQDN", 81, OT_INTERNAL },
                    444:   { "agent-id", 82, OT_INTERNAL },
                    445:   { "client-arch", 93, 2 | OT_DEC },
                    446:   { "client-interface-id", 94, 0 },
                    447:   { "client-machine-id", 97, 0 },
                    448:   { "subnet-select", 118, OT_INTERNAL },
                    449:   { "domain-search", 119, OT_RFC1035_NAME },
                    450:   { "sip-server", 120, 0 },
                    451:   { "classless-static-route", 121, 0 },
                    452:   { "vendor-id-encap", 125, 0 },
                    453:   { "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
                    454:   { NULL, 0, 0 }
                    455: };
                    456: 
                    457: #ifdef HAVE_DHCP6
                    458: static const struct opttab_t opttab6[] = {
                    459:   { "client-id", 1, OT_INTERNAL },
                    460:   { "server-id", 2, OT_INTERNAL },
                    461:   { "ia-na", 3, OT_INTERNAL },
                    462:   { "ia-ta", 4, OT_INTERNAL },
                    463:   { "iaaddr", 5, OT_INTERNAL },
                    464:   { "oro", 6, OT_INTERNAL },
                    465:   { "preference", 7, OT_INTERNAL | OT_DEC },
                    466:   { "unicast", 12, OT_INTERNAL },
                    467:   { "status", 13, OT_INTERNAL },
                    468:   { "rapid-commit", 14, OT_INTERNAL },
                    469:   { "user-class", 15, OT_INTERNAL | OT_CSTRING },
                    470:   { "vendor-class", 16, OT_INTERNAL | OT_CSTRING },
                    471:   { "vendor-opts", 17, OT_INTERNAL },
                    472:   { "sip-server-domain", 21,  OT_RFC1035_NAME },
                    473:   { "sip-server", 22, OT_ADDR_LIST },
                    474:   { "dns-server", 23, OT_ADDR_LIST },
                    475:   { "domain-search", 24, OT_RFC1035_NAME },
                    476:   { "nis-server", 27, OT_ADDR_LIST },
                    477:   { "nis+-server", 28, OT_ADDR_LIST },
                    478:   { "nis-domain", 29,  OT_RFC1035_NAME },
                    479:   { "nis+-domain", 30, OT_RFC1035_NAME },
                    480:   { "sntp-server", 31,  OT_ADDR_LIST },
                    481:   { "information-refresh-time", 32, OT_TIME },
                    482:   { "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
                    483:   { "ntp-server", 56,  OT_ADDR_LIST },
                    484:   { "bootfile-url", 59, OT_NAME },
                    485:   { "bootfile-param", 60, OT_CSTRING },
                    486:   { NULL, 0, 0 }
                    487: };
                    488: #endif
                    489: 
                    490: 
                    491: 
                    492: void display_opts(void)
                    493: {
                    494:   int i;
                    495:   
                    496:   printf(_("Known DHCP options:\n"));
                    497:   
                    498:   for (i = 0; opttab[i].name; i++)
                    499:     if (!(opttab[i].size & OT_INTERNAL))
                    500:       printf("%3d %s\n", opttab[i].val, opttab[i].name);
                    501: }
                    502: 
                    503: #ifdef HAVE_DHCP6
                    504: void display_opts6(void)
                    505: {
                    506:   int i;
                    507:   printf(_("Known DHCPv6 options:\n"));
                    508:   
                    509:   for (i = 0; opttab6[i].name; i++)
                    510:     if (!(opttab6[i].size & OT_INTERNAL))
                    511:       printf("%3d %s\n", opttab6[i].val, opttab6[i].name);
                    512: }
                    513: #endif
                    514: 
                    515: u16 lookup_dhcp_opt(int prot, char *name)
                    516: {
                    517:   const struct opttab_t *t;
                    518:   int i;
                    519: 
                    520: #ifdef HAVE_DHCP6
                    521:   if (prot == AF_INET6)
                    522:     t = opttab6;
                    523:   else
                    524: #endif
                    525:     t = opttab;
                    526: 
                    527:   for (i = 0; t[i].name; i++)
                    528:     if (strcasecmp(t[i].name, name) == 0)
                    529:       return t[i].val;
                    530:   
                    531:   return 0;
                    532: }
                    533: 
                    534: u16 lookup_dhcp_len(int prot, u16 val)
                    535: {
                    536:   const struct opttab_t *t;
                    537:   int i;
                    538: 
                    539: #ifdef HAVE_DHCP6
                    540:   if (prot == AF_INET6)
                    541:     t = opttab6;
                    542:   else
                    543: #endif
                    544:     t = opttab;
                    545: 
                    546:   for (i = 0; t[i].name; i++)
                    547:     if (val == t[i].val)
                    548:       return t[i].size & ~OT_DEC;
                    549: 
                    550:    return 0;
                    551: }
                    552: 
                    553: char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len)
                    554: {
                    555:   int o, i, j, nodecode = 0;
                    556:   const struct opttab_t *ot = opttab;
                    557: 
                    558: #ifdef HAVE_DHCP6
                    559:   if (prot == AF_INET6)
                    560:     ot = opttab6;
                    561: #endif
                    562: 
                    563:   for (o = 0; ot[o].name; o++)
                    564:     if (ot[o].val == opt)
                    565:       {
                    566:        if (buf)
                    567:          {
                    568:            memset(buf, 0, buf_len);
                    569:            
                    570:            if (ot[o].size & OT_ADDR_LIST) 
                    571:              {
                    572:                struct all_addr addr;
                    573:                int addr_len = INADDRSZ;
                    574: 
                    575: #ifdef HAVE_DHCP6
                    576:                if (prot == AF_INET6)
                    577:                  addr_len = IN6ADDRSZ;
                    578: #endif
                    579:                for (buf[0]= 0, i = 0; i <= opt_len - addr_len; i += addr_len) 
                    580:                  {
                    581:                    if (i != 0)
                    582:                      strncat(buf, ", ", buf_len - strlen(buf));
                    583:                    /* align */
                    584:                    memcpy(&addr, &val[i], addr_len); 
                    585:                    inet_ntop(prot, &val[i], daemon->addrbuff, ADDRSTRLEN);
                    586:                    strncat(buf, daemon->addrbuff, buf_len - strlen(buf));
                    587:                  }
                    588:              }
                    589:            else if (ot[o].size & OT_NAME)
                    590:                for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
                    591:                  {
                    592:                    char c = val[i];
                    593:                    if (isprint((int)c))
                    594:                      buf[j++] = c;
                    595:                  }
                    596: #ifdef HAVE_DHCP6
                    597:            /* We don't handle compressed rfc1035 names, so no good in IPv4 land */
                    598:            else if ((ot[o].size & OT_RFC1035_NAME) && prot == AF_INET6)
                    599:              {
                    600:                i = 0, j = 0;
                    601:                while (i < opt_len && val[i] != 0)
                    602:                  {
                    603:                    int k, l = i + val[i] + 1;
                    604:                    for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
                    605:                     {
                    606:                       char c = val[k];
                    607:                       if (isprint((int)c))
                    608:                         buf[j++] = c;
                    609:                     }
                    610:                    i = l;
                    611:                    if (val[i] != 0 && j < buf_len)
                    612:                      buf[j++] = '.';
                    613:                  }
                    614:              }
                    615:            else if ((ot[o].size & OT_CSTRING))
                    616:              {
                    617:                int k, len;
                    618:                unsigned char *p;
                    619: 
                    620:                i = 0, j = 0;
                    621:                while (1)
                    622:                  {
                    623:                    p = &val[i];
                    624:                    GETSHORT(len, p);
                    625:                    for (k = 0; k < len && j < buf_len; k++)
                    626:                      {
                    627:                       char c = *p++;
                    628:                       if (isprint((int)c))
                    629:                         buf[j++] = c;
                    630:                     }
                    631:                    i += len +2;
                    632:                    if (i >= opt_len)
                    633:                      break;
                    634: 
                    635:                    if (j < buf_len)
                    636:                      buf[j++] = ',';
                    637:                  }
                    638:              }       
                    639: #endif
                    640:            else if ((ot[o].size & (OT_DEC | OT_TIME)) && opt_len != 0)
                    641:              {
                    642:                unsigned int dec = 0;
                    643:                
                    644:                for (i = 0; i < opt_len; i++)
                    645:                  dec = (dec << 8) | val[i]; 
                    646: 
                    647:                if (ot[o].size & OT_TIME)
                    648:                  prettyprint_time(buf, dec);
                    649:                else
                    650:                  sprintf(buf, "%u", dec);
                    651:              }
                    652:            else
                    653:              nodecode = 1;
                    654:          }
                    655:        break;
                    656:       }
                    657: 
                    658:   if (opt_len != 0 && buf && (!ot[o].name || nodecode))
                    659:     {
                    660:       int trunc  = 0;
                    661:       if (opt_len > 14)
                    662:        {
                    663:          trunc = 1;
                    664:          opt_len = 14;
                    665:        }
                    666:       print_mac(buf, val, opt_len);
                    667:       if (trunc)
                    668:        strncat(buf, "...", buf_len - strlen(buf));
                    669:     
                    670: 
                    671:     }
                    672: 
                    673:   return ot[o].name ? ot[o].name : "";
                    674: 
                    675: }
                    676: 
                    677: void log_context(int family, struct dhcp_context *context)
                    678: {
                    679:   /* Cannot use dhcp_buff* for RA contexts */
                    680: 
                    681:   void *start = &context->start;
                    682:   void *end = &context->end;
                    683:   char *template = "", *p = daemon->namebuff;
                    684:   
                    685:   *p = 0;
                    686:     
                    687: #ifdef HAVE_DHCP6
                    688:   if (family == AF_INET6)
                    689:     {
                    690:       struct in6_addr subnet = context->start6;
                    691:       if (!(context->flags & CONTEXT_TEMPLATE))
                    692:        setaddr6part(&subnet, 0);
                    693:       inet_ntop(AF_INET6, &subnet, daemon->addrbuff, ADDRSTRLEN); 
                    694:       start = &context->start6;
                    695:       end = &context->end6;
                    696:     }
                    697: #endif
                    698: 
                    699:   if (family != AF_INET && (context->flags & CONTEXT_DEPRECATE))
                    700:     strcpy(daemon->namebuff, _(", prefix deprecated"));
                    701:   else
                    702:     {
                    703:       p += sprintf(p, _(", lease time "));
                    704:       prettyprint_time(p, context->lease_time);
                    705:       p += strlen(p);
                    706:     }  
                    707: 
                    708: #ifdef HAVE_DHCP6
                    709:   if (context->flags & CONTEXT_CONSTRUCTED)
                    710:     {
                    711:       char ifrn_name[IFNAMSIZ];
                    712:       
                    713:       template = p;
                    714:       p += sprintf(p, ", ");
                    715:       
                    716:       if (indextoname(daemon->doing_dhcp6 ? daemon->dhcp6fd : daemon->icmp6fd, context->if_index, ifrn_name))
                    717:        sprintf(p, "constructed for %s", ifrn_name);
                    718:     }
                    719:   else if (context->flags & CONTEXT_TEMPLATE)
                    720:     {
                    721:       template = p;
                    722:       p += sprintf(p, ", ");
                    723:        
                    724:       sprintf(p, "template for %s", context->template_interface);  
                    725:     }
                    726: #endif
                    727:      
                    728:   if ((context->flags & CONTEXT_DHCP) || family == AF_INET) 
                    729:     {
                    730:       inet_ntop(family, start, daemon->dhcp_buff, 256);
                    731:       inet_ntop(family, end, daemon->dhcp_buff3, 256);
                    732:       my_syslog(MS_DHCP | LOG_INFO, 
                    733:              (context->flags & CONTEXT_RA_STATELESS) ? 
                    734:              _("%s stateless on %s%.0s%.0s%s") :
                    735:              (context->flags & CONTEXT_STATIC) ? 
                    736:              _("%s, static leases only on %.0s%s%s%.0s") :
                    737:              (context->flags & CONTEXT_PROXY) ?
                    738:              _("%s, proxy on subnet %.0s%s%.0s%.0s") :
                    739:              _("%s, IP range %s -- %s%s%.0s"),
                    740:              (family != AF_INET) ? "DHCPv6" : "DHCP",
                    741:                daemon->dhcp_buff, daemon->dhcp_buff3, daemon->namebuff, template);
                    742:     }
                    743:   
                    744: #ifdef HAVE_DHCP6
                    745:   if (context->flags & CONTEXT_RA_NAME)
                    746:     my_syslog(MS_DHCP | LOG_INFO, _("DHCPv4-derived IPv6 names on %s%s"), daemon->addrbuff, template);
                    747:        
                    748:   if ((context->flags & CONTEXT_RA) || (option_bool(OPT_RA) && (context->flags & CONTEXT_DHCP) && family == AF_INET6)) 
                    749:     my_syslog(MS_DHCP | LOG_INFO, _("router advertisement on %s%s"), daemon->addrbuff, template);
                    750: #endif
                    751: 
                    752: }
                    753:       
                    754: 
                    755: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>