File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / rfc3315.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 09:57:01 2016 UTC (7 years, 8 months ago) by misho
Branches: elwix, dnsmasq, MAIN
CVS tags: v2_76p1, HEAD
dnsmasq 2.76

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

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