Annotation of embedaddon/dnsmasq/src/rfc3315.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
1.1       misho       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: 
                     18: #include "dnsmasq.h"
                     19: 
                     20: #ifdef HAVE_DHCP6
                     21: 
                     22: struct state {
                     23:   unsigned char *clid;
1.1.1.2 ! misho      24:   int clid_len, iaid, ia_type, interface, hostname_auth, lease_allocate;
1.1       misho      25:   char *client_hostname, *hostname, *domain, *send_domain;
                     26:   struct dhcp_context *context;
1.1.1.2 ! misho      27:   struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
1.1       misho      28:   unsigned int xid, fqdn_flags;
                     29:   char *iface_name;
                     30:   void *packet_options, *end;
                     31:   struct dhcp_netid *tags, *context_tags;
1.1.1.2 ! misho      32:   unsigned char mac[DHCP_CHADDR_MAX];
        !            33:   unsigned int mac_len, mac_type;
1.1       misho      34: #ifdef OPTION6_PREFIX_CLASS
                     35:   struct prefix_class *send_prefix_class;
                     36: #endif
                     37: };
                     38: 
1.1.1.2 ! misho      39: static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, 
        !            40:                             struct in6_addr *client_addr, int is_unicast, time_t now);
        !            41: static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
1.1       misho      42: static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
                     43: static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
1.1.1.2 ! misho      44: static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
1.1       misho      45: static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize);
                     46: static void *opt6_next(void *opts, void *end);
                     47: static unsigned int opt6_uint(unsigned char *opt, int offset, int size);
                     48: static void get_context_tag(struct state *state, struct dhcp_context *context);
                     49: static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
                     50: static int build_ia(struct state *state, int *t1cntr);
                     51: static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
                     52: #ifdef OPTION6_PREFIX_CLASS
                     53: static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
                     54: #endif
1.1.1.2 ! misho      55: static void mark_context_used(struct state *state, struct in6_addr *addr);
1.1       misho      56: static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
                     57: static int check_address(struct state *state, struct in6_addr *addr);
1.1.1.2 ! misho      58: static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, 
        !            59:                        unsigned int *min_time, struct in6_addr *addr, time_t now);
1.1       misho      60: static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
                     61: static int add_local_addrs(struct dhcp_context *context);
1.1.1.2 ! misho      62: static struct dhcp_netid *add_options(struct state *state, int do_refresh);
1.1       misho      63: static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep, 
1.1.1.2 ! misho      64:                            unsigned int *preferred_timep, unsigned int lease_time);
1.1       misho      65: 
                     66: #define opt6_len(opt) ((int)(opt6_uint(opt, -2, 2)))
                     67: #define opt6_type(opt) (opt6_uint(opt, -4, 2))
                     68: #define opt6_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[4+(i)]))
                     69: 
1.1.1.2 ! misho      70: #define opt6_user_vendor_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2+(i)]))
        !            71: #define opt6_user_vendor_len(opt) ((int)(opt6_uint(opt, -4, 2)))
        !            72: #define opt6_user_vendor_next(opt, end) (opt6_next(((void *) opt) - 2, end))
        !            73:  
1.1       misho      74: 
                     75: unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
1.1.1.2 ! misho      76:                           struct in6_addr *fallback,  struct in6_addr *ll_addr, struct in6_addr *ula_addr,
        !            77:                           size_t sz, struct in6_addr *client_addr, time_t now)
1.1       misho      78: {
                     79:   struct dhcp_vendor *vendor;
                     80:   int msg_type;
1.1.1.2 ! misho      81:   struct state state;
1.1       misho      82:   
                     83:   if (sz <= 4)
                     84:     return 0;
                     85:   
                     86:   msg_type = *((unsigned char *)daemon->dhcp_packet.iov_base);
                     87:   
                     88:   /* Mark these so we only match each at most once, to avoid tangled linked lists */
                     89:   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
                     90:     vendor->netid.next = &vendor->netid;
                     91:   
                     92:   save_counter(0);
1.1.1.2 ! misho      93:   state.context = context;
        !            94:   state.interface = interface;
        !            95:   state.iface_name = iface_name;
        !            96:   state.fallback = fallback;
        !            97:   state.ll_addr = ll_addr;
        !            98:   state.ula_addr = ula_addr;
        !            99:   state.mac_len = 0;
        !           100:   state.tags = NULL;
        !           101:   state.link_address = NULL;
        !           102: 
        !           103:   if (dhcp6_maybe_relay(&state, daemon->dhcp_packet.iov_base, sz, client_addr, 
        !           104:                        IN6_IS_ADDR_MULTICAST(client_addr), now))
1.1       misho     105:     return msg_type == DHCP6RELAYFORW ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
                    106: 
                    107:   return 0;
                    108: }
                    109: 
                    110: /* This cost me blood to write, it will probably cost you blood to understand - srk. */
1.1.1.2 ! misho     111: static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz, 
        !           112:                             struct in6_addr *client_addr, int is_unicast, time_t now)
1.1       misho     113: {
                    114:   void *end = inbuff + sz;
                    115:   void *opts = inbuff + 34;
                    116:   int msg_type = *((unsigned char *)inbuff);
                    117:   unsigned char *outmsgtypep;
                    118:   void *opt;
                    119:   struct dhcp_vendor *vendor;
                    120: 
                    121:   /* if not an encaplsulated relayed message, just do the stuff */
                    122:   if (msg_type != DHCP6RELAYFORW)
                    123:     {
                    124:       /* if link_address != NULL if points to the link address field of the 
                    125:         innermost nested RELAYFORW message, which is where we find the
                    126:         address of the network on which we can allocate an address.
1.1.1.2 ! misho     127:         Recalculate the available contexts using that information. 
        !           128: 
        !           129:       link_address == NULL means there's no relay in use, so we try and find the client's 
        !           130:       MAC address from the local ND cache. */
1.1       misho     131:       
1.1.1.2 ! misho     132:       if (!state->link_address)
        !           133:        get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type);
        !           134:       else
1.1       misho     135:        {
                    136:          struct dhcp_context *c;
1.1.1.2 ! misho     137:          state->context = NULL;
1.1       misho     138:           
1.1.1.2 ! misho     139:          if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
        !           140:              !IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
        !           141:              !IN6_IS_ADDR_MULTICAST(state->link_address))
1.1       misho     142:            for (c = daemon->dhcp6; c; c = c->next)
                    143:              if ((c->flags & CONTEXT_DHCP) &&
1.1.1.2 ! misho     144:                  !(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
        !           145:                  is_same_net6(state->link_address, &c->start6, c->prefix) &&
        !           146:                  is_same_net6(state->link_address, &c->end6, c->prefix))
1.1       misho     147:                {
                    148:                  c->preferred = c->valid = 0xffffffff;
1.1.1.2 ! misho     149:                  c->current = state->context;
        !           150:                  state->context = c;
1.1       misho     151:                }
                    152:          
1.1.1.2 ! misho     153:          if (!state->context)
1.1       misho     154:            {
1.1.1.2 ! misho     155:              inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN); 
1.1       misho     156:              my_syslog(MS_DHCP | LOG_WARNING, 
                    157:                        _("no address range available for DHCPv6 request from relay at %s"),
                    158:                        daemon->addrbuff);
                    159:              return 0;
                    160:            }
                    161:        }
1.1.1.2 ! misho     162:          
        !           163:       if (!state->context)
1.1       misho     164:        {
                    165:          my_syslog(MS_DHCP | LOG_WARNING, 
1.1.1.2 ! misho     166:                    _("no address range available for DHCPv6 request via %s"), state->iface_name);
1.1       misho     167:          return 0;
                    168:        }
                    169: 
1.1.1.2 ! misho     170:       return dhcp6_no_relay(state, msg_type, inbuff, sz, is_unicast, now);
1.1       misho     171:     }
                    172: 
                    173:   /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
                    174:      which is               1   +    1   +    16      +     16     + 2 + 2 = 38 */
                    175:   if (sz < 38)
                    176:     return 0;
                    177:   
                    178:   /* copy header stuff into reply message and set type to reply */
1.1.1.2 ! misho     179:   if (!(outmsgtypep = put_opt6(inbuff, 34)))
        !           180:     return 0;
1.1       misho     181:   *outmsgtypep = DHCP6RELAYREPL;
                    182: 
                    183:   /* look for relay options and set tags if found. */
                    184:   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
                    185:     {
                    186:       int mopt;
                    187:       
                    188:       if (vendor->match_type == MATCH_SUBSCRIBER)
                    189:        mopt = OPTION6_SUBSCRIBER_ID;
                    190:       else if (vendor->match_type == MATCH_REMOTE)
                    191:        mopt = OPTION6_REMOTE_ID; 
                    192:       else
                    193:        continue;
                    194: 
                    195:       if ((opt = opt6_find(opts, end, mopt, 1)) &&
                    196:          vendor->len == opt6_len(opt) &&
                    197:          memcmp(vendor->data, opt6_ptr(opt, 0), vendor->len) == 0 &&
                    198:          vendor->netid.next != &vendor->netid)
                    199:        {
1.1.1.2 ! misho     200:          vendor->netid.next = state->tags;
        !           201:          state->tags = &vendor->netid;
1.1       misho     202:          break;
                    203:        }
                    204:     }
                    205:   
1.1.1.2 ! misho     206:   /* RFC-6939 */
        !           207:   if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
        !           208:     {
        !           209:       state->mac_type = opt6_uint(opt, 0, 2);
        !           210:       state->mac_len = opt6_len(opt) - 2;
        !           211:       memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
        !           212:     }
        !           213:   
1.1       misho     214:   for (opt = opts; opt; opt = opt6_next(opt, end))
                    215:     {
                    216:       int o = new_opt6(opt6_type(opt));
                    217:       if (opt6_type(opt) == OPTION6_RELAY_MSG)
                    218:        {
1.1.1.2 ! misho     219:          struct in6_addr align;
1.1       misho     220:          /* the packet data is unaligned, copy to aligned storage */
1.1.1.2 ! misho     221:          memcpy(&align, inbuff + 2, IN6ADDRSZ); 
        !           222:          state->link_address = &align;
        !           223:          /* zero is_unicast since that is now known to refer to the 
1.1       misho     224:             relayed packet, not the original sent by the client */
1.1.1.2 ! misho     225:          if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
1.1       misho     226:            return 0;
                    227:        }
1.1.1.2 ! misho     228:       else if (opt6_type(opt) != OPTION6_CLIENT_MAC)
1.1       misho     229:        put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
                    230:       end_opt6(o);         
                    231:     }
                    232:   
                    233:   return 1;
                    234: }
                    235: 
