From: David Hankins Date: Fri, 8 Aug 2008 22:37:46 +0000 (+0000) Subject: Backing out [ISC-Bugs #17610] X-Git-Tag: v4_1_0a2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0524508a91826897c158c605db476351bdc253e4;p=thirdparty%2Fdhcp.git Backing out [ISC-Bugs #17610] --- diff --git a/RELNOTES b/RELNOTES index bc977bcf0..049287828 100644 --- a/RELNOTES +++ b/RELNOTES @@ -48,7 +48,7 @@ work on other platforms. Please report any problems and suggested fixes to . - Changes since 4.1.0a1 + Changes since 4.1.0a2 - Corrected list of failover state values in dhcpd man page. @@ -60,6 +60,8 @@ work on other platforms. Please report any problems and suggested fixes to - The server wasn't always sending the FQDN option when it should. + Changes since 4.1.0a1 + - Fixed a coredump when adding a class via OMAPI. - Check whether files are zero length before trying to parse them. @@ -109,9 +111,6 @@ work on other platforms. Please report any problems and suggested fixes to - Fix handling of -A and -a flags in dhcrelay; it was failing to expand packet size as needed to add relay agent options. -- The BSD socket code will now permit multiple DHCPv6 server instances to - operate on different interfaces. - Changes since 4.0.0 (new features) - Added DHCPv6 rapid commit support. diff --git a/common/discover.c b/common/discover.c index 20aaf6612..7022b091a 100644 --- a/common/discover.c +++ b/common/discover.c @@ -1265,10 +1265,6 @@ discover_interfaces(int state) { if (status != ISC_R_SUCCESS) log_fatal ("Can't register I/O handle for %s: %s", tmp -> name, isc_result_totext (status)); -#if defined(DHCPv6) - /* Only register the first interface with OMAPI for select. */ - break; -#endif } if (state == DISCOVER_SERVER && wifcount == 0) { @@ -1399,7 +1395,6 @@ got_one_v6(omapi_object_t *h) { char buf[65536]; /* maximum size for a UDP packet is 65536 */ struct interface_info *ip; int is_unicast; - unsigned int if_idx = 0; if (h->type != dhcp_type_interface) { return ISC_R_INVALIDARG; @@ -1407,16 +1402,12 @@ got_one_v6(omapi_object_t *h) { ip = (struct interface_info *)h; result = receive_packet6(ip, (unsigned char *)buf, sizeof(buf), - &from, &to, &if_idx); + &from, &to); if (result < 0) { log_error("receive_packet6() failed on %s: %m", ip->name); return ISC_R_UNEXPECTED; } - /* 0 is 'any' interface. */ - if (if_idx == 0) - return ISC_R_NOTFOUND; - if (dhcpv6_packet_handler != NULL) { /* * If a packet is not multicast, we assume it is unicast. @@ -1430,13 +1421,6 @@ got_one_v6(omapi_object_t *h) { ifrom.len = 16; memcpy(ifrom.iabuf, &from.sin6_addr, ifrom.len); - /* Seek forward to find the matching source interface. */ - while ((ip != NULL) && (if_nametoindex(ip->name) != if_idx)) - ip = ip->next; - - if (ip == NULL) - return ISC_R_NOTFOUND; - (*dhcpv6_packet_handler)(ip, buf, result, from.sin6_port, &ifrom, is_unicast); diff --git a/common/socket.c b/common/socket.c index e5eb98229..c748875ff 100644 --- a/common/socket.c +++ b/common/socket.c @@ -54,17 +54,6 @@ # endif #endif -#if defined(DHCPv6) -/* - * XXX: this is gross. we need to go back and overhaul the API for socket - * handling and make an additional layer for v6 sockets. - */ -static unsigned int global_v6_socket_references = 0; -static int global_v6_socket = -1; - -static void if_register_multicast(struct interface_info *info); -#endif - /* * If we can't bind() to a specific interface, then we can only have * a single socket. This variable insures that we don't try to listen @@ -142,7 +131,7 @@ get_ifaddr6(struct interface_info *info, struct in6_addr *ifaddr6) { /* Generic interface registration routine... */ int -if_register_socket(struct interface_info *info, int family) { +if_register_socket(struct interface_info *info, int family, int do_multicast) { struct sockaddr_storage name; int name_len; int sock; @@ -170,7 +159,6 @@ if_register_socket(struct interface_info *info, int family) { struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&name; addr->sin6_family = AF_INET6; addr->sin6_port = local_port; - /* XXX: what will happen to multicasts if this is nonzero? */ memcpy(&addr->sin6_addr, &local_address6, sizeof(addr->sin6_addr)); @@ -229,24 +217,6 @@ if_register_socket(struct interface_info *info, int family) { log_fatal("Can't set SO_BROADCAST option on dhcp socket: %m"); } -#if defined(DHCPv6) && defined(SO_REUSEPORT) - /* - * We only set SO_REUSEPORT on AF_INET6 sockets, so that multiple - * daemons can bind to their own sockets and get data for their - * respective interfaces. This does not (and should not) affect - * DHCPv4 sockets; we can't yet support BSD sockets well, much - * less multiple sockets. - */ - if (local_family == AF_INET6) { - flag = 1; - if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, - (char *)&flag, sizeof(flag)) < 0) { - log_fatal("Can't set SO_REUSEPORT option on dhcp " - "socket: %m"); - } - } -#endif - /* Bind the socket to this interface's IP address. */ if (bind(sock, (struct sockaddr *)&name, name_len) < 0) { log_error("Can't bind to dhcp address: %m"); @@ -259,7 +229,7 @@ if_register_socket(struct interface_info *info, int family) { #if defined(SO_BINDTODEVICE) /* Bind this socket to this interface. */ - if ((local_family != AF_INET6) && (info->ifp != NULL) && + if (info->ifp && setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) { log_fatal("setsockopt: SO_BINDTODEVICE: %m"); @@ -302,6 +272,36 @@ if_register_socket(struct interface_info *info, int family) { } #endif } + + if ((family == AF_INET6) && do_multicast) { + struct ipv6_mreq mreq; + + /* + * Join the DHCPv6 multicast groups so we will receive + * multicast messages. + */ + if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers, + &mreq.ipv6mr_multiaddr) <= 0) { + log_fatal("inet_pton: unable to convert '%s'", + All_DHCP_Relay_Agents_and_Servers); + } + mreq.ipv6mr_interface = if_nametoindex(info->name); + if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq, sizeof(mreq)) < 0) { + log_fatal("setsockopt: IPV6_JOIN_GROUP: %m"); + } + if (inet_pton(AF_INET6, All_DHCP_Servers, + &mreq.ipv6mr_multiaddr) <= 0) { + log_fatal("inet_pton: unable to convert '%s'", + All_DHCP_Servers); + } + mreq.ipv6mr_interface = if_nametoindex(info->name); + if (((info->flags & INTERFACE_DOWNSTREAM) == 0) && + (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mreq, sizeof(mreq)) < 0)) { + log_fatal("setsockopt: IPV6_JOIN_GROUP: %m"); + } + } if ((family == AF_INET6) && ((info->flags & INTERFACE_UPSTREAM) != 0)) { @@ -313,8 +313,7 @@ if_register_socket(struct interface_info *info, int family) { } #endif /* DHCPv6 */ - /* If this is a normal IPv4 address, get the hardware address. */ - if ((local_family == AF_INET) && (strcmp(info->name, "fallback") != 0)) + if (strcmp(info->name, "fallback") != 0) get_hw_addr(info->name, &info->hw_address); return sock; @@ -326,7 +325,7 @@ void if_register_send (info) struct interface_info *info; { #ifndef USE_SOCKET_RECEIVE - info -> wfdesc = if_register_socket (info, AF_INET); + info -> wfdesc = if_register_socket (info, AF_INET, 0); #if defined (USE_SOCKET_FALLBACK) /* Fallback only registers for send, but may need to receive as well. */ @@ -394,70 +393,15 @@ void if_deregister_receive (info) #ifdef DHCPv6 -/* - * This function joines the interface to DHCPv6 multicast groups so we will - * receive multicast messages. - */ -static void -if_register_multicast(struct interface_info *info) { - int sock = info->rfdesc; - struct ipv6_mreq mreq; - - if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers, - &mreq.ipv6mr_multiaddr) <= 0) { - log_fatal("inet_pton: unable to convert '%s'", - All_DHCP_Relay_Agents_and_Servers); - } - mreq.ipv6mr_interface = if_nametoindex(info->name); - if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - &mreq, sizeof(mreq)) < 0) { - log_fatal("setsockopt: IPV6_JOIN_GROUP: %m"); - } - if (inet_pton(AF_INET6, All_DHCP_Servers, - &mreq.ipv6mr_multiaddr) <= 0) { - log_fatal("inet_pton: unable to convert '%s'", - All_DHCP_Servers); - } - mreq.ipv6mr_interface = if_nametoindex(info->name); - if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, - &mreq, sizeof(mreq)) < 0) { - log_fatal("setsockopt: IPV6_JOIN_GROUP: %m"); - } -} - void if_register6(struct interface_info *info, int do_multicast) { - if (global_v6_socket_references == 0) { - global_v6_socket = if_register_socket(info, AF_INET6); - if (global_v6_socket < 0) { - /* - * if_register_socket() fatally logs if it fails - * to create a socket, so this is just a sanity - * check. - */ - log_fatal("Impossible condition at %s:%d", MDL); - } else { - log_info("Bound to *:%d", ntohs(local_port)); - } - } - - /* Reference the global v6 socket. */ - info->rfdesc = global_v6_socket; - info->wfdesc = global_v6_socket; - global_v6_socket_references++; - - if (do_multicast) - if_register_multicast(info); - - get_hw_addr(info->name, &info->hw_address); - + info->rfdesc = if_register_socket(info, AF_INET6, do_multicast); + info->wfdesc = info->rfdesc; if (!quiet_interface_discovery) { if (info->shared_network != NULL) { - log_info("Listening on Socket/%d/%s/%s", - global_v6_socket, info->name, + log_info("Listening on Socket/%s/%s", info->name, info->shared_network->name); - log_info("Sending on Socket/%d/%s/%s", - global_v6_socket, info->name, + log_info("Sending on Socket/%s/%s", info->name, info->shared_network->name); } else { log_info("Listening on Socket/%s", info->name); @@ -468,16 +412,14 @@ if_register6(struct interface_info *info, int do_multicast) { void if_deregister6(struct interface_info *info) { - /* Dereference the global v6 socket. */ - if ((info->rfdesc == global_v6_socket) && - (info->wfdesc == global_v6_socket) && - (global_v6_socket_references > 0)) { - global_v6_socket_references--; - info->rfdesc = -1; - info->wfdesc = -1; - } else { - log_fatal("Impossible condition at %s:%d", MDL); - } + /* + * XXX: it would be nice to check for >= 0, but we need to change + * interface_allocate() to set the file descriptors for that. + */ + close(info->rfdesc); + info->rfdesc = -1; + close(info->wfdesc); + info->wfdesc = -1; if (!quiet_interface_discovery) { if (info->shared_network != NULL) { @@ -490,13 +432,6 @@ if_deregister6(struct interface_info *info) { log_info("Disabling output on Socket/%s", info->name); } } - - if (global_v6_socket_references == 0) { - close(global_v6_socket); - global_v6_socket = -1; - - log_info("Unbound from *:%d", ntohs(local_port)); - } } #endif /* DHCPv6 */ @@ -705,14 +640,13 @@ ssize_t receive_packet (interface, buf, len, from, hfrom) ssize_t receive_packet6(struct interface_info *interface, unsigned char *buf, size_t len, - struct sockaddr_in6 *from, struct in6_addr *to_addr, - unsigned int *if_idx) { + struct sockaddr_in6 *from, struct in6_addr *to_addr) { struct msghdr m; struct iovec v; int result; struct cmsghdr *cmsg; struct in6_pktinfo *pktinfo; - int found_pktinfo; + int found_to_addr; union { struct cmsghdr cmsg_sizer; u_int8_t pktinfo_sizer[CMSG_SPACE(sizeof(struct in6_pktinfo))]; @@ -761,19 +695,18 @@ receive_packet6(struct interface_info *interface, * We also keep a flag to see if we found it. If we * didn't, then we consider this to be an error. */ - found_pktinfo = 0; + found_to_addr = 0; cmsg = CMSG_FIRSTHDR(&m); while (cmsg != NULL) { if ((cmsg->cmsg_level == IPPROTO_IPV6) && (cmsg->cmsg_type == IPV6_PKTINFO)) { pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg); *to_addr = pktinfo->ipi6_addr; - *if_idx = pktinfo->ipi6_ifindex; - found_pktinfo = 1; + found_to_addr = 1; } cmsg = CMSG_NXTHDR(&m, cmsg); } - if (!found_pktinfo) { + if (!found_to_addr) { result = -1; errno = EIO; } diff --git a/includes/dhcpd.h b/includes/dhcpd.h index ac5c8dd30..98ee91ef5 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -1124,7 +1124,7 @@ struct interface_info { unsigned remote_id_len; /* Length of Remote ID. */ char name [IFNAMSIZ]; /* Its name... */ - int index; /* Its index in the registry. */ + int index; /* Its index. */ int rfdesc; /* Its read file descriptor. */ int wfdesc; /* Its write file descriptor, if different. */ @@ -2135,7 +2135,7 @@ void get_hw_addr(const char *name, struct hardware *hw); /* socket.c */ #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ || defined (USE_SOCKET_FALLBACK) -int if_register_socket(struct interface_info *, int); +int if_register_socket(struct interface_info *, int, int); #endif #if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND) @@ -2184,8 +2184,7 @@ void maybe_setup_fallback PROTO ((void)); void if_register6(struct interface_info *info, int do_multicast); ssize_t receive_packet6(struct interface_info *interface, unsigned char *buf, size_t len, - struct sockaddr_in6 *from, struct in6_addr *to_addr, - unsigned int *if_index); + struct sockaddr_in6 *from, struct in6_addr *to_addr); void if_deregister6(struct interface_info *info);