Репозиторий Sisyphus
Последнее обновление: 15 октября 2018 | Пакетов: 18651 | Посещений: 12366585
en ru br
Репозитории ALT
S:7.0.7-alt1
D:4.0.0-alt0.1.rc4
5.1: 4.0.15-alt4.M51.1
4.1: 3.0.17-alt4
4.0: 3.0.17-alt2.M40.1
3.0: 1.3.22pl4-alt3
+backports:3.0.17-alt3.M30
www.altlinux.org/Changes

Группа :: Система/Серверы
Пакет: dhcpcd

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: dhcpcd-7.0.7-alt1.patch
Скачать


 hooks/10-wpa_supplicant   |  9 +++++++
 hooks/15-timezone         |  3 ++-
 hooks/20-resolv.conf      | 16 ++++++++---
 hooks/29-lookup-hostname  |  3 ++-
 hooks/30-hostname         | 32 ++++++++++++----------
 hooks/50-ntp.conf         | 59 +++++++++++++++++++++-------------------
 hooks/50-yp.conf          |  5 ++--
 hooks/50-ypbind.in        | 11 +++++---
 hooks/dhcpcd-run-hooks.in | 33 +++++++++++++++--------
 iconfig.mk                |  4 +--
 src/common.h              |  1 +
 src/dhcp.c                | 20 +++++++-------
 src/dhcpcd.conf           | 29 +++++++++++++++++---
 src/if-linux.c            | 69 ++++++++++++++++++++++++++++++++++++++++++-----
 14 files changed, 207 insertions(+), 87 deletions(-)
diff --git a/hooks/10-wpa_supplicant b/hooks/10-wpa_supplicant
index 6249385..0f87eb9 100644
--- a/hooks/10-wpa_supplicant
+++ b/hooks/10-wpa_supplicant
@@ -5,6 +5,7 @@
 
 if [ -z "$wpa_supplicant_conf" ]; then
 	for x in \
+		/etc/net/ifaces/"$interface"/wpa_supplicant.conf \
 		/etc/wpa_supplicant/wpa_supplicant-"$interface".conf \
 		/etc/wpa_supplicant/wpa_supplicant.conf \
 		/etc/wpa_supplicant-"$interface".conf \
