Diff for /embedaddon/dnsmasq/src/dhcp.c between versions 1.1.1.2 and 1.1.1.3

version 1.1.1.2, 2014/06/15 16:31:38 version 1.1.1.3, 2016/11/02 09:57:01
Line 1 Line 1
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley/* dnsmasq is Copyright (c) 2000-2016 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 146  void dhcp_packet(time_t now, int pxe_fd) Line 146  void dhcp_packet(time_t now, int pxe_fd)
   struct iovec iov;    struct iovec iov;
   ssize_t sz;     ssize_t sz; 
   int iface_index = 0, unicast_dest = 0, is_inform = 0;    int iface_index = 0, unicast_dest = 0, is_inform = 0;
     int rcvd_iface_index;
   struct in_addr iface_addr;    struct in_addr iface_addr;
   struct iface_param parm;    struct iface_param parm;
 #ifdef HAVE_LINUX_NETWORK  #ifdef HAVE_LINUX_NETWORK
Line 225  void dhcp_packet(time_t now, int pxe_fd) Line 226  void dhcp_packet(time_t now, int pxe_fd)
   strncpy(arp_req.arp_dev, ifr.ifr_name, 16);    strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
 #endif   #endif 
   
   /* One form of bridging on BSD has the property that packets  /* If the interface on which the DHCP request was received is an
      can be recieved on bridge interfaces which do not have an IP address.     alias of some other interface (as specified by the
      We allow these to be treated as aliases of another interface which does have     --bridge-interface option), change ifr.ifr_name so that we look
      an IP address with --dhcp-bridge=interface,alias,alias */     for DHCP contexts associated with the aliased interface instead
      of with the aliasing one. */
   rcvd_iface_index = iface_index;
   for (bridge = daemon->bridges; bridge; bridge = bridge->next)    for (bridge = daemon->bridges; bridge; bridge = bridge->next)
     {      {
       for (alias = bridge->alias; alias; alias = alias->next)        for (alias = bridge->alias; alias; alias = alias->next)
        if (strncmp(ifr.ifr_name, alias->iface, IF_NAMESIZE) == 0)        if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
           {            {
             if (!(iface_index = if_nametoindex(bridge->iface)))              if (!(iface_index = if_nametoindex(bridge->iface)))
               {                {
                my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);                my_syslog(MS_DHCP | LOG_WARNING,
                           _("unknown interface %s in bridge-interface"),
                           bridge->iface);
                 return;                  return;
               }                }
             else               else 
Line 376  void dhcp_packet(time_t now, int pxe_fd) Line 381  void dhcp_packet(time_t now, int pxe_fd)
         }          }
     }       } 
 #if defined(HAVE_LINUX_NETWORK)  #if defined(HAVE_LINUX_NETWORK)
  else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||  else
           mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) 
     {      {
      /* broadcast to 255.255.255.255 (or mac address invalid) */      /* fill cmsg for outbound interface (both broadcast & unicast) */
       struct in_pktinfo *pkt;        struct in_pktinfo *pkt;
       msg.msg_control = control_u.control;        msg.msg_control = control_u.control;
       msg.msg_controllen = sizeof(control_u);        msg.msg_controllen = sizeof(control_u);
       cmptr = CMSG_FIRSTHDR(&msg);        cmptr = CMSG_FIRSTHDR(&msg);
       pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);        pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
      pkt->ipi_ifindex = iface_index;      pkt->ipi_ifindex = rcvd_iface_index;
       pkt->ipi_spec_dst.s_addr = 0;        pkt->ipi_spec_dst.s_addr = 0;
       msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));        msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
       cmptr->cmsg_level = IPPROTO_IP;        cmptr->cmsg_level = IPPROTO_IP;
      cmptr->cmsg_type = IP_PKTINFO;        cmptr->cmsg_type = IP_PKTINFO;
      dest.sin_addr.s_addr = INADDR_BROADCAST;
      dest.sin_port = htons(daemon->dhcp_client_port);      if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
          mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
         {
           /* broadcast to 255.255.255.255 (or mac address invalid) */
           dest.sin_addr.s_addr = INADDR_BROADCAST;
           dest.sin_port = htons(daemon->dhcp_client_port);
         }
       else
         {
           /* unicast to unconfigured client. Inject mac address direct into ARP cache.
           struct sockaddr limits size to 14 bytes. */
           dest.sin_addr = mess->yiaddr;
           dest.sin_port = htons(daemon->dhcp_client_port);
           memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
           arp_req.arp_ha.sa_family = mess->htype;
           memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
           /* interface name already copied in */
           arp_req.arp_flags = ATF_COM;
           if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
             my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
         }
     }      }
   else  
     {  
       /* unicast to unconfigured client. Inject mac address direct into ARP cache.   
          struct sockaddr limits size to 14 bytes. */  
       dest.sin_addr = mess->yiaddr;  
       dest.sin_port = htons(daemon->dhcp_client_port);  
       memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));  
       arp_req.arp_ha.sa_family = mess->htype;  
       memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);  
       /* interface name already copied in */  
       arp_req.arp_flags = ATF_COM;  
       ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);  
     }  
 #elif defined(HAVE_SOLARIS_NETWORK)  #elif defined(HAVE_SOLARIS_NETWORK)
   else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)    else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
     {      {
Line 442  void dhcp_packet(time_t now, int pxe_fd) Line 453  void dhcp_packet(time_t now, int pxe_fd)
   setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));    setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
 #endif  #endif
       
  while(sendmsg(fd, &msg, 0) == -1 && retry_send());  while(retry_send(sendmsg(fd, &msg, 0)));
 
   /* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
   if (errno != 0)
     my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
               inet_ntoa(dest.sin_addr), strerror(errno));
 }  }
 
 /* check against secondary interface addresses */  /* check against secondary interface addresses */
 static int check_listen_addrs(struct in_addr local, int if_index, char *label,  static int check_listen_addrs(struct in_addr local, int if_index, char *label,
                               struct in_addr netmask, struct in_addr broadcast, void *vparam)                                struct in_addr netmask, struct in_addr broadcast, void *vparam)
Line 637  int address_allocate(struct dhcp_context *context, Line 653  int address_allocate(struct dhcp_context *context,
   /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good    /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
      dispersal even with similarly-valued "strings". */        dispersal even with similarly-valued "strings". */ 
   for (j = 0, i = 0; i < hw_len; i++)    for (j = 0, i = 0; i < hw_len; i++)
    j += hwaddr[i] + (j << 6) + (j << 16) - j;    j = hwaddr[i] + (j << 6) + (j << 16) - j;
       
   for (pass = 0; pass <= 1; pass++)    for (pass = 0; pass <= 1; pass++)
     for (c = context; c; c = c->current)      for (c = context; c; c = c->current)

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


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