1.1.1.2 ! misho     236: static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
1.1       misho     237: {
                    238:   void *opt;
                    239:   int i, o, o1, start_opts;
                    240:   struct dhcp_opt *opt_cfg;
                    241:   struct dhcp_netid *tagif;
                    242:   struct dhcp_config *config = NULL;
                    243:   struct dhcp_netid known_id, iface_id, v6_id;
                    244:   unsigned char *outmsgtypep;
                    245:   struct dhcp_vendor *vendor;
                    246:   struct dhcp_context *context_tmp;
1.1.1.2 ! misho     247:   struct dhcp_mac *mac_opt;
1.1       misho     248:   unsigned int ignore = 0;
                    249: #ifdef OPTION6_PREFIX_CLASS
                    250:   struct prefix_class *p;
                    251:   int dump_all_prefix_classes = 0;
                    252: #endif
                    253: 
1.1.1.2 ! misho     254:   state->packet_options = inbuff + 4;
        !           255:   state->end = inbuff + sz;
        !           256:   state->clid = NULL;
        !           257:   state->clid_len = 0;
        !           258:   state->lease_allocate = 0;
        !           259:   state->context_tags = NULL;
        !           260:   state->domain = NULL;
        !           261:   state->send_domain = NULL;
        !           262:   state->hostname_auth = 0;
        !           263:   state->hostname = NULL;
        !           264:   state->client_hostname = NULL;
        !           265:   state->fqdn_flags = 0x01; /* default to send if we recieve no FQDN option */
1.1       misho     266: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     267:   state->send_prefix_class = NULL;
1.1       misho     268: #endif
                    269: 
                    270:   /* set tag with name == interface */
1.1.1.2 ! misho     271:   iface_id.net = state->iface_name;
        !           272:   iface_id.next = state->tags;
        !           273:   state->tags = &iface_id; 
1.1       misho     274: 
                    275:   /* set tag "dhcpv6" */
                    276:   v6_id.net = "dhcpv6";
1.1.1.2 ! misho     277:   v6_id.next = state->tags;
        !           278:   state->tags = &v6_id;
1.1       misho     279: 
                    280:   /* copy over transaction-id, and save pointer to message type */
1.1.1.2 ! misho     281:   if (!(outmsgtypep = put_opt6(inbuff, 4)))
        !           282:     return 0;
1.1       misho     283:   start_opts = save_counter(-1);
1.1.1.2 ! misho     284:   state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
1.1       misho     285:    
                    286:   /* We're going to be linking tags from all context we use. 
                    287:      mark them as unused so we don't link one twice and break the list */
1.1.1.2 ! misho     288:   for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
1.1       misho     289:     {
1.1.1.2 ! misho     290:       context_tmp->netid.next = &context_tmp->netid;
1.1       misho     291: 
                    292:       if (option_bool(OPT_LOG_OPTS))
                    293:        {
                    294:           inet_ntop(AF_INET6, &context_tmp->start6, daemon->dhcp_buff, ADDRSTRLEN); 
                    295:           inet_ntop(AF_INET6, &context_tmp->end6, daemon->dhcp_buff2, ADDRSTRLEN); 
                    296:           if (context_tmp->flags & (CONTEXT_STATIC))
                    297:             my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCPv6 subnet: %s/%d"),
1.1.1.2 ! misho     298:                       state->xid, daemon->dhcp_buff, context_tmp->prefix);
1.1       misho     299:           else
                    300:             my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"), 
1.1.1.2 ! misho     301:                       state->xid, daemon->dhcp_buff, daemon->dhcp_buff2);
1.1       misho     302:        }
                    303:     }
                    304: 
1.1.1.2 ! misho     305:   if ((opt = opt6_find(state->packet_options, state->end, OPTION6_CLIENT_ID, 1)))
1.1       misho     306:     {
1.1.1.2 ! misho     307:       state->clid = opt6_ptr(opt, 0);
        !           308:       state->clid_len = opt6_len(opt);
1.1       misho     309:       o = new_opt6(OPTION6_CLIENT_ID);
1.1.1.2 ! misho     310:       put_opt6(state->clid, state->clid_len);
1.1       misho     311:       end_opt6(o);
                    312:     }
                    313:   else if (msg_type != DHCP6IREQ)
                    314:     return 0;
                    315: 
                    316:   /* server-id must match except for SOLICIT and CONFIRM messages */
                    317:   if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
1.1.1.2 ! misho     318:       (!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
1.1       misho     319:        opt6_len(opt) != daemon->duid_len ||
                    320:        memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
                    321:     return 0;
                    322:   
                    323:   o = new_opt6(OPTION6_SERVER_ID);
                    324:   put_opt6(daemon->duid, daemon->duid_len);
                    325:   end_opt6(o);
                    326: 
                    327:   if (is_unicast &&
                    328:       (msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
                    329:     
                    330:     {  
                    331:       o1 = new_opt6(OPTION6_STATUS_CODE);
                    332:       put_opt6_short(DHCP6USEMULTI);
                    333:       put_opt6_string("Use multicast");
                    334:       end_opt6(o1);
                    335:       return 1;
                    336:     }
                    337: 
                    338:   /* match vendor and user class options */
                    339:   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
                    340:     {
                    341:       int mopt;
                    342:       
                    343:       if (vendor->match_type == MATCH_VENDOR)
                    344:        mopt = OPTION6_VENDOR_CLASS;
                    345:       else if (vendor->match_type == MATCH_USER)
                    346:        mopt = OPTION6_USER_CLASS; 
                    347:       else
                    348:        continue;
                    349: 
1.1.1.2 ! misho     350:       if ((opt = opt6_find(state->packet_options, state->end, mopt, 2)))
1.1       misho     351:        {
                    352:          void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
                    353:          int offset = 0;
                    354:          
                    355:          if (mopt == OPTION6_VENDOR_CLASS)
                    356:            {
                    357:              if (opt6_len(opt) < 4)
                    358:                continue;
                    359:              
                    360:              if (vendor->enterprise != opt6_uint(opt, 0, 4))
                    361:                continue;
                    362:            
                    363:              offset = 4;
                    364:            }
                    365:  
1.1.1.2 ! misho     366:          /* Note that format if user/vendor classes is different to DHCP options - no option types. */
        !           367:          for (enc_opt = opt6_ptr(opt, offset); enc_opt; enc_opt = opt6_user_vendor_next(enc_opt, enc_end))
        !           368:            for (i = 0; i <= (opt6_user_vendor_len(enc_opt) - vendor->len); i++)
        !           369:              if (memcmp(vendor->data, opt6_user_vendor_ptr(enc_opt, i), vendor->len) == 0)
1.1       misho     370:                {
1.1.1.2 ! misho     371:                  vendor->netid.next = state->tags;
        !           372:                  state->tags = &vendor->netid;
1.1       misho     373:                  break;
                    374:                }
                    375:        }
                    376:     }
                    377: 
1.1.1.2 ! misho     378:   if (option_bool(OPT_LOG_OPTS) && (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
        !           379:     my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %u"), state->xid, opt6_uint(opt, 0, 4));
1.1       misho     380:   
                    381:   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
                    382:      Otherwise assume the option is an array, and look for a matching element. 
                    383:      If no data given, existance of the option is enough. This code handles 
                    384:      V-I opts too. */
                    385:   for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
                    386:     {
                    387:       int match = 0;
                    388:       
                    389:       if (opt_cfg->flags & DHOPT_RFC3925)
                    390:        {
1.1.1.2 ! misho     391:          for (opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_OPTS, 4);
1.1       misho     392:               opt;
1.1.1.2 ! misho     393:               opt = opt6_find(opt6_next(opt, state->end), state->end, OPTION6_VENDOR_OPTS, 4))
1.1       misho     394:            {
                    395:              void *vopt;
                    396:              void *vend = opt6_ptr(opt, opt6_len(opt));
                    397:              
                    398:              for (vopt = opt6_find(opt6_ptr(opt, 4), vend, opt_cfg->opt, 0);
                    399:                   vopt;
                    400:                   vopt = opt6_find(opt6_next(vopt, vend), vend, opt_cfg->opt, 0))
                    401:                if ((match = match_bytes(opt_cfg, opt6_ptr(vopt, 0), opt6_len(vopt))))
                    402:                  break;
                    403:            }
                    404:          if (match)
                    405:            break;
                    406:        }
                    407:       else
                    408:        {
1.1.1.2 ! misho     409:          if (!(opt = opt6_find(state->packet_options, state->end, opt_cfg->opt, 1)))
1.1       misho     410:            continue;
                    411:          
                    412:          match = match_bytes(opt_cfg, opt6_ptr(opt, 0), opt6_len(opt));
                    413:        } 
                    414:   
                    415:       if (match)
                    416:        {
1.1.1.2 ! misho     417:          opt_cfg->netid->next = state->tags;
        !           418:          state->tags = opt_cfg->netid;
1.1       misho     419:        }
                    420:     }
1.1.1.2 ! misho     421: 
        !           422:   if (state->mac_len != 0)
        !           423:     {
        !           424:       if (option_bool(OPT_LOG_OPTS))
        !           425:        {
        !           426:          print_mac(daemon->dhcp_buff, state->mac, state->mac_len);
        !           427:          my_syslog(MS_DHCP | LOG_INFO, _("%u client MAC address: %s"), state->xid, daemon->dhcp_buff);
        !           428:        }
        !           429: 
        !           430:       for (mac_opt = daemon->dhcp_macs; mac_opt; mac_opt = mac_opt->next)
        !           431:        if ((unsigned)mac_opt->hwaddr_len == state->mac_len &&
        !           432:            ((unsigned)mac_opt->hwaddr_type == state->mac_type || mac_opt->hwaddr_type == 0) &&
        !           433:            memcmp_masked(mac_opt->hwaddr, state->mac, state->mac_len, mac_opt->mask))
        !           434:          {
        !           435:            mac_opt->netid.next = state->tags;
        !           436:            state->tags = &mac_opt->netid;
        !           437:          }
        !           438:     }
1.1       misho     439:   
1.1.1.2 ! misho     440:   if ((opt = opt6_find(state->packet_options, state->end, OPTION6_FQDN, 1)))
1.1       misho     441:     {
                    442:       /* RFC4704 refers */
                    443:        int len = opt6_len(opt) - 1;
                    444:        
1.1.1.2 ! misho     445:        state->fqdn_flags = opt6_uint(opt, 0, 1);
1.1       misho     446:        
                    447:        /* Always force update, since the client has no way to do it itself. */
1.1.1.2 ! misho     448:        if (!option_bool(OPT_FQDN_UPDATE) && !(state->fqdn_flags & 0x01))
        !           449:         state->fqdn_flags |= 0x03;
1.1       misho     450:  
1.1.1.2 ! misho     451:        state->fqdn_flags &= ~0x04;
1.1       misho     452: 
                    453:        if (len != 0 && len < 255)
                    454:         {
                    455:           unsigned char *pp, *op = opt6_ptr(opt, 1);
                    456:           char *pq = daemon->dhcp_buff;
                    457:           
                    458:           pp = op;
                    459:           while (*op != 0 && ((op + (*op)) - pp) < len)
                    460:             {
                    461:               memcpy(pq, op+1, *op);
                    462:               pq += *op;
                    463:               op += (*op)+1;
                    464:               *(pq++) = '.';
                    465:             }
                    466:           
                    467:           if (pq != daemon->dhcp_buff)
                    468:             pq--;
                    469:           *pq = 0;
                    470:           
                    471:           if (legal_hostname(daemon->dhcp_buff))
                    472:             {
1.1.1.2 ! misho     473:               state->client_hostname = daemon->dhcp_buff;
1.1       misho     474:               if (option_bool(OPT_LOG_OPTS))
1.1.1.2 ! misho     475:                 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname); 
1.1       misho     476:             }
                    477:         }
                    478:     }   
                    479:   
1.1.1.2 ! misho     480:   if (state->clid)
1.1       misho     481:     {
1.1.1.2 ! misho     482:       config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL);
1.1       misho     483:       
                    484:       if (have_config(config, CONFIG_NAME))
                    485:        {
1.1.1.2 ! misho     486:          state->hostname = config->hostname;
        !           487:          state->domain = config->domain;
        !           488:          state->hostname_auth = 1;
1.1       misho     489:        }
1.1.1.2 ! misho     490:       else if (state->client_hostname)
1.1       misho     491:        {
1.1.1.2 ! misho     492:          state->domain = strip_hostname(state->client_hostname);
1.1       misho     493:          
1.1.1.2 ! misho     494:          if (strlen(state->client_hostname) != 0)
1.1       misho     495:            {
1.1.1.2 ! misho     496:              state->hostname = state->client_hostname;
1.1       misho     497:              if (!config)
                    498:                {
                    499:                  /* Search again now we have a hostname. 
                    500:                     Only accept configs without CLID here, (it won't match)
                    501:                     to avoid impersonation by name. */
1.1.1.2 ! misho     502:                  struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname);
1.1       misho     503:                  if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
                    504:                    config = new;
                    505:                }
                    506:            }
                    507:        }
                    508:     }
                    509: 
                    510:   if (config)
                    511:     {
                    512:       struct dhcp_netid_list *list;
                    513:       
                    514:       for (list = config->netid; list; list = list->next)
                    515:         {
1.1.1.2 ! misho     516:           list->list->next = state->tags;
        !           517:           state->tags = list->list;
1.1       misho     518:         }
                    519: 
                    520:       /* set "known" tag for known hosts */
                    521:       known_id.net = "known";
1.1.1.2 ! misho     522:       known_id.next = state->tags;
        !           523:       state->tags = &known_id;
1.1       misho     524: 
                    525:       if (have_config(config, CONFIG_DISABLE))
                    526:        ignore = 1;
                    527:     }
                    528: 
                    529: #ifdef OPTION6_PREFIX_CLASS
                    530:   /* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
                    531:   if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
                    532:     {
                    533:       void *oro;
                    534:       
1.1.1.2 ! misho     535:       if ((oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0)))
1.1       misho     536:        for (i = 0; i <  opt6_len(oro) - 1; i += 2)
                    537:          if (opt6_uint(oro, i, 2) == OPTION6_PREFIX_CLASS)
                    538:            {
                    539:              dump_all_prefix_classes = 1;
                    540:              break;
                    541:            }
                    542:       
                    543:       if (msg_type != DHCP6SOLICIT || dump_all_prefix_classes)
                    544:        /* Add the tags associated with prefix classes so we can use the DHCP ranges.
                    545:           Not done for SOLICIT as we add them  one-at-time. */
                    546:        for (p = daemon->prefix_classes; p ; p = p->next)
                    547:          {
1.1.1.2 ! misho     548:            p->tag.next = state->tags;
        !           549:            state->tags = &p->tag;
1.1       misho     550:          }
                    551:     }    
                    552: #endif
                    553: 
