From d97c47cad830d00c9da685cc4ea157d6185f6c97 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 3 Mar 2009 18:28:20 -0800 Subject: auto import from //depot/cupcake/@135843 --- Android.mk | 66 -- Makefile | 51 -- README | 67 -- android.conf | 6 - bpf-filter.h | 101 --- bpf.c | 206 ----- client.c | 1839 --------------------------------------- client.h | 35 - common.c | 327 ------- common.h | 87 -- config.h | 75 -- configure.c | 420 --------- configure.h | 41 - dhcp.c | 1251 -------------------------- dhcp.h | 178 ---- dhcpcd-hooks/01-test | 7 - dhcpcd-hooks/10-mtu | 5 - dhcpcd-hooks/20-dns.conf | 32 - dhcpcd-hooks/20-resolv.conf | 107 --- dhcpcd-hooks/29-lookup-hostname | 34 - dhcpcd-hooks/30-hostname | 28 - dhcpcd-hooks/50-dhcpcd-compat | 31 - dhcpcd-hooks/50-ntp.conf | 82 -- dhcpcd-hooks/50-yp.conf | 49 -- dhcpcd-hooks/90-NetworkManager | 8 - dhcpcd-hooks/95-configured | 26 - dhcpcd-hooks/Makefile | 13 - dhcpcd-run-hooks | 31 - dhcpcd-run-hooks.8 | 113 --- dhcpcd-run-hooks.8.in | 113 --- dhcpcd-run-hooks.in | 138 --- dhcpcd.8 | 430 --------- dhcpcd.8.in | 430 --------- dhcpcd.c | 1038 ---------------------- dhcpcd.conf | 13 - dhcpcd.conf.5 | 155 ---- dhcpcd.conf.5.in | 155 ---- dhcpcd.h | 95 -- if-bsd.c | 241 ----- if-linux.c | 379 -------- logger.c | 89 -- logger.h | 43 - lpf.c | 168 ---- mk/cc.mk | 28 - mk/depend.mk | 11 - mk/dist.mk | 31 - mk/files.mk | 9 - mk/man.mk | 25 - mk/os-BSD.mk | 5 - mk/os-Darwin.mk | 5 - mk/os-Linux.mk | 8 - mk/os.mk | 7 - mk/prog.mk | 68 -- mk/scripts.mk | 9 - mk/sys.mk | 14 - net.c | 707 --------------- net.h | 176 ---- showlease.c | 349 -------- signals.c | 125 --- signals.h | 37 - 60 files changed, 10417 deletions(-) delete mode 100644 Android.mk delete mode 100644 Makefile delete mode 100644 README delete mode 100644 android.conf delete mode 100644 bpf-filter.h delete mode 100644 bpf.c delete mode 100644 client.c delete mode 100644 client.h delete mode 100644 common.c delete mode 100644 common.h delete mode 100644 config.h delete mode 100644 configure.c delete mode 100644 configure.h delete mode 100644 dhcp.c delete mode 100644 dhcp.h delete mode 100644 dhcpcd-hooks/01-test delete mode 100644 dhcpcd-hooks/10-mtu delete mode 100644 dhcpcd-hooks/20-dns.conf delete mode 100644 dhcpcd-hooks/20-resolv.conf delete mode 100644 dhcpcd-hooks/29-lookup-hostname delete mode 100644 dhcpcd-hooks/30-hostname delete mode 100644 dhcpcd-hooks/50-dhcpcd-compat delete mode 100644 dhcpcd-hooks/50-ntp.conf delete mode 100644 dhcpcd-hooks/50-yp.conf delete mode 100644 dhcpcd-hooks/90-NetworkManager delete mode 100644 dhcpcd-hooks/95-configured delete mode 100644 dhcpcd-hooks/Makefile delete mode 100755 dhcpcd-run-hooks delete mode 100644 dhcpcd-run-hooks.8 delete mode 100644 dhcpcd-run-hooks.8.in delete mode 100644 dhcpcd-run-hooks.in delete mode 100644 dhcpcd.8 delete mode 100644 dhcpcd.8.in delete mode 100644 dhcpcd.c delete mode 100644 dhcpcd.conf delete mode 100644 dhcpcd.conf.5 delete mode 100644 dhcpcd.conf.5.in delete mode 100644 dhcpcd.h delete mode 100644 if-bsd.c delete mode 100644 if-linux.c delete mode 100644 logger.c delete mode 100644 logger.h delete mode 100644 lpf.c delete mode 100644 mk/cc.mk delete mode 100644 mk/depend.mk delete mode 100644 mk/dist.mk delete mode 100644 mk/files.mk delete mode 100644 mk/man.mk delete mode 100644 mk/os-BSD.mk delete mode 100644 mk/os-Darwin.mk delete mode 100644 mk/os-Linux.mk delete mode 100644 mk/os.mk delete mode 100644 mk/prog.mk delete mode 100644 mk/scripts.mk delete mode 100644 mk/sys.mk delete mode 100644 net.c delete mode 100644 net.h delete mode 100644 showlease.c delete mode 100644 signals.c delete mode 100644 signals.h diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 5cac7ea..0000000 --- a/Android.mk +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2006 The Android Open Source Project -ifneq ($(TARGET_SIMULATOR),true) -LOCAL_PATH:= $(call my-dir) - -etc_dir := $(TARGET_OUT)/etc/dhcpcd -hooks_dir := dhcpcd-hooks -hooks_target := $(etc_dir)/$(hooks_dir) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := common.c dhcp.c dhcpcd.c logger.c net.c \ - signals.c configure.c client.c if-linux.c lpf.c -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -LOCAL_SHARED_LIBRARIES := libc libcutils -LOCAL_MODULE = dhcpcd -LOCAL_MODULE_TAGS := user development -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) -LOCAL_SRC_FILES := showlease.c -LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -LOCAL_SHARED_LIBRARIES := libc -LOCAL_MODULE = showlease -LOCAL_MODULE_TAGS := user development -include $(BUILD_EXECUTABLE) - -include $(CLEAR_VARS) -LOCAL_MODULE := dhcpcd.conf -LOCAL_MODULE_TAGS := user development -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(etc_dir) -LOCAL_SRC_FILES := android.conf -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := dhcpcd-run-hooks -LOCAL_MODULE_TAGS := user development -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(etc_dir) -LOCAL_SRC_FILES := $(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := 01-test -LOCAL_MODULE_TAGS := user development -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(hooks_target) -LOCAL_SRC_FILES := $(hooks_dir)/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := 20-dns.conf -LOCAL_MODULE_TAGS := user development -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(hooks_target) -LOCAL_SRC_FILES := $(hooks_dir)/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -include $(CLEAR_VARS) -LOCAL_MODULE := 95-configured -LOCAL_MODULE_TAGS := user development -LOCAL_MODULE_CLASS := ETC -LOCAL_MODULE_PATH := $(hooks_target) -LOCAL_SRC_FILES := $(hooks_dir)/$(LOCAL_MODULE) -include $(BUILD_PREBUILT) - -endif diff --git a/Makefile b/Makefile deleted file mode 100644 index a6b066b..0000000 --- a/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# Makefile based on BSD make. -# Our mk stubs also work with GNU make. -# Copyright 2008 Roy Marples - -PROG= dhcpcd -SRCS= common.c dhcp.c dhcpcd.c logger.c net.c signals.c -SRCS+= configure.c client.c -SRCS+= ${SRC_IF} ${SRC_PF} - -LIBEXECDIR?= ${PREFIX}/system/etc/dhcpcd -SCRIPT= ${LIBEXECDIR}/dhcpcd-run-hooks -HOOKDIR= ${LIBEXECDIR}/dhcpcd-hooks - -BINDIR= ${PREFIX}/sbin -DBDIR= /data/misc/dhcp -SYSCONFDIR?= ${PREFIX}/system/etc/dhcpcd - -MAN= dhcpcd.conf.5 dhcpcd.8 dhcpcd-run-hooks.8 -CLEANFILES= dhcpcd.conf.5 dhcpcd.8 dhcpcd-run-hooks.8 - -SCRIPTS= dhcpcd-run-hooks -SCRIPTSDIR= ${LIBEXECDIR} -CLEANFILES+= dhcpcd-run-hooks - -FILES= dhcpcd.conf -FILESDIR= ${SYSCONFDIR} - -CPPFLAGS+= -DDBDIR=\"${DBDIR}\" -CPPFLAGS+= -DSCRIPT=\"${SCRIPT}\" -CPPFLAGS+= -DSYSCONFDIR=\"${SYSCONFDIR}\" -LDADD+= ${LIBRT} - -SUBDIRS= dhcpcd-hooks - -.SUFFIXES: .in .sh.in - -SED_DBDIR= -e 's:@DBDIR@:${DBDIR}:g' -SED_HOOKDIR= -e 's:@HOOKDIR@:${HOOKDIR}:g' -SED_SCRIPT= -e 's:@SCRIPT@:${SCRIPT}:g' -SED_SYS= -e 's:@SYSCONFDIR@:${SYSCONFDIR}:g' - -.in: - ${SED} ${SED_DBDIR} ${SED_HOOKDIR} ${SED_SCRIPT} ${SED_SYS} $< > $@ - -.sh.in.sh: - ${SED} ${SED_HOOKDIR} ${SED_SCRIPT} ${SED_SYS} $< > $@ - -MK= mk -include ${MK}/sys.mk -include ${MK}/os.mk -include ${MK}/prog.mk diff --git a/README b/README deleted file mode 100644 index 50294fe..0000000 --- a/README +++ /dev/null @@ -1,67 +0,0 @@ -dhcpcd-4 - DHCP client daemon -Copyright 2006-2008 Roy Marples - - -Installation ------------- -Edit config.h to match your building requirements. -Then just make; make install -man dhcpcd for command line options - - -Notes ------ -If you're cross compiling you may need to set the below knobs to avoid -automatic tests. -OS=BSD | Linux - -If you're building for an MMU-less system where fork() does not work, you -should add -DTHERE_IS_NO_FORK to your CPPFLAGS. -This also puts the --no-background flag on and stops the --background flag -from working. - -You can change the default dir with these knobs. -For example, to satisfy FHS compliance you would do this:- -LIBEXECDIR=/lib/dhcpcd -DBDIR=/var/lib/dhcpcd - -We now default to using -std=c99. For 64-bit linux, this always works, but -for 32-bit linux it requires either gnu99 or a patch to asm/types.h. -Most distros patch linux headers so this should work fine. -linux-2.6.24 finally ships with a working 32-bit header. -If your linux headers are older, or your distro hasn't patched them you can -set CSTD=gnu99 to work around this. - - -Hooks ------ -Not all the hooks in dhcpcd-hooks are installed by default. -By default we install 01-test, 10-mtu, 20-resolv.conf and 30-hostname. -To add more simply add them in the HOOKSCRIPTS variable. -make HOOKSCRIPTS=50-ntp install - - -Compatibility -------------- -If you require compatibility with dhcpcd-3 and older style variables, -you can install 50-dhcpcd-compat into the directory $LIBEXECDIR/dhcpcd-hooks -We don't install this by default. -You should also add -DCMDLINE_COMPAT to your CPPFLAGS if you need to be fully -commandline compatible with prior versions. - -dhcpcd-3 enabled DUID support by default - this has changed in dhcpcd-4. -You can enable it via the --duid, -D command line option or by using the -duid directive in dhcpcd.conf. -If CMDLINE_COMPAT is defined the we renable DUID support by default IF -the dhcpcd.duid file exits. This keeps the clients working as they were, -which is good. - -dhcpcd-4 is NOT fully commandline compatible with dhcpcd-2 and older and -changes the meaning of some options. - - -ChangeLog ---------- -We no longer supply a ChangeLog. -However, you're more than welcome to read the git commit comments at -http://git.marples.name/?p=dhcpcd.git;a=summary diff --git a/android.conf b/android.conf deleted file mode 100644 index 5aa418d..0000000 --- a/android.conf +++ /dev/null @@ -1,6 +0,0 @@ -# dhcpcd configuration for Android Wi-Fi interface -# See dhcpcd.conf(5) for details. - -interface tiwlan0 -# dhcpcd-run-hooks uses these options. -option subnet_mask, routers, domain_name_servers diff --git a/bpf-filter.h b/bpf-filter.h deleted file mode 100644 index 881f678..0000000 --- a/bpf-filter.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef BPF_ETHCOOK -# define BPF_ETHCOOK 0 -#endif -#ifndef BPF_WHOLEPACKET -# define BPF_WHOLEPACKET ~0U -#endif -static const struct bpf_insn const arp_bpf_filter [] = { -#ifndef BPF_SKIPTYPE - /* Make sure this is an ARP packet... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_ARP, 0, 3), -#endif - /* Make sure this is an ARP REQUEST... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), - /* or ARP REPLY... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 0, 1), - /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET), - /* Otherwise, drop it. */ - BPF_STMT(BPF_RET + BPF_K, 0), -}; -static const size_t arp_bpf_filter_len = - sizeof(arp_bpf_filter) / sizeof(arp_bpf_filter[0]); - - -/* dhcp_bpf_filter taken from bpf.c in dhcp-3.1.0 - * - * Copyright (c) 2004,2007 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1996-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * - * http://www.isc.org/ - */ - -static const struct bpf_insn const dhcp_bpf_filter [] = { -#ifndef BPF_SKIPTYPE - /* Make sure this is an IP packet... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8), -#endif - /* Make sure it's a UDP packet... */ - BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23 + BPF_ETHCOOK), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6), - /* Make sure this isn't a fragment... */ - BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20 + BPF_ETHCOOK), - BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0), - /* Get the IP header length... */ - BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14 + BPF_ETHCOOK), - /* Make sure it's to the right port... */ - BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16 + BPF_ETHCOOK), - BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_CLIENT_PORT, 0, 1), - /* If we passed all the tests, ask for the whole packet. */ - BPF_STMT(BPF_RET + BPF_K, BPF_WHOLEPACKET), - /* Otherwise, drop it. */ - BPF_STMT(BPF_RET + BPF_K, 0), -}; -static const size_t dhcp_bpf_filter_len = - sizeof(dhcp_bpf_filter) / sizeof(dhcp_bpf_filter[0]); diff --git a/bpf.c b/bpf.c deleted file mode 100644 index 96e53a1..0000000 --- a/bpf.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "dhcp.h" -#include "logger.h" -#include "net.h" -#include "bpf-filter.h" - -int -open_socket(struct interface *iface, int protocol) -{ - int fd = -1; - int *fdp = NULL; - struct ifreq ifr; - int buf_len = 0; - struct bpf_version pv; - struct bpf_program pf; -#ifdef BIOCIMMEDIATE - int flags; -#endif -#ifdef _PATH_BPF - fd = open(_PATH_BPF, O_RDWR | O_NONBLOCK); -#else - char *device; - int n = 0; - - device = xmalloc(sizeof(char) * PATH_MAX); - do { - snprintf(device, PATH_MAX, "/dev/bpf%d", n++); - fd = open(device, O_RDWR | O_NONBLOCK); - } while (fd == -1 && errno == EBUSY); - free(device); -#endif - - if (fd == -1) - return -1; - - if (ioctl(fd, BIOCVERSION, &pv) == -1) - goto eexit; - if (pv.bv_major != BPF_MAJOR_VERSION || - pv.bv_minor < BPF_MINOR_VERSION) { - logger(LOG_ERR, "BPF version mismatch - recompile " PACKAGE); - goto eexit; - } - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); - if (ioctl(fd, BIOCSETIF, &ifr) == -1) - goto eexit; - - /* Get the required BPF buffer length from the kernel. */ - if (ioctl(fd, BIOCGBLEN, &buf_len) == -1) - goto eexit; - if (iface->buffer_size != (size_t)buf_len) { - free(iface->buffer); - iface->buffer_size = buf_len; - iface->buffer = xmalloc(buf_len); - iface->buffer_len = iface->buffer_pos = 0; - } - -#ifdef BIOCIMMEDIATE - flags = 1; - if (ioctl(fd, BIOCIMMEDIATE, &flags) == -1) - goto eexit; -#endif - - /* Install the DHCP filter */ - if (protocol == ETHERTYPE_ARP) { - pf.bf_insns = UNCONST(arp_bpf_filter); - pf.bf_len = arp_bpf_filter_len; - fdp = &iface->arp_fd; - } else { - pf.bf_insns = UNCONST(dhcp_bpf_filter); - pf.bf_len = dhcp_bpf_filter_len; - fdp = &iface->raw_fd; - } - if (ioctl(fd, BIOCSETF, &pf) == -1) - goto eexit; - if (set_cloexec(fd) == -1) - goto eexit; - if (fdp) { - if (*fdp != -1) - close(*fdp); - *fdp = fd; - } - return fd; - -eexit: - free(iface->buffer); - iface->buffer = NULL; - close(fd); - return -1; -} - -ssize_t -send_raw_packet(const struct interface *iface, int protocol, - const void *data, ssize_t len) -{ - struct iovec iov[2]; - struct ether_header hw; - int fd; - - memset(&hw, 0, ETHER_HDR_LEN); - memset(&hw.ether_dhost, 0xff, ETHER_ADDR_LEN); - hw.ether_type = htons(protocol); - iov[0].iov_base = &hw; - iov[0].iov_len = ETHER_HDR_LEN; - iov[1].iov_base = UNCONST(data); - iov[1].iov_len = len; - if (protocol == ETHERTYPE_ARP) - fd = iface->arp_fd; - else - fd = iface->raw_fd; - return writev(fd, iov, 2); -} - -/* BPF requires that we read the entire buffer. - * So we pass the buffer in the API so we can loop on >1 packet. */ -ssize_t -get_raw_packet(struct interface *iface, int protocol, - void *data, ssize_t len) -{ - int fd = -1; - struct bpf_hdr packet; - ssize_t bytes; - const unsigned char *payload; - - if (protocol == ETHERTYPE_ARP) - fd = iface->arp_fd; - else - fd = iface->raw_fd; - - for (;;) { - if (iface->buffer_len == 0) { - bytes = read(fd, iface->buffer, iface->buffer_size); - if (bytes == -1) - return errno == EAGAIN ? 0 : -1; - else if ((size_t)bytes < sizeof(packet)) - return -1; - iface->buffer_len = bytes; - iface->buffer_pos = 0; - } - bytes = -1; - memcpy(&packet, iface->buffer + iface->buffer_pos, - sizeof(packet)); - if (packet.bh_caplen != packet.bh_datalen) - goto next; /* Incomplete packet, drop. */ - if (iface->buffer_pos + packet.bh_caplen + packet.bh_hdrlen > - iface->buffer_len) - goto next; /* Packet beyond buffer, drop. */ - payload = iface->buffer + packet.bh_hdrlen + ETHER_HDR_LEN; - bytes = packet.bh_caplen - ETHER_HDR_LEN; - if (bytes > len) - bytes = len; - memcpy(data, payload, bytes); -next: - iface->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen + - packet.bh_caplen); - if (iface->buffer_pos >= iface->buffer_len) - iface->buffer_len = iface->buffer_pos = 0; - if (bytes != -1) - return bytes; - } -} diff --git a/client.c b/client.c deleted file mode 100644 index c34d318..0000000 --- a/client.c +++ /dev/null @@ -1,1839 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#ifdef __linux__ -# include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "client.h" -#include "configure.h" -#include "dhcp.h" -#include "dhcpcd.h" -#include "net.h" -#include "logger.h" -#include "signals.h" - -#define IPV4LL_LEASETIME 2 - -/* Some platforms don't define INFTIM */ -#ifndef INFTIM -# define INFTIM -1 -#endif - -#define STATE_INIT 0 -#define STATE_DISCOVERING 1 -#define STATE_REQUESTING 2 -#define STATE_BOUND 3 -#define STATE_RENEWING 4 -#define STATE_REBINDING 5 -#define STATE_REBOOT 6 -#define STATE_RENEW_REQUESTED 7 -#define STATE_INIT_IPV4LL 8 -#define STATE_PROBING 9 -#define STATE_ANNOUNCING 10 - -/* Constants taken from RFC 2131. */ -#define T1 0.5 -#define T2 0.875 -#define DHCP_BASE 4 -#define DHCP_MAX 64 -#define DHCP_RAND_MIN -1 -#define DHCP_RAND_MAX 1 -#define DHCP_ARP_FAIL 10 - -/* We should define a maximum for the NAK exponential backoff */ -#define NAKOFF_MAX 60 - -#define SOCKET_CLOSED 0 -#define SOCKET_OPEN 1 - -/* These are for IPV4LL, RFC 3927. */ -#define PROBE_WAIT 1 -#define PROBE_NUM 3 -#define PROBE_MIN 1 -#define PROBE_MAX 2 -#define ANNOUNCE_WAIT 2 -/* BSD systems always do a grauitous ARP when assigning an address, - * so we can do one less announce. */ -#ifdef BSD -# define ANNOUNCE_NUM 1 -#else -# define ANNOUNCE_NUM 2 -#endif -#define ANNOUNCE_INTERVAL 2 -#define MAX_CONFLICTS 10 -#define RATE_LIMIT_INTERVAL 60 -#define DEFEND_INTERVAL 10 - - -/* number of usecs in a second. */ -#define USECS_SECOND 1000000 -/* As we use timevals, we should use the usec part for - * greater randomisation. */ -#define DHCP_RAND_MIN_U DHCP_RAND_MIN * USECS_SECOND -#define DHCP_RAND_MAX_U DHCP_RAND_MAX * USECS_SECOND -#define PROBE_MIN_U PROBE_MIN * USECS_SECOND -#define PROBE_MAX_U PROBE_MAX * USECS_SECOND - -#define timernorm(tvp) \ - do { \ - while ((tvp)->tv_usec >= 1000000) { \ - (tvp)->tv_sec++; \ - (tvp)->tv_usec -= 1000000; \ - } \ - } while (0 /* CONSTCOND */); - -#define timerneg(tvp) ((tvp)->tv_sec < 0 || (tvp)->tv_usec < 0) - -struct if_state { - int options; - struct interface *interface; - struct dhcp_message *offer; - struct dhcp_message *new; - struct dhcp_message *old; - struct dhcp_lease lease; - struct timeval timeout; - struct timeval stop; - struct timeval exit; - int state; - int messages; - time_t nakoff; - uint32_t xid; - int socket; - int *pid_fd; - int signal_fd; - int carrier; - int probes; - int claims; - int conflicts; - time_t defend; - struct in_addr fail; -}; - -#define LINK_UP 1 -#define LINK_UNKNOWN 0 -#define LINK_DOWN -1 - -struct dhcp_op { - uint8_t value; - const char *name; -}; - -static const struct dhcp_op const dhcp_ops[] = { - { DHCP_DISCOVER, "DHCP_DISCOVER" }, - { DHCP_OFFER, "DHCP_OFFER" }, - { DHCP_REQUEST, "DHCP_REQUEST" }, - { DHCP_DECLINE, "DHCP_DECLINE" }, - { DHCP_ACK, "DHCP_ACK" }, - { DHCP_NAK, "DHCP_NAK" }, - { DHCP_RELEASE, "DHCP_RELEASE" }, - { DHCP_INFORM, "DHCP_INFORM" }, - { 0, NULL } -}; - -static const char * -get_dhcp_op(uint8_t type) -{ - const struct dhcp_op *d; - - for (d = dhcp_ops; d->name; d++) - if (d->value == type) - return d->name; - return NULL; -} - -#ifdef THERE_IS_NO_FORK -#define daemonise(a,b) 0 -#else -static int -daemonise(struct if_state *state, const struct options *options) -{ - pid_t pid; - sigset_t full; - sigset_t old; - char buf = '\0'; - int sidpipe[2]; - - if (state->options & DHCPCD_DAEMONISED || - !(options->options & DHCPCD_DAEMONISE)) - return 0; - - sigfillset(&full); - sigprocmask(SIG_SETMASK, &full, &old); - - /* Setup a signal pipe so parent knows when to exit. */ - if (pipe(sidpipe) == -1) { - logger(LOG_ERR,"pipe: %s", strerror(errno)); - return -1; - } - - logger(LOG_DEBUG, "forking to background"); - switch (pid = fork()) { - case -1: - logger(LOG_ERR, "fork: %s", strerror(errno)); - exit(EXIT_FAILURE); - /* NOTREACHED */ - case 0: - setsid(); - /* Notify parent it's safe to exit as we've detached. */ - close(sidpipe[0]); - write(sidpipe[1], &buf, 1); - close(sidpipe[1]); - close_fds(); - break; - default: - /* Reset signals as we're the parent about to exit. */ - signal_reset(); - /* Wait for child to detach */ - close(sidpipe[1]); - read(sidpipe[0], &buf, 1); - close(sidpipe[0]); - break; - } - - /* Done with the fd now */ - if (pid != 0) { - writepid(*state->pid_fd, pid); - close(*state->pid_fd); - *state->pid_fd = -1; - } - - sigprocmask(SIG_SETMASK, &old, NULL); - if (pid == 0) { - state->options |= DHCPCD_DAEMONISED; - timerclear(&state->exit); - return 0; - } - state->options |= DHCPCD_PERSISTENT | DHCPCD_FORKED; - return -1; -} -#endif - -#define THIRTY_YEARS_IN_SECONDS 946707779 -static size_t -get_duid(unsigned char *duid, const struct interface *iface) -{ - FILE *f; - uint16_t type = 0; - uint16_t hw = 0; - uint32_t ul; - time_t t; - int x = 0; - unsigned char *p = duid; - size_t len = 0, l = 0; - char *buffer = NULL, *line, *option; - - /* If we already have a DUID then use it as it's never supposed - * to change once we have one even if the interfaces do */ - if ((f = fopen(DUID, "r"))) { - while ((get_line(&buffer, &len, f))) { - line = buffer; - while ((option = strsep(&line, " \t"))) - if (*option != '\0') - break; - if (!option || *option == '\0' || *option == '#') - continue; - l = hwaddr_aton(NULL, option); - if (l && l <= DUID_LEN) { - hwaddr_aton(duid, option); - break; - } - l = 0; - } - fclose(f); - free(buffer); - if (l) - return l; - } else { - if (errno != ENOENT) - return 0; - } - - /* No file? OK, lets make one based on our interface */ - if (!(f = fopen(DUID, "w"))) - return 0; - type = htons(1); /* DUI-D-LLT */ - memcpy(p, &type, 2); - p += 2; - hw = htons(iface->family); - memcpy(p, &hw, 2); - p += 2; - /* time returns seconds from jan 1 1970, but DUID-LLT is - * seconds from jan 1 2000 modulo 2^32 */ - t = time(NULL) - THIRTY_YEARS_IN_SECONDS; - ul = htonl(t & 0xffffffff); - memcpy(p, &ul, 4); - p += 4; - /* Finally, add the MAC address of the interface */ - memcpy(p, iface->hwaddr, iface->hwlen); - p += iface->hwlen; - len = p - duid; - x = fprintf(f, "%s\n", hwaddr_ntoa(duid, len)); - fclose(f); - /* Failed to write the duid? scrub it, we cannot use it */ - if (x < 1) { - len = 0; - unlink(DUID); - } - return len; -} - -static struct dhcp_message* -ipv4ll_get_dhcp(uint32_t old_addr) -{ - uint32_t u32; - struct dhcp_message *dhcp; - uint8_t *p; - - dhcp = xzalloc(sizeof(*dhcp)); - /* Put some LL options in */ - p = dhcp->options; - *p++ = DHO_SUBNETMASK; - *p++ = sizeof(u32); - u32 = htonl(LINKLOCAL_MASK); - memcpy(p, &u32, sizeof(u32)); - p += sizeof(u32); - *p++ = DHO_BROADCAST; - *p++ = sizeof(u32); - u32 = htonl(LINKLOCAL_BRDC); - memcpy(p, &u32, sizeof(u32)); - p += sizeof(u32); - *p++ = DHO_END; - - for (;;) { - dhcp->yiaddr = htonl(LINKLOCAL_ADDR | - (((uint32_t)abs((int)arc4random()) - % 0xFD00) + 0x0100)); - if (dhcp->yiaddr != old_addr && - IN_LINKLOCAL(ntohl(dhcp->yiaddr))) - break; - } - return dhcp; -} - -static double -timeval_to_double(struct timeval *tv) -{ - return tv->tv_sec * 1.0 + tv->tv_usec * 1.0e-6; -} - -static void -get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp) -{ - time_t t; - - lease->frominfo = 0; - lease->addr.s_addr = dhcp->yiaddr; - - if (get_option_addr(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1) - lease->net.s_addr = get_netmask(dhcp->yiaddr); - if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) { - /* Ensure that we can use the lease */ - t = 0; - if (t + (time_t)lease->leasetime < t) { - logger(LOG_WARNING, "lease of %u would overflow, " - "treating as infinite", lease->leasetime); - lease->leasetime = ~0U; /* Infinite lease */ - } - } else - lease->leasetime = DEFAULT_LEASETIME; - if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) - lease->renewaltime = 0; - if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) - lease->rebindtime = 0; -} - -static int -get_old_lease(struct if_state *state) -{ - struct interface *iface = state->interface; - struct dhcp_lease *lease = &state->lease; - struct dhcp_message *dhcp = NULL; - struct timeval tv; - unsigned int offset = 0; - struct stat sb; - - if (stat(iface->leasefile, &sb) == -1) { - if (errno != ENOENT) - logger(LOG_ERR, "stat: %s", strerror(errno)); - goto eexit; - } - if (!IN_LINKLOCAL(ntohl(iface->addr.s_addr))) - logger(LOG_INFO, "trying to use old lease in `%s'", - iface->leasefile); - if ((dhcp = read_lease(iface)) == NULL) { - logger(LOG_INFO, "read_lease: %s", strerror(errno)); - goto eexit; - } - get_lease(&state->lease, dhcp); - lease->frominfo = 1; - lease->leasedfrom = sb.st_mtime; - - /* Vitaly important we remove the server information here */ - state->lease.server.s_addr = 0; - dhcp->servername[0] = '\0'; - - if (!IN_LINKLOCAL(ntohl(dhcp->yiaddr))) { - if (!(state->options & DHCPCD_LASTLEASE)) - goto eexit; - - /* Ensure that we can still use the lease */ - if (gettimeofday(&tv, NULL) == -1) { - logger(LOG_ERR, "gettimeofday: %s", strerror(errno)); - goto eexit; - } - - offset = tv.tv_sec - lease->leasedfrom; - if (lease->leasedfrom && - tv.tv_sec - lease->leasedfrom > (time_t)lease->leasetime) - { - logger(LOG_ERR, "lease expired %u seconds ago", - offset + lease->leasetime); - /* Persistent interfaces should still try and use the - * lease if we can't contact a DHCP server. - * We just set the timeout to 1 second. */ - if (state->options & DHCPCD_PERSISTENT) - offset = lease->renewaltime - 1; - else - goto eexit; - } - } - - if (lease->leasedfrom == 0) - offset = 0; - iface->start_uptime = uptime(); - state->timeout.tv_sec = lease->renewaltime - offset; - free(state->old); - state->old = state->new; - state->new = NULL; - state->offer = dhcp; - return 0; - -eexit: - lease->addr.s_addr = 0; - free(dhcp); - return -1; -} - -static int -client_setup(struct if_state *state, const struct options *options) -{ - struct interface *iface = state->interface; - struct dhcp_lease *lease = &state->lease; - struct in_addr addr; - struct timeval tv; - size_t len = 0; - unsigned char *duid = NULL; - uint32_t ul; - - state->state = STATE_INIT; - state->nakoff = 1; - state->options = options->options; - timerclear(&tv); - - if (options->request_address.s_addr == 0 && - (options->options & DHCPCD_INFORM || - options->options & DHCPCD_REQUEST || - (options->options & DHCPCD_DAEMONISED && - !(options->options & DHCPCD_BACKGROUND)))) - { - if (get_old_lease(state) != 0) - return -1; - timerclear(&state->timeout); - - if (!(options->options & DHCPCD_DAEMONISED) && - IN_LINKLOCAL(ntohl(lease->addr.s_addr))) - { - logger(LOG_ERR, "cannot request a link local address"); - return -1; - } - } else { - lease->addr.s_addr = options->request_address.s_addr; - lease->net.s_addr = options->request_netmask.s_addr; - } - - if (options->options & DHCPCD_REQUEST && - state->options & DHCPCD_ARP && - !state->offer) - { - state->offer = xzalloc(sizeof(*state->offer)); - state->offer->yiaddr = options->request_address.s_addr; - state->state = STATE_PROBING; - state->xid = arc4random(); - } - - /* If INFORMing, ensure the interface has the address */ - if (state->options & DHCPCD_INFORM && - has_address(iface->name, &lease->addr, &lease->net) < 1) - { - addr.s_addr = lease->addr.s_addr | ~lease->net.s_addr; - logger(LOG_DEBUG, "adding IP address %s/%d", - inet_ntoa(lease->addr), inet_ntocidr(lease->net)); - if (add_address(iface->name, &lease->addr, - &lease->net, &addr) == -1) - { - logger(LOG_ERR, "add_address: %s", strerror(errno)); - return -1; - } - iface->addr.s_addr = lease->addr.s_addr; - iface->net.s_addr = lease->net.s_addr; - } - - if (*options->clientid) { - iface->clientid = xmalloc(options->clientid[0] + 1); - memcpy(iface->clientid, - options->clientid, options->clientid[0] + 1); - } else if (options->options & DHCPCD_CLIENTID) { - if (options->options & DHCPCD_DUID) { - duid = xmalloc(DUID_LEN); - if ((len = get_duid(duid, iface)) == 0) - logger(LOG_ERR, "get_duid: %s", - strerror(errno)); - } - - if (len > 0) { - logger(LOG_DEBUG, "DUID = %s", - hwaddr_ntoa(duid, len)); - - iface->clientid = xmalloc(len + 6); - iface->clientid[0] = len + 5; - iface->clientid[1] = 255; /* RFC 4361 */ - - /* IAID is 4 bytes, so if the iface name is 4 bytes - * or less, use it */ - ul = strlen(iface->name); - if (ul < 5) { - memcpy(iface->clientid + 2, iface->name, ul); - if (ul < 4) - memset(iface->clientid + 2 + ul, - 0, 4 - ul); - } else { - /* Name isn't 4 bytes, so use the index */ - ul = htonl(if_nametoindex(iface->name)); - memcpy(iface->clientid + 2, &ul, 4); - } - - memcpy(iface->clientid + 6, duid, len); - free(duid); - } - if (len == 0) { - len = iface->hwlen + 1; - iface->clientid = xmalloc(len + 1); - iface->clientid[0] = len; - iface->clientid[1] = iface->family; - memcpy(iface->clientid + 2, iface->hwaddr, iface->hwlen); - } - } - - if (state->options & DHCPCD_LINK) { - open_link_socket(iface); - switch (carrier_status(iface->name)) { - case 0: - state->carrier = LINK_DOWN; - break; - case 1: - state->carrier = LINK_UP; - break; - default: - state->carrier = LINK_UNKNOWN; - } - } - - if (options->timeout > 0 && - !(state->options & DHCPCD_DAEMONISED)) - { - if (state->options & DHCPCD_IPV4LL) { - state->stop.tv_sec = options->timeout; - if (!(state->options & DHCPCD_BACKGROUND)) - state->exit.tv_sec = state->stop.tv_sec + 10; - } else if (!(state->options & DHCPCD_BACKGROUND)) - state->exit.tv_sec = options->timeout; - } - return 0; -} - -static int -do_socket(struct if_state *state, int mode) -{ - if (state->interface->raw_fd != -1) { - close(state->interface->raw_fd); - state->interface->raw_fd = -1; - } - if (mode == SOCKET_CLOSED) { - if (state->interface->udp_fd != -1) { - close(state->interface->udp_fd); - state->interface->udp_fd = -1; - } - if (state->interface->arp_fd != -1) { - close(state->interface->arp_fd); - state->interface->arp_fd = -1; - } - } - - /* Always have the UDP socket open to avoid the kernel sending - * ICMP unreachable messages. */ - /* For systems without SO_BINDTODEVICE, (ie BSD ones) we may get an - * error or EADDRINUSE when binding to INADDR_ANY as another dhcpcd - * instance could be running. - * Oddly enough, we don't care about this as the socket is there - * just to please the kernel - we don't care for reading from it. */ - if (mode == SOCKET_OPEN && - state->interface->udp_fd == -1 && - open_udp_socket(state->interface) == -1 && - (errno != EADDRINUSE || state->interface->addr.s_addr != 0)) - logger(LOG_ERR, "open_udp_socket: %s", strerror(errno)); - - if (mode == SOCKET_OPEN) - if (open_socket(state->interface, ETHERTYPE_IP) == -1) { - logger(LOG_ERR, "open_socket: %s", strerror(errno)); - return -1; - } - state->socket = mode; - return 0; -} - -static ssize_t -send_message(struct if_state *state, int type, const struct options *options) -{ - struct dhcp_message *dhcp; - uint8_t *udp; - ssize_t len, r; - struct in_addr from, to; - in_addr_t a = 0; - - if (state->carrier == LINK_DOWN) - return 0; - if (type == DHCP_RELEASE) - logger(LOG_DEBUG, "sending %s with xid 0x%x", - get_dhcp_op(type), state->xid); - else - logger(LOG_DEBUG, - "sending %s with xid 0x%x, next in %0.2f seconds", - get_dhcp_op(type), state->xid, - timeval_to_double(&state->timeout)); - state->messages++; - if (state->messages < 0) - state->messages = INT_MAX; - /* If we couldn't open a UDP port for our IP address - * then we cannot renew. - * This could happen if our IP was pulled out from underneath us. */ - if (state->interface->udp_fd == -1) { - a = state->interface->addr.s_addr; - state->interface->addr.s_addr = 0; - } - len = make_message(&dhcp, state->interface, &state->lease, state->xid, - type, options); - if (state->interface->udp_fd == -1) - state->interface->addr.s_addr = a; - from.s_addr = dhcp->ciaddr; - if (from.s_addr) - to.s_addr = state->lease.server.s_addr; - else - to.s_addr = 0; - if (to.s_addr && to.s_addr != INADDR_BROADCAST) { - r = send_packet(state->interface, to, (uint8_t *)dhcp, len); - if (r == -1) - logger(LOG_ERR, "send_packet: %s", strerror(errno)); - } else { - len = make_udp_packet(&udp, (uint8_t *)dhcp, len, from, to); - r = send_raw_packet(state->interface, ETHERTYPE_IP, udp, len); - free(udp); - if (r == -1) - logger(LOG_ERR, "send_raw_packet: %s", strerror(errno)); - } - free(dhcp); - /* Failed to send the packet? Return to the init state */ - if (r == -1) { - state->state = STATE_INIT; - timerclear(&state->timeout); - timerclear(&state->stop); - do_socket(state, SOCKET_CLOSED); - } - return r; -} - -static void -drop_config(struct if_state *state, const char *reason, - const struct options *options) -{ - if (state->new || strcmp(reason, "FAIL") == 0) { - configure(state->interface, reason, NULL, state->new, - &state->lease, options, 0); - free(state->old); - state->old = NULL; - free(state->new); - state->new = NULL; - } - state->lease.addr.s_addr = 0; -} - -static void -reduce_timers(struct if_state *state, const struct timeval *tv) -{ - if (timerisset(&state->exit)) { - timersub(&state->exit, tv, &state->exit); - if (!timerisset(&state->exit)) - state->exit.tv_sec = -1; - } - if (timerisset(&state->stop)) { - timersub(&state->stop, tv, &state->stop); - if (!timerisset(&state->stop)) - state->stop.tv_sec = -1; - } - if (timerisset(&state->timeout)) { - timersub(&state->timeout, tv, &state->timeout); - if (!timerisset(&state->timeout)) - state->timeout.tv_sec = -1; - } -} - -static struct timeval * -get_lowest_timer(struct if_state *state) -{ - struct timeval *ref = NULL; - - if (timerisset(&state->exit)) - ref = &state->exit; - if (timerisset(&state->stop)) { - if (!ref || timercmp(&state->stop, ref, <)) - ref = &state->stop; - } - if (timerisset(&state->timeout)) { - if (!ref || timercmp(&state->timeout, ref, <)) - ref = &state->timeout; - } - return ref; -} - -static int -wait_for_fd(struct if_state *state, int *fd) -{ - struct pollfd fds[4]; /* signal, link, raw, arp */ - struct interface *iface = state->interface; - int i, r, nfds = 0, msecs = -1; - struct timeval start, stop, diff, *ref; - static int lastinf = 0; - - /* Ensure that we haven't already timed out */ - ref = get_lowest_timer(state); - if (ref && timerneg(ref)) - return 0; - - /* We always listen to signals */ - fds[nfds].fd = state->signal_fd; - fds[nfds].events = POLLIN; - nfds++; - /* And links */ - if (iface->link_fd != -1) { - fds[nfds].fd = iface->link_fd; - fds[nfds].events = POLLIN; - nfds++; - } - - if (state->lease.leasetime == ~0U && - state->state == STATE_BOUND) - { - if (!lastinf) { - logger(LOG_DEBUG, "waiting for infinity"); - lastinf = 1; - } - ref = NULL; - } else if (state->carrier == LINK_DOWN && !ref) { - if (!lastinf) { - logger(LOG_DEBUG, "waiting for carrier"); - lastinf = 1; - } - if (timerisset(&state->exit)) - ref = &state->exit; - else - ref = NULL; - } else { - if (iface->raw_fd != -1) { - fds[nfds].fd = iface->raw_fd; - fds[nfds].events = POLLIN; - nfds++; - } - if (iface->arp_fd != -1) { - fds[nfds].fd = iface->arp_fd; - fds[nfds].events = POLLIN; - nfds++; - } - } - - /* Wait and then reduce the timers. - * If we reduce a timer to zero, set it negative to indicate timeout. - * We cannot reliably use select as there is no guarantee we will - * actually wait the whole time if greater than 31 days according - * to POSIX. So we loop on poll if needed as it's limitation of - * INT_MAX milliseconds is known. */ - for (;;) { - get_monotonic(&start); - if (ref) { - lastinf = 0; - if (ref->tv_sec > INT_MAX / 1000 || - (ref->tv_sec == INT_MAX / 1000 && - (ref->tv_usec + 999) / 1000 > INT_MAX % 1000)) - msecs = INT_MAX; - else - msecs = ref->tv_sec * 1000 + - (ref->tv_usec + 999) / 1000; - } else - msecs = -1; - r = poll(fds, nfds, msecs); - get_monotonic(&stop); - timersub(&stop, &start, &diff); - reduce_timers(state, &diff); - if (r == -1) { - if (errno != EINTR) - logger(LOG_ERR, "poll: %s", strerror(errno)); - return -1; - } - if (r) - break; - /* We should not have an infinite timeout if we get here */ - if (timerneg(ref)) - return 0; - } - - /* We configured our array in the order we should deal with them */ - for (i = 0; i < nfds; i++) - if (fds[i].revents & POLLIN) { - *fd = fds[i].fd; - return r; - } - return r; -} - -static int -handle_signal(int sig, struct if_state *state, const struct options *options) -{ - struct dhcp_lease *lease = &state->lease; - - switch (sig) { - case SIGINT: - logger(LOG_INFO, "received SIGINT, stopping"); - if (!(state->options & DHCPCD_PERSISTENT)) - drop_config(state, "STOP", options); - return -1; - case SIGTERM: - logger(LOG_INFO, "received SIGTERM, stopping"); - if (!(state->options & DHCPCD_PERSISTENT)) - drop_config(state, "STOP", options); - return -1; - case SIGALRM: - logger(LOG_INFO, "received SIGALRM, renewing lease"); - do_socket(state, SOCKET_CLOSED); - state->state = STATE_RENEW_REQUESTED; - timerclear(&state->timeout); - timerclear(&state->stop); - return 1; - case SIGHUP: - logger(LOG_INFO, "received SIGHUP, releasing lease"); - if (lease->addr.s_addr && - !IN_LINKLOCAL(ntohl(lease->addr.s_addr))) - { - do_socket(state, SOCKET_OPEN); - state->xid = arc4random(); - send_message(state, DHCP_RELEASE, options); - do_socket(state, SOCKET_CLOSED); - } - drop_config(state, "RELEASE", options); - return -1; - default: - logger (LOG_ERR, - "received signal %d, but don't know what to do with it", - sig); - } - - return 0; -} - -static int bind_dhcp(struct if_state *state, const struct options *options) -{ - struct interface *iface = state->interface; - struct dhcp_lease *lease = &state->lease; - const char *reason = NULL; - struct timeval start, stop, diff; - int retval; - - free(state->old); - state->old = state->new; - state->new = state->offer; - state->offer = NULL; - state->messages = 0; - state->conflicts = 0; - state->defend = 0; - timerclear(&state->exit); - if (clock_monotonic) - get_monotonic(&lease->boundtime); - - if (options->options & DHCPCD_INFORM) { - if (options->request_address.s_addr != 0) - lease->addr.s_addr = options->request_address.s_addr; - else - lease->addr.s_addr = iface->addr.s_addr; - logger(LOG_INFO, "received approval for %s", - inet_ntoa(lease->addr)); - state->state = STATE_BOUND; - state->lease.leasetime = ~0U; - timerclear(&state->stop); - reason = "INFORM"; - } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) { - get_lease(lease, state->new); - logger(LOG_INFO, "using IPv4LL address %s", - inet_ntoa(lease->addr)); - state->state = STATE_INIT; - timerclear(&state->timeout); - reason = "IPV4LL"; - } else { - if (gettimeofday(&start, NULL) == 0) - lease->leasedfrom = start.tv_sec; - - get_lease(lease, state->new); - if (lease->frominfo) - reason = "TIMEOUT"; - - if (lease->leasetime == ~0U) { - lease->renewaltime = lease->rebindtime = lease->leasetime; - logger(LOG_INFO, "leased %s for infinity", - inet_ntoa(lease->addr)); - state->state = STATE_BOUND; - timerclear(&state->stop); - } else { - if (lease->rebindtime >= lease->leasetime) { - lease->rebindtime = lease->leasetime * T2; - logger(LOG_ERR, - "rebind time greater than lease " - "time, forcing to %u seconds", - lease->rebindtime); - } - if (lease->renewaltime > lease->rebindtime) { - lease->renewaltime = lease->leasetime * T1; - logger(LOG_ERR, - "renewal time greater than rebind time, " - "forcing to %u seconds", - lease->renewaltime); - } - if (!lease->renewaltime) - lease->renewaltime = lease->leasetime * T1; - if (!lease->rebindtime) - lease->rebindtime = lease->leasetime * T2; - logger(LOG_INFO, - "leased %s for %u seconds", - inet_ntoa(lease->addr), lease->leasetime); - state->stop.tv_sec = lease->renewaltime; - state->stop.tv_usec = 0; - } - state->state = STATE_BOUND; - } - - state->xid = 0; - timerclear(&state->timeout); - if (!reason) { - if (state->old) { - if (state->old->yiaddr == state->new->yiaddr && - lease->server.s_addr) - reason = "RENEW"; - else - reason = "REBIND"; - } else - reason = "BOUND"; - } - /* If we have a monotonic clock we can safely substract the - * script execution time from our timers. - * Otherwise we can't as the script may update the real time. */ - if (clock_monotonic) - get_monotonic(&start); - retval = configure(iface, reason, state->new, state->old, - &state->lease, options, 1); - if (clock_monotonic) { - get_monotonic(&stop); - timersub(&stop, &start, &diff); - reduce_timers(state, &diff); - } - if (retval != 0) - return -1; - return daemonise(state, options); -} - -static int -handle_timeout_fail(struct if_state *state, const struct options *options) -{ - struct dhcp_lease *lease = &state->lease; - struct interface *iface = state->interface; - int gotlease = -1; - const char *reason = NULL; - - timerclear(&state->stop); - timerclear(&state->exit); - if (state->state != STATE_DISCOVERING) - state->messages = 0; - - switch (state->state) { - case STATE_INIT: /* FALLTHROUGH */ - case STATE_DISCOVERING: /* FALLTHROUGH */ - case STATE_REQUESTING: - if (IN_LINKLOCAL(ntohl(iface->addr.s_addr))) { - if (!(state->options & DHCPCD_DAEMONISED)) - logger(LOG_ERR, "timed out"); - } else { - if (iface->addr.s_addr != 0 && - !(state->options & DHCPCD_INFORM)) - logger(LOG_ERR, "lost lease"); - else if (state->carrier != LINK_DOWN || - !(state->options & DHCPCD_DAEMONISED)) - logger(LOG_ERR, "timed out"); - } - do_socket(state, SOCKET_CLOSED); - if (state->options & DHCPCD_INFORM || - state->options & DHCPCD_TEST) - return -1; - - if (state->carrier != LINK_DOWN && - (state->options & DHCPCD_IPV4LL || - state->options & DHCPCD_LASTLEASE)) - gotlease = get_old_lease(state); - - if (state->carrier != LINK_DOWN && - state->options & DHCPCD_IPV4LL && - gotlease != 0) - { - logger(LOG_INFO, "probing for an IPV4LL address"); - free(state->offer); - state->offer = ipv4ll_get_dhcp(0); - gotlease = 0; - } - - if (gotlease == 0 && - state->offer->yiaddr != iface->addr.s_addr) - { - state->state = STATE_PROBING; - state->claims = 0; - state->probes = 0; - if (iface->addr.s_addr) - state->conflicts = 0; - return 1; - } - - if (gotlease == 0) - return bind_dhcp(state, options); - - if (iface->addr.s_addr) - reason = "EXPIRE"; - else - reason = "FAIL"; - drop_config(state, reason, options); - if (!(state->options & DHCPCD_DAEMONISED) && - (state->options & DHCPCD_DAEMONISE)) - return -1; - state->state = STATE_RENEW_REQUESTED; - return 1; - case STATE_BOUND: - logger(LOG_INFO, "renewing lease of %s",inet_ntoa(lease->addr)); - if (state->carrier != LINK_DOWN) - do_socket(state, SOCKET_OPEN); - state->xid = arc4random(); - state->state = STATE_RENEWING; - state->stop.tv_sec = lease->rebindtime - lease->renewaltime; - break; - case STATE_RENEWING: - logger(LOG_ERR, "failed to renew, attempting to rebind"); - state->state = STATE_REBINDING; - if (lease->server.s_addr == 0) - state->stop.tv_sec = options->timeout; - else - state->stop.tv_sec = lease->rebindtime - \ - lease->renewaltime; - lease->server.s_addr = 0; - break; - case STATE_REBINDING: - logger(LOG_ERR, "failed to rebind"); - reason = "EXPIRE"; - drop_config(state, reason, options); - state->state = STATE_INIT; - break; - case STATE_PROBING: /* FALLTHROUGH */ - case STATE_ANNOUNCING: - /* We should have lost carrier here and exit timer went */ - logger(LOG_ERR, "timed out"); - return -1; - default: - logger(LOG_DEBUG, "handle_timeout_failed: invalid state %d", - state->state); - } - - /* This effectively falls through into the handle_timeout funtion */ - return 1; -} - -static int -handle_timeout(struct if_state *state, const struct options *options) -{ - struct dhcp_lease *lease = &state->lease; - struct interface *iface = state->interface; - int i = 0; - struct in_addr addr; - struct timeval tv; - - timerclear(&state->timeout); - if (timerneg(&state->exit)) - return handle_timeout_fail(state, options); - - if (state->state == STATE_RENEW_REQUESTED && - IN_LINKLOCAL(ntohl(lease->addr.s_addr))) - { - state->state = STATE_PROBING; - free(state->offer); - state->offer = read_lease(state->interface); - state->probes = 0; - state->claims = 0; - } - switch (state->state) { - case STATE_INIT_IPV4LL: - state->state = STATE_PROBING; - free(state->offer); - state->offer = ipv4ll_get_dhcp(0); - state->probes = 0; - state->claims = 0; - /* FALLTHROUGH */ - case STATE_PROBING: - if (iface->arp_fd == -1) - open_socket(iface, ETHERTYPE_ARP); - if (state->probes < PROBE_NUM) { - if (state->probes == 0) { - addr.s_addr = state->offer->yiaddr; - logger(LOG_INFO, "checking %s is available" - " on attached networks", - inet_ntoa(addr)); - } - state->probes++; - if (state->probes < PROBE_NUM) { - state->timeout.tv_sec = PROBE_MIN; - state->timeout.tv_usec = arc4random() % - (PROBE_MAX_U - PROBE_MIN_U); - timernorm(&state->timeout); - } else { - state->timeout.tv_sec = ANNOUNCE_WAIT; - state->timeout.tv_usec = 0; - } - logger(LOG_DEBUG, - "sending ARP probe (%d of %d), next in %0.2f seconds", - state->probes, PROBE_NUM, - timeval_to_double(&state->timeout)); - if (send_arp(iface, ARPOP_REQUEST, 0, - state->offer->yiaddr) == -1) - { - logger(LOG_ERR, "send_arp: %s", strerror(errno)); - return -1; - } - return 0; - } else { - /* We've waited for ANNOUNCE_WAIT after the final probe - * so the address is now ours */ - if (IN_LINKLOCAL(htonl(state->offer->yiaddr))) { - i = bind_dhcp(state, options); - state->state = STATE_ANNOUNCING; - state->timeout.tv_sec = ANNOUNCE_INTERVAL; - state->timeout.tv_usec = 0; - return i; - } - state->state = STATE_REQUESTING; - } - break; - case STATE_ANNOUNCING: - if (iface->arp_fd == -1) - open_socket(iface, ETHERTYPE_ARP); - if (state->claims < ANNOUNCE_NUM) { - state->claims++; - if (state->claims < ANNOUNCE_NUM) { - state->timeout.tv_sec = ANNOUNCE_INTERVAL; - state->timeout.tv_usec = 0; - logger(LOG_DEBUG, - "sending ARP announce (%d of %d)," - " next in %0.2f seconds", - state->claims, ANNOUNCE_NUM, - timeval_to_double(&state->timeout)); - } else - logger(LOG_DEBUG, - "sending ARP announce (%d of %d)", - state->claims, ANNOUNCE_NUM); - i = send_arp(iface, ARPOP_REQUEST, - state->new->yiaddr, state->new->yiaddr); - if (i == -1) { - logger(LOG_ERR, "send_arp: %s", strerror(errno)); - return -1; - } - } - if (state->claims < ANNOUNCE_NUM) - return 0; - if (IN_LINKLOCAL(htonl(state->new->yiaddr))) { - /* We should pretend to be at the end - * of the DHCP negotation cycle */ - state->state = STATE_INIT; - state->messages = DHCP_MAX / DHCP_BASE; - state->probes = 0; - state->claims = 0; - timerclear(&state->stop); - goto dhcp_timeout; - } else { - state->state = STATE_BOUND; - close(iface->arp_fd); - iface->arp_fd = -1; - if (lease->leasetime != ~0U) { - state->stop.tv_sec = lease->renewaltime; - state->stop.tv_usec = 0; - if (clock_monotonic) { - get_monotonic(&tv); - timersub(&tv, &lease->boundtime, &tv); - timersub(&state->stop, &tv, &state->stop); - } else { - state->stop.tv_sec -= - (ANNOUNCE_INTERVAL * ANNOUNCE_NUM); - } - logger(LOG_DEBUG, "renew in %ld seconds", - (long int)state->stop.tv_sec); - } - } - return 0; - } - - if (timerneg(&state->stop)) - return handle_timeout_fail(state, options); - - switch (state->state) { - case STATE_BOUND: /* FALLTHROUGH */ - case STATE_RENEW_REQUESTED: - timerclear(&state->stop); - /* FALLTHROUGH */ - case STATE_INIT: - do_socket(state, SOCKET_OPEN); - state->xid = arc4random(); - iface->start_uptime = uptime(); - break; - } - - switch(state->state) { - case STATE_RENEW_REQUESTED: - /* If a renew was requested (ie, didn't timeout) we actually - * enter the REBIND state so that we broadcast to all servers. - * We need to do this for when we change networks. */ - lease->server.s_addr = 0; - state->messages = 0; - if (lease->addr.s_addr && !(state->options & DHCPCD_INFORM)) { - logger(LOG_INFO, "rebinding lease of %s", - inet_ntoa(lease->addr)); - state->state = STATE_REBINDING; - state->stop.tv_sec = options->timeout; - state->stop.tv_usec = 0; - break; - } - /* FALLTHROUGH */ - case STATE_INIT: - if (state->carrier == LINK_DOWN) - return 0; - if (lease->addr.s_addr == 0 || - IN_LINKLOCAL(ntohl(iface->addr.s_addr))) - { - logger(LOG_INFO, "broadcasting for a lease"); - state->state = STATE_DISCOVERING; - } else if (state->options & DHCPCD_INFORM) { - logger(LOG_INFO, "broadcasting inform for %s", - inet_ntoa(lease->addr)); - state->state = STATE_REQUESTING; - } else { - logger(LOG_INFO, "broadcasting for a lease of %s", - inet_ntoa(lease->addr)); - state->state = STATE_REQUESTING; - } - if (!lease->addr.s_addr && !timerisset(&state->stop)) { - state->stop.tv_sec = DHCP_MAX + DHCP_RAND_MIN; - state->stop.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U); - timernorm(&state->stop); - } - break; - } - -dhcp_timeout: - if (state->carrier == LINK_DOWN) { - timerclear(&state->timeout); - return 0; - } - state->timeout.tv_sec = DHCP_BASE; - for (i = 0; i < state->messages; i++) { - state->timeout.tv_sec *= 2; - if (state->timeout.tv_sec > DHCP_MAX) { - state->timeout.tv_sec = DHCP_MAX; - break; - } - } - state->timeout.tv_sec += DHCP_RAND_MIN; - state->timeout.tv_usec = arc4random() % - (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U); - timernorm(&state->timeout); - - /* We send the message here so that the timeout is reported */ - switch (state->state) { - case STATE_DISCOVERING: - send_message(state, DHCP_DISCOVER, options); - break; - case STATE_REQUESTING: - if (state->options & DHCPCD_INFORM) { - send_message(state, DHCP_INFORM, options); - break; - } - /* FALLTHROUGH */ - case STATE_RENEWING: /* FALLTHROUGH */ - case STATE_REBINDING: - if (iface->raw_fd == -1) - do_socket(state, SOCKET_OPEN); - send_message(state, DHCP_REQUEST, options); - break; - } - - return 0; -} - -static void -log_dhcp(int lvl, const char *msg, const struct dhcp_message *dhcp) -{ - char *a; - struct in_addr addr; - int r; - - if (strcmp(msg, "NAK:") == 0) - a = get_option_string(dhcp, DHO_MESSAGE); - else { - addr.s_addr = dhcp->yiaddr; - a = xstrdup(inet_ntoa(addr)); - } - r = get_option_addr(&addr.s_addr, dhcp, DHO_SERVERID); - if (dhcp->servername[0] && r == 0) - logger(lvl, "%s %s from %s `%s'", msg, a, - inet_ntoa(addr), dhcp->servername); - else if (r == 0) - logger(lvl, "%s %s from %s", msg, a, inet_ntoa(addr)); - else - logger(lvl, "%s %s", msg, a); - free(a); -} - -static int -handle_dhcp(struct if_state *state, struct dhcp_message **dhcpp, - const struct options *options) -{ - struct dhcp_message *dhcp = *dhcpp; - struct interface *iface = state->interface; - struct dhcp_lease *lease = &state->lease; - uint8_t type, tmp; - struct in_addr addr; - size_t i; - int r; - - /* reset the message counter */ - state->messages = 0; - - /* We have to have DHCP type to work */ - if (get_option_uint8(&type, dhcp, DHO_MESSAGETYPE) == -1) { - log_dhcp(LOG_ERR, "no DHCP type in", dhcp); - return 0; - } - - /* Ensure that it's not from a blacklisted server. - * We should expand this to check IP and/or hardware address - * at the packet level. */ - if (options->blacklist_len != 0 && - get_option_addr(&addr.s_addr, dhcp, DHO_SERVERID) == 0) - { - for (i = 0; i < options->blacklist_len; i++) { - if (options->blacklist[i] != addr.s_addr) - continue; - if (dhcp->servername[0]) - logger(LOG_WARNING, - "ignoring blacklisted server %s `%s'", - inet_ntoa(addr), dhcp->servername); - else - logger(LOG_WARNING, - "ignoring blacklisted server %s", - inet_ntoa(addr)); - return 0; - } - } - - /* We should restart on a NAK */ - if (type == DHCP_NAK) { - log_dhcp(LOG_WARNING, "NAK:", dhcp); - drop_config(state, "EXPIRE", options); - do_socket(state, SOCKET_CLOSED); - state->state = STATE_INIT; - /* If we constantly get NAKS then we should slowly back off */ - if (state->nakoff == 0) { - state->nakoff = 1; - timerclear(&state->timeout); - } else { - state->timeout.tv_sec = state->nakoff; - state->timeout.tv_usec = 0; - state->nakoff *= 2; - if (state->nakoff > NAKOFF_MAX) - state->nakoff = NAKOFF_MAX; - } - return 0; - } - - /* No NAK, so reset the backoff */ - state->nakoff = 1; - - /* Ensure that all required options are present */ - for (i = 1; i < 255; i++) { - if (has_option_mask(options->requiremask, i) && - get_option_uint8(&tmp, dhcp, i) != 0) - { - log_dhcp(LOG_WARNING, "reject", dhcp); - return 0; - } - } - - if (type == DHCP_OFFER && state->state == STATE_DISCOVERING) { - lease->addr.s_addr = dhcp->yiaddr; - get_option_addr(&lease->server.s_addr, dhcp, DHO_SERVERID); - log_dhcp(LOG_INFO, "offered", dhcp); - if (state->options & DHCPCD_TEST) { - run_script(options, iface->name, "TEST", dhcp, NULL); - /* Fake the fact we forked so we return 0 to userland */ - state->options |= DHCPCD_FORKED; - return -1; - } - free(state->offer); - state->offer = dhcp; - *dhcpp = NULL; - timerclear(&state->timeout); - if (state->options & DHCPCD_ARP && - iface->addr.s_addr != state->offer->yiaddr) - { - /* If the interface already has the address configured - * then we can't ARP for duplicate detection. */ - addr.s_addr = state->offer->yiaddr; - if (!has_address(iface->name, &addr, NULL)) { - state->state = STATE_PROBING; - state->claims = 0; - state->probes = 0; - state->conflicts = 0; - timerclear(&state->stop); - return 1; - } - } - state->state = STATE_REQUESTING; - return 1; - } - - if (type == DHCP_OFFER) { - log_dhcp(LOG_INFO, "ignoring offer of", dhcp); - return 0; - } - - /* We should only be dealing with acks */ - if (type != DHCP_ACK) { - log_dhcp(LOG_ERR, "not ACK or OFFER", dhcp); - return 0; - } - - switch (state->state) { - case STATE_RENEW_REQUESTED: - case STATE_REQUESTING: - case STATE_RENEWING: - case STATE_REBINDING: - if (!(state->options & DHCPCD_INFORM)) { - get_option_addr(&lease->server.s_addr, - dhcp, DHO_SERVERID); - log_dhcp(LOG_INFO, "acknowledged", dhcp); - } - free(state->offer); - state->offer = dhcp; - *dhcpp = NULL; - break; - default: - logger(LOG_ERR, "wrong state %d", state->state); - } - - do_socket(state, SOCKET_CLOSED); - r = bind_dhcp(state, options); - if (!(state->options & DHCPCD_ARP)) { - if (!(state->options & DHCPCD_INFORM)) - logger(LOG_DEBUG, "renew in %ld seconds", - (long int)state->stop.tv_sec); - return r; - } - state->state = STATE_ANNOUNCING; - if (state->options & DHCPCD_FORKED) - return r; - return 1; -} - -static int -handle_dhcp_packet(struct if_state *state, const struct options *options) -{ - uint8_t *packet; - struct interface *iface = state->interface; - struct dhcp_message *dhcp = NULL; - const uint8_t *pp; - uint8_t *p; - ssize_t bytes; - int retval = -1; - - /* We loop through until our buffer is empty. - * The benefit is that if we get >1 DHCP packet in our buffer and - * the first one fails for any reason, we can use the next. */ - packet = xmalloc(udp_dhcp_len); - for(;;) { - bytes = get_raw_packet(iface, ETHERTYPE_IP, - packet, udp_dhcp_len); - if (bytes == 0) { - retval = 0; - break; - } - if (bytes == -1) - break; - if (valid_udp_packet(packet) == -1) - continue; - bytes = get_udp_data(&pp, packet); - if ((size_t)bytes > sizeof(*dhcp)) { - logger(LOG_ERR, "packet greater than DHCP size"); - continue; - } - if (!dhcp) - dhcp = xmalloc(sizeof(*dhcp)); - memcpy(dhcp, pp, bytes); - if (dhcp->cookie != htonl(MAGIC_COOKIE)) { - logger(LOG_DEBUG, "bogus cookie, ignoring"); - continue; - } - /* Ensure it's the right transaction */ - if (state->xid != dhcp->xid) { - logger(LOG_DEBUG, - "ignoring packet with xid 0x%x as" - " it's not ours (0x%x)", - dhcp->xid, state->xid); - continue; - } - /* Ensure packet is for us */ - if (iface->hwlen <= sizeof(dhcp->chaddr) && - memcmp(dhcp->chaddr, iface->hwaddr, iface->hwlen)) - { - logger(LOG_DEBUG, "xid 0x%x is not for our hwaddr %s", - dhcp->xid, - hwaddr_ntoa(dhcp->chaddr, sizeof(dhcp->chaddr))); - continue; - } - /* We should ensure that the packet is terminated correctly - * if we have space for the terminator */ - if ((size_t)bytes < sizeof(struct dhcp_message)) { - p = (uint8_t *)dhcp + bytes - 1; - while (p > dhcp->options && *p == DHO_PAD) - p--; - if (*p != DHO_END) - *++p = DHO_END; - } - retval = handle_dhcp(state, &dhcp, options); - if (retval == 0 && state->options & DHCPCD_TEST) - state->options |= DHCPCD_FORKED; - break; - } - - free(packet); - free(dhcp); - return retval; -} - -static int -handle_arp_packet(struct if_state *state) -{ - struct arphdr reply; - uint32_t reply_s; - uint32_t reply_t; - uint8_t arp_reply[sizeof(reply) + 2 * sizeof(reply_s) + 2 * HWADDR_LEN]; - uint8_t *hw_s, *hw_t; - ssize_t bytes; - struct interface *iface = state->interface; - - state->fail.s_addr = 0; - for(;;) { - bytes = get_raw_packet(iface, ETHERTYPE_ARP, - arp_reply, sizeof(arp_reply)); - if (bytes == 0 || bytes == -1) - return (int)bytes; - /* We must have a full ARP header */ - if ((size_t)bytes < sizeof(reply)) - continue; - memcpy(&reply, arp_reply, sizeof(reply)); - /* Protocol must be IP. */ - if (reply.ar_pro != htons(ETHERTYPE_IP)) - continue; - if (reply.ar_pln != sizeof(reply_s)) - continue; - /* Only these types are recognised */ - if (reply.ar_op != htons(ARPOP_REPLY) && - reply.ar_op != htons(ARPOP_REQUEST)) - continue; - - /* Get pointers to the hardware addreses */ - hw_s = arp_reply + sizeof(reply); - hw_t = hw_s + reply.ar_hln + reply.ar_pln; - /* Ensure we got all the data */ - if ((hw_t + reply.ar_hln + reply.ar_pln) - arp_reply > bytes) - continue; - /* Ignore messages from ourself */ - if (reply.ar_hln == iface->hwlen && - memcmp(hw_s, iface->hwaddr, iface->hwlen) == 0) - continue; - /* Copy out the IP addresses */ - memcpy(&reply_s, hw_s + reply.ar_hln, reply.ar_pln); - memcpy(&reply_t, hw_t + reply.ar_hln, reply.ar_pln); - - /* Check for conflict */ - if (state->offer && - (reply_s == state->offer->yiaddr || - (reply_s == 0 && reply_t == state->offer->yiaddr))) - state->fail.s_addr = state->offer->yiaddr; - - /* Handle IPv4LL conflicts */ - if (IN_LINKLOCAL(htonl(iface->addr.s_addr)) && - (reply_s == iface->addr.s_addr || - (reply_s == 0 && reply_t == iface->addr.s_addr))) - state->fail.s_addr = iface->addr.s_addr; - - if (state->fail.s_addr) { - logger(LOG_ERR, "hardware address %s claims %s", - hwaddr_ntoa((unsigned char *)hw_s, - (size_t)reply.ar_hln), - inet_ntoa(state->fail)); - errno = EEXIST; - return -1; - } - } -} - -static int -handle_arp_fail(struct if_state *state, const struct options *options) -{ - time_t up; - int cookie = state->offer->cookie; - - if (!IN_LINKLOCAL(htonl(state->fail.s_addr))) { - state->state = STATE_INIT; - free(state->offer); - state->offer = NULL; - state->lease.addr.s_addr = 0; - if (!cookie) - return 1; - state->timeout.tv_sec = DHCP_ARP_FAIL; - state->timeout.tv_usec = 0; - do_socket(state, SOCKET_OPEN); - send_message(state, DHCP_DECLINE, options); - do_socket(state, SOCKET_CLOSED); - return 0; - } - - if (state->fail.s_addr == state->interface->addr.s_addr) { - if (state->state == STATE_PROBING) - /* This should only happen when SIGALRM or - * link when down/up and we have a conflict. */ - drop_config(state, "EXPIRE", options); - else { - up = uptime(); - if (state->defend + DEFEND_INTERVAL > up) { - drop_config(state, "EXPIRE", options); - state->conflicts = -1; - /* drop through to set conflicts to 0 */ - } else { - state->defend = up; - return 0; - } - } - } - do_socket(state, SOCKET_CLOSED); - state->conflicts++; - timerclear(&state->stop); - if (state->conflicts > MAX_CONFLICTS) { - logger(LOG_ERR, "failed to obtain an IPv4LL address"); - state->state = STATE_INIT; - timerclear(&state->timeout); - if (!(state->options & DHCPCD_DAEMONISED) && - (state->options & DHCPCD_DAEMONISE)) - return -1; - return 1; - } - state->state = STATE_INIT_IPV4LL; - state->timeout.tv_sec = PROBE_WAIT; - state->timeout.tv_usec = 0; - return 0; -} - -static int -handle_link(struct if_state *state) -{ - int retval; - - retval = link_changed(state->interface); - if (retval == -1) { - logger(LOG_ERR, "link_changed: %s", strerror(errno)); - return -1; - } - if (retval == 0) - return 0; - - timerclear(&state->timeout); - switch (carrier_status(state->interface->name)) { - case -1: - logger(LOG_ERR, "carrier_status: %s", strerror(errno)); - return -1; - case 0: - if (state->carrier != LINK_DOWN) { - logger(LOG_INFO, "carrier lost"); - state->carrier = LINK_DOWN; - do_socket(state, SOCKET_CLOSED); - if (state->state != STATE_BOUND) - timerclear(&state->stop); - } - break; - default: - if (state->carrier != LINK_UP) { - logger(LOG_INFO, "carrier acquired"); - state->state = STATE_RENEW_REQUESTED; - state->carrier = LINK_UP; - timerclear(&state->stop); - return 1; - } - break; - } - return 0; -} - -int -dhcp_run(const struct options *options, int *pid_fd) -{ - struct interface *iface; - struct if_state *state = NULL; - int fd = -1, r = 0, sig; - - iface = read_interface(options->interface, options->metric); - if (!iface) { - logger(LOG_ERR, "read_interface: %s", strerror(errno)); - goto eexit; - } - logger(LOG_DEBUG, "hardware address = %s", - hwaddr_ntoa(iface->hwaddr, iface->hwlen)); - state = xzalloc(sizeof(*state)); - state->pid_fd = pid_fd; - state->interface = iface; - if (!(options->options & DHCPCD_TEST)) - run_script(options, iface->name, "PREINIT", NULL, NULL); - - if (client_setup(state, options) == -1) - goto eexit; - if (signal_init() == -1) - goto eexit; - if (signal_setup() == -1) - goto eexit; - state->signal_fd = signal_fd(); - - if (state->options & DHCPCD_BACKGROUND && - !(state->options & DHCPCD_DAEMONISED)) - if (daemonise(state, options) == -1) - goto eexit; - - if (state->carrier == LINK_DOWN) - logger(LOG_INFO, "waiting for carrier"); - - for (;;) { - if (r == 0) - r = handle_timeout(state, options); - else if (r > 0) { - if (fd == state->signal_fd) { - if ((sig = signal_read()) != -1) - r = handle_signal(sig, state, options); - } else if (fd == iface->link_fd) - r = handle_link(state); - else if (fd == iface->raw_fd) - r = handle_dhcp_packet(state, options); - else if (fd == iface->arp_fd) { - if ((r = handle_arp_packet(state)) == -1) - r = handle_arp_fail(state, options); - } else - r = 0; - } - if (r == -1) - break; - if (r == 0) { - fd = -1; - r = wait_for_fd(state, &fd); - if (r == -1 && errno == EINTR) { - r = 1; - fd = state->signal_fd; - } - } else - r = 0; - } - -eexit: - if (iface) { - do_socket(state, SOCKET_CLOSED); - if (iface->link_fd != -1) - close(iface->link_fd); - free_routes(iface->routes); - free(iface->clientid); - free(iface->buffer); - free(iface); - } - - if (state) { - if (state->options & DHCPCD_FORKED) - r = 0; - if (state->options & DHCPCD_DAEMONISED) - unlink(options->pidfile); - free(state->offer); - free(state->new); - free(state->old); - free(state); - } - - return r; -} diff --git a/client.h b/client.h deleted file mode 100644 index 35a5e37..0000000 --- a/client.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef CLIENT_H -#define CLIENT_H - -#include "dhcpcd.h" - -int dhcp_run(const struct options *, int *); - -#endif diff --git a/common.c b/common.c deleted file mode 100644 index d90c7d2..0000000 --- a/common.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifdef __APPLE__ -# include -# include -#endif - -#include -#include - -#include -#include -#ifdef BSD -# include -#endif -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "logger.h" - -#ifndef _PATH_DEVNULL -# define _PATH_DEVNULL "/dev/null" -#endif - -int clock_monotonic = 0; - -/* Handy routine to read very long lines in text files. - * This means we read the whole line and avoid any nasty buffer overflows. */ -ssize_t -get_line(char **line, size_t *len, FILE *fp) -{ - char *p; - size_t last = 0; - - while(!feof(fp)) { - if (*line == NULL || last != 0) { - *len += BUFSIZ; - *line = xrealloc(*line, *len); - } - p = *line + last; - memset(p, 0, BUFSIZ); - fgets(p, BUFSIZ, fp); - last += strlen(p); - if (last && (*line)[last - 1] == '\n') { - (*line)[last - 1] = '\0'; - break; - } - } - return last; -} - -/* Simple hack to return a random number without arc4random */ -#ifndef HAVE_ARC4RANDOM -uint32_t arc4random(void) -{ - int fd; - static unsigned long seed = 0; - - if (!seed) { - fd = open("/dev/urandom", 0); - if (fd == -1 || read(fd, &seed, sizeof(seed)) == -1) - seed = time(0); - if (fd >= 0) - close(fd); - srandom(seed); - } - - return (uint32_t)random(); -} -#endif - -/* strlcpy is nice, shame glibc does not define it */ -#if HAVE_STRLCPY -#else -size_t -strlcpy(char *dst, const char *src, size_t size) -{ - const char *s = src; - size_t n = size; - - if (n && --n) - do { - if (!(*dst++ = *src++)) - break; - } while (--n); - - if (!n) { - if (size) - *dst = '\0'; - while (*src++); - } - - return src - s - 1; -} -#endif - -#if HAVE_CLOSEFROM -#else -int -closefrom(int fd) -{ - int max = getdtablesize(); - int i; - int r = 0; - - for (i = fd; i < max; i++) - r += close(i); - return r; -} -#endif - -/* Close our fd's */ -int -close_fds(void) -{ - int fd; - - if ((fd = open(_PATH_DEVNULL, O_RDWR)) == -1) - return -1; - - dup2(fd, fileno(stdin)); - dup2(fd, fileno(stdout)); - dup2(fd, fileno(stderr)); - if (fd > 2) - close(fd); - return 0; -} - -int -set_cloexec(int fd) -{ - int flags; - - if ((flags = fcntl(fd, F_GETFD, 0)) == -1 - || fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - { - logger(LOG_ERR, "fcntl: %s", strerror(errno)); - return -1; - } - return 0; -} - -int -set_nonblock(int fd) -{ - int flags; - - if ((flags = fcntl(fd, F_GETFL, 0)) == -1 - || fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) - { - logger(LOG_ERR, "fcntl: %s", strerror(errno)); - return -1; - } - return 0; -} - -/* Handy function to get the time. - * We only care about time advancements, not the actual time itself - * Which is why we use CLOCK_MONOTONIC, but it is not available on all - * platforms. - */ -#define NO_MONOTONIC "host does not support a monotonic clock - timing can skew" -int -get_monotonic(struct timeval *tp) -{ - static int posix_clock_set = 0; -#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC) - struct timespec ts; - static clockid_t posix_clock; - - if (posix_clock_set == 0) { - if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - posix_clock = CLOCK_MONOTONIC; - clock_monotonic = 1; - } - posix_clock_set = 1; - } - - if (clock_monotonic) { - if (clock_gettime(posix_clock, &ts) == 0) { - tp->tv_sec = ts.tv_sec; - tp->tv_usec = ts.tv_nsec / 1000; - return 0; - } - } -#elif defined(__APPLE__) -#define NSEC_PER_SEC 1000000000 - /* We can use mach kernel functions here. - * This is crap though - why can't they implement clock_gettime?*/ - static struct mach_timebase_info info = { 0, 0 }; - static double factor = 0.0; - uint64_t nano; - long rem; - - if (posix_clock_set == 0) { - if (mach_timebase_info(&info) == KERN_SUCCESS) { - factor = (double)info.numer / (double)info.denom; - clock_monotonic = 1; - } - posix_clock_set = 1; - } - if (clock_monotonic) { - nano = mach_absolute_time(); - if ((info.denom != 1 || info.numer != 1) && factor != 0.0) - nano *= factor; - tp->tv_sec = nano / NSEC_PER_SEC; - rem = nano % NSEC_PER_SEC; - if (rem < 0) { - tp->tv_sec--; - rem += NSEC_PER_SEC; - } - tp->tv_usec = rem / 1000; - return 0; - } -#endif - - /* Something above failed, so fall back to gettimeofday */ - if (!posix_clock_set) { - logger(LOG_WARNING, NO_MONOTONIC); - posix_clock_set = 1; - } - return gettimeofday(tp, NULL); -} - -time_t -uptime(void) -{ - struct timeval tv; - - if (get_monotonic(&tv) == -1) - return -1; - return tv.tv_sec; -} - -int -writepid(int fd, pid_t pid) -{ - char spid[16]; - ssize_t len; - - if (ftruncate(fd, (off_t)0) == -1) - return -1; - snprintf(spid, sizeof(spid), "%u\n", pid); - len = pwrite(fd, spid, strlen(spid), (off_t)0); - if (len != (ssize_t)strlen(spid)) - return -1; - return 0; -} - -void * -xmalloc(size_t s) -{ - void *value = malloc(s); - - if (value) - return value; - logger(LOG_ERR, "memory exhausted"); - exit (EXIT_FAILURE); - /* NOTREACHED */ -} - -void * -xzalloc(size_t s) -{ - void *value = xmalloc(s); - - memset(value, 0, s); - return value; -} - -void * -xrealloc(void *ptr, size_t s) -{ - void *value = realloc(ptr, s); - - if (value) - return (value); - logger(LOG_ERR, "memory exhausted"); - exit(EXIT_FAILURE); - /* NOTREACHED */ -} - -char * -xstrdup(const char *str) -{ - char *value; - - if (!str) - return NULL; - - if ((value = strdup(str))) - return value; - - logger(LOG_ERR, "memory exhausted"); - exit(EXIT_FAILURE); - /* NOTREACHED */ -} diff --git a/common.h b/common.h deleted file mode 100644 index 2522663..0000000 --- a/common.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef COMMON_H -#define COMMON_H - -/* string.h pulls in features.h so the below define checks work */ -#include -#include -#include -#include -#include - -#define UNCONST(a) ((void *)(unsigned long)(const void *)(a)) - -#if __GNUC__ > 2 || defined(__INTEL_COMPILER) -# define _unused __attribute__((__unused__)) -#else -# define _unused -#endif - -#ifndef HAVE_ARC4RANDOM -# ifdef __GLIBC__ -uint32_t arc4random(void); -#else -# define HAVE_ARC4RANDOM -# endif -#endif - -#ifndef HAVE_STRLCPY -# define HAVE_STRLCPY 1 -#endif -/* Only GLIBC doesn't support strlcpy */ -#ifdef __GLIBC__ -# if !defined(__UCLIBC__) && !defined (__dietlibc__) -# undef HAVE_STRLCPY -size_t strlcpy(char *, const char *, size_t); -# endif -#endif - -#ifndef HAVE_CLOSEFROM -# if defined(__NetBSD__) || defined(__OpenBSD__) -# define HAVE_CLOSEFROM 1 -# endif -#endif -#ifndef HAVE_CLOSEFROM -int closefrom(int); -#endif - -int close_fds(void); -int set_cloexec(int); -int set_nonblock(int); -ssize_t get_line(char **, size_t *, FILE *); -extern int clock_monotonic; -int get_monotonic(struct timeval *); -time_t uptime(void); -int writepid(int, pid_t); -void *xrealloc(void *, size_t); -void *xmalloc(size_t); -void *xzalloc(size_t); -char *xstrdup(const char *); - -#endif diff --git a/config.h b/config.h deleted file mode 100644 index cff7079..0000000 --- a/config.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef CONFIG_H -#define CONFIG_H - -#define PACKAGE "dhcpcd" -#define VERSION "4.0.1" - -/* - * By default we don't add a local link route if we got a routeable address. - * This is because dhcpcd can't really decide which interface should allow - * link local routing when we have more than one interface. - * Ideally the host network scripts should add the link local route for us. - * If not, you can define this to get dhcpcd to always add the link local route. - */ -// #define IPV4LL_ALWAYSROUTE - -/* Some systems do not have a working fork. */ -/* #define THERE_IS_NO_FORK */ - -/* Paths to things */ -#ifndef SYSCONFDIR -# define SYSCONFDIR "/system/etc/dhcpcd" -#endif -#ifndef LIBEXECDIR -# define LIBEXECDIR "/system/etc/dhcpcd" -#endif -#ifndef RUNDIR -# define RUNDIR "/data/misc/dhcp" -#endif -#ifndef DBDIR -# define DBDIR "/data/misc/dhcp" -#endif - -#ifndef CONFIG -# define CONFIG SYSCONFDIR "/" PACKAGE ".conf" -#endif -#ifndef SCRIPT -# define SCRIPT LIBEXECDIR "/" PACKAGE "-run-hooks" -#endif -#ifndef DUID -# define DUID SYSCONFDIR "/" PACKAGE ".duid" -#endif -#ifndef LEASEFILE -# define LEASEFILE DBDIR "/" PACKAGE "-%s.lease" -#endif -#ifndef PIDFILE -# define PIDFILE RUNDIR "/" PACKAGE "-%s.pid" -#endif - -#endif diff --git a/configure.c b/configure.c deleted file mode 100644 index dad3bce..0000000 --- a/configure.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "configure.h" -#include "dhcp.h" -#include "dhcpcd.h" -#include "logger.h" -#include "net.h" -#include "signals.h" - -#define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" - - -static int -exec_script(char *const *argv, char *const *env) -{ - pid_t pid; - sigset_t full; - sigset_t old; - - /* OK, we need to block signals */ - sigfillset(&full); - sigprocmask(SIG_SETMASK, &full, &old); - signal_reset(); - - switch (pid = vfork()) { - case -1: - logger(LOG_ERR, "vfork: %s", strerror(errno)); - break; - case 0: - sigprocmask(SIG_SETMASK, &old, NULL); - execve(argv[0], argv, env); - logger(LOG_ERR, "%s: %s", argv[0], strerror(errno)); - _exit(127); - /* NOTREACHED */ - } - - /* Restore our signals */ - signal_setup(); - sigprocmask(SIG_SETMASK, &old, NULL); - return pid; -} - -int -run_script(const struct options *options, const char *iface, - const char *reason, - const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo) -{ - char *const argv[2] = { UNCONST(options->script), NULL }; - char **env = NULL, **ep; - char *path; - ssize_t e, elen; - pid_t pid; - int status = 0; - - logger(LOG_DEBUG, "executing `%s', reason %s", options->script, reason); - - /* Make our env */ - elen = 5; - env = xmalloc(sizeof(char *) * (elen + 1)); - path = getenv("PATH"); - if (path) { - e = strlen("PATH") + strlen(path) + 2; - env[0] = xmalloc(e); - snprintf(env[0], e, "PATH=%s", path); - } else - env[0] = xstrdup(DEFAULT_PATH); - e = strlen("interface") + strlen(iface) + 2; - env[1] = xmalloc(e); - snprintf(env[1], e, "interface=%s", iface); - e = strlen("reason") + strlen(reason) + 2; - env[2] = xmalloc(e); - snprintf(env[2], e, "reason=%s", reason); - e = 20; - env[3] = xmalloc(e); - snprintf(env[3], e, "pid=%d", getpid()); - env[4] = xmalloc(e); - snprintf(env[4], e, "metric=%d", options->metric); - if (dhcpo) { - e = configure_env(NULL, NULL, dhcpo, options); - if (e > 0) { - env = xrealloc(env, sizeof(char *) * (elen + e + 1)); - elen += configure_env(env + elen, "old", dhcpo, options); - } - } - if (dhcpn) { - e = configure_env(NULL, NULL, dhcpn, options); - if (e > 0) { - env = xrealloc(env, sizeof(char *) * (elen + e + 1)); - elen += configure_env(env + elen, "new", dhcpn, options); - } - } - /* Add our base environment */ - if (options->environ) { - e = 0; - while (options->environ[e++]) - ; - env = xrealloc(env, sizeof(char *) * (elen + e + 1)); - e = 0; - while (options->environ[e]) { - env[elen + e] = xstrdup(options->environ[e]); - e++; - } - elen += e; - } - env[elen] = '\0'; - - pid = exec_script(argv, env); - if (pid == -1) - status = -1; - else if (pid != 0) { - /* Wait for the script to finish */ - while (waitpid(pid, &status, 0) == -1) { - if (errno != EINTR) { - logger(LOG_ERR, "waitpid: %s", strerror(errno)); - status = -1; - break; - } - } - } - - /* Cleanup */ - ep = env; - while (*ep) - free(*ep++); - free(env); - return status; -} - -static struct rt * -reverse_routes(struct rt *routes) -{ - struct rt *rt; - struct rt *rtn = NULL; - - while (routes) { - rt = routes->next; - routes->next = rtn; - rtn = routes; - routes = rt; - } - return rtn; -} - -static int -delete_route(const char *iface, struct rt *rt, int metric) -{ - char *addr; - int retval; - - addr = xstrdup(inet_ntoa(rt->dest)); - logger(LOG_DEBUG, "deleting route %s/%d via %s", - addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate)); - free(addr); - retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric); - if (retval != 0 && errno != ENOENT && errno != ESRCH) - logger(LOG_ERR," del_route: %s", strerror(errno)); - return retval; -} - -static int -delete_routes(struct interface *iface, int metric) -{ - struct rt *rt; - struct rt *rtn; - int retval = 0; - - rt = reverse_routes(iface->routes); - while (rt) { - rtn = rt->next; - retval += delete_route(iface->name, rt, metric); - free(rt); - rt = rtn; - } - iface->routes = NULL; - - return retval; -} - -static int -in_routes(const struct rt *routes, const struct rt *rt) -{ - while (routes) { - if (routes->dest.s_addr == rt->dest.s_addr && - routes->net.s_addr == rt->net.s_addr && - routes->gate.s_addr == rt->gate.s_addr) - return 0; - routes = routes->next; - } - return -1; -} - -static int -configure_routes(struct interface *iface, const struct dhcp_message *dhcp, - const struct options *options) -{ - struct rt *rt, *ort; - struct rt *rtn = NULL, *nr = NULL; - int remember; - int retval = 0; - char *addr; - - ort = get_option_routes(dhcp); - -#ifdef IPV4LL_ALWAYSROUTE - if (options->options & DHCPCD_IPV4LL && - IN_PRIVATE(ntohl(dhcp->yiaddr))) - { - for (rt = ort; rt; rt = rt->next) { - /* Check if we have already got a link locale route - * dished out by the DHCP server */ - if (rt->dest.s_addr == htonl(LINKLOCAL_ADDR) && - rt->net.s_addr == htonl(LINKLOCAL_MASK)) - break; - rtn = rt; - } - - if (!rt) { - rt = xmalloc(sizeof(*rt)); - rt->dest.s_addr = htonl(LINKLOCAL_ADDR); - rt->net.s_addr = htonl(LINKLOCAL_MASK); - rt->gate.s_addr = 0; - rt->next = NULL; - if (rtn) - rtn->next = rt; - else - ort = rt; - } - } -#endif - - /* Now remove old routes we no longer use. - * We should do this in reverse order. */ - iface->routes = reverse_routes(iface->routes); - for (rt = iface->routes; rt; rt = rt->next) - if (in_routes(ort, rt) != 0) - delete_route(iface->name, rt, options->metric); - - for (rt = ort; rt; rt = rt->next) { - /* Don't set default routes if not asked to */ - if (rt->dest.s_addr == 0 && - rt->net.s_addr == 0 && - !(options->options & DHCPCD_GATEWAY)) - continue; - - addr = xstrdup(inet_ntoa(rt->dest)); - logger(LOG_DEBUG, "adding route to %s/%d via %s", - addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate)); - free(addr); - remember = add_route(iface->name, &rt->dest, - &rt->net, &rt->gate, - options->metric); - retval += remember; - - /* If we failed to add the route, we may have already added it - ourselves. If so, remember it again. */ - if (remember < 0) { - if (errno != EEXIST) - logger(LOG_ERR, "add_route: %s", - strerror(errno)); - if (in_routes(iface->routes, rt) == 0) - remember = 1; - } - - /* This login is split from above due to the #ifdef below */ - if (remember >= 0) { - if (nr) { - rtn->next = xmalloc(sizeof(*rtn)); - rtn = rtn->next; - } else { - nr = rtn = xmalloc(sizeof(*rtn)); - } - rtn->dest.s_addr = rt->dest.s_addr; - rtn->net.s_addr = rt->net.s_addr; - rtn->gate.s_addr = rt->gate.s_addr; - rtn->next = NULL; - } - } - free_routes(ort); - free_routes(iface->routes); - iface->routes = nr; - return retval; -} - -static int -delete_address(struct interface *iface) -{ - int retval; - logger(LOG_DEBUG, "deleting IP address %s/%d", - inet_ntoa(iface->addr), - inet_ntocidr(iface->net)); - retval = del_address(iface->name, &iface->addr, &iface->net); - if (retval == -1 && errno != EADDRNOTAVAIL) - logger(LOG_ERR, "del_address: %s", strerror(errno)); - iface->addr.s_addr = 0; - iface->net.s_addr = 0; - return retval; -} - -int -configure(struct interface *iface, const char *reason, - const struct dhcp_message *dhcp, const struct dhcp_message *old, - const struct dhcp_lease *lease, const struct options *options, - int up) -{ - struct in_addr addr; - struct in_addr net; - struct in_addr brd; -#ifdef __linux__ - struct in_addr dest; - struct in_addr gate; -#endif - - /* Grab our IP config */ - if (dhcp == NULL) - up = 0; - else { - addr.s_addr = dhcp->yiaddr; - if (addr.s_addr == 0) - addr.s_addr = lease->addr.s_addr; - /* Ensure we have all the needed values */ - if (get_option_addr(&net.s_addr, dhcp, DHO_SUBNETMASK) == -1) - net.s_addr = get_netmask(addr.s_addr); - if (get_option_addr(&brd.s_addr, dhcp, DHO_BROADCAST) == -1) - brd.s_addr = addr.s_addr | ~net.s_addr; - } - - /* If we aren't up, then reset the interface as much as we can */ - if (!up) { - /* Only reset things if we had set them before */ - if (iface->addr.s_addr != 0) { - delete_routes(iface, options->metric); - delete_address(iface); - } - - run_script(options, iface->name, reason, NULL, old); - return 0; - } - - /* This also changes netmask */ - if (!(options->options & DHCPCD_INFORM) || - !has_address(iface->name, &addr, &net)) { - logger(LOG_DEBUG, "adding IP address %s/%d", - inet_ntoa(addr), inet_ntocidr(net)); - if (add_address(iface->name, &addr, &net, &brd) == -1 && - errno != EEXIST) - { - logger(LOG_ERR, "add_address: %s", strerror(errno)); - return -1; - } - } - - /* Now delete the old address if different */ - if (iface->addr.s_addr != addr.s_addr && - iface->addr.s_addr != 0) - delete_address(iface); - -#ifdef __linux__ - /* On linux, we need to change the subnet route to have our metric. */ - if (iface->addr.s_addr != lease->addr.s_addr && - options->metric > 0 && net.s_addr != INADDR_BROADCAST) - { - dest.s_addr = addr.s_addr & net.s_addr; - gate.s_addr = 0; - add_route(iface->name, &dest, &net, &gate, options->metric); - del_route(iface->name, &dest, &net, &gate, 0); - } -#endif - - configure_routes(iface, dhcp, options); - up = (iface->addr.s_addr != addr.s_addr || - iface->net.s_addr != net.s_addr); - iface->addr.s_addr = addr.s_addr; - iface->net.s_addr = net.s_addr; - - if (!lease->frominfo) - if (write_lease(iface, dhcp) == -1) - logger(LOG_ERR, "write_lease: %s", strerror(errno)); - - run_script(options, iface->name, reason, dhcp, old); - return 0; -} diff --git a/configure.h b/configure.h deleted file mode 100644 index fe065db..0000000 --- a/configure.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef DHCPCONFIG_H -#define DHCPCONFIG_H - -#include "dhcpcd.h" -#include "dhcp.h" -#include "net.h" - -int run_script(const struct options *, const char *, const char *, - const struct dhcp_message *, const struct dhcp_message *); -int configure(struct interface *, const char *, - const struct dhcp_message *, const struct dhcp_message *, - const struct dhcp_lease *, const struct options *, int); - -#endif diff --git a/dhcp.c b/dhcp.c deleted file mode 100644 index 2469429..0000000 --- a/dhcp.c +++ /dev/null @@ -1,1251 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "dhcp.h" - -#define REQUEST (1 << 0) -#define UINT8 (1 << 1) -#define UINT16 (1 << 2) -#define SINT16 (1 << 3) -#define UINT32 (1 << 4) -#define SINT32 (1 << 5) -#define IPV4 (1 << 6) -#define STRING (1 << 7) -#define PAIR (1 << 8) -#define ARRAY (1 << 9) -#define RFC3361 (1 << 10) -#define RFC3397 (1 << 11) -#define RFC3442 (1 << 12) - -#define IPV4R IPV4 | REQUEST - -/* Our aggregate option buffer. - * We ONLY use this when options are split, which for most purposes is - * practically never. See RFC3396 for details. */ -static uint8_t *dhcp_opt_buffer = NULL; - -struct dhcp_opt { - uint8_t option; - int type; - const char *var; -}; - -static const struct dhcp_opt const dhcp_opts[] = { - { 1, IPV4 | REQUEST, "subnet_mask" }, - { 2, UINT32, "time_offset" }, - { 3, IPV4 | ARRAY | REQUEST, "routers" }, - { 4, IPV4 | ARRAY, "time_servers" }, - { 5, IPV4 | ARRAY, "ien116_name_servers" }, - { 6, IPV4 | ARRAY, "domain_name_servers" }, - { 7, IPV4 | ARRAY, "log_servers" }, - { 8, IPV4 | ARRAY, "cookie_servers" }, - { 9, IPV4 | ARRAY, "lpr_servers" }, - { 10, IPV4 | ARRAY, "impress_servers" }, - { 11, IPV4 | ARRAY, "resource_location_servers" }, - { 12, STRING, "host_name" }, - { 13, UINT16, "boot_size" }, - { 14, STRING, "merit_dump" }, - { 15, STRING, "domain_name" }, - { 16, IPV4, "swap_server" }, - { 17, STRING, "root_path" }, - { 18, STRING, "extensions_path" }, - { 19, UINT8, "ip_forwarding" }, - { 20, UINT8, "non_local_source_routing" }, - { 21, IPV4 | ARRAY, "policy_filter" }, - { 22, SINT16, "max_dgram_reassembly" }, - { 23, UINT16, "default_ip_ttl" }, - { 24, UINT32, "path_mtu_aging_timeout" }, - { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, - { 26, UINT16, "interface_mtu" }, - { 27, UINT8, "all_subnets_local" }, - { 28, IPV4 | REQUEST, "broadcast_address" }, - { 29, UINT8, "perform_mask_discovery" }, - { 30, UINT8, "mask_supplier" }, - { 31, UINT8, "router_discovery" }, - { 32, IPV4, "router_solicitation_address" }, - { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, - { 34, UINT8, "trailer_encapsulation" }, - { 35, UINT32, "arp_cache_timeout" }, - { 36, UINT16, "ieee802_3_encapsulation" }, - { 37, UINT8, "default_tcp_ttl" }, - { 38, UINT32, "tcp_keepalive_interval" }, - { 39, UINT8, "tcp_keepalive_garbage" }, - { 40, STRING, "nis_domain" }, - { 41, IPV4 | ARRAY, "nis_servers" }, - { 42, IPV4 | ARRAY, "ntp_servers" }, - { 43, STRING, "vendor_encapsulated_options" }, - { 44, IPV4 | ARRAY, "netbios_name_servers" }, - { 45, IPV4, "netbios_dd_server" }, - { 46, UINT8, "netbios_node_type" }, - { 47, STRING, "netbios_scope" }, - { 48, IPV4 | ARRAY, "font_servers" }, - { 49, IPV4 | ARRAY, "x_display_manager" }, - { 50, IPV4, "dhcp_requested_address" }, - { 51, UINT32 | REQUEST, "dhcp_lease_time" }, - { 52, UINT8, "dhcp_option_overload" }, - { 53, UINT8, "dhcp_message_type" }, - { 54, IPV4, "dhcp_server_identifier" }, - { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, - { 56, STRING, "dhcp_message" }, - { 57, UINT16, "dhcp_max_message_size" }, - { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, - { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, - { 64, STRING, "nisplus_domain" }, - { 65, IPV4 | ARRAY, "nisplus_servers" }, - { 66, STRING, "tftp_server_name" }, - { 67, STRING, "bootfile_name" }, - { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, - { 69, IPV4 | ARRAY, "smtp_server" }, - { 70, IPV4 | ARRAY, "pop_server" }, - { 71, IPV4 | ARRAY, "nntp_server" }, - { 72, IPV4 | ARRAY, "www_server" }, - { 73, IPV4 | ARRAY, "finger_server" }, - { 74, IPV4 | ARRAY, "irc_server" }, - { 75, IPV4 | ARRAY, "streettalk_server" }, - { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, - { 77, STRING, "user_class" }, - { 81, STRING | RFC3397, "fqdn_name" }, - { 85, IPV4 | ARRAY, "nds_servers" }, - { 86, STRING, "nds_tree_name" }, - { 87, STRING, "nds_context" }, - { 88, STRING | RFC3397, "bcms_controller_names" }, - { 89, IPV4 | ARRAY, "bcms_controller_address" }, - { 91, UINT32, "client_last_transaction_time" }, - { 92, IPV4 | ARRAY, "associated_ip" }, - { 98, STRING, "uap_servers" }, - { 112, IPV4 | ARRAY, "netinfo_server_address" }, - { 113, STRING, "netinfo_server_tag" }, - { 114, STRING, "default_url" }, - { 118, IPV4, "subnet_selection" }, - { 119, STRING | RFC3397, "domain_search" }, - { 121, RFC3442 | REQUEST, "classless_static_routes" }, - { 249, RFC3442, "ms_classless_static_routes" }, - { 0, 0, NULL } -}; - -void -print_options(void) -{ - const struct dhcp_opt *opt; - - for (opt = dhcp_opts; opt->option; opt++) - if (opt->var) - printf("%03d %s\n", opt->option, opt->var); -} - -int make_option_mask(uint8_t *mask, char **opts, int add) -{ - char *token, *p = *opts, *t; - const struct dhcp_opt *opt; - int match, n; - - while ((token = strsep(&p, ", "))) { - if (*token == '\0') - continue; - for (opt = dhcp_opts; opt->option; opt++) { - if (!opt->var) - continue; - match = 0; - if (strcmp(opt->var, token) == 0) - match = 1; - else { - errno = 0; - n = strtol(token, &t, 0); - if (errno == 0 && !*t) - if (opt->option == n) - match = 1; - } - if (match) { - if (add == 1) - add_option_mask(mask, - opt->option); - else - del_option_mask(mask, - opt->option); - break; - } - } - if (!opt->option) { - *opts = token; - errno = ENOENT; - return -1; - } - } - return 0; -} - -static int -valid_length(uint8_t option, int dl, int *type) -{ - const struct dhcp_opt *opt; - ssize_t sz; - - if (dl == 0) - return -1; - - for (opt = dhcp_opts; opt->option; opt++) { - if (opt->option != option) - continue; - - if (type) - *type = opt->type; - - if (opt->type == 0 || opt->type & STRING || opt->type & RFC3442) - return 0; - - sz = 0; - if (opt->type & UINT32 || opt->type & IPV4) - sz = sizeof(uint32_t); - if (opt->type & UINT16) - sz = sizeof(uint16_t); - if (opt->type & UINT8) - sz = sizeof(uint8_t); - if (opt->type & IPV4 || opt->type & ARRAY) - return dl % sz; - return (dl == sz ? 0 : -1); - } - - /* unknown option, so let it pass */ - return 0; -} - -static void -free_option_buffer(void) -{ - free(dhcp_opt_buffer); -} - -#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) -static const uint8_t * -get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) -{ - const uint8_t *p = dhcp->options; - const uint8_t *e = p + sizeof(dhcp->options); - uint8_t l, ol = 0; - uint8_t o = 0; - uint8_t overl = 0; - uint8_t *bp = NULL; - const uint8_t *op = NULL; - int bl = 0; - - while (p < e) { - o = *p++; - if (o == opt) { - if (op) { - if (!dhcp_opt_buffer) { - dhcp_opt_buffer = xmalloc(sizeof(struct dhcp_message)); - atexit(free_option_buffer); - } - if (!bp) - bp = dhcp_opt_buffer; - memcpy(bp, op, ol); - bp += ol; - } - ol = *p; - op = p + 1; - bl += ol; - } - switch (o) { - case DHO_PAD: - continue; - case DHO_END: - if (overl & 1) { - /* bit 1 set means parse boot file */ - overl &= ~1; - p = dhcp->bootfile; - e = p + sizeof(dhcp->bootfile); - } else if (overl & 2) { - /* bit 2 set means parse server name */ - overl &= ~2; - p = dhcp->servername; - e = p + sizeof(dhcp->servername); - } else - goto exit; - break; - case DHO_OPTIONSOVERLOADED: - /* Ensure we only get this option once */ - if (!overl) - overl = p[1]; - break; - } - l = *p++; - p += l; - } - -exit: - if (valid_length(opt, bl, type) == -1) { - errno = EINVAL; - return NULL; - } - if (len) - *len = bl; - if (bp) { - memcpy(bp, op, ol); - return (const uint8_t *)&dhcp_opt_buffer; - } - if (op) - return op; - errno = ENOENT; - return NULL; -} - -int -get_option_addr(uint32_t *a, const struct dhcp_message *dhcp, uint8_t option) -{ - const uint8_t *p = get_option_raw(dhcp, option); - - if (!p) - return -1; - memcpy(a, p, sizeof(*a)); - return 0; -} - -int -get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) -{ - uint32_t a; - - if (get_option_addr(&a, dhcp, option) == -1) - return -1; - - *i = ntohl(a); - return 0; -} - -int -get_option_uint16(uint16_t *i, const struct dhcp_message *dhcp, uint8_t option) -{ - const uint8_t *p = get_option_raw(dhcp, option); - uint16_t d; - - if (!p) - return -1; - memcpy(&d, p, sizeof(d)); - *i = ntohs(d); - return 0; -} - -int -get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option) -{ - const uint8_t *p = get_option_raw(dhcp, option); - - if (!p) - return -1; - *i = *(p); - return 0; -} - -/* Decode an RFC3397 DNS search order option into a space - * seperated string. Returns length of string (including - * terminating zero) or zero on error. out may be NULL - * to just determine output length. */ -static ssize_t -decode_rfc3397(char *out, ssize_t len, int pl, const uint8_t *p) -{ - const uint8_t *r, *q = p; - int count = 0, l, hops; - uint8_t ltype; - - while (q - p < pl) { - r = NULL; - hops = 0; - /* We check we are inside our length again incase - * the data is NOT terminated correctly. */ - while ((l = *q++) && q - p < pl) { - ltype = l & 0xc0; - if (ltype == 0x80 || ltype == 0x40) - return 0; - else if (ltype == 0xc0) { /* pointer */ - l = (l & 0x3f) << 8; - l |= *q++; - /* save source of first jump. */ - if (!r) - r = q; - hops++; - if (hops > 255) - return 0; - q = p + l; - if (q - p >= pl) - return 0; - } else { - /* straightforward name segment, add with '.' */ - count += l + 1; - if (out) { - if ((ssize_t)l + 1 > len) { - errno = ENOBUFS; - return -1; - } - memcpy(out, q, l); - out += l; - *out++ = '.'; - len -= l; - len--; - } - q += l; - } - } - /* change last dot to space */ - if (out) - *(out - 1) = ' '; - if (r) - q = r; - } - - /* change last space to zero terminator */ - if (out) - *(out - 1) = 0; - - return count; -} - -static ssize_t -decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p) -{ - const uint8_t *e; - ssize_t bytes = 0; - ssize_t b; - uint8_t cidr; - uint8_t ocets; - struct in_addr addr; - char *o = out; - - /* Minimum is 5 -first is CIDR and a router length of 4 */ - if (pl < 5) { - errno = EINVAL; - return -1; - } - - e = p + pl; - while (p < e) { - cidr = *p++; - if (cidr > 32) { - errno = EINVAL; - return -1; - } - ocets = (cidr + 7) / 8; - if (!out) { - p += 4 + ocets; - bytes += ((4 * 4) * 2) + 4; - continue; - } - if ((((4 * 4) * 2) + 4) > len) { - errno = ENOBUFS; - return -1; - } - if (o != out) { - *o++ = ' '; - len--; - } - /* If we have ocets then we have a destination and netmask */ - if (ocets > 0) { - addr.s_addr = 0; - memcpy(&addr.s_addr, p, (size_t)ocets); - b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr); - p += ocets; - } else - b = snprintf(o, len, "0.0.0.0/0"); - o += b; - len -= b; - - /* Finally, snag the router */ - memcpy(&addr.s_addr, p, 4); - p += 4; - b = snprintf(o, len, " %s", inet_ntoa(addr)); - o += b; - len -= b; - } - - if (out) - return o - out; - return bytes; -} - -static struct rt * -decode_rfc3442_rt(int dl, const uint8_t *data) -{ - const uint8_t *p = data; - const uint8_t *e; - uint8_t cidr; - uint8_t ocets; - struct rt *routes = NULL; - struct rt *rt = NULL; - - /* Minimum is 5 -first is CIDR and a router length of 4 */ - if (dl < 5) - return NULL; - - e = p + dl; - while (p < e) { - cidr = *p++; - if (cidr > 32) { - free_routes(routes); - errno = EINVAL; - return NULL; - } - - if (rt) { - rt->next = xzalloc(sizeof(*rt)); - rt = rt->next; - } else { - routes = rt = xzalloc(sizeof(*routes)); - } - rt->next = NULL; - - ocets = (cidr + 7) / 8; - /* If we have ocets then we have a destination and netmask */ - if (ocets > 0) { - memcpy(&rt->dest.s_addr, p, (size_t)ocets); - memset(&rt->net.s_addr, 255, (size_t)ocets - 1); - memset((uint8_t *)&rt->net.s_addr + - (ocets - 1), - (256 - (1 << (32 - cidr) % 8)), 1); - p += ocets; - } else { - rt->dest.s_addr = 0; - rt->net.s_addr = 0; - } - - /* Finally, snag the router */ - memcpy(&rt->gate.s_addr, p, 4); - p += 4; - } - return routes; -} - -static char * -decode_rfc3361(int dl, const uint8_t *data) -{ - uint8_t enc; - unsigned int l; - char *sip = NULL; - struct in_addr addr; - char *p; - - if (dl < 2) { - errno = EINVAL; - return 0; - } - - enc = *data++; - dl--; - switch (enc) { - case 0: - if ((l = decode_rfc3397(NULL, 0, dl, data)) > 0) { - sip = xmalloc(l); - decode_rfc3397(sip, l, dl, data); - } - break; - case 1: - if (dl == 0 || dl % 4 != 0) { - errno = EINVAL; - break; - } - addr.s_addr = INADDR_BROADCAST; - l = ((dl / sizeof(addr.s_addr)) * ((4 * 4) + 1)) + 1; - sip = p = xmalloc(l); - while (l != 0) { - memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); - data += sizeof(addr.s_addr); - p += snprintf(p, l - (p - sip), "%s ", inet_ntoa(addr)); - l -= sizeof(addr.s_addr); - } - *--p = '\0'; - break; - default: - errno = EINVAL; - return 0; - } - - return sip; -} - -char * -get_option_string(const struct dhcp_message *dhcp, uint8_t option) -{ - int type = 0; - int len; - const uint8_t *p; - char *s; - - p = get_option(dhcp, option, &len, &type); - if (!p || *p == '\0') - return NULL; - - if (type & RFC3397) { - type = decode_rfc3397(NULL, 0, len, p); - if (!type) { - errno = EINVAL; - return NULL; - } - s = xmalloc(sizeof(char) * type); - decode_rfc3397(s, type, len, p); - return s; - } - - if (type & RFC3361) - return decode_rfc3361(len, p); - - s = xmalloc(sizeof(char) * (len + 1)); - memcpy(s, p, len); - s[len] = '\0'; - return s; -} - -/* This calculates the netmask that we should use for static routes. - * This IS different from the calculation used to calculate the netmask - * for an interface address. */ -static uint32_t -route_netmask(uint32_t ip_in) -{ - /* used to be unsigned long - check if error */ - uint32_t p = ntohl(ip_in); - uint32_t t; - - if (IN_CLASSA(p)) - t = ~IN_CLASSA_NET; - else { - if (IN_CLASSB(p)) - t = ~IN_CLASSB_NET; - else { - if (IN_CLASSC(p)) - t = ~IN_CLASSC_NET; - else - t = 0; - } - } - - while (t & p) - t >>= 1; - - return (htonl(~t)); -} - -/* We need to obey routing options. - * If we have a CSR then we only use that. - * Otherwise we add static routes and then routers. */ -struct rt * -get_option_routes(const struct dhcp_message *dhcp) -{ - const uint8_t *p; - const uint8_t *e; - struct rt *routes = NULL; - struct rt *route = NULL; - int len; - - /* If we have CSR's then we MUST use these only */ - p = get_option(dhcp, DHO_CSR, &len, NULL); - /* Check for crappy MS option */ - if (!p) - p = get_option(dhcp, DHO_MSCSR, &len, NULL); - if (p) { - routes = decode_rfc3442_rt(len, p); - if (routes) - return routes; - } - - /* OK, get our static routes first. */ - p = get_option(dhcp, DHO_STATICROUTE, &len, NULL); - if (p) { - e = p + len; - while (p < e) { - if (route) { - route->next = xmalloc(sizeof(*route)); - route = route->next; - } else - routes = route = xmalloc(sizeof(*routes)); - route->next = NULL; - memcpy(&route->dest.s_addr, p, 4); - p += 4; - memcpy(&route->gate.s_addr, p, 4); - p += 4; - route->net.s_addr = route_netmask(route->dest.s_addr); - } - } - - /* Now grab our routers */ - p = get_option(dhcp, DHO_ROUTER, &len, NULL); - if (p) { - e = p + len; - while (p < e) { - if (route) { - route->next = xzalloc(sizeof(*route)); - route = route->next; - } else - routes = route = xzalloc(sizeof(*route)); - memcpy(&route->gate.s_addr, p, 4); - p += 4; - } - } - - return routes; -} - -static size_t -encode_rfc1035(const char *src, uint8_t *dst, size_t len) -{ - const char *c = src; - uint8_t *p = dst; - uint8_t *lp = p++; - - if (len == 0) - return 0; - while (c < src + len) { - if (*c == '\0') - break; - if (*c == '.') { - /* Skip the trailing . */ - if (c == src + len - 1) - break; - *lp = p - lp - 1; - if (*lp == '\0') - return p - dst; - lp = p++; - } else - *p++ = (uint8_t) *c; - c++; - } - *lp = p - lp - 1; - *p++ = '\0'; - return p - dst; -} - -ssize_t -make_message(struct dhcp_message **message, - const struct interface *iface, const struct dhcp_lease *lease, - uint32_t xid, uint8_t type, const struct options *options) -{ - struct dhcp_message *dhcp; - uint8_t *m, *lp, *p; - uint8_t *n_params = NULL; - time_t up = uptime() - iface->start_uptime; - uint32_t ul; - uint16_t sz; - const struct dhcp_opt *opt; - - dhcp = xzalloc(sizeof (*dhcp)); - m = (uint8_t *)dhcp; - p = dhcp->options; - - if ((type == DHCP_INFORM || - type == DHCP_RELEASE || - type == DHCP_REQUEST) && - !IN_LINKLOCAL(ntohl(iface->addr.s_addr))) - { - dhcp->ciaddr = iface->addr.s_addr; - /* Just incase we haven't actually configured the address yet */ - if (type == DHCP_INFORM && iface->addr.s_addr == 0) - dhcp->ciaddr = lease->addr.s_addr; - /* Zero the address if we're currently on a different subnet */ - if (type == DHCP_REQUEST && - iface->net.s_addr != lease->net.s_addr) - dhcp->ciaddr = 0; - } - - dhcp->op = DHCP_BOOTREQUEST; - dhcp->hwtype = iface->family; - switch (iface->family) { - case ARPHRD_ETHER: - case ARPHRD_IEEE802: - dhcp->hwlen = ETHER_ADDR_LEN; - memcpy(&dhcp->chaddr, &iface->hwaddr, ETHER_ADDR_LEN); - break; - case ARPHRD_IEEE1394: - case ARPHRD_INFINIBAND: - dhcp->hwlen = 0; - if (dhcp->ciaddr == 0) - dhcp->flags = htons(BROADCAST_FLAG); - break; - } - - if (up < 0 || up > (time_t)UINT16_MAX) - dhcp->secs = htons((uint16_t)UINT16_MAX); - else - dhcp->secs = htons(up); - dhcp->xid = xid; - dhcp->cookie = htonl(MAGIC_COOKIE); - - *p++ = DHO_MESSAGETYPE; - *p++ = 1; - *p++ = type; - - if (type == DHCP_REQUEST) { - *p++ = DHO_MAXMESSAGESIZE; - *p++ = 2; - sz = get_mtu(iface->name); - if (sz < MTU_MIN) { - if (set_mtu(iface->name, MTU_MIN) == 0) - sz = MTU_MIN; - } - sz = htons(sz); - memcpy(p, &sz, 2); - p += 2; - } - - if (iface->clientid) { - *p++ = DHO_CLIENTID; - memcpy(p, iface->clientid, iface->clientid[0] + 1); - p += iface->clientid[0] + 1; - } - - if (type != DHCP_DECLINE && type != DHCP_RELEASE) { - if (options->userclass[0]) { - *p++ = DHO_USERCLASS; - memcpy(p, options->userclass, options->userclass[0] + 1); - p += options->userclass[0] + 1; - } - - if (options->vendorclassid[0]) { - *p++ = DHO_VENDORCLASSID; - memcpy(p, options->vendorclassid, - options->vendorclassid[0] + 1); - p += options->vendorclassid[0] + 1; - } - } - - if (type == DHCP_DISCOVER || type == DHCP_REQUEST) { -#define PUTADDR(_type, _val) \ - { \ - *p++ = _type; \ - *p++ = 4; \ - memcpy(p, &_val.s_addr, 4); \ - p += 4; \ - } - if (lease->addr.s_addr && - lease->addr.s_addr != iface->addr.s_addr && - !IN_LINKLOCAL(ntohl(lease->addr.s_addr))) - { - PUTADDR(DHO_IPADDRESS, lease->addr); - if (lease->server.s_addr) - PUTADDR(DHO_SERVERID, lease->server); - } -#undef PUTADDR - - if (options->leasetime != 0) { - *p++ = DHO_LEASETIME; - *p++ = 4; - ul = htonl(options->leasetime); - memcpy(p, &ul, 4); - p += 4; - } - } - - if (type == DHCP_DISCOVER || - type == DHCP_INFORM || - type == DHCP_REQUEST) - { - if (options->hostname[0]) { - *p++ = DHO_HOSTNAME; - memcpy(p, options->hostname, options->hostname[0] + 1); - p += options->hostname[0] + 1; - } - if (options->fqdn != FQDN_DISABLE) { - /* IETF DHC-FQDN option (81), RFC4702 */ - *p++ = DHO_FQDN; - lp = p; - *p++ = 3; - /* - * Flags: 0000NEOS - * S: 1 => Client requests Server to update - * a RR in DNS as well as PTR - * O: 1 => Server indicates to client that - * DNS has been updated - * E: 1 => Name data is DNS format - * N: 1 => Client requests Server to not - * update DNS - */ - *p++ = (options->fqdn & 0x09) | 0x04; - *p++ = 0; /* from server for PTR RR */ - *p++ = 0; /* from server for A RR if S=1 */ - ul = encode_rfc1035(options->hostname + 1, p, - options->hostname[0]); - *lp += ul; - p += ul; - } - - /* vendor is already encoded correctly, so just add it */ - if (options->vendor[0]) { - *p++ = DHO_VENDOR; - memcpy(p, options->vendor, options->vendor[0] + 1); - p += options->vendor[0] + 1; - } - - *p++ = DHO_PARAMETERREQUESTLIST; - n_params = p; - *p++ = 0; - for (opt = dhcp_opts; opt->option; opt++) { - if (!(opt->type & REQUEST || - has_option_mask(options->requestmask, opt->option))) - continue; - switch (opt->option) { - case DHO_RENEWALTIME: /* FALLTHROUGH */ - case DHO_REBINDTIME: - if (type == DHCP_INFORM) - continue; - break; - } - *p++ = opt->option; - } - *n_params = p - n_params - 1; - } - *p++ = DHO_END; - -#ifdef BOOTP_MESSAGE_LENTH_MIN - /* Some crappy DHCP servers think they have to obey the BOOTP minimum - * message length. - * They are wrong, but we should still cater for them. */ - while (p - m < BOOTP_MESSAGE_LENTH_MIN) - *p++ = DHO_PAD; -#endif - - *message = dhcp; - return p - m; -} - -ssize_t -write_lease(const struct interface *iface, const struct dhcp_message *dhcp) -{ - int fd; - ssize_t bytes = sizeof(*dhcp); - const uint8_t *p = dhcp->options; - const uint8_t *e = p + sizeof(dhcp->options); - uint8_t l; - uint8_t o = 0; - - fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0400); -#ifdef ANDROID - if (fd == -1 && errno == EACCES) { - /* the lease file might have been created when dhcpcd was running as root */ - unlink(iface->leasefile); - fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0400); - } -#endif - if (fd == -1) - return -1; - - /* Only write as much as we need */ - while (p < e) { - o = *p; - if (o == DHO_END) { - bytes = p - (const uint8_t *)dhcp; - break; - } - p++; - if (o != DHO_PAD) { - l = *p++; - p += l; - } - } - bytes = write(fd, dhcp, bytes); - close(fd); - return bytes; -} - -struct dhcp_message * -read_lease(const struct interface *iface) -{ - int fd; - struct dhcp_message *dhcp; - ssize_t bytes; - - fd = open(iface->leasefile, O_RDONLY); - if (fd == -1) - return NULL; - dhcp = xmalloc(sizeof(*dhcp)); - memset(dhcp, 0, sizeof(*dhcp)); - bytes = read(fd, dhcp, sizeof(*dhcp)); - close(fd); - if (bytes < 0) { - free(dhcp); - dhcp = NULL; - } - return dhcp; -} - -static ssize_t -print_string(char *s, ssize_t len, int dl, const uint8_t *data) -{ - uint8_t c; - const uint8_t *e; - ssize_t bytes = 0; - ssize_t r; - - e = data + dl; - while (data < e) { - c = *data++; - if (!isascii(c) || !isprint(c)) { - if (s) { - if (len < 5) { - errno = ENOBUFS; - return -1; - } - r = snprintf(s, len, "\\%03o", c); - len -= r; - bytes += r; - s += r; - } else - bytes += 4; - continue; - } - switch (c) { - case '"': /* FALLTHROUGH */ - case '\'': /* FALLTHROUGH */ - case '$': /* FALLTHROUGH */ - case '`': /* FALLTHROUGH */ - case '\\': /* FALLTHROUGH */ - if (s) { - if (len < 3) { - errno = ENOBUFS; - return -1; - } - *s++ = '\\'; - len--; - } - bytes++; - break; - } - if (s) { - *s++ = c; - len--; - } - bytes++; - } - - /* NULL */ - if (s) - *s = '\0'; - bytes++; - return bytes; -} - -static ssize_t -print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data) -{ - const uint8_t *e, *t; - uint16_t u16; - int16_t s16; - uint32_t u32; - int32_t s32; - struct in_addr addr; - ssize_t bytes = 0; - ssize_t l; - char *tmp; - - if (type & RFC3397) { - l = decode_rfc3397(NULL, 0, dl, data); - if (l < 1) - return l; - tmp = xmalloc(l); - decode_rfc3397(tmp, l, dl, data); - l = print_string(s, len, l - 1, (uint8_t *)tmp); - free(tmp); - return l; - } - - if (type & RFC3442) - return decode_rfc3442(s, len, dl, data); - - if (type & STRING) { - /* Some DHCP servers return NULL strings */ - if (*data == '\0') - return 0; - return print_string(s, len, dl, data); - } - - if (!s) { - if (type & UINT8) - l = 3; - else if (type & UINT16) - l = 5; - else if (type & SINT16) - l = 6; - else if (type & UINT32) - l = 10; - else if (type & SINT32) - l = 11; - else if (type & IPV4) - l = 16; - else { - errno = EINVAL; - return -1; - } - return (l + 1) * dl; - } - - t = data; - e = data + dl; - while (data < e) { - if (data != t) { - *s++ = ' '; - bytes++; - len--; - } - if (type & UINT8) { - l = snprintf(s, len, "%d", *data); - data++; - } else if (type & UINT16) { - memcpy(&u16, data, sizeof(u16)); - u16 = ntohs(u16); - l = snprintf(s, len, "%d", u16); - data += sizeof(u16); - } else if (type & SINT16) { - memcpy(&s16, data, sizeof(s16)); - s16 = ntohs(s16); - l = snprintf(s, len, "%d", s16); - data += sizeof(s16); - } else if (type & UINT32) { - memcpy(&u32, data, sizeof(u32)); - u32 = ntohl(u32); - l = snprintf(s, len, "%d", u32); - data += sizeof(u32); - } else if (type & SINT32) { - memcpy(&s32, data, sizeof(s32)); - s32 = ntohl(s32); - l = snprintf(s, len, "%d", s32); - data += sizeof(s32); - } else if (type & IPV4) { - memcpy(&addr.s_addr, data, sizeof(addr.s_addr)); - l = snprintf(s, len, "%s", inet_ntoa(addr)); - data += sizeof(addr.s_addr); - } else - l = 0; - len -= l; - bytes += l; - s += l; - } - - return bytes; -} - -static void -setvar(char ***e, const char *prefix, const char *var, const char *value) -{ - size_t len = strlen(prefix) + strlen(var) + strlen(value) + 4; - - **e = xmalloc(len); - snprintf(**e, len, "%s_%s=%s", prefix, var, value); - (*e)++; -} - -ssize_t -configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp, - const struct options *options) -{ - unsigned int i; - const uint8_t *p; - int pl; - struct in_addr addr; - struct in_addr net; - struct in_addr brd; - char *val, *v; - const struct dhcp_opt *opt; - ssize_t len, e = 0; - char **ep; - char cidr[4]; - uint8_t overl = 0; - - get_option_uint8(&overl, dhcp, DHO_OPTIONSOVERLOADED); - - if (!env) { - for (opt = dhcp_opts; opt->option; opt++) { - if (!opt->var) - continue; - if (has_option_mask(options->nomask, opt->option)) - continue; - if (get_option_raw(dhcp, opt->option)) - e++; - } - if (dhcp->yiaddr) - e += 5; - if (*dhcp->bootfile && !(overl & 1)) - e++; - if (*dhcp->servername && !(overl & 2)) - e++; - return e; - } - - ep = env; - if (dhcp->yiaddr) { - /* Set some useful variables that we derive from the DHCP - * message but are not necessarily in the options */ - addr.s_addr = dhcp->yiaddr; - setvar(&ep, prefix, "ip_address", inet_ntoa(addr)); - if (get_option_addr(&net.s_addr, dhcp, DHO_SUBNETMASK) == -1) { - net.s_addr = get_netmask(addr.s_addr); - setvar(&ep, prefix, "subnet_mask", inet_ntoa(net)); - } - i = inet_ntocidr(net); - snprintf(cidr, sizeof(cidr), "%d", inet_ntocidr(net)); - setvar(&ep, prefix, "subnet_cidr", cidr); - if (get_option_addr(&brd.s_addr, dhcp, DHO_BROADCAST) == -1) { - brd.s_addr = addr.s_addr | ~net.s_addr; - setvar(&ep, prefix, "broadcast_address", inet_ntoa(net)); - } - addr.s_addr = dhcp->yiaddr & net.s_addr; - setvar(&ep, prefix, "network_number", inet_ntoa(addr)); - } - - if (*dhcp->bootfile && !(overl & 1)) - setvar(&ep, prefix, "filename", (const char *)dhcp->bootfile); - if (*dhcp->servername && !(overl & 2)) - setvar(&ep, prefix, "server_name", (const char *)dhcp->servername); - - for (opt = dhcp_opts; opt->option; opt++) { - if (!opt->var) - continue; - if (has_option_mask(options->nomask, opt->option)) - continue; - val = NULL; - p = get_option(dhcp, opt->option, &pl, NULL); - if (!p) - continue; - /* We only want the FQDN name */ - if (opt->option == DHO_FQDN) { - p += 3; - pl -= 3; - } - len = print_option(NULL, 0, opt->type, pl, p); - if (len < 0) - return -1; - e = strlen(prefix) + strlen(opt->var) + len + 4; - v = val = *ep++ = xmalloc(e); - v += snprintf(val, e, "%s_%s=", prefix, opt->var); - if (len != 0) - print_option(v, len, opt->type, pl, p); - } - - return ep - env; -} diff --git a/dhcp.h b/dhcp.h deleted file mode 100644 index e584452..0000000 --- a/dhcp.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef DHCP_H -#define DHCP_H - -#include - -#include - -#include "config.h" -#include "dhcpcd.h" -#include "net.h" - -/* Max MTU - defines dhcp option length */ -#define MTU_MAX 1500 -#define MTU_MIN 576 - -/* UDP port numbers for DHCP */ -#define DHCP_SERVER_PORT 67 -#define DHCP_CLIENT_PORT 68 - -#define MAGIC_COOKIE 0x63825363 -#define BROADCAST_FLAG 0x8000 - -/* DHCP message OP code */ -#define DHCP_BOOTREQUEST 1 -#define DHCP_BOOTREPLY 2 - -/* DHCP message type */ -#define DHCP_DISCOVER 1 -#define DHCP_OFFER 2 -#define DHCP_REQUEST 3 -#define DHCP_DECLINE 4 -#define DHCP_ACK 5 -#define DHCP_NAK 6 -#define DHCP_RELEASE 7 -#define DHCP_INFORM 8 - -/* DHCP options */ -enum DHO -{ - DHO_PAD = 0, - DHO_SUBNETMASK = 1, - DHO_ROUTER = 3, - DHO_DNSSERVER = 6, - DHO_HOSTNAME = 12, - DHO_DNSDOMAIN = 15, - DHO_MTU = 26, - DHO_BROADCAST = 28, - DHO_STATICROUTE = 33, - DHO_NISDOMAIN = 40, - DHO_NISSERVER = 41, - DHO_NTPSERVER = 42, - DHO_VENDOR = 43, - DHO_IPADDRESS = 50, - DHO_LEASETIME = 51, - DHO_OPTIONSOVERLOADED = 52, - DHO_MESSAGETYPE = 53, - DHO_SERVERID = 54, - DHO_PARAMETERREQUESTLIST = 55, - DHO_MESSAGE = 56, - DHO_MAXMESSAGESIZE = 57, - DHO_RENEWALTIME = 58, - DHO_REBINDTIME = 59, - DHO_VENDORCLASSID = 60, - DHO_CLIENTID = 61, - DHO_USERCLASS = 77, /* RFC 3004 */ - DHO_FQDN = 81, - DHO_DNSSEARCH = 119, /* RFC 3397 */ - DHO_CSR = 121, /* RFC 3442 */ - DHO_MSCSR = 249, /* MS code for RFC 3442 */ - DHO_END = 255 -}; - -/* FQDN values - lsnybble used in flags - * hsnybble to create order - * and to allow 0x00 to mean disable - */ -enum FQDN { - FQDN_DISABLE = 0x00, - FQDN_NONE = 0x18, - FQDN_PTR = 0x20, - FQDN_BOTH = 0x31 -}; - -/* Sizes for DHCP options */ -#define DHCP_CHADDR_LEN 16 -#define SERVERNAME_LEN 64 -#define BOOTFILE_LEN 128 -#define DHCP_UDP_LEN (20 + 8) -#define DHCP_BASE_LEN (4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4) -#define DHCP_RESERVE_LEN (4 + 4 + 4 + 4 + 2) -#define DHCP_FIXED_LEN (DHCP_BASE_LEN + DHCP_CHADDR_LEN + \ - + SERVERNAME_LEN + BOOTFILE_LEN) -#define DHCP_OPTION_LEN (MTU_MAX - DHCP_FIXED_LEN - DHCP_UDP_LEN \ - - DHCP_RESERVE_LEN) - -/* Some crappy DHCP servers require the BOOTP minimum length */ -#define BOOTP_MESSAGE_LENTH_MIN 300 - -struct dhcp_message { - uint8_t op; /* message type */ - uint8_t hwtype; /* hardware address type */ - uint8_t hwlen; /* hardware address length */ - uint8_t hwopcount; /* should be zero in client message */ - uint32_t xid; /* transaction id */ - uint16_t secs; /* elapsed time in sec. from boot */ - uint16_t flags; - uint32_t ciaddr; /* (previously allocated) client IP */ - uint32_t yiaddr; /* 'your' client IP address */ - uint32_t siaddr; /* should be zero in client's messages */ - uint32_t giaddr; /* should be zero in client's messages */ - uint8_t chaddr[DHCP_CHADDR_LEN]; /* client's hardware address */ - uint8_t servername[SERVERNAME_LEN]; /* server host name */ - uint8_t bootfile[BOOTFILE_LEN]; /* boot file name */ - uint32_t cookie; - uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */ -}; - -struct dhcp_lease { - struct in_addr addr; - struct in_addr net; - uint32_t leasetime; - uint32_t renewaltime; - uint32_t rebindtime; - struct in_addr server; - time_t leasedfrom; - struct timeval boundtime; - uint8_t frominfo; -}; - -#define add_option_mask(var, val) (var[val >> 3] |= 1 << (val & 7)) -#define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7))) -#define has_option_mask(var, val) (var[val >> 3] & (1 << (val & 7))) -int make_option_mask(uint8_t *, char **, int); -void print_options(void); -char *get_option_string(const struct dhcp_message *, uint8_t); -int get_option_addr(uint32_t *, const struct dhcp_message *, uint8_t); -int get_option_uint32(uint32_t *, const struct dhcp_message *, uint8_t); -int get_option_uint16(uint16_t *, const struct dhcp_message *, uint8_t); -int get_option_uint8(uint8_t *, const struct dhcp_message *, uint8_t); -struct rt *get_option_routes(const struct dhcp_message *); -ssize_t configure_env(char **, const char *, const struct dhcp_message *, - const struct options *); - -ssize_t make_message(struct dhcp_message **, - const struct interface *, const struct dhcp_lease *, - uint32_t, uint8_t, const struct options *); -int valid_dhcp_packet(unsigned char *); - -ssize_t write_lease(const struct interface *, const struct dhcp_message *); -struct dhcp_message *read_lease(const struct interface *iface); -#endif diff --git a/dhcpcd-hooks/01-test b/dhcpcd-hooks/01-test deleted file mode 100644 index 609b3a1..0000000 --- a/dhcpcd-hooks/01-test +++ /dev/null @@ -1,7 +0,0 @@ -# Just echo our DHCP options we have - -case ${reason} in -TEST) set | grep "^\(interface\|metric\|pid\|reason\|skip_hooks\)=" | sort - set | grep "^\(new_\|old_\)" | sort - ;; -esac diff --git a/dhcpcd-hooks/10-mtu b/dhcpcd-hooks/10-mtu deleted file mode 100644 index 4265b48..0000000 --- a/dhcpcd-hooks/10-mtu +++ /dev/null @@ -1,5 +0,0 @@ -# Configure the MTU for the interface - -if [ -n "${new_interface_mtu}" ]; then - ifconfig "${interface}" mtu "${new_interface_mtu}" -fi diff --git a/dhcpcd-hooks/20-dns.conf b/dhcpcd-hooks/20-dns.conf deleted file mode 100644 index a92e91d..0000000 --- a/dhcpcd-hooks/20-dns.conf +++ /dev/null @@ -1,32 +0,0 @@ -# Set net..dnsN properties that contain the -# DNS server addresses given by the DHCP server. - -set_dns_props() -{ - case "${new_domain_name_servers}" in - "") return 0;; - esac - - count=1 - for i in 1 2 3 4; do - setprop dhcp.${interface}.dns${i} "" - done - - count=1 - for dnsaddr in ${new_domain_name_servers}; do - setprop dhcp.${interface}.dns${count} ${dnsaddr} - count=$(($count + 1)) - done -} - -unset_dns_props() -{ - for i in 1 2 3 4; do - setprop dhcp.${interface}.dns${i} "" - done -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_dns_props;; -EXPIRE|FAIL|IPV4LL|RELEASE|STOP) unset_dns_props;; -esac diff --git a/dhcpcd-hooks/20-resolv.conf b/dhcpcd-hooks/20-resolv.conf deleted file mode 100644 index e757ddf..0000000 --- a/dhcpcd-hooks/20-resolv.conf +++ /dev/null @@ -1,107 +0,0 @@ -# Generate /etc/resolv.conf -# Support resolvconf(8) if available -# We can merge other dhcpcd resolv.conf files into one like resolvconf, -# but resolvconf is preferred as other applications like VPN clients -# can readily hook into it. -# Also, resolvconf can configure local nameservers such as bind -# or dnsmasq. This is important as the libc resolver isn't that powerful. - -resolv_conf_dir="${state_dir}/resolv.conf" - -build_resolv_conf() -{ - local cf="/etc/resolv.conf.${interface}" - local interfaces= header= search= srvs= servers= x= - - # Build a list of interfaces - interfaces=$(list_interfaces "${resolv_conf_dir}") - - # Build the resolv.conf - if [ -n "${interfaces}" ]; then - # Build the header - for x in ${interfaces}; do - header="${header}${header:+, }${x}" - done - - # Build the search list - search=$(cd "${resolv_conf_dir}"; \ - key_get_value "search " ${interfaces}) - [ -n "${search}" ] && search="search $(uniqify ${search})\n" - - # Build the nameserver list - srvs=$(cd "${resolv_conf_dir}"; \ - key_get_value "nameserver " ${interfaces}) - for x in $(uniqify ${srvs}); do - servers="${servers}nameserver ${x}\n" - done - fi - header="${signature_base}${header:+ ${from} }${header}" - - # Assemble resolv.conf using our head and tail files - [ -f "${cf}" ] && rm -f "${cf}" - echo "${header}" > "${cf}" - if [ -f /etc/resolv.conf.head ]; then - cat /etc/resolv.conf.head >> "${cf}" - else - echo "# /etc/resolv.conf.head can replace this line" >> "${cf}" - fi - printf "${search}${servers}" >> "${cf}" - if [ -f /etc/resolv.conf.tail ]; then - cat /etc/resolv.conf.tail >> "${cf}" - else - echo "# /etc/resolv.conf.tail can replace this line" >> "${cf}" - fi - mv -f "${cf}" /etc/resolv.conf -} - -add_resolv_conf() -{ - local x= conf="${signature}\n" - - # If we don't have any configuration, remove it - if [ -z "${new_domain_name_servers}" -a \ - -z "${new_domain_name}" -a \ - -z "${new_domain_search}" ]; then - remove_resolv_conf - return $? - fi - - if [ -n "${new_domain_search}" ]; then - conf="${conf}search ${new_domain_search}\n" - elif [ -n "${new_domain_name}" ]; then - conf="${conf}search ${new_domain_name}\n" - fi - for x in ${new_domain_name_servers}; do - conf="${conf}nameserver ${x}\n" - done - if type resolvconf >/dev/null 2>&1; then - printf "${conf}" | resolvconf -a "${interface}" - return $? - fi - - if [ -e "${resolv_conf_dir}/${interface}" ]; then - rm -f "${resolv_conf_dir}/${interface}" - fi - if [ ! -d "${resolv_conf_dir}" ]; then - mkdir -p "${resolv_conf_dir}" - fi - printf "${conf}" > "${resolv_conf_dir}/${interface}" - build_resolv_conf -} - -remove_resolv_conf() -{ - if type resolvconf >/dev/null 2>&1; then - resolvconf -d "${interface}" -f - else - if [ -e "${resolv_conf_dir}/${interface}" ]; then - rm -f "${resolv_conf_dir}/${interface}" - fi - build_resolv_conf - fi -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) add_resolv_conf;; -PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP) remove_resolv_conf;; -esac diff --git a/dhcpcd-hooks/29-lookup-hostname b/dhcpcd-hooks/29-lookup-hostname deleted file mode 100644 index 3dfade3..0000000 --- a/dhcpcd-hooks/29-lookup-hostname +++ /dev/null @@ -1,34 +0,0 @@ -# Lookup the hostname in DNS if not set - -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/\.$//' - return 0 - fi - elif type host >/dev/null 2>&1; then - h=`host ${new_ip_address}` - if [ $? = 0 ]; then - echo "${h}" \ - | sed 's/.* domain name pointer \(.*\)./\1/' - return 0 - fi - fi - return 1 -} - -set_hostname() -{ - if [ -z "${new_host_name}" -a -z "${new_fqdn_name}" ]; then - export new_host_name="$(lookup_hostname)" - fi -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;; -esac diff --git a/dhcpcd-hooks/30-hostname b/dhcpcd-hooks/30-hostname deleted file mode 100644 index b2e5fc8..0000000 --- a/dhcpcd-hooks/30-hostname +++ /dev/null @@ -1,28 +0,0 @@ -# Set the hostname from DHCP data if required - -need_hostname() -{ - case "$(hostname)" in - ""|"(none)"|localhost|localhost.localdomain) - [ -n "${new_host_name}" -o -n "${new_fqdn_name}" ];; - "${old_host_name}"|"${old_fqdn_name}") - true;; - *) - false;; - esac -} - -set_hostname() -{ - if need_hostname; then - if [ -n "${new_host_name}" ]; then - hostname "${new_host_name}" - else - hostname "${new_fqdn_name}" - fi - fi -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;; -esac diff --git a/dhcpcd-hooks/50-dhcpcd-compat b/dhcpcd-hooks/50-dhcpcd-compat deleted file mode 100644 index cba40a4..0000000 --- a/dhcpcd-hooks/50-dhcpcd-compat +++ /dev/null @@ -1,31 +0,0 @@ -# Compat enter hook shim for older dhcpcd versions - -IPADDR=${new_ip_address} -INTERFACE=${interface} -NETMASK=${new_subnet_mask} -BROADCAST=${new_broadcast_address} -NETWORK=${new_network_number} -DHCPSID=${new_dhcp_server_identifier} -GATEWAYS=${new_routers} -DNSSERVERS=${new_domain_name_servers} -DNSDOMAIN=${new_domain_name} -DNSSEARCH=${new_domain_search} -NISDOMAIN=${new_nis_domain} -NISSERVERS=${new_nis_servers} -NTPSERVERS=${new_ntp_servers} - -GATEWAY= -for x in ${new_routers}; do - GATEWAY="${GATEWAY}${GATEWAY:+,}${x}" -done -DNS= -for x in ${new_domain_name_servers}; do - DNS="${DNS}${DNS:+,}${x}" -done - -x="down" -case "${reason}" in -RENEW) x="up";; -BOUND|INFORM|REBIND|REBOOT|TEST|TIMEOUT|IPV4LL) x="new";; -esac -set -- "" "${x}" diff --git a/dhcpcd-hooks/50-ntp.conf b/dhcpcd-hooks/50-ntp.conf deleted file mode 100644 index 536f14e..0000000 --- a/dhcpcd-hooks/50-ntp.conf +++ /dev/null @@ -1,82 +0,0 @@ -# Sample dhcpcd hook script for ntp -# Like our resolv.conf hook script, we store a database of ntp.conf files -# and merge into /etc/ntp.conf - -# Detect OpenRC or BSD rc -# Distributions may want to just have their command here instead of this -if type rc-service >/dev/null 2>&1 && rc-service --exists ntpd; then - ntpd_restart_cmd="rc-service ntpd -- --ifstarted --quiet restart" -elif [ -x /etc/rc.d/ntpd ]; then - ntpd_restart_cmd="/etc/rc.d/ntpd restart" -elif [ -x /usr/local/etc/rc.d/ntpd ]; then - ntpd_restart_cmd="/usr/local/etc/rc.d/ntpd restart" -fi - -ntp_conf_dir="${state_dir}/ntp.conf" - -build_ntp_conf() -{ - local cf="/etc/ntp.conf.${interface}" - local interfaces= header= srvs= servers= x= - - # Build a list of interfaces - interfaces=$(list_interfaces "${ntp_conf_dir}") - - if [ -n "${interfaces}" ]; then - # Build the header - for x in ${interfaces}; do - header="${header}${header:+, }${x}" - done - - # Build a server list - srvs=$(cd "${ntp_conf_dir}"; - key_get_value "server " ${interfaces}) - if [ -n "${srvs}" ]; then - for x in $(uniqify ${srvs}); do - servers="${servers}server ${x}\n" - done - fi - fi - - # Merge our config into ntp.conf - [ -e "${cf}" ] && rm -f "${cf}" - remove_markers "${signature_base}" "${signature_base_end}" \ - /etc/ntp.conf > "${cf}" - if [ -n "${servers}" ]; then - echo "${signature_base}${header:+ ${from} }${header}" >> "${cf}" - printf "${search}${servers}" >> "${cf}" - echo "${signature_base_end}${header:+ ${from} }${header}" >> "${cf}" - fi - - # If we changed anything, restart ntpd - if change_file /etc/ntp.conf "${cf}"; then - [ -n "${ntpd_restart_cmd}" ] && ${ntpd_restart_cmd} - fi -} - -add_ntp_conf() -{ - local cf="${ntp_conf_dir}/${interface}" x= - - [ -e "${cf}" ] && rm "${cf}" - [ -d "${ntp_conf_dir}" ] || mkdir -p "${ntp_conf_dir}" - if [ -n "${new_ntp_servers}" ]; then - for x in ${new_ntp_servers}; do - echo "server ${x}" >> "${cf}" - done - fi - build_ntp_conf -} - -remove_ntp_conf() -{ - if [ -e "${ntp_conf_dir}/${interface}" ]; then - rm "${ntp_conf_dir}/${interface}" - fi - build_ntp_conf -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) add_ntp_conf add;; -PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP) remove_ntp_conf del;; -esac diff --git a/dhcpcd-hooks/50-yp.conf b/dhcpcd-hooks/50-yp.conf deleted file mode 100644 index a2296eb..0000000 --- a/dhcpcd-hooks/50-yp.conf +++ /dev/null @@ -1,49 +0,0 @@ -# Sample dhcpcd hook for ypbind -# This script is only suitable for the Linux version. - -ypbind_pid() -{ - [ -s /var/run/ypbind.pid ] && cat /var/run/ypbind.pid -} - -make_yp_conf() -{ - [ -z "${new_nis_domain}" -a -z "${new_nis_servers}" ] && return 0 - local cf=/etc/yp.conf."${interface}" prefix= x= pid= - rm -f "${cf}" - echo "${signature}" > "${cf}" - if [ -n "${new_nis_domain}" ]; then - domainname "${new_nis_domain}" - if [ -n "${new_nis_servers}" ]; then - prefix="domain ${new_nis_domain} server " - else - echo "domain ${new_nis_domain} broadcast" >> "${cf}" - fi - else - prefix="ypserver " - fi - for x in ${new_nis_servers}; do - echo "${prefix}${x}" >> "${cf}" - done - save_conf /etc/yp.conf - mv -f "${cf}" /etc/yp.conf - pid="$(ypbind_pid)" - if [ -n "${pid}" ]; then - kill -HUP "${pid}" - fi -} - -restore_yp_conf() -{ - [ -n "${old_nis_domain}" ] && domainname "" - restore_conf /etc/yp.conf || return 0 - local pid="$(ypbind_pid)" - if [ -n "${pid}" ]; then - kill -HUP "${pid}" - fi -} - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) make_yp_conf;; -EXPIRE|FAIL|IPV4LL|RELEASE|STOP) restore_yp_conf;; -esac diff --git a/dhcpcd-hooks/90-NetworkManager b/dhcpcd-hooks/90-NetworkManager deleted file mode 100644 index c4d69fe..0000000 --- a/dhcpcd-hooks/90-NetworkManager +++ /dev/null @@ -1,8 +0,0 @@ -# Hook for NetworkManager-0.7.0 -# NOTE: NetworkManager will override the script dhcpcd calls, so this hook -# only makes sense if NetworkManager is patched NOT to override the -# script dhcpcd would call. - -if [ -x /usr/libexec/nm-dhcp-client.action ]; then - /usr/libexec/nm-dhcp-client.action -fi diff --git a/dhcpcd-hooks/95-configured b/dhcpcd-hooks/95-configured deleted file mode 100644 index 93f1c43..0000000 --- a/dhcpcd-hooks/95-configured +++ /dev/null @@ -1,26 +0,0 @@ -# This script runs last, after all network configuration -# has completed. It sets a property to let the framework -# know that setting up the interface is complete. - -# For debugging: -setprop dhcp.${interface}.reason "${reason}" - -case "${reason}" in -BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) - setprop dhcp.${interface}.ipaddress "${new_ip_address}" - setprop dhcp.${interface}.gateway "${new_routers%% *}" - setprop dhcp.${interface}.mask "${new_subnet_mask}" - setprop dhcp.${interface}.leasetime "${new_dhcp_lease_time}" - setprop dhcp.${interface}.server "${new_dhcp_server_identifier}" - - setprop dhcp.${interface}.result "ok" - ;; - -EXPIRE|FAIL|IPV4LL|STOP) - setprop dhcp.${interface}.result "failed" - ;; - -RELEASE) - setprop dhcp.${interface}.result "released" - ;; -esac diff --git a/dhcpcd-hooks/Makefile b/dhcpcd-hooks/Makefile deleted file mode 100644 index cfb19f7..0000000 --- a/dhcpcd-hooks/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -LIBEXECDIR?= ${PREFIX}/libexec -HOOKDIR= ${LIBEXECDIR}/dhcpcd-hooks -SYSTEMSCRIPTS= 01-test 10-mtu 20-resolv.conf 30-hostname -FILES= ${SYSTEMSCRIPTS} ${HOOKSCRIPTS} -FILESDIR= ${HOOKDIR} - -all: - -MK= ../mk -include ${MK}/os.mk -include ${MK}/sys.mk -include ${MK}/files.mk -install: _filesinstall diff --git a/dhcpcd-run-hooks b/dhcpcd-run-hooks deleted file mode 100755 index db9c4f8..0000000 --- a/dhcpcd-run-hooks +++ /dev/null @@ -1,31 +0,0 @@ -#!/system/bin/sh -# dhcpcd client configuration script - -# Handy variables and functions for our hooks to use -from="from" -signature_base="# Generated by dhcpcd" -signature="${signature_base} ${from} ${interface}" -signature_base_end="# End of dhcpcd" -signature_end="${signature_base_end} ${from} ${interface}" -state_dir="/data/misc/dhcpcd" - -# We source each script into this one so that scripts run earlier can -# remove variables from the environment so later scripts don't see them. -# Thus, the user can create their dhcpcd.enter/exit-hook script to configure -# /etc/resolv.conf how they want and stop the system scripts ever updating it. -for hook in \ - /system/etc/dhcpcd/dhcpcd.enter-hook \ - /system/etc/dhcpcd/dhcpcd-hooks/* \ - /system/etc/dhcpcd/dhcpcd.exit-hook -do - for skip in ${skip_hooks}; do - case "${hook}" in - "${skip}") continue 2;; - */[0-9][0-9]"-${skip}") continue 2;; - */[0-9][0-9]"-${skip}.sh") continue 2;; - esac - done - if ls "${hook}" >/dev/null 2>&1; then - . "${hook}" - fi -done diff --git a/dhcpcd-run-hooks.8 b/dhcpcd-run-hooks.8 deleted file mode 100644 index dca5378..0000000 --- a/dhcpcd-run-hooks.8 +++ /dev/null @@ -1,113 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 14, 2008 -.Dt DHCPCD.SH 8 SMM -.Sh NAME -.Nm dhcpcd-run-hooks -.Nd DHCP client configuration script -.Sh DESCRIPTION -.Nm -is used by -.Xr dhcpcd 8 -to run any system and user defined hook scripts. -System hook scripts are found in -.Pa /system/etc/dhcpcd/dhcpcd-hooks -and the user defined hooks are -.Pa /system/etc/dhcpcd/dhcpcd.enter-hook . -and -.Pa /system/etc/dhcpcd/dhcpcd.exit-hook . -The default install supplies hook scripts for configuring -.Pa /etc/resolv.conf -and the hostname. -Your distribution may have included other hook scripts to say configure -ntp or ypbind. -A test hook is also supplied that simply echos the dhcp variables to the -console from DISCOVER message. -.Pp -Each time -.Nm -is invoked, -.Ev $interface -is set to the interface that -.Nm dhcpcd -is run on and -.Ev $reason -is to the reason why -.Nm -was invoked. -DHCP information to be configured is held in variables starting with the word -new_ and old DHCP information to be removed is held in variables starting with -the word old_. -.Nm dhcpcd -can display the full list of variables it knows how about by using the -.Fl V , -variables -argument. -.Pp -Here's a list of reasons why -.Nm -could be invoked: -.Bl -tag -width indent -.It Dv PREINIT -dhcpcd is starting up and any pre-initialisation should be done. -.It Dv INFORM -dhcpcd informed a DHCP server about it's address and obtained other -configuration details. -.It Dv BOUND -dhcpcd obtained a new lease from a DHCP server. -.It Dv RENEW -dhcpcd renewed it's lease. -.It Dv REBIND -dhcpcd has rebound to a new DHCP server. -.It Dv REBOOT -dhcpcd successfully requested a lease from a DHCP server. -.It Dv EXPIRE -dhcpcd's lease expired and it failed to obtain a new one. -.It Dv IPV4LL -dhcpcd failed to contact any DHCP servers but did obtain an IPV4LL address. -.It Dv FAIL -dhcpcd failed to contact any DHCP servers or use an old lease. -.It Dv TIMEOUT -dhcpcd failed to contact any DHCP servers but was able to use an old lease. -.It Dv TEST -dhcpcd received an OFFER from a DHCP server but will not configure the -interface. -This is primarily used to test the variables are filled correctly for the -script to process them. -.El -.Sh FILES -When -.Nm -runs, it loads -.Pa /system/etc/dhcpcd/dhcpcd.enter-hook -and any scripts found in -.Pa /system/etc/dhcpcd/dhcpcd-hooks -in a lexical order and then finally -.Pa /system/etc/dhcpcd/dhcpcd.exit-hook -.Sh SEE ALSO -.Xr dhcpcd 8 -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd-run-hooks.8.in b/dhcpcd-run-hooks.8.in deleted file mode 100644 index 72669f5..0000000 --- a/dhcpcd-run-hooks.8.in +++ /dev/null @@ -1,113 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 14, 2008 -.Dt DHCPCD.SH 8 SMM -.Sh NAME -.Nm dhcpcd-run-hooks -.Nd DHCP client configuration script -.Sh DESCRIPTION -.Nm -is used by -.Xr dhcpcd 8 -to run any system and user defined hook scripts. -System hook scripts are found in -.Pa @HOOKDIR@ -and the user defined hooks are -.Pa @SYSCONFDIR@/dhcpcd.enter-hook . -and -.Pa @SYSCONFDIR@/dhcpcd.exit-hook . -The default install supplies hook scripts for configuring -.Pa /etc/resolv.conf -and the hostname. -Your distribution may have included other hook scripts to say configure -ntp or ypbind. -A test hook is also supplied that simply echos the dhcp variables to the -console from DISCOVER message. -.Pp -Each time -.Nm -is invoked, -.Ev $interface -is set to the interface that -.Nm dhcpcd -is run on and -.Ev $reason -is to the reason why -.Nm -was invoked. -DHCP information to be configured is held in variables starting with the word -new_ and old DHCP information to be removed is held in variables starting with -the word old_. -.Nm dhcpcd -can display the full list of variables it knows how about by using the -.Fl V , -variables -argument. -.Pp -Here's a list of reasons why -.Nm -could be invoked: -.Bl -tag -width indent -.It Dv PREINIT -dhcpcd is starting up and any pre-initialisation should be done. -.It Dv INFORM -dhcpcd informed a DHCP server about it's address and obtained other -configuration details. -.It Dv BOUND -dhcpcd obtained a new lease from a DHCP server. -.It Dv RENEW -dhcpcd renewed it's lease. -.It Dv REBIND -dhcpcd has rebound to a new DHCP server. -.It Dv REBOOT -dhcpcd successfully requested a lease from a DHCP server. -.It Dv EXPIRE -dhcpcd's lease expired and it failed to obtain a new one. -.It Dv IPV4LL -dhcpcd failed to contact any DHCP servers but did obtain an IPV4LL address. -.It Dv FAIL -dhcpcd failed to contact any DHCP servers or use an old lease. -.It Dv TIMEOUT -dhcpcd failed to contact any DHCP servers but was able to use an old lease. -.It Dv TEST -dhcpcd received an OFFER from a DHCP server but will not configure the -interface. -This is primarily used to test the variables are filled correctly for the -script to process them. -.El -.Sh FILES -When -.Nm -runs, it loads -.Pa @SYSCONFDIR@/dhcpcd.enter-hook -and any scripts found in -.Pa @HOOKDIR@ -in a lexical order and then finally -.Pa @SYSCONFDIR@/dhcpcd.exit-hook -.Sh SEE ALSO -.Xr dhcpcd 8 -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd-run-hooks.in b/dhcpcd-run-hooks.in deleted file mode 100644 index 1e5d5b3..0000000 --- a/dhcpcd-run-hooks.in +++ /dev/null @@ -1,138 +0,0 @@ -#!/bin/sh -# dhcpcd client configuration script - -# Handy variables and functions for our hooks to use -from="from" -signature_base="# Generated by dhcpcd" -signature="${signature_base} ${from} ${interface}" -signature_base_end="# End of dhcpcd" -signature_end="${signature_base_end} ${from} ${interface}" -state_dir="/var/run/dhcpcd" - -# Ensure that all arguments are unique -uniqify() -{ - local result= - - while [ -n "$1" ]; do - case " ${result} " in - *" $1 "*);; - *) result="${result}${result:+ }$1";; - esac - shift - done - echo "${result}" -} - -# List interface config files in a dir -# We may wish to control the order at some point rather than just lexical -list_interfaces() -{ - local x= interfaces= - for x in "$1"/*; do - [ -e "${x}" ] || continue - interfaces="${interfaces}${interfaces:+ }${x##*/}" - done - echo "${interfaces}" -} - -# We normally use sed to extract values using a key from a list of files -# but sed may not always be available at the time. -key_get_value() -{ - local key="$1" value= x= line= - - shift - if type sed >/dev/null 2>&1; then - sed -n "s/^${key}//p" $@ - else - for x; do - while read line; do - case "${line}" in - "${key}"*) echo "${line##${key}}";; - esac - done < "${x}" - done - fi -} - -# We normally use sed to remove markers from a configuration file -# but sed may not always be available at the time. -remove_markers() -{ - local m1="$1" m2="$2" x= line= in_marker=0 - - shift; shift - if type sed >/dev/null 2>&1; then - sed "/^${m1}/,/^${m2}/d" $@ - else - for x; do - while read line; do - case "${line}" in - "${m1}"*) in_marker=1;; - "${m2}"*) in_marker=0;; - *) [ ${in_marker} = 0 ] && echo "${line}";; - esac - done < "${x}" - done - fi -} - -# Compare two files -# It different, replace first with second otherwise remove second -change_file() -{ - if type cmp >/dev/null 2>&1; then - cmp -s "$1" "$2" - elif type diff >/dev/null 2>&1; then - diff -q "$1" "$2" >/dev/null - else - # Hopefully we're only working on small text files ... - [ "$(cat "$1")" = "$(cat "$2")" ] - fi - if [ $? -eq 0 ]; then - rm -f "$2" - return 1 - fi - mv -f "$2" "$1" - return 0 -} - -# Save a config file -save_conf() -{ - if [ -f "$1" ]; then - rm -f "$1"-pre."${interface}" - mv -f "$1" "$1"-pre."${interface}" - fi -} - -# Restore a config file -restore_conf() -{ - [ -f "$1"-pre."${interface}" ] || return 1 - rm -f "$1" - mv -f "$1"-pre."${interface}" "$1" -} - - -# We source each script into this one so that scripts run earlier can -# remove variables from the environment so later scripts don't see them. -# Thus, the user can create their dhcpcd.enter/exit-hook script to configure -# /etc/resolv.conf how they want and stop the system scripts ever updating it. -for hook in \ - @SYSCONFDIR@/dhcpcd.enter-hook \ - @HOOKDIR@/* \ - @SYSCONFDIR@/dhcpcd.exit-hook -do - for skip in ${skip_hooks}; do - case "${hook}" in - "${skip}") continue 2;; - */[0-9][0-9]"-${skip}") continue 2;; - */[0-9][0-9]"-${skip}.sh") continue 2;; - esac - done - if [ -f "${hook}" ]; then - . "${hook}" - fi -done diff --git a/dhcpcd.8 b/dhcpcd.8 deleted file mode 100644 index ac6150c..0000000 --- a/dhcpcd.8 +++ /dev/null @@ -1,430 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 20, 2008 -.Dt DHCPCD 8 SMM -.Sh NAME -.Nm dhcpcd -.Nd an RFC 2131 compliant DHCP client -.Sh SYNOPSIS -.Nm -.Op Fl bdknpqABDEGKLSTV -.Op Fl c , -script Ar script -.Op Fl f , -config Ar file -.Op Fl h , -hostname Ar hostname -.Op Fl i , -vendorclassid Ar vendorclassid -.Op Fl l , -leasetime Ar seconds -.Op Fl m , -metric Ar metric -.Op Fl o , -option Ar option -.Op Fl r , -request Ar address -.Op Fl s , -inform Ar address Ns Op Ar /cidr -.Op Fl t , -timeout Ar seconds -.Op Fl u , -userclass Ar class -.Op Fl v , -vendor Ar code , Ar value -.Op Fl C , -nohook Ar hook -.Op Fl F , -fqdn Ar FQDN -.Op Fl I , -clientid Ar clientid -.Op Fl O , -nooption Ar option -.Op Fl Q , -require Ar option -.Op Fl X , -blacklist Ar address -.Ar interface -.Nm -.Fl k , -release -.Ar interface -.Nm -.Fl x , -exit -.Ar interface -.Sh DESCRIPTION -.Nm -is an implementation of the DHCP client specified in -.Li RFC 2131 . -.Nm -gets the host information -.Po -IP address, routes, etc -.Pc -from a DHCP server and configures the network -.Ar interface -of the -machine on which it is running. -.Nm -then runs the configuration script which writes DNS information to -.Xr resolvconf 8 , -if available, otherwise directly to -.Pa /etc/resolv.conf . -If the hostname is currenly blank, (null) or localhost then -.Nm -sets the hostname to the one supplied by the DHCP server. -.Nm -then daemonises and waits for the lease renewal time to lapse. -Then it attempts to renew its lease and reconfigure if the new lease changes. -.Ss Local Link configuration -If -.Nm -failed to obtain a lease, it probes for a valid IPv4LL address -.Po -aka ZeroConf, aka APIPA -.Pc . -Once obtained it restarts the process of looking for a DHCP server to get a -proper address. -.Pp -When using IPv4LL, -.Nm -nearly always succeeds and returns an exit code of 0. -In the rare case it fails, it normally means that there is a reverse ARP proxy -installed which always defeats IPv4LL probing. -To disable this behaviour, you can use the -.Fl L , -noipv4ll -option. -.Ss Hooking into DHCP events -.Nm -runs -.Pa /system/etc/dhcpcd/dhcpcd-run-hooks , -or the script specified by the -.Fl c , -script -option. -This script runs each script found in -.Pa /system/etc/dhcpcd/dhcpcd-hooks -in a lexical order. -The default installation supplies the scripts -.Pa 01-test , -.Pa 10-mtu , -.Pa 20-resolv.conf -and -.Pa 30-hostname . -You can disable each script by using the -.Fl C , -nohook -option. -See -.Xr dhcpcd-run-hooks 8 -for details on how these scripts work. -.Nm -currently ignores the exit code of the script. -.Ss Fine tuning -You can fine tune the behaviour of -.Nm -with the following options: -.Bl -tag -width indent -.It Fl b , -background -Background immediately. -This is useful for startup scripts which don't disable link messages for -carrier status. -.It Fl c , -script Ar script -Use this -.Ar script -instead of the default -.Pa /system/etc/dhcpcd/dhcpcd-run-hooks . -.It Fl d , -debug -Echo debug and informational messages to the console. -Subsequent debug options stop -.Nm -from daemonising. -.It Fl f , -config Ar file -Specify a config to load instead of -.Pa /system/etc/dhcpcd/dhcpcd.conf . -.Nm -always processes the config file before any command line options. -.It Fl h , -hostname Ar hostname -By default, -.Nm -sends the current hostname to the DHCP server so it can register in DNS. -You can use this option to specify the -.Ar hostname -sent, or an empty string to -stop any -.Ar hostname -from being sent. -.It Fl i , -vendorclassid Ar vendorclassid -Override the -.Ar vendorclassid -field sent. The default is -dhcpcd . -If not set then none is sent. -.It Fl k , -release -This causes an existing -.Nm -process running on the -.Ar interface -to release its lease, deconfigure the -.Ar interface -and then exit. -.Nm -then waits until this process has exited. -.It Fl l , -leasetime Ar seconds -Request a specific lease time in -.Ar seconds . -By default -.Nm -does not request any lease time and leaves the it in the hands of the -DHCP server. -.It Fl m , -metric Ar metric -Added routes will use the -.Ar metric -on systems where this is supported -.Po -presently only Linux -.Pc . -Route metrics allow the addition of routes to the same destination across -different interfaces, the lower the metric the more it is preferred. -.It Fl o , -option Ar option -Request the DHCP -.Ar option -variable for use in -.Pa /system/etc/dhcpcd/dhcpcd-run-hooks . -.It Fl n , -rebind -Notifies an existing -.Nm -process running on the -.Ar interface -to rebind it's lease. -.Nm -will not re-configure itself or use any other command line arguments. -.Nm -will timeout the rebind after 30 seconds at which point the lease will be -expired and -.Nm -will enter the discovery state to obtain a new lease. -Use the -.Fl t , -timeout -option to change this. -If -.Nm -is not running, then it starts up as normal. -This option used to be renew, but rebind is more accurate as we need to -broadcast the request instead of unicasting. -.It Fl p , -persistent -.Nm -normally deconfigures the -.Ar interface -and configuration when it exits. -Sometimes, this isn't desirable if for example you have root mounted over NFS. -You can use this option to stop this from happening. -.It Fl r , -request Op Ar address -.Nm -normally sends a DHCP DISCOVER to find servers to offer an address. -.Nm -then requests the address used. -You can use this option to skip the BROADCAST step and just request the -.Ar address . -The downside is if you request an -.Ar address -the DHCP server does not know about or the DHCP server is not -authorative, it will remain silent. -In this situation, we go back to the init state and DISCOVER again. -If no -.Ar address -is given then the first address currently assigned to the -.Ar interface -is used. -.It Fl s , -inform Op Ar address Ns Op Ar /cidr -Behaves like -.Fl r , -request -as above, but sends a DHCP INFORM instead of a REQUEST. -This does not get a lease as such, just notifies the DHCP server of the -.Ar address -in use. -You should also include the optional -.Ar cidr -network number in-case the address is not already configured on the interface. -.Nm -remains running and pretends it has an infinite lease. -.Nm -will not de-configure the interface when it exits. -If -.Nm -fails to contact a DHCP server then it returns a failure instead of falling -back on IPv4LL. -.It Fl t , -timeout Ar seconds -Timeout after -.Ar seconds , -instead of the default 30. -A setting of 0 -.Ar seconds -causes -.Nm -to wait forever to get a lease. -.It Fl u , -userclass Ar class -Tags the DHCP message with the userclass -.Ar class . -DHCP servers use this give members of the class DHCP options other than the -default, without having to know things like hardware address or hostname. -.It Fl v , -vendor Ar code , Ns Ar value -Add an enscapulated vendor option. -.Ar code -should be between 1 and 254 inclusive. -Examples. -.Pp -Set the vendor option 01 with an IP address. -.D1 dhcpcd \-v 01,192.168.0.2 eth0 -Set the vendor option 02 with a hex code. -.D1 dhcpcd \-v 02,01:02:03:04:05 eth0 -Do the above and set a third option with a string and not an IP address. -.D1 dhcpcd \-v 01,192.168.0.2 \-v 02,01:02:03:04:05 \-v 03,\e"192.168.0.2\e" eth0 -.It Fl x , -exit -This will signal an existing -.Nm -process running on the -.Ar interface -to deconfigure the -.Ar interface -and exit. -.Nm -then waits until this process has exited. -.It Fl D , -duid -Generate an -.Li RFC 4361 -compliant clientid. -This requires persistent storage and not all DHCP servers work with it so it's -not enabled by default. -.Nm -generates the DUID and stores in it -.Pa /system/etc/dhcpcd/dhcpcd.duid -This file should not be copied to other hosts. -.It Fl E , -lastlease -If -.Nm -cannot obtain a lease, then try to use the last lease acquired for the -interface. -If the -.Fl p, -persistent -option is not given then the lease is used if it hasn't expired. -.It Fl F , -fqdn Ar fqdn -Requests that the DHCP server updates DNS using FQDN instead of just a -hostname. -Valid values for -.Ar fqdn -are disable, none, ptr and both. -The current hostname or the hostname specified using the -.Fl h , -hostname -option must be a FQDN. -.Nm -itself never does any DNS updates. -.Nm -encodes the FQDN hostname as specified in -.Li RFC1035 . -.It Fl I , -clientid Ar clientid -Change the default clientid sent from the interface hardware address. -If the string is of the format 01:02:03 then it is encoded as hex. -If not set then none is sent. -.El -.Ss Restriciting behaviour -.Nm -will try to do as much as it can by default. -However, there are sometimes situations where you don't want the things to be -configured exactly how the the DHCP server wants. -Here are some options that deal with turning these bits off. -.Bl -tag -width indent -.It Fl q , -quiet -Quiet -.Nm -on the command line, only warnings and errors will be displayed. -The messages are still logged though. -.It Fl A , -noarp -Don't request or claim the address by ARP. -This also disables IPv4LL. -.It Fl B , -nobackground -Don't run in the background when we acquire a lease. -This is mainly useful for running under the control of another process, such -as a debugger or a network manager. -.It Fl C , -nohook Ar script -Don't run this hook script. -Matches full name, or prefixed with 2 numbers optionally ending with -.Pa .sh . -.Pp -So to stop dhcpcd from touching your DNS or MTU settings you would do:- -.D1 dhcpcd -C resolv.conf -C mtu eth0 -.It Fl G , -nogateway -Don't set any default routes. -.It Fl K , -nolink -Don't receive link messages for carrier status. -You should only have to use this with buggy device drivers or running -.Nm -through a network manager. -.It Fl L , -noipv4ll -Don't use IPv4LL (aka APIPA, aka Bonjour, aka ZeroConf). -.It Fl O , -nooption Ar option -Don't request the specified option. -If no option given, then don't request any options other than those to -configure the interface and routing. -.It Fl Q , -require Ar option -Requires the -.Ar option -to be present in all DHCP messages, otherwise the message is ignored. -.It Fl T, -test -On receipt of OFFER messages just call -.Pa /system/etc/dhcpcd/dhcpcd-run-hooks -with the reason of TEST which echo's the DHCP variables found in the message -to the console. -The interface configuration isn't touched and neither are any configuration -files. -.It Fl V, -variables -Display a list of option codes and the associated variable for use in -.Xr dhcpcd-run-hooks 8 . -.It Fl X, -blacklist Ar address -Ignores all DHCP messages which have this -.Ar address -as the server ID. -This may be expanded in future releases to ignore all packets -matching either the IP or hardware -.Ar address . -.El -.Sh NOTES -.Nm -requires a Berkley Packet Filter, or BPF device on BSD based systems and a -Linux Socket Filter, or LPF device on Linux based systems. -.Sh FILES -.Bl -ohang -.It Pa /system/etc/dhcpcd/dhcpcd.conf -Configuration file for dhcpcd. -If you always use the same options, put them here. -.It Pa /system/etc/dhcpcd/dhcpcd.duid -Text file that holds the DUID used to identify the host. -.It Pa /system/etc/dhcpcd/dhcpcd-run-hooks -Bourne shell script that is run to configure or deconfigure an interface. -.It Pa /system/etc/dhcpcd/dhcpcd-hooks -A directory containing bourne shell scripts that are run by the above script. -Each script can be disabled by using the -.Fl C , -nohook -option described above. -.It Pa /data/misc/dhcp/dhcpcd\- Ns Ar interface Ns .lease -The actual DHCP message send by the server. We use this when reading the last -lease and use the files mtime as when it was issued. -.It Pa /var/run/dhcpcd\- Ns Ar interface Ns .pid -Stores the PID of -.Nm -running on the -.Ar interface . -.El -.Sh SEE ALSO -.Xr dhcpcd.conf 5 , -.Xr dhcpcd-run-hooks 8 , -.Xr resolv.conf 5 , -.Xr resolvconf 8 , -.Sh STANDARDS -RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3361, RFC 3396, RFC 3397, -RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702. -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd.8.in b/dhcpcd.8.in deleted file mode 100644 index 6c82d3f..0000000 --- a/dhcpcd.8.in +++ /dev/null @@ -1,430 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 20, 2008 -.Dt DHCPCD 8 SMM -.Sh NAME -.Nm dhcpcd -.Nd an RFC 2131 compliant DHCP client -.Sh SYNOPSIS -.Nm -.Op Fl bdknpqABDEGKLSTV -.Op Fl c , -script Ar script -.Op Fl f , -config Ar file -.Op Fl h , -hostname Ar hostname -.Op Fl i , -vendorclassid Ar vendorclassid -.Op Fl l , -leasetime Ar seconds -.Op Fl m , -metric Ar metric -.Op Fl o , -option Ar option -.Op Fl r , -request Ar address -.Op Fl s , -inform Ar address Ns Op Ar /cidr -.Op Fl t , -timeout Ar seconds -.Op Fl u , -userclass Ar class -.Op Fl v , -vendor Ar code , Ar value -.Op Fl C , -nohook Ar hook -.Op Fl F , -fqdn Ar FQDN -.Op Fl I , -clientid Ar clientid -.Op Fl O , -nooption Ar option -.Op Fl Q , -require Ar option -.Op Fl X , -blacklist Ar address -.Ar interface -.Nm -.Fl k , -release -.Ar interface -.Nm -.Fl x , -exit -.Ar interface -.Sh DESCRIPTION -.Nm -is an implementation of the DHCP client specified in -.Li RFC 2131 . -.Nm -gets the host information -.Po -IP address, routes, etc -.Pc -from a DHCP server and configures the network -.Ar interface -of the -machine on which it is running. -.Nm -then runs the configuration script which writes DNS information to -.Xr resolvconf 8 , -if available, otherwise directly to -.Pa /etc/resolv.conf . -If the hostname is currenly blank, (null) or localhost then -.Nm -sets the hostname to the one supplied by the DHCP server. -.Nm -then daemonises and waits for the lease renewal time to lapse. -Then it attempts to renew its lease and reconfigure if the new lease changes. -.Ss Local Link configuration -If -.Nm -failed to obtain a lease, it probes for a valid IPv4LL address -.Po -aka ZeroConf, aka APIPA -.Pc . -Once obtained it restarts the process of looking for a DHCP server to get a -proper address. -.Pp -When using IPv4LL, -.Nm -nearly always succeeds and returns an exit code of 0. -In the rare case it fails, it normally means that there is a reverse ARP proxy -installed which always defeats IPv4LL probing. -To disable this behaviour, you can use the -.Fl L , -noipv4ll -option. -.Ss Hooking into DHCP events -.Nm -runs -.Pa @SCRIPT@ , -or the script specified by the -.Fl c , -script -option. -This script runs each script found in -.Pa @HOOKDIR@ -in a lexical order. -The default installation supplies the scripts -.Pa 01-test , -.Pa 10-mtu , -.Pa 20-resolv.conf -and -.Pa 30-hostname . -You can disable each script by using the -.Fl C , -nohook -option. -See -.Xr dhcpcd-run-hooks 8 -for details on how these scripts work. -.Nm -currently ignores the exit code of the script. -.Ss Fine tuning -You can fine tune the behaviour of -.Nm -with the following options: -.Bl -tag -width indent -.It Fl b , -background -Background immediately. -This is useful for startup scripts which don't disable link messages for -carrier status. -.It Fl c , -script Ar script -Use this -.Ar script -instead of the default -.Pa @SCRIPT@ . -.It Fl d , -debug -Echo debug and informational messages to the console. -Subsequent debug options stop -.Nm -from daemonising. -.It Fl f , -config Ar file -Specify a config to load instead of -.Pa @SYSCONFDIR@/dhcpcd.conf . -.Nm -always processes the config file before any command line options. -.It Fl h , -hostname Ar hostname -By default, -.Nm -sends the current hostname to the DHCP server so it can register in DNS. -You can use this option to specify the -.Ar hostname -sent, or an empty string to -stop any -.Ar hostname -from being sent. -.It Fl i , -vendorclassid Ar vendorclassid -Override the -.Ar vendorclassid -field sent. The default is -dhcpcd . -If not set then none is sent. -.It Fl k , -release -This causes an existing -.Nm -process running on the -.Ar interface -to release its lease, deconfigure the -.Ar interface -and then exit. -.Nm -then waits until this process has exited. -.It Fl l , -leasetime Ar seconds -Request a specific lease time in -.Ar seconds . -By default -.Nm -does not request any lease time and leaves the it in the hands of the -DHCP server. -.It Fl m , -metric Ar metric -Added routes will use the -.Ar metric -on systems where this is supported -.Po -presently only Linux -.Pc . -Route metrics allow the addition of routes to the same destination across -different interfaces, the lower the metric the more it is preferred. -.It Fl o , -option Ar option -Request the DHCP -.Ar option -variable for use in -.Pa @SCRIPT@ . -.It Fl n , -rebind -Notifies an existing -.Nm -process running on the -.Ar interface -to rebind it's lease. -.Nm -will not re-configure itself or use any other command line arguments. -.Nm -will timeout the rebind after 30 seconds at which point the lease will be -expired and -.Nm -will enter the discovery state to obtain a new lease. -Use the -.Fl t , -timeout -option to change this. -If -.Nm -is not running, then it starts up as normal. -This option used to be renew, but rebind is more accurate as we need to -broadcast the request instead of unicasting. -.It Fl p , -persistent -.Nm -normally deconfigures the -.Ar interface -and configuration when it exits. -Sometimes, this isn't desirable if for example you have root mounted over NFS. -You can use this option to stop this from happening. -.It Fl r , -request Op Ar address -.Nm -normally sends a DHCP DISCOVER to find servers to offer an address. -.Nm -then requests the address used. -You can use this option to skip the BROADCAST step and just request the -.Ar address . -The downside is if you request an -.Ar address -the DHCP server does not know about or the DHCP server is not -authorative, it will remain silent. -In this situation, we go back to the init state and DISCOVER again. -If no -.Ar address -is given then the first address currently assigned to the -.Ar interface -is used. -.It Fl s , -inform Op Ar address Ns Op Ar /cidr -Behaves like -.Fl r , -request -as above, but sends a DHCP INFORM instead of a REQUEST. -This does not get a lease as such, just notifies the DHCP server of the -.Ar address -in use. -You should also include the optional -.Ar cidr -network number in-case the address is not already configured on the interface. -.Nm -remains running and pretends it has an infinite lease. -.Nm -will not de-configure the interface when it exits. -If -.Nm -fails to contact a DHCP server then it returns a failure instead of falling -back on IPv4LL. -.It Fl t , -timeout Ar seconds -Timeout after -.Ar seconds , -instead of the default 30. -A setting of 0 -.Ar seconds -causes -.Nm -to wait forever to get a lease. -.It Fl u , -userclass Ar class -Tags the DHCP message with the userclass -.Ar class . -DHCP servers use this give members of the class DHCP options other than the -default, without having to know things like hardware address or hostname. -.It Fl v , -vendor Ar code , Ns Ar value -Add an enscapulated vendor option. -.Ar code -should be between 1 and 254 inclusive. -Examples. -.Pp -Set the vendor option 01 with an IP address. -.D1 dhcpcd \-v 01,192.168.0.2 eth0 -Set the vendor option 02 with a hex code. -.D1 dhcpcd \-v 02,01:02:03:04:05 eth0 -Do the above and set a third option with a string and not an IP address. -.D1 dhcpcd \-v 01,192.168.0.2 \-v 02,01:02:03:04:05 \-v 03,\e"192.168.0.2\e" eth0 -.It Fl x , -exit -This will signal an existing -.Nm -process running on the -.Ar interface -to deconfigure the -.Ar interface -and exit. -.Nm -then waits until this process has exited. -.It Fl D , -duid -Generate an -.Li RFC 4361 -compliant clientid. -This requires persistent storage and not all DHCP servers work with it so it's -not enabled by default. -.Nm -generates the DUID and stores in it -.Pa @SYSCONFDIR@/dhcpcd.duid -This file should not be copied to other hosts. -.It Fl E , -lastlease -If -.Nm -cannot obtain a lease, then try to use the last lease acquired for the -interface. -If the -.Fl p, -persistent -option is not given then the lease is used if it hasn't expired. -.It Fl F , -fqdn Ar fqdn -Requests that the DHCP server updates DNS using FQDN instead of just a -hostname. -Valid values for -.Ar fqdn -are disable, none, ptr and both. -The current hostname or the hostname specified using the -.Fl h , -hostname -option must be a FQDN. -.Nm -itself never does any DNS updates. -.Nm -encodes the FQDN hostname as specified in -.Li RFC1035 . -.It Fl I , -clientid Ar clientid -Change the default clientid sent from the interface hardware address. -If the string is of the format 01:02:03 then it is encoded as hex. -If not set then none is sent. -.El -.Ss Restriciting behaviour -.Nm -will try to do as much as it can by default. -However, there are sometimes situations where you don't want the things to be -configured exactly how the the DHCP server wants. -Here are some options that deal with turning these bits off. -.Bl -tag -width indent -.It Fl q , -quiet -Quiet -.Nm -on the command line, only warnings and errors will be displayed. -The messages are still logged though. -.It Fl A , -noarp -Don't request or claim the address by ARP. -This also disables IPv4LL. -.It Fl B , -nobackground -Don't run in the background when we acquire a lease. -This is mainly useful for running under the control of another process, such -as a debugger or a network manager. -.It Fl C , -nohook Ar script -Don't run this hook script. -Matches full name, or prefixed with 2 numbers optionally ending with -.Pa .sh . -.Pp -So to stop dhcpcd from touching your DNS or MTU settings you would do:- -.D1 dhcpcd -C resolv.conf -C mtu eth0 -.It Fl G , -nogateway -Don't set any default routes. -.It Fl K , -nolink -Don't receive link messages for carrier status. -You should only have to use this with buggy device drivers or running -.Nm -through a network manager. -.It Fl L , -noipv4ll -Don't use IPv4LL (aka APIPA, aka Bonjour, aka ZeroConf). -.It Fl O , -nooption Ar option -Don't request the specified option. -If no option given, then don't request any options other than those to -configure the interface and routing. -.It Fl Q , -require Ar option -Requires the -.Ar option -to be present in all DHCP messages, otherwise the message is ignored. -.It Fl T, -test -On receipt of OFFER messages just call -.Pa @SCRIPT@ -with the reason of TEST which echo's the DHCP variables found in the message -to the console. -The interface configuration isn't touched and neither are any configuration -files. -.It Fl V, -variables -Display a list of option codes and the associated variable for use in -.Xr dhcpcd-run-hooks 8 . -.It Fl X, -blacklist Ar address -Ignores all DHCP messages which have this -.Ar address -as the server ID. -This may be expanded in future releases to ignore all packets -matching either the IP or hardware -.Ar address . -.El -.Sh NOTES -.Nm -requires a Berkley Packet Filter, or BPF device on BSD based systems and a -Linux Socket Filter, or LPF device on Linux based systems. -.Sh FILES -.Bl -ohang -.It Pa @SYSCONFDIR@/dhcpcd.conf -Configuration file for dhcpcd. -If you always use the same options, put them here. -.It Pa @SYSCONFDIR@/dhcpcd.duid -Text file that holds the DUID used to identify the host. -.It Pa @SCRIPT@ -Bourne shell script that is run to configure or deconfigure an interface. -.It Pa @HOOKDIR@ -A directory containing bourne shell scripts that are run by the above script. -Each script can be disabled by using the -.Fl C , -nohook -option described above. -.It Pa @DBDIR@/dhcpcd\- Ns Ar interface Ns .lease -The actual DHCP message send by the server. We use this when reading the last -lease and use the files mtime as when it was issued. -.It Pa /var/run/dhcpcd\- Ns Ar interface Ns .pid -Stores the PID of -.Nm -running on the -.Ar interface . -.El -.Sh SEE ALSO -.Xr dhcpcd.conf 5 , -.Xr dhcpcd-run-hooks 8 , -.Xr resolv.conf 5 , -.Xr resolvconf 8 , -.Sh STANDARDS -RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3361, RFC 3396, RFC 3397, -RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702. -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd.c b/dhcpcd.c deleted file mode 100644 index e674bd2..0000000 --- a/dhcpcd.c +++ /dev/null @@ -1,1038 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -const char copyright[] = "Copyright (c) 2006-2008 Roy Marples"; - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "client.h" -#include "dhcpcd.h" -#include "dhcp.h" -#include "net.h" -#include "logger.h" - -#ifdef ANDROID -#include -#include -#include -#include -#endif - -/* Don't set any optional arguments here so we retain POSIX - * compatibility with getopt */ -#define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:Q:TVX:" - -static int doversion = 0; -static int dohelp = 0; -static const struct option longopts[] = { - {"background", no_argument, NULL, 'b'}, - {"script", required_argument, NULL, 'c'}, - {"debug", no_argument, NULL, 'd'}, - {"config", required_argument, NULL, 'f'}, - {"hostname", optional_argument, NULL, 'h'}, - {"vendorclassid", optional_argument, NULL, 'i'}, - {"release", no_argument, NULL, 'k'}, - {"leasetime", required_argument, NULL, 'l'}, - {"metric", required_argument, NULL, 'm'}, - {"rebind", no_argument, NULL, 'n'}, - {"option", required_argument, NULL, 'o'}, - {"persistent", no_argument, NULL, 'p'}, - {"quiet", no_argument, NULL, 'q'}, - {"request", optional_argument, NULL, 'r'}, - {"inform", optional_argument, NULL, 's'}, - {"timeout", required_argument, NULL, 't'}, - {"userclass", required_argument, NULL, 'u'}, - {"vendor", required_argument, NULL, 'v'}, - {"exit", no_argument, NULL, 'x'}, - {"noarp", no_argument, NULL, 'A'}, - {"nobackground", no_argument, NULL, 'B'}, - {"nohook", required_argument, NULL, 'C'}, - {"duid", no_argument, NULL, 'D'}, - {"lastlease", no_argument, NULL, 'E'}, - {"fqdn", optional_argument, NULL, 'F'}, - {"nogateway", no_argument, NULL, 'G'}, - {"clientid", optional_argument, NULL, 'I'}, - {"nolink", no_argument, NULL, 'K'}, - {"noipv4ll", no_argument, NULL, 'L'}, - {"nooption", optional_argument, NULL, 'O'}, - {"require", required_argument, NULL, 'Q'}, - {"test", no_argument, NULL, 'T'}, - {"variables", no_argument, NULL, 'V'}, - {"blacklist", required_argument, NULL, 'X'}, - {"help", no_argument, &dohelp, 1}, - {"version", no_argument, &doversion, 1}, -#ifdef CMDLINE_COMPAT - {"classid", optional_argument, NULL, 'i'}, - {"renew", no_argument, NULL, 'n'}, - {"nohostname", no_argument, NULL, 'H'}, - {"nomtu", no_argument, NULL, 'M'}, - {"nontp", no_argument, NULL, 'N'}, - {"nodns", no_argument, NULL, 'R'}, - {"msscr", no_argument, NULL, 'S'}, - {"nonis", no_argument, NULL, 'Y'}, -#endif - {NULL, 0, NULL, '\0'} -}; - -#ifdef CMDLINE_COMPAT -# define EXTRA_OPTS "HMNRSY" -#endif - -#ifndef EXTRA_OPTS -# define EXTRA_OPTS -#endif - -static int -atoint(const char *s) -{ - char *t; - long n; - - errno = 0; - n = strtol(s, &t, 0); - if ((errno != 0 && n == 0) || s == t || - (errno == ERANGE && (n == LONG_MAX || n == LONG_MIN))) - { - logger(LOG_ERR, "`%s' out of range", s); - return -1; - } - - return (int)n; -} - -static pid_t -read_pid(const char *pidfile) -{ - FILE *fp; - pid_t pid = 0; - - if ((fp = fopen(pidfile, "r")) == NULL) { - errno = ENOENT; - return 0; - } - - fscanf(fp, "%d", &pid); - fclose(fp); - - return pid; -} - -static void -usage(void) -{ - printf("usage: "PACKAGE" [-dknpqxADEGHKLOTV] [-c script] [-f file ] [-h hostname]\n" - " [-i classID ] [-l leasetime] [-m metric] [-o option] [-r ipaddr]\n" - " [-s ipaddr] [-t timeout] [-u userclass] [-F none|ptr|both]\n" - " [-I clientID] [-C hookscript] [-Q option] [-X ipaddr] \n"); -} - -static char * -add_environ(struct options *options, const char *value, int uniq) -{ - char **newlist; - char **lst = options->environ; - size_t i = 0, l, lv; - char *match = NULL, *p; - - match = xstrdup(value); - p = strchr(match, '='); - if (p) - *p++ = '\0'; - l = strlen(match); - - while (lst && lst[i]) { - if (match && strncmp(lst[i], match, l) == 0) { - if (uniq) { - free(lst[i]); - lst[i] = xstrdup(value); - } else { - /* Append a space and the value to it */ - l = strlen(lst[i]); - lv = strlen(p); - lst[i] = xrealloc(lst[i], l + lv + 2); - lst[i][l] = ' '; - memcpy(lst[i] + l + 1, p, lv); - lst[i][l + lv + 1] = '\0'; - } - free(match); - return lst[i]; - } - i++; - } - - newlist = xrealloc(lst, sizeof(char *) * (i + 2)); - newlist[i] = xstrdup(value); - newlist[i + 1] = NULL; - options->environ = newlist; - free(match); - return newlist[i]; -} - -#define parse_string(buf, len, arg) parse_string_hwaddr(buf, len, arg, 0) -static ssize_t -parse_string_hwaddr(char *sbuf, ssize_t slen, char *str, int clid) -{ - ssize_t l; - char *p; - int i; - char c[4]; - - /* If surrounded by quotes then it's a string */ - if (*str == '"') { - str++; - l = strlen(str); - p = str + l - 1; - if (*p == '"') - *p = '\0'; - } else { - l = hwaddr_aton(NULL, str); - if (l > 1) { - if (l > slen) { - errno = ENOBUFS; - return -1; - } - hwaddr_aton((uint8_t *)sbuf, str); - return l; - } - } - - /* Process escapes */ - l = 0; - /* If processing a string on the clientid, first byte should be - * 0 to indicate a non hardware type */ - if (clid) { - *sbuf++ = 0; - l++; - } - c[3] = '\0'; - while (*str) { - if (++l > slen) { - errno = ENOBUFS; - return -1; - } - if (*str == '\\') { - str++; - switch(*str++) { - case '\0': - break; - case 'b': - *sbuf++ = '\b'; - break; - case 'n': - *sbuf++ = '\n'; - break; - case 'r': - *sbuf++ = '\r'; - break; - case 't': - *sbuf++ = '\t'; - break; - case 'x': - /* Grab a hex code */ - c[1] = '\0'; - for (i = 0; i < 2; i++) { - if (isxdigit((unsigned char)*str) == 0) - break; - c[i] = *str++; - } - if (c[1] != '\0') { - c[2] = '\0'; - *sbuf++ = strtol(c, NULL, 16); - } else - l--; - break; - case '0': - /* Grab an octal code */ - c[2] = '\0'; - for (i = 0; i < 3; i++) { - if (*str < '0' || *str > '7') - break; - c[i] = *str++; - } - if (c[2] != '\0') { - i = strtol(c, NULL, 8); - if (i > 255) - i = 255; - *sbuf ++= i; - } else - l--; - break; - default: - *sbuf++ = *str++; - } - } else - *sbuf++ = *str++; - } - return l; -} - -static int -parse_option(int opt, char *oarg, struct options *options) -{ - int i; - char *p; - ssize_t s; - struct in_addr addr; - - switch(opt) { - case 'b': - options->options |= DHCPCD_BACKGROUND; - break; - case 'c': - strlcpy(options->script, oarg, sizeof(options->script)); - break; - case 'h': - if (oarg) - s = parse_string(options->hostname + 1, - HOSTNAME_MAX_LEN, oarg); - else - s = 0; - if (s == -1) { - logger(LOG_ERR, "hostname: %s", strerror(errno)); - return -1; - } - if (s != 0 && options->hostname[1] == '.') { - logger(LOG_ERR, "hostname cannot begin with a ."); - return -1; - } - options->hostname[0] = (uint8_t)s; - break; - case 'i': - if (oarg) - s = parse_string((char *)options->vendorclassid + 1, - VENDORCLASSID_MAX_LEN, oarg); - else - s = 0; - if (s == -1) { - logger(LOG_ERR, "vendorclassid: %s", strerror(errno)); - return -1; - } - *options->vendorclassid = (uint8_t)s; - break; - case 'l': - if (*oarg == '-') { - logger(LOG_ERR, - "leasetime must be a positive value"); - return -1; - } - errno = 0; - options->leasetime = (uint32_t)strtol(oarg, NULL, 0); - if (errno == EINVAL || errno == ERANGE) { - logger(LOG_ERR, "`%s' out of range", oarg); - return -1; - } - break; - case 'm': - options->metric = atoint(oarg); - if (options->metric < 0) { - logger(LOG_ERR, "metric must be a positive value"); - return -1; - } - break; - case 'o': - if (make_option_mask(options->requestmask, &oarg, 1) != 0) { - logger(LOG_ERR, "unknown option `%s'", oarg); - return -1; - } - break; - case 'p': - options->options |= DHCPCD_PERSISTENT; - break; - case 'q': - setloglevel(LOG_WARNING); - break; - case 's': - options->options |= DHCPCD_INFORM; - options->options |= DHCPCD_PERSISTENT; - options->options &= ~DHCPCD_ARP; - if (!oarg || *oarg == '\0') { - options->request_address.s_addr = 0; - break; - } else { - if ((p = strchr(oarg, '/'))) { - /* nullify the slash, so the -r option - * can read the address */ - *p++ = '\0'; - if (sscanf(p, "%d", &i) != 1 || - inet_cidrtoaddr(i, &options->request_netmask) != 0) - { - logger(LOG_ERR, - "`%s' is not a valid CIDR", - p); - return -1; - } - } - } - /* FALLTHROUGH */ - case 'r': - if (!(options->options & DHCPCD_INFORM)) - options->options |= DHCPCD_REQUEST; - if (oarg && !inet_aton(oarg, &options->request_address)) { - logger(LOG_ERR, "`%s' is not a valid IP address", - oarg); - return -1; - } - break; - case 't': - options->timeout = atoint(oarg); - if (options->timeout < 0) { - logger (LOG_ERR, "timeout must be a positive value"); - return -1; - } - break; - case 'u': - s = USERCLASS_MAX_LEN - options->userclass[0] - 1; - s = parse_string((char *)options->userclass + options->userclass[0] + 2, - s, oarg); - if (s == -1) { - logger(LOG_ERR, "userclass: %s", strerror(errno)); - return -1; - } - if (s != 0) { - options->userclass[options->userclass[0] + 1] = s; - options->userclass[0] += s + 1; - } - break; - case 'v': - p = strchr(oarg, ','); - if (!p || !p[1]) { - logger(LOG_ERR, "invalid vendor format"); - return -1; - } - *p = '\0'; - i = atoint(oarg); - oarg = p + 1; - if (i < 1 || i > 254) { - logger(LOG_ERR, "vendor option should be between" - " 1 and 254 inclusive"); - return -1; - } - s = VENDOR_MAX_LEN - options->vendor[0] - 2; - if (inet_aton(oarg, &addr) == 1) { - if (s < 6) { - s = -1; - errno = ENOBUFS; - } else - memcpy(options->vendor + options->vendor[0] + 3, - &addr.s_addr, sizeof(addr.s_addr)); - } else { - s = parse_string((char *)options->vendor + options->vendor[0] + 3, - s, oarg); - } - if (s == -1) { - logger(LOG_ERR, "vendor: %s", strerror(errno)); - return -1; - } - if (s != 0) { - options->vendor[options->vendor[0] + 1] = i; - options->vendor[options->vendor[0] + 2] = s; - options->vendor[0] += s + 2; - } - break; - case 'A': - options->options &= ~DHCPCD_ARP; - /* IPv4LL requires ARP */ - options->options &= ~DHCPCD_IPV4LL; - break; - case 'B': - options->options &= ~DHCPCD_DAEMONISE; - break; - case 'C': - /* Commas to spaces for shell */ - while ((p = strchr(oarg, ','))) - *p = ' '; - s = strlen("skip_hooks=") + strlen(oarg) + 1; - p = xmalloc(sizeof(char) * s); - snprintf(p, s, "skip_hooks=%s", oarg); - add_environ(options, p, 0); - free(p); - break; - case 'D': - options->options |= DHCPCD_DUID; - break; - case 'E': - options->options |= DHCPCD_LASTLEASE; - break; - case 'F': - if (!oarg) { - options->fqdn = FQDN_BOTH; - break; - } - if (strcmp(oarg, "none") == 0) - options->fqdn = FQDN_NONE; - else if (strcmp(oarg, "ptr") == 0) - options->fqdn = FQDN_PTR; - else if (strcmp(oarg, "both") == 0) - options->fqdn = FQDN_BOTH; - else if (strcmp(oarg, "disable") == 0) - options->fqdn = FQDN_DISABLE; - else { - logger(LOG_ERR, "invalid value `%s' for FQDN", - oarg); - return -1; - } - break; - case 'G': - options->options &= ~DHCPCD_GATEWAY; - break; - case 'I': - /* Strings have a type of 0 */; - options->clientid[1] = 0; - if (oarg) - s = parse_string_hwaddr((char *)options->clientid + 1, - CLIENTID_MAX_LEN, oarg, 1); - else - s = 0; - if (s == -1) { - logger(LOG_ERR, "clientid: %s", strerror(errno)); - return -1; - } - options->clientid[0] = (uint8_t)s; - if (s == 0) { - options->options &= ~DHCPCD_DUID; - options->options &= ~DHCPCD_CLIENTID; - } - break; - case 'K': - options->options &= ~DHCPCD_LINK; - break; - case 'L': - options->options &= ~DHCPCD_IPV4LL; - break; - case 'O': - if (make_option_mask(options->requestmask, &oarg, -1) != 0 || - make_option_mask(options->requiremask, &oarg, -1) != 0 || - make_option_mask(options->nomask, &oarg, 1) != 0) - { - logger(LOG_ERR, "unknown option `%s'", oarg); - return -1; - } - break; - case 'Q': - if (make_option_mask(options->requiremask, &oarg, 1) != 0 || - make_option_mask(options->requestmask, &oarg, 1) != 0) - { - logger(LOG_ERR, "unknown option `%s'", oarg); - return -1; - } - break; - case 'X': - if (!inet_aton(oarg, &addr)) { - logger(LOG_ERR, "`%s' is not a valid IP address", - oarg); - return -1; - } - options->blacklist = xrealloc(options->blacklist, - sizeof(in_addr_t) * (options->blacklist_len + 1)); - options->blacklist[options->blacklist_len] = addr.s_addr; - options->blacklist_len++; - break; - default: - return 0; - } - - return 1; -} - -static int -parse_config_line(const char *opt, char *line, struct options *options) -{ - unsigned int i; - - for (i = 0; i < sizeof(longopts) / sizeof(longopts[0]); i++) { - if (!longopts[i].name || - strcmp(longopts[i].name, opt) != 0) - continue; - - if (longopts[i].has_arg == required_argument && !line) { - fprintf(stderr, - PACKAGE ": option requires an argument -- %s\n", - opt); - return -1; - } - - return parse_option(longopts[i].val, line, options); - } - - fprintf(stderr, PACKAGE ": unknown option -- %s\n", opt); - return -1; -} - -#ifdef ANDROID -void switchUser() { - gid_t groups[] = { AID_INET, AID_SHELL }; - setgroups(sizeof(groups)/sizeof(groups[0]), groups); - - prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); - - setgid(AID_DHCP); - setuid(AID_DHCP); - - struct __user_cap_header_struct header; - struct __user_cap_data_struct cap; - header.version = _LINUX_CAPABILITY_VERSION; - header.pid = 0; - cap.effective = cap.permitted = - (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | - (1 << CAP_NET_BROADCAST) | (1 << CAP_NET_BIND_SERVICE); - cap.inheritable = 0; - capset(&header, &cap); -} -#endif /* ANDROID */ - -int -main(int argc, char **argv) -{ - struct options *options; - int opt; - int option_index = 0; - char *prefix; - pid_t pid; - int debug = 0; - int i, r; - int pid_fd = -1; - int sig = 0; - int retval = EXIT_FAILURE; - char *line, *option, *p, *buffer = NULL; - size_t len = 0; - FILE *f; - char *cf = NULL; - char *intf = NULL; - struct timespec ts; - -#ifdef ANDROID - switchUser(); -#endif - closefrom(3); - /* Saves calling fflush(stream) in the logger */ - setlinebuf(stdout); - openlog(PACKAGE, LOG_PID, LOG_LOCAL0); - setlogprefix(PACKAGE ": "); - - options = xzalloc(sizeof(*options)); - options->options |= DHCPCD_CLIENTID | DHCPCD_GATEWAY | DHCPCD_DAEMONISE; - options->options |= DHCPCD_ARP | DHCPCD_IPV4LL | DHCPCD_LINK; - options->timeout = DEFAULT_TIMEOUT; - strlcpy(options->script, SCRIPT, sizeof(options->script)); - - options->vendorclassid[0] = snprintf((char *)options->vendorclassid + 1, - VENDORCLASSID_MAX_LEN, - "%s %s", PACKAGE, VERSION); - -#ifdef CMDLINE_COMPAT - add_option_mask(options->requestmask, DHO_DNSSERVER); - add_option_mask(options->requestmask, DHO_DNSDOMAIN); - add_option_mask(options->requestmask, DHO_DNSSEARCH); - add_option_mask(options->requestmask, DHO_NISSERVER); - add_option_mask(options->requestmask, DHO_NISDOMAIN); - add_option_mask(options->requestmask, DHO_NTPSERVER); - - /* If the duid file exists, then enable duid by default - * This means we don't break existing clients that easily :) */ - if ((f = fopen(DUID, "r"))) { - options->options |= DHCPCD_DUID; - fclose(f); - } -#endif - - gethostname(options->hostname + 1, sizeof(options->hostname)); - if (strcmp(options->hostname + 1, "(none)") == 0 || - strcmp(options->hostname + 1, "localhost") == 0) - options->hostname[1] = '\0'; - *options->hostname = strlen(options->hostname + 1); - - while ((opt = getopt_long(argc, argv, OPTS EXTRA_OPTS, - longopts, &option_index)) != -1) - { - switch (opt) { - case 0: - if (longopts[option_index].flag) - break; - logger(LOG_ERR, "option `%s' should set a flag", - longopts[option_index].name); - goto abort; - case 'f': - cf = optarg; - break; - case 'V': - print_options(); - goto abort; - case '?': - usage(); - goto abort; - } - } - - if (doversion) - printf(""PACKAGE" "VERSION"\n%s\n", copyright); - - if (dohelp) - usage(); - - if (optind < argc) { - if (strlen(argv[optind]) >= IF_NAMESIZE) { - logger(LOG_ERR, - "`%s' too long for an interface name (max=%d)", - argv[optind], IF_NAMESIZE); - goto abort; - } - strlcpy(options->interface, argv[optind], - sizeof(options->interface)); - } else { - /* If only version was requested then exit now */ - if (doversion || dohelp) { - retval = 0; - goto abort; - } - - logger(LOG_ERR, "no interface specified"); - goto abort; - } - - /* Parse our options file */ - f = fopen(cf ? cf : CONFIG, "r"); - if (f) { - r = 1; - while ((get_line(&buffer, &len, f))) { - line = buffer; - while ((option = strsep(&line, " \t"))) - if (*option != '\0') - break; - if (!option || *option == '\0' || *option == '#') - continue; - /* Trim leading whitespace */ - if (line) { - while (*line != '\0' && (*line == ' ' || *line == '\t')) - line++; - } - /* Trim trailing whitespace */ - if (line && *line) { - p = line + strlen(line) - 1; - while (p != line && - (*p == ' ' || *p == '\t') && - *(p - 1) != '\\') - *p-- = '\0'; - } - if (strcmp(option, "interface") == 0) { - free(intf); - intf = xstrdup(line); - continue; - } - /* If we're in an interface block don't use these - * options unless it's for us */ - if (intf && strcmp(intf, options->interface) != 0) - continue; - r = parse_config_line(option, line, options); - if (r != 1) - break; - } - free(buffer); - free(intf); - fclose(f); - if (r == 0) - usage(); - if (r != 1) - goto abort; - } else { - if (errno != ENOENT || cf) { - logger(LOG_ERR, "fopen `%s': %s", cf ? cf : CONFIG, - strerror(errno)); - goto abort; - } - } - - optind = 0; - while ((opt = getopt_long(argc, argv, OPTS EXTRA_OPTS, - longopts, &option_index)) != -1) - { - switch (opt) { - case 'd': - debug++; - switch (debug) { - case 1: - setloglevel(LOG_DEBUG); - break; - case 2: - options->options &= ~DHCPCD_DAEMONISE; - break; - } - break; - case 'f': - break; - case 'k': - sig = SIGHUP; - break; - case 'n': - sig = SIGALRM; - break; - case 'x': - sig = SIGTERM; - break; - case 'T': - options->options |= DHCPCD_TEST | DHCPCD_PERSISTENT; - break; -#ifdef CMDLINE_COMPAT - case 'H': /* FALLTHROUGH */ - case 'M': - del_option_mask(options->requestmask, DHO_MTU); - break; - case 'N': - del_option_mask(options->requestmask, DHO_NTPSERVER); - break; - case 'R': - del_option_mask(options->requestmask, DHO_DNSSERVER); - del_option_mask(options->requestmask, DHO_DNSDOMAIN); - del_option_mask(options->requestmask, DHO_DNSSEARCH); - break; - case 'S': - add_option_mask(options->requestmask, DHO_MSCSR); - break; - case 'Y': - del_option_mask(options->requestmask, DHO_NISSERVER); - del_option_mask(options->requestmask, DHO_NISDOMAIN); - break; -#endif - default: - i = parse_option(opt, optarg, options); - if (i == 1) - break; - if (i == 0) - usage(); - goto abort; - } - } - -#ifdef THERE_IS_NO_FORK - options->options &= ~DHCPCD_DAEMONISE; -#endif - -#ifndef ANDROID - /* android runs us as user "dhcp" */ - if (geteuid()) - logger(LOG_WARNING, PACKAGE " will not work correctly unless" - " run as root"); -#endif - - if (options->options & DHCPCD_TEST) { - if (options->options & DHCPCD_REQUEST || - options->options & DHCPCD_INFORM) { - logger(LOG_ERR, - "cannot test with --inform or --request"); - goto abort; - } - - if (options->options & DHCPCD_LASTLEASE) { - logger(LOG_ERR, "cannot test with --lastlease"); - goto abort; - } - - if (sig != 0) { - logger(LOG_ERR, - "cannot test with --release or --renew"); - goto abort; - } - } - - prefix = xmalloc(sizeof(char) * (IF_NAMESIZE + 3)); - snprintf(prefix, IF_NAMESIZE, "%s: ", options->interface); - setlogprefix(prefix); - snprintf(options->pidfile, sizeof(options->pidfile), PIDFILE, - options->interface); - free(prefix); - - if (options->request_address.s_addr == 0 && - (options->options & DHCPCD_INFORM || - options->options & DHCPCD_REQUEST)) - { - errno = 0; - if (get_address(options->interface, - &options->request_address, - &options->request_netmask) != 1) - { - if (errno) - logger(LOG_ERR, "get_address: %s", - strerror(errno)); - else - logger(LOG_ERR, "no existing address"); - goto abort; - } - } - if (IN_LINKLOCAL(ntohl(options->request_address.s_addr))) { - logger(LOG_ERR, - "you are not allowed to request a link local address"); - goto abort; - } - - chdir("/"); - umask(022); - - if (sig != 0 && !(options->options & DHCPCD_DAEMONISED)) { -#ifdef ANDROID - char pidpropname[PROPERTY_KEY_MAX]; - char pidpropval[PROPERTY_VALUE_MAX]; - - i = -1; - if (snprintf(pidpropname, - sizeof(pidpropname), - "dhcp.%s.pid", options->interface) >= PROPERTY_KEY_MAX) { - goto abort; - } - property_get(pidpropname, pidpropval, NULL); - if (strlen(pidpropval) == 0) { - goto abort; - } - pid = atoi(pidpropval); -#else - i = -1; - pid = read_pid(options->pidfile); -#endif - if (pid != 0) - logger(LOG_INFO, "sending signal %d to pid %d", - sig, pid); - - if (!pid || (i = kill(pid, sig))) { - if (sig != SIGALRM) - logger(LOG_ERR, ""PACKAGE" not running"); - unlink(options->pidfile); - } - if (i == 0) { - if (sig == SIGALRM) { - retval = EXIT_SUCCESS; - goto abort; - } - /* Spin until it exits */ - logger(LOG_INFO, "waiting for pid %d to exit", pid); - ts.tv_sec = 0; - ts.tv_nsec = 100000000; /* 10th of a second */ - for(i = 0; i < 100; i++) { - nanosleep(&ts, NULL); - if (read_pid(options->pidfile) == 0) { - retval = EXIT_SUCCESS; - break; - } - } - if (retval != EXIT_SUCCESS) - logger(LOG_ERR, "pid %d failed to exit", pid); - goto abort; - } - if (sig != SIGALRM) - goto abort; - } - - if (!(options->options & DHCPCD_TEST) && - !(options->options & DHCPCD_DAEMONISED)) - { -#ifdef ANDROID - char pidpropname[PROPERTY_KEY_MAX]; - char pidpropval[PROPERTY_VALUE_MAX]; -#endif -#ifndef ANDROID - if ((pid = read_pid(options->pidfile)) > 0 && - kill(pid, 0) == 0) - { - logger(LOG_ERR, ""PACKAGE - " already running on pid %d (%s)", - pid, options->pidfile); - goto abort; - } -#endif - pid_fd = open(options->pidfile, - O_WRONLY | O_CREAT | O_NONBLOCK, 0664); - if (pid_fd == -1) { - logger(LOG_ERR, "open `%s': %s", - options->pidfile, strerror(errno)); - goto abort; - } - - /* Lock the file so that only one instance of dhcpcd runs - * on an interface */ - if (flock(pid_fd, LOCK_EX | LOCK_NB) == -1) { - logger(LOG_ERR, "flock `%s': %s", - options->pidfile, strerror(errno)); - goto abort; - } - - if (set_cloexec(pid_fd) == -1) - goto abort; -#ifdef ANDROID - if (snprintf(pidpropname, - sizeof(pidpropname), - "dhcp.%s.pid", options->interface) >= PROPERTY_KEY_MAX) { - goto abort; - } - if (snprintf(pidpropval, sizeof(pidpropval), "%d", getpid()) >= PROPERTY_VALUE_MAX) { - goto abort; - } - property_set(pidpropname, pidpropval); -#else - writepid(pid_fd, getpid()); -#endif - logger(LOG_INFO, PACKAGE " " VERSION " starting"); - } - - /* Terminate the encapsulated options */ - if (options->vendor[0]) { - options->vendor[0]++; - options->vendor[options->vendor[0]] = DHO_END; - } - - if (dhcp_run(options, &pid_fd) == 0) - retval = EXIT_SUCCESS; - -abort: - /* If we didn't daemonise then we need to punt the pidfile now */ - if (pid_fd > -1) { - close(pid_fd); - unlink(options->pidfile); - } - if (options->environ) { - len = 0; - while (options->environ[len]) - free(options->environ[len++]); - free(options->environ); - } - free(options->blacklist); - free(options); - exit(retval); - /* NOTREACHED */ -} diff --git a/dhcpcd.conf b/dhcpcd.conf deleted file mode 100644 index cce1795..0000000 --- a/dhcpcd.conf +++ /dev/null @@ -1,13 +0,0 @@ -# A sample configuration for dhcpcd. -# See dhcpcd.conf(5) for details. - -# dhcpcd-run-hooks uses these options. -option domain_name_servers, domain_name, domain_search, host_name - -# Most distros have ntp support. -option ntp_servers - -# We should behave nicely on networks and respect their MTU. -# However, a lot of buggy DHCP servers set invalid MTUs so this is not -# enabled by default. -#option interface_mtu diff --git a/dhcpcd.conf.5 b/dhcpcd.conf.5 deleted file mode 100644 index 217ecba..0000000 --- a/dhcpcd.conf.5 +++ /dev/null @@ -1,155 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 18, 2008 -.Dt DHCPCD.CONF 5 SMM -.Sh NAME -.Nm dhcpcd.conf -.Nd dhcpcd configuration file -.Sh DESCRIPTION -Although -.Nm dhcpcd -can do everything from the command line, there are cases where it's just easier -to do it once in a configuration file. -Most of the options found in -.Xr dhcpcd 8 -can be used here. -The first word on the line is the option and the rest of the line is the value. -Leading and trailing whitespace for the option and value are trimmed. -You can escape characters in the value using the \\ character. -.Pp -Blank lines and lines starting with # are ignored. -.Pp -Here's a list of available options: -.Bl -tag -width indent -.It Ic background -Background immediately. -This is useful for startup scripts which don't disable link messages for -carrier status. -.It Ic clientid Ar string -Change the default clientid sent from the interface hardware address. -If the string is of the format 01:02:03 then it is encoded as hex. -If not set then none is sent. -.It Ic duid -Generate an -.Rs -.%T "RFC 4361" -.Re -compliant clientid. -This requires persistent storage and not all DHCP servers work with it so it's -not enabled by default. -The duid generated will be held in -.Pa /system/etc/dhcpcd/dhcpcd.duid -and should not be copied to other hosts. -.It Ic hostname Ar name -Sends specified -.Ar hostname -to the DHCP server so it can be registered in DNS. If -.Ar hostname -if a FQDN (ie, contains a .) then it will be encoded as such. -.It Ic fqdn Op none | ptr | both -none disables FQDN encoding, ptr just asks the DHCP server to update the PTR -record of the host in DNS whereas both also updates the A record. -The current hostname or the hostname specified using the -.Ic hostname -option must be a FQDN. -.Nm dhcpcd -itself never does any DNS updates. -.Nm dhcpcd -encodes the FQDN hostname as specified in -.Li RFC1035 . -.It Ic interface Ar interface -Subsequent options are only parsed for this -.Ar interface . -.It Ic leasetime Ar seconds -Request a leasetime of -.Ar seconds . -.It Ic noarp -Don't send any ARP requests. -This also disables IPv4LL. -.It Ic nogateway -Don't install any default routes. -.It Ic nohook Ar script -Don't run this hook script. -Matches full name, or prefixed with 2 numbers optionally ending with -.Pa .sh . -.It Ic noipv4ll -Don't attempt to obtain an IPv4LL address if we failed to get one via DHCP. -See -.Rs -.%T "RFC 3927" -.Re -.It Ic nolink -Don't receive link messages about carrier status. -You should only set this for buggy interface drivers. -.It Ic option Ar option -Requests the -.Ar option -from the server. -It can be a variable to be used in -.Xr dhcpcd-run-hooks 8 -or the numerical value. -You can specify more options seperated by commas, spaces or more option lines. -.It Ic require Ar option -Requires the -.Ar option -to be present in all DHCP messages, otherwise the message is ignored. -It can be a variable to be used in -.Xr dhcpcd-run-hooks 8 -or the numerical value. -You can specify more options seperated by commas, spaces or more require lines. -.It Ic script Ar script -Use -.Ar script -instead of the default -.Pa /system/etc/dhcpcd/dhcpcd-run-hooks . -.It Ic timeout Ar seconds -The default timeout for waiting for a DHCP response is 30 seconds which may -be too long or too short and can be changed here. -.It Ic userclass Ar string -Tag the DHCP messages with the userclass. -You can specify more than one. -.It Ic vendor Ar code , Ns Ar value -Add an enscapulated vendor option. -.Ar code -should be between 1 and 254 inclusive. -Examples. -.Pp -Set the vendor option 01 with an IP address. -.D1 vendor 01,192.168.0.2 -Set the vendor option 02 with a hex code. -.D1 vendor 02,01:02:03:04:05 -Set the vendor option 03 with an IP address as a string. -.D1 vendor 03,\e"192.168.0.2\e" -.It Ic vendorclassid Ar string -Change the default vendorclassid sent from dhcpcd-version. -If not set then none is sent. -.El -.Sh SEE ALSO -.Xr dhcpcd-run-hooks 8 , -.Xr dhcpcd 8 -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in deleted file mode 100644 index 899aea3..0000000 --- a/dhcpcd.conf.5.in +++ /dev/null @@ -1,155 +0,0 @@ -.\" Copyright 2006-2008 Roy Marples -.\" All rights reserved -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd August 18, 2008 -.Dt DHCPCD.CONF 5 SMM -.Sh NAME -.Nm dhcpcd.conf -.Nd dhcpcd configuration file -.Sh DESCRIPTION -Although -.Nm dhcpcd -can do everything from the command line, there are cases where it's just easier -to do it once in a configuration file. -Most of the options found in -.Xr dhcpcd 8 -can be used here. -The first word on the line is the option and the rest of the line is the value. -Leading and trailing whitespace for the option and value are trimmed. -You can escape characters in the value using the \\ character. -.Pp -Blank lines and lines starting with # are ignored. -.Pp -Here's a list of available options: -.Bl -tag -width indent -.It Ic background -Background immediately. -This is useful for startup scripts which don't disable link messages for -carrier status. -.It Ic clientid Ar string -Change the default clientid sent from the interface hardware address. -If the string is of the format 01:02:03 then it is encoded as hex. -If not set then none is sent. -.It Ic duid -Generate an -.Rs -.%T "RFC 4361" -.Re -compliant clientid. -This requires persistent storage and not all DHCP servers work with it so it's -not enabled by default. -The duid generated will be held in -.Pa @SYSCONFDIR@/dhcpcd.duid -and should not be copied to other hosts. -.It Ic hostname Ar name -Sends specified -.Ar hostname -to the DHCP server so it can be registered in DNS. If -.Ar hostname -if a FQDN (ie, contains a .) then it will be encoded as such. -.It Ic fqdn Op none | ptr | both -none disables FQDN encoding, ptr just asks the DHCP server to update the PTR -record of the host in DNS whereas both also updates the A record. -The current hostname or the hostname specified using the -.Ic hostname -option must be a FQDN. -.Nm dhcpcd -itself never does any DNS updates. -.Nm dhcpcd -encodes the FQDN hostname as specified in -.Li RFC1035 . -.It Ic interface Ar interface -Subsequent options are only parsed for this -.Ar interface . -.It Ic leasetime Ar seconds -Request a leasetime of -.Ar seconds . -.It Ic noarp -Don't send any ARP requests. -This also disables IPv4LL. -.It Ic nogateway -Don't install any default routes. -.It Ic nohook Ar script -Don't run this hook script. -Matches full name, or prefixed with 2 numbers optionally ending with -.Pa .sh . -.It Ic noipv4ll -Don't attempt to obtain an IPv4LL address if we failed to get one via DHCP. -See -.Rs -.%T "RFC 3927" -.Re -.It Ic nolink -Don't receive link messages about carrier status. -You should only set this for buggy interface drivers. -.It Ic option Ar option -Requests the -.Ar option -from the server. -It can be a variable to be used in -.Xr dhcpcd-run-hooks 8 -or the numerical value. -You can specify more options seperated by commas, spaces or more option lines. -.It Ic require Ar option -Requires the -.Ar option -to be present in all DHCP messages, otherwise the message is ignored. -It can be a variable to be used in -.Xr dhcpcd-run-hooks 8 -or the numerical value. -You can specify more options seperated by commas, spaces or more require lines. -.It Ic script Ar script -Use -.Ar script -instead of the default -.Pa @SCRIPT@ . -.It Ic timeout Ar seconds -The default timeout for waiting for a DHCP response is 30 seconds which may -be too long or too short and can be changed here. -.It Ic userclass Ar string -Tag the DHCP messages with the userclass. -You can specify more than one. -.It Ic vendor Ar code , Ns Ar value -Add an enscapulated vendor option. -.Ar code -should be between 1 and 254 inclusive. -Examples. -.Pp -Set the vendor option 01 with an IP address. -.D1 vendor 01,192.168.0.2 -Set the vendor option 02 with a hex code. -.D1 vendor 02,01:02:03:04:05 -Set the vendor option 03 with an IP address as a string. -.D1 vendor 03,\e"192.168.0.2\e" -.It Ic vendorclassid Ar string -Change the default vendorclassid sent from dhcpcd-version. -If not set then none is sent. -.El -.Sh SEE ALSO -.Xr dhcpcd-run-hooks 8 , -.Xr dhcpcd 8 -.Sh AUTHORS -.An Roy Marples -.Sh BUGS -Please report them to http://bugs.marples.name diff --git a/dhcpcd.h b/dhcpcd.h deleted file mode 100644 index 1cd2b5d..0000000 --- a/dhcpcd.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef DHCPCD_H -#define DHCPCD_H - -#include -#include - -#include -#include - -#include - -#include "common.h" - -#define DEFAULT_TIMEOUT 30 -#define DEFAULT_LEASETIME 3600 /* 1 hour */ - -#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */ -#define VENDORCLASSID_MAX_LEN 48 -#define CLIENTID_MAX_LEN 48 -#define USERCLASS_MAX_LEN 255 -#define VENDOR_MAX_LEN 255 - -#define DHCPCD_ARP (1 << 0) -#define DHCPCD_DOMAIN (1 << 2) -#define DHCPCD_GATEWAY (1 << 3) -#define DHCPCD_LASTLEASE (1 << 7) -#define DHCPCD_INFORM (1 << 8) -#define DHCPCD_REQUEST (1 << 9) -#define DHCPCD_IPV4LL (1 << 10) -#define DHCPCD_DUID (1 << 11) -#define DHCPCD_PERSISTENT (1 << 12) -#define DHCPCD_DAEMONISE (1 << 14) -#define DHCPCD_DAEMONISED (1 << 15) -#define DHCPCD_TEST (1 << 16) -#define DHCPCD_FORKED (1 << 17) -#define DHCPCD_HOSTNAME (1 << 18) -#define DHCPCD_CLIENTID (1 << 19) -#define DHCPCD_LINK (1 << 20) -#define DHCPCD_BACKGROUND (1 << 21) - -struct options { - char interface[IF_NAMESIZE]; - int metric; - uint8_t requestmask[256 / 8]; - uint8_t requiremask[256 / 8]; - uint8_t nomask[256 / 8]; - uint32_t leasetime; - time_t timeout; - int options; - - struct in_addr request_address; - struct in_addr request_netmask; - - char **environ; - char script[PATH_MAX]; - char pidfile[PATH_MAX]; - - char hostname[HOSTNAME_MAX_LEN + 1]; - int fqdn; - uint8_t vendorclassid[VENDORCLASSID_MAX_LEN + 1]; - char clientid[CLIENTID_MAX_LEN + 1]; - uint8_t userclass[USERCLASS_MAX_LEN + 1]; - uint8_t vendor[VENDOR_MAX_LEN + 1]; - - size_t blacklist_len; - in_addr_t *blacklist; -}; -#endif diff --git a/if-bsd.c b/if-bsd.c deleted file mode 100644 index bbf1a95..0000000 --- a/if-bsd.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "dhcp.h" -#include "net.h" - -/* Darwin doesn't define this for some very odd reason */ -#ifndef SA_SIZE -# define SA_SIZE(sa) \ - ( (!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? \ - sizeof(long) : \ - 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) ) -#endif - -int -if_address(const char *ifname, const struct in_addr *address, - const struct in_addr *netmask, const struct in_addr *broadcast, - int action) -{ - int s; - int retval; - struct ifaliasreq ifa; - union { - struct sockaddr *sa; - struct sockaddr_in *sin; - } _s; - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return -1; - - memset(&ifa, 0, sizeof(ifa)); - strlcpy(ifa.ifra_name, ifname, sizeof(ifa.ifra_name)); - -#define ADDADDR(_var, _addr) \ - _s.sa = &_var; \ - _s.sin->sin_family = AF_INET; \ - _s.sin->sin_len = sizeof(*_s.sin); \ - memcpy(&_s.sin->sin_addr, _addr, sizeof(_s.sin->sin_addr)); - - ADDADDR(ifa.ifra_addr, address); - ADDADDR(ifa.ifra_mask, netmask); - if (action >= 0) { - ADDADDR(ifa.ifra_broadaddr, broadcast); - } -#undef ADDADDR - - if (action < 0) - retval = ioctl(s, SIOCDIFADDR, &ifa); - else - retval = ioctl(s, SIOCAIFADDR, &ifa); - close(s); - return retval; -} - -int -if_route(const char *ifname, const struct in_addr *destination, - const struct in_addr *netmask, const struct in_addr *gateway, - _unused int metric, int action) -{ - int s; - static int seq; - union sockunion { - struct sockaddr sa; - struct sockaddr_in sin; -#ifdef INET6 - struct sockaddr_in6 sin6; -#endif - struct sockaddr_dl sdl; - struct sockaddr_storage ss; - } su; - struct rtm - { - struct rt_msghdr hdr; - char buffer[sizeof(su) * 3]; - } rtm; - char *bp = rtm.buffer; - size_t l; - unsigned char *hwaddr; - size_t hwlen = 0; - int retval = 0; - - if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) - return -1; - - memset(&rtm, 0, sizeof(rtm)); - rtm.hdr.rtm_version = RTM_VERSION; - rtm.hdr.rtm_seq = ++seq; - if (action == 0) - rtm.hdr.rtm_type = RTM_CHANGE; - else if (action > 0) - rtm.hdr.rtm_type = RTM_ADD; - else - rtm.hdr.rtm_type = RTM_DELETE; - rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC; - if (netmask->s_addr == INADDR_BROADCAST) - rtm.hdr.rtm_flags |= RTF_HOST; - - /* This order is important */ - rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; - -#define ADDADDR(_addr) \ - memset (&su, 0, sizeof(su)); \ - su.sin.sin_family = AF_INET; \ - su.sin.sin_len = sizeof(su.sin); \ - memcpy (&su.sin.sin_addr, _addr, sizeof(su.sin.sin_addr)); \ - l = SA_SIZE (&(su.sa)); \ - memcpy (bp, &(su), l); \ - bp += l; - - ADDADDR(destination); - - if (gateway->s_addr == INADDR_ANY) { - /* Make us a link layer socket */ - hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN); - do_interface(ifname, hwaddr, &hwlen, NULL, 0, 0); - memset(&su, 0, sizeof(su)); - su.sdl.sdl_len = sizeof(su.sdl); - su.sdl.sdl_family = AF_LINK; - su.sdl.sdl_nlen = strlen(ifname); - memcpy(&su.sdl.sdl_data, ifname, (size_t)su.sdl.sdl_nlen); - su.sdl.sdl_alen = hwlen; - memcpy(((unsigned char *)&su.sdl.sdl_data) + su.sdl.sdl_nlen, - hwaddr, (size_t)su.sdl.sdl_alen); - - l = SA_SIZE(&(su.sa)); - memcpy(bp, &su, l); - bp += l; - free(hwaddr); - } else { - rtm.hdr.rtm_flags |= RTF_GATEWAY; - ADDADDR(gateway); - } - - ADDADDR(netmask); -#undef ADDADDR - - rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; - if (write(s, &rtm, l) == -1) - retval = -1; - close(s); - return retval; -} - -int -open_link_socket(struct interface *iface) -{ - int fd; - - fd = socket(PF_ROUTE, SOCK_RAW, 0); - if (fd == -1) - return -1; - set_cloexec(fd); - if (iface->link_fd != -1) - close(iface->link_fd); - iface->link_fd = fd; - return 0; -} - -#define BUFFER_LEN 2048 -int -link_changed(struct interface *iface) -{ - char buffer[2048], *p; - ssize_t bytes; - struct rt_msghdr *rtm; - struct if_msghdr *ifm; - int i; - - if ((i = if_nametoindex(iface->name)) == -1) - return -1; - for (;;) { - bytes = recv(iface->link_fd, buffer, BUFFER_LEN, MSG_DONTWAIT); - if (bytes == -1) { - if (errno == EAGAIN) - return 0; - if (errno == EINTR) - continue; - return -1; - } - for (p = buffer; bytes > 0; - bytes -= ((struct rt_msghdr *)p)->rtm_msglen, - p += ((struct rt_msghdr *)p)->rtm_msglen) - { - rtm = (struct rt_msghdr *)p; - if (rtm->rtm_type != RTM_IFINFO) - continue; - ifm = (struct if_msghdr *)p; - if (ifm->ifm_index != i) - continue; - - /* Link changed */ - return 1; - } - } - return 0; -} diff --git a/if-linux.c b/if-linux.c deleted file mode 100644 index 1009270..0000000 --- a/if-linux.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include /* Needed for 2.4 kernels */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* Support older kernels */ -#ifndef IFLA_WIRELESS -# define IFLA_WIRELSSS (IFLFA_MASTER + 1) -#endif - -#include "config.h" -#include "common.h" -#include "dhcp.h" -#include "net.h" - -#define BUFFERLEN 256 - -int -open_link_socket(struct interface *iface) -{ - int fd; - struct sockaddr_nl nl; - - if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) - return -1; - memset(&nl, 0, sizeof(nl)); - nl.nl_family = AF_NETLINK; - nl.nl_groups = RTMGRP_LINK; - if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) - return -1; - set_cloexec(fd); - if (iface->link_fd != -1) - close(iface->link_fd); - iface->link_fd = fd; - return 0; -} - -static int -get_netlink(int fd, int flags, - int (*callback)(struct nlmsghdr *, const char *), - const char *ifname) -{ - char *buffer = NULL; - ssize_t bytes; - struct nlmsghdr *nlm; - int r = -1; - - buffer = xzalloc(sizeof(char) * BUFFERLEN); - for (;;) { - bytes = recv(fd, buffer, BUFFERLEN, flags); - if (bytes == -1) { - if (errno == EAGAIN) { - r = 0; - goto eexit; - } - if (errno == EINTR) - continue; - goto eexit; - } - for (nlm = (struct nlmsghdr *)buffer; - NLMSG_OK(nlm, (size_t)bytes); - nlm = NLMSG_NEXT(nlm, bytes)) - { - r = callback(nlm, ifname); - if (r != 0) - goto eexit; - } - } - -eexit: - free(buffer); - return r; -} - -static int -err_netlink(struct nlmsghdr *nlm, _unused const char *ifname) -{ - struct nlmsgerr *err; - int l; - - if (nlm->nlmsg_type != NLMSG_ERROR) - return 0; - l = nlm->nlmsg_len - sizeof(*nlm); - if ((size_t)l < sizeof(*err)) { - errno = EBADMSG; - return -1; - } - err = (struct nlmsgerr *)NLMSG_DATA(nlm); - if (err->error == 0) - return l; - errno = -err->error; - return -1; -} - -static int -link_netlink(struct nlmsghdr *nlm, const char *ifname) -{ - int len; - struct rtattr *rta; - struct ifinfomsg *ifi; - char ifn[IF_NAMESIZE + 1]; - - if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK) - return 0; - len = nlm->nlmsg_len - sizeof(*nlm); - if ((size_t)len < sizeof(*ifi)) { - errno = EBADMSG; - return -1; - } - ifi = NLMSG_DATA(nlm); - if (ifi->ifi_flags & IFF_LOOPBACK) - return 0; - rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi))); - len = NLMSG_PAYLOAD(nlm, sizeof(*ifi)); - *ifn = '\0'; - while (RTA_OK(rta, len)) { - switch (rta->rta_type) { - case IFLA_WIRELESS: - /* Ignore wireless messages */ - if (nlm->nlmsg_type == RTM_NEWLINK && - ifi->ifi_change == 0) - return 0; - break; - case IFLA_IFNAME: - strlcpy(ifn, RTA_DATA(rta), sizeof(ifn)); - break; - } - rta = RTA_NEXT(rta, len); - } - - if (strncmp(ifname, ifn, sizeof(ifn)) == 0) - return 1; - return 0; -} - -int -link_changed(struct interface *iface) -{ - return get_netlink(iface->link_fd, MSG_DONTWAIT, - &link_netlink, iface->name); -} - -static int -send_netlink(struct nlmsghdr *hdr) -{ - int fd, r; - struct sockaddr_nl nl; - struct iovec iov; - struct msghdr msg; - static unsigned int seq; - - if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) - return -1; - memset(&nl, 0, sizeof(nl)); - nl.nl_family = AF_NETLINK; - if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) { - close(fd); - return -1; - } - memset(&iov, 0, sizeof(iov)); - iov.iov_base = hdr; - iov.iov_len = hdr->nlmsg_len; - memset(&msg, 0, sizeof(msg)); - msg.msg_name = &nl; - msg.msg_namelen = sizeof(nl); - msg.msg_iov = &iov; - msg.msg_iovlen = 1; - /* Request a reply */ - hdr->nlmsg_flags |= NLM_F_ACK; - hdr->nlmsg_seq = ++seq; - - if (sendmsg(fd, &msg, 0) != -1) - r = get_netlink(fd, 0, &err_netlink, NULL); - else - r = -1; - close(fd); - return r; -} - -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len))) - -static int -add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, - const void *data, int alen) -{ - int len = RTA_LENGTH(alen); - struct rtattr *rta; - - if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { - errno = ENOBUFS; - return -1; - } - - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - - return 0; -} - -static int -add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data) -{ - int len = RTA_LENGTH(sizeof(data)); - struct rtattr *rta; - - if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) { - errno = ENOBUFS; - return -1; - } - - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), &data, sizeof(data)); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; - - return 0; -} - -struct nlma -{ - struct nlmsghdr hdr; - struct ifaddrmsg ifa; - char buffer[64]; -}; - -struct nlmr -{ - struct nlmsghdr hdr; - struct rtmsg rt; - char buffer[256]; -}; - -int -if_address(const char *ifname, - const struct in_addr *address, const struct in_addr *netmask, - const struct in_addr *broadcast, int action) -{ - struct nlma *nlm; - int retval = 0; - - nlm = xzalloc(sizeof(*nlm)); - nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - nlm->hdr.nlmsg_flags = NLM_F_REQUEST; - if (action >= 0) { - nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; - nlm->hdr.nlmsg_type = RTM_NEWADDR; - } else - nlm->hdr.nlmsg_type = RTM_DELADDR; - if (!(nlm->ifa.ifa_index = if_nametoindex(ifname))) { - free(nlm); - errno = ENODEV; - return -1; - } - nlm->ifa.ifa_family = AF_INET; - nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask); - /* This creates the aliased interface */ - add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL, - ifname, strlen(ifname) + 1); - add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL, - &address->s_addr, sizeof(address->s_addr)); - if (action >= 0) - add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST, - &broadcast->s_addr, sizeof(broadcast->s_addr)); - - if (send_netlink(&nlm->hdr) == -1) - retval = -1; - free(nlm); - return retval; -} - -int -if_route(const char *ifname, - const struct in_addr *destination, const struct in_addr *netmask, - const struct in_addr *gateway, int metric, int action) -{ - struct nlmr *nlm; - unsigned int ifindex; - int retval = 0; - - - if (!(ifindex = if_nametoindex(ifname))) { - errno = ENODEV; - return -1; - } - - nlm = xzalloc(sizeof(*nlm)); - nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); - nlm->hdr.nlmsg_type = RTM_NEWROUTE; - if (action == 0) - nlm->hdr.nlmsg_flags = NLM_F_REPLACE; - else if (action > 0) - /* - * ers@google: - * commented out NLM_F_EXCL here and below. We - * sometimes keep one interface up while we are - * configuring the other one, and this flag - * causes route addition to fail. - */ - nlm->hdr.nlmsg_flags = NLM_F_CREATE /* | NLM_F_EXCL */; - else - nlm->hdr.nlmsg_type = RTM_DELROUTE; - nlm->hdr.nlmsg_flags |= NLM_F_REQUEST; - nlm->rt.rtm_family = AF_INET; - nlm->rt.rtm_table = RT_TABLE_MAIN; - - if (action < 0) - nlm->rt.rtm_scope = RT_SCOPE_NOWHERE; - else { - nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/; - nlm->rt.rtm_protocol = RTPROT_BOOT; - if (gateway->s_addr == INADDR_ANY) - nlm->rt.rtm_scope = RT_SCOPE_LINK; - else - nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE; - nlm->rt.rtm_type = RTN_UNICAST; - } - - nlm->rt.rtm_dst_len = inet_ntocidr(*netmask); - add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST, - &destination->s_addr, sizeof(destination->s_addr)); - add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY, - &gateway->s_addr, sizeof(gateway->s_addr)); - - add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex); - add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, metric); - - if (send_netlink(&nlm->hdr) == -1) - retval = -1; - free(nlm); - return retval; -} diff --git a/logger.c b/logger.c deleted file mode 100644 index 15c6cf7..0000000 --- a/logger.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include "common.h" -#include "logger.h" - -static int loglevel = LOG_INFO; -static char logprefix[12] = {0}; - -void -setloglevel(int level) -{ - loglevel = level; -} - -void -setlogprefix(const char *prefix) -{ - strlcpy(logprefix, prefix, sizeof(logprefix)); -} - -void -logger(int level, const char *fmt, ...) -{ - va_list p, p2; - FILE *f = stderr; - size_t len, fmt2len; - char *fmt2, *pf; - - va_start(p, fmt); - va_copy(p2, p); - - if (level <= LOG_ERR || level <= loglevel) { - fprintf(f, "%s", logprefix); - vfprintf(f, fmt, p); - fputc('\n', f); - } - - if (level < LOG_DEBUG || level <= loglevel) { - len = strlen(logprefix); - fmt2len = strlen(fmt) + len + 1; - fmt2 = pf = malloc(sizeof(char) * fmt2len); - if (fmt2) { - strlcpy(pf, logprefix, fmt2len); - pf += len; - strlcpy(pf, fmt, fmt2len - len); - vsyslog(level, fmt2, p2); - free(fmt2); - } else { - vsyslog(level, fmt, p2); - syslog(LOG_ERR, "logger: memory exhausted"); - exit(EXIT_FAILURE); - } - } - - va_end(p2); - va_end(p); -} diff --git a/logger.h b/logger.h deleted file mode 100644 index 8ac76b6..0000000 --- a/logger.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef LOGGER_H -#define LOGGER_H - -#if defined(__GNUC__) -# define _PRINTF_LIKE(_one, _two) __attribute__ ((__format__ (__printf__, _one, _two))) -#else -# define _PRINTF_LIKE(_one, _two) -#endif - -#include - -void setloglevel(int); -void setlogprefix(const char *); -void logger(int, const char *, ...) _PRINTF_LIKE (2, 3); - -#endif diff --git a/lpf.c b/lpf.c deleted file mode 100644 index ae5dd03..0000000 --- a/lpf.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#ifdef __linux__ -# include /* needed for 2.4 kernels for the below header */ -# include -# include -# define bpf_insn sock_filter -# define BPF_SKIPTYPE -# define BPF_ETHCOOK -ETH_HLEN -# define BPF_WHOLEPACKET 0x0fffffff /* work around buggy LPF filters */ -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "dhcp.h" -#include "net.h" -#include "bpf-filter.h" - -/* Broadcast address for IPoIB */ -static const uint8_t ipv4_bcast_addr[] = { - 0x00, 0xff, 0xff, 0xff, - 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff -}; - -int -open_socket(struct interface *iface, int protocol) -{ - int s; - union sockunion { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_ll sll; - struct sockaddr_storage ss; - } su; - struct sock_fprog pf; - int *fd; - - if ((s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1) - return -1; - - memset(&su, 0, sizeof(su)); - su.sll.sll_family = PF_PACKET; - su.sll.sll_protocol = htons(protocol); - if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) { - errno = ENOENT; - goto eexit; - } - /* Install the DHCP filter */ - memset(&pf, 0, sizeof(pf)); - if (protocol == ETHERTYPE_ARP) { - pf.filter = UNCONST(arp_bpf_filter); - pf.len = arp_bpf_filter_len; - } else { - pf.filter = UNCONST(dhcp_bpf_filter); - pf.len = dhcp_bpf_filter_len; - } - if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0) - goto eexit; - if (set_cloexec(s) == -1) - goto eexit; - if (set_nonblock(s) == -1) - goto eexit; - if (bind(s, &su.sa, sizeof(su)) == -1) - goto eexit; - if (protocol == ETHERTYPE_ARP) - fd = &iface->arp_fd; - else - fd = &iface->raw_fd; - if (*fd != -1) - close(*fd); - *fd = s; - return s; - -eexit: - close(s); - return -1; -} - -ssize_t -send_raw_packet(const struct interface *iface, int protocol, - const void *data, ssize_t len) -{ - union sockunion { - struct sockaddr sa; - struct sockaddr_ll sll; - struct sockaddr_storage ss; - } su; - int fd; - - memset(&su, 0, sizeof(su)); - su.sll.sll_family = AF_PACKET; - su.sll.sll_protocol = htons(protocol); - if (!(su.sll.sll_ifindex = if_nametoindex(iface->name))) { - errno = ENOENT; - return -1; - } - su.sll.sll_hatype = htons(iface->family); - su.sll.sll_halen = iface->hwlen; - if (iface->family == ARPHRD_INFINIBAND) - memcpy(&su.sll.sll_addr, - &ipv4_bcast_addr, sizeof(ipv4_bcast_addr)); - else - memset(&su.sll.sll_addr, 0xff, iface->hwlen); - if (protocol == ETHERTYPE_ARP) - fd = iface->arp_fd; - else - fd = iface->raw_fd; - - return sendto(fd, data, len, 0, &su.sa, sizeof(su)); -} - -ssize_t -get_raw_packet(struct interface *iface, int protocol, void *data, ssize_t len) -{ - ssize_t bytes; - int fd = -1; - - if (protocol == ETHERTYPE_ARP) - fd = iface->arp_fd; - else - fd = iface->raw_fd; - bytes = read(fd, data, len); - if (bytes == -1) - return errno == EAGAIN ? 0 : -1; - return bytes; -} diff --git a/mk/cc.mk b/mk/cc.mk deleted file mode 100644 index fcf0535..0000000 --- a/mk/cc.mk +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright 2008 Roy Marples - -# Setup some good default CFLAGS -CFLAGS?= -Os - -# Default to using the C99 standard -CSTD?= c99 -_CSTD_SH= if test -n "${CSTD}"; then echo "-std=${CSTD}"; else echo ""; fi -_CSTD!= ${_CSTD_SH} -CFLAGS+= ${_CSTD}$(shell ${_CSTD_SH}) - -# Try and use some good cc flags if we're building from git -_CCFLAGS= -pedantic -Wall -Wunused -Wimplicit -Wshadow -Wformat=2 \ - -Wmissing-declarations -Wno-missing-prototypes -Wwrite-strings \ - -Wbad-function-cast -Wnested-externs -Wcomment -Winline \ - -Wchar-subscripts -Wcast-align -Wno-format-nonliteral \ - -Wdeclaration-after-statement -Wsequence-point -Wextra -_CC_FLAGS_SH= if ! test -d .git; then echo ""; else for f in ${_CCFLAGS}; do \ - if ${CC} $$f -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \ - then printf "%s" "$$f "; fi \ - done; fi -_CC_FLAGS!= ${_CC_FLAGS_SH} -CFLAGS+= ${_CC_FLAGS}$(shell ${_CC_FLAGS_SH}) - -_GGDB_SH= if test "${DEBUG}" = "yes"; then echo "-ggdb -DDEBUG"; else echo ""; fi -_GGDB!= ${_GGDB_SH} -GGDB= ${_GGDB}$(shell ${_GGDB_SH}) -CFLAGS+= ${GGDB} diff --git a/mk/depend.mk b/mk/depend.mk deleted file mode 100644 index a4d717a..0000000 --- a/mk/depend.mk +++ /dev/null @@ -1,11 +0,0 @@ -# This only works for make implementations that always include a .depend if -# it exists. Only GNU make does not do this. - -# Copyright 2008 Roy Marples - -CLEANFILES+= .depend - -.depend: ${SRCS} - ${CC} ${CFLAGS} -MM ${SRCS} > .depend - -depend: .depend diff --git a/mk/dist.mk b/mk/dist.mk deleted file mode 100644 index 3d9385b..0000000 --- a/mk/dist.mk +++ /dev/null @@ -1,31 +0,0 @@ -# rules to make a distribution tarball from a git repo -# Copyright 2008 Roy Marples - -GITREF?= HEAD -DISTPREFIX?= ${PROG}-${VERSION} -DISTFILE?= ${DISTPREFIX}.tar.bz2 - -CLEANFILES+= *.tar.bz2 - -_VERSION_SH= sed -n 's/\#define VERSION[[:space:]]*"\(.*\)".*/\1/p' config.h -_VERSION!= ${_VERSION_SH} -VERSION= ${_VERSION}$(shell ${_VERSION_SH}) - -_SNAP_SH= date -u +%Y%m%d%H%M -_SNAP!= ${_SNAP_SH} -SNAP= ${_SNAP}$(shell ${_SNAP_SH}) -SNAPDIR= ${DISTPREFIX}-${SNAP} -SNAPFILE= ${SNAPDIR}.tar.bz2 - -dist: - git archive --prefix=${DISTPREFIX}/ ${GITREF} | bzip2 > ${DISTFILE} - -snapshot: - mkdir /tmp/${SNAPDIR} - cp -RPp * /tmp/${SNAPDIR} - (cd /tmp/${SNAPDIR}; make clean) - tar -cvjpf ${SNAPFILE} -C /tmp ${SNAPDIR} - rm -rf /tmp/${SNAPDIR} - ls -l ${SNAPFILE} - -snap: snapshot diff --git a/mk/files.mk b/mk/files.mk deleted file mode 100644 index 0682b03..0000000 --- a/mk/files.mk +++ /dev/null @@ -1,9 +0,0 @@ -# Quick and dirty files -# Copyright 2008 Roy Marples - -FILESDIR?= ${BINDIR} -FILESMODE?= ${NONBINMODE} - -_filesinstall: - ${INSTALL} -d ${DESTDIR}${FILESDIR} - ${INSTALL} -m ${FILESMODE} ${FILES} ${DESTDIR}${FILESDIR} diff --git a/mk/man.mk b/mk/man.mk deleted file mode 100644 index f1570bb..0000000 --- a/mk/man.mk +++ /dev/null @@ -1,25 +0,0 @@ -# rules to install manpages -# Copyright 2008 Roy Marples - -_MANPREFIX_SH= if [ -n "${PREFIX}" ]; then echo "${PREFIX}"; else echo "/usr/share"; fi -_MANPREFIX!= ${_MANPREFIX_SH} -MANPREFIX?= ${_MANPREFIX}$(shell ${_MANPREFIX_SH}) - -MANDIR?= ${MANPREFIX}/man/man -MANMODE?= 0444 - -_MAN5_SH= for man in ${MAN}; do case $$man in *.5) echo $$man;; esac; done -_MAN5!= ${_MAN5_SH} -MAN5= ${_MAN5}$(shell ${_MAN5_SH}) - -_MAN8_SH= for man in ${MAN}; do case $$man in *.8) echo $$man;; esac; done -_MAN8!= ${_MAN8_SH} -MAN8= ${_MAN8}$(shell ${_MAN8_SH}) - -_man: ${MAN} - -_maninstall: _man - ${INSTALL} -d ${DESTDIR}${MANDIR}5 - ${INSTALL} -m ${MANMODE} ${MAN5} ${DESTDIR}${MANDIR}5 - ${INSTALL} -d ${DESTDIR}${MANDIR}8 - ${INSTALL} -m ${MANMODE} ${MAN8} ${DESTDIR}${MANDIR}8 diff --git a/mk/os-BSD.mk b/mk/os-BSD.mk deleted file mode 100644 index f9d3397..0000000 --- a/mk/os-BSD.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Setup OS specific variables -# Copyright 2008 Roy Marples - -SRC_PF= bpf.c -SRC_IF= if-bsd.c diff --git a/mk/os-Darwin.mk b/mk/os-Darwin.mk deleted file mode 100644 index f2c3104..0000000 --- a/mk/os-Darwin.mk +++ /dev/null @@ -1,5 +0,0 @@ -# Setup OS specific variables -# Copyright 2008 Roy Marples - -include ${MK}/os-BSD.mk -LINK_RPATH= --rpath diff --git a/mk/os-Linux.mk b/mk/os-Linux.mk deleted file mode 100644 index 2d316b1..0000000 --- a/mk/os-Linux.mk +++ /dev/null @@ -1,8 +0,0 @@ -# Setup OS specific variables -# Copyright 2008 Roy Marples - -SRC_PF= lpf.c -SRC_IF= if-linux.c - -CPPFLAGS+= -D_BSD_SOURCE -D_XOPEN_SOURCE=600 -LIBRT= -lrt diff --git a/mk/os.mk b/mk/os.mk deleted file mode 100644 index f3426e4..0000000 --- a/mk/os.mk +++ /dev/null @@ -1,7 +0,0 @@ -# Setup OS specific variables -# Copyright 2008 Roy Marples - -_OS_SH= case `uname -s` in Linux) echo "Linux";; Darwin) echo "Darwin";; *) echo "BSD";; esac -_OS!= ${_OS_SH} -OS= ${_OS}$(shell ${_OS_SH}) -include ${MK}/os-${OS}.mk diff --git a/mk/prog.mk b/mk/prog.mk deleted file mode 100644 index d970b2d..0000000 --- a/mk/prog.mk +++ /dev/null @@ -1,68 +0,0 @@ -# rules to build a program -# based on FreeBSD's bsd.prog.mk - -# Copyright 2008 Roy Marples - -include ${MK}/cc.mk - -OBJS+= ${SRCS:.c=.o} - -# If building for /, ensure we use the libc in / if different from -# the default one in /usr/lib -LINK_RPATH?= -Wl,-rpath -_RPATH_SH= if test "${PREFIX}" = "" -o "${PREIX}" = "/"; then \ - echo "${LINK_RPATH}=${PREFIX}/${LIBNAME}"; \ - else \ - echo ""; \ - fi -_RPATH!= ${_RPATH_SH} -LDFLAGS+= ${_RPATH}$(shell ${_RPATH_SH}) - -# If building for /, ensure we use the linker in /libexec if different from -# the default one in /usr/libexec -_DYNLINK_SH= if test "${PREFIX}" = "" -o "${PREFIX}" = "/" && test -e /libexec/ld.elf_so; then \ - echo "-Wl,-dynamic-linker=/libexec/ld.elf_so"; \ - else \ - echo ""; \ - fi -_DYNLINK!= ${_DYNLINK_SH} -LDFLAGS+= ${_DYNLINK}$(shell ${_DYNLINK_SH}) - -all: ${PROG} ${SCRIPTS} _man - -.c.o: - ${CC} ${CFLAGS} ${CPPFLAGS} -c $< -o $@ - -${PROG}: ${OBJS} - ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LDADD} - -# We could save about 600 bytes by building it like this -# instead of the more traditional method above -small: ${SRCS} - echo "" > _${PROG}.c - for src in ${SRCS}; do echo "#include \"$$src\"" >> _${PROG}.c; done - ${CC} ${CFLAGS} ${CPPFLAGS} -c _${PROG}.c -o _${PROG}.o - ${CC} ${LDFLAGS} -o ${PROG} _${PROG}.o ${LDADD} - -_proginstall: ${PROG} - ${INSTALL} -d ${DESTDIR}${BINDIR} - ${INSTALL} -m ${BINMODE} ${PROG} ${DESTDIR}${BINDIR} - ${INSTALL} -d ${DESTDIR}${DBDIR} - -include ${MK}/depend.mk -include ${MK}/files.mk -include ${MK}/scripts.mk -include ${MK}/man.mk -include ${MK}/dist.mk - -install: _proginstall _scriptsinstall _filesinstall _maninstall - for x in ${SUBDIRS}; do cd $$x; ${MAKE} $@; cd ..; done - -clean: - rm -f ${OBJS} ${PROG} _${PROG}.c _${PROG}.o ${PROG}.core ${CLEANFILES} - -LINTFLAGS?= -hx -LINTFLAGS+= -X 159,247,352 - -lint: ${SRCS:.c=.c} - ${LINT} ${LINTFLAGS} ${CFLAGS:M-[DIU]*} $^ ${.ALLSRC} diff --git a/mk/scripts.mk b/mk/scripts.mk deleted file mode 100644 index d295163..0000000 --- a/mk/scripts.mk +++ /dev/null @@ -1,9 +0,0 @@ -# Quick and dirty scripts -# Copyright 2008 Roy Marples - -SCRIPTSDIR?= ${BINDIR} -SCRIPTSMODE?= ${BINMODE} - -_scriptsinstall: ${SCRIPTS} - ${INSTALL} -d ${DESTDIR}${SCRIPTSDIR} - ${INSTALL} -m ${SCRIPTSMODE} ${SCRIPTS} ${DESTDIR}${SCRIPTSDIR} diff --git a/mk/sys.mk b/mk/sys.mk deleted file mode 100644 index 81882ab..0000000 --- a/mk/sys.mk +++ /dev/null @@ -1,14 +0,0 @@ -# Simple defaults - -BINDIR?= ${PREFIX}/usr/bin -BINMODE?= 0755 -NONBINMODE?= 0644 - -SYSCONFDIR?= ${PREFIX}/etc - -INSTALL?= install -SED?= sed - -_LIBNAME_SH= case `readlink /lib` in "") echo "lib";; *) basename `readlink /lib`;; esac -_LIBNAME!= ${_LIBNAME_SH} -LIBNAME?= ${_LIBNAME}$(shell ${_LIBNAME_SH}) diff --git a/net.c b/net.c deleted file mode 100644 index b905573..0000000 --- a/net.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#ifdef __linux__ -#include -#include -#endif -#include -#include -#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ -#include -#undef __FAVOR_BSD -#ifdef SIOCGIFMEDIA -#include -#endif -#include -#ifdef AF_LINK -# include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "common.h" -#include "dhcp.h" -#include "logger.h" -#include "net.h" -#include "signals.h" - -int -inet_ntocidr(struct in_addr address) -{ - int cidr = 0; - uint32_t mask = htonl(address.s_addr); - - while (mask) { - cidr++; - mask <<= 1; - } - - return cidr; -} - -int -inet_cidrtoaddr(int cidr, struct in_addr *addr) -{ - int ocets; - - if (cidr < 0 || cidr > 32) { - errno = EINVAL; - return -1; - } - ocets = (cidr + 7) / 8; - - addr->s_addr = 0; - if (ocets > 0) { - memset(&addr->s_addr, 255, (size_t)ocets - 1); - memset((unsigned char *)&addr->s_addr + (ocets - 1), - (256 - (1 << (32 - cidr) % 8)), 1); - } - - return 0; -} - -uint32_t -get_netmask(uint32_t addr) -{ - uint32_t dst; - - if (addr == 0) - return 0; - - dst = htonl(addr); - if (IN_CLASSA(dst)) - return ntohl(IN_CLASSA_NET); - if (IN_CLASSB (dst)) - return ntohl(IN_CLASSB_NET); - if (IN_CLASSC (dst)) - return ntohl(IN_CLASSC_NET); - - return 0; -} - -char * -hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen) -{ - static char buffer[(HWADDR_LEN * 3) + 1]; - char *p = buffer; - size_t i; - - for (i = 0; i < hwlen && i < HWADDR_LEN; i++) { - if (i > 0) - *p ++= ':'; - p += snprintf(p, 3, "%.2x", hwaddr[i]); - } - - *p ++= '\0'; - - return buffer; -} - -size_t -hwaddr_aton(unsigned char *buffer, const char *addr) -{ - char c[3]; - const char *p = addr; - unsigned char *bp = buffer; - size_t len = 0; - - c[2] = '\0'; - while (*p) { - c[0] = *p++; - c[1] = *p++; - /* Ensure that digits are hex */ - if (isxdigit((unsigned char)c[0]) == 0 || - isxdigit((unsigned char)c[1]) == 0) - { - errno = EINVAL; - return 0; - } - /* We should have at least two entries 00:01 */ - if (len == 0 && *p == '\0') { - errno = EINVAL; - return 0; - } - /* Ensure that next data is EOL or a seperator with data */ - if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) { - errno = EINVAL; - return 0; - } - if (*p) - p++; - if (bp) - *bp++ = (unsigned char)strtol(c, NULL, 16); - len++; - } - return len; -} - -int -do_interface(const char *ifname, - _unused unsigned char *hwaddr, _unused size_t *hwlen, - struct in_addr *addr, struct in_addr *net, int get) -{ - int s; - struct ifconf ifc; - int retval = 0, found = 0; - int len = 10 * sizeof(struct ifreq); - int lastlen = 0; - char *p; - union { - char *buffer; - struct ifreq *ifr; - } ifreqs; - struct sockaddr_in address; - struct ifreq *ifr; - struct sockaddr_in netmask; -#ifdef AF_LINK - struct sockaddr_dl *sdl; -#endif - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return -1; - - /* Not all implementations return the needed buffer size for - * SIOGIFCONF so we loop like so for all until it works */ - memset(&ifc, 0, sizeof(ifc)); - for (;;) { - ifc.ifc_len = len; - ifc.ifc_buf = xmalloc((size_t)len); - if (ioctl(s, SIOCGIFCONF, &ifc) == -1) { - if (errno != EINVAL || lastlen != 0) { - close(s); - free(ifc.ifc_buf); - return -1; - } - } else { - if (ifc.ifc_len == lastlen) - break; - lastlen = ifc.ifc_len; - } - - free(ifc.ifc_buf); - ifc.ifc_buf = NULL; - len *= 2; - } - - for (p = (char *)ifc.ifc_buf; p < (char *)ifc.ifc_buf + ifc.ifc_len;) { - /* Cast the ifc buffer to an ifreq cleanly */ - ifreqs.buffer = p; - ifr = ifreqs.ifr; - -#ifndef __linux__ - if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru)) - p += offsetof(struct ifreq, ifr_ifru) + - ifr->ifr_addr.sa_len; - else -#endif - p += sizeof(*ifr); - - if (strcmp(ifname, ifr->ifr_name) != 0) - continue; - - found = 1; - -#ifdef AF_LINK - if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) { - sdl = xmalloc(ifr->ifr_addr.sa_len); - memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len); - *hwlen = sdl->sdl_alen; - memcpy(hwaddr, LLADDR(sdl), *hwlen); - free(sdl); - retval = 1; - break; - } -#endif - - if (ifr->ifr_addr.sa_family == AF_INET) { - memcpy(&address, &ifr->ifr_addr, sizeof(address)); - if (ioctl(s, SIOCGIFNETMASK, ifr) == -1) - continue; - memcpy(&netmask, &ifr->ifr_addr, sizeof(netmask)); - if (get) { - addr->s_addr = address.sin_addr.s_addr; - net->s_addr = netmask.sin_addr.s_addr; - retval = 1; - break; - } else { - if (address.sin_addr.s_addr == addr->s_addr && - (!net || - netmask.sin_addr.s_addr == net->s_addr)) - { - retval = 1; - break; - } - } - } - - } - - if (!found) - errno = ENXIO; - close(s); - free(ifc.ifc_buf); - return retval; -} - -int -up_interface(const char *ifname) -{ - int s; - struct ifreq ifr; - int retval = -1; -#ifdef __linux__ - char *p; -#endif - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return -1; - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); -#ifdef __linux__ - /* We can only bring the real interface up */ - if ((p = strchr(ifr.ifr_name, ':'))) - *p = '\0'; -#endif - if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) { - if ((ifr.ifr_flags & IFF_UP)) - retval = 0; - else { - ifr.ifr_flags |= IFF_UP; - if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0) - retval = 0; - } - } - close(s); - return retval; -} - -int -carrier_status(const char *ifname) -{ - int s; - struct ifreq ifr; - int retval = -1; -#ifdef SIOCGIFMEDIA - struct ifmediareq ifmr; -#endif -#ifdef __linux__ - char *p; -#endif - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return -1; - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); -#ifdef __linux__ - /* We can only test the real interface up */ - if ((p = strchr(ifr.ifr_name, ':'))) - *p = '\0'; -#endif - if ((retval = ioctl(s, SIOCGIFFLAGS, &ifr)) == 0) { - if (ifr.ifr_flags & IFF_UP && ifr.ifr_flags & IFF_RUNNING) - retval = 1; - else - retval = 0; - } - -#ifdef SIOCGIFMEDIA - if (retval == 1) { - memset(&ifmr, 0, sizeof(ifmr)); - strncpy(ifmr.ifm_name, ifr.ifr_name, sizeof(ifmr.ifm_name)); - if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 && - ifmr.ifm_status & IFM_AVALID) - { - if (!(ifmr.ifm_status & IFM_ACTIVE)) - retval = 0; - } - } -#endif - close(s); - return retval; -} - -struct interface * -read_interface(const char *ifname, _unused int metric) -{ - int s; - struct ifreq ifr; - struct interface *iface = NULL; - unsigned char *hwaddr = NULL; - size_t hwlen = 0; - sa_family_t family = 0; - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return NULL; - -#ifdef __linux__ - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) - goto eexit; - - switch (ifr.ifr_hwaddr.sa_family) { - case ARPHRD_ETHER: - case ARPHRD_IEEE802: - hwlen = ETHER_ADDR_LEN; - break; - case ARPHRD_IEEE1394: - hwlen = EUI64_ADDR_LEN; - case ARPHRD_INFINIBAND: - hwlen = INFINIBAND_ADDR_LEN; - break; - } - - hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN); - memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, hwlen); - family = ifr.ifr_hwaddr.sa_family; -#else - ifr.ifr_metric = metric; - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1) - goto eexit; - - hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN); - if (do_interface(ifname, hwaddr, &hwlen, NULL, NULL, 0) != 1) - goto eexit; - - family = ARPHRD_ETHER; -#endif - - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCGIFMTU, &ifr) == -1) - goto eexit; - - /* Ensure that the MTU is big enough for DHCP */ - if (ifr.ifr_mtu < MTU_MIN) { - ifr.ifr_mtu = MTU_MIN; - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - if (ioctl(s, SIOCSIFMTU, &ifr) == -1) - goto eexit; - } - - if (up_interface(ifname) != 0) - goto eexit; - - iface = xzalloc(sizeof(*iface)); - strlcpy(iface->name, ifname, IF_NAMESIZE); - snprintf(iface->leasefile, PATH_MAX, LEASEFILE, ifname); - memcpy(&iface->hwaddr, hwaddr, hwlen); - iface->hwlen = hwlen; - - iface->family = family; - iface->arpable = !(ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK)); - - /* 0 is a valid fd, so init to -1 */ - iface->raw_fd = -1; - iface->udp_fd = -1; - iface->arp_fd = -1; - iface->link_fd = -1; - -eexit: - close(s); - free(hwaddr); - return iface; -} - -int -do_mtu(const char *ifname, short int mtu) -{ - struct ifreq ifr; - int r; - int s; - - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); - ifr.ifr_mtu = mtu; - r = ioctl(s, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr); - close(s); - if (r == -1) - return -1; - return ifr.ifr_mtu; -} - -void -free_routes(struct rt *routes) -{ - struct rt *r; - - while (routes) { - r = routes->next; - free(routes); - routes = r; - } -} - -int -open_udp_socket(struct interface *iface) -{ - int s; - union sockunion { - struct sockaddr sa; - struct sockaddr_in sin; - } su; - int n; -#ifdef SO_BINDTODEVICE - struct ifreq ifr; -#endif - - if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) - return -1; - - n = 1; - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1) - goto eexit; -#ifdef SO_BINDTODEVICE - memset(&ifr, 0, sizeof(ifr)); - strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name)); - if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1) - goto eexit; -#endif - /* As we don't use this socket for receiving, set the - * receive buffer to 1 */ - n = 1; - if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1) - goto eexit; - memset(&su, 0, sizeof(su)); - su.sin.sin_family = AF_INET; - su.sin.sin_port = htons(DHCP_CLIENT_PORT); - su.sin.sin_addr.s_addr = iface->addr.s_addr; - if (bind(s, &su.sa, sizeof(su)) == -1) - goto eexit; - - iface->udp_fd = s; - set_cloexec(s); - return 0; - -eexit: - close(s); - return -1; -} - -ssize_t -send_packet(const struct interface *iface, struct in_addr to, - const uint8_t *data, ssize_t len) -{ - union sockunion { - struct sockaddr sa; - struct sockaddr_in sin; - } su; - - memset(&su, 0, sizeof(su)); - su.sin.sin_family = AF_INET; - su.sin.sin_addr.s_addr = to.s_addr; - su.sin.sin_port = htons(DHCP_SERVER_PORT); - - return sendto(iface->udp_fd, data, len, 0, &su.sa, sizeof(su)); -} - -struct udp_dhcp_packet -{ - struct ip ip; - struct udphdr udp; - struct dhcp_message dhcp; -}; -const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet); - -static uint16_t -checksum(const void *data, uint16_t len) -{ - const uint8_t *addr = data; - uint32_t sum = 0; - - while (len > 1) { - sum += addr[0] * 256 + addr[1]; - addr += 2; - len -= 2; - } - - if (len == 1) - sum += *addr * 256; - - sum = (sum >> 16) + (sum & 0xffff); - sum += (sum >> 16); - - sum = htons(sum); - - return ~sum; -} - -ssize_t -make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length, - struct in_addr source, struct in_addr dest) -{ - struct udp_dhcp_packet *udpp; - struct ip *ip; - struct udphdr *udp; - - udpp = xzalloc(sizeof(*udpp)); - ip = &udpp->ip; - udp = &udpp->udp; - - /* OK, this is important :) - * We copy the data to our packet and then create a small part of the - * ip structure and an invalid ip_len (basically udp length). - * We then fill the udp structure and put the checksum - * of the whole packet into the udp checksum. - * Finally we complete the ip structure and ip checksum. - * If we don't do the ordering like so then the udp checksum will be - * broken, so find another way of doing it! */ - - memcpy(&udpp->dhcp, data, length); - - ip->ip_p = IPPROTO_UDP; - ip->ip_src.s_addr = source.s_addr; - if (dest.s_addr == 0) - ip->ip_dst.s_addr = INADDR_BROADCAST; - else - ip->ip_dst.s_addr = dest.s_addr; - - udp->uh_sport = htons(DHCP_CLIENT_PORT); - udp->uh_dport = htons(DHCP_SERVER_PORT); - udp->uh_ulen = htons(sizeof(*udp) + length); - ip->ip_len = udp->uh_ulen; - udp->uh_sum = checksum(udpp, sizeof(*udpp)); - - ip->ip_v = IPVERSION; - ip->ip_hl = 5; - ip->ip_id = 0; - ip->ip_tos = IPTOS_LOWDELAY; - ip->ip_len = htons (sizeof(*ip) + sizeof(*udp) + length); - ip->ip_id = 0; - ip->ip_off = htons(IP_DF); /* Don't fragment */ - ip->ip_ttl = IPDEFTTL; - - ip->ip_sum = checksum(ip, sizeof(*ip)); - - *packet = (uint8_t *)udpp; - return sizeof(*ip) + sizeof(*udp) + length; -} - -ssize_t -get_udp_data(const uint8_t **data, const uint8_t *udp) -{ - struct udp_dhcp_packet packet; - - memcpy(&packet, udp, sizeof(packet)); - *data = udp + offsetof(struct udp_dhcp_packet, dhcp); - return ntohs(packet.ip.ip_len) - sizeof(packet.ip) - sizeof(packet.udp); -} - -int -valid_udp_packet(const uint8_t *data) -{ - struct udp_dhcp_packet packet; - uint16_t bytes; - uint16_t ipsum; - uint16_t iplen; - uint16_t udpsum; - struct in_addr source; - struct in_addr dest; - int retval = 0; - - memcpy(&packet, data, sizeof(packet)); - bytes = ntohs(packet.ip.ip_len); - ipsum = packet.ip.ip_sum; - iplen = packet.ip.ip_len; - udpsum = packet.udp.uh_sum; - - if (0 != checksum(&packet.ip, sizeof(packet.ip))) { - errno = EINVAL; - return -1; - } - - packet.ip.ip_sum = 0; - memcpy(&source, &packet.ip.ip_src, sizeof(packet.ip.ip_src)); - memcpy(&dest, &packet.ip.ip_dst, sizeof(packet.ip.ip_dst)); - memset(&packet.ip, 0, sizeof(packet.ip)); - packet.udp.uh_sum = 0; - - packet.ip.ip_p = IPPROTO_UDP; - memcpy(&packet.ip.ip_src, &source, sizeof(packet.ip.ip_src)); - memcpy(&packet.ip.ip_dst, &dest, sizeof(packet.ip.ip_dst)); - packet.ip.ip_len = packet.udp.uh_ulen; - if (udpsum && udpsum != checksum(&packet, bytes)) { - errno = EINVAL; - retval = -1; - } - - return retval; -} - -int -send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip) -{ - struct arphdr *arp; - size_t arpsize; - uint8_t *p; - int retval; - - arpsize = sizeof(*arp) + 2 * iface->hwlen + 2 * sizeof(sip); - arp = xmalloc(arpsize); - arp->ar_hrd = htons(iface->family); - arp->ar_pro = htons(ETHERTYPE_IP); - arp->ar_hln = iface->hwlen; - arp->ar_pln = sizeof(sip); - arp->ar_op = htons(op); - p = (uint8_t *)arp; - p += sizeof(*arp); - memcpy(p, iface->hwaddr, iface->hwlen); - p += iface->hwlen; - memcpy(p, &sip, sizeof(sip)); - p += sizeof(sip); - /* ARP requests should ignore this */ - retval = iface->hwlen; - while (retval--) - *p++ = '\0'; - memcpy(p, &tip, sizeof(tip)); - p += sizeof(tip); - retval = send_raw_packet(iface, ETHERTYPE_ARP, arp, arpsize); - free(arp); - return retval; -} diff --git a/net.h b/net.h deleted file mode 100644 index 3ade025..0000000 --- a/net.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef INTERFACE_H -#define INTERFACE_H - -#include -#include -#include - -#include -#include -#include - -#include - -#include "config.h" - -#ifndef DUID_LEN -# define DUID_LEN 128 + 2 -#endif - -#define EUI64_ADDR_LEN 8 -#define INFINIBAND_ADDR_LEN 20 - -/* Linux 2.4 doesn't define this */ -#ifndef ARPHRD_IEEE1394 -# define ARPHRD_IEEE1394 24 -#endif - -/* The BSD's don't define this yet */ -#ifndef ARPHRD_INFINIBAND -# define ARPHRD_INFINIBAND 32 -#endif - -#define HWADDR_LEN 20 - -/* Work out if we have a private address or not - * 10/8 - * 172.16/12 - * 192.168/16 - */ -#ifndef IN_PRIVATE -# define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \ - ((addr & 0xfff00000) == 0xac100000) || \ - ((addr & IN_CLASSB_NET) == 0xc0a80000)) -#endif - -#define LINKLOCAL_ADDR 0xa9fe0000 -#define LINKLOCAL_MASK IN_CLASSB_NET -#define LINKLOCAL_BRDC (LINKLOCAL_ADDR | ~LINKLOCAL_MASK) - -#ifndef IN_LINKLOCAL -# define IN_LINKLOCAL(addr) ((addr & IN_CLASSB_NET) == LINKLOCAL_ADDR) -#endif - -/* There is an argument that this should be converted to an STAIL using - * queue(3). However, that isn't readily available on all libc's that - * dhcpcd works on. The only benefit of STAILQ over this is the ability to - * quickly loop backwards through the list - currently we reverse the list - * and then move through it forwards. This isn't that much of a big deal - * though as the norm is to just have one default route, and an IPV4LL route. - * You can (and do) get more routes in the DHCP message, but not enough to - * really warrant a change to STAIL queue for performance reasons. */ -struct rt { - struct in_addr dest; - struct in_addr net; - struct in_addr gate; - struct rt *next; -}; - -struct interface -{ - char name[IF_NAMESIZE]; - sa_family_t family; - unsigned char hwaddr[HWADDR_LEN]; - size_t hwlen; - int arpable; - - int raw_fd; - int udp_fd; - int arp_fd; - int link_fd; - size_t buffer_size, buffer_len, buffer_pos; - unsigned char *buffer; - - struct in_addr addr; - struct in_addr net; - struct rt *routes; - - char leasefile[PATH_MAX]; - time_t start_uptime; - - unsigned char *clientid; -}; - -uint32_t get_netmask(uint32_t); -char *hwaddr_ntoa(const unsigned char *, size_t); -size_t hwaddr_aton(unsigned char *, const char *); - -struct interface *read_interface(const char *, int); -int do_mtu(const char *, short int); -#define get_mtu(iface) do_mtu(iface, 0) -#define set_mtu(iface, mtu) do_mtu(iface, mtu) - -int inet_ntocidr(struct in_addr); -int inet_cidrtoaddr(int, struct in_addr *); - -int up_interface(const char *); -int do_interface(const char *, unsigned char *, size_t *, - struct in_addr *, struct in_addr *, int); -int if_address(const char *, const struct in_addr *, const struct in_addr *, - const struct in_addr *, int); -#define add_address(ifname, addr, net, brd) \ - if_address(ifname, addr, net, brd, 1) -#define del_address(ifname, addr, net) \ - if_address(ifname, addr, net, NULL, -1) -#define has_address(ifname, addr, net) \ - do_interface(ifname, NULL, NULL, addr, net, 0) -#define get_address(ifname, addr, net) \ - do_interface(ifname, NULL, NULL, addr, net, 1) - -int if_route(const char *, const struct in_addr *, const struct in_addr *, - const struct in_addr *, int, int); -#define add_route(ifname, dest, mask, gate, metric) \ - if_route(ifname, dest, mask, gate, metric, 1) -#define change_route(ifname, dest, mask, gate, metric) \ - if_route(ifname, dest, mask, gate, metric, 0) -#define del_route(ifname, dest, mask, gate, metric) \ - if_route(ifname, dest, mask, gate, metric, -1) -void free_routes(struct rt *); - -int open_udp_socket(struct interface *); -const size_t udp_dhcp_len; -ssize_t make_udp_packet(uint8_t **, const uint8_t *, size_t, - struct in_addr, struct in_addr); -ssize_t get_udp_data(const uint8_t **, const uint8_t *); -int valid_udp_packet(const uint8_t *); - -int open_socket(struct interface *, int); -ssize_t send_packet(const struct interface *, struct in_addr, - const uint8_t *, ssize_t); -ssize_t send_raw_packet(const struct interface *, int, - const void *, ssize_t); -ssize_t get_raw_packet(struct interface *, int, void *, ssize_t); - -int send_arp(const struct interface *, int, in_addr_t, in_addr_t); - -int open_link_socket(struct interface *); -int link_changed(struct interface *); -int carrier_status(const char *); -#endif diff --git a/showlease.c b/showlease.c deleted file mode 100644 index 9bee4ab..0000000 --- a/showlease.c +++ /dev/null @@ -1,349 +0,0 @@ -#include -#include -#include -#include - -#include "dhcp.h" -#include "config.h" - -#define REQUEST (1 << 0) -#define UINT8 (1 << 1) -#define UINT16 (1 << 2) -#define SINT16 (1 << 3) -#define UINT32 (1 << 4) -#define SINT32 (1 << 5) -#define IPV4 (1 << 6) -#define STRING (1 << 7) -#define PAIR (1 << 8) -#define ARRAY (1 << 9) -#define RFC3361 (1 << 10) -#define RFC3397 (1 << 11) -#define RFC3442 (1 << 12) - -struct dhcp_opt { - uint8_t option; - int type; - const char *var; -}; - -static const struct dhcp_opt const dhcp_opts[] = { - { 1, IPV4 | REQUEST, "subnet_mask" }, - { 2, UINT32, "time_offset" }, - { 3, IPV4 | ARRAY | REQUEST, "routers" }, - { 4, IPV4 | ARRAY, "time_servers" }, - { 5, IPV4 | ARRAY, "ien116_name_servers" }, - { 6, IPV4 | ARRAY, "domain_name_servers" }, - { 7, IPV4 | ARRAY, "log_servers" }, - { 8, IPV4 | ARRAY, "cookie_servers" }, - { 9, IPV4 | ARRAY, "lpr_servers" }, - { 10, IPV4 | ARRAY, "impress_servers" }, - { 11, IPV4 | ARRAY, "resource_location_servers" }, - { 12, STRING, "host_name" }, - { 13, UINT16, "boot_size" }, - { 14, STRING, "merit_dump" }, - { 15, STRING, "domain_name" }, - { 16, IPV4, "swap_server" }, - { 17, STRING, "root_path" }, - { 18, STRING, "extensions_path" }, - { 19, UINT8, "ip_forwarding" }, - { 20, UINT8, "non_local_source_routing" }, - { 21, IPV4 | ARRAY, "policy_filter" }, - { 22, SINT16, "max_dgram_reassembly" }, - { 23, UINT16, "default_ip_ttl" }, - { 24, UINT32, "path_mtu_aging_timeout" }, - { 25, UINT16 | ARRAY, "path_mtu_plateau_table" }, - { 26, UINT16, "interface_mtu" }, - { 27, UINT8, "all_subnets_local" }, - { 28, IPV4 | REQUEST, "broadcast_address" }, - { 29, UINT8, "perform_mask_discovery" }, - { 30, UINT8, "mask_supplier" }, - { 31, UINT8, "router_discovery" }, - { 32, IPV4, "router_solicitation_address" }, - { 33, IPV4 | ARRAY | REQUEST, "static_routes" }, - { 34, UINT8, "trailer_encapsulation" }, - { 35, UINT32, "arp_cache_timeout" }, - { 36, UINT16, "ieee802_3_encapsulation" }, - { 37, UINT8, "default_tcp_ttl" }, - { 38, UINT32, "tcp_keepalive_interval" }, - { 39, UINT8, "tcp_keepalive_garbage" }, - { 40, STRING, "nis_domain" }, - { 41, IPV4 | ARRAY, "nis_servers" }, - { 42, IPV4 | ARRAY, "ntp_servers" }, - { 43, STRING, "vendor_encapsulated_options" }, - { 44, IPV4 | ARRAY, "netbios_name_servers" }, - { 45, IPV4, "netbios_dd_server" }, - { 46, UINT8, "netbios_node_type" }, - { 47, STRING, "netbios_scope" }, - { 48, IPV4 | ARRAY, "font_servers" }, - { 49, IPV4 | ARRAY, "x_display_manager" }, - { 50, IPV4, "dhcp_requested_address" }, - { 51, UINT32 | REQUEST, "dhcp_lease_time" }, - { 52, UINT8, "dhcp_option_overload" }, - { 53, UINT8, "dhcp_message_type" }, - { 54, IPV4, "dhcp_server_identifier" }, - { 55, UINT8 | ARRAY, "dhcp_parameter_request_list" }, - { 56, STRING, "dhcp_message" }, - { 57, UINT16, "dhcp_max_message_size" }, - { 58, UINT32 | REQUEST, "dhcp_renewal_time" }, - { 59, UINT32 | REQUEST, "dhcp_rebinding_time" }, - { 64, STRING, "nisplus_domain" }, - { 65, IPV4 | ARRAY, "nisplus_servers" }, - { 66, STRING, "tftp_server_name" }, - { 67, STRING, "bootfile_name" }, - { 68, IPV4 | ARRAY, "mobile_ip_home_agent" }, - { 69, IPV4 | ARRAY, "smtp_server" }, - { 70, IPV4 | ARRAY, "pop_server" }, - { 71, IPV4 | ARRAY, "nntp_server" }, - { 72, IPV4 | ARRAY, "www_server" }, - { 73, IPV4 | ARRAY, "finger_server" }, - { 74, IPV4 | ARRAY, "irc_server" }, - { 75, IPV4 | ARRAY, "streettalk_server" }, - { 76, IPV4 | ARRAY, "streettalk_directory_assistance_server" }, - { 77, STRING, "user_class" }, - { 85, IPV4 | ARRAY, "nds_servers" }, - { 86, STRING, "nds_tree_name" }, - { 87, STRING, "nds_context" }, - { 88, STRING | RFC3397, "bcms_controller_names" }, - { 89, IPV4 | ARRAY, "bcms_controller_address" }, - { 91, UINT32, "client_last_transaction_time" }, - { 92, IPV4 | ARRAY, "associated_ip" }, - { 98, STRING, "uap_servers" }, - { 112, IPV4 | ARRAY, "netinfo_server_address" }, - { 113, STRING, "netinfo_server_tag" }, - { 114, STRING, "default_url" }, - { 118, IPV4, "subnet_selection" }, - { 119, STRING | RFC3397, "domain_search" }, - { 121, RFC3442 | REQUEST, "classless_static_routes" }, - { 249, RFC3442, "ms-classless_static_routes" }, - { 0, 0, NULL } -}; - -struct dhcp_message * -get_lease(const char *leasefile) -{ - int fd; - struct dhcp_message *dhcp; - ssize_t bytes; - - fd = open(leasefile, O_RDONLY); - if (fd == -1) - return NULL; - dhcp = malloc(sizeof(*dhcp)); - memset(dhcp, 0, sizeof(*dhcp)); - bytes = read(fd, dhcp, sizeof(*dhcp)); - close(fd); - if (bytes < 0) { - free(dhcp); - dhcp = NULL; - } - return dhcp; -} - -static uint8_t *dhcp_opt_buffer = NULL; - -static int -valid_length(uint8_t option, int dl, int *type) -{ - const struct dhcp_opt *opt; - ssize_t sz; - - if (dl == 0) - return -1; - - for (opt = dhcp_opts; opt->option; opt++) { - if (opt->option != option) - continue; - - if (type) - *type = opt->type; - - if (opt->type == 0 || opt->type & STRING || opt->type & RFC3442) - return 0; - - sz = 0; - if (opt->type & UINT32 || opt->type & IPV4) - sz = sizeof(uint32_t); - if (opt->type & UINT16) - sz = sizeof(uint16_t); - if (opt->type & UINT8) - sz = sizeof(uint8_t); - if (opt->type & IPV4 || opt->type & ARRAY) - return dl % sz; - return (dl == sz ? 0 : -1); - } - - /* unknown option, so let it pass */ - return 0; -} - -static void -free_option_buffer(void) -{ - free(dhcp_opt_buffer); -} - - -#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL) -static const uint8_t * -get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type) -{ - const uint8_t *p = dhcp->options; - const uint8_t *e = p + sizeof(dhcp->options); - uint8_t l, ol = 0; - uint8_t o = 0; - uint8_t overl = 0; - uint8_t *bp = NULL; - const uint8_t *op = NULL; - int bl = 0; - - while (p < e) { - o = *p++; - if (o == opt) { - if (op) { - if (!dhcp_opt_buffer) { - dhcp_opt_buffer = malloc(sizeof(struct dhcp_message)); - atexit(free_option_buffer); - } - if (!bp) - bp = dhcp_opt_buffer; - memcpy(bp, op, ol); - bp += ol; - } - ol = *p; - op = p + 1; - bl += ol; - } - switch (o) { - case DHO_PAD: - continue; - case DHO_END: - if (overl & 1) { - /* bit 1 set means parse boot file */ - overl &= ~1; - p = dhcp->bootfile; - e = p + sizeof(dhcp->bootfile); - } else if (overl & 2) { - /* bit 2 set means parse server name */ - overl &= ~2; - p = dhcp->servername; - e = p + sizeof(dhcp->servername); - } else - goto exit; - break; - case DHO_OPTIONSOVERLOADED: - /* Ensure we only get this option once */ - if (!overl) - overl = p[1]; - break; - } - l = *p++; - p += l; - } - -exit: - if (valid_length(o, bl, type) == -1) { - errno = EINVAL; - return NULL; - } - if (len) - *len = bl; - if (bp) { - memcpy(bp, op, ol); - return (const uint8_t *)&dhcp_opt_buffer; - } - if (op) - return op; - errno = ENOENT; - return NULL; -} - -int -get_option_addr(uint32_t *a, const struct dhcp_message *dhcp, uint8_t option) -{ - const uint8_t *p = get_option_raw(dhcp, option); - - if (!p) - return -1; - memcpy(a, p, sizeof(*a)); - return 0; -} - -int -get_option_uint32(uint32_t *i, const struct dhcp_message *dhcp, uint8_t option) -{ - uint32_t a; - - if (get_option_addr(&a, dhcp, option) == -1) - return -1; - - *i = ntohl(a); - return 0; -} - -uint32_t -get_netmask(uint32_t addr) -{ - uint32_t dst; - - if (addr == 0) - return 0; - - dst = htonl(addr); - if (IN_CLASSA(dst)) - return ntohl(IN_CLASSA_NET); - if (IN_CLASSB (dst)) - return ntohl(IN_CLASSB_NET); - if (IN_CLASSC (dst)) - return ntohl(IN_CLASSC_NET); - - return 0; -} - -void showlease(struct dhcp_lease *lease) -{ - printf("addr: %s\n", inet_ntoa(lease->addr)); - printf("net: %s\n", inet_ntoa(lease->net)); - printf("leasetime: %d\n", lease->leasetime); - printf("renew: %d\n", lease->renewaltime); - printf("rebind: %d\n", lease->rebindtime); - printf("server: %s\n", inet_ntoa(lease->server)); -} -#define MAX_LEASETIME 2147460 - -int -main(int argc, char *argv[]) -{ - struct dhcp_message *dhcp; - struct dhcp_lease *lease; - char leasefile[PATH_MAX]; - - if (argc < 2) { - fprintf(stderr, "Usage: %s \n", argv[0]); - exit(1); - } - snprintf(leasefile, PATH_MAX, LEASEFILE, argv[1]); - if ((dhcp = get_lease(leasefile)) == NULL) { - fprintf(stderr, "Couldn't read lease file: %s\n", strerror(errno)); - exit(1); - } - lease = malloc(sizeof(*lease)); - lease->frominfo = 0; - lease->addr.s_addr = dhcp->yiaddr; - - if (get_option_addr(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1) - lease->net.s_addr = get_netmask(dhcp->yiaddr); - if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) != 0) - lease->leasetime = DEFAULT_LEASETIME; - get_option_addr(&lease->server.s_addr, dhcp, DHO_SERVERID); - /* Dm: limit lease time value to avoid negative numbers when - converting to milliseconds */ - if ((lease->leasetime != ~0U) && (lease->leasetime > MAX_LEASETIME)) - lease->leasetime = MAX_LEASETIME; - if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0) - lease->renewaltime = 0; - if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0) - lease->rebindtime = 0; - showlease(lease); - free(lease); - return 0; -} diff --git a/signals.c b/signals.c deleted file mode 100644 index 58679d6..0000000 --- a/signals.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include -#include -#include -#include - -#include "common.h" -#include "signals.h" - -static int signal_pipe[2]; - -static const int handle_sigs[] = { - SIGHUP, - SIGALRM, - SIGTERM, - SIGINT -}; - -static void -signal_handler(int sig) -{ - int serrno = errno; - - write(signal_pipe[1], &sig, sizeof(sig)); - /* Restore errno */ - errno = serrno; -} - -int -signal_fd(void) -{ - return (signal_pipe[0]); -} - -/* Read a signal from the signal pipe. Returns 0 if there is - * no signal, -1 on error (and sets errno appropriately), and - * your signal on success */ -int -signal_read(void) -{ - int sig = -1; - char buf[16]; - size_t bytes; - - memset(buf, 0, sizeof(buf)); - bytes = read(signal_pipe[0], buf, sizeof(buf)); - if (bytes >= sizeof(sig)) - memcpy(&sig, buf, sizeof(sig)); - return sig; -} - -/* Call this before doing anything else. Sets up the socket pair - * and installs the signal handler */ -int -signal_init(void) -{ - if (pipe(signal_pipe) == -1) - return -1; - /* Don't block on read */ - if (set_nonblock(signal_pipe[0]) == -1) - return -1; - /* Stop any scripts from inheriting us */ - if (set_cloexec(signal_pipe[0]) == -1) - return -1; - if (set_cloexec(signal_pipe[1]) == -1) - return -1; - return 0; -} - -static int -signal_handle(void (*func)(int)) -{ - unsigned int i; - struct sigaction sa; - - memset(&sa, 0, sizeof(sa)); - sa.sa_handler = func; - sigemptyset(&sa.sa_mask); - - for (i = 0; i < sizeof(handle_sigs) / sizeof(handle_sigs[0]); i++) - if (sigaction(handle_sigs[i], &sa, NULL) == -1) - return -1; - return 0; -} - -int -signal_setup(void) -{ - return signal_handle(signal_handler); -} - -int -signal_reset(void) -{ - return signal_handle(SIG_DFL); -} diff --git a/signals.h b/signals.h deleted file mode 100644 index f784a68..0000000 --- a/signals.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples - * All rights reserved - - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef SIGNAL_H -#define SIGNAL_H - -int signal_init(void); -int signal_setup(void); -int signal_reset(void); -int signal_fd(void); -int signal_read(void); - -#endif -- cgit v1.1