Diff for /embedaddon/dnsmasq/src/radv.c between versions 1.1.1.3 and 1.1.1.5

version 1.1.1.3, 2016/11/02 09:57:01 version 1.1.1.5, 2023/09/27 11:02:07
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2016 Simon Kelley/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
   
    This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
Line 82  void ra_init(time_t now) Line 82  void ra_init(time_t now)
   /* ensure this is around even if we're not doing DHCPv6 */    /* ensure this is around even if we're not doing DHCPv6 */
   expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));    expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
     
  /* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */  /* See if we're guessing SLAAC addresses, if so we need to receive ping replies */
   for (context = daemon->dhcp6; context; context = context->next)    for (context = daemon->dhcp6; context; context = context->next)
     if ((context->flags & CONTEXT_RA_NAME))      if ((context->flags & CONTEXT_RA_NAME))
       break;        break;
Line 112  void ra_init(time_t now) Line 112  void ra_init(time_t now)
    daemon->icmp6fd = fd;     daemon->icmp6fd = fd;
         
    if (daemon->doing_ra)     if (daemon->doing_ra)
     ra_start_unsolicted(now, NULL);     ra_start_unsolicited(now, NULL);
 }  }
   
void ra_start_unsolicted(time_t now, struct dhcp_context *context)void ra_start_unsolicited(time_t now, struct dhcp_context *context)
 {     {   
    /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed     /* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
      if it's not appropriate to advertise those contexts.       if it's not appropriate to advertise those contexts.
Line 123  void ra_start_unsolicted(time_t now, struct dhcp_conte Line 123  void ra_start_unsolicted(time_t now, struct dhcp_conte
      and pick up new interfaces */       and pick up new interfaces */
       
   if (context)    if (context)
    context->ra_short_period_start = context->ra_time = now;    {
       context->ra_short_period_start = now;
       /* start after 1 second to get logging right at startup. */
       context->ra_time = now + 1;
     }
   else    else
     for (context = daemon->dhcp6; context; context = context->next)      for (context = daemon->dhcp6; context; context = context->next)
       if (!(context->flags & CONTEXT_TEMPLATE))        if (!(context->flags & CONTEXT_TEMPLATE))
Line 162  void icmp6_packet(time_t now) Line 166  void icmp6_packet(time_t now)
     return;      return;
         
   packet = (unsigned char *)daemon->outpacket.iov_base;    packet = (unsigned char *)daemon->outpacket.iov_base;
  
   for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
     if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)      if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
       {        {
Line 187  void icmp6_packet(time_t now) Line 191  void icmp6_packet(time_t now)
     
   if (packet[1] != 0)    if (packet[1] != 0)
     return;      return;
  
   if (packet[0] == ICMP6_ECHO_REPLY)    if (packet[0] == ICMP6_ECHO_REPLY)
     lease_ping_reply(&from.sin6_addr, packet, interface);       lease_ping_reply(&from.sin6_addr, packet, interface); 
   else if (packet[0] == ND_ROUTER_SOLICIT)    else if (packet[0] == ND_ROUTER_SOLICIT)
     {      {
       char *mac = "";        char *mac = "";
       struct dhcp_bridge *bridge, *alias;        struct dhcp_bridge *bridge, *alias;
         ssize_t rem;
         unsigned char *p;
         int opt_sz;
               
   #ifdef HAVE_DUMPFILE
         dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
   #endif           
         
       /* look for link-layer address option for logging */        /* look for link-layer address option for logging */
      if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)      for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz)
         {          {
          print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);          opt_sz = p[1] * 8;
          mac = daemon->namebuff;          
           if (opt_sz == 0 || opt_sz > rem)
             return; /* Bad packet */
           
           if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME))
             {
               print_mac(daemon->namebuff, &p[2], opt_sz - 2);
               mac = daemon->namebuff;
             }
         }          }
               
       if (!option_bool(OPT_QUIET_RA))        if (!option_bool(OPT_QUIET_RA))
         my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);          my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
   