1.1.1.2 ! misho     554:   tagif = run_tag_if(state->tags);
1.1       misho     555:   
                    556:   /* if all the netids in the ignore list are present, ignore this client */
                    557:   if (daemon->dhcp_ignore)
                    558:     {
                    559:       struct dhcp_netid_list *id_list;
                    560:      
                    561:       for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
                    562:        if (match_netid(id_list->list, tagif, 0))
                    563:          ignore = 1;
                    564:     }
                    565:   
                    566:   /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1.1.1.2 ! misho     567:   if (!state->hostname_auth)
1.1       misho     568:     {
                    569:        struct dhcp_netid_list *id_list;
                    570:        
                    571:        for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
                    572:         if ((!id_list->list) || match_netid(id_list->list, tagif, 0))
                    573:           break;
                    574:        if (id_list)
1.1.1.2 ! misho     575:         state->hostname = NULL;
1.1       misho     576:     }
                    577:   
                    578: 
                    579:   switch (msg_type)
                    580:     {
                    581:     default:
                    582:       return 0;
1.1.1.2 ! misho     583:       
        !           584:       
1.1       misho     585:     case DHCP6SOLICIT:
                    586:       {
                    587:        int address_assigned = 0;
                    588:        /* tags without all prefix-class tags */
1.1.1.2 ! misho     589:        struct dhcp_netid *solicit_tags;
1.1       misho     590:        struct dhcp_context *c;
1.1.1.2 ! misho     591:        
        !           592:        *outmsgtypep = DHCP6ADVERTISE;
        !           593:        
        !           594:        if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
1.1       misho     595:          {
1.1.1.2 ! misho     596:            *outmsgtypep = DHCP6REPLY;
        !           597:            state->lease_allocate = 1;
1.1       misho     598:            o = new_opt6(OPTION6_RAPID_COMMIT);
                    599:            end_opt6(o);
                    600:          }
1.1.1.2 ! misho     601:        
        !           602:        log6_quiet(state, "DHCPSOLICIT", NULL, ignore ? _("ignored") : NULL);
1.1       misho     603: 
1.1.1.2 ! misho     604:       request_no_address:
        !           605:        solicit_tags = tagif;
1.1       misho     606:        
                    607:        if (ignore)
                    608:          return 0;
                    609:        
                    610:        /* reset USED bits in leases */
                    611:        lease6_reset();
                    612: 
                    613:        /* Can use configured address max once per prefix */
1.1.1.2 ! misho     614:        for (c = state->context; c; c = c->current)
1.1       misho     615:          c->flags &= ~CONTEXT_CONF_USED;
                    616: 
1.1.1.2 ! misho     617:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho     618:          {   
                    619:            void *ia_option, *ia_end;
                    620:            unsigned int min_time = 0xffffffff;
                    621:            int t1cntr;
                    622:            int ia_counter;
                    623:            /* set unless we're sending a particular prefix-class, when we
                    624:               want only dhcp-ranges with the correct tags set and not those without any tags. */
                    625:            int plain_range = 1;
1.1.1.2 ! misho     626:            u32 lease_time;
1.1       misho     627:            struct dhcp_lease *ltmp;
                    628:            struct in6_addr *req_addr;
                    629:            struct in6_addr addr;
                    630: 
1.1.1.2 ! misho     631:            if (!check_ia(state, opt, &ia_end, &ia_option))
1.1       misho     632:              continue;
                    633:            
                    634:            /* reset USED bits in contexts - one address per prefix per IAID */
1.1.1.2 ! misho     635:            for (c = state->context; c; c = c->current)
1.1       misho     636:              c->flags &= ~CONTEXT_USED;
                    637: 
                    638: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     639:            if (daemon->prefix_classes && state->ia_type == OPTION6_IA_NA)
1.1       misho     640:              {
                    641:                void *prefix_opt;
                    642:                int prefix_class;
                    643:                
                    644:                if (dump_all_prefix_classes)
                    645:                  /* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
                    646:                  plain_range = 0;
                    647:                else 
                    648:                  { 
                    649:                    if ((prefix_opt = opt6_find(opt6_ptr(opt, 12), ia_end, OPTION6_PREFIX_CLASS, 2)))
                    650:                      {
                    651:                        
                    652:                        prefix_class = opt6_uint(prefix_opt, 0, 2);
                    653:                        
                    654:                        for (p = daemon->prefix_classes; p ; p = p->next)
                    655:                          if (p->class == prefix_class)
                    656:                            break;
                    657:                        
                    658:                        if (!p)
                    659:                          my_syslog(MS_DHCP | LOG_WARNING, _("unknown prefix-class %d"), prefix_class);
                    660:                        else
                    661:                          {
                    662:                            /* add tag to list, and exclude undecorated dhcp-ranges */
1.1.1.2 ! misho     663:                            p->tag.next = state->tags;
1.1       misho     664:                            solicit_tags = run_tag_if(&p->tag);
                    665:                            plain_range = 0;
1.1.1.2 ! misho     666:                            state->send_prefix_class = p;
1.1       misho     667:                          }
                    668:                      }
                    669:                    else
                    670:                      {
                    671:                        /* client didn't ask for a prefix class, lets see if we can find one. */
                    672:                        for (p = daemon->prefix_classes; p ; p = p->next)
                    673:                          {
                    674:                            p->tag.next = NULL;
                    675:                            if (match_netid(&p->tag, solicit_tags, 1))
                    676:                              break;
                    677:                          }
                    678:                        
                    679:                        if (p)
                    680:                          {
                    681:                            plain_range = 0;
1.1.1.2 ! misho     682:                            state->send_prefix_class = p;
1.1       misho     683:                          }
                    684:                      }
                    685: 
                    686:                    if (p && option_bool(OPT_LOG_OPTS))
1.1.1.2 ! misho     687:                      my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state->xid, p->class, p->tag.net); 
1.1       misho     688:                  }
                    689:              }
                    690: #endif
                    691: 
1.1.1.2 ! misho     692:            o = build_ia(state, &t1cntr);
1.1       misho     693: 
                    694:            for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
                    695:              {
                    696:                req_addr = opt6_ptr(ia_option, 0);
1.1.1.2 ! misho     697:                                
        !           698:                if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
1.1       misho     699:                  {
                    700:                    lease_time = c->lease_time;
                    701:                    /* If the client asks for an address on the same network as a configured address, 
                    702:                       offer the configured address instead, to make moving to newly-configured
                    703:                       addresses automatic. */
1.1.1.2 ! misho     704:                    if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
1.1       misho     705:                      {
                    706:                        req_addr = &addr;
                    707:                        mark_config_used(c, &addr);
                    708:                        if (have_config(config, CONFIG_TIME))
                    709:                          lease_time = config->lease_time;
                    710:                      }
1.1.1.2 ! misho     711:                    else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
1.1       misho     712:                      continue; /* not an address we're allowed */
1.1.1.2 ! misho     713:                    else if (!check_address(state, req_addr))
1.1       misho     714:                      continue; /* address leased elsewhere */
                    715:                    
                    716:                    /* add address to output packet */
                    717: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     718:                    if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
        !           719:                      state->send_prefix_class = prefix_class_from_context(c);
1.1       misho     720: #endif             
1.1.1.2 ! misho     721:                    add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
        !           722:                    mark_context_used(state, req_addr);
        !           723:                    get_context_tag(state, c);
1.1       misho     724:                    address_assigned = 1;
                    725:                  }
                    726:              }
                    727:            
                    728:            /* Suggest configured address(es) */
1.1.1.2 ! misho     729:            for (c = state->context; c; c = c->current) 
1.1       misho     730:              if (!(c->flags & CONTEXT_CONF_USED) &&
                    731:                  match_netid(c->filter, solicit_tags, plain_range) &&
                    732:                  config_valid(config, c, &addr) && 
1.1.1.2 ! misho     733:                  check_address(state, &addr))
1.1       misho     734:                {
1.1.1.2 ! misho     735:                  mark_config_used(state->context, &addr);
1.1       misho     736:                  if (have_config(config, CONFIG_TIME))
                    737:                    lease_time = config->lease_time;
                    738:                  else
                    739:                    lease_time = c->lease_time;
                    740:                  /* add address to output packet */
                    741: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     742:                  if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
        !           743:                    state->send_prefix_class = prefix_class_from_context(c);
1.1       misho     744: #endif
1.1.1.2 ! misho     745:                  add_address(state, c, lease_time, NULL, &min_time, &addr, now);
        !           746:                  mark_context_used(state, &addr);
        !           747:                  get_context_tag(state, c);
1.1       misho     748:                  address_assigned = 1;
                    749:                }
                    750:            
                    751:            /* return addresses for existing leases */
                    752:            ltmp = NULL;
1.1.1.2 ! misho     753:            while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
1.1       misho     754:              {
1.1.1.2 ! misho     755:                req_addr = &ltmp->addr6;
        !           756:                if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
1.1       misho     757:                  {
                    758: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     759:                    if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
        !           760:                      state->send_prefix_class = prefix_class_from_context(c);
1.1       misho     761: #endif
1.1.1.2 ! misho     762:                    add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
        !           763:                    mark_context_used(state, req_addr);
        !           764:                    get_context_tag(state, c);
1.1       misho     765:                    address_assigned = 1;
                    766:                  }
                    767:              }
                    768:                           
                    769:            /* Return addresses for all valid contexts which don't yet have one */
1.1.1.2 ! misho     770:            while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
        !           771:                                          state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
