diff --git a/SOURCES/11-dhclient b/SOURCES/11-dhclient index 3be4cd6..b931c1d 100644 --- a/SOURCES/11-dhclient +++ b/SOURCES/11-dhclient @@ -29,6 +29,10 @@ if [ -d $ETCDIR/dhclient.d ]; then . ${f} if [ "$2" = "up" ]; then "${subsystem}_config" + elif [ "$2" = "dhcp4-change" ]; then + if [ "$subsystem" = "chrony" -o "$subsystem" = "ntp" ]; then + "${subsystem}_config" + fi elif [ "$2" = "down" ]; then "${subsystem}_restore" fi diff --git a/SOURCES/dhclient-script b/SOURCES/dhclient-script index a829568..d985454 100644 --- a/SOURCES/dhclient-script +++ b/SOURCES/dhclient-script @@ -44,14 +44,6 @@ logmessage() { logger -p ${LOGFACILITY}.${LOGLEVEL} -t "NET" "dhclient: ${msg}" } -if [ -x /sbin/restorecon ]; then - fix_context() { - /sbin/restorecon ${1} >/dev/null 2>&1 - } -else - fix_context() { :; } -fi - eventually_add_hostnames_domain_to_search() { # For the case when hostname for this machine has a domain that is not in domain_search list # 1) get a hostname with `ipcalc --hostname` or `hostname` @@ -145,8 +137,6 @@ make_resolv_conf() { if [ -n "${search}" ]; then eventually_add_hostnames_domain_to_search "${search}" fi - - fix_context /etc/resolv.conf elif [ -n "${new_dhcp6_name_servers}" ] || [ -n "${new_dhcp6_domain_search}" ]; then rscf="$(mktemp ${TMPDIR:-/tmp}/XXXXXX)" @@ -189,8 +179,6 @@ make_resolv_conf() { if [ -n "${search}" ]; then eventually_add_hostnames_domain_to_search "${search}" fi - - fix_context /etc/resolv.conf fi } @@ -274,17 +262,9 @@ is_router_reachable() { mysubnet="$(get_network_address ${new_ip_address} ${new_subnet_mask})" if [ ! "${routersubnet}" = "${mysubnet}" ]; then - ip -4 route add ${router}/32 dev ${interface} - if [ $? -eq 0 ]; then - if ping -q -c1 -w2 -I ${interface} ${router}; then - return 0 - else - logmessage "DHCP router ${router} is unreachable on DHCP subnet ${mysubnet} router subnet ${routersubnet}" - ip route del ${router}/32 dev ${interface} - return 1 - fi - else - logmessage "failed to create host router for unreachable router ${router} not on subnet ${mysubnet}" + ip -4 route replace ${router}/32 dev ${interface} + if [ "$?" -ne 0 ]; then + logmessage "failed to create host route for ${router}" return 1 fi fi @@ -537,7 +517,6 @@ dhconfig() { if [ -e ${tzfile} ]; then cp -fp ${tzfile} /etc/localtime touch /etc/localtime - fix_context /etc/localtime fi fi @@ -558,22 +537,30 @@ add_ipv6_addr_with_DAD() { for i in $(seq 5); do sleep 1 # give the DAD some time + addr=$(ip -6 addr show dev ${interface} \ + | grep ${new_ip6_address}/${new_ip6_prefixlen}) + # tentative flag == DAD is still not complete - tentative=$(ip -6 addr show dev ${interface} tentative \ - | grep ${new_ip6_address}/${new_ip6_prefixlen}) + tentative=$(echo "${addr}" | grep tentative) # dadfailed flag == address is already in use somewhere else - dadfailed=$(ip -6 addr show dev ${interface} dadfailed \ - | grep ${new_ip6_address}/${new_ip6_prefixlen}) + dadfailed=$(echo "${addr}" | grep dadfailed) if [ -n "${dadfailed}" ] ; then - #ip -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} dev ${interface} + # address was added with valid_lft/preferred_lft 'forever', remove it + ip -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} dev ${interface} exit_with_hooks 3 fi if [ -z "${tentative}" ] ; then - # DAD is over - return 0 + if [ -n "${addr}" ]; then + # DAD is over + return 0 + else + # address was auto-removed (or not added at all) + exit_with_hooks 3 + fi fi done + return 0 } dh6config() { @@ -596,18 +583,16 @@ dh6config() { ;; RENEW6|REBIND6) - if [ -z "${new_ip6_address}" ] || - [ -z "${new_ip6_prefixlen}" ]; then - exit_with_hooks 2 - fi - - if [ ! "${new_ip6_address}" = "${old_ip6_address}" ]; then - add_ipv6_addr_with_DAD - else # only update address lifetimes - ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ - dev ${interface} scope global valid_lft ${new_max_life} \ - preferred_lft ${new_preferred_life} - fi + if [[ -n "${new_ip6_address}" ]] && + [[ -n "${new_ip6_prefixlen}" ]]; then + if [[ ! "${new_ip6_address}" = "${old_ip6_address}" ]]; then + add_ipv6_addr_with_DAD + else # only update address lifetimes + ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ + dev ${interface} scope global valid_lft ${new_max_life} \ + preferred_lft ${new_preferred_life} + fi + fi if [ ! "${new_dhcp6_name_servers}" = "${old_dhcp6_name_servers}" ] || [ ! "${new_dhcp6_domain_search}" = "${old_dhcp6_domain_search}" ]; then @@ -705,6 +690,15 @@ case "${reason}" in # remove any stale addresses from aborted clients ip -6 addr flush dev ${interface} scope global permanent + # we need a link-local address to be ready (not tentative) + for i in $(seq 50); do + linklocal=$(ip -6 addr show dev ${interface} scope link) + # tentative flag means DAD is still not complete + tentative=$(echo "${linklocal}" | grep tentative) + [[ -n "${linklocal}" && -z "${tentative}" ]] && exit_with_hooks 0 + sleep 0.1 + done + exit_with_hooks 0 ;; diff --git a/SOURCES/dhcp-4.2.5-centos-branding.patch b/SOURCES/dhcp-4.2.5-centos-branding.patch deleted file mode 100644 index f3e7113..0000000 --- a/SOURCES/dhcp-4.2.5-centos-branding.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -uNrp dhcp-4.1.1-P1.orig/omapip/errwarn.c dhcp-4.1.1-P1/omapip/errwarn.c ---- dhcp-4.1.1-P1.orig/omapip/errwarn.c 2012-08-15 14:04:33.149141000 +0000 -+++ dhcp-4.1.1-P1/omapip/errwarn.c 2012-08-15 14:13:05.582416057 +0000 -@@ -81,8 +81,8 @@ void log_fatal (const char * fmt, ... ) - log_error ("have been made to the base software release in order to make"); - log_error ("it work better with this distribution."); - log_error ("%s", ""); -- log_error ("Please report for this software via the Red Hat Bugzilla site:"); -- log_error (" http://bugzilla.redhat.com"); -+ log_error ("Please report for this software via the CentOS Bugs Database:"); -+ log_error (" http://bugs.centos.org/"); - log_error ("%s", ""); - log_error ("exiting."); - #endif diff --git a/SOURCES/dhcp-4.2.5-ipv6-bind-to-interface.patch b/SOURCES/dhcp-4.2.5-ipv6-bind-to-interface.patch deleted file mode 100644 index 0163237..0000000 --- a/SOURCES/dhcp-4.2.5-ipv6-bind-to-interface.patch +++ /dev/null @@ -1,26 +0,0 @@ -Index: dhcp-4.2.5-P1/common/socket.c -=================================================================== ---- dhcp-4.2.5-P1.orig/common/socket.c -+++ dhcp-4.2.5-P1/common/socket.c -@@ -227,7 +227,7 @@ if_register_socket(struct interface_info - flag = 1; - if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, - (char *)&flag, sizeof(flag)) < 0) { -- log_fatal("Can't set SO_REUSEPORT option on dhcp " -+ log_error("Can't set SO_REUSEPORT option on dhcp " - "socket: %m"); - } - } -@@ -245,10 +245,10 @@ 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 || !*do_multicast) && info->ifp && - setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) { -- log_fatal("setsockopt: SO_BINDTODEVICE: %m"); -+ log_error("setsockopt: SO_BINDTODEVICE: %m"); - } - #endif - diff --git a/SOURCES/dhcp-IPoIB-log-id.patch b/SOURCES/dhcp-IPoIB-log-id.patch new file mode 100644 index 0000000..4b4f71b --- /dev/null +++ b/SOURCES/dhcp-IPoIB-log-id.patch @@ -0,0 +1,260 @@ +diff -up dhcp-4.2.5/common/lpf.c.IPoIB-log-id dhcp-4.2.5/common/lpf.c +--- dhcp-4.2.5/common/lpf.c.IPoIB-log-id 2014-09-08 14:50:39.000000000 +0200 ++++ dhcp-4.2.5/common/lpf.c 2014-09-08 14:54:43.935612705 +0200 +@@ -158,6 +158,7 @@ int if_register_lpf (info) + void if_register_send (info) + struct interface_info *info; + { ++ int hlen; + /* If we're using the lpf API for sending and receiving, + we don't need to register this interface twice. */ + #ifndef USE_LPF_RECEIVE +@@ -165,11 +166,15 @@ void if_register_send (info) + #else + info -> wfdesc = info -> rfdesc; + #endif ++ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) ++ hlen = 9; ++ else ++ hlen = info -> hw_address.hlen; + if (!quiet_interface_discovery) + log_info ("Sending on LPF/%s/%s%s%s", + info -> name, + print_hw_addr (info -> hw_address.hbuf [0], +- info -> hw_address.hlen - 1, ++ hlen - 1, + &info -> hw_address.hbuf [1]), + (info -> shared_network ? "/" : ""), + (info -> shared_network ? +@@ -179,6 +184,9 @@ void if_register_send (info) + void if_deregister_send (info) + struct interface_info *info; + { ++ int hlen = info -> hw_address.hlen; ++ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) ++ hlen = 9; + /* don't need to close twice if we are using lpf for sending and + receiving */ + #ifndef USE_LPF_RECEIVE +@@ -191,7 +199,7 @@ void if_deregister_send (info) + log_info ("Disabling output on LPF/%s/%s%s%s", + info -> name, + print_hw_addr (info -> hw_address.hbuf [0], +- info -> hw_address.hlen - 1, ++ hlen - 1, + &info -> hw_address.hbuf [1]), + (info -> shared_network ? "/" : ""), + (info -> shared_network ? +@@ -218,7 +226,7 @@ static void lpf_gen_filter_setup (struct + void if_register_receive (info) + struct interface_info *info; + { +- int val; ++ int val, hlen; + + /* Open a LPF device and hang it on this interface... */ + info -> rfdesc = if_register_lpf (info); +@@ -230,7 +238,9 @@ void if_register_receive (info) + if (errno != ENOPROTOOPT) + log_fatal ("Failed to set auxiliary packet data: %m"); + } +- } ++ hlen = info -> hw_address.hlen; ++ } else ++ hlen = 9; + + #if defined (HAVE_TR_SUPPORT) + if (info -> hw_address.hbuf [0] == HTYPE_IEEE802) +@@ -243,7 +253,7 @@ void if_register_receive (info) + log_info ("Listening on LPF/%s/%s%s%s", + info -> name, + print_hw_addr (info -> hw_address.hbuf [0], +- info -> hw_address.hlen - 1, ++ hlen - 1, + &info -> hw_address.hbuf [1]), + (info -> shared_network ? "/" : ""), + (info -> shared_network ? +@@ -253,6 +263,9 @@ void if_register_receive (info) + void if_deregister_receive (info) + struct interface_info *info; + { ++ int hlen = info -> hw_address.hlen; ++ if (info->hw_address.hbuf[0] == HTYPE_INFINIBAND) ++ hlen = 9; + /* for LPF this is simple, packet filters are removed when sockets + are closed */ + close (info -> rfdesc); +@@ -261,7 +274,7 @@ void if_deregister_receive (info) + log_info ("Disabling input on LPF/%s/%s%s%s", + info -> name, + print_hw_addr (info -> hw_address.hbuf [0], +- info -> hw_address.hlen - 1, ++ hlen - 1, + &info -> hw_address.hbuf [1]), + (info -> shared_network ? "/" : ""), + (info -> shared_network ? +diff -up dhcp-4.2.5/server/dhcp.c.IPoIB-log-id dhcp-4.2.5/server/dhcp.c +--- dhcp-4.2.5/server/dhcp.c.IPoIB-log-id 2014-09-08 14:50:39.000000000 +0200 ++++ dhcp-4.2.5/server/dhcp.c 2014-09-08 15:06:28.367697349 +0200 +@@ -80,6 +80,42 @@ const int dhcp_type_name_max = ((sizeof + # define send_packet trace_packet_send + #endif + ++char *print_client_identifier_from_packet (packet) ++ struct packet *packet; ++{ ++ struct option_cache *oc; ++ struct data_string client_identifier; ++ char *ci; ++ ++ memset (&client_identifier, 0, sizeof client_identifier); ++ ++ oc = lookup_option (&dhcp_universe, packet -> options, ++ DHO_DHCP_CLIENT_IDENTIFIER); ++ if (oc && ++ evaluate_option_cache (&client_identifier, ++ packet, (struct lease *)0, ++ (struct client_state *)0, ++ packet -> options, ++ (struct option_state *)0, ++ &global_scope, oc, MDL)) { ++ ci = print_hw_addr (HTYPE_INFINIBAND, client_identifier.len, client_identifier.data); ++ data_string_forget (&client_identifier, MDL); ++ return ci; ++ } else ++ return "\"no client id\""; ++} ++ ++char *print_hw_addr_or_client_id (packet) ++ struct packet *packet; ++{ ++ if (packet -> raw -> htype == HTYPE_INFINIBAND) ++ return print_client_identifier_from_packet (packet); ++ else ++ return print_hw_addr (packet -> raw -> htype, ++ packet -> raw -> hlen, ++ packet -> raw -> chaddr); ++} ++ + void + dhcp (struct packet *packet) { + int ms_nulltp = 0; +@@ -108,9 +144,7 @@ dhcp (struct packet *packet) { + + log_info("%s from %s via %s: %s", s, + (packet->raw->htype +- ? print_hw_addr(packet->raw->htype, +- packet->raw->hlen, +- packet->raw->chaddr) ++ ? print_hw_addr_or_client_id (packet) + : ""), + packet->raw->giaddr.s_addr + ? inet_ntoa(packet->raw->giaddr) +@@ -294,9 +328,7 @@ void dhcpdiscover (packet, ms_nulltp) + */ + snprintf (msgbuf, sizeof msgbuf, "DHCPDISCOVER from %s %s%s%svia %s", + (packet -> raw -> htype +- ? print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr) ++ ? print_hw_addr_or_client_id (packet) + : (lease + ? print_hex_1(lease->uid_len, lease->uid, 60) + : "")), +@@ -490,9 +522,7 @@ void dhcprequest (packet, ms_nulltp, ip_ + "DHCPREQUEST for %s%s from %s %s%s%svia %s", + piaddr (cip), smbuf, + (packet -> raw -> htype +- ? print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr) ++ ? print_hw_addr_or_client_id (packet) + : (lease + ? print_hex_1(lease->uid_len, lease->uid, 60) + : "")), +@@ -735,9 +765,7 @@ void dhcprelease (packet, ms_nulltp) + if ((oc = lookup_option (&dhcp_universe, packet -> options, + DHO_DHCP_REQUESTED_ADDRESS))) { + log_info ("DHCPRELEASE from %s specified requested-address.", +- print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr)); ++ print_hw_addr_or_client_id (packet)); + } + + oc = lookup_option (&dhcp_universe, packet -> options, +@@ -811,9 +839,7 @@ void dhcprelease (packet, ms_nulltp) + "DHCPRELEASE of %s from %s %s%s%svia %s (%sfound)", + cstr, + (packet -> raw -> htype +- ? print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr) ++ ? print_hw_addr_or_client_id (packet) + : (lease + ? print_hex_1(lease->uid_len, lease->uid, 60) + : "")), +@@ -906,9 +932,7 @@ void dhcpdecline (packet, ms_nulltp) + "DHCPDECLINE of %s from %s %s%s%svia %s", + piaddr (cip), + (packet -> raw -> htype +- ? print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr) ++ ? print_hw_addr_or_client_id(packet) + : (lease + ? print_hex_1(lease->uid_len, lease->uid, 60) + : "")), +@@ -1348,8 +1372,7 @@ void dhcpinform (packet, ms_nulltp) + /* Report what we're sending. */ + snprintf(msgbuf, sizeof msgbuf, "DHCPACK to %s (%s) via", piaddr(cip), + (packet->raw->htype && packet->raw->hlen) ? +- print_hw_addr(packet->raw->htype, packet->raw->hlen, +- packet->raw->chaddr) : ++ print_hw_addr_or_client_id(packet) : + ""); + log_info("%s %s", msgbuf, gip.len ? piaddr(gip) : + packet->interface->name); +@@ -1493,9 +1516,7 @@ void nak_lease (packet, cip) + /* Report what we're sending... */ + log_info ("DHCPNAK on %s to %s via %s", + piaddr (*cip), +- print_hw_addr (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr), ++ print_hw_addr_or_client_id (packet), + packet -> raw -> giaddr.s_addr + ? inet_ntoa (packet -> raw -> giaddr) + : packet -> interface -> name); +@@ -3214,7 +3235,7 @@ void dhcp_reply (lease) + ? (state -> offer == DHCPACK ? "DHCPACK" : "DHCPOFFER") + : "BOOTREPLY"), + piaddr (lease -> ip_addr), +- (lease -> hardware_addr.hlen ++ (lease -> hardware_addr.hlen > 1 + ? print_hw_addr (lease -> hardware_addr.hbuf [0], + lease -> hardware_addr.hlen - 1, + &lease -> hardware_addr.hbuf [1]) +@@ -3772,10 +3793,7 @@ int find_lease (struct lease **lp, + if (uid_lease) { + if (uid_lease->binding_state == FTS_ACTIVE) { + log_error ("client %s has duplicate%s on %s", +- (print_hw_addr +- (packet -> raw -> htype, +- packet -> raw -> hlen, +- packet -> raw -> chaddr)), ++ (print_hw_addr_or_client_id(packet)), + " leases", + (ip_lease -> subnet -> + shared_network -> name)); +@@ -3942,9 +3960,7 @@ int find_lease (struct lease **lp, + log_error("uid lease %s for client %s is duplicate " + "on %s", + piaddr(uid_lease->ip_addr), +- print_hw_addr(packet->raw->htype, +- packet->raw->hlen, +- packet->raw->chaddr), ++ print_hw_addr_or_client_id(packet), + uid_lease->subnet->shared_network->name); + + if (!packet -> raw -> ciaddr.s_addr && diff --git a/SOURCES/dhcp-dhc6-life.patch b/SOURCES/dhcp-dhc6-life.patch new file mode 100644 index 0000000..49b3a5b --- /dev/null +++ b/SOURCES/dhcp-dhc6-life.patch @@ -0,0 +1,37 @@ +From 4d5514f9579197a4200a52332a9047da1424b3ee Mon Sep 17 00:00:00 2001 +From: Jiri Popelka +Date: Thu, 4 Sep 2014 16:03:38 +0200 +Subject: [PATCH] [dhclient -6] fix lease time exporting + +addr->preferred_life and addr->max_life are u_int32_t +so casting them to (int) causes problems with big values, +for example with 'infinity' (0xffffffff), which is +then represented as '-1' in dhclient-script. + +Signed-off-by: Jiri Popelka +--- + client/dhc6.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/client/dhc6.c b/client/dhc6.c +index c724b58..04a8fa0 100644 +--- a/client/dhc6.c ++++ b/client/dhc6.c +@@ -3862,10 +3862,10 @@ dhc6_marshall_values(const char *prefix, struct client_state *client, + } + client_envadd(client, prefix, "life_starts", "%d", + (int)(addr->starts)); +- client_envadd(client, prefix, "preferred_life", "%d", +- (int)(addr->preferred_life)); +- client_envadd(client, prefix, "max_life", "%d", +- (int)(addr->max_life)); ++ client_envadd(client, prefix, "preferred_life", "%u", ++ addr->preferred_life); ++ client_envadd(client, prefix, "max_life", "%u", ++ addr->max_life); + } + + /* ia fields. */ +-- +2.1.0 + diff --git a/SOURCES/dhcp-hop-limit.patch b/SOURCES/dhcp-hop-limit.patch new file mode 100644 index 0000000..b4b6a78 --- /dev/null +++ b/SOURCES/dhcp-hop-limit.patch @@ -0,0 +1,117 @@ +From accb28721d061f2e06e927bdb1337317db3aa706 Mon Sep 17 00:00:00 2001 +From: Thomas Markwalder +Date: Mon, 19 Jan 2015 13:40:25 -0500 +Subject: [PATCH] [v4_2] Fixed inconsistencies in setting hop count limit in + dhcrelay + +diff --git a/common/socket.c b/common/socket.c +index c170448..5467a35 100644 +--- a/common/socket.c ++++ b/common/socket.c +@@ -300,18 +300,24 @@ if_register_socket(struct interface_info *info, int family, + #endif + } + +- if ((family == AF_INET6) && +- ((info->flags & INTERFACE_UPSTREAM) != 0)) { +- int hop_limit = 32; +- if (setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, +- &hop_limit, sizeof(int)) < 0) { +- log_fatal("setsockopt: IPV6_MULTICAST_HOPS: %m"); +- } +- } + #endif /* DHCPv6 */ + + return sock; + } ++ ++#ifdef DHCPv6 ++void set_multicast_hop_limit(struct interface_info* info, int hop_limit) { ++ if (setsockopt(info->wfdesc, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, ++ &hop_limit, sizeof(int)) < 0) { ++ log_fatal("setMulticaseHopLimit: IPV6_MULTICAST_HOPS: %m"); ++ } ++ ++ log_debug("Setting hop count limit to %d for interface %s", ++ hop_limit, info->name); ++ ++} ++#endif /* DHCPv6 */ ++ + #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE || USE_SOCKET_FALLBACK */ + + #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) +diff --git a/includes/dhcpd.h b/includes/dhcpd.h +index 2b15430..bd11b48 100644 +--- a/includes/dhcpd.h ++++ b/includes/dhcpd.h +@@ -2386,6 +2386,8 @@ void get_hw_addr(const char *name, struct hardware *hw); + #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_RECEIVE) \ + || defined (USE_SOCKET_FALLBACK) + int if_register_socket(struct interface_info *, int, int *, struct in6_addr *); ++ ++void set_multicast_hop_limit(struct interface_info* info, int hop_limit); + #endif + + #if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND) +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 927e404..ad76d3e 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -1173,8 +1173,8 @@ parse_downstream(char *arg) { + /* Share with up side? */ + for (up = upstreams; up; up = up->next) { + if (strcmp(ifname, up->ifp->name) == 0) { +- log_info("Interface '%s' is both down and up.", +- ifname); ++ log_info("parse_downstream: Interface '%s' is " ++ "both down and up.", ifname); + ifp = up->ifp; + break; + } +@@ -1192,8 +1192,8 @@ parse_downstream(char *arg) { + interface_dereference(&interfaces, MDL); + } + interface_reference(&interfaces, ifp, MDL); +- ifp->flags |= INTERFACE_REQUESTED | INTERFACE_DOWNSTREAM; + } ++ ifp->flags |= INTERFACE_REQUESTED | INTERFACE_DOWNSTREAM; + + /* New downstream. */ + dp = (struct stream_list *) dmalloc(sizeof(*dp), MDL); +@@ -1244,6 +1244,8 @@ parse_upstream(char *arg) { + } + for (dp = downstreams; dp; dp = dp->next) { + if (strcmp(ifname, dp->ifp->name) == 0) { ++ log_info("parse_upstream: Interface '%s' is " ++ "both down and up.", ifname); + ifp = dp->ifp; + break; + } +@@ -1261,8 +1263,8 @@ parse_upstream(char *arg) { + interface_dereference(&interfaces, MDL); + } + interface_reference(&interfaces, ifp, MDL); +- ifp->flags |= INTERFACE_REQUESTED | INTERFACE_UPSTREAM; + } ++ ifp->flags |= INTERFACE_REQUESTED | INTERFACE_UPSTREAM; + + /* New upstream. */ + up = (struct stream_list *) dmalloc(sizeof(*up), MDL); +@@ -1330,6 +1332,13 @@ setup_streams(void) { + if (up->ifp->v6address_count == 0) + log_fatal("Interface '%s' has no IPv6 addresses.", + up->ifp->name); ++ ++ /* RFC 3315 Sec 20 - "If the relay agent relays messages to ++ * the All_DHCP_Servers address or other multicast addresses, ++ * it sets the Hop Limit field to 32." */ ++ if (IN6_IS_ADDR_MULTICAST(&up->link.sin6_addr)) { ++ set_multicast_hop_limit(up->ifp, HOP_COUNT_LIMIT); ++ } + } + } + +-- +2.1.0 + diff --git a/SOURCES/dhcp-multiple-6-clients.patch b/SOURCES/dhcp-multiple-6-clients.patch new file mode 100644 index 0000000..6187bcc --- /dev/null +++ b/SOURCES/dhcp-multiple-6-clients.patch @@ -0,0 +1,323 @@ +From 4b8251a0c06b7d8706a28904fdef2414f045cc2c Mon Sep 17 00:00:00 2001 +From: Shawn Routhier +Date: Mon, 21 Oct 2013 14:59:41 -0700 +Subject: [PATCH] -n [master] Fix the socket handling for DHCPv6 clients to + allow multiple instances of a clinet on a single machine to work properly. + [ISC-Bugs #34784] + +--- + common/discover.c | 19 ++++----- + common/socket.c | 114 +++++++++++++++++++++++++++++++++++++++++++++--------- + includes/dhcpd.h | 6 +-- + 4 files changed, 112 insertions(+), 33 deletions(-) + +diff --git a/common/discover.c b/common/discover.c +index 1d55317..30da566 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -58,10 +58,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, +@@ -1242,7 +1238,7 @@ discover_interfaces(int state) { + (state == DISCOVER_RELAY)) { + if_register6(tmp, 1); + } else { +- if_register6(tmp, 0); ++ if_register_linklocal6(tmp); + } + #endif /* DHCPv6 */ + } +@@ -1298,13 +1294,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 8a9ebea..2bedd3a 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,7 +224,7 @@ 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) { + flag = 1; +@@ -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 +@@ -748,7 +824,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); +@@ -1047,7 +1123,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 73c632f..9e18818 100644 +--- a/includes/dhcpd.h ++++ b/includes/dhcpd.h +@@ -2414,7 +2414,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 *); ++int if_register_socket(struct interface_info *, int, int *, struct in6_addr *); + #endif + + #if defined (USE_SOCKET_FALLBACK) && !defined (USE_SOCKET_SEND) +@@ -2425,7 +2425,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 + +@@ -2461,6 +2461,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, +@@ -2606,7 +2607,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; +-- +2.1.0 + diff --git a/SOURCES/dhcp-stateless-store-duid.patch b/SOURCES/dhcp-stateless-store-duid.patch new file mode 100644 index 0000000..c4555b2 --- /dev/null +++ b/SOURCES/dhcp-stateless-store-duid.patch @@ -0,0 +1,14 @@ +diff -up dhcp-4.2.5/client/dhclient.c.stateless-store-duid dhcp-4.2.5/client/dhclient.c +--- dhcp-4.2.5/client/dhclient.c.stateless-store-duid 2014-12-09 17:29:32.683444318 +0100 ++++ dhcp-4.2.5/client/dhclient.c 2014-12-09 17:30:53.917444318 +0100 +@@ -1151,7 +1151,9 @@ void run_stateless(int exit_mode) + if (default_duid.buffer != NULL) + data_string_forget(&default_duid, MDL); + +- form_duid(&default_duid, MDL); ++ if (form_duid(&default_duid, MDL) == ISC_R_SUCCESS && ++ duid_type == DUID_LLT) ++ write_duid(&default_duid); + } + + /* Start a configuration state machine. */ diff --git a/SOURCES/dhcpd.service b/SOURCES/dhcpd.service index 746011b..84a6cf7 100644 --- a/SOURCES/dhcpd.service +++ b/SOURCES/dhcpd.service @@ -1,7 +1,8 @@ [Unit] Description=DHCPv4 Server Daemon Documentation=man:dhcpd(8) man:dhcpd.conf(5) -After=network.target +Wants=network-online.target +After=network-online.target After=time-sync.target [Service] diff --git a/SOURCES/dhcpd6.service b/SOURCES/dhcpd6.service index 32d3eda..35a7eae 100644 --- a/SOURCES/dhcpd6.service +++ b/SOURCES/dhcpd6.service @@ -1,7 +1,8 @@ [Unit] Description=DHCPv6 Server Daemon Documentation=man:dhcpd(8) man:dhcpd.conf(5) -After=network.target +Wants=network-online.target +After=network-online.target After=time-sync.target [Service] diff --git a/SOURCES/dhcrelay.service b/SOURCES/dhcrelay.service index b84c4ff..67389cc 100644 --- a/SOURCES/dhcrelay.service +++ b/SOURCES/dhcrelay.service @@ -1,7 +1,8 @@ [Unit] Description=DHCP Relay Agent Daemon Documentation=man:dhcrelay(8) -After=network.target +Wants=network-online.target +After=network-online.target [Service] Type=notify diff --git a/SPECS/dhcp.spec b/SPECS/dhcp.spec index d81eaf2..b21ab04 100644 --- a/SPECS/dhcp.spec +++ b/SPECS/dhcp.spec @@ -18,7 +18,7 @@ Summary: Dynamic host configuration protocol software Name: dhcp Version: 4.2.5 -Release: 27%{?dist}.2 +Release: 36%{?dist} # NEVER CHANGE THE EPOCH on this package. The previous maintainer (prior to # 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. @@ -79,10 +79,13 @@ Patch45: dhcp-4.2.4-P2-conflex-do-forward-updates.patch Patch46: dhcp-4.2.4-P2-dupl-key.patch Patch47: dhcp-4.2.5-range6.patch Patch48: dhcp-4.2.5-next-server.patch -Patch49: dhcp-4.2.5-ipv6-bind-to-interface.patch +Patch49: dhcp-multiple-6-clients.patch Patch50: dhcp-ffff-checksum.patch Patch51: dhcp-sd-daemon.patch -Patch52: dhcp-4.2.5-centos-branding.patch +Patch52: dhcp-IPoIB-log-id.patch +Patch53: dhcp-dhc6-life.patch +Patch54: dhcp-hop-limit.patch +Patch55: dhcp-stateless-store-duid.patch BuildRequires: autoconf BuildRequires: automake @@ -91,11 +94,6 @@ BuildRequires: openldap-devel BuildRequires: libcap-ng-devel BuildRequires: bind-lite-devel BuildRequires: systemd systemd-devel -%if 0%{?fedora} -# %%check -# there's no atf package in RHEL -BuildRequires: atf libatf-c-devel -%endif %if %sdt BuildRequires: systemtap-sdt-devel %global tapsetdir /usr/share/systemtap/tapset @@ -347,8 +345,11 @@ rm -rf includes/isc-dhcp # (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #33098]) %patch48 -p1 -b .next-server -# dhclient: Bind socket to interface also for IPv6 (#1005814) -%patch49 -p1 -b .ipv6-bind-to-interface +# 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. (#1005814, #1151039) +# (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #34784]) +%patch49 -p1 -b .multiple-6-clients # dhcpd rejects the udp packet with checksum=0xffff (#1016143) # (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #25587]) @@ -356,7 +357,20 @@ rm -rf includes/isc-dhcp # support for sending startup notification to systemd (#1087245) %patch51 -p1 -b .sd-daemon -%patch52 -p1 + +# Add GUIDs in the DHCP logs for IPoIB. (#1109947) +%patch52 -p1 -b .IPoIB-log-id + +# [dhclient -6] infinite preferred/valid lifetime represented as -1 (#1133839) +# (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #37084]) +%patch53 -p1 -b .life + +# Relay-forward Message's Hop Limit should be 32 (#1147240) +# (Submitted to dhcp-bugs@isc.org - [ISC-Bugs #37426]) +%patch54 -p1 -b .hop-limit + +# Write DUID_LLT even in stateless mode (#1156356) +%patch55 -p1 -b .stateless-store-duid # Update paths in all man pages for page in client/dhclient.conf.5 client/dhclient.leases.5 \ @@ -397,18 +411,10 @@ CFLAGS="%{optflags} -fno-strict-aliasing" \ --enable-systemtap \ --with-tapset-install-dir=%{tapsetdir} \ %endif -%if 0%{?fedora} - --with-atf \ -%endif --enable-paranoia --enable-early-chroot \ --with-systemd %{__make} %{?_smp_mflags} -%if 0%{?fedora} -%check -%{__make} check -%endif - %install %{__make} install DESTDIR=%{buildroot} @@ -524,6 +530,7 @@ for servicename in dhcpd dhcpd6 dhcrelay; do etcservicefile=%{_sysconfdir}/systemd/system/${servicename}.service if [ -f ${etcservicefile} ]; then grep -q Type= ${etcservicefile} || sed -i '/\[Service\]/a Type=notify' ${etcservicefile} + sed -i 's/After=network.target/Wants=network-online.target\nAfter=network-online.target/' ${etcservicefile} fi done exit 0 @@ -631,13 +638,40 @@ done %changelog -* Mon Oct 06 2014 CentOS Sources - 4.2.5-27.el7.centos.2 -- Roll in CentOS Branding +* Tue Jan 20 2015 Jiri Popelka - 12:4.2.5-36 +- use upstream patch for #1147240 (Relay-forward's Hop Limit) + +* Tue Dec 09 2014 Jiri Popelka - 12:4.2.5-35 +- Write DUID_LLT even in stateless mode (#1156356) + +* Tue Nov 18 2014 Jiri Popelka - 12:4.2.5-34 +- Use network-online.target instead of network.target (#1145832) +- dhclient-script: restorecon calls shouldn't be needed + as we have SELinux transition rules (#1161500) + +* Fri Oct 10 2014 Jiri Popelka - 12:4.2.5-33 +- Relay-forward Message's Hop Limit should be 32 (#1147240) + +* Thu Oct 09 2014 Jiri Popelka - 12:4.2.5-32 +- fix problem (found by Coverity) in previously add patch + +* Thu Oct 09 2014 Jiri Popelka - 12:4.2.5-31 +- dhcrelay -6 was not working due to patch for #1005814 (#1151039) + +* Wed Sep 10 2014 Jiri Popelka - 12:4.2.5-30 +- 11-dhclient: handle "dhcp4-change" and limit it to chrony/ntp (#1093490) +- [dhclient -6] infinite preferred/valid lifetime represented as -1 (#1133839) -* Wed Oct 01 2014 Jiri Popelka - 12:4.2.5-27.2 -- dhclient-script: it's OK if the arping reply comes from our system (#1148345) +* Mon Sep 08 2014 Jiri Popelka - 12:4.2.5-29 +- dhclient-script: fix stateless DHCPv6 mode (#1101149) +- Add GUIDs in the DHCP logs for IPoIB. (#1109947) +- dhclient-script: handle option 121 properly (#1109949) +- dhclient-script: it's OK if the arping reply comes from our system (#1116004) +- dhclient-script: PREINIT6: make sure link-local address is available (#1130803) +- dhclient-script: IPv6 address which fails DAD is auto-removed when it was + added with valid_lft/preferred_lft other then 'forever' (#1133465) -* Mon Jul 07 2014 Jiri Popelka - 12:4.2.5-27.1 +* Mon Jul 07 2014 Jiri Popelka - 12:4.2.5-28 - support for sending startup notification to systemd (#1087245) * Fri Jan 24 2014 Daniel Mach - 12:4.2.5-27