Line 243  static void send_ra_alias(time_t now, int iface, char  Line 262  static void send_ra_alias(time_t now, int iface, char 
   struct dhcp_netid iface_id;    struct dhcp_netid iface_id;
   struct dhcp_opt *opt_cfg;    struct dhcp_opt *opt_cfg;
   struct ra_interface *ra_param = find_iface_param(iface_name);    struct ra_interface *ra_param = find_iface_param(iface_name);
  int done_dns = 0, old_prefix = 0;  int done_dns = 0, old_prefix = 0, mtu = 0;
   unsigned int min_pref_time;    unsigned int min_pref_time;
 #ifdef HAVE_LINUX_NETWORK  #ifdef HAVE_LINUX_NETWORK
   FILE *f;    FILE *f;
Line 261  static void send_ra_alias(time_t now, int iface, char  Line 280  static void send_ra_alias(time_t now, int iface, char 
   parm.adv_interval = calc_interval(ra_param);    parm.adv_interval = calc_interval(ra_param);
   parm.prio = calc_prio(ra_param);    parm.prio = calc_prio(ra_param);
       
  save_counter(0);  reset_counter();
  ra = expand(sizeof(struct ra_packet)); 
       
     if (!(ra = expand(sizeof(struct ra_packet))))
       return;
     
   ra->type = ND_ROUTER_ADVERT;    ra->type = ND_ROUTER_ADVERT;
   ra->code = 0;    ra->code = 0;
   ra->hop_limit = hop_limit;    ra->hop_limit = hop_limit;
Line 283  static void send_ra_alias(time_t now, int iface, char  Line 304  static void send_ra_alias(time_t now, int iface, char 
       context->netid.next = &context->netid;        context->netid.next = &context->netid;
     }      }
   
  if (!iface_enumerate(AF_INET6, &parm, add_prefixes))  /* If no link-local address then we can't advertise since source address of
      advertisement must be link local address: RFC 4861 para 6.1.2. */
   if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
       parm.link_pref_time == 0)
     return;      return;
   
   /* Find smallest preferred time within address classes,    /* Find smallest preferred time within address classes,
Line 397  static void send_ra_alias(time_t now, int iface, char  Line 421  static void send_ra_alias(time_t now, int iface, char 
       put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));        put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
     }      }
   
     /* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */
     /* an MTU of -1 prevents the option from being sent. */
     if (ra_param)
       mtu = ra_param->mtu;
 #ifdef HAVE_LINUX_NETWORK  #ifdef HAVE_LINUX_NETWORK
  /* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU  /* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
      available from SIOCGIFMTU */       available from SIOCGIFMTU */
  sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name);  if (mtu == 0)
  if ((f = fopen(daemon->namebuff, "r"))) 
     {      {
      if (fgets(daemon->namebuff, MAXDNAME, f))      char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
        {      sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? mtu_name : iface_name);
          put_opt6_char(ICMP6_OPT_MTU);      if ((f = fopen(daemon->namebuff, "r")))
          put_opt6_char(1);        {
          put_opt6_short(0);          if (fgets(daemon->namebuff, MAXDNAME, f))
          put_opt6_long(atoi(daemon->namebuff));            mtu = atoi(daemon->namebuff);
        }          fclose(f);
      fclose(f);        }
     }      }
 #endif  #endif
     if (mtu > 0)
       {
         put_opt6_char(ICMP6_OPT_MTU);
         put_opt6_char(1);
         put_opt6_short(0);
         put_opt6_long(mtu);
       }
             
   iface_enumerate(AF_LOCAL, &send_iface, add_lla);    iface_enumerate(AF_LOCAL, &send_iface, add_lla);
     
Line 525  static void send_ra_alias(time_t now, int iface, char  Line 559  static void send_ra_alias(time_t now, int iface, char 
       setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));        setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
     }      }
       
   #ifdef HAVE_DUMPFILE
     {
       struct sockaddr_in6 src;
       src.sin6_family = AF_INET6;
       src.sin6_addr = parm.link_local;
       
       dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
     }
   #endif
   
   while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,     while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, 
                           save_counter(0), 0, (struct sockaddr *)&addr,                            save_counter(-1), 0, (struct sockaddr *)&addr, 
                            sizeof(addr))));                             sizeof(addr))));
       
 }  }