1.1       misho     772:              {
                    773: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     774:                if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
        !           775:                  state->send_prefix_class = prefix_class_from_context(c);
1.1       misho     776: #endif
1.1.1.2 ! misho     777:                add_address(state, c, c->lease_time, NULL, &min_time, &addr, now);
        !           778:                mark_context_used(state, &addr);
        !           779:                get_context_tag(state, c);
1.1       misho     780:                address_assigned = 1;
                    781:              }
                    782:            
                    783:            end_ia(t1cntr, min_time, 0);
                    784:            end_opt6(o);        
                    785:          }
                    786: 
                    787:        if (address_assigned) 
                    788:          {
                    789:            o1 = new_opt6(OPTION6_STATUS_CODE);
                    790:            put_opt6_short(DHCP6SUCCESS);
                    791:            put_opt6_string(_("success"));
                    792:            end_opt6(o1);
                    793:            
                    794:            /* If --dhcp-authoritative is set, we can tell client not to wait for
                    795:               other possible servers */
                    796:            o = new_opt6(OPTION6_PREFERENCE);
                    797:            put_opt6_char(option_bool(OPT_AUTHORITATIVE) ? 255 : 0);
                    798:            end_opt6(o);
1.1.1.2 ! misho     799:            tagif = add_options(state, 0);
1.1       misho     800:          }
                    801:        else
                    802:          { 
                    803:            /* no address, return error */
                    804:            o1 = new_opt6(OPTION6_STATUS_CODE);
                    805:            put_opt6_short(DHCP6NOADDRS);
                    806:            put_opt6_string(_("no addresses available"));
                    807:            end_opt6(o1);
1.1.1.2 ! misho     808:            log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available"));
1.1       misho     809:          }
                    810: 
                    811:        break;
                    812:       }
                    813:       
                    814:     case DHCP6REQUEST:
                    815:       {
                    816:        int address_assigned = 0;
1.1.1.2 ! misho     817:        int start = save_counter(-1);
        !           818: 
1.1       misho     819:        /* set reply message type */
                    820:        *outmsgtypep = DHCP6REPLY;
1.1.1.2 ! misho     821:        state->lease_allocate = 1;
1.1       misho     822: 
1.1.1.2 ! misho     823:        log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
1.1       misho     824:        
                    825:        if (ignore)
                    826:          return 0;
                    827:        
1.1.1.2 ! misho     828:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho     829:          {   
                    830:            void *ia_option, *ia_end;
                    831:            unsigned int min_time = 0xffffffff;
                    832:            int t1cntr;
                    833:            
1.1.1.2 ! misho     834:             if (!check_ia(state, opt, &ia_end, &ia_option))
1.1       misho     835:               continue;
1.1.1.2 ! misho     836: 
        !           837:             if (!ia_option)
        !           838:               {
        !           839:                 /* If we get a request with a IA_*A without addresses, treat it exactly like
        !           840:                    a SOLICT with rapid commit set. */
        !           841:                 save_counter(start);
        !           842:                 goto request_no_address; 
        !           843:               }
        !           844: 
        !           845:            o = build_ia(state, &t1cntr);
1.1       misho     846:              
                    847:            for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
                    848:              {
                    849:                struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
                    850:                struct dhcp_context *dynamic, *c;
                    851:                unsigned int lease_time;
                    852:                struct in6_addr addr;
                    853:                int config_ok = 0;
                    854:                
1.1.1.2 ! misho     855:                if ((c = address6_valid(state->context, req_addr, tagif, 1)))
1.1       misho     856:                  config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
                    857:                
1.1.1.2 ! misho     858:                if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
1.1       misho     859:                  {
                    860:                    if (!dynamic && !config_ok)
                    861:                      {
                    862:                        /* Static range, not configured. */
                    863:                        o1 = new_opt6(OPTION6_STATUS_CODE);
                    864:                        put_opt6_short(DHCP6UNSPEC);
                    865:                        put_opt6_string(_("address unavailable"));
                    866:                        end_opt6(o1);
                    867:                      }
1.1.1.2 ! misho     868:                    else if (!check_address(state, req_addr))
1.1       misho     869:                      {
                    870:                        /* Address leased to another DUID/IAID */
                    871:                        o1 = new_opt6(OPTION6_STATUS_CODE);
                    872:                        put_opt6_short(DHCP6UNSPEC);
                    873:                        put_opt6_string(_("address in use"));
                    874:                        end_opt6(o1);
                    875:                      } 
                    876:                    else 
                    877:                      {
                    878:                        if (!dynamic)
                    879:                          dynamic = c;
                    880: 
                    881:                        lease_time = dynamic->lease_time;
                    882:                        
                    883:                        if (config_ok && have_config(config, CONFIG_TIME))
                    884:                          lease_time = config->lease_time;
                    885: 
                    886: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho     887:                        if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
        !           888:                          state->send_prefix_class = prefix_class_from_context(c);
1.1       misho     889: #endif
1.1.1.2 ! misho     890:                        add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
        !           891:                        get_context_tag(state, dynamic);
1.1       misho     892:                        address_assigned = 1;
                    893:                      }
                    894:                  }
                    895:                else 
                    896:                  {
                    897:                    /* requested address not on the correct link */
                    898:                    o1 = new_opt6(OPTION6_STATUS_CODE);
                    899:                    put_opt6_short(DHCP6NOTONLINK);
                    900:                    put_opt6_string(_("not on link"));
                    901:                    end_opt6(o1);
                    902:                  }
                    903:              }
                    904:         
                    905:            end_ia(t1cntr, min_time, 0);
                    906:            end_opt6(o);        
                    907:          }
                    908: 
                    909:        if (address_assigned) 
                    910:          {
                    911:            o1 = new_opt6(OPTION6_STATUS_CODE);
                    912:            put_opt6_short(DHCP6SUCCESS);
                    913:            put_opt6_string(_("success"));
                    914:            end_opt6(o1);
                    915:          }
                    916:        else
                    917:          { 
                    918:            /* no address, return error */
                    919:            o1 = new_opt6(OPTION6_STATUS_CODE);
                    920:            put_opt6_short(DHCP6NOADDRS);
                    921:            put_opt6_string(_("no addresses available"));
                    922:            end_opt6(o1);
1.1.1.2 ! misho     923:            log6_packet(state, "DHCPREPLY", NULL, _("no addresses available"));
1.1       misho     924:          }
                    925: 
1.1.1.2 ! misho     926:        tagif = add_options(state, 0);
1.1       misho     927:        break;
                    928:       }
                    929:       
                    930:   
                    931:     case DHCP6RENEW:
                    932:       {
                    933:        /* set reply message type */
                    934:        *outmsgtypep = DHCP6REPLY;
                    935:        
1.1.1.2 ! misho     936:        log6_quiet(state, "DHCPRENEW", NULL, NULL);
1.1       misho     937: 
1.1.1.2 ! misho     938:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho     939:          {
                    940:            void *ia_option, *ia_end;
                    941:            unsigned int min_time = 0xffffffff;
                    942:            int t1cntr, iacntr;
                    943:            
1.1.1.2 ! misho     944:            if (!check_ia(state, opt, &ia_end, &ia_option))
1.1       misho     945:              continue;
                    946:            
1.1.1.2 ! misho     947:            o = build_ia(state, &t1cntr);
1.1       misho     948:            iacntr = save_counter(-1); 
                    949:            
                    950:            for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
                    951:              {
                    952:                struct dhcp_lease *lease = NULL;
                    953:                struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
1.1.1.2 ! misho     954:                unsigned int preferred_time =  opt6_uint(ia_option, 16, 4);
        !           955:                unsigned int valid_time =  opt6_uint(ia_option, 20, 4);
1.1       misho     956:                char *message = NULL;
                    957:                struct dhcp_context *this_context;
                    958:                
1.1.1.2 ! misho     959:                if (!(lease = lease6_find(state->clid, state->clid_len,
        !           960:                                          state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, 
        !           961:                                          state->iaid, req_addr)))
1.1       misho     962:                  {
                    963:                    /* If the server cannot find a client entry for the IA the server
                    964:                       returns the IA containing no addresses with a Status Code option set
                    965:                       to NoBinding in the Reply message. */
                    966:                    save_counter(iacntr);
                    967:                    t1cntr = 0;
                    968:                    
1.1.1.2 ! misho     969:                    log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
1.1       misho     970:                    
                    971:                    o1 = new_opt6(OPTION6_STATUS_CODE);
                    972:                    put_opt6_short(DHCP6NOBINDING);
                    973:                    put_opt6_string(_("no binding found"));
                    974:                    end_opt6(o1);
1.1.1.2 ! misho     975: 
        !           976:                    preferred_time = valid_time = 0;
1.1       misho     977:                    break;
                    978:                  }
                    979:                
                    980:                
1.1.1.2 ! misho     981:                if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
        !           982:                    (this_context = address6_valid(state->context, req_addr, tagif, 1)))
1.1       misho     983:                  {
                    984:                    struct in6_addr addr;
                    985:                    unsigned int lease_time;
                    986: 
1.1.1.2 ! misho     987:                    get_context_tag(state, this_context);
1.1       misho     988:                    
                    989:                    if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
                    990:                      lease_time = config->lease_time;
                    991:                    else 
                    992:                      lease_time = this_context->lease_time;
                    993:                    
1.1.1.2 ! misho     994:                    calculate_times(this_context, &min_time, &valid_time, &preferred_time, lease_time); 
1.1       misho     995:                    
                    996:                    lease_set_expires(lease, valid_time, now);
1.1.1.2 ! misho     997:                    /* Update MAC record in case it's new information. */
        !           998:                    if (state->mac_len != 0)
        !           999:                      lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
        !          1000:                    if (state->ia_type == OPTION6_IA_NA && state->hostname)
1.1       misho    1001:                      {
                   1002:                        char *addr_domain = get_domain6(req_addr);
1.1.1.2 ! misho    1003:                        if (!state->send_domain)
        !          1004:                          state->send_domain = addr_domain;
        !          1005:                        lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain); 
        !          1006:                        message = state->hostname;
1.1       misho    1007:                      }
                   1008:                    
                   1009:                    
                   1010:                    if (preferred_time == 0)
                   1011:                      message = _("deprecated");
                   1012:                  }
                   1013:                else
1.1.1.2 ! misho    1014:                  {
        !          1015:                    preferred_time = valid_time = 0;
        !          1016:                    message = _("address invalid");
        !          1017:                  }
        !          1018: 
        !          1019:                if (message)
        !          1020:                  log6_packet(state, "DHCPREPLY", req_addr, message);   
        !          1021:                else
        !          1022:                  log6_quiet(state, "DHCPREPLY", req_addr, message);
        !          1023:        
1.1       misho    1024:                o1 =  new_opt6(OPTION6_IAADDR);
                   1025:                put_opt6(req_addr, sizeof(*req_addr));
                   1026:                put_opt6_long(preferred_time);
                   1027:                put_opt6_long(valid_time);
                   1028:                end_opt6(o1);
                   1029:              }
                   1030:            
                   1031:            end_ia(t1cntr, min_time, 1);
                   1032:            end_opt6(o);
                   1033:          }
                   1034:        
