diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:20 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:20 -0800 |
commit | d97c47cad830d00c9da685cc4ea157d6185f6c97 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 | |
parent | 4c5a5fb53bccceff331bae70f748bf9b4609fe0a (diff) | |
download | external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.zip external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.gz external_dhcpcd-d97c47cad830d00c9da685cc4ea157d6185f6c97.tar.bz2 |
auto import from //depot/cupcake/@135843
-rw-r--r-- | Android.mk | 66 | ||||
-rw-r--r-- | Makefile | 51 | ||||
-rw-r--r-- | README | 67 | ||||
-rw-r--r-- | android.conf | 6 | ||||
-rw-r--r-- | bpf-filter.h | 101 | ||||
-rw-r--r-- | bpf.c | 206 | ||||
-rw-r--r-- | client.c | 1839 | ||||
-rw-r--r-- | client.h | 35 | ||||
-rw-r--r-- | common.c | 327 | ||||
-rw-r--r-- | common.h | 87 | ||||
-rw-r--r-- | config.h | 75 | ||||
-rw-r--r-- | configure.c | 420 | ||||
-rw-r--r-- | configure.h | 41 | ||||
-rw-r--r-- | dhcp.c | 1251 | ||||
-rw-r--r-- | dhcp.h | 178 | ||||
-rw-r--r-- | dhcpcd-hooks/01-test | 7 | ||||
-rw-r--r-- | dhcpcd-hooks/10-mtu | 5 | ||||
-rw-r--r-- | dhcpcd-hooks/20-dns.conf | 32 | ||||
-rw-r--r-- | dhcpcd-hooks/20-resolv.conf | 107 | ||||
-rw-r--r-- | dhcpcd-hooks/29-lookup-hostname | 34 | ||||
-rw-r--r-- | dhcpcd-hooks/30-hostname | 28 | ||||
-rw-r--r-- | dhcpcd-hooks/50-dhcpcd-compat | 31 | ||||
-rw-r--r-- | dhcpcd-hooks/50-ntp.conf | 82 | ||||
-rw-r--r-- | dhcpcd-hooks/50-yp.conf | 49 | ||||
-rw-r--r-- | dhcpcd-hooks/90-NetworkManager | 8 | ||||
-rw-r--r-- | dhcpcd-hooks/95-configured | 26 | ||||
-rw-r--r-- | dhcpcd-hooks/Makefile | 13 | ||||
-rwxr-xr-x | dhcpcd-run-hooks | 31 | ||||
-rw-r--r-- | dhcpcd-run-hooks.8 | 113 | ||||
-rw-r--r-- | dhcpcd-run-hooks.8.in | 113 | ||||
-rw-r--r-- | dhcpcd-run-hooks.in | 138 | ||||
-rw-r--r-- | dhcpcd.8 | 430 | ||||
-rw-r--r-- | dhcpcd.8.in | 430 | ||||
-rw-r--r-- | dhcpcd.c | 1038 | ||||
-rw-r--r-- | dhcpcd.conf | 13 | ||||
-rw-r--r-- | dhcpcd.conf.5 | 155 | ||||
-rw-r--r-- | dhcpcd.conf.5.in | 155 | ||||
-rw-r--r-- | dhcpcd.h | 95 | ||||
-rw-r--r-- | if-bsd.c | 241 | ||||
-rw-r--r-- | if-linux.c | 379 | ||||
-rw-r--r-- | logger.c | 89 | ||||
-rw-r--r-- | logger.h | 43 | ||||
-rw-r--r-- | lpf.c | 168 | ||||
-rw-r--r-- | mk/cc.mk | 28 | ||||
-rw-r--r-- | mk/depend.mk | 11 | ||||
-rw-r--r-- | mk/dist.mk | 31 | ||||
-rw-r--r-- | mk/files.mk | 9 | ||||
-rw-r--r-- | mk/man.mk | 25 | ||||
-rw-r--r-- | mk/os-BSD.mk | 5 | ||||
-rw-r--r-- | mk/os-Darwin.mk | 5 | ||||
-rw-r--r-- | mk/os-Linux.mk | 8 | ||||
-rw-r--r-- | mk/os.mk | 7 | ||||
-rw-r--r-- | mk/prog.mk | 68 | ||||
-rw-r--r-- | mk/scripts.mk | 9 | ||||
-rw-r--r-- | mk/sys.mk | 14 | ||||
-rw-r--r-- | net.c | 707 | ||||
-rw-r--r-- | net.h | 176 | ||||
-rw-r--r-- | showlease.c | 349 | ||||
-rw-r--r-- | signals.c | 125 | ||||
-rw-r--r-- | signals.h | 37 |
60 files changed, 0 insertions, 10417 deletions
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 <roy@marples.name> - -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 @@ -1,67 +0,0 @@ -dhcpcd-4 - DHCP client daemon -Copyright 2006-2008 Roy Marples <roy@marples.name> - - -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 <roy@marples.name> - * - * 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 - * <info@isc.org> - * 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]); @@ -1,206 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * - * 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 <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/uio.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <arpa/inet.h> - -#include <errno.h> -#include <fcntl.h> -#include <paths.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <arpa/inet.h> - -#ifdef __linux__ -# include <netinet/ether.h> -#endif - -#include <errno.h> -#include <poll.h> -#include <signal.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 <roy@marples.name> - * 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 <mach/mach_time.h> -# include <mach/kern_return.h> -#endif - -#include <sys/param.h> -#include <sys/time.h> - -#include <errno.h> -#include <fcntl.h> -#ifdef BSD -# include <paths.h> -#endif -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 <sys/types.h> -#include <sys/time.h> -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#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 <roy@marples.name> - * - * 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 <roy@marples.name> - * 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 <sys/stat.h> -#include <sys/wait.h> - -#include <netinet/in.h> -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <signal.h> -#include <stdlib.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 @@ -1,1251 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * 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 <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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; -} @@ -1,178 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * 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 <arpa/inet.h> - -#include <stdint.h> - -#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.<iface>.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 <roy@marples.name> -.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 <roy@marples.name> -.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 <version>. -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 <roy@marples.name> -.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 <version>. -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 <roy@marples.name> -.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 <roy@marples.name> - * 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 <sys/file.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <paths.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <time.h> - -#include "config.h" -#include "client.h" -#include "dhcpcd.h" -#include "dhcp.h" -#include "net.h" -#include "logger.h" - -#ifdef ANDROID -#include <linux/capability.h> -#include <linux/prctl.h> -#include <cutils/properties.h> -#include <private/android_filesystem_config.h> -#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] <interface>\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 <roy@marples.name> -.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 <roy@marples.name> -.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 <roy@marples.name> - * 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 <sys/param.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <netinet/in.h> - -#include <limits.h> - -#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 <roy@marples.name> - * 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 <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/param.h> - -#include <arpa/inet.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/route.h> -#include <netinet/in.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 <asm/types.h> /* Needed for 2.4 kernels */ - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/ioctl.h> -#include <sys/param.h> - -#include <arpa/inet.h> -#include <linux/netlink.h> -#include <linux/rtnetlink.h> -#include <netinet/ether.h> -#include <netpacket/packet.h> - -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -/* 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 <roy@marples.name> - * 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 <ctype.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> - -#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 <roy@marples.name> - * 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 <syslog.h> - -void setloglevel(int); -void setlogprefix(const char *); -void logger(int, const char *, ...) _PRINTF_LIKE (2, 3); - -#endif @@ -1,168 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * - * 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 <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <netinet/in_systm.h> -#include <netinet/in.h> -#include <arpa/inet.h> - -#ifdef __linux__ -# include <asm/types.h> /* needed for 2.4 kernels for the below header */ -# include <linux/filter.h> -# include <netpacket/packet.h> -# define bpf_insn sock_filter -# define BPF_SKIPTYPE -# define BPF_ETHCOOK -ETH_HLEN -# define BPF_WHOLEPACKET 0x0fffffff /* work around buggy LPF filters */ -#endif - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#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 <roy@marples.name> - -# 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 <roy@marples.name> - -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 <roy@marples.name> - -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 <roy@marples.name> - -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 <roy@marples.name> - -_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 <roy@marples.name> - -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 <roy@marples.name> - -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 <roy@marples.name> - -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 <roy@marples.name> - -_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 <roy@marples.name> - -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 <roy@marples.name> - -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}) @@ -1,707 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * 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 <sys/types.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <net/if.h> -#include <net/if_arp.h> -#include <arpa/inet.h> -#include <netinet/in_systm.h> -#ifdef __linux__ -#include <netinet/ether.h> -#include <netpacket/packet.h> -#endif -#include <netinet/in.h> -#include <netinet/ip.h> -#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */ -#include <netinet/udp.h> -#undef __FAVOR_BSD -#ifdef SIOCGIFMEDIA -#include <net/if_media.h> -#endif -#include <arpa/inet.h> -#ifdef AF_LINK -# include <net/if_dl.h> -#endif - -#include <ctype.h> -#include <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#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; -} @@ -1,176 +0,0 @@ -/* - * dhcpcd - DHCP client daemon - * Copyright 2006-2008 Roy Marples <roy@marples.name> - * 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 <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <limits.h> - -#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 <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <fcntl.h> - -#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 <interface>\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 <roy@marples.name> - * 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 <sys/types.h> -#include <sys/socket.h> - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <unistd.h> - -#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 <roy@marples.name> - * 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 |