@@ -20,6 +21,8 @@ fi
 
 wpa_supplicant_ctrldir()
 {
+	local dir
+
 	dir=$(key_get_value "[[:space:]]*ctrl_interface=" \
 		"$wpa_supplicant_conf")
 	dir=$(trim "$dir")
@@ -35,6 +38,8 @@ wpa_supplicant_ctrldir()
 
 wpa_supplicant_start()
 {
+	local dir err errn
+
 	# If the carrier is up, don't bother checking anything
 	[ "$ifcarrier" = "up" ] && return 0
 
@@ -68,6 +73,8 @@ wpa_supplicant_start()
 
 wpa_supplicant_reconfigure()
 {
+	local dir err errn
+
 	dir=$(wpa_supplicant_ctrldir)
 	[ -z "$dir" ] && return 1
 	if ! wpa_cli -p "$dir" -i "$interface" status >/dev/null 2>&1; then
@@ -86,6 +93,8 @@ wpa_supplicant_reconfigure()
 
 wpa_supplicant_stop()
 {
+	local dir err errn
+
 	dir=$(wpa_supplicant_ctrldir)
 	[ -z "$dir" ] && return 1
 	wpa_cli -p "$dir" -i "$interface" status >/dev/null 2>&1 || return 0
diff --git a/hooks/15-timezone b/hooks/15-timezone
index ac04c65..0ccdc45 100644
--- a/hooks/15-timezone
+++ b/hooks/15-timezone
@@ -4,9 +4,10 @@
 
 set_zoneinfo()
 {
+	local zoneinfo_dir= zone_file=
+
 	[ -z "$new_tzdb_timezone" ] && return 0
 
-	zoneinfo_dir=
 	for d in \
 		/usr/share/zoneinfo	\
 		/usr/lib/zoneinfo	\
diff --git a/hooks/20-resolv.conf b/hooks/20-resolv.conf
index b03ab57..cda43f4 100644
--- a/hooks/20-resolv.conf
+++ b/hooks/20-resolv.conf
@@ -7,13 +7,16 @@
 # or dnsmasq. This is important as the libc resolver isn't that powerful.
 
 resolv_conf_dir="$state_dir/resolv.conf"
+uchrooted=/sbin/update_chrooted
+
 NL="
 "
 : ${resolvconf:=resolvconf}
 
 build_resolv_conf()
 {
-	cf="$state_dir/resolv.conf.$ifname"
+	local cf="$state_dir/resolv.conf.$ifname"
+	local interfaces= header= domain= search= srvs= servers= x=
 
 	# Build a list of interfaces
 	interfaces=$(list_interfaces "$resolv_conf_dir")
@@ -66,6 +69,7 @@ build_resolv_conf()
 		chmod 644 /etc/resolv.conf
 	fi
 	rm -f "$cf"
+	[ ! -x "$uchrooted" ] || "$uchrooted" conf
 }
 
 # Extract any ND DNS options from the RA
@@ -76,6 +80,7 @@ build_resolv_conf()
 # regarding DNS option lifetime in ND messages.
 eval_nd_dns()
 {
+
 	eval ltime=\$nd${i}_rdnss${j}_lifetime
 	if [ -z "$ltime" -o "$ltime" = 0 ]; then
 		rdnss=
@@ -99,8 +104,8 @@ eval_nd_dns()
 
 add_resolv_conf()
 {
-	conf="$signature$NL"
-	warn=true
+	local x= conf="$signature$NL" warn=true
+	local i j ltime rdnss dnssl new_rdnss new_dnssl
 
 	# Loop to extract the ND DNS options using our indexed shell values
 	i=1
@@ -162,7 +167,10 @@ add_resolv_conf()
 		conf="${conf}nameserver $x$NL"
 	done
 	if type "$resolvconf" >/dev/null 2>&1; then
-		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
+		# Don't use metric for resolvconf:
+		# at the time metric is not used in all cases
+		# of network interfaces configuration.
+#		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
 		printf %s "$conf" | "$resolvconf" -a "$ifname"
 		return $?
 	fi
diff --git a/hooks/29-lookup-hostname b/hooks/29-lookup-hostname
index d0b1032..38e2708 100644
--- a/hooks/29-lookup-hostname
+++ b/hooks/29-lookup-hostname
@@ -3,11 +3,12 @@
 lookup_hostname()
 {
 	[ -z "$new_ip_address" ] && return 1
+	local h=
 	# Silly ISC programs love to send error text to stdout
 	if type dig >/dev/null 2>&1; then
 		h=$(dig +short -x $new_ip_address)
 		if [ $? = 0 ]; then
-			echo "$h" | sed 's/\.$//'
+			echo "${h%.}"
 			return 0
 		fi
 	elif type host >/dev/null 2>&1; then
diff --git a/hooks/30-hostname b/hooks/30-hostname
index 5f7d26d..ff02209 100644
--- a/hooks/30-hostname
+++ b/hooks/30-hostname
@@ -22,6 +22,8 @@
 # Some systems don't have hostname(1)
 _hostname()
 {
+	local name=
+
 	if [ -z "${1+x}" ]; then
 		if type hostname >/dev/null 2>&1; then
 			hostname
@@ -53,19 +55,10 @@ _hostname()
 	fi
 }
 
-set_hostname_vars()
-{
-	hfqdn=false
-	hshort=false
-	case "$hostname_fqdn" in
-	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)	hfqdn=true;;
-	""|[Ss][Ee][Rr][Vv][Ee][Rr])		;;
-	*)					hshort=true;;
-	esac
-}
-
 need_hostname()
 {
+	local hfqdn=false hshort=false
+
 	# Always load the hostname variable for future use
 	hostname="$(_hostname)"
 	case "$hostname" in
@@ -77,7 +70,11 @@ need_hostname()
 	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1) return 0;;
 	esac
 
-	set_hostname_vars
+	case "$hostname_fqdn" in
+	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)	hfqdn=true;;
+	""|[Ss][Ee][Rr][Vv][Ee][Rr])		;;
+	*)					hshort=true;;
+	esac
 
 	if [ -n "$old_fqdn" ]; then
 		if ${hfqdn} || ! ${hsort}; then
@@ -108,6 +105,7 @@ need_hostname()
 
 try_hostname()
 {
+
 	[ "$hostname" = "$1" ] && return 0
 	if valid_domainname "$1"; then
 		syslog info "Setting hostname: $1"
@@ -119,9 +117,15 @@ try_hostname()
 
 set_hostname()
 {
-	need_hostname || return
+	local hfqdn=false hshort=false
+
+	need_hostname || return 0
 
-	set_hostname_vars
+	case "$hostname_fqdn" in
+	[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|1)	hfqdn=true;;
+	""|[Ss][Ee][Rr][Vv][Ee][Rr])		;;
+	*)					hshort=true;;
+	esac
 
 	if [ -n "$new_fqdn" ]; then
 		if ${hfqdn} || ! ${hshort}; then
diff --git a/hooks/50-ntp.conf b/hooks/50-ntp.conf
index 1217868..fe080c2 100644
--- a/hooks/50-ntp.conf
+++ b/hooks/50-ntp.conf
@@ -16,53 +16,58 @@
 # To use Chrony instead, simply change ntpd.conf to chrony.conf in the
 # above examples.
 
-: ${ntp_confs:=ntp.conf ntpd.conf chrony.conf}
-: ${ntp_conf_dirs=/etc /usr/pkg/etc /usr/local/etc}
+: ${ntp_confs:=ntpd.conf ntp.conf chrony.conf}
 ntp_conf_dir="$state_dir/ntp.conf"
+ntp_conf_server_word=
 
 # If NTP_CONF is not set, work out a good default
 if [ -z "$NTP_CONF" ]; then
-	for d in ${ntp_conf_dirs}; do
-		for f in ${ntp_confs}; do
-			if [ -e "$d/$f" ]; then
-				NTP_CONF="$d/$f"
-				break 2
-			fi
-		done
+	for f in ${ntp_confs}; do
+		if [ -e "/etc/$f" ]; then
+			NTP_CONF="/etc/$f"
+			break
+		fi
 	done
-	[ -e "$NTP_CONF" ] || NTP_CONF=/etc/ntp.conf
 fi
 
+[ -n "$NTP_CONF" -a -e "$NTP_CONF" ] || NTP_CONF=
+
 # Derive service name from configuration
 if [ -z "$ntp_service" ]; then
 	case "$NTP_CONF" in
-	*chrony.conf)		ntp_service=chronyd;;
-	*)			ntp_service=ntpd;;
+	*/chrony.conf)
+		ntp_service=chronyd
+		;;
+	*/ntpd.conf)
+		ntp_service=ntpd
+		#for openntpd will be used "servers" keyword instead "server"
+		ntp_conf_server_word="servers"
+		;;
+	*)
+		ntp_service=ntpd
+		;;
 	esac
 fi
 