1.1.1.2 ! misho    1035:        tagif = add_options(state, 0);
1.1       misho    1036:        break;
                   1037:        
                   1038:       }
                   1039:       
                   1040:     case DHCP6CONFIRM:
                   1041:       {
                   1042:        /* set reply message type */
                   1043:        *outmsgtypep = DHCP6REPLY;
                   1044:        
1.1.1.2 ! misho    1045:        log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
1.1       misho    1046:        
1.1.1.2 ! misho    1047:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho    1048:          {
                   1049:            void *ia_option, *ia_end;
                   1050:            
1.1.1.2 ! misho    1051:            for (check_ia(state, opt, &ia_end, &ia_option);
1.1       misho    1052:                 ia_option;
                   1053:                 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
                   1054:              {
                   1055:                struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
                   1056:                
1.1.1.2 ! misho    1057:                if (!address6_available(state->context, req_addr, tagif, 1))
1.1       misho    1058:                  {
                   1059:                    o1 = new_opt6(OPTION6_STATUS_CODE);
                   1060:                    put_opt6_short(DHCP6NOTONLINK);
                   1061:                    put_opt6_string(_("confirm failed"));
                   1062:                    end_opt6(o1);
                   1063:                    return 1;
                   1064:                  }
                   1065: 
1.1.1.2 ! misho    1066:                log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
1.1       misho    1067:              }
                   1068:          }      
                   1069: 
                   1070:        o1 = new_opt6(OPTION6_STATUS_CODE);
                   1071:        put_opt6_short(DHCP6SUCCESS );
                   1072:        put_opt6_string(_("all addresses still on link"));
                   1073:        end_opt6(o1);
                   1074:        break;
                   1075:     }
                   1076:       
                   1077:     case DHCP6IREQ:
                   1078:       {
                   1079:        /* We can't discriminate contexts based on address, as we don't know it.
                   1080:           If there is only one possible context, we can use its tags */
1.1.1.2 ! misho    1081:        if (state->context && state->context->netid.net && !state->context->current)
1.1       misho    1082:          {
1.1.1.2 ! misho    1083:            state->context->netid.next = NULL;
        !          1084:            state->context_tags =  &state->context->netid;
1.1       misho    1085:          }
1.1.1.2 ! misho    1086: 
        !          1087:        /* Similarly, we can't determine domain from address, but if the FQDN is
        !          1088:           given in --dhcp-host, we can use that, and failing that we can use the 
        !          1089:           unqualified configured domain, if any. */
        !          1090:        if (state->hostname_auth)
        !          1091:          state->send_domain = state->domain;
        !          1092:        else
        !          1093:          state->send_domain = get_domain6(NULL);
        !          1094: 
        !          1095:        log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
1.1       misho    1096:        if (ignore)
                   1097:          return 0;
                   1098:        *outmsgtypep = DHCP6REPLY;
1.1.1.2 ! misho    1099:        tagif = add_options(state, 1);
1.1       misho    1100:        break;
                   1101:       }
                   1102:       
                   1103:       
                   1104:     case DHCP6RELEASE:
                   1105:       {
                   1106:        /* set reply message type */
                   1107:        *outmsgtypep = DHCP6REPLY;
                   1108: 
1.1.1.2 ! misho    1109:        log6_quiet(state, "DHCPRELEASE", NULL, NULL);
1.1       misho    1110: 
1.1.1.2 ! misho    1111:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho    1112:          {
                   1113:            void *ia_option, *ia_end;
                   1114:            int made_ia = 0;
                   1115:                    
1.1.1.2 ! misho    1116:            for (check_ia(state, opt, &ia_end, &ia_option);
1.1       misho    1117:                 ia_option;
                   1118:                 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) 
                   1119:              {
                   1120:                struct dhcp_lease *lease;
                   1121:                
1.1.1.2 ! misho    1122:                if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
        !          1123:                                         state->iaid, opt6_ptr(ia_option, 0))))
1.1       misho    1124:                  lease_prune(lease, now);
                   1125:                else
                   1126:                  {
                   1127:                    if (!made_ia)
                   1128:                      {
1.1.1.2 ! misho    1129:                        o = new_opt6(state->ia_type);
        !          1130:                        put_opt6_long(state->iaid);
        !          1131:                        if (state->ia_type == OPTION6_IA_NA)
1.1       misho    1132:                          {
                   1133:                            put_opt6_long(0);
                   1134:                            put_opt6_long(0); 
                   1135:                          }
                   1136:                        made_ia = 1;
                   1137:                      }
                   1138:                    
                   1139:                    o1 = new_opt6(OPTION6_IAADDR);
                   1140:                    put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
                   1141:                    put_opt6_long(0);
                   1142:                    put_opt6_long(0);
                   1143:                    end_opt6(o1);
                   1144:                  }
                   1145:              }
                   1146:            
                   1147:            if (made_ia)
                   1148:              {
                   1149:                o1 = new_opt6(OPTION6_STATUS_CODE);
                   1150:                put_opt6_short(DHCP6NOBINDING);
                   1151:                put_opt6_string(_("no binding found"));
                   1152:                end_opt6(o1);
                   1153:                
                   1154:                end_opt6(o);
                   1155:              }
                   1156:          }
                   1157:        
                   1158:        o1 = new_opt6(OPTION6_STATUS_CODE);
                   1159:        put_opt6_short(DHCP6SUCCESS);
                   1160:        put_opt6_string(_("release received"));
                   1161:        end_opt6(o1);
                   1162:        
                   1163:        break;
                   1164:       }
                   1165: 
                   1166:     case DHCP6DECLINE:
                   1167:       {
                   1168:        /* set reply message type */
                   1169:        *outmsgtypep = DHCP6REPLY;
                   1170:        
1.1.1.2 ! misho    1171:        log6_quiet(state, "DHCPDECLINE", NULL, NULL);
1.1       misho    1172: 
1.1.1.2 ! misho    1173:        for (opt = state->packet_options; opt; opt = opt6_next(opt, state->end))
1.1       misho    1174:          {
                   1175:            void *ia_option, *ia_end;
                   1176:            int made_ia = 0;
                   1177:                    
1.1.1.2 ! misho    1178:            for (check_ia(state, opt, &ia_end, &ia_option);
1.1       misho    1179:                 ia_option;
                   1180:                 ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24)) 
                   1181:              {
                   1182:                struct dhcp_lease *lease;
                   1183:                struct in6_addr *addrp = opt6_ptr(ia_option, 0);
                   1184: 
                   1185:                if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
                   1186:                  {
                   1187:                    prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
                   1188:                    inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
                   1189:                    my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), 
                   1190:                              daemon->addrbuff, daemon->dhcp_buff3);
                   1191:                    config->flags |= CONFIG_DECLINED;
                   1192:                    config->decline_time = now;
                   1193:                  }
                   1194:                else
                   1195:                  /* make sure this host gets a different address next time. */
1.1.1.2 ! misho    1196:                  for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
        !          1197:                    context_tmp->addr_epoch++;
1.1       misho    1198:                
1.1.1.2 ! misho    1199:                if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
        !          1200:                                         state->iaid, opt6_ptr(ia_option, 0))))
1.1       misho    1201:                  lease_prune(lease, now);
                   1202:                else
                   1203:                  {
                   1204:                    if (!made_ia)
                   1205:                      {
1.1.1.2 ! misho    1206:                        o = new_opt6(state->ia_type);
        !          1207:                        put_opt6_long(state->iaid);
        !          1208:                        if (state->ia_type == OPTION6_IA_NA)
1.1       misho    1209:                          {
                   1210:                            put_opt6_long(0);
                   1211:                            put_opt6_long(0); 
                   1212:                          }
                   1213:                        made_ia = 1;
                   1214:                      }
                   1215:                    
                   1216:                    o1 = new_opt6(OPTION6_IAADDR);
                   1217:                    put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
                   1218:                    put_opt6_long(0);
                   1219:                    put_opt6_long(0);
                   1220:                    end_opt6(o1);
                   1221:                  }
                   1222:              }
                   1223:            
                   1224:            if (made_ia)
                   1225:              {
                   1226:                o1 = new_opt6(OPTION6_STATUS_CODE);
                   1227:                put_opt6_short(DHCP6NOBINDING);
                   1228:                put_opt6_string(_("no binding found"));
                   1229:                end_opt6(o1);
                   1230:                
                   1231:                end_opt6(o);
                   1232:              }
                   1233:            
                   1234:          }
                   1235:        break;
                   1236:       }
                   1237: 
                   1238:     }
                   1239:   
1.1.1.2 ! misho    1240:   log_tags(tagif, state->xid);
        !          1241:   log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
1.1       misho    1242:   
                   1243:   return 1;
                   1244: 
                   1245: }
                   1246: 
1.1.1.2 ! misho    1247: static struct dhcp_netid *add_options(struct state *state, int do_refresh)  
1.1       misho    1248: {
                   1249:   void *oro;
                   1250:   /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
                   1251:   struct dhcp_netid *tagif = option_filter(state->tags, state->context_tags, daemon->dhcp_opts6);
                   1252:   struct dhcp_opt *opt_cfg;
1.1.1.2 ! misho    1253:   int done_dns = 0, done_refresh = !do_refresh, do_encap = 0;
1.1       misho    1254:   int i, o, o1;
                   1255: 
                   1256:   oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0);
                   1257:   
                   1258:   for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
                   1259:     {
                   1260:       /* netids match and not encapsulated? */
                   1261:       if (!(opt_cfg->flags & DHOPT_TAGOK))
                   1262:        continue;
                   1263:       
                   1264:       if (!(opt_cfg->flags & DHOPT_FORCE) && oro)
                   1265:        {
                   1266:          for (i = 0; i <  opt6_len(oro) - 1; i += 2)
                   1267:            if (opt6_uint(oro, i, 2) == (unsigned)opt_cfg->opt)
                   1268:              break;
                   1269:          
                   1270:          /* option not requested */
                   1271:          if (i >=  opt6_len(oro) - 1)
                   1272:            continue;
                   1273:        }
                   1274:       
1.1.1.2 ! misho    1275:       if (opt_cfg->opt == OPTION6_REFRESH_TIME)
        !          1276:        done_refresh = 1;
1.1       misho    1277:       
                   1278:       if (opt_cfg->flags & DHOPT_ADDR6)
                   1279:        {
1.1.1.2 ! misho    1280:          int len, j;
        !          1281:          struct in6_addr *a;
        !          1282:          
        !          1283:          if (opt_cfg->opt == OPTION6_DNS_SERVER)
        !          1284:            done_dns = 1;
        !          1285:          
        !          1286:          for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0; 
        !          1287:               j < opt_cfg->len; j += IN6ADDRSZ, a++)
        !          1288:            if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) ||
        !          1289:                (IN6_IS_ADDR_LINK_LOCAL_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ll_addr)))
        !          1290:              len -= IN6ADDRSZ;
        !          1291:          
        !          1292:          if (len != 0)
        !          1293:            {
        !          1294:              
        !          1295:              o = new_opt6(opt_cfg->opt);
        !          1296:                  
        !          1297:              for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
        !          1298:                {
        !          1299:                  if (IN6_IS_ADDR_UNSPECIFIED(a))
        !          1300:                    {
        !          1301:                      if (!add_local_addrs(state->context))
        !          1302:                        put_opt6(state->fallback, IN6ADDRSZ);
        !          1303:                    }
        !          1304:                  else if (IN6_IS_ADDR_ULA_ZERO(a))
        !          1305:                    {
        !          1306:                      if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
        !          1307:                        put_opt6(state->ula_addr, IN6ADDRSZ);
        !          1308:                    }
        !          1309:                  else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
        !          1310:                    {
        !          1311:                      if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
        !          1312:                        put_opt6(state->ll_addr, IN6ADDRSZ);
        !          1313:                    }
        !          1314:                  else
        !          1315:                    put_opt6(a, IN6ADDRSZ);
1.1       misho    1316:                }
1.1.1.2 ! misho    1317: 
        !          1318:              end_opt6(o);
        !          1319:            }
        !          1320:        }
        !          1321:       else
        !          1322:        {
        !          1323:          o = new_opt6(opt_cfg->opt);
        !          1324:          if (opt_cfg->val)
        !          1325:            put_opt6(opt_cfg->val, opt_cfg->len);
        !          1326:          end_opt6(o);
1.1       misho    1327:        }
                   1328:     }
                   1329:   