Line 608  static int add_prefixes(struct in6_addr *local,  int p Line 652  static int add_prefixes(struct in6_addr *local,  int p
                     real_prefix = context->prefix;                      real_prefix = context->prefix;
                   }                    }
   
                /* find floor time, don't reduce below 3 * RA interval. */                /* find floor time, don't reduce below 3 * RA interval.
                if (time > context->lease_time)                   If the lease time has been left as default, don't
                    use that as a floor. */
                 if ((context->flags & CONTEXT_SETLEASE) &&
                     time > context->lease_time)
                   {                    {
                     time = context->lease_time;                      time = context->lease_time;
                     if (time < ((unsigned int)(3 * param->adv_interval)))                      if (time < ((unsigned int)(3 * param->adv_interval)))
Line 725  static int add_lla(int index, unsigned int type, char  Line 772  static int add_lla(int index, unsigned int type, char 
          add 7 to round up */           add 7 to round up */
       int len = (maclen + 9) >> 3;        int len = (maclen + 9) >> 3;
       unsigned char *p = expand(len << 3);        unsigned char *p = expand(len << 3);
         if (!p)
           return 1;
       memset(p, 0, len << 3);        memset(p, 0, len << 3);
       *p++ = ICMP6_OPT_SOURCE_MAC;        *p++ = ICMP6_OPT_SOURCE_MAC;
       *p++ = len;        *p++ = len;
Line 778  time_t periodic_ra(time_t now) Line 827  time_t periodic_ra(time_t now)
            associated with it, because it's for a subnet we dont              associated with it, because it's for a subnet we dont 
            have an interface on. Probably we're doing DHCP on             have an interface on. Probably we're doing DHCP on
            a remote subnet via a relay. Zero the timer, since we won't             a remote subnet via a relay. Zero the timer, since we won't
           ever be able to send ra's and satistfy it. */           ever be able to send ra's and satisfy it. */
         context->ra_time = 0;          context->ra_time = 0;
               
       if (param.iface != 0 &&        if (param.iface != 0 &&
Line 873  static int iface_search(struct in6_addr *local,  int p Line 922  static int iface_search(struct in6_addr *local,  int p
 {  {
   struct search_param *param = vparam;    struct search_param *param = vparam;
   struct dhcp_context *context;    struct dhcp_context *context;
  struct iname *tmp;
   
   (void)scope;    (void)scope;
   (void)preferred;    (void)preferred;
   (void)valid;    (void)valid;
 
   /* ignore interfaces we're not doing DHCP on. */
   if (!indextoname(daemon->icmp6fd, if_index, param->name) ||
       !iface_check(AF_LOCAL, NULL, param->name, NULL))
     return 1;
 
   for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
     if (tmp->name && wildcard_match(tmp->name, param->name))
       return 1;
 
   for (context = daemon->dhcp6; context; context = context->next)    for (context = daemon->dhcp6; context; context = context->next)
     if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&      if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
         prefix <= context->prefix &&          prefix <= context->prefix &&
Line 889  static int iface_search(struct in6_addr *local,  int p Line 948  static int iface_search(struct in6_addr *local,  int p
         /* found an interface that's overdue for RA determine new           /* found an interface that's overdue for RA determine new 
            timeout value and arrange for RA to be sent unless interface is             timeout value and arrange for RA to be sent unless interface is
            still doing DAD.*/             still doing DAD.*/
           
         if (!(flags & IFACE_TENTATIVE))          if (!(flags & IFACE_TENTATIVE))
           param->iface = if_index;            param->iface = if_index;
           
         /* should never fail */  
         if (!indextoname(daemon->icmp6fd, if_index, param->name))  
           {  
             param->iface = 0;  
             return 0;  
           }  
                   
         new_timeout(context, param->name, param->now);          new_timeout(context, param->name, param->now);
                   

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.5


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