-# Debian has a seperate file for DHCP config to avoid stamping on
-# the master.
-if [ "$ntp_service" = ntpd ] && type invoke-rc.d >/dev/null 2>&1; then
-	[ -e /var/lib/ntp ] || mkdir /var/lib/ntp
-	: ${ntp_service:=ntp}
-	: ${NTP_DHCP_CONF:=/var/lib/ntp/ntp.conf.dhcp}
+if [ -n "$NTP_CONF" ]; then
+	ntp_restart_cmd="/sbin/service $ntp_service condrestart"
 fi
 
-: ${ntp_restart_cmd:=service_condcommand $ntp_service restart}
-
-ntp_conf=${NTP_CONF}
 NL="
 "
 
 build_ntp_conf()
 {
-	cf="$state_dir/ntp.conf.$ifname"
+	local ntp_conf="$1"
+	local server_keyword=${2:-server}
+	local cf="$state_dir/ntp.conf.$ifname"
+	local interfaces= header= srvs= servers= x=
+
+	[ -n "$ntp_conf" -a -w "$ntp_conf" ] || return 0
 
 	# Build a list of interfaces
 	interfaces=$(list_interfaces "$ntp_conf_dir")
 
-	servers=
 	if [ -n "$interfaces" ]; then
 		# Build the header
 		for x in ${interfaces}; do
@@ -74,7 +79,7 @@ build_ntp_conf()
 			key_get_value "server " $interfaces)
 		if [ -n "$srvs" ]; then
 			for x in $(uniqify $srvs); do
-				servers="${servers}server $x$NL"
+				servers="${servers}${server_keyword} $x$NL"
 			done
 		fi
 	fi