1.1.1.2 ! misho    1330:   if (daemon->port == NAMESERVER_PORT && !done_dns)
1.1       misho    1331:     {
                   1332:       o = new_opt6(OPTION6_DNS_SERVER);
1.1.1.2 ! misho    1333:       if (!add_local_addrs(state->context))
        !          1334:        put_opt6(state->fallback, IN6ADDRSZ);
        !          1335:       end_opt6(o); 
        !          1336:     }
        !          1337: 
        !          1338:   if (state->context && !done_refresh)
        !          1339:     {
        !          1340:       struct dhcp_context *c;
        !          1341:       unsigned int lease_time = 0xffffffff;
        !          1342:       
        !          1343:       /* Find the smallest lease tie of all contexts,
        !          1344:         subjext to the RFC-4242 stipulation that this must not 
        !          1345:         be less than 600. */
        !          1346:       for (c = state->context; c; c = c->next)
        !          1347:        if (c->lease_time < lease_time)
        !          1348:          {
        !          1349:            if (c->lease_time < 600)
        !          1350:              lease_time = 600;
        !          1351:            else
        !          1352:              lease_time = c->lease_time;
        !          1353:          }
        !          1354: 
        !          1355:       o = new_opt6(OPTION6_REFRESH_TIME);
        !          1356:       put_opt6_long(lease_time);
1.1       misho    1357:       end_opt6(o); 
                   1358:     }
                   1359:    
                   1360:     /* handle vendor-identifying vendor-encapsulated options,
                   1361:        dhcp-option = vi-encap:13,17,....... */
                   1362:   for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
                   1363:     opt_cfg->flags &= ~DHOPT_ENCAP_DONE;
                   1364:     
                   1365:   if (oro)
                   1366:     for (i = 0; i <  opt6_len(oro) - 1; i += 2)
                   1367:       if (opt6_uint(oro, i, 2) == OPTION6_VENDOR_OPTS)
                   1368:        do_encap = 1;
                   1369:   
                   1370:   for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
                   1371:     { 
                   1372:       if (opt_cfg->flags & DHOPT_RFC3925)
                   1373:        {
                   1374:          int found = 0;
                   1375:          struct dhcp_opt *oc;
                   1376:          
                   1377:          if (opt_cfg->flags & DHOPT_ENCAP_DONE)
                   1378:            continue;
                   1379:          
                   1380:          for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
                   1381:            {
                   1382:              oc->flags &= ~DHOPT_ENCAP_MATCH;
                   1383:              
                   1384:              if (!(oc->flags & DHOPT_RFC3925) || opt_cfg->u.encap != oc->u.encap)
                   1385:                continue;
                   1386:              
                   1387:              oc->flags |= DHOPT_ENCAP_DONE;
                   1388:              if (match_netid(oc->netid, tagif, 1))
                   1389:                {
                   1390:                  /* option requested/forced? */
                   1391:                  if (!oro || do_encap || (oc->flags & DHOPT_FORCE))
                   1392:                    {
                   1393:                      oc->flags |= DHOPT_ENCAP_MATCH;
                   1394:                      found = 1;
                   1395:                    }
                   1396:                } 
                   1397:            }
                   1398:          
                   1399:          if (found)
                   1400:            { 
                   1401:              o = new_opt6(OPTION6_VENDOR_OPTS);              
                   1402:              put_opt6_long(opt_cfg->u.encap);  
                   1403:             
                   1404:              for (oc = daemon->dhcp_opts6; oc; oc = oc->next)
                   1405:                if (oc->flags & DHOPT_ENCAP_MATCH)
                   1406:                  {
                   1407:                    o1 = new_opt6(oc->opt);
                   1408:                    put_opt6(oc->val, oc->len);
                   1409:                    end_opt6(o1);
                   1410:                  }
                   1411:              end_opt6(o);
                   1412:            }
                   1413:        }
                   1414:     }      
                   1415: 
                   1416: 
                   1417:   if (state->hostname)
                   1418:     {
                   1419:       unsigned char *p;
                   1420:       size_t len = strlen(state->hostname);
                   1421:       
                   1422:       if (state->send_domain)
1.1.1.2 ! misho    1423:        len += strlen(state->send_domain) + 2;
1.1       misho    1424: 
                   1425:       o = new_opt6(OPTION6_FQDN);
1.1.1.2 ! misho    1426:       if ((p = expand(len + 2)))
1.1       misho    1427:        {
                   1428:          *(p++) = state->fqdn_flags;
                   1429:          p = do_rfc1035_name(p, state->hostname);
                   1430:          if (state->send_domain)
1.1.1.2 ! misho    1431:            {
        !          1432:              p = do_rfc1035_name(p, state->send_domain);
        !          1433:              *p = 0;
        !          1434:            }
1.1       misho    1435:        }
                   1436:       end_opt6(o);
                   1437:     }
                   1438: 
                   1439: 
                   1440:   /* logging */
                   1441:   if (option_bool(OPT_LOG_OPTS) && oro)
                   1442:     {
                   1443:       char *q = daemon->namebuff;
                   1444:       for (i = 0; i <  opt6_len(oro) - 1; i += 2)
                   1445:        {
                   1446:          char *s = option_string(AF_INET6, opt6_uint(oro, i, 2), NULL, 0, NULL, 0);
                   1447:          q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
                   1448:                        "%d%s%s%s", 
                   1449:                        opt6_uint(oro, i, 2),
                   1450:                        strlen(s) != 0 ? ":" : "",
                   1451:                        s, 
                   1452:                        (i > opt6_len(oro) - 3) ? "" : ", ");
                   1453:          if ( i >  opt6_len(oro) - 3 || (q - daemon->namebuff) > 40)
                   1454:            {
                   1455:              q = daemon->namebuff;
                   1456:              my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), state->xid, daemon->namebuff);
                   1457:            }
                   1458:        }
                   1459:     } 
                   1460: 
                   1461:   return tagif;
                   1462: }
                   1463:  
                   1464: static int add_local_addrs(struct dhcp_context *context)
                   1465: {
                   1466:   int done = 0;
                   1467:   
                   1468:   for (; context; context = context->current)
                   1469:     if ((context->flags & CONTEXT_USED) && !IN6_IS_ADDR_UNSPECIFIED(&context->local6))
                   1470:       {
                   1471:        /* squash duplicates */
                   1472:        struct dhcp_context *c;
                   1473:        for (c = context->current; c; c = c->current)
                   1474:          if ((c->flags & CONTEXT_USED) &&
                   1475:              IN6_ARE_ADDR_EQUAL(&context->local6, &c->local6))
                   1476:            break;
                   1477:        
                   1478:        if (!c)
                   1479:          { 
                   1480:            done = 1;
                   1481:            put_opt6(&context->local6, IN6ADDRSZ);
                   1482:          }
                   1483:       }
                   1484: 
                   1485:   return done;
                   1486: }
                   1487: 
                   1488: 
                   1489: static void get_context_tag(struct state *state, struct dhcp_context *context)
                   1490: {
                   1491:   /* get tags from context if we've not used it before */
                   1492:   if (context->netid.next == &context->netid && context->netid.net)
                   1493:     {
                   1494:       context->netid.next = state->context_tags;
                   1495:       state->context_tags = &context->netid;
                   1496:       if (!state->hostname_auth)
                   1497:        {
                   1498:          struct dhcp_netid_list *id_list;
                   1499:          
                   1500:          for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
                   1501:            if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
                   1502:              break;
                   1503:          if (id_list)
                   1504:            state->hostname = NULL;
                   1505:        }
                   1506:     }
                   1507: } 
                   1508: 
                   1509: #ifdef OPTION6_PREFIX_CLASS
                   1510: static struct prefix_class *prefix_class_from_context(struct dhcp_context *context)
                   1511: {
                   1512:   struct prefix_class *p;
                   1513:   struct dhcp_netid *t;
                   1514:   
                   1515:   for (p = daemon->prefix_classes; p ; p = p->next)
                   1516:     for (t = context->filter; t; t = t->next)
                   1517:       if (strcmp(p->tag.net, t->net) == 0)
                   1518:        return p;
                   1519:   
                   1520:  return NULL;
                   1521: }
                   1522: #endif
                   1523: 
                   1524: static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
                   1525: {
                   1526:   state->ia_type = opt6_type(opt);
                   1527:   *ia_option = NULL;
                   1528: 
                   1529:   if (state->ia_type != OPTION6_IA_NA && state->ia_type != OPTION6_IA_TA)
                   1530:     return 0;
                   1531:   
                   1532:   if (state->ia_type == OPTION6_IA_NA && opt6_len(opt) < 12)
                   1533:     return 0;
                   1534:            
                   1535:   if (state->ia_type == OPTION6_IA_TA && opt6_len(opt) < 4)
                   1536:     return 0;
                   1537:   
                   1538:   *endp = opt6_ptr(opt, opt6_len(opt));
                   1539:   state->iaid = opt6_uint(opt, 0, 4);
                   1540:   *ia_option = opt6_find(opt6_ptr(opt, state->ia_type == OPTION6_IA_NA ? 12 : 4), *endp, OPTION6_IAADDR, 24);
                   1541: 
                   1542:   return 1;
                   1543: }
                   1544: 
                   1545: 
                   1546: static int build_ia(struct state *state, int *t1cntr)
                   1547: {
                   1548:   int  o = new_opt6(state->ia_type);
                   1549:  
                   1550:   put_opt6_long(state->iaid);
                   1551:   *t1cntr = 0;
                   1552:            
                   1553:   if (state->ia_type == OPTION6_IA_NA)
                   1554:     {
                   1555:       /* save pointer */
                   1556:       *t1cntr = save_counter(-1);
                   1557:       /* so we can fill these in later */
                   1558:       put_opt6_long(0);
                   1559:       put_opt6_long(0); 
                   1560:     }
                   1561: 
                   1562:   return o;
                   1563: }
                   1564: 
                   1565: static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
                   1566: {
                   1567:   if (t1cntr != 0)
                   1568:     {
                   1569:       /* go back an fill in fields in IA_NA option */
                   1570:       int sav = save_counter(t1cntr);
                   1571:       unsigned int t1, t2, fuzz = 0;
                   1572: 
                   1573:       if (do_fuzz)
                   1574:        {
                   1575:          fuzz = rand16();
                   1576:       
                   1577:          while (fuzz > (min_time/16))
                   1578:            fuzz = fuzz/2;
                   1579:        }
                   1580:       
                   1581:       t1 = (min_time == 0xffffffff) ? 0xffffffff : min_time/2 - fuzz;
                   1582:       t2 = (min_time == 0xffffffff) ? 0xffffffff : ((min_time/8)*7) - fuzz;
                   1583:       put_opt6_long(t1);
                   1584:       put_opt6_long(t2);
                   1585:       save_counter(sav);
                   1586:     }  
                   1587: }
                   1588: 
1.1.1.2 ! misho    1589: static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, 
        !          1590:                        unsigned int *min_time, struct in6_addr *addr, time_t now)
