parent
9e0789bf20
commit
ab0ccbcb6b
@ -1,12 +0,0 @@
|
|||||||
diff -up dhcp-4.2.5/common/socket.c.bindtodevice_inet6 dhcp-4.2.5/common/socket.c
|
|
||||||
--- dhcp-4.2.5/common/socket.c.bindtodevice_inet6 2013-09-17 16:47:05.000000000 +0200
|
|
||||||
+++ dhcp-4.2.5/common/socket.c 2013-09-17 16:48:18.975997842 +0200
|
|
||||||
@@ -245,7 +245,7 @@ if_register_socket(struct interface_info
|
|
||||||
|
|
||||||
#if defined(SO_BINDTODEVICE)
|
|
||||||
/* Bind this socket to this interface. */
|
|
||||||
- if ((local_family != AF_INET6) && (info->ifp != NULL) &&
|
|
||||||
+ if (((do_multicast == 0)||(*do_multicast == 0)) && (info->ifp != NULL) &&
|
|
||||||
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
|
|
||||||
(char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) {
|
|
||||||
log_fatal("setsockopt: SO_BINDTODEVICE: %m");
|
|
329
dhcp-dhclient6-bind.patch
Normal file
329
dhcp-dhclient6-bind.patch
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
From 198a1fcc9f6f8c39ddf8c6e962b7e4925d43072c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jiri Popelka <jpopelka@redhat.com>
|
||||||
|
Date: Thu, 24 Oct 2013 10:03:52 +0200
|
||||||
|
Subject: [PATCH] Fix the socket handling for DHCPv6 clients to allow multiple
|
||||||
|
instances
|
||||||
|
|
||||||
|
of a client on a single machine to work properly. Previously only
|
||||||
|
one client would receive the packets. Thanks to Jiri Popelka at Red
|
||||||
|
Hat for the bug report and a potential patch.
|
||||||
|
[ISC-Bugs #34784]
|
||||||
|
---
|
||||||
|
common/discover.c | 19 ++++-----
|
||||||
|
common/socket.c | 116 ++++++++++++++++++++++++++++++++++++++++++++----------
|
||||||
|
includes/dhcpd.h | 6 +--
|
||||||
|
3 files changed, 107 insertions(+), 34 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/common/discover.c b/common/discover.c
|
||||||
|
index a305d92..4027d1a 100644
|
||||||
|
--- a/common/discover.c
|
||||||
|
+++ b/common/discover.c
|
||||||
|
@@ -57,10 +57,6 @@ struct in_addr limited_broadcast;
|
||||||
|
int local_family = AF_INET;
|
||||||
|
struct in_addr local_address;
|
||||||
|
|
||||||
|
-#ifdef DHCPv6
|
||||||
|
-struct in6_addr local_address6;
|
||||||
|
-#endif /* DHCPv6 */
|
||||||
|
-
|
||||||
|
void (*bootp_packet_handler) (struct interface_info *,
|
||||||
|
struct dhcp_packet *, unsigned,
|
||||||
|
unsigned int,
|
||||||
|
@@ -877,7 +873,7 @@ discover_interfaces(int state) {
|
||||||
|
(state == DISCOVER_RELAY)) {
|
||||||
|
if_register6(tmp, 1);
|
||||||
|
} else {
|
||||||
|
- if_register6(tmp, 0);
|
||||||
|
+ if_register_linklocal6(tmp);
|
||||||
|
}
|
||||||
|
#endif /* DHCPv6 */
|
||||||
|
}
|
||||||
|
@@ -933,13 +929,14 @@ discover_interfaces(int state) {
|
||||||
|
tmp -> name, isc_result_totext (status));
|
||||||
|
|
||||||
|
#if defined(DHCPv6)
|
||||||
|
- /* Only register the first interface for V6, since they all
|
||||||
|
- * use the same socket. XXX: This has some messy side
|
||||||
|
- * effects if we start dynamically adding and removing
|
||||||
|
- * interfaces, but we're well beyond that point in terms of
|
||||||
|
- * mess.
|
||||||
|
+ /* Only register the first interface for V6, since
|
||||||
|
+ * servers and relays all use the same socket.
|
||||||
|
+ * XXX: This has some messy side effects if we start
|
||||||
|
+ * dynamically adding and removing interfaces, but
|
||||||
|
+ * we're well beyond that point in terms of mess.
|
||||||
|
*/
|
||||||
|
- if (local_family == AF_INET6)
|
||||||
|
+ if (((state == DISCOVER_SERVER) || (state == DISCOVER_RELAY)) &&
|
||||||
|
+ (local_family == AF_INET6))
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
} /* for (tmp = interfaces; ... */
|
||||||
|
diff --git a/common/socket.c b/common/socket.c
|
||||||
|
index 8fead01..f0c2c94 100644
|
||||||
|
--- a/common/socket.c
|
||||||
|
+++ b/common/socket.c
|
||||||
|
@@ -67,6 +67,7 @@
|
||||||
|
* XXX: this is gross. we need to go back and overhaul the API for socket
|
||||||
|
* handling.
|
||||||
|
*/
|
||||||
|
+static int no_global_v6_socket = 0;
|
||||||
|
static unsigned int global_v6_socket_references = 0;
|
||||||
|
static int global_v6_socket = -1;
|
||||||
|
|
||||||
|
@@ -127,7 +128,7 @@ void if_reinitialize_receive (info)
|
||||||
|
/* Generic interface registration routine... */
|
||||||
|
int
|
||||||
|
if_register_socket(struct interface_info *info, int family,
|
||||||
|
- int *do_multicast)
|
||||||
|
+ int *do_multicast, struct in6_addr *linklocal6)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage name;
|
||||||
|
int name_len;
|
||||||
|
@@ -161,10 +162,12 @@ if_register_socket(struct interface_info *info, int family,
|
||||||
|
addr6 = (struct sockaddr_in6 *)&name;
|
||||||
|
addr6->sin6_family = AF_INET6;
|
||||||
|
addr6->sin6_port = local_port;
|
||||||
|
- /* XXX: What will happen to multicasts if this is nonzero? */
|
||||||
|
- memcpy(&addr6->sin6_addr,
|
||||||
|
- &local_address6,
|
||||||
|
- sizeof(addr6->sin6_addr));
|
||||||
|
+ if (linklocal6) {
|
||||||
|
+ memcpy(&addr6->sin6_addr,
|
||||||
|
+ linklocal6,
|
||||||
|
+ sizeof(addr6->sin6_addr));
|
||||||
|
+ addr6->sin6_scope_id = if_nametoindex(info->name);
|
||||||
|
+ }
|
||||||
|
#ifdef HAVE_SA_LEN
|
||||||
|
addr6->sin6_len = sizeof(*addr6);
|
||||||
|
#endif
|
||||||
|
@@ -221,9 +224,9 @@ if_register_socket(struct interface_info *info, int family,
|
||||||
|
* 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.
|
||||||
|
+ * less multiple sockets. Make sense only with multicast.
|
||||||
|
*/
|
||||||
|
- if (local_family == AF_INET6) {
|
||||||
|
+ if (local_family == AF_INET6 && *do_multicast) {
|
||||||
|
flag = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
|
||||||
|
(char *)&flag, sizeof(flag)) < 0) {
|
||||||
|
@@ -322,7 +325,7 @@ void if_register_send (info)
|
||||||
|
struct interface_info *info;
|
||||||
|
{
|
||||||
|
#ifndef USE_SOCKET_RECEIVE
|
||||||
|
- info->wfdesc = if_register_socket(info, AF_INET, 0);
|
||||||
|
+ info->wfdesc = if_register_socket(info, AF_INET, 0, NULL);
|
||||||
|
/* If this is a normal IPv4 address, get the hardware address. */
|
||||||
|
if (strcmp(info->name, "fallback") != 0)
|
||||||
|
get_hw_addr(info);
|
||||||
|
@@ -368,7 +371,7 @@ void if_register_receive (info)
|
||||||
|
|
||||||
|
#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
|
||||||
|
if (global_v4_socket_references == 0) {
|
||||||
|
- global_v4_socket = if_register_socket(info, AF_INET, 0);
|
||||||
|
+ global_v4_socket = if_register_socket(info, AF_INET, 0, NULL);
|
||||||
|
if (global_v4_socket < 0) {
|
||||||
|
/*
|
||||||
|
* if_register_socket() fatally logs if it fails to
|
||||||
|
@@ -384,7 +387,7 @@ void if_register_receive (info)
|
||||||
|
#else
|
||||||
|
/* If we're using the socket API for sending and receiving,
|
||||||
|
we don't need to register this interface twice. */
|
||||||
|
- info->rfdesc = if_register_socket(info, AF_INET, 0);
|
||||||
|
+ info->rfdesc = if_register_socket(info, AF_INET, 0, NULL);
|
||||||
|
#endif /* IP_PKTINFO... */
|
||||||
|
/* If this is a normal IPv4 address, get the hardware address. */
|
||||||
|
if (strcmp(info->name, "fallback") != 0)
|
||||||
|
@@ -477,9 +480,13 @@ if_register6(struct interface_info *info, int do_multicast) {
|
||||||
|
/* Bounce do_multicast to a stack variable because we may change it. */
|
||||||
|
int req_multi = do_multicast;
|
||||||
|
|
||||||
|
+ if (no_global_v6_socket) {
|
||||||
|
+ log_fatal("Impossible condition at %s:%d", MDL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (global_v6_socket_references == 0) {
|
||||||
|
global_v6_socket = if_register_socket(info, AF_INET6,
|
||||||
|
- &req_multi);
|
||||||
|
+ &req_multi, NULL);
|
||||||
|
if (global_v6_socket < 0) {
|
||||||
|
/*
|
||||||
|
* if_register_socket() fatally logs if it fails to
|
||||||
|
@@ -515,12 +522,73 @@ if_register6(struct interface_info *info, int do_multicast) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * Register an IPv6 socket bound to the link-local address of
|
||||||
|
+ * the argument interface (used by clients on a multiple interface box,
|
||||||
|
+ * vs. a server or a relay using the global IPv6 socket and running
|
||||||
|
+ * *only* in a single instance).
|
||||||
|
+ */
|
||||||
|
+void
|
||||||
|
+if_register_linklocal6(struct interface_info *info) {
|
||||||
|
+ int sock;
|
||||||
|
+ int count;
|
||||||
|
+ struct in6_addr *addr6 = NULL;
|
||||||
|
+ int req_multi = 0;
|
||||||
|
+
|
||||||
|
+ if (global_v6_socket >= 0) {
|
||||||
|
+ log_fatal("Impossible condition at %s:%d", MDL);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ no_global_v6_socket = 1;
|
||||||
|
+
|
||||||
|
+ /* get the (?) link-local address */
|
||||||
|
+ for (count = 0; count < info->v6address_count; count++) {
|
||||||
|
+ addr6 = &info->v6addresses[count];
|
||||||
|
+ if (IN6_IS_ADDR_LINKLOCAL(addr6))
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!addr6) {
|
||||||
|
+ log_fatal("no link-local IPv6 address for %s", info->name);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ sock = if_register_socket(info, AF_INET6, &req_multi, addr6);
|
||||||
|
+
|
||||||
|
+ if (sock < 0) {
|
||||||
|
+ log_fatal("if_register_socket for %s fails", info->name);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ info->rfdesc = sock;
|
||||||
|
+ info->wfdesc = sock;
|
||||||
|
+
|
||||||
|
+ get_hw_addr(info);
|
||||||
|
+
|
||||||
|
+ if (!quiet_interface_discovery) {
|
||||||
|
+ if (info->shared_network != NULL) {
|
||||||
|
+ log_info("Listening on Socket/%d/%s/%s",
|
||||||
|
+ global_v6_socket, info->name,
|
||||||
|
+ info->shared_network->name);
|
||||||
|
+ log_info("Sending on Socket/%d/%s/%s",
|
||||||
|
+ global_v6_socket, info->name,
|
||||||
|
+ info->shared_network->name);
|
||||||
|
+ } else {
|
||||||
|
+ log_info("Listening on Socket/%s", info->name);
|
||||||
|
+ log_info("Sending on Socket/%s", info->name);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
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)) {
|
||||||
|
+ /* client case */
|
||||||
|
+ if (no_global_v6_socket) {
|
||||||
|
+ close(info->rfdesc);
|
||||||
|
+ info->rfdesc = -1;
|
||||||
|
+ info->wfdesc = -1;
|
||||||
|
+ } else if ((info->rfdesc == global_v6_socket) &&
|
||||||
|
+ (info->wfdesc == global_v6_socket) &&
|
||||||
|
+ (global_v6_socket_references > 0)) {
|
||||||
|
+ /* Dereference the global v6 socket. */
|
||||||
|
global_v6_socket_references--;
|
||||||
|
info->rfdesc = -1;
|
||||||
|
info->wfdesc = -1;
|
||||||
|
@@ -540,7 +608,8 @@ if_deregister6(struct interface_info *info) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (global_v6_socket_references == 0) {
|
||||||
|
+ if (!no_global_v6_socket &&
|
||||||
|
+ (global_v6_socket_references == 0)) {
|
||||||
|
close(global_v6_socket);
|
||||||
|
global_v6_socket = -1;
|
||||||
|
|
||||||
|
@@ -692,9 +761,11 @@ ssize_t send_packet6(struct interface_info *interface,
|
||||||
|
struct sockaddr_in6 *to) {
|
||||||
|
struct msghdr m;
|
||||||
|
struct iovec v;
|
||||||
|
+ struct sockaddr_in6 dst;
|
||||||
|
int result;
|
||||||
|
struct in6_pktinfo *pktinfo;
|
||||||
|
struct cmsghdr *cmsg;
|
||||||
|
+ unsigned int ifindex;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If necessary allocate space for the control message header.
|
||||||
|
@@ -717,9 +788,14 @@ ssize_t send_packet6(struct interface_info *interface,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the target address we're sending to.
|
||||||
|
+ * Enforce the scope ID for bogus BSDs.
|
||||||
|
*/
|
||||||
|
- m.msg_name = to;
|
||||||
|
- m.msg_namelen = sizeof(*to);
|
||||||
|
+ memcpy(&dst, to, sizeof(dst));
|
||||||
|
+ m.msg_name = &dst;
|
||||||
|
+ m.msg_namelen = sizeof(dst);
|
||||||
|
+ ifindex = if_nametoindex(interface->name);
|
||||||
|
+ if (no_global_v6_socket)
|
||||||
|
+ dst.sin6_scope_id = ifindex;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the data buffer we're sending. (Using this wacky
|
||||||
|
@@ -747,7 +823,7 @@ ssize_t send_packet6(struct interface_info *interface,
|
||||||
|
cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
|
||||||
|
pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
|
||||||
|
memset(pktinfo, 0, sizeof(*pktinfo));
|
||||||
|
- pktinfo->ipi6_ifindex = if_nametoindex(interface->name);
|
||||||
|
+ pktinfo->ipi6_ifindex = ifindex;
|
||||||
|
m.msg_controllen = cmsg->cmsg_len;
|
||||||
|
|
||||||
|
result = sendmsg(interface->wfdesc, &m, 0);
|
||||||
|
@@ -1046,7 +1122,7 @@ void maybe_setup_fallback ()
|
||||||
|
isc_result_t status;
|
||||||
|
struct interface_info *fbi = (struct interface_info *)0;
|
||||||
|
if (setup_fallback (&fbi, MDL)) {
|
||||||
|
- fbi -> wfdesc = if_register_socket (fbi, AF_INET, 0);
|
||||||
|
+ fbi -> wfdesc = if_register_socket (fbi, AF_INET, 0, NULL);
|
||||||
|
fbi -> rfdesc = fbi -> wfdesc;
|
||||||
|
log_info ("Sending on Socket/%s%s%s",
|
||||||
|
fbi -> name,
|
||||||
|
diff --git a/includes/dhcpd.h b/includes/dhcpd.h
|
||||||
|
index b2fbc8b..56d4eab 100644
|
||||||
|
--- a/includes/dhcpd.h
|
||||||
|
+++ b/includes/dhcpd.h
|
||||||
|
@@ -2378,7 +2378,7 @@ void get_hw_addr(struct interface_info *info);
|
||||||
|
/* socket.c */
|
||||||
|
#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \
|
||||||
|
|| defined (USE_SOCKET_FALLBACK)
|
||||||
|
-int if_register_socket(struct interface_info *, int, int *);
|
||||||
|
+int if_register_socket(struct interface_info *, int, int *, struct in6_addr *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND)
|
||||||
|
@@ -2389,7 +2389,7 @@ ssize_t send_fallback (struct interface_info *,
|
||||||
|
struct in_addr,
|
||||||
|
struct sockaddr_in *, struct hardware *);
|
||||||
|
ssize_t send_fallback6(struct interface_info *, struct packet *,
|
||||||
|
- struct dhcp_packet *, size_t, struct in6_addr,
|
||||||
|
+ struct dhcp_packet *, size_t, struct in6_addr *,
|
||||||
|
struct sockaddr_in6 *, struct hardware *);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -2425,6 +2425,7 @@ void maybe_setup_fallback (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void if_register6(struct interface_info *info, int do_multicast);
|
||||||
|
+void if_register_linklocal6(struct interface_info *info);
|
||||||
|
ssize_t receive_packet6(struct interface_info *interface,
|
||||||
|
unsigned char *buf, size_t len,
|
||||||
|
struct sockaddr_in6 *from, struct in6_addr *to_addr,
|
||||||
|
@@ -2570,7 +2571,6 @@ void interface_trace_setup (void);
|
||||||
|
extern struct in_addr limited_broadcast;
|
||||||
|
extern int local_family;
|
||||||
|
extern struct in_addr local_address;
|
||||||
|
-extern struct in6_addr local_address6;
|
||||||
|
|
||||||
|
extern u_int16_t local_port;
|
||||||
|
extern u_int16_t remote_port;
|
||||||
|
--
|
||||||
|
1.8.3.1
|
||||||
|
|
@ -18,7 +18,7 @@
|
|||||||
Summary: Dynamic host configuration protocol software
|
Summary: Dynamic host configuration protocol software
|
||||||
Name: dhcp
|
Name: dhcp
|
||||||
Version: 4.2.5
|
Version: 4.2.5
|
||||||
Release: 24%{?dist}
|
Release: 25%{?dist}
|
||||||
# NEVER CHANGE THE EPOCH on this package. The previous maintainer (prior to
|
# NEVER CHANGE THE EPOCH on this package. The previous maintainer (prior to
|
||||||
# dcantrell maintaining the package) made incorrect use of the epoch and
|
# dcantrell maintaining the package) made incorrect use of the epoch and
|
||||||
# that's why it is at 12 now. It should have never been used, but it was.
|
# that's why it is at 12 now. It should have never been used, but it was.
|
||||||
@ -79,7 +79,7 @@ Patch45: dhcp-4.2.4-P2-conflex-do-forward-updates.patch
|
|||||||
Patch46: dhcp-4.2.4-P2-dupl-key.patch
|
Patch46: dhcp-4.2.4-P2-dupl-key.patch
|
||||||
Patch47: dhcp-4.2.5-range6.patch
|
Patch47: dhcp-4.2.5-range6.patch
|
||||||
Patch48: dhcp-4.2.5-next-server.patch
|
Patch48: dhcp-4.2.5-next-server.patch
|
||||||
Patch49: dhcp-bindtodevice-inet6.patch
|
Patch49: dhcp-dhclient6-bind.patch
|
||||||
Patch50: dhcp-no-subnet-error2info.patch
|
Patch50: dhcp-no-subnet-error2info.patch
|
||||||
Patch51: dhcp-ffff-checksum.patch
|
Patch51: dhcp-ffff-checksum.patch
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ rm -rf includes/isc-dhcp
|
|||||||
|
|
||||||
# dhclient -6: bind socket to interface (#1001742)
|
# dhclient -6: bind socket to interface (#1001742)
|
||||||
# (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #34784])
|
# (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #34784])
|
||||||
%patch49 -p1 -b .bindtodevice_inet6
|
%patch49 -p1 -b .dhclient6-bind
|
||||||
|
|
||||||
# 'No subnet declaration for <iface>' should be info, not error.
|
# 'No subnet declaration for <iface>' should be info, not error.
|
||||||
%patch50 -p1 -b .error2info
|
%patch50 -p1 -b .error2info
|
||||||
@ -624,6 +624,9 @@ done
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Oct 24 2013 Jiri Popelka <jpopelka@redhat.com> - 12:4.2.5-25
|
||||||
|
- use upstream patch for #1001742 ([ISC-Bugs #34784])
|
||||||
|
|
||||||
* Mon Oct 07 2013 Jiri Popelka <jpopelka@redhat.com> - 12:4.2.5-24
|
* Mon Oct 07 2013 Jiri Popelka <jpopelka@redhat.com> - 12:4.2.5-24
|
||||||
- dhcpd rejects the udp packet with checksum=0xffff (#1015997)
|
- dhcpd rejects the udp packet with checksum=0xffff (#1015997)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user