@@ -107,7 +112,7 @@ build_ntp_conf()
 
 add_ntp_conf()
 {
-	cf="$ntp_conf_dir/$ifname"
+	local cf="$ntp_conf_dir/$ifname" x=
 
 	[ -e "$cf" ] && rm "$cf"
 	[ -d "$ntp_conf_dir" ] || mkdir -p "$ntp_conf_dir"
@@ -116,7 +121,7 @@ add_ntp_conf()
 			echo "server $x" >> "$cf"
 		done
 	fi
-	build_ntp_conf
+	build_ntp_conf "$NTP_CONF" $ntp_conf_server_word
 }
 
 remove_ntp_conf()
@@ -124,7 +129,7 @@ remove_ntp_conf()
 	if [ -e "$ntp_conf_dir/$ifname" ]; then
 		rm "$ntp_conf_dir/$ifname"
 	fi
-	build_ntp_conf
+	build_ntp_conf "$NTP_CONF" $ntp_conf_server_word
 }
 
 # For ease of use, map DHCP6 names onto our DHCP4 names
diff --git a/hooks/50-yp.conf b/hooks/50-yp.conf
index cc63d13..2da68eb 100644
--- a/hooks/50-yp.conf
+++ b/hooks/50-yp.conf
@@ -9,10 +9,9 @@ ypbind_pid()
 make_yp_conf()
 {
 	[ -z "$new_nis_domain" -a -z "$new_nis_servers" ] && return 0
-	cf=/etc/yp.conf."$ifname"
+	local cf=/etc/yp.conf."$ifname" prefix= x= pid=
 	rm -f "$cf"
 	echo "$signature" > "$cf"
-	prefix=
 	if [ -n "$new_nis_domain" ]; then
 		if ! valid_domainname "$new_nis_domain"; then
 			syslog err "Invalid NIS domain name: $new_nis_domain"
@@ -44,7 +43,7 @@ restore_yp_conf()
 {
 	[ -n "$old_nis_domain" ] && domainname ""
 	restore_conf /etc/yp.conf || return 0
-	pid="$(ypbind_pid)"
+	local pid="$(ypbind_pid)"
 	if [ -n "$pid" ]; then
 		kill -HUP "$pid"
 	fi
diff --git a/hooks/50-ypbind.in b/hooks/50-ypbind.in
index eeb3f71..a9ebbfa 100644
--- a/hooks/50-ypbind.in
+++ b/hooks/50-ypbind.in
@@ -10,6 +10,8 @@ ypbind_dir="$state_dir/ypbind"
 
 best_domain()
 {
+	local i=
+
 	for i in "$ypbind_dir/$interface_order".*; do
 		if [ -f "$i" ]; then
 			cat "$i"
@@ -27,9 +29,9 @@ make_yp_binding()
 	if [ -z "$ypdomain_dir" ]; then
 		false
 	else
-		cf="$ypdomain_dir/$new_nis_domain$ypdomain_suffix"
+		local cf="$ypdomain_dir/$new_nis_domain$ypdomain_suffix"
 		if [ -n "$new_nis_servers" ]; then
-			ncf="$cf.$ifname"
+			local ncf="$cf.$ifname" x=
 			rm -f "$ncf"
 			for x in $new_nis_servers; do
 				echo "$x" >>"$ncf"
@@ -40,7 +42,7 @@ make_yp_binding()
 		fi
 	fi
 
-	nd="$(best_domain)"
+	local nd="$(best_domain)"
 	if [ $? = 0 -a "$nd" != "$(domainname)" ]; then
 		domainname "$nd"
 		if [ -n "$ypbind_restart_cmd" ]; then
@@ -51,8 +53,9 @@ make_yp_binding()
 
 restore_yp_binding()
 {
+
 	rm -f "$ypbind_dir/$ifname"
-	nd="$(best_domain)"
+	local nd="$(best_domain)"
 	# We need to stop ypbind if there is no best domain
 	# otherwise it will just stall as we cannot set domainname
 	# to blank :/
diff --git a/hooks/dhcpcd-run-hooks.in b/hooks/dhcpcd-run-hooks.in
index 6e506da..4134508 100644
--- a/hooks/dhcpcd-run-hooks.in
+++ b/hooks/dhcpcd-run-hooks.in
@@ -10,6 +10,7 @@ signature_base_end="# End of dhcpcd"
 signature_end="$signature_base_end $from $ifname"
 state_dir=@RUNDIR@/dhcpcd
 _detected_init=false
+logger_util=logger
 
 : ${if_up:=false}
 : ${if_down:=false}
@@ -18,7 +19,7 @@ _detected_init=false
 # Ensure that all arguments are unique
 uniqify()
 {
-	result=
+	local result= i=
 	for i do
 		case " $result " in
 			*" $i "*);;
@@ -34,7 +35,7 @@ uniqify()
 # Otherwise we just use what we have.
 list_interfaces()
 {
-	ifaces=
+	local i= x= ifaces=
 	for i in $interface_order; do
 		for x in "$1"/$i.*; do
 			[ -f "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}"
@@ -49,7 +50,8 @@ list_interfaces()
 # Trim function
 trim()
 {
-	var="$*"
+	local var="$*"
+
 	var=${var#"${var%%[![:space:]]*}"}
 	var=${var%"${var##*[![:space:]]}"}
 	if [ -z "$var" ]; then
@@ -64,9 +66,9 @@ trim()
 # but sed may not always be available at the time.
 key_get_value()
 {
-	key="$1"
-	shift
+	local key="$1" value= x= line=
 
+	shift
 	if type sed >/dev/null 2>&1; then
 		sed -n "s/^$key//p" $@
 	else
@@ -84,9 +86,7 @@ key_get_value()
 # but sed may not always be available at the time.
 remove_markers()
 {
-	m1="$1"
-	m2="$2"
-	in_marker=0
+	local m1="$1" m2="$2" x= line= in_marker=0
 
 	shift; shift
 	if type sed >/dev/null 2>&1; then
@@ -107,6 +107,7 @@ remove_markers()
 # Compare two files.
 comp_file()
 {
+
 	[ -e "$1" -a -e "$2" ] || return 1
 
 	if type cmp >/dev/null 2>&1; then
@@ -167,7 +168,7 @@ restore_conf()
 # Write a syslog entry
 syslog()
 {
-	lvl="$1"
+	local lvl="$1"
 
 	if [ "$lvl" = debug ]; then
 		${syslog_debug} || return 0
@@ -186,7 +187,8 @@ syslog()
 # Check for a valid name as per RFC952 and RFC1123 section 2.1
 valid_domainname()
 {
-	name="$1"
+	local name="$1" label
+
 	[ -z "$name" -o ${#name} -gt 255 ] && return 1
 	
 	while [ -n "$name" ]; do
@@ -204,6 +206,8 @@ valid_domainname()
 
 valid_domainname_list()
 {
+	local name
+
 	for name do
 		valid_domainname "$name" || return $?
 	done
@@ -229,7 +233,7 @@ detect_init()
 	# Detect the running init system.
 	# As systemd and OpenRC can be installed on top of legacy init
 	# systems we try to detect them first.
-	status="@STATUSARG@"
+	local status="@STATUSARG@"
 	: ${status:=status}
 	if [ -x /bin/systemctl -a -S /run/systemd/private ]; then
 		_service_exists="/bin/systemctl --quiet is-enabled \$1.service"
@@ -337,6 +341,9 @@ for hook in \
 	@HOOKDIR@/* \
 	@SYSCONFDIR@/dhcpcd.exit-hook
 do
+	# Don't run *.rpm* and *~ scripts.
+	[ "${hook%.rpm*}" = "$hook" -a "${hook%\~}" = "$hook" ] || continue
+
 	for skip in $skip_hooks; do
 		case "$hook" in
 			*/*~)				continue 2;;
@@ -347,5 +354,9 @@ do
 	done
 	if [ -f "$hook" ]; then
 		. "$hook"
+		exit_status="$?"
+		if [ "$exit_status" -ne 0 ] && type $logger_util >/dev/null 2>&1; then
+			$logger_util -p daemon.err "dhcpcd-run-hooks($reason): ${hook##*/} returned non-zero exit status $exit_status"
+		fi
 	fi
 done
diff --git a/iconfig.mk b/iconfig.mk
index 465e02e..c28818b 100644
--- a/iconfig.mk
+++ b/iconfig.mk
@@ -1,7 +1,7 @@
 # Nasty hack so that make clean works without configure being run
 # Requires gmake4
 TOP?=		.
-_CONFIG_MK!=	test -e ${TOP}/config.mk && \
-		    echo config.mk || echo config-null.mk
+_CONFIG_MK:= $(shell test -e ${TOP}/config.mk && \
+		    echo config.mk || echo config-null.mk)
 CONFIG_MK?=	${_CONFIG_MK}
 include		${TOP}/${CONFIG_MK}
diff --git a/src/common.h b/src/common.h
index 3031fab..ce6cc2f 100644
--- a/src/common.h
+++ b/src/common.h
@@ -30,6 +30,7 @@
 
 #include <sys/param.h>
 #include <sys/time.h>
+#include <sys/types.h>
 #include <stdio.h>
 
 #include "config.h"
diff --git a/src/dhcp.c b/src/dhcp.c
index 83c997b..c89d889 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -36,9 +36,7 @@
 #include <netinet/in_systm.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
-#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
 #include <netinet/udp.h>
-#undef __FAVOR_BSD
 
 #include <assert.h>
 #include <ctype.h>
@@ -1039,6 +1037,8 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
 		    i < ifp->ctx->dhcp_opts_len;
 		    i++, opt++)
 		{
+			if (has_option_mask (ifo->nomask, opt->option))
+				continue;
 			if (!(opt->type & OT_REQUEST ||
 			    has_option_mask(ifo->requestmask, opt->option)))
 				continue;
@@ -1670,11 +1670,11 @@ dhcp_makeudppacket(size_t *sz, const uint8_t *data, size_t length,
 	else
 		ip->ip_dst.s_addr = dest.s_addr;
 
-	udp->uh_sport = htons(BOOTPC);
-	udp->uh_dport = htons(BOOTPS);
-	udp->uh_ulen = htons((uint16_t)(sizeof(*udp) + length));
-	ip->ip_len = udp->uh_ulen;
-	udp->uh_sum = checksum(udpp, sizeof(*ip) +  sizeof(*udp) + length);
+	udp->source = htons(BOOTPC);
+	udp->dest = htons(BOOTPS);
+	udp->len = htons((uint16_t)(sizeof(*udp) + length));
+	ip->ip_len = udp->len;
+	udp->check = checksum(udpp, sizeof(*ip) +  sizeof(*udp) + length);
 
 	ip->ip_v = IPVERSION;
 	ip->ip_hl = sizeof(*ip) >> 2;
@@ -3310,12 +3310,12 @@ valid_udp_packet(void *data, size_t data_len, struct in_addr *from,
 		/* This does scribble on the packet, but at this point
 		 * we don't care to keep it. */
 		iplen = p->ip.ip_len;
-		udpsum = p->udp.uh_sum;
-		p->udp.uh_sum = 0;
+		udpsum = p->udp.check;
+		p->udp.check = 0;
 		p->ip.ip_hl = 0;
 		p->ip.ip_v = 0;
 		p->ip.ip_tos = 0;
-		p->ip.ip_len = p->udp.uh_ulen;
+		p->ip.ip_len = p->udp.len;
 		p->ip.ip_id = 0;
 		p->ip.ip_off = 0;
 		p->ip.ip_ttl = 0;
diff --git a/src/dhcpcd.conf b/src/dhcpcd.conf
index 537ed77..a90c721 100644
--- a/src/dhcpcd.conf
+++ b/src/dhcpcd.conf
@@ -7,16 +7,19 @@
 # Inform the DHCP server of our hostname for DDNS.
 hostname
 
-# Use the hardware address of the interface for the Client ID.
+# To share the DHCP lease across OSX and Windows a ClientID is needed.
+# Enabling this may get a different lease than the kernel DHCP client.
+# Some upstream DHCP servers may also require a ClientID, such as FRITZ!Box.
+# Use the hardware address of the interface for the Client ID (default).
 #clientid
 # or
 # Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
 # Some non-RFC compliant DHCP servers do not reply with this set.
 # In this case, comment out duid and enable clientid above.
-duid
+#duid
 
 # Persist interface configuration when dhcpcd exits.
-persistent
+#persistent
 
 # Rapid commit support.
 # Safe to enable by default because it requires the equivalent option set
@@ -30,7 +33,7 @@ option classless_static_routes
 option interface_mtu
 
 # Most distributions have NTP support.
-#option ntp_servers
+option ntp_servers
 
 # A ServerID is required by RFC2131.
 require dhcp_server_identifier
@@ -39,3 +42,21 @@ require dhcp_server_identifier
 #slaac hwaddr
 # OR generate Stable Private IPv6 Addresses based from the DUID
 slaac private
+
+# A hook script is provided to lookup the hostname if not set by the DHCP
+# server, but it should not be run by default.
+nohook lookup-hostname
+
+# Don't attempt to obtain an IPv4LL address if we failed to get one via DHCP.
+noipv4ll
+
+# Don't send any ARP requests.
+noarp
+
+# Don't attmept to configure an IPv6 address.
+noipv6
+
+# Force the sending of the short hostname.
+# So DDNS will always work, even if the hostname domain is different
+# from the DHCP servers.
+hostname_short
diff --git a/src/if-linux.c b/src/if-linux.c
index abd4cd5..e5af4b0 100644
--- a/src/if-linux.c
+++ b/src/if-linux.c
@@ -31,6 +31,7 @@
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/param.h>
+#include <sys/utsname.h>
 
 #include <linux/if_addr.h>
 #include <linux/if_link.h>
@@ -339,6 +340,61 @@ if_closesockets_os(struct dhcpcd_ctx *ctx)
 	}
 }
 
+#if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
+/*
+ * This function from glibc_preinstall originally.
+ * Permission to use under 2-clause BSD license is granted by ldv@.
+ */
+static int
+parse_release(const char *p)
+{
+    unsigned int i, osversion = 0;
+
+    for (i = 0; i < 3 && *p; i++, ++p)
+    {
+        unsigned int d = 0;
+        const char *p0 = p;
+
+        for (;*p >= '0' && *p <= '9'; ++p)
+            d = d * 10 + (*p - '0');
+
+        if ((d == 0 && p == p0) || d >= 255 || (i < 2 && *p && *p != '.')) {
+            osversion = 0;
+            break;
+        }
+        osversion |= d << (16 - 8 * i);
+
+        if (!*p)
+            break;
+    }
+    return osversion;
+}
+
+static bool
+can_ifa_flags(void)
+{
+	static int can = -1;
+    struct utsname name;
+
+	if (can >= 0)
+		return can > 0;
+
+	can = 0;
+
+    if (uname(&name) < 0) {
+		logwarn("Can't get kernel version, netlink's IFA_FLAGS are disabled");
+		return false;
+	}
+
+    if (parse_release(name.release) < parse_release("3.14.0"))
+		logdebugx("This kernel is too old, netlink's IFA_FLAGS are disabled");
+	else
+		can = 1;
+
+	return can > 0;
+}
+#endif /*IFA_F_NOPREFIXROUTE || IFA_F_MANAGETEMPADDR */
+
 static int
 get_netlink(struct dhcpcd_ctx *ctx, struct iovec *iov,
     struct interface *ifp, int fd, int flags,
@@ -1472,7 +1528,7 @@ if_address(unsigned char cmd, const struct ipv4_addr *addr)
 		    &addr->brd.s_addr, sizeof(addr->brd.s_addr));
 
 #ifdef IFA_F_NOPREFIXROUTE
-	if (nlm.ifa.ifa_prefixlen < 32)
+	if (nlm.ifa.ifa_prefixlen < 32 && can_ifa_flags())
 		flags |= IFA_F_NOPREFIXROUTE;
 	if (flags)
 		add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
@@ -1518,13 +1574,14 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 	if (ia->flags & IPV6_AF_TEMPORARY) {
 		/* Currently the kernel filters out these flags */
 #ifdef IFA_F_NOPREFIXROUTE
-		flags |= IFA_F_TEMPORARY;
-#else
-		nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
+		if (can_ifa_flags())
+			flags |= IFA_F_TEMPORARY;
+		else
 #endif
+			nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
 	}
 #elif IFA_F_MANAGETEMPADDR
-	if (ia->flags & IPV6_AF_AUTOCONF)
+	if (ia->flags & IPV6_AF_AUTOCONF && can_ifa_flags())
 		flags |= IFA_F_MANAGETEMPADDR;
 #endif
 
@@ -1547,7 +1604,7 @@ if_address6(unsigned char cmd, const struct ipv6_addr *ia)
 	}
 
 #ifdef IFA_F_NOPREFIXROUTE
-	if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr))
+	if (!IN6_IS_ADDR_LINKLOCAL(&ia->addr) && can_ifa_flags())
 		flags |= IFA_F_NOPREFIXROUTE;
 #endif
 #if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin