diff --git a/server/dhcp/actions.py b/server/dhcp/actions.py
new file mode 100644
index 0000000000..9ef28f7b1a
--- /dev/null
+++ b/server/dhcp/actions.py
@@ -0,0 +1,70 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Licensed under the GNU General Public License, version 3.
+# See the file http://www.gnu.org/licenses/gpl.txt
+
+from pisi.actionsapi import autotools
+from pisi.actionsapi import pisitools
+from pisi.actionsapi import shelltools
+from pisi.actionsapi import get
+
+def setup():
+ shelltools.export("CFLAGS", "%s -D_GNU_SOURCE -fPIC" % get.CFLAGS())
+#in some troff man pages
+ #for i in ["dhclient.conf.5", "dhclient.leases.5", "dhclient-script.8", "dhclient.8"]:
+ # pisitools.dosed("client/%s" % i, "CLIENTBINDIR", "/sbin")
+ # pisitools.dosed("client/%s" % i, "RUNDIR", "/run")
+ # pisitools.dosed("client/%s" % i, "DBDIR", "/var/lib/dhcpd")
+ # pisitools.dosed("client/%s" % i, "ETCDIR", "/etc/dhcp")
+
+ #for i in ["dhcpd.conf.5", "dhcpd.leases.5", "dhcpd.8"]:
+ # pisitools.dosed("server/%s" % i, "CLIENTBINDIR", "/sbin")
+ # pisitools.dosed("server/%s" % i, "RUNDIR", "/run")
+ # pisitools.dosed("server/%s" % i, "DBDIR", "/var/lib/dhcpd")
+ # pisitools.dosed("server/%s" % i, "ETCDIR", "/etc/dhcp")
+
+ pisitools.dosed("client/scripts/linux", "/etc/dhclient-exit-hooks", "/etc/dhcp/dhclient-exit-hooks")
+ pisitools.dosed("client/scripts/linux", "/etc/dhclient-enter-hooks", "/etc/dhcp/dhclient-enter-hooks")
+
+ autotools.autoreconf("-vfi")
+ autotools.configure("--with-srv-lease-file=/var/lib/dhcpd/dhcpd.leases \
+ --with-srv6-lease-file=/var/lib/dhcpd/dhcpd6.leases \
+ --with-cli-lease-file=/var/lib/dhclient/dhclient.leases \
+ --with-cli6-lease-file=/var/lib/dhclient/dhclient6.leases \
+ --with-srv-pid-file=/run/dhcpd.pid \
+ --with-srv6-pid-file=/run/dhcpd6.pid \
+ --with-cli-pid-file=/run/dhclient.pid \
+ --with-cli6-pid-file=/run/dhclient6.pid \
+ --with-relay-pid-file=/run/dhcrelay.pid \
+ --with-ldap \
+ --with-ldapcrypto")
+
+def build():
+ autotools.make()
+
+def install():
+ autotools.rawInstall("DESTDIR=%s" % get.installDIR())
+
+ # Remove files we don't want
+ pisitools.remove("/etc/dhcpd.conf.example")
+ pisitools.remove("/etc/dhclient.conf.example")
+
+ # Install dhcp.schema for LDAP configuration
+ pisitools.insinto("/etc/openldap/schema", "contrib/ldap/dhcp.schema")
+
+ # dhclient configuration per service support is not ready yet, no need to create this directory for now
+ # Install empty directory for dhclient.d scripts
+ #pisitools.dodir("/etc/dhcp/dhclient.d")
+
+ # Create directory hierarchy in /var
+ pisitools.dodir("/var/lib/dhcpd")
+ pisitools.dodir("/var/lib/dhclient")
+
+ # Sample configuration files
+ pisitools.insinto("/usr/share/doc/dhcp", "client/dhclient.conf.5", "dhclient.conf.exsample")
+ pisitools.insinto("/usr/share/doc/dhcp", "server/dhcpd.conf.5", "dhcpd.conf.example")
+ pisitools.insinto("/usr/share/doc/dhcp", "doc/examples/dhclient-dhcpv6.conf")
+ pisitools.insinto("/usr/share/doc/dhcp", "doc/examples/dhcpd-dhcpv6.conf")
+
+ pisitools.dodoc("LICENSE", "README", "RELNOTES")
diff --git a/server/dhcp/comar/dhcpd.py b/server/dhcp/comar/dhcpd.py
new file mode 100644
index 0000000000..d1d7b9e59e
--- /dev/null
+++ b/server/dhcp/comar/dhcpd.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+from comar.service import *
+
+serviceType = "server"
+serviceDesc = _({"en": "DHCP Daemon",
+ "tr": "DHCP Servisi"})
+
+serviceConf = "dhcpd"
+
+MSG_NM_NOT_RUNNING = _({"en": "NetworkManager service is not running",
+ "tr": "NetworkManager hizmeti çalışmıyor",
+ })
+
+PIDFILE = "/run/dhcpd.pid"
+TIMEOUT = config.get("TIMEOUT", 10)
+
+@synchronized
+def start():
+ try:
+ startDependencies("NetworkManager")
+ # Prevent race condition between NM and dhcpd
+ if run("/usr/bin/nm-online -q -t %s" % TIMEOUT) != 0:
+ # NM is not running
+ fail(MSG_NM_NOT_RUNNING)
+ except:
+ pass
+
+ startService(command="/usr/sbin/dhcpd",
+ args="-cf %s %s %s" % (config.get("DHCPD_CONF", "/etc/dhcp/dhcpd.conf"), config.get("DHCPD_ARGS", ""), config.get("INTERFACES", "")),
+ pidfile=PIDFILE,
+ donotify=True)
+
+@synchronized
+def stop():
+ stopService(pidfile=PIDFILE,
+ donotify=True)
+
+def status():
+ return isServiceRunning(PIDFILE)
diff --git a/server/dhcp/comar/dhcpd6.py b/server/dhcp/comar/dhcpd6.py
new file mode 100644
index 0000000000..9dee3b6cf3
--- /dev/null
+++ b/server/dhcp/comar/dhcpd6.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+from comar.service import *
+
+serviceType = "server"
+serviceDesc = _({"en": "DHCPv6 Daemon",
+ "tr": "DHCPv6 Servisi"})
+
+serviceConf = "dhcpd6"
+
+MSG_NM_NOT_RUNNING = _({"en": "NetworkManager service is not running",
+ "tr": "NetworkManager hizmeti çalışmıyor",
+ })
+
+PIDFILE = "/run/dhcpd6.pid"
+TIMEOUT = config.get("TIMEOUT", 10)
+
+@synchronized
+def start():
+ try:
+ startDependencies("NetworkManager")
+ # Prevent race condition between NM and dhcpd
+ if run("/usr/bin/nm-online -q -t %s" % TIMEOUT) != 0:
+ # NM is not running
+ fail(MSG_NM_NOT_RUNNING)
+ except:
+ pass
+
+ startService(command="/usr/sbin/dhcpd",
+ args="-6 -cf %s %s %s" % (config.get("DHCPD_CONF", "/etc/dhcp/dhcpd.conf"), config.get("DHCPD_ARGS", ""), config.get("INTERFACES", "")),
+ pidfile=PIDFILE,
+ donotify=True)
+
+@synchronized
+def stop():
+ stopService(pidfile=PIDFILE,
+ donotify=True)
+
+def status():
+ return isServiceRunning(PIDFILE)
diff --git a/server/dhcp/comar/dhcrelay.py b/server/dhcp/comar/dhcrelay.py
new file mode 100644
index 0000000000..2c7a246b3c
--- /dev/null
+++ b/server/dhcp/comar/dhcrelay.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+from comar.service import *
+
+serviceType = "server"
+serviceDesc = _({"en": "DHCP Relay Server",
+ "tr": "DHCP Relay Servisi"})
+serviceConf = "dhcrelay"
+
+pidfile = "/run/dhcrelay.pid"
+
+@synchronized
+def start():
+ startService(command="/usr/sbin/dhcrelay",
+ args="%s %s" % (config.get("DHCPD_ARGS", ""), config.get("INTERFACES", "")),
+ donotify=True)
+
+@synchronized
+def stop():
+ stopService(command="/usr/sbin/dhcpd",
+ pidfile=pidfile,
+ donotify=True)
+
+def status():
+ return isServiceRunning(pidfile)
diff --git a/server/dhcp/comar/package.py b/server/dhcp/comar/package.py
new file mode 100644
index 0000000000..d7ab76d36c
--- /dev/null
+++ b/server/dhcp/comar/package.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+import os
+
+def postInstall(fromVersion, fromRelease, toVersion, toRelease):
+ if not os.path.exists("/var/lib/dhcpd/dhcpd.leases"):
+ os.system("/bin/touch /var/lib/dhcpd/dhcpd.leases")
+
+ if not os.path.exists("/var/lib/dhcpd/dhcpd6.leases"):
+ os.system("/bin/touch /var/lib/dhcpd/dhcpd6.leases")
+
diff --git a/server/dhcp/files/11-dhclient b/server/dhcp/files/11-dhclient
new file mode 100644
index 0000000000..5842f8287c
--- /dev/null
+++ b/server/dhcp/files/11-dhclient
@@ -0,0 +1,37 @@
+#!/bin/bash
+# run dhclient.d scripts in an emulated environment
+
+PATH=/bin:/usr/bin:/sbin
+SAVEDIR=/var/lib/dhclient
+ETCDIR=/etc/dhcp
+interface=$1
+
+eval "$(
+declare | LC_ALL=C grep '^DHCP4_[A-Z_]*=' | while read opt; do
+ optname=${opt%%=*}
+ optname=${optname,,}
+ optname=new_${optname#dhcp4_}
+ optvalue=${opt#*=}
+ echo "$optname=$optvalue"
+done
+)"
+
+[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network
+
+[ -f /etc/sysconfig/network-scripts/ifcfg-$interface ] && \
+ . /etc/sysconfig/network-scripts/ifcfg-$interface
+
+if [ -d $ETCDIR/dhclient.d ]; then
+ for f in $ETCDIR/dhclient.d/*.sh; do
+ if [ -x $f ]; then
+ subsystem="${f%.sh}"
+ subsystem="${subsystem##*/}"
+ . ${f}
+ if [ "$2" = "up" ]; then
+ "${subsystem}_config"
+ elif [ "$2" = "down" ]; then
+ "${subsystem}_restore"
+ fi
+ fi
+ done
+fi
diff --git a/server/dhcp/files/12-dhcpd b/server/dhcp/files/12-dhcpd
new file mode 100644
index 0000000000..a48da320da
--- /dev/null
+++ b/server/dhcp/files/12-dhcpd
@@ -0,0 +1,21 @@
+#!/bin/bash
+export LC_ALL=C
+
+[ -f /etc/sysconfig/dhcpd ] && . /etc/sysconfig/dhcpd
+
+# restart dhcpd whenever $1 interface is brought up by NM (rhbz #565921)
+if [ "$2" = "up" ]; then
+ # exit if the service is not configured to be started in the current runlevel
+ /sbin/chkconfig dhcpd || exit 0
+
+ # exit if dhcpd is not defined to listen on $1
+ # i.e. if there are interfaces defined in DHCPDARGS and $1 is not among them
+ if [ -n "${DHCPDARGS}" ] &&
+ [[ "${DHCPDARGS}" == *eth* ]] &&
+ [[ "${DHCPDARGS}" != *$1* ]]; then
+ exit 0
+ fi
+
+ # restart service
+ /sbin/service dhcpd restart || :
+fi
diff --git a/server/dhcp/files/56dhclient b/server/dhcp/files/56dhclient
new file mode 100644
index 0000000000..25d14db205
--- /dev/null
+++ b/server/dhcp/files/56dhclient
@@ -0,0 +1,61 @@
+#!/bin/sh
+# If we are running dhclient, shutdown running instances cleanly and
+# bring them back up on resume.
+
+. "${PM_FUNCTIONS}"
+
+PM_DHCLIENT_RUNDIR="${PM_UTILS_RUNDIR}/network"
+PM_DHCLIENT_SUSPEND="${PM_DHCLIENT_RUNDIR}/dhclient.suspend"
+
+suspend_dhclient() {
+ [ ! -d /etc/sysconfig/network-scripts ] && return
+ [ ! -x /sbin/ifdown ] && return
+
+ [ ! -d ${PM_DHCLIENT_RUNDIR} ] && /bin/mkdir -p ${PM_DHCLIENT_RUNDIR}
+ [ -f ${PM_DHCLIENT_SUSPEND} ] && /bin/rm -f ${PM_DHCLIENT_SUSPEND}
+
+ cd /etc/sysconfig/network-scripts
+ for ifcfg in ifcfg-* ; do
+ # Clear relevant parameters set by previous interface
+ # (lo doesn't set them)
+ NM_CONTROLLED=
+ BOOTPROTO=
+
+ . ./${ifcfg}
+
+ if [ "${NM_CONTROLLED}" = "no" ] || [ "${NM_CONTROLLED}" = "n" ] || [ "${NM_CONTROLLED}" = "false" ]; then
+ if [ "${BOOTPROTO}" = "bootp" ] || [ "${BOOTPROTO}" = "dhcp" ] || [ -z "${BOOTPROTO}" ]; then
+ # device is not NetworkManager controlled and uses dhcp,
+ # now see if it's actually up at the moment
+ /sbin/ip link show ${DEVICE} | /bin/grep -qE "state (UP|UNKNOWN)" >/dev/null 2>&1
+ if [ $? -eq 0 ]; then
+ echo "${DEVICE}" >> ${PM_DHCLIENT_SUSPEND}
+ /sbin/ifdown ${DEVICE}
+ fi
+ fi
+ fi
+ done
+}
+
+resume_dhclient() {
+ [ ! -f ${PM_DHCLIENT_SUSPEND} ] && return
+ [ ! -x /sbin/ifup ] && return
+
+ cd /etc/sysconfig/network-scripts
+ while read device ; do
+ /sbin/ifup ${device}
+ done < ${PM_DHCLIENT_SUSPEND}
+
+ /bin/rm -f ${PM_DHCLIENT_SUSPEND}
+}
+
+case "$1" in
+ hibernate|suspend)
+ suspend_dhclient
+ ;;
+ thaw|resume)
+ resume_dhclient
+ ;;
+ *) exit $NA
+ ;;
+esac
diff --git a/server/dhcp/files/dhclient-script b/server/dhcp/files/dhclient-script
new file mode 100644
index 0000000000..9290d91a9a
--- /dev/null
+++ b/server/dhcp/files/dhclient-script
@@ -0,0 +1,754 @@
+#!/bin/bash
+#
+# dhclient-script: Network interface configuration script run by
+# dhclient based on DHCP client communication
+#
+# Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
+#
+# 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
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+# Author(s): David Cantrell
+#
+# ----------
+# This script is a rewrite/reworking on dhclient-script originally
+# included as part of dhcp-970306:
+# dhclient-script for Linux. Dan Halbert, March, 1997.
+# Updated for Linux 2.[12] by Brian J. Murrell, January 1999.
+# Modified by David Cantrell for Fedora and RHEL
+# ----------
+#
+
+PATH=/bin:/usr/bin:/sbin
+SAVEDIR=/var/lib/dhclient
+
+LOGFACILITY="local7"
+LOGLEVEL="notice"
+
+ETCDIR="/etc/dhcp"
+
+logmessage() {
+ msg="${1}"
+ logger -p ${LOGFACILITY}.${LOGLEVEL} -t "NET" "dhclient: ${msg}"
+}
+
+fix_context() {
+ if [ -x /sbin/restorecon ]; then
+ /sbin/restorecon ${1} >/dev/null 2>&1
+ fi
+}
+
+save_previous() {
+ origfile="${1}"
+ savefile="${SAVEDIR}/${origfile##*/}.predhclient.${interface}"
+
+ if [ ! -d ${SAVEDIR} ]; then
+ mkdir -p ${SAVEDIR}
+ fi
+
+ if [ -e ${origfile} ]; then
+ contents="$(< ${origfile})"
+ echo "${contents}" > ${savefile}
+ rm -f ${origfile}
+ else
+ echo > ${savefile}
+ fi
+
+ fix_context ${savefile}
+}
+
+make_resolv_conf() {
+ [ "${PEERDNS}" = "no" ] && return
+
+ if [ "${reason}" = "RENEW" ] &&
+ [ "${new_domain_name}" = "${old_domain_name}" ] &&
+ [ "${new_domain_name_servers}" = "${old_domain_name_servers}" ]; then
+ return
+ fi
+
+ if [ -n "${new_domain_name}" ] ||
+ [ -n "${new_domain_name_servers}" ] ||
+ [ -n "${new_domain_search}" ]; then
+ save_previous /etc/resolv.conf
+ rscf="$(mktemp /tmp/XXXXXX)"
+ echo "; generated by /sbin/dhclient-script" > ${rscf}
+
+ if [ -n "${SEARCH}" ]; then
+ echo "search ${SEARCH}" >> $rscf
+ else
+ if [ -n "${new_domain_search}" ]; then
+ echo "search ${new_domain_search//\\032/ }" >> ${rscf}
+ elif [ -n "${new_domain_name}" ]; then
+ # Note that the DHCP 'Domain Name Option' is really just a domain
+ # name, and that this practice of using the domain name option as
+ # a search path is both nonstandard and deprecated.
+ echo "search ${new_domain_name//\\032/ }" >> ${rscf}
+ fi
+ fi
+
+ if [ -n "${RES_OPTIONS}" ]; then
+ echo "options ${RES_OPTIONS}" >> ${rscf}
+ fi
+
+ for nameserver in ${new_domain_name_servers} ; do
+ echo "nameserver ${nameserver}" >> ${rscf}
+ done
+
+ change_resolv_conf ${rscf}
+ rm -f ${rscf}
+
+ fix_context /etc/resolv.conf
+ elif [ -n "${new_dhcp6_name_servers}" ] ||
+ [ -n "${new_dhcp6_domain_search}" ]; then
+ save_previous /etc/resolv.conf
+ rscf="$(mktemp /tmp/XXXXXX)"
+ echo "; generated by /sbin/dhclient-script" > ${rscf}
+
+ if [ -n "${SEARCH}" ]; then
+ echo "search ${SEARCH}" >> $rscf
+ else
+ if [ -n "${new_dhcp6_domain_search}" ]; then
+ echo "search ${new_dhcp6_domain_search//\\032/ }" >> ${rscf}
+ fi
+ fi
+
+ if [ -n "${RES_OPTIONS}" ]; then
+ echo "options ${RES_OPTIONS}" >> ${rscf}
+ fi
+
+ for nameserver in ${new_dhcp6_name_servers} ; do
+ echo "nameserver ${nameserver}" >> ${rscf}
+ done
+
+ change_resolv_conf ${rscf}
+ rm -f ${rscf}
+
+ fix_context /etc/resolv.conf
+ fi
+}
+
+exit_with_hooks() {
+ exit_status="${1}"
+
+ if [ -x ${ETCDIR}/dhclient-exit-hooks ]; then
+ . ${ETCDIR}/dhclient-exit-hooks
+ fi
+
+ exit ${exit_status}
+}
+
+quad2num() {
+ if [ $# -eq 4 ]; then
+ let n="${1} << 24 | ${2} << 16 | ${3} << 8 | ${4}"
+ echo "${n}"
+ return 0
+ else
+ echo "0"
+ return 1
+ fi
+}
+
+ip2num() {
+ IFS="." quad2num ${1}
+}
+
+num2ip() {
+ let n="${1}"
+ let o1="(n >> 24) & 0xff"
+ let o2="(n >> 16) & 0xff"
+ let o3="(n >> 8) & 0xff"
+ let o4="n & 0xff"
+ echo "${o1}.${o2}.${o3}.${o4}"
+}
+
+get_network_address() {
+# get network address for the given IP address and (netmask or prefix)
+ ip="${1}"
+ nm="${2}"
+
+ if [ -n "${ip}" -a -n "${nm}" ]; then
+ if [[ "${nm}" = *.* ]]; then
+ ipcalc -s -n ${ip} ${nm} | cut -d '=' -f 2
+ else
+ ipcalc -s -n ${ip}/${nm} | cut -d '=' -f 2
+ fi
+ fi
+}
+
+get_prefix() {
+# get prefix for the given IP address and mask
+ ip="${1}"
+ nm="${2}"
+
+ if [ -n "${ip}" -a -n "${nm}" ]; then
+ ipcalc -s -p ${ip} ${nm} | cut -d '=' -f 2
+ fi
+}
+
+class_bits() {
+ let ip=$(IFS='.' ip2num $1)
+ let bits=32
+ let mask='255'
+ for ((i=0; i <= 3; i++, 'mask<<=8')); do
+ let v='ip&mask'
+ if [ "$v" -eq 0 ] ; then
+ let bits-=8
+ else
+ break
+ fi
+ done
+ echo $bits
+}
+
+is_router_reachable() {
+ # handle DHCP servers that give us a router not on our subnet
+ router="${1}"
+ routersubnet="$(get_network_address ${router} ${new_subnet_mask})"
+ mysubnet="$(get_network_address ${new_ip_address} ${new_subnet_mask})"
+ unreachable=0
+
+ if [ ! "${routersubnet}" = "${mysubnet}" ]; then
+ unreachable=1
+ if arping -f -q -I ${interface} -w2 ${router}; then
+ ip -4 route add ${router}/32 dev ${interface}
+ if [ $? -eq 0 ]; then
+ unreachable=0
+ else
+ logmessage "failed to create host router for unreachable router ${router} not on subnet ${mysubnet}"
+ fi
+ else
+ unreachable=1
+ logmessage "DHCP router ${router} is unreachable on DHCP subnet ${mysubnet} router subnet ${routersubnet}"
+ fi
+ fi
+
+ return ${unreachable}
+}
+
+add_default_gateway() {
+ router="${1}"
+ metric=""
+
+ if [ $# -gt 1 ] && [ ${2} -gt 0 ]; then
+ metric="metric ${2}"
+ fi
+
+ if is_router_reachable ${router} ; then
+ ip -4 route replace default via ${router} dev ${interface} ${metric}
+ if [ $? -ne 0 ]; then
+ logmessage "failed to create default route: ${router} dev ${interface} ${metric}"
+ return 1
+ else
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+dhconfig() {
+ if [ -n "${old_ip_address}" ] && [ -n "${alias_ip_address}" ] &&
+ [ ! "${alias_ip_address}" = "${old_ip_address}" ]; then
+ # possible new alias, remove old alias first
+ ip -4 addr del ${old_ip_address} dev ${interface}:0
+ fi
+
+ if [ -n "${old_ip_address}" ] &&
+ [ ! "${old_ip_address}" = "${new_ip_address}" ]; then
+ # IP address changed. Bringing down the interface will delete all
+ # routes, and clear the ARP cache.
+ ip -4 addr flush dev ${interface} >/dev/null 2>&1
+ fi
+
+ if [ "${reason}" = "BOUND" ] || [ "${reason}" = "REBOOT" ] ||
+ [ ! "${old_ip_address}" = "${new_ip_address}" ] ||
+ [ ! "${old_subnet_mask}" = "${new_subnet_mask}" ] ||
+ [ ! "${old_network_number}" = "${new_network_number}" ] ||
+ [ ! "${old_broadcast_address}" = "${new_broadcast_address}" ] ||
+ [ ! "${old_routers}" = "${new_routers}" ] ||
+ [ ! "${old_interface_mtu}" = "${new_interface_mtu}" ]; then
+ ip -4 addr add ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface}
+ ip link set dev ${interface} up
+
+ # The 576 MTU is only used for X.25 and dialup connections
+ # where the admin wants low latency. Such a low MTU can cause
+ # problems with UDP traffic, among other things. As such,
+ # disallow MTUs from 576 and below by default, so that broken
+ # MTUs are ignored, but higher stuff is allowed (1492, 1500, etc).
+ if [ -n "${new_interface_mtu}" ] && [ ${new_interface_mtu} -gt 576 ]; then
+ ip link set ${interface} mtu ${new_interface_mtu}
+ fi
+
+ if [ -x ${ETCDIR}/dhclient-${interface}-up-hooks ]; then
+ . ${ETCDIR}/dhclient-${interface}-up-hooks
+ elif [ -x ${ETCDIR}/dhclient-up-hooks ]; then
+ . ${ETCDIR}/dhclient-up-hooks
+ fi
+
+ # static routes
+ if [ -n "${new_classless_static_routes}" ] ||
+ [ -n "${new_static_routes}" ]; then
+ if [ -n "${new_classless_static_routes}" ]; then
+ IFS=', |' static_routes=(${new_classless_static_routes})
+
+ # If the DHCP server returns both a Classless Static Routes option and
+ # a Router option, the DHCP client MUST ignore the Router option. (RFC3442)
+ new_routers=""
+ else
+ IFS=', |' static_routes=(${new_static_routes})
+ fi
+ route_targets=()
+
+ for((i=0; i<${#static_routes[@]}; i+=2)); do
+ target=${static_routes[$i]}
+ if [ -n "${new_classless_static_routes}" ]; then
+ prefix=$(echo ${target} | cut -d "." -f 1)
+ target=$(echo ${target} | cut -d "." -f 2-)
+ IFS="." target_arr=(${target})
+ unset IFS
+ ((pads=4-${#target_arr[@]}))
+ for j in $(seq $pads); do
+ target=${target}".0"
+ done
+
+ # Client MUST zero any bits in the subnet number where the corresponding bit in the mask is zero.
+ # In other words, the subnet number installed in the routing table is the logical AND of
+ # the subnet number and subnet mask given in the Classless Static Routes option. (RFC3442)
+ target="$(get_network_address ${target} ${prefix})"
+ else
+ prefix=$(class_bits ${target})
+ fi
+ gateway=${static_routes[$i+1]}
+
+ metric=''
+ for t in ${route_targets[@]}; do
+ if [ ${t} = ${target} ]; then
+ if [ -z "${metric}" ]; then
+ metric=1
+ else
+ ((metric=metric+1))
+ fi
+ fi
+ done
+
+ if [ -n "${metric}" ]; then
+ metric="metric ${metric}"
+ fi
+
+ if is_router_reachable ${gateway}; then
+ ip -4 route replace ${target}/${prefix} via ${gateway} dev ${interface} ${metric}
+
+ if [ $? -ne 0 ]; then
+ logmessage "failed to create static route: ${target}/${prefix} via ${gateway} dev ${interface} ${metric}"
+ else
+ route_targets=(${route_targets[@]} ${target})
+ fi
+ fi
+ done
+ fi
+
+ # gateways
+ if [[ ( "${DEFROUTE}" != "no") &&
+ (( -z "${GATEWAYDEV}" ) ||
+ ( "${GATEWAYDEV}" = "${interface}" )) ]]; then
+ if [[ ( -z "$GATEWAY" ) ||
+ (( -n "$DHCLIENT_IGNORE_GATEWAY" ) &&
+ ( "$DHCLIENT_IGNORE_GATEWAY" = [Yy]* )) ]]; then
+ metric="${METRIC:-}"
+ let i="${METRIC:-0}"
+ default_routers=()
+
+ for router in ${new_routers} ; do
+ added_router=-
+
+ for r in ${default_routers[@]} ; do
+ if [ "${r}" = "${router}" ]; then
+ added_router=1
+ fi
+ done
+
+ if [ -z "${router}" ] ||
+ [ "${added_router}" = "1" ] ||
+ [ $(IFS=. ip2num ${router}) -le 0 ] ||
+ [[ ( "${router}" = "${new_broadcast_address}" ) &&
+ ( "${new_subnet_mask}" != "255.255.255.255" ) ]]; then
+ continue
+ fi
+
+ default_routers=(${default_routers[@]} ${router})
+ add_default_gateway ${router} ${metric}
+ let i=i+1
+ metric=${i}
+ done
+ elif [ -n "${GATEWAY}" ]; then
+ routersubnet=$(get_network_address ${GATEWAY} ${new_subnet_mask})
+ mysubnet=$(get_network_address ${new_ip_address} ${new_subnet_mask})
+
+ if [ "${routersubnet}" = "${mysubnet}" ]; then
+ ip -4 route replace default via ${GATEWAY} dev ${interface}
+ fi
+ fi
+ fi
+
+ fi
+
+ if [ ! "${new_ip_address}" = "${alias_ip_address}" ] &&
+ [ -n "${alias_ip_address}" ]; then
+ ip -4 addr flush dev ${interface}:0 >/dev/null 2>&1
+ ip -4 addr add ${alias_ip_address}/${alias_prefix} dev ${interface}:0
+ ip -4 route replace ${alias_ip_address}/32 dev ${interface}:0
+ fi
+
+ make_resolv_conf
+
+ if [ -n "${new_host_name}" ] && need_hostname; then
+ hostname ${new_host_name} || echo "See -nc option in dhclient(8) man page."
+ fi
+
+ if [ -n "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" ] &&
+ [[ "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ]]; then
+ if [ -n "${new_time_offset}" ]; then
+ # DHCP option "time-offset" is requested by default and should be
+ # handled. The geographical zone abbreviation cannot be determined
+ # from the GMT offset, but the $ZONEINFO/Etc/GMT$offset file can be
+ # used - note: this disables DST.
+ ((z=new_time_offset/3600))
+ ((hoursWest=$(printf '%+d' $z)))
+
+ if (( $hoursWest < 0 )); then
+ # tzdata treats negative 'hours west' as positive 'gmtoff'!
+ ((hoursWest*=-1))
+ fi
+
+ tzfile=/usr/share/zoneinfo/Etc/GMT$(printf '%+d' ${hoursWest})
+ if [ -e ${tzfile} ]; then
+ save_previous /etc/localtime
+ cp -fp ${tzfile} /etc/localtime
+ touch /etc/localtime
+ fix_context /etc/localtime
+ fi
+ fi
+ fi
+
+ # execute any additional client side configuration scripts we have
+ if [ -d ${ETCDIR}/dhclient.d ]; then
+ for f in ${ETCDIR}/dhclient.d/*.sh ; do
+ if [ -x ${f} ]; then
+ subsystem="${f%.sh}"
+ subsystem="${subsystem##*/}"
+ . ${f}
+ "${subsystem}_config"
+ fi
+ done
+ fi
+}
+
+# Section 18.1.8. (Receipt of Reply Messages) of RFC 3315 says:
+# The client SHOULD perform duplicate address detection on each of
+# the addresses in any IAs it receives in the Reply message before
+# using that address for traffic.
+add_ipv6_addr_with_DAD() {
+ ip -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \
+ dev ${interface} scope global
+
+ # repeatedly test whether newly added address passed
+ # duplicate address detection (DAD)
+ for i in $(seq 5); do
+ sleep 1 # give the DAD some time
+
+ # tentative flag = DAD is still not complete or failed
+ duplicate=$(ip -6 addr show dev ${interface} tentative \
+ | grep ${new_ip6_address}/${new_ip6_prefixlen})
+
+ # if there's no tentative flag, address passed DAD
+ if [ -z "${duplicate}" ]; then
+ break
+ fi
+ done
+
+ # if there's still tentative flag = address didn't pass DAD =
+ # = it's duplicate = remove it
+ if [ -n "${duplicate}" ]; then
+ ip -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} dev ${interface}
+ exit_with_hooks 3
+ fi
+}
+
+dh6config() {
+ case "${reason}" in
+ BOUND6)
+ if [ -z "${new_ip6_address}" ] &&
+ [ -z "${new_ip6_prefixlen}" ]; then
+ exit_with_hooks 2
+ fi
+
+ add_ipv6_addr_with_DAD
+
+ make_resolv_conf
+ ;;
+
+ RENEW6|REBIND6)
+ if [ -n "${new_ip6_prefixlen}" ] &&
+ [ -n "${new_ip6_address}" ] &&
+ [ ! "${new_ip6_address}" = "${old_ip6_address}" ]; then
+ add_ipv6_addr_with_DAD
+ fi
+
+ if [ ! "${new_dhcp6_name_servers}" = "${old_dhcp6_name_servers}" ] ||
+ [ ! "${new_dhcp6_domain_search}" = "${old_dhcp6_domain_search}" ]; then
+ make_resolv_conf
+ fi
+ ;;
+
+ DEPREF6)
+ if [ -z "${new_ip6_prefixlen}" ]; then
+ exit_with_hooks 2
+ fi
+
+ ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \
+ dev ${interface} scope global preferred_lft 0
+ ;;
+ esac
+
+ # execute any additional client side configuration scripts we have
+ if [ -d ${ETCDIR}/dhclient.d ]; then
+ for f in ${ETCDIR}/dhclient.d/*.sh ; do
+ if [ -x ${f} ]; then
+ subsystem="${f%.sh}"
+ subsystem="${subsystem##*/}"
+ . ${f}
+ "${subsystem}_config"
+ fi
+ done
+ fi
+}
+
+
+#
+# ### MAIN
+#
+
+if [ -x ${ETCDIR}/dhclient-enter-hooks ]; then
+ exit_status=0
+
+ # dhclient-enter-hooks can abort dhclient-script by setting
+ # the exit_status variable to a non-zero value
+ . ${ETCDIR}/dhclient-enter-hooks
+ if [ ${exit_status} -ne 0 ]; then
+ exit ${exit_status}
+ fi
+fi
+
+if [ ! -r /etc/sysconfig/network-scripts/network-functions ]; then
+ echo "Missing /etc/sysconfig/network-scripts/network-functions, exiting." >&2
+ exit 1
+fi
+
+if [ ! -r /etc/rc.d/init.d/functions ]; then
+ echo "Missing /etc/rc.d/init.d/functions, exiting." >&2
+ exit 1
+fi
+
+. /etc/sysconfig/network-scripts/network-functions
+. /etc/rc.d/init.d/functions
+
+if [ -f /etc/sysconfig/network ]; then
+ . /etc/sysconfig/network
+fi
+
+if [ -f /etc/sysconfig/networking/network ]; then
+ . /etc/sysconfig/networking/network
+fi
+
+cd /etc/sysconfig/network-scripts
+CONFIG="ifcfg-${interface}"
+need_config ${CONFIG}
+source_config >/dev/null 2>&1
+
+new_prefix="$(get_prefix ${new_ip_address} ${new_subnet_mask})"
+old_prefix="$(get_prefix ${old_ip_address} ${old_subnet_mask})"
+alias_prefix="$(get_prefix ${alias_ip_address} ${alias_subnet_mask})"
+
+case "${reason}" in
+ MEDIUM)
+ # Linux doesn't handle mediums (media)
+ exit_with_hooks 0
+ ;;
+
+ PREINIT)
+ if [ -n "${alias_ip_address}" ]; then
+ # Bring down alias interface, its routes will disappear too.
+ ip link set ${interface}:0 down
+ fi
+
+ if [ "${keep_old_ip}" = "yes" ]; then
+ ip link set ${interface} up
+ else
+ ip -4 addr flush dev ${interface} >/dev/null 2>&1
+ ip link set ${interface} up
+ fi
+
+ if [ -n "${DHCLIENT_DELAY}" ] && [ ${DHCLIENT_DELAY} -gt 0 ]; then
+ sleep ${DHCLIENT_DELAY}
+ fi
+
+ exit_with_hooks 0
+ ;;
+
+ PREINIT6)
+ # ensure interface is up
+ ip link set ${interface} up
+
+ # remove any stale addresses from aborted clients
+ ip -6 addr flush dev ${interface} scope global permanent
+
+ exit_with_hooks 0
+ ;;
+
+ ARPCHECK|ARPSEND)
+ if [ -z "${new_ip_address}" ] || [ -z "${interface}" ] ||
+ arping -q -f -c 2 -w 3 -D -I ${interface} ${new_ip_address}; then
+ exit_with_hooks 0
+ else
+ exit_with_hooks 1
+ fi
+ ;;
+
+ BOUND|RENEW|REBIND|REBOOT)
+ dhconfig
+ exit_with_hooks 0
+ ;;
+
+ BOUND6|RENEW6|REBIND6|DEPREF6)
+ dh6config
+ exit_with_hooks 0
+ ;;
+
+ EXPIRE6|RELEASE6|STOP6)
+ if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then
+ exit_with_hooks 2
+ fi
+
+ ip -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \
+ dev ${interface}
+
+ # execute any additional client side configuration scripts we have
+ if [ -d ${ETCDIR}/dhclient.d ]; then
+ for f in ${ETCDIR}/dhclient.d/*.sh ; do
+ if [ -x ${f} ]; then
+ subsystem="${f%.sh}"
+ subsystem="${subsystem##*/}"
+ . ${f}
+ "${subsystem}_restore"
+ fi
+ done
+ fi
+
+ if [ -x ${ETCDIR}/dhclient-${interface}-down-hooks ]; then
+ . ${ETCDIR}/dhclient-${interface}-down-hooks
+ elif [ -x ${ETCDIR}/dhclient-down-hooks ]; then
+ . ${ETCDIR}/dhclient-down-hooks
+ fi
+
+ exit_with_hooks 0
+ ;;
+
+ EXPIRE|FAIL|RELEASE|STOP)
+ # only restore config files if there are no other dhclient processes
+ # running (#306381)
+ any_other_clients="$(ps -eo pid,ppid,comm | grep dhclient | grep -v ${PPID})"
+ if [ -n "${any_other_clients}" ]; then
+ if [ -f ${SAVEDIR}/resolv.conf.predhclient.${interface} ]; then
+ change_resolv_conf ${SAVEDIR}/resolv.conf.predhclient.${interface}
+ rm -f ${SAVEDIR}/resolv.conf.predhclient.${interface}
+ fi
+
+ if [ -n "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" ] &&
+ [[ "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ]]; then
+ if [ -e ${SAVEDIR}/localtime.predhclient.${interface} ]; then
+ rm -f /etc/localtime
+ contents="$(< ${SAVEDIR}/localtime.predhclient.${interface})"
+ echo "${contents}" > /etc/localtime
+ rm -f ${SAVEDIR}/localtime.predhclient.${interface}
+ touch /etc/localtime
+ fix_context /etc/localtime
+ fi
+ fi
+ fi
+
+ # execute any additional client side configuration scripts we have
+ if [ -d ${ETCDIR}/dhclient.d ]; then
+ for f in ${ETCDIR}/dhclient.d/*.sh ; do
+ if [ -x ${f} ]; then
+ subsystem="${f%.sh}"
+ subsystem="${subsystem##*/}"
+ . ${f}
+ "${subsystem}_restore"
+ fi
+ done
+ fi
+
+ if [ -x ${ETCDIR}/dhclient-${interface}-down-hooks ]; then
+ . ${ETCDIR}/dhclient-${interface}-down-hooks
+ elif [ -x ${ETCDIR}/dhclient-down-hooks ]; then
+ . ${ETCDIR}/dhclient-down-hooks
+ fi
+
+ if [ -n "${alias_ip_address}" ]; then
+ # Turn off alias interface
+ ip link set ${interface}:0 down
+ fi
+
+ if [ -n "${old_ip_address}" ]; then
+ # Shut down interface, which will delete routes and clear arp cache.
+ ip -4 addr flush dev ${interface} >/dev/null 2>&1
+ ip link set ${interface} down
+ fi
+
+ if [ -n "${alias_ip_address}" ]; then
+ ip -4 addr add ${alias_ip_address}/${alias_prefix} dev ${interface}:0
+ ip -4 route replace ${alias_ip_address}/32 ${interface}:0
+ fi
+
+ exit_with_hooks 0
+ ;;
+
+ TIMEOUT)
+ if [ -n "${new_routers}" ]; then
+ if [ -n "${alias_ip_address}" ]; then
+ ip -4 addr flush dev ${interface}:0 >/dev/null 2>&1
+ fi
+
+ ip -4 addr add ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface}
+ set ${new_routers}
+
+ if ping -q -c 1 -w 10 -I ${interface} ${1}; then
+ dhconfig
+ exit_with_hooks 0
+ fi
+
+ ip -4 addr flush dev ${interface} >/dev/null 2>&1
+ ip link set ${interface} down
+ exit_with_hooks 1
+ else
+ exit_with_hooks 1
+ fi
+ ;;
+
+ *)
+ logmessage "unhandled state: ${reason}"
+ exit_with_hooks 1
+ ;;
+esac
+
+exit_with_hooks 0
diff --git a/server/dhcp/files/dhclient.conf b/server/dhcp/files/dhclient.conf
new file mode 100644
index 0000000000..c5837d7479
--- /dev/null
+++ b/server/dhcp/files/dhclient.conf
@@ -0,0 +1,40 @@
+#Please refer to dhclient.conf(5) man page
+
+#send host-name "pisilinux";
+#send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
+#send dhcp-lease-time 3600;
+#supersede domain-name "fugue.com home.vix.com";
+#prepend domain-name-servers 127.0.0.1;
+
+#request subnet-mask, broadcast-address, time-offset, routers,
+# domain-name, domain-name-servers, host-name;
+
+#require subnet-mask, domain-name-servers;
+#timeout 60;
+#retry 60;
+#reboot 10;
+#select-timeout 5;
+#initial-interval 2;
+#script "/etc/dhcp/dhclient-script";
+#media "-link0 -link1 -link2", "link0 link1";
+#reject 192.33.137.209;
+
+#alias {
+# interface "ep0";
+# fixed-address 192.5.5.213;
+# option subnet-mask 255.255.255.255;
+#}
+
+#lease {
+# interface "ep0";
+# fixed-address 192.33.137.200;
+# medium "link0 link1";
+# option host-name "andare.swiftmedia.com";
+# option subnet-mask 255.255.255.0;
+# option broadcast-address 192.33.137.255;
+# option routers 192.33.137.250;
+# option domain-name-servers 127.0.0.1;
+# renew 2 2000/1/12 00:00:01;
+# rebind 2 2000/1/12 00:00:01;
+# expire 2 2000/1/12 00:00:01;
+#}
diff --git a/server/dhcp/files/dhcp-4.2.0-IFNAMSIZ.patch b/server/dhcp/files/dhcp-4.2.0-IFNAMSIZ.patch
new file mode 100644
index 0000000000..b8437daaac
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-IFNAMSIZ.patch
@@ -0,0 +1,12 @@
+diff -up dhcp-4.2.0/server/dhcpd.c.ifnamsiz dhcp-4.2.0/server/dhcpd.c
+--- dhcp-4.2.0/server/dhcpd.c.ifnamsiz 2010-07-21 14:31:39.000000000 +0200
++++ dhcp-4.2.0/server/dhcpd.c 2010-07-21 16:05:49.000000000 +0200
+@@ -409,7 +409,7 @@ main(int argc, char **argv) {
+ log_fatal ("Insufficient memory to %s %s: %s",
+ "record interface", argv [i],
+ isc_result_totext (result));
+- strcpy (tmp -> name, argv [i]);
++ strncpy (tmp -> name, argv [i], sizeof (tmp -> name));
+ if (interfaces) {
+ interface_reference (&tmp -> next,
+ interfaces, MDL);
diff --git a/server/dhcp/files/dhcp-4.2.0-P2-omapi.patch b/server/dhcp/files/dhcp-4.2.0-P2-omapi.patch
new file mode 100644
index 0000000000..0222090eda
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-P2-omapi.patch
@@ -0,0 +1,12 @@
+diff -up dhcp-4.2.0-P2/omapip/protocol.c.omapi dhcp-4.2.0-P2/omapip/protocol.c
+--- dhcp-4.2.0-P2/omapip/protocol.c.omapi 2009-11-20 02:49:02.000000000 +0100
++++ dhcp-4.2.0-P2/omapip/protocol.c 2011-01-03 16:30:25.000000000 +0100
+@@ -386,7 +386,7 @@ isc_result_t omapi_protocol_signal_handl
+ /* Should only receive these when opening the initial authenticator. */
+ if (!strcmp (name, "status")) {
+ status = va_arg (ap, isc_result_t);
+- if (status != ISC_R_SUCCESS) {
++ if ((status != ISC_R_SUCCESS) && (status >= ISC_RESULTCLASS_DHCP)) {
+ omapi_signal_in (h -> inner, "status", status,
+ (omapi_object_t *)0);
+ omapi_disconnect (p -> outer, 1);
diff --git a/server/dhcp/files/dhcp-4.2.0-PPP.patch b/server/dhcp/files/dhcp-4.2.0-PPP.patch
new file mode 100644
index 0000000000..bef2be7f08
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-PPP.patch
@@ -0,0 +1,150 @@
+diff -up dhcp-4.2.0-P1/client/dhc6.c.PPP dhcp-4.2.0-P1/client/dhc6.c
+--- dhcp-4.2.0-P1/client/dhc6.c.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/client/dhc6.c 2010-11-09 15:54:12.000000000 +0100
+@@ -129,7 +129,7 @@ extern int stateless;
+ * is not how it is intended. Upcoming rearchitecting the client should
+ * address this "one daemon model."
+ */
+-void
++isc_result_t
+ form_duid(struct data_string *duid, const char *file, int line)
+ {
+ struct interface_info *ip;
+@@ -141,6 +141,15 @@ form_duid(struct data_string *duid, cons
+ if (ip == NULL)
+ log_fatal("Impossible condition at %s:%d.", MDL);
+
++ while (ip && ip->hw_address.hbuf[0] == HTYPE_RESERVED) {
++ /* Try the other interfaces */
++ log_debug("Cannot form default DUID from interface %s.", ip->name);
++ ip = ip->next;
++ }
++ if (ip == NULL) {
++ return ISC_R_UNEXPECTED;
++ }
++
+ if ((ip->hw_address.hlen == 0) ||
+ (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
+ log_fatal("Impossible hardware address length at %s:%d.", MDL);
+@@ -176,6 +185,8 @@ form_duid(struct data_string *duid, cons
+ memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
+ ip->hw_address.hlen - 1);
+ }
++
++ return ISC_R_SUCCESS;
+ }
+
+ /*
+@@ -5289,7 +5300,8 @@ make_client6_options(struct client_state
+ */
+ if ((oc = lookup_option(&dhcpv6_universe, *op,
+ D6O_CLIENTID)) == NULL) {
+- if (!option_cache(&oc, &default_duid, NULL, clientid_option,
++ if (default_duid.len == 0 ||
++ !option_cache(&oc, &default_duid, NULL, clientid_option,
+ MDL))
+ log_fatal("Failure assembling a DUID.");
+
+diff -up dhcp-4.2.0-P1/client/dhclient.c.PPP dhcp-4.2.0-P1/client/dhclient.c
+--- dhcp-4.2.0-P1/client/dhclient.c.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/client/dhclient.c 2010-11-09 15:37:26.000000000 +0100
+@@ -911,8 +911,8 @@ main(int argc, char **argv) {
+ if (default_duid.buffer != NULL)
+ data_string_forget(&default_duid, MDL);
+
+- form_duid(&default_duid, MDL);
+- write_duid(&default_duid);
++ if (form_duid(&default_duid, MDL) == ISC_R_SUCCESS)
++ write_duid(&default_duid);
+ }
+
+ for (ip = interfaces ; ip != NULL ; ip = ip->next) {
+diff -up dhcp-4.2.0-P1/common/bpf.c.PPP dhcp-4.2.0-P1/common/bpf.c
+--- dhcp-4.2.0-P1/common/bpf.c.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/common/bpf.c 2010-11-09 15:42:42.000000000 +0100
+@@ -599,6 +599,22 @@ get_hw_addr(const char *name, struct har
+ memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
+ break;
+ #endif /* IFT_FDDI */
++#if defined(IFT_PPP)
++ case IFT_PPP:
++ if (local_family != AF_INET6)
++ log_fatal("Unsupported device type %d for \"%s\"",
++ sa->sdl_type, name);
++ hw->hlen = 0;
++ hw->hbuf[0] = HTYPE_RESERVED;
++ /* 0xdeadbeef should never occur on the wire,
++ * and is a signature that something went wrong.
++ */
++ hw->hbuf[1] = 0xde;
++ hw->hbuf[2] = 0xad;
++ hw->hbuf[3] = 0xbe;
++ hw->hbuf[4] = 0xef;
++ break;
++#endif
+ default:
+ log_fatal("Unsupported device type %d for \"%s\"",
+ sa->sdl_type, name);
+diff -up dhcp-4.2.0-P1/common/lpf.c.PPP dhcp-4.2.0-P1/common/lpf.c
+--- dhcp-4.2.0-P1/common/lpf.c.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/common/lpf.c 2010-11-09 15:45:40.000000000 +0100
+@@ -502,6 +502,22 @@ get_hw_addr(const char *name, struct har
+ hw->hbuf[0] = HTYPE_FDDI;
+ memcpy(&hw->hbuf[1], sa->sa_data, 16);
+ break;
++#if defined(ARPHRD_PPP)
++ case ARPHRD_PPP:
++ if (local_family != AF_INET6)
++ log_fatal("Unsupported device type %d for \"%s\"",
++ sa->sa_family, name);
++ hw->hlen = 0;
++ hw->hbuf[0] = HTYPE_RESERVED;
++ /* 0xdeadbeef should never occur on the wire,
++ * and is a signature that something went wrong.
++ */
++ hw->hbuf[1] = 0xde;
++ hw->hbuf[2] = 0xad;
++ hw->hbuf[3] = 0xbe;
++ hw->hbuf[4] = 0xef;
++ break;
++#endif
+ default:
+ log_fatal("Unsupported device type %ld for \"%s\"",
+ (long int)sa->sa_family, name);
+diff -up dhcp-4.2.0-P1/includes/dhcpd.h.PPP dhcp-4.2.0-P1/includes/dhcpd.h
+--- dhcp-4.2.0-P1/includes/dhcpd.h.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/includes/dhcpd.h 2010-11-09 15:46:58.000000000 +0100
+@@ -2733,7 +2733,7 @@ void dhcpv4_client_assignments(void);
+ void dhcpv6_client_assignments(void);
+
+ /* dhc6.c */
+-void form_duid(struct data_string *duid, const char *file, int line);
++isc_result_t form_duid(struct data_string *duid, const char *file, int line);
+ void dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line);
+ void start_init6(struct client_state *client);
+ void start_info_request6(struct client_state *client);
+diff -up dhcp-4.2.0-P1/includes/dhcp.h.PPP dhcp-4.2.0-P1/includes/dhcp.h
+--- dhcp-4.2.0-P1/includes/dhcp.h.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/includes/dhcp.h 2010-11-09 15:48:53.000000000 +0100
+@@ -80,6 +80,8 @@ struct dhcp_packet {
+ #define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */
+ #define HTYPE_FDDI 8 /* FDDI... */
+
++#define HTYPE_RESERVED 0 /* RFC 5494 */
++
+ /* Magic cookie validating dhcp options field (and bootp vendor
+ extensions field). */
+ #define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+diff -up dhcp-4.2.0-P1/server/dhcpv6.c.PPP dhcp-4.2.0-P1/server/dhcpv6.c
+--- dhcp-4.2.0-P1/server/dhcpv6.c.PPP 2010-11-05 10:47:37.000000000 +0100
++++ dhcp-4.2.0-P1/server/dhcpv6.c 2010-11-09 15:50:17.000000000 +0100
+@@ -300,6 +300,9 @@ generate_new_server_duid(void) {
+ if (p->hw_address.hlen > 0) {
+ break;
+ }
++ if (p->next == NULL && p->hw_address.hbuf[0] == HTYPE_RESERVED) {
++ log_error("Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
++ }
+ }
+ if (p == NULL) {
+ return ISC_R_UNEXPECTED;
diff --git a/server/dhcp/files/dhcp-4.2.0-add_timeout_when_NULL.patch b/server/dhcp/files/dhcp-4.2.0-add_timeout_when_NULL.patch
new file mode 100644
index 0000000000..4784d5a684
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-add_timeout_when_NULL.patch
@@ -0,0 +1,14 @@
+diff -up dhcp-4.2.0/common/dispatch.c.dracut dhcp-4.2.0/common/dispatch.c
+--- dhcp-4.2.0/common/dispatch.c.dracut 2010-06-01 19:29:59.000000000 +0200
++++ dhcp-4.2.0/common/dispatch.c 2010-07-21 16:10:09.000000000 +0200
+@@ -189,6 +189,10 @@ void add_timeout (when, where, what, ref
+ isc_interval_t interval;
+ isc_time_t expires;
+
++ if (when == NULL) {
++ return;
++ }
++
+ /* See if this timeout supersedes an existing timeout. */
+ t = (struct timeout *)0;
+ for (q = timeouts; q; q = q->next) {
diff --git a/server/dhcp/files/dhcp-4.2.0-default-requested-options.patch b/server/dhcp/files/dhcp-4.2.0-default-requested-options.patch
new file mode 100644
index 0000000000..fea8a4b99c
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-default-requested-options.patch
@@ -0,0 +1,44 @@
+diff -up dhcp-4.2.0/client/clparse.c.requested dhcp-4.2.0/client/clparse.c
+--- dhcp-4.2.0/client/clparse.c.requested 2010-07-21 13:29:05.000000000 +0200
++++ dhcp-4.2.0/client/clparse.c 2010-07-21 13:50:29.000000000 +0200
+@@ -37,7 +37,7 @@
+
+ struct client_config top_level_config;
+
+-#define NUM_DEFAULT_REQUESTED_OPTS 9
++#define NUM_DEFAULT_REQUESTED_OPTS 14
+ struct option *default_requested_options[NUM_DEFAULT_REQUESTED_OPTS + 1];
+
+ static void parse_client_default_duid(struct parse *cfile);
+@@ -111,6 +111,31 @@ isc_result_t read_client_conf ()
+ option_code_hash_lookup(&default_requested_options[8],
+ dhcpv6_universe.code_hash, &code, 0, MDL);
+
++ /* 10 */
++ code = DHO_NIS_DOMAIN;
++ option_code_hash_lookup(&default_requested_options[9],
++ dhcp_universe.code_hash, &code, 0, MDL);
++
++ /* 11 */
++ code = DHO_NIS_SERVERS;
++ option_code_hash_lookup(&default_requested_options[10],
++ dhcp_universe.code_hash, &code, 0, MDL);
++
++ /* 12 */
++ code = DHO_NTP_SERVERS;
++ option_code_hash_lookup(&default_requested_options[11],
++ dhcp_universe.code_hash, &code, 0, MDL);
++
++ /* 13 */
++ code = DHO_INTERFACE_MTU;
++ option_code_hash_lookup(&default_requested_options[12],
++ dhcp_universe.code_hash, &code, 0, MDL);
++
++ /* 14 */
++ code = DHO_DOMAIN_SEARCH;
++ option_code_hash_lookup(&default_requested_options[13],
++ dhcp_universe.code_hash, &code, 0, MDL);
++
+ for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
+ if (default_requested_options[code] == NULL)
+ log_fatal("Unable to find option definition for "
diff --git a/server/dhcp/files/dhcp-4.2.0-dhclient-decline-backoff.patch b/server/dhcp/files/dhcp-4.2.0-dhclient-decline-backoff.patch
new file mode 100644
index 0000000000..81bec7bd47
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-dhclient-decline-backoff.patch
@@ -0,0 +1,63 @@
+diff -up dhcp-4.2.0/client/dhclient.c.backoff dhcp-4.2.0/client/dhclient.c
+--- dhcp-4.2.0/client/dhclient.c.backoff 2010-07-21 13:37:03.000000000 +0200
++++ dhcp-4.2.0/client/dhclient.c 2010-07-21 13:38:31.000000000 +0200
+@@ -1208,6 +1208,8 @@ void state_init (cpp)
+ void *cpp;
+ {
+ struct client_state *client = cpp;
++ enum dhcp_state init_state = client->state;
++ struct timeval tv;
+
+ ASSERT_STATE(state, S_INIT);
+
+@@ -1220,9 +1222,18 @@ void state_init (cpp)
+ client -> first_sending = cur_time;
+ client -> interval = client -> config -> initial_interval;
+
+- /* Add an immediate timeout to cause the first DHCPDISCOVER packet
+- to go out. */
+- send_discover (client);
++ if (init_state != S_DECLINED) {
++ /* Add an immediate timeout to cause the first DHCPDISCOVER packet
++ to go out. */
++ send_discover(client);
++ } else {
++ /* We've received an OFFER and it has been DECLINEd by dhclient-script.
++ * wait for a random time between 1 and backoff_cutoff seconds before
++ * trying again. */
++ tv . tv_sec = cur_time + ((1 + (random() >> 2)) % client->config->backoff_cutoff);
++ tv . tv_usec = 0;
++ add_timeout(&tv, send_discover, client, 0, 0);
++ }
+ }
+
+ /*
+@@ -1501,6 +1512,7 @@ void bind_lease (client)
+ send_decline (client);
+ destroy_client_lease (client -> new);
+ client -> new = (struct client_lease *)0;
++ client -> state = S_DECLINED;
+ state_init (client);
+ return;
+ }
+@@ -3711,6 +3723,7 @@ void client_location_changed ()
+ case S_INIT:
+ case S_REBINDING:
+ case S_STOPPED:
++ case S_DECLINED:
+ break;
+ }
+ client -> state = S_INIT;
+diff -up dhcp-4.2.0/includes/dhcpd.h.backoff dhcp-4.2.0/includes/dhcpd.h
+--- dhcp-4.2.0/includes/dhcpd.h.backoff 2010-07-21 13:29:05.000000000 +0200
++++ dhcp-4.2.0/includes/dhcpd.h 2010-07-21 13:38:31.000000000 +0200
+@@ -1056,7 +1056,8 @@ enum dhcp_state {
+ S_BOUND = 5,
+ S_RENEWING = 6,
+ S_REBINDING = 7,
+- S_STOPPED = 8
++ S_STOPPED = 8,
++ S_DECLINED = 9
+ };
+
+ /* Authentication and BOOTP policy possibilities (not all values work
diff --git a/server/dhcp/files/dhcp-4.2.0-errwarn-message.patch b/server/dhcp/files/dhcp-4.2.0-errwarn-message.patch
new file mode 100644
index 0000000000..a0f70cd042
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-errwarn-message.patch
@@ -0,0 +1,30 @@
+diff -up dhcp-4.2.0/omapip/errwarn.c.errwarn dhcp-4.2.0/omapip/errwarn.c
+--- dhcp-4.2.0/omapip/errwarn.c.errwarn 2009-07-23 20:52:21.000000000 +0200
++++ dhcp-4.2.0/omapip/errwarn.c 2010-07-21 13:23:47.000000000 +0200
+@@ -76,20 +76,13 @@ void log_fatal (const char * fmt, ... )
+
+ #if !defined (NOMINUM)
+ log_error ("%s", "");
+- log_error ("If you did not get this software from ftp.isc.org, please");
+- log_error ("get the latest from ftp.isc.org and install that before");
+- log_error ("requesting help.");
++ log_error ("This version of ISC DHCP is based on the release available");
++ log_error ("on ftp.isc.org. Features have been added and other changes");
++ 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 ("If you did get this software from ftp.isc.org and have not");
+- log_error ("yet read the README, please read it before requesting help.");
+- log_error ("If you intend to request help from the dhcp-server@isc.org");
+- log_error ("mailing list, please read the section on the README about");
+- log_error ("submitting bug reports and requests for help.");
+- log_error ("%s", "");
+- log_error ("Please do not under any circumstances send requests for");
+- log_error ("help directly to the authors of this software - please");
+- log_error ("send them to the appropriate mailing list as described in");
+- log_error ("the README file.");
++ log_error ("Please report for this software via the Red Hat Bugzilla site:");
++ log_error (" http://bugzilla.redhat.com");
+ log_error ("%s", "");
+ log_error ("exiting.");
+ #endif
diff --git a/server/dhcp/files/dhcp-4.2.0-garbage-chars.patch b/server/dhcp/files/dhcp-4.2.0-garbage-chars.patch
new file mode 100644
index 0000000000..118ff3fc1a
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-garbage-chars.patch
@@ -0,0 +1,12 @@
+diff -up dhcp-4.2.0/common/tables.c.garbage dhcp-4.2.0/common/tables.c
+--- dhcp-4.2.0/common/tables.c.garbage 2009-11-20 02:49:01.000000000 +0100
++++ dhcp-4.2.0/common/tables.c 2010-07-21 14:40:56.000000000 +0200
+@@ -207,7 +207,7 @@ static struct option dhcp_options[] = {
+ { "netinfo-server-tag", "t", &dhcp_universe, 113, 1 },
+ { "default-url", "t", &dhcp_universe, 114, 1 },
+ { "subnet-selection", "I", &dhcp_universe, 118, 1 },
+- { "domain-search", "Dc", &dhcp_universe, 119, 1 },
++ { "domain-search", "D", &dhcp_universe, 119, 1 },
+ { "vivco", "Evendor-class.", &dhcp_universe, 124, 1 },
+ { "vivso", "Evendor.", &dhcp_universe, 125, 1 },
+ #if 0
diff --git a/server/dhcp/files/dhcp-4.2.0-honor-expired.patch b/server/dhcp/files/dhcp-4.2.0-honor-expired.patch
new file mode 100644
index 0000000000..45eadfad80
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-honor-expired.patch
@@ -0,0 +1,52 @@
+diff -up dhcp-4.2.0/client/dhc6.c.honor-expired dhcp-4.2.0/client/dhc6.c
+--- dhcp-4.2.0/client/dhc6.c.honor-expired 2010-10-07 12:55:37.000000000 +0200
++++ dhcp-4.2.0/client/dhc6.c 2010-10-07 12:56:43.000000000 +0200
+@@ -1405,6 +1405,35 @@ start_info_request6(struct client_state
+ go_daemon();
+ }
+
++/* Run through the addresses in lease and return true if there's any unexpired.
++ * Return false otherwise.
++ */
++isc_boolean_t
++unexpired_address_in_lease(struct dhc6_lease *lease)
++{
++ struct dhc6_ia *ia;
++ struct dhc6_addr *addr;
++
++ if (lease == NULL)
++ return;
++
++ for (ia = lease->bindings ; ia != NULL ; ia = ia->next) {
++ for (addr = ia->addrs ; addr != NULL ; addr = addr->next) {
++ if (addr->flags & DHC6_ADDR_EXPIRED)
++ continue;
++
++ if (addr->starts + addr->max_life > cur_time) {
++ return ISC_TRUE;
++ }
++ }
++ }
++
++ log_info("PRC: Previous lease is devoid of active addresses."
++ " Re-initializing.");
++
++ return ISC_FALSE;
++}
++
+ /*
+ * start_confirm6() kicks off an "init-reboot" version of the process, at
+ * startup to find out if old bindings are 'fair' and at runtime whenever
+@@ -1417,8 +1446,10 @@ start_confirm6(struct client_state *clie
+
+ /* If there is no active lease, there is nothing to check. */
+ if ((client->active_lease == NULL) ||
+- !active_prefix(client) ||
+- client->active_lease->released) {
++ !active_prefix(client) ||
++ client->active_lease->released ||
++ !unexpired_address_in_lease(client->active_lease)) {
++ dhc6_lease_destroy(&client->active_lease, MDL);
+ start_init6(client);
+ return;
+ }
diff --git a/server/dhcp/files/dhcp-4.2.0-inherit-leases.patch b/server/dhcp/files/dhcp-4.2.0-inherit-leases.patch
new file mode 100644
index 0000000000..052f642594
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-inherit-leases.patch
@@ -0,0 +1,34 @@
+diff -up dhcp-4.2.0/client/dhclient.c.inherit dhcp-4.2.0/client/dhclient.c
+--- dhcp-4.2.0/client/dhclient.c.inherit 2010-07-21 14:33:44.000000000 +0200
++++ dhcp-4.2.0/client/dhclient.c 2010-07-21 14:40:05.000000000 +0200
+@@ -2322,6 +2322,7 @@ void send_request (cpp)
+ {
+ struct client_state *client = cpp;
+
++ int i;
+ int result;
+ int interval;
+ struct sockaddr_in destination;
+@@ -2381,6 +2382,22 @@ void send_request (cpp)
+ /* Now do a preinit on the interface so that we can
+ discover a new address. */
+ script_init (client, "PREINIT", (struct string_list *)0);
++
++ /* Has an active lease */
++ if (client -> interface -> addresses != NULL) {
++ for (i = 0; i < client -> interface -> address_count; i++) {
++ if (client -> active &&
++ client -> active -> is_bootp &&
++ client -> active -> expiry > cur_time &&
++ client -> interface -> addresses[i].s_addr != 0 &&
++ client -> active -> address.len == 4 &&
++ memcpy (client -> active -> address.iabuf, &(client -> interface -> addresses[i]), 4) == 0) {
++ client_envadd (client, "", "keep_old_ip", "%s", "yes");
++ break;
++ }
++ }
++ }
++
+ if (client -> alias)
+ script_write_params (client, "alias_",
+ client -> alias);
diff --git a/server/dhcp/files/dhcp-4.2.0-logpid.patch b/server/dhcp/files/dhcp-4.2.0-logpid.patch
new file mode 100644
index 0000000000..c24adb14a9
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-logpid.patch
@@ -0,0 +1,12 @@
+diff -up dhcp-4.2.0/client/dhclient.c.logpid dhcp-4.2.0/client/dhclient.c
+--- dhcp-4.2.0/client/dhclient.c.logpid 2010-07-21 16:13:52.000000000 +0200
++++ dhcp-4.2.0/client/dhclient.c 2010-07-21 16:16:51.000000000 +0200
+@@ -154,7 +154,7 @@ main(int argc, char **argv) {
+ else if (fd != -1)
+ close(fd);
+
+- openlog("dhclient", LOG_NDELAY, LOG_DAEMON);
++ openlog("dhclient", LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+ #if !(defined(DEBUG) || defined(__CYGWIN32__))
+ setlogmask(LOG_UPTO(LOG_INFO));
diff --git a/server/dhcp/files/dhcp-4.2.0-paths.patch b/server/dhcp/files/dhcp-4.2.0-paths.patch
new file mode 100644
index 0000000000..54c7aba8e6
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-paths.patch
@@ -0,0 +1,45 @@
+diff -up dhcp-4.2.0/includes/dhcpd.h.paths dhcp-4.2.0/includes/dhcpd.h
+--- dhcp-4.2.0/includes/dhcpd.h.paths 2010-07-21 13:55:42.000000000 +0200
++++ dhcp-4.2.0/includes/dhcpd.h 2010-07-21 14:29:57.000000000 +0200
+@@ -1390,15 +1390,15 @@ typedef unsigned char option_mask [16];
+ #else /* !DEBUG */
+
+ #ifndef _PATH_DHCPD_CONF
+-#define _PATH_DHCPD_CONF "/etc/dhcpd.conf"
++#define _PATH_DHCPD_CONF "/etc/dhcp/dhcpd.conf"
+ #endif /* DEBUG */
+
+ #ifndef _PATH_DHCPD_DB
+-#define _PATH_DHCPD_DB LOCALSTATEDIR"/db/dhcpd.leases"
++#define _PATH_DHCPD_DB LOCALSTATEDIR"/dhcpd/dhcpd.leases"
+ #endif
+
+ #ifndef _PATH_DHCPD6_DB
+-#define _PATH_DHCPD6_DB LOCALSTATEDIR"/db/dhcpd6.leases"
++#define _PATH_DHCPD6_DB LOCALSTATEDIR"/dhcpd/dhcpd6.leases"
+ #endif
+
+ #ifndef _PATH_DHCPD_PID
+@@ -1412,7 +1412,7 @@ typedef unsigned char option_mask [16];
+ #endif /* DEBUG */
+
+ #ifndef _PATH_DHCLIENT_CONF
+-#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf"
++#define _PATH_DHCLIENT_CONF "/etc/dhcp/dhclient.conf"
+ #endif
+
+ #ifndef _PATH_DHCLIENT_SCRIPT
+@@ -1428,11 +1428,11 @@ typedef unsigned char option_mask [16];
+ #endif
+
+ #ifndef _PATH_DHCLIENT_DB
+-#define _PATH_DHCLIENT_DB LOCALSTATEDIR"/db/dhclient.leases"
++#define _PATH_DHCLIENT_DB LOCALSTATEDIR"/dhclient/dhclient.leases"
+ #endif
+
+ #ifndef _PATH_DHCLIENT6_DB
+-#define _PATH_DHCLIENT6_DB LOCALSTATEDIR"/db/dhclient6.leases"
++#define _PATH_DHCLIENT6_DB LOCALSTATEDIR"/dhclient/dhclient6.leases"
+ #endif
+
+ #ifndef _PATH_RESOLV_CONF
diff --git a/server/dhcp/files/dhcp-4.2.0-release-by-ifup.patch b/server/dhcp/files/dhcp-4.2.0-release-by-ifup.patch
new file mode 100644
index 0000000000..1ad8213fb6
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-release-by-ifup.patch
@@ -0,0 +1,85 @@
+diff -up dhcp-4.2.0/client/dhclient.c.ifup dhcp-4.2.0/client/dhclient.c
+--- dhcp-4.2.0/client/dhclient.c.ifup 2010-07-21 13:30:10.000000000 +0200
++++ dhcp-4.2.0/client/dhclient.c 2010-07-21 13:37:03.000000000 +0200
+@@ -497,9 +497,81 @@ main(int argc, char **argv) {
+ kill(oldpid, SIGTERM);
+ }
+ fclose(pidfd);
++ } else {
++ /* handle release for interfaces requested with Red Hat
++ * /sbin/ifup - pidfile will be /var/run/dhclient-$interface.pid
++ */
++
++ if ((path_dhclient_pid == NULL) || (*path_dhclient_pid == '\0'))
++ path_dhclient_pid = "/var/run/dhclient.pid";
++
++ char *new_path_dhclient_pid;
++ struct interface_info *ip;
++ int pdp_len = strlen(path_dhclient_pid), pfx, dpfx;
++
++ /* find append point: beginning of any trailing '.pid'
++ * or '-$IF.pid' */
++ for (pfx=pdp_len; (pfx >= 0) && (path_dhclient_pid[pfx] != '.') && (path_dhclient_pid[pfx] != '/'); pfx--);
++ if (pfx == -1)
++ pfx = pdp_len;
++
++ if (path_dhclient_pid[pfx] == '/')
++ pfx += 1;
++
++ for (dpfx=pfx; (dpfx >= 0) && (path_dhclient_pid[dpfx] != '-') && (path_dhclient_pid[dpfx] != '/'); dpfx--);
++ if ((dpfx > -1) && (path_dhclient_pid[dpfx] != '/'))
++ pfx = dpfx;
++
++ for (ip = interfaces; ip; ip = ip->next) {
++ if (interfaces_requested && (ip->flags & (INTERFACE_REQUESTED)) && (ip->name != NULL)) {
++ int n_len = strlen(ip->name);
++
++ new_path_dhclient_pid = (char*) malloc(pfx + n_len + 6);
++ strncpy(new_path_dhclient_pid, path_dhclient_pid, pfx);
++ sprintf(new_path_dhclient_pid + pfx, "-%s.pid", ip->name);
++
++ if ((pidfd = fopen(new_path_dhclient_pid, "r")) != NULL) {
++ e = fscanf(pidfd, "%ld\n", &temp);
++ oldpid = (pid_t)temp;
++
++ if (e != 0 && e != EOF) {
++ if (oldpid) {
++ if (kill(oldpid, SIGTERM) == 0)
++ unlink(path_dhclient_pid);
++ }
++ }
++
++ fclose(pidfd);
++ }
++
++ free(new_path_dhclient_pid);
++ }
++ }
++ }
++ } else {
++ FILE *pidfp = NULL;
++ long temp = 0;
++ pid_t dhcpid = 0;
++ int dhc_running = 0;
++ char procfn[256] = "";
++
++ if ((pidfp = fopen(path_dhclient_pid, "r")) != NULL) {
++ if ((fscanf(pidfp, "%ld", &temp)==1) && ((dhcpid=(pid_t)temp) > 0)) {
++ snprintf(procfn,256,"/proc/%u",dhcpid);
++ dhc_running = (access(procfn, F_OK) == 0);
++ }
++
++ fclose(pidfp);
++ }
++
++ if (dhc_running) {
++ log_fatal("dhclient(%u) is already running - exiting. ", dhcpid);
++ return(1);
+ }
+ }
+
++ write_client_pid_file();
++
+ if (!quiet) {
+ log_info("%s %s", message, PACKAGE_VERSION);
+ log_info(copyright);
diff --git a/server/dhcp/files/dhcp-4.2.0-sendDecline.patch b/server/dhcp/files/dhcp-4.2.0-sendDecline.patch
new file mode 100644
index 0000000000..5f04b6b8aa
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-sendDecline.patch
@@ -0,0 +1,233 @@
+diff -up dhcp-4.2.0/client/dhc6.c.sendDecline dhcp-4.2.0/client/dhc6.c
+--- dhcp-4.2.0/client/dhc6.c.sendDecline 2009-11-20 02:48:58.000000000 +0100
++++ dhcp-4.2.0/client/dhc6.c 2010-07-21 16:18:51.000000000 +0200
+@@ -95,6 +95,8 @@ void do_select6(void *input);
+ void do_refresh6(void *input);
+ static void do_release6(void *input);
+ static void start_bound(struct client_state *client);
++static void start_decline6(struct client_state *client);
++static void do_decline6(void *input);
+ static void start_informed(struct client_state *client);
+ void informed_handler(struct packet *packet, struct client_state *client);
+ void bound_handler(struct packet *packet, struct client_state *client);
+@@ -2140,6 +2142,7 @@ start_release6(struct client_state *clie
+ cancel_timeout(do_select6, client);
+ cancel_timeout(do_refresh6, client);
+ cancel_timeout(do_release6, client);
++ cancel_timeout(do_decline6, client);
+ client->state = S_STOPPED;
+
+ /*
+@@ -2790,6 +2793,7 @@ dhc6_check_reply(struct client_state *cl
+ break;
+
+ case S_STOPPED:
++ case S_DECLINED:
+ action = dhc6_stop_action;
+ break;
+
+@@ -2891,6 +2895,7 @@ dhc6_check_reply(struct client_state *cl
+ break;
+
+ case S_STOPPED:
++ case S_DECLINED:
+ /* Nothing critical to do at this stage. */
+ break;
+
+@@ -3933,17 +3938,23 @@ reply_handler(struct packet *packet, str
+ cancel_timeout(do_select6, client);
+ cancel_timeout(do_refresh6, client);
+ cancel_timeout(do_release6, client);
++ cancel_timeout(do_decline6, client);
+
+ /* If this is in response to a Release/Decline, clean up and return. */
+- if (client->state == S_STOPPED) {
+- if (client->active_lease == NULL)
+- return;
++ if ((client->state == S_STOPPED) ||
++ (client->state == S_DECLINED)) {
++
++ if (client->active_lease != NULL) {
++ dhc6_lease_destroy(&client->active_lease, MDL);
++ client->active_lease = NULL;
++ /* We should never wait for nothing!? */
++ if (stopping_finished())
++ exit(0);
++ }
++
++ if (client->state == S_DECLINED)
++ start_init6(client);
+
+- dhc6_lease_destroy(&client->active_lease, MDL);
+- client->active_lease = NULL;
+- /* We should never wait for nothing!? */
+- if (stopping_finished())
+- exit(0);
+ return;
+ }
+
+@@ -4470,7 +4481,11 @@ start_bound(struct client_state *client)
+ oldia, oldaddr);
+ dhc6_marshall_values("new_", client, lease, ia, addr);
+
+- script_go(client);
++ // when script returns 3, DAD failed
++ if (script_go(client) == 3) {
++ start_decline6(client);
++ return;
++ }
+ }
+
+ /* XXX: maybe we should loop on the old values instead? */
+@@ -4516,6 +4531,151 @@ start_bound(struct client_state *client)
+ dhc6_check_times(client);
+ }
+
++/*
++ * Decline addresses.
++ */
++void
++start_decline6(struct client_state *client)
++{
++ /* Cancel any pending transmissions */
++ cancel_timeout(do_confirm6, client);
++ cancel_timeout(do_select6, client);
++ cancel_timeout(do_refresh6, client);
++ cancel_timeout(do_release6, client);
++ cancel_timeout(do_decline6, client);
++ client->state = S_DECLINED;
++
++ if (client->active_lease == NULL)
++ return;
++
++ /* Set timers per RFC3315 section 18.1.7. */
++ client->IRT = DEC_TIMEOUT * 100;
++ client->MRT = 0;
++ client->MRC = DEC_MAX_RC;
++ client->MRD = 0;
++
++ dhc6_retrans_init(client);
++ client->v6_handler = reply_handler;
++
++ client->refresh_type = DHCPV6_DECLINE;
++ do_decline6(client);
++}
++
++/*
++ * do_decline6() creates a Decline packet and transmits it.
++ */
++static void
++do_decline6(void *input)
++{
++ struct client_state *client;
++ struct data_string ds;
++ int send_ret;
++ struct timeval elapsed, tv;
++
++ client = input;
++
++ if ((client->active_lease == NULL) || !active_prefix(client))
++ return;
++
++ if ((client->MRC != 0) && (client->txcount > client->MRC)) {
++ log_info("Max retransmission count exceeded.");
++ goto decline_done;
++ }
++
++ /*
++ * Start_time starts at the first transmission.
++ */
++ if (client->txcount == 0) {
++ client->start_time.tv_sec = cur_tv.tv_sec;
++ client->start_time.tv_usec = cur_tv.tv_usec;
++ }
++
++ /* elapsed = cur - start */
++ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
++ elapsed.tv_usec = cur_tv.tv_usec - client->start_time.tv_usec;
++ if (elapsed.tv_usec < 0) {
++ elapsed.tv_sec -= 1;
++ elapsed.tv_usec += 1000000;
++ }
++
++ memset(&ds, 0, sizeof(ds));
++ if (!buffer_allocate(&ds.buffer, 4, MDL)) {
++ log_error("Unable to allocate memory for Decline.");
++ goto decline_done;
++ }
++
++ ds.data = ds.buffer->data;
++ ds.len = 4;
++ ds.buffer->data[0] = DHCPV6_DECLINE;
++ memcpy(ds.buffer->data + 1, client->dhcpv6_transaction_id, 3);
++
++ /* Form an elapsed option. */
++ /* Maximum value is 65535 1/100s coded as 0xffff. */
++ if ((elapsed.tv_sec < 0) || (elapsed.tv_sec > 655) ||
++ ((elapsed.tv_sec == 655) && (elapsed.tv_usec > 350000))) {
++ client->elapsed = 0xffff;
++ } else {
++ client->elapsed = elapsed.tv_sec * 100;
++ client->elapsed += elapsed.tv_usec / 10000;
++ }
++
++ client->elapsed = htons(client->elapsed);
++
++ log_debug("XMT: Forming Decline.");
++ make_client6_options(client, &client->sent_options,
++ client->active_lease, DHCPV6_DECLINE);
++ dhcpv6_universe.encapsulate(&ds, NULL, NULL, client, NULL,
++ client->sent_options, &global_scope,
++ &dhcpv6_universe);
++
++ /* Append IA's (but don't release temporary addresses). */
++ if (wanted_ia_na &&
++ dhc6_add_ia_na(client, &ds, client->active_lease,
++ DHCPV6_DECLINE) != ISC_R_SUCCESS) {
++ data_string_forget(&ds, MDL);
++ goto decline_done;
++ }
++ if (wanted_ia_pd &&
++ dhc6_add_ia_pd(client, &ds, client->active_lease,
++ DHCPV6_DECLINE) != ISC_R_SUCCESS) {
++ data_string_forget(&ds, MDL);
++ goto decline_done;
++ }
++
++ /* Transmit and wait. */
++ log_info("XMT: Decline on %s, interval %ld0ms.",
++ client->name ? client->name : client->interface->name,
++ (long int)client->RT);
++
++ send_ret = send_packet6(client->interface, ds.data, ds.len,
++ &DHCPv6DestAddr);
++ if (send_ret != ds.len) {
++ log_error("dhc6: sendpacket6() sent %d of %d bytes",
++ send_ret, ds.len);
++ }
++
++ data_string_forget(&ds, MDL);
++
++ /* Wait RT */
++ tv.tv_sec = cur_tv.tv_sec + client->RT / 100;
++ tv.tv_usec = cur_tv.tv_usec + (client->RT % 100) * 10000;
++ if (tv.tv_usec >= 1000000) {
++ tv.tv_sec += 1;
++ tv.tv_usec -= 1000000;
++ }
++ add_timeout(&tv, do_decline6, client, NULL, NULL);
++ dhc6_retrans_advance(client);
++ return;
++
++decline_done:
++ if (client->active_lease != NULL) {
++ dhc6_lease_destroy(&client->active_lease, MDL);
++ client->active_lease = NULL;
++ }
++ start_init6(client);
++ return;
++}
++
+ /* While bound, ignore packets. In the future we'll want to answer
+ * Reconfigure-Request messages and the like.
+ */
diff --git a/server/dhcp/files/dhcp-4.2.0-unicast-bootp.patch b/server/dhcp/files/dhcp-4.2.0-unicast-bootp.patch
new file mode 100644
index 0000000000..78bc078dcf
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.0-unicast-bootp.patch
@@ -0,0 +1,99 @@
+diff -up dhcp-4.2.0/server/bootp.c.unicast dhcp-4.2.0/server/bootp.c
+--- dhcp-4.2.0/server/bootp.c.unicast 2009-11-20 02:49:03.000000000 +0100
++++ dhcp-4.2.0/server/bootp.c 2010-07-21 13:40:25.000000000 +0200
+@@ -58,6 +58,7 @@ void bootp (packet)
+ char msgbuf [1024];
+ int ignorep;
+ int peer_has_leases = 0;
++ int norelay = 0;
+
+ if (packet -> raw -> op != BOOTREQUEST)
+ return;
+@@ -73,7 +74,7 @@ void bootp (packet)
+ ? inet_ntoa (packet -> raw -> giaddr)
+ : packet -> interface -> name);
+
+- if (!locate_network (packet)) {
++ if ((norelay = locate_network (packet)) == 0) {
+ log_info ("%s: network unknown", msgbuf);
+ return;
+ }
+@@ -390,6 +391,13 @@ void bootp (packet)
+ from, &to, &hto);
+ goto out;
+ }
++ } else if (norelay == 2) {
++ to.sin_addr = raw.ciaddr;
++ to.sin_port = remote_port;
++ if (fallback_interface) {
++ result = send_packet (fallback_interface, (struct packet *)0, &raw, outgoing.packet_length, from, &to, &hto);
++ goto out;
++ }
+
+ /* If it comes from a client that already knows its address
+ and is not requesting a broadcast response, and we can
+diff -up dhcp-4.2.0/server/dhcp.c.unicast dhcp-4.2.0/server/dhcp.c
+--- dhcp-4.2.0/server/dhcp.c.unicast 2010-06-01 19:29:59.000000000 +0200
++++ dhcp-4.2.0/server/dhcp.c 2010-07-21 13:40:25.000000000 +0200
+@@ -4185,6 +4185,7 @@ int locate_network (packet)
+ struct data_string data;
+ struct subnet *subnet = (struct subnet *)0;
+ struct option_cache *oc;
++ int norelay = 0;
+
+ /* See if there's a Relay Agent Link Selection Option, or a
+ * Subnet Selection Option. The Link-Select and Subnet-Select
+@@ -4200,12 +4201,24 @@ int locate_network (packet)
+ from the interface, if there is one. If not, fail. */
+ if (!oc && !packet -> raw -> giaddr.s_addr) {
+ if (packet -> interface -> shared_network) {
+- shared_network_reference
+- (&packet -> shared_network,
+- packet -> interface -> shared_network, MDL);
+- return 1;
++ struct in_addr any_addr;
++ any_addr.s_addr = INADDR_ANY;
++
++ if (!packet -> packet_type && memcmp(&packet -> raw -> ciaddr, &any_addr, 4)) {
++ struct iaddr cip;
++ memcpy(cip.iabuf, &packet -> raw -> ciaddr, 4);
++ cip.len = 4;
++ if (!find_grouped_subnet(&subnet, packet->interface->shared_network, cip, MDL))
++ norelay = 2;
++ }
++
++ if (!norelay) {
++ shared_network_reference(&packet -> shared_network, packet -> interface -> shared_network, MDL);
++ return 1;
++ }
++ } else {
++ return 0;
+ }
+- return 0;
+ }
+
+ /* If there's an option indicating link connection, and it's valid,
+@@ -4228,7 +4241,10 @@ int locate_network (packet)
+ data_string_forget (&data, MDL);
+ } else {
+ ia.len = 4;
+- memcpy (ia.iabuf, &packet -> raw -> giaddr, 4);
++ if (norelay)
++ memcpy (ia.iabuf, &packet->raw->ciaddr, 4);
++ else
++ memcpy (ia.iabuf, &packet->raw->giaddr, 4);
+ }
+
+ /* If we know the subnet on which the IP address lives, use it. */
+@@ -4236,7 +4252,10 @@ int locate_network (packet)
+ shared_network_reference (&packet -> shared_network,
+ subnet -> shared_network, MDL);
+ subnet_dereference (&subnet, MDL);
+- return 1;
++ if (norelay)
++ return norelay;
++ else
++ return 1;
+ }
+
+ /* Otherwise, fail. */
diff --git a/server/dhcp/files/dhcp-4.2.1-retransmission.patch b/server/dhcp/files/dhcp-4.2.1-retransmission.patch
new file mode 100644
index 0000000000..18e447f6a3
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.2.1-retransmission.patch
@@ -0,0 +1,48 @@
+diff -up dhcp-4.2.1b1/client/dhc6.c.retransmission dhcp-4.2.1b1/client/dhc6.c
+--- dhcp-4.2.1b1/client/dhc6.c.retransmission 2011-01-28 08:40:56.000000000 +0100
++++ dhcp-4.2.1b1/client/dhc6.c 2011-01-28 08:39:22.000000000 +0100
+@@ -361,7 +361,7 @@ dhc6_retrans_init(struct client_state *c
+ static void
+ dhc6_retrans_advance(struct client_state *client)
+ {
+- struct timeval elapsed;
++ struct timeval elapsed, elapsed_after_RT;
+
+ /* elapsed = cur - start */
+ elapsed.tv_sec = cur_tv.tv_sec - client->start_time.tv_sec;
+@@ -378,6 +378,8 @@ dhc6_retrans_advance(struct client_state
+ elapsed.tv_sec += 1;
+ elapsed.tv_usec -= 1000000;
+ }
++ elapsed_after_RT.tv_sec = elapsed.tv_sec;
++ elapsed_after_RT.tv_usec = elapsed.tv_usec;
+
+ /*
+ * RT for each subsequent message transmission is based on the previous
+@@ -415,13 +417,10 @@ dhc6_retrans_advance(struct client_state
+ elapsed.tv_usec -= 1000000;
+ }
+ if (elapsed.tv_sec >= client->MRD) {
+- /*
+- * wake at RT + cur = start + MRD
+- */
+- client->RT = client->MRD +
+- (client->start_time.tv_sec - cur_tv.tv_sec);
+- client->RT = client->RT * 100 +
+- (client->start_time.tv_usec - cur_tv.tv_usec) / 10000;
++ client->RT = client->MRD - elapsed_after_RT.tv_sec;
++ client->RT = client->RT * 100 - elapsed_after_RT.tv_usec / 10000;
++ if (client->RT < 0)
++ client->RT = 0;
+ }
+ client->txcount++;
+ }
+@@ -1497,7 +1496,7 @@ check_timing6 (struct client_state *clie
+ }
+
+ /* Check if finished (-1 argument). */
+- if ((client->MRD != 0) && (elapsed.tv_sec > client->MRD)) {
++ if ((client->MRD != 0) && (elapsed.tv_sec >= client->MRD)) {
+ log_info("Max retransmission duration exceeded.");
+ return(CHK_TIM_MRD_EXCEEDED);
+ }
diff --git a/server/dhcp/files/dhcp-4.3.0a1-PPP.patch b/server/dhcp/files/dhcp-4.3.0a1-PPP.patch
new file mode 100644
index 0000000000..7c349fa9b8
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.3.0a1-PPP.patch
@@ -0,0 +1,150 @@
+diff -up dhcp-4.3.0a1/client/dhc6.c.PPP dhcp-4.3.0a1/client/dhc6.c
+--- dhcp-4.3.0a1/client/dhc6.c.PPP 2013-12-19 16:16:45.925550229 +0100
++++ dhcp-4.3.0a1/client/dhc6.c 2013-12-19 16:16:45.930550159 +0100
+@@ -5080,7 +5080,8 @@ make_client6_options(struct client_state
+ */
+ if ((oc = lookup_option(&dhcpv6_universe, *op,
+ D6O_CLIENTID)) == NULL) {
+- if (!option_cache(&oc, &default_duid, NULL, clientid_option,
++ if (default_duid.len == 0 ||
++ !option_cache(&oc, &default_duid, NULL, clientid_option,
+ MDL))
+ log_fatal("Failure assembling a DUID.");
+
+diff -up dhcp-4.3.0a1/client/dhclient.c.PPP dhcp-4.3.0a1/client/dhclient.c
+--- dhcp-4.3.0a1/client/dhclient.c.PPP 2013-12-19 16:16:45.932550131 +0100
++++ dhcp-4.3.0a1/client/dhclient.c 2013-12-19 16:27:38.334473958 +0100
+@@ -926,8 +926,8 @@ main(int argc, char **argv) {
+ if (default_duid.buffer != NULL)
+ data_string_forget(&default_duid, MDL);
+
+- form_duid(&default_duid, MDL);
+- write_duid(&default_duid);
++ if (form_duid(&default_duid, MDL) == ISC_R_SUCCESS)
++ write_duid(&default_duid);
+ }
+ }
+
+@@ -3225,7 +3225,7 @@ write_options(struct client_state *clien
+ * is not how it is intended. Upcoming rearchitecting the client should
+ * address this "one daemon model."
+ */
+-void
++isc_result_t
+ form_duid(struct data_string *duid, const char *file, int line)
+ {
+ struct interface_info *ip;
+@@ -3237,6 +3237,15 @@ form_duid(struct data_string *duid, cons
+ if (ip == NULL)
+ log_fatal("Impossible condition at %s:%d.", MDL);
+
++ while (ip && ip->hw_address.hbuf[0] == HTYPE_RESERVED) {
++ /* Try the other interfaces */
++ log_debug("Cannot form default DUID from interface %s.", ip->name);
++ ip = ip->next;
++ }
++ if (ip == NULL) {
++ return ISC_R_UNEXPECTED;
++ }
++
+ if ((ip->hw_address.hlen == 0) ||
+ (ip->hw_address.hlen > sizeof(ip->hw_address.hbuf)))
+ log_fatal("Impossible hardware address length at %s:%d.", MDL);
+@@ -3272,6 +3281,8 @@ form_duid(struct data_string *duid, cons
+ memcpy(duid->buffer->data + 4, ip->hw_address.hbuf + 1,
+ ip->hw_address.hlen - 1);
+ }
++
++ return ISC_R_SUCCESS;
+ }
+
+ /* Write the default DUID to the lease store. */
+diff -up dhcp-4.3.0a1/common/bpf.c.PPP dhcp-4.3.0a1/common/bpf.c
+--- dhcp-4.3.0a1/common/bpf.c.PPP 2013-12-19 16:16:45.868551024 +0100
++++ dhcp-4.3.0a1/common/bpf.c 2013-12-19 16:16:45.934550103 +0100
+@@ -602,6 +602,22 @@ get_hw_addr(const char *name, struct har
+ memcpy(&hw->hbuf[1], LLADDR(sa), sa->sdl_alen);
+ break;
+ #endif /* IFT_FDDI */
++#if defined(IFT_PPP)
++ case IFT_PPP:
++ if (local_family != AF_INET6)
++ log_fatal("Unsupported device type %d for \"%s\"",
++ sa->sdl_type, name);
++ hw->hlen = 0;
++ hw->hbuf[0] = HTYPE_RESERVED;
++ /* 0xdeadbeef should never occur on the wire,
++ * and is a signature that something went wrong.
++ */
++ hw->hbuf[1] = 0xde;
++ hw->hbuf[2] = 0xad;
++ hw->hbuf[3] = 0xbe;
++ hw->hbuf[4] = 0xef;
++ break;
++#endif
+ default:
+ log_fatal("Unsupported device type %d for \"%s\"",
+ sa->sdl_type, name);
+diff -up dhcp-4.3.0a1/common/lpf.c.PPP dhcp-4.3.0a1/common/lpf.c
+--- dhcp-4.3.0a1/common/lpf.c.PPP 2013-12-19 16:16:45.848551303 +0100
++++ dhcp-4.3.0a1/common/lpf.c 2013-12-19 16:16:45.934550103 +0100
+@@ -511,6 +511,22 @@ get_hw_addr(const char *name, struct har
+ hw->hbuf[0] = HTYPE_FDDI;
+ memcpy(&hw->hbuf[1], sa->sa_data, 6);
+ break;
++#if defined(ARPHRD_PPP)
++ case ARPHRD_PPP:
++ if (local_family != AF_INET6)
++ log_fatal("Unsupported device type %d for \"%s\"",
++ sa->sa_family, name);
++ hw->hlen = 0;
++ hw->hbuf[0] = HTYPE_RESERVED;
++ /* 0xdeadbeef should never occur on the wire,
++ * and is a signature that something went wrong.
++ */
++ hw->hbuf[1] = 0xde;
++ hw->hbuf[2] = 0xad;
++ hw->hbuf[3] = 0xbe;
++ hw->hbuf[4] = 0xef;
++ break;
++#endif
+ default:
+ log_fatal("Unsupported device type %ld for \"%s\"",
+ (long int)sa->sa_family, name);
+diff -up dhcp-4.3.0a1/includes/dhcp.h.PPP dhcp-4.3.0a1/includes/dhcp.h
+--- dhcp-4.3.0a1/includes/dhcp.h.PPP 2013-12-19 16:16:45.919550313 +0100
++++ dhcp-4.3.0a1/includes/dhcp.h 2013-12-19 16:16:45.936550076 +0100
+@@ -85,6 +85,8 @@ struct dhcp_packet {
+ * is no standard for this so we
+ * just steal a type */
+
++#define HTYPE_RESERVED 0 /* RFC 5494 */
++
+ /* Magic cookie validating dhcp options field (and bootp vendor
+ extensions field). */
+ #define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+diff -up dhcp-4.3.0a1/includes/dhcpd.h.PPP dhcp-4.3.0a1/includes/dhcpd.h
+--- dhcp-4.3.0a1/includes/dhcpd.h.PPP 2013-12-19 16:16:45.935550090 +0100
++++ dhcp-4.3.0a1/includes/dhcpd.h 2013-12-19 16:28:33.468709007 +0100
+@@ -2824,7 +2824,7 @@ void client_dns_remove(struct client_sta
+
+ void dhcpv4_client_assignments(void);
+ void dhcpv6_client_assignments(void);
+-void form_duid(struct data_string *duid, const char *file, int line);
++isc_result_t form_duid(struct data_string *duid, const char *file, int line);
+
+ /* dhc6.c */
+ void dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line);
+diff -up dhcp-4.3.0a1/server/dhcpv6.c.PPP dhcp-4.3.0a1/server/dhcpv6.c
+--- dhcp-4.3.0a1/server/dhcpv6.c.PPP 2013-12-19 16:16:45.901550564 +0100
++++ dhcp-4.3.0a1/server/dhcpv6.c 2013-12-19 16:16:45.937550062 +0100
+@@ -307,6 +307,9 @@ generate_new_server_duid(void) {
+ if (p->hw_address.hlen > 0) {
+ break;
+ }
++ if (p->next == NULL && p->hw_address.hbuf[0] == HTYPE_RESERVED) {
++ log_error("Can not generate DUID from interfaces which do not have hardware addresses, please configure server-duid!");
++ }
+ }
+ if (p == NULL) {
+ return ISC_R_UNEXPECTED;
\ No newline at end of file
diff --git a/server/dhcp/files/dhcp-4.3.0a1-errwarn-message.patch b/server/dhcp/files/dhcp-4.3.0a1-errwarn-message.patch
new file mode 100644
index 0000000000..223f1a9bc8
--- /dev/null
+++ b/server/dhcp/files/dhcp-4.3.0a1-errwarn-message.patch
@@ -0,0 +1,30 @@
+diff -up dhcp-4.3.0a1/omapip/errwarn.c.errwarn dhcp-4.3.0a1/omapip/errwarn.c
+--- dhcp-4.3.0a1/omapip/errwarn.c.errwarn 2012-07-11 22:46:29.000000000 +0200
++++ dhcp-4.3.0a1/omapip/errwarn.c 2013-12-19 15:09:17.857125042 +0100
+@@ -76,20 +76,13 @@ void log_fatal (const char * fmt, ... )
+
+ #if !defined (NOMINUM)
+ log_error ("%s", "");
+- log_error ("If you did not get this software from ftp.isc.org, please");
+- log_error ("get the latest from ftp.isc.org and install that before");
+- log_error ("requesting help.");
++ log_error ("This version of ISC DHCP is based on the release available");
++ log_error ("on ftp.isc.org. Features have been added and other changes");
++ 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 ("If you did get this software from ftp.isc.org and have not");
+- log_error ("yet read the README, please read it before requesting help.");
+- log_error ("If you intend to request help from the dhcp-server@isc.org");
+- log_error ("mailing list, please read the section on the README about");
+- log_error ("submitting bug reports and requests for help.");
+- log_error ("%s", "");
+- log_error ("Please do not under any circumstances send requests for");
+- log_error ("help directly to the authors of this software - please");
+- log_error ("send them to the appropriate mailing list as described in");
+- log_error ("the README file.");
++ log_error ("Please report for this software via the Red Hat Bugzilla site:");
++ log_error (" http://bugzilla.redhat.com");
+ log_error ("%s", "");
+ log_error ("exiting.");
+ #endif
\ No newline at end of file
diff --git a/server/dhcp/files/dhcpd b/server/dhcp/files/dhcpd
new file mode 100644
index 0000000000..2af815e3e3
--- /dev/null
+++ b/server/dhcp/files/dhcpd
@@ -0,0 +1,15 @@
+# DHCP Server Configuration file for Pisi Linux
+
+# Specify a configuration file - the default is /etc/dhcp/dhcpd.conf
+DHCPD_CONF="/etc/dhcp/dhcpd.conf"
+
+# Configure which interface or interfaces to for dhcpd to listen on.
+# List all interfaces space separated. If this is not specified then
+# we listen on all interfaces.
+INTERFACES=""
+
+# Insert any other dhcpd options - see the man page for a full list.
+DHCPD_ARGS=""
+
+# Wait for interfaces being up (in seconds.)
+TIMEOUT=10
diff --git a/server/dhcp/files/dhcpd.conf b/server/dhcp/files/dhcpd.conf
new file mode 100644
index 0000000000..d1449ba360
--- /dev/null
+++ b/server/dhcp/files/dhcpd.conf
@@ -0,0 +1,31 @@
+# DHCP Server Configuration file.
+# see /usr/share/doc/dhcp/dhcpd.conf.sample
+# see 'man 5 dhcpd.conf'
+#
+#############################################
+# ddns-update-style none;
+#
+# default-lease-time 21600;
+# max-lease-time 21600;
+#
+# option subnet-mask 255.255.255.0;
+# option broadcast-address 10.0.0.255;
+# option routers 10.0.0.1;
+# option domain-name-servers 10.0.0.1;
+# option domain-name "pisilinux";
+#
+# next-server 10.0.0.1;
+# get-lease-hostnames on;
+#
+# option root-path "10.0.0.1:/opt/ptsp";
+#
+# subnet 10.0.0.0 netmask 255.255.255.0 {
+# range 10.0.0.1 10.0.0.99;
+
+ #Send this file for pxe file requests
+ #filename "/pts/latest-ptsp/pxelinux.0";
+# }
+# host AccessPoint {
+# hardware ethernet XX:XX:XX:XX:XX:XX;
+# fixed-address 10.0.0.120;
+#}
diff --git a/server/dhcp/files/dhcpd6 b/server/dhcp/files/dhcpd6
new file mode 100644
index 0000000000..b769b9d3a6
--- /dev/null
+++ b/server/dhcp/files/dhcpd6
@@ -0,0 +1,15 @@
+# DHCPv6 Server Configuration file for Pisi Linux
+
+# Specify a configuration file - the default is /etc/dhcp/dhcpd.conf
+DHCPD_CONF="/etc/dhcp/dhcpd.conf"
+
+# Configure which interface or interfaces to for dhcpd to listen on.
+# List all interfaces space separated. If this is not specified then
+# we listen on all interfaces.
+INTERFACES=""
+
+# Insert any other dhcpd options - see the man page for a full list.
+DHCPD_ARGS=""
+
+# Wait for interfaces being up (in seconds.)
+TIMEOUT=10
diff --git a/server/dhcp/files/dhcpd6.conf b/server/dhcp/files/dhcpd6.conf
new file mode 100644
index 0000000000..6bfb59fbef
--- /dev/null
+++ b/server/dhcp/files/dhcpd6.conf
@@ -0,0 +1,32 @@
+# DHCP for IPv6 Server Configuration file.
+# see /usr/share/doc/dhcp/dhcpd6.conf.sample
+# see 'man 5 dhcpd.conf'
+# run 'service dhcpd6 start' or 'dhcpd -6 -cf /etc/dhcp/dhcpd6.conf'
+#
+#############################################
+# ddns-update-style none;
+#
+# default-lease-time 21600;
+# max-lease-time 21600;
+#
+# option subnet-mask 255.255.255.0;
+# option broadcast-address 10.0.0.255;
+# option routers 10.0.0.1;
+# option domain-name-servers 10.0.0.1;
+# option domain-name "pisilinux";
+#
+# next-server 10.0.0.1;
+# get-lease-hostnames on;
+#
+# option root-path "10.0.0.1:/opt/ptsp";
+#
+# subnet 10.0.0.0 netmask 255.255.255.0 {
+# range 10.0.0.1 10.0.0.99;
+
+ #Send this file for pxe file requests
+ #filename "/pts/latest-ptsp/pxelinux.0";
+# }
+# host AccessPoint {
+# hardware ethernet XX:XX:XX:XX:XX:XX;
+# fixed-address 10.0.0.120;
+#}
diff --git a/server/dhcp/files/dhcrelay b/server/dhcp/files/dhcrelay
new file mode 100644
index 0000000000..19d6b75087
--- /dev/null
+++ b/server/dhcp/files/dhcrelay
@@ -0,0 +1,14 @@
+# DHCP Relay Server Configuration file for Pisi Linux
+
+# Configure which interface or interfaces to for dhcpd to listen on.
+# List all interfaces space separated. If this is not specified then
+# we listen on all interfaces.
+#
+# DHCPv4 only
+INTERFACES=""
+
+#DHCPv4 only
+DHCP_SERVERS=""
+
+# Insert any other dhcpd options - see the man page for a full list.
+DHCRELAY_ARGS=""
diff --git a/server/dhcp/pspec.xml b/server/dhcp/pspec.xml
new file mode 100644
index 0000000000..f423e13bf6
--- /dev/null
+++ b/server/dhcp/pspec.xml
@@ -0,0 +1,151 @@
+
+
+
+
+ dhcp
+ http://www.isc.org/products/DHCP
+
+ PisiLinux Community
+ admins@pisilinux.org
+
+ isc-dhcp
+ app:console
+ library
+ service
+ Dynamic host configuration protocol software
+ DHCP (Dynamic Host Configuration Protocol) is a protocol which allows individual devices on an IP network to get their own network configuration information (IP address, subnetmask, broadcast address, etc.) from a DHCP server.
+ http://ftp.isc.org/isc/dhcp/4.3.0/dhcp-4.3.0.tar.gz
+
+ groff
+ openldap-client
+ bind-devel
+
+
+
+
+
+ dhcp-4.2.0-release-by-ifup.patch
+ dhcp-4.2.0-dhclient-decline-backoff.patch
+ dhcp-4.2.0-unicast-bootp.patch
+
+ dhcp-4.2.0-default-requested-options.patch
+
+ dhcp-4.2.0-paths.patch
+
+ dhcp-4.2.0-inherit-leases.patch
+ dhcp-4.2.0-garbage-chars.patch
+
+ dhcp-4.2.0-IFNAMSIZ.patch
+ dhcp-4.2.0-add_timeout_when_NULL.patch
+
+ dhcp-4.2.0-logpid.patch
+ dhcp-4.2.0-sendDecline.patch
+ dhcp-4.2.1-retransmission.patch
+
+ dhcp-4.2.0-honor-expired.patch
+
+
+ dhcp-4.3.0a1-PPP.patch
+ dhcp-4.2.0-P2-omapi.patch
+
+
+
+
+
+ dhcp
+
+ openldap-client
+ bind-libs
+
+
+ /etc
+ /usr/bin
+ /usr/sbin
+ /usr/lib
+ /var/lib
+ /run
+ /usr/share/man
+ /usr/share/doc
+
+
+ dhcpd
+ dhcpd6
+ dhcrelay
+ dhcpd.conf
+
+
+
+ System.Service
+ System.Service
+ System.Service
+ System.Package
+
+
+
+
+ dhclient
+ app:console
+ Provides the dhclient ISC DHCP client daemon
+
+ dhcp
+ bind-libs
+
+
+
+ /etc/dhcp/dhclient.conf
+ /usr/sbin/dhclient
+
+ /var/lib/dhclient
+ /usr/share/man/man5/dhclient*
+ /usr/share/man/man8/dhclient*
+ /usr/share/man/man5/dhcp-options*
+ /usr/share/man/man5/dhcp-eval*
+ /usr/share/doc/dhcp/dhclient*
+
+
+ dhclient.conf
+
+
+
+
+
+
+ dhcp-devel
+ Development files for dhcp
+
+ dhcp
+
+
+ /usr/include
+ /usr/share/man/man3
+
+
+
+
+
+ 2014-05-19
+ 4.3.0
+ Version Bump
+ Vedat Demir
+ vedat@pisilinux.org
+
+
+ 2014-01-22
+ 4.2.5
+ Version Bump
+ Stefan Gronewold(groni)
+ groni@pisilinux.org
+
+
+ 2012-10-14
+ 4.2.3
+ First release
+ PisiLinux Community
+ admins@pisilinux.org
+
+
+
diff --git a/server/dhcp/translations.xml b/server/dhcp/translations.xml
new file mode 100644
index 0000000000..281f1fff7d
--- /dev/null
+++ b/server/dhcp/translations.xml
@@ -0,0 +1,19 @@
+
+
+
+ dhcp
+ DHCP Sunucusu
+ IP adresi atanmasını ve TCP/IP bilgilerinin yapılandırılmasını sağlayan DHCP Sunucusu
+ DHCP-Server
+
+
+
+ dhclient
+ DHCP İstemcisi
+
+
+
+ dhcp-devel
+ dhcp için geliştirme dosyaları
+
+