1.1       misho    1591: {
1.1.1.2 ! misho    1592:   unsigned int valid_time = 0, preferred_time = 0;
1.1       misho    1593:   int o = new_opt6(OPTION6_IAADDR);
                   1594:   struct dhcp_lease *lease;
                   1595: 
1.1.1.2 ! misho    1596:   /* get client requested times */
        !          1597:   if (ia_option)
        !          1598:     {
        !          1599:       preferred_time =  opt6_uint(ia_option, 16, 4);
        !          1600:       valid_time =  opt6_uint(ia_option, 20, 4);
        !          1601:     }
        !          1602: 
        !          1603:   calculate_times(context, min_time, &valid_time, &preferred_time, lease_time); 
1.1       misho    1604:   
                   1605:   put_opt6(addr, sizeof(*addr));
                   1606:   put_opt6_long(preferred_time);
                   1607:   put_opt6_long(valid_time);               
                   1608:   
                   1609: #ifdef OPTION6_PREFIX_CLASS
                   1610:   if (state->send_prefix_class)
                   1611:     {
                   1612:       int o1 = new_opt6(OPTION6_PREFIX_CLASS);
                   1613:       put_opt6_short(state->send_prefix_class->class);
                   1614:       end_opt6(o1);
                   1615:     }
                   1616: #endif
                   1617: 
                   1618:   end_opt6(o);
                   1619:   
1.1.1.2 ! misho    1620:   if (state->lease_allocate)
1.1       misho    1621:     update_leases(state, context, addr, valid_time, now);
                   1622: 
                   1623:   if ((lease = lease6_find_by_addr(addr, 128, 0)))
                   1624:     lease->flags |= LEASE_USED;
                   1625: 
                   1626:   /* get tags from context if we've not used it before */
                   1627:   if (context->netid.next == &context->netid && context->netid.net)
                   1628:     {
                   1629:       context->netid.next = state->context_tags;
                   1630:       state->context_tags = &context->netid;
                   1631:       
                   1632:       if (!state->hostname_auth)
                   1633:        {
                   1634:          struct dhcp_netid_list *id_list;
                   1635:          
                   1636:          for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
                   1637:            if ((!id_list->list) || match_netid(id_list->list, &context->netid, 0))
                   1638:              break;
                   1639:          if (id_list)
                   1640:            state->hostname = NULL;
                   1641:        }
                   1642:     }
                   1643: 
1.1.1.2 ! misho    1644:   log6_quiet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", addr, state->hostname);
1.1       misho    1645: 
                   1646: }
                   1647: 
1.1.1.2 ! misho    1648: static void mark_context_used(struct state *state, struct in6_addr *addr)
1.1       misho    1649: {
1.1.1.2 ! misho    1650:   struct dhcp_context *context;
        !          1651: 
1.1       misho    1652:   /* Mark that we have an address for this prefix. */
                   1653: #ifdef OPTION6_PREFIX_CLASS
1.1.1.2 ! misho    1654:   for (context = state->context; context; context = context->current)
1.1       misho    1655:     if (is_same_net6(addr, &context->start6, context->prefix) &&
                   1656:        (!state->send_prefix_class || state->send_prefix_class == prefix_class_from_context(context)))
                   1657:       context->flags |= CONTEXT_USED;
                   1658: #else
1.1.1.2 ! misho    1659:   for (context = state->context; context; context = context->current)
1.1       misho    1660:     if (is_same_net6(addr, &context->start6, context->prefix))
                   1661:       context->flags |= CONTEXT_USED;
                   1662: #endif
                   1663: }
                   1664: 
                   1665: static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
                   1666: {
                   1667:   for (; context; context = context->current)
                   1668:     if (is_same_net6(addr, &context->start6, context->prefix))
                   1669:       context->flags |= CONTEXT_CONF_USED;
                   1670: }
                   1671: 
                   1672: /* make sure address not leased to another CLID/IAID */
                   1673: static int check_address(struct state *state, struct in6_addr *addr)
                   1674: { 
                   1675:   struct dhcp_lease *lease;
                   1676: 
                   1677:   if (!(lease = lease6_find_by_addr(addr, 128, 0)))
                   1678:     return 1;
                   1679: 
                   1680:   if (lease->clid_len != state->clid_len || 
                   1681:       memcmp(lease->clid, state->clid, state->clid_len) != 0 ||
1.1.1.2 ! misho    1682:       lease->iaid != state->iaid)
1.1       misho    1683:     return 0;
                   1684: 
                   1685:   return 1;
                   1686: }
                   1687: 
1.1.1.2 ! misho    1688: 
        !          1689: /* Calculate valid and preferred times to send in leases/renewals. 
        !          1690: 
        !          1691:    Inputs are:
        !          1692: 
        !          1693:    *valid_timep, *preferred_timep - requested times from IAADDR options.
        !          1694:    context->valid, context->preferred - times associated with subnet address on local interface.
        !          1695:    context->flags | CONTEXT_DEPRECATE - "deprecated" flag in dhcp-range.
        !          1696:    lease_time - configured time for context for individual client.
        !          1697:    *min_time - smallest valid time sent so far.
        !          1698: 
        !          1699:    Outputs are :
        !          1700:    
        !          1701:    *valid_timep, *preferred_timep - times to be send in IAADDR option.
        !          1702:    *min_time - smallest valid time sent so far, to calculate T1 and T2.
        !          1703:    
        !          1704:    */
1.1       misho    1705: static void calculate_times(struct dhcp_context *context, unsigned int *min_time, unsigned int *valid_timep, 
1.1.1.2 ! misho    1706:                            unsigned int *preferred_timep, unsigned int lease_time)
1.1       misho    1707: {
1.1.1.2 ! misho    1708:   unsigned int req_preferred = *preferred_timep, req_valid = *valid_timep;
        !          1709:   unsigned int valid_time = lease_time, preferred_time = lease_time;
        !          1710:   
        !          1711:   /* RFC 3315: "A server ignores the lifetimes set
        !          1712:      by the client if the preferred lifetime is greater than the valid
        !          1713:      lifetime. */
        !          1714:   if (req_preferred <= req_valid)
        !          1715:     {
        !          1716:       if (req_preferred != 0)
        !          1717:        {
        !          1718:          /* 0 == "no preference from client" */
        !          1719:          if (req_preferred < 120u)
        !          1720:            req_preferred = 120u; /* sanity */
        !          1721:          
        !          1722:          if (req_preferred < preferred_time)
        !          1723:            preferred_time = req_preferred;
        !          1724:        }
        !          1725:       
        !          1726:       if (req_valid != 0)
        !          1727:        /* 0 == "no preference from client" */
        !          1728:        {
        !          1729:          if (req_valid < 120u)
        !          1730:            req_valid = 120u; /* sanity */
        !          1731:          
        !          1732:          if (req_valid < valid_time)
        !          1733:            valid_time = req_valid;
        !          1734:        }
        !          1735:     }
1.1       misho    1736: 
1.1.1.2 ! misho    1737:   /* deprecate (preferred == 0) which configured, or when local address 
        !          1738:      is deprecated */
        !          1739:   if ((context->flags & CONTEXT_DEPRECATE) || context->preferred == 0)
1.1       misho    1740:     preferred_time = 0;
1.1.1.2 ! misho    1741:   
1.1       misho    1742:   if (preferred_time != 0 && preferred_time < *min_time)
                   1743:     *min_time = preferred_time;
                   1744:   
                   1745:   if (valid_time != 0 && valid_time < *min_time)
                   1746:     *min_time = valid_time;
                   1747:   
                   1748:   *valid_timep = valid_time;
                   1749:   *preferred_timep = preferred_time;
                   1750: }
                   1751: 
                   1752: static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now)
                   1753: {
                   1754:   struct dhcp_lease *lease = lease6_find_by_addr(addr, 128, 0);
1.1.1.2 ! misho    1755: #ifdef HAVE_SCRIPT
1.1       misho    1756:   struct dhcp_netid *tagif = run_tag_if(state->tags);
1.1.1.2 ! misho    1757: #endif
        !          1758: 
        !          1759:   (void)context;
1.1       misho    1760: 
                   1761:   if (!lease)
                   1762:     lease = lease6_allocate(addr, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA);
                   1763:   
                   1764:   if (lease)
                   1765:     {
                   1766:       lease_set_expires(lease, lease_time, now);
1.1.1.2 ! misho    1767:       lease_set_iaid(lease, state->iaid); 
        !          1768:       lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
1.1       misho    1769:       lease_set_interface(lease, state->interface, now);
                   1770:       if (state->hostname && state->ia_type == OPTION6_IA_NA)
                   1771:        {
                   1772:          char *addr_domain = get_domain6(addr);
                   1773:          if (!state->send_domain)
                   1774:            state->send_domain = addr_domain;
                   1775:          lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
                   1776:        }
                   1777:       
                   1778: #ifdef HAVE_SCRIPT
                   1779:       if (daemon->lease_change_command)
                   1780:        {
                   1781:          void *class_opt;
                   1782:          lease->flags |= LEASE_CHANGED;
                   1783:          free(lease->extradata);
                   1784:          lease->extradata = NULL;
                   1785:          lease->extradata_size = lease->extradata_len = 0;
                   1786:          lease->vendorclass_count = 0; 
                   1787:          
                   1788:          if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
                   1789:            {
                   1790:              void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
                   1791:              lease->vendorclass_count++;
                   1792:              /* send enterprise number first  */
                   1793:              sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
                   1794:              lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
                   1795:              
                   1796:              if (opt6_len(class_opt) >= 6) 
                   1797:                for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
                   1798:                  {
                   1799:                    lease->vendorclass_count++;
                   1800:                    lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
                   1801:                  }
                   1802:            }
                   1803:          
                   1804:          lease_add_extradata(lease, (unsigned char *)state->client_hostname, 
                   1805:                              state->client_hostname ? strlen(state->client_hostname) : 0, 0);                          
                   1806:          
                   1807:          /* space-concat tag set */
                   1808:          if (!tagif && !context->netid.net)
                   1809:            lease_add_extradata(lease, NULL, 0, 0);
                   1810:          else
                   1811:            {
                   1812:              if (context->netid.net)
                   1813:                lease_add_extradata(lease, (unsigned char *)context->netid.net, strlen(context->netid.net), tagif ? ' ' : 0);
                   1814:              
                   1815:              if (tagif)
                   1816:                {
                   1817:                  struct dhcp_netid *n;
                   1818:                  for (n = tagif; n; n = n->next)
                   1819:                    {
                   1820:                      struct dhcp_netid *n1;
                   1821:                      /* kill dupes */
                   1822:                      for (n1 = n->next; n1; n1 = n1->next)
                   1823:                        if (strcmp(n->net, n1->net) == 0)
                   1824:                          break;
                   1825:                      if (!n1)
                   1826:                        lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); 
                   1827:                    }
                   1828:                }
                   1829:            }
                   1830:          
                   1831:          if (state->link_address)
                   1832:            inet_ntop(AF_INET6, state->link_address, daemon->addrbuff, ADDRSTRLEN);
                   1833:          
                   1834:          lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, state->link_address ? strlen(daemon->addrbuff) : 0, 0);
                   1835:          
                   1836:          if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
                   1837:            {
                   1838:              void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
                   1839:              for (enc_opt = opt6_ptr(class_opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
                   1840:                lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
                   1841:            }
                   1842:        }
                   1843: #endif 
                   1844:       
                   1845:     }
                   1846: }
                   1847:                          
                   1848:                        
                   1849:        
                   1850: static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts)
                   1851: {
                   1852:   void *opt;
                   1853:   char *desc = nest ? "nest" : "sent";
                   1854:   
1.1.1.2 ! misho    1855:   if (!option_bool(OPT_LOG_OPTS) || start_opts == end_opts)
1.1       misho    1856:     return;
                   1857:   
                   1858:   for (opt = start_opts; opt; opt = opt6_next(opt, end_opts))
                   1859:     {
                   1860:       int type = opt6_type(opt);
                   1861:       void *ia_options = NULL;
                   1862:       char *optname;
                   1863:       
                   1864:       if (type == OPTION6_IA_NA)
                   1865:        {
                   1866:          sprintf(daemon->namebuff, "IAID=%u T1=%u T2=%u",
                   1867:                  opt6_uint(opt, 0, 4), opt6_uint(opt, 4, 4), opt6_uint(opt, 8, 4));
                   1868:          optname = "ia-na";
                   1869:          ia_options = opt6_ptr(opt, 12);
                   1870:        }
                   1871:       else if (type == OPTION6_IA_TA)
                   1872:        {
                   1873:          sprintf(daemon->namebuff, "IAID=%u", opt6_uint(opt, 0, 4));
                   1874:          optname = "ia-ta";
                   1875:          ia_options = opt6_ptr(opt, 4);
                   1876:        }
                   1877:       else if (type == OPTION6_IAADDR)
                   1878:        {
                   1879:          inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
                   1880:          sprintf(daemon->namebuff, "%s PL=%u VL=%u", 
                   1881:                  daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
                   1882:          optname = "iaaddr";
                   1883:          ia_options = opt6_ptr(opt, 24);
                   1884:        }
                   1885: #ifdef OPTION6_PREFIX_CLASS
                   1886:       else if (type == OPTION6_PREFIX_CLASS)
                   1887:        {
                   1888:          optname = "prefix-class";
                   1889:          sprintf(daemon->namebuff, "class=%u", opt6_uint(opt, 0, 2));
                   1890:        }
                   1891: #endif
                   1892:       else if (type == OPTION6_STATUS_CODE)
                   1893:        {
                   1894:          int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
                   1895:          memcpy(daemon->namebuff + len, opt6_ptr(opt, 2), opt6_len(opt)-2);
                   1896:          daemon->namebuff[len + opt6_len(opt) - 2] = 0;
                   1897:          optname = "status";
                   1898:        }
                   1899:       else
                   1900:        {
                   1901:          /* account for flag byte on FQDN */
                   1902:          int offset = type == OPTION6_FQDN ? 1 : 0;
                   1903:          optname = option_string(AF_INET6, type, opt6_ptr(opt, offset), opt6_len(opt) - offset, daemon->namebuff, MAXDNAME);
                   1904:        }
                   1905:       
                   1906:       my_syslog(MS_DHCP | LOG_INFO, "%u %s size:%3d option:%3d %s  %s", 
                   1907:                xid, desc, opt6_len(opt), type, optname, daemon->namebuff);
                   1908:       
                   1909:       if (ia_options)
                   1910:        log6_opts(1, xid, ia_options, opt6_ptr(opt, opt6_len(opt)));
                   1911:     }
                   1912: }               
                   1913:  
1.1.1.2 ! misho    1914: static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string)
        !          1915: {
        !          1916:   if (option_bool(OPT_LOG_OPTS) || !option_bool(OPT_QUIET_DHCP6))
        !          1917:     log6_packet(state, type, addr, string);
        !          1918: }
        !          1919: 
1.1       misho    1920: static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string)
                   1921: {
                   1922:   int clid_len = state->clid_len;
                   1923: 
                   1924:   /* avoid buffer overflow */
                   1925:   if (clid_len > 100)
                   1926:     clid_len = 100;
                   1927:   
                   1928:   print_mac(daemon->namebuff, state->clid, clid_len);
                   1929: 
                   1930:   if (addr)
                   1931:     {
                   1932:       inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
                   1933:       strcat(daemon->dhcp_buff2, " ");
                   1934:     }
                   1935:   else
                   1936:     daemon->dhcp_buff2[0] = 0;
                   1937: 
                   1938:   if(option_bool(OPT_LOG_OPTS))
                   1939:     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s %s",
                   1940:              state->xid, 
                   1941:              type,
                   1942:              state->iface_name, 
                   1943:              daemon->dhcp_buff2,
                   1944:              daemon->namebuff,
                   1945:              string ? string : "");
                   1946:   else
                   1947:     my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s %s",
                   1948:              type,
                   1949:              state->iface_name, 
                   1950:              daemon->dhcp_buff2,
                   1951:              daemon->namebuff,
                   1952:              string ? string : "");
                   1953: }
                   1954: 
                   1955: static void *opt6_find (void *opts, void *end, unsigned int search, unsigned int minsize)
                   1956: {
                   1957:   u16 opt, opt_len;
                   1958:   void *start;
                   1959:   
                   1960:   if (!opts)
                   1961:     return NULL;
                   1962:     
                   1963:   while (1)
                   1964:     {
                   1965:       if (end - opts < 4) 
                   1966:        return NULL;
                   1967:       
                   1968:       start = opts;
                   1969:       GETSHORT(opt, opts);
                   1970:       GETSHORT(opt_len, opts);
                   1971:       
                   1972:       if (opt_len > (end - opts))
                   1973:        return NULL;
                   1974:       
                   1975:       if (opt == search && (opt_len >= minsize))
                   1976:        return start;
                   1977:       
                   1978:       opts += opt_len;
                   1979:     }
                   1980: }
                   1981: 
                   1982: static void *opt6_next(void *opts, void *end)
                   1983: {
                   1984:   u16 opt_len;
                   1985:   
                   1986:   if (end - opts < 4) 
                   1987:     return NULL;
                   1988:   
                   1989:   opts += 2;
                   1990:   GETSHORT(opt_len, opts);
                   1991:   
                   1992:   if (opt_len >= (end - opts))
                   1993:     return NULL;
                   1994:   
                   1995:   return opts + opt_len;
                   1996: }
                   1997: 
                   1998: static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
                   1999: {
                   2000:   /* this worries about unaligned data and byte order */
                   2001:   unsigned int ret = 0;
                   2002:   int i;
                   2003:   unsigned char *p = opt6_ptr(opt, offset);
                   2004:   
                   2005:   for (i = 0; i < size; i++)
                   2006:     ret = (ret << 8) | *p++;
                   2007:   
                   2008:   return ret;
                   2009: } 
                   2010: 
1.1.1.2 ! misho    2011: void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id)
        !          2012: {
        !          2013:   /* ->local is same value for all relays on ->current chain */
        !          2014:   
        !          2015:   struct all_addr from;
        !          2016:   unsigned char *header;
        !          2017:   unsigned char *inbuff = daemon->dhcp_packet.iov_base;
        !          2018:   int msg_type = *inbuff;
        !          2019:   int hopcount;
        !          2020:   struct in6_addr multicast;
        !          2021:   unsigned int maclen, mactype;
        !          2022:   unsigned char mac[DHCP_CHADDR_MAX];
        !          2023: 
        !          2024:   inet_pton(AF_INET6, ALL_SERVERS, &multicast);
        !          2025:   get_client_mac(peer_address, scope_id, mac, &maclen, &mactype);
        !          2026: 
        !          2027:   /* source address == relay address */
        !          2028:   from.addr.addr6 = relay->local.addr.addr6;
        !          2029:     
        !          2030:   /* Get hop count from nested relayed message */ 
        !          2031:   if (msg_type == DHCP6RELAYFORW)
        !          2032:     hopcount = *((unsigned char *)inbuff+1) + 1;
        !          2033:   else
        !          2034:     hopcount = 0;
        !          2035: 
        !          2036:   /* RFC 3315 HOP_COUNT_LIMIT */
        !          2037:   if (hopcount > 32)
        !          2038:     return;
        !          2039: 
        !          2040:   save_counter(0);
        !          2041: 
        !          2042:   if ((header = put_opt6(NULL, 34)))
        !          2043:     {
        !          2044:       int o;
        !          2045: 
        !          2046:       header[0] = DHCP6RELAYFORW;
        !          2047:       header[1] = hopcount;
        !          2048:       memcpy(&header[2],  &relay->local.addr.addr6, IN6ADDRSZ);
        !          2049:       memcpy(&header[18], peer_address, IN6ADDRSZ);
        !          2050:  
        !          2051:       /* RFC-6939 */
        !          2052:       if (maclen != 0)
        !          2053:        {
        !          2054:          o = new_opt6(OPTION6_CLIENT_MAC);
        !          2055:          put_opt6_short(mactype);
        !          2056:          put_opt6(mac, maclen);
        !          2057:          end_opt6(o);
        !          2058:        }
        !          2059:       
        !          2060:       o = new_opt6(OPTION6_RELAY_MSG);
        !          2061:       put_opt6(inbuff, sz);
        !          2062:       end_opt6(o);
        !          2063:       
        !          2064:       for (; relay; relay = relay->current)
        !          2065:        {
        !          2066:          union mysockaddr to;
        !          2067:          
        !          2068:          to.sa.sa_family = AF_INET6;
        !          2069:          to.in6.sin6_addr = relay->server.addr.addr6;
        !          2070:          to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
        !          2071:          to.in6.sin6_flowinfo = 0;
        !          2072:          to.in6.sin6_scope_id = 0;
        !          2073: 
        !          2074:          if (IN6_ARE_ADDR_EQUAL(&relay->server.addr.addr6, &multicast))
        !          2075:            {
        !          2076:              int multicast_iface;
        !          2077:              if (!relay->interface || strchr(relay->interface, '*') ||
        !          2078:                  (multicast_iface = if_nametoindex(relay->interface)) == 0 ||
        !          2079:                  setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
        !          2080:                my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
        !          2081:            }
        !          2082:                
        !          2083:          send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
        !          2084:          
        !          2085:          if (option_bool(OPT_LOG_OPTS))
        !          2086:            {
        !          2087:              inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
        !          2088:              inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
        !          2089:              my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->namebuff);
        !          2090:            }
        !          2091: 
        !          2092:          /* Save this for replies */
        !          2093:          relay->iface_index = scope_id;
        !          2094:        }
        !          2095:     }
        !          2096: }
        !          2097: 
        !          2098: unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
        !          2099: {
        !          2100:   struct dhcp_relay *relay;
        !          2101:   struct in6_addr link;
        !          2102:   unsigned char *inbuff = daemon->dhcp_packet.iov_base;
        !          2103:   
        !          2104:   /* must have at least msg_type+hopcount+link_address+peer_address+minimal size option
        !          2105:      which is               1   +    1   +    16      +     16     + 2 + 2 = 38 */
        !          2106:   
        !          2107:   if (sz < 38 || *inbuff != DHCP6RELAYREPL)
        !          2108:     return 0;
        !          2109:   
        !          2110:   memcpy(&link, &inbuff[2], IN6ADDRSZ); 
        !          2111:   
        !          2112:   for (relay = daemon->relay6; relay; relay = relay->next)
        !          2113:     if (IN6_ARE_ADDR_EQUAL(&link, &relay->local.addr.addr6) &&
        !          2114:        (!relay->interface || wildcard_match(relay->interface, arrival_interface)))
        !          2115:       break;
        !          2116:       
        !          2117:   save_counter(0);
        !          2118: 
        !          2119:   if (relay)
        !          2120:     {
        !          2121:       void *opt, *opts = inbuff + 34;
        !          2122:       void *end = inbuff + sz;
        !          2123:       for (opt = opts; opt; opt = opt6_next(opt, end))
        !          2124:        if (opt6_type(opt) == OPTION6_RELAY_MSG && opt6_len(opt) > 0)
        !          2125:          {
        !          2126:            int encap_type = *((unsigned char *)opt6_ptr(opt, 0));
        !          2127:            put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
        !          2128:            memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ); 
        !          2129:            peer->sin6_scope_id = relay->iface_index;
        !          2130:            return encap_type == DHCP6RELAYREPL ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
        !          2131:          }
        !          2132:     }
        !          2133: 
        !          2134:   return 0;
        !          2135: }
        !          2136: 
1.1       misho    2137: #endif

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