Import dhpcd-4.0.0rc3. Major changes since beta4:

- support for link state notification (e.g. renew lease after carrier
  returned)
- support to start go into background immediately
- don't cleanup interface state. dhcpcd will leave the interface in the
  same state as before if the lease uses separate addresses. -p still
  stops it from removing the configured address on exit
- various smaller bugfixes, optimisations and cleanups
This commit is contained in:
joerg 2008-07-27 18:06:30 +00:00
parent c8ccd39051
commit b2f096aeb9
32 changed files with 7937 additions and 0 deletions

65
external/bsd/dhcpcd/dist/README vendored Normal file
View File

@ -0,0 +1,65 @@
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 a NOMMU system where fork() does not work, you should
add -DTHERE_IS_NO_FORK to your CPPFLAGS.
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

101
external/bsd/dhcpcd/dist/bpf-filter.h vendored Normal file
View File

@ -0,0 +1,101 @@
/*
* 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]);

206
external/bsd/dhcpcd/dist/bpf.c vendored Normal file
View File

@ -0,0 +1,206 @@
/*
* 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;
}
}

1764
external/bsd/dhcpcd/dist/client.c vendored Normal file

File diff suppressed because it is too large Load Diff

35
external/bsd/dhcpcd/dist/client.h vendored Normal file
View File

@ -0,0 +1,35 @@
/*
* 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

284
external/bsd/dhcpcd/dist/common.c vendored Normal file
View File

@ -0,0 +1,284 @@
/*
* 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/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
/* 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.
*/
int
clock_monotonic(struct timeval *tp)
{
#if defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
struct timespec ts;
static clockid_t posix_clock;
static int posix_clock_set = 0;
if (!posix_clock_set) {
if (sysconf(_SC_MONOTONIC_CLOCK) >= 0)
posix_clock = CLOCK_MONOTONIC;
else
posix_clock = CLOCK_REALTIME;
posix_clock_set = 1;
}
if (clock_gettime(posix_clock, &ts) == -1)
return -1;
tp->tv_sec = ts.tv_sec;
tp->tv_usec = ts.tv_nsec / 1000;
return 0;
#else
return gettimeofday(tp, NULL);
#endif
}
time_t
uptime(void)
{
struct timeval tv;
if (clock_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", 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 */
}

86
external/bsd/dhcpcd/dist/common.h vendored Normal file
View File

@ -0,0 +1,86 @@
/*
* 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 *);
int clock_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

75
external/bsd/dhcpcd/dist/config.h vendored Normal file
View File

@ -0,0 +1,75 @@
/*
* 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.0-rc3"
/*
* 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 "/etc"
#endif
#ifndef LIBEXECDIR
# define LIBEXECDIR "/libexec"
#endif
#ifndef RUNDIR
# define RUNDIR "/var/run"
#endif
#ifndef DBDIR
# define DBDIR "/var/db"
#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

501
external/bsd/dhcpcd/dist/configure.c vendored Normal file
View File

@ -0,0 +1,501 @@
/*
* 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"
int
exec_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;
int ret = 0;
pid_t pid;
int status = 0;
sigset_t full;
sigset_t old;
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';
/* OK, we need to block signals */
sigfillset(&full);
sigprocmask(SIG_SETMASK, &full, &old);
#ifdef THERE_IS_NO_FORK
signal_reset();
pid = vfork();
#else
pid = fork();
#endif
switch (pid) {
case -1:
#ifdef THERE_IS_NO_FORK
logger(LOG_ERR, "vfork: %s", strerror(errno));
#else
logger(LOG_ERR, "fork: %s", strerror(errno));
#endif
ret = -1;
break;
case 0:
#ifndef THERE_IS_NO_FORK
signal_reset();
#endif
sigprocmask(SIG_SETMASK, &old, NULL);
execve(options->script, argv, env);
logger(LOG_ERR, "%s: %s", options->script, strerror(errno));
_exit(111);
/* NOTREACHED */
}
#ifdef THERE_IS_NO_FORK
signal_setup();
#endif
/* Restore our signals */
sigprocmask(SIG_SETMASK, &old, NULL);
/* 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;
#ifdef THERE_IS_NO_FORK
char *skipp;
size_t skiplen;
int skip = 0;
free(dhcpcd_skiproutes);
/* We can never have more than 255 routes. So we need space
* for 255 3 digit numbers and commas */
skiplen = 255 * 4 + 1;
skipp = dhcpcd_skiproutes = xmalloc(sizeof(char) * skiplen);
*skipp = '\0';
#endif
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
#ifdef THERE_IS_NO_FORK
if (dhcpcd_skiproutes) {
int i = -1;
char *sk, *skp, *token;
free_routes(iface->routes);
for (rt = ort; rt; rt = rt->next) {
i++;
/* Check that we did add this route or not */
sk = skp = xstrdup(dhcpcd_skiproutes);
while ((token = strsep(&skp, ","))) {
if (isdigit((unsigned char)*token) &&
atoi(token) == i)
break;
}
free(sk);
if (token)
continue;
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;
}
iface->routes = nr;
nr = NULL;
/* We no longer need this */
free(dhcpcd_skiproutes);
dhcpcd_skiproutes = NULL;
}
#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;
}
#ifdef THERE_IS_NO_FORK
/* If we have daemonised yet we need to record which routes
* we failed to add so we can skip them */
else if (!(options->options & DHCPCD_DAEMONISED)) {
/* We can never have more than 255 / 4 routes,
* so 3 chars is plently */
printf("foo\n");
if (*skipp)
*skipp++ = ',';
skipp += snprintf(skipp,
dhcpcd_skiproutes + skiplen - skipp,
"%d", skip);
}
skip++;
#endif
}
free_routes(ort);
free_routes(iface->routes);
iface->routes = nr;
#ifdef THERE_IS_NO_FORK
if (dhcpcd_skiproutes) {
if (*dhcpcd_skiproutes)
*skipp = '\0';
else {
free(dhcpcd_skiproutes);
dhcpcd_skiproutes = NULL;
}
}
#endif
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 || dhcp->yiaddr == 0)
up = 0;
else {
addr.s_addr = dhcp->yiaddr;
/* Ensure we have all the needed values */
if (get_option_addr(&net.s_addr, dhcp, DHCP_SUBNETMASK) == -1)
net.s_addr = get_netmask(addr.s_addr);
if (get_option_addr(&brd.s_addr, dhcp, DHCP_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);
}
exec_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));
exec_script(options, iface->name, reason, dhcp, old);
return 0;
}

41
external/bsd/dhcpcd/dist/configure.h vendored Normal file
View File

@ -0,0 +1,41 @@
/*
* 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 exec_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

1211
external/bsd/dhcpcd/dist/dhcp.c vendored Normal file

File diff suppressed because it is too large Load Diff

185
external/bsd/dhcpcd/dist/dhcp.h vendored Normal file
View File

@ -0,0 +1,185 @@
/*
* 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 DHCP_OPTIONS
{
DHCP_PAD = 0,
DHCP_SUBNETMASK = 1,
DHCP_ROUTER = 3,
DHCP_DNSSERVER = 6,
DHCP_HOSTNAME = 12,
DHCP_DNSDOMAIN = 15,
DHCP_MTU = 26,
DHCP_BROADCAST = 28,
DHCP_STATICROUTE = 33,
DHCP_NISDOMAIN = 40,
DHCP_NISSERVER = 41,
DHCP_NTPSERVER = 42,
DHCP_VENDOR = 43,
DHCP_IPADDRESS = 50,
DHCP_LEASETIME = 51,
DHCP_OPTIONSOVERLOADED = 52,
DHCP_MESSAGETYPE = 53,
DHCP_SERVERID = 54,
DHCP_PARAMETERREQUESTLIST = 55,
DHCP_MESSAGE = 56,
DHCP_MAXMESSAGESIZE = 57,
DHCP_RENEWALTIME = 58,
DHCP_REBINDTIME = 59,
DHCP_CLASSID = 60,
DHCP_CLIENTID = 61,
DHCP_USERCLASS = 77, /* RFC 3004 */
DHCP_FQDN = 81,
DHCP_DNSSEARCH = 119, /* RFC 3397 */
DHCP_CSR = 121, /* RFC 3442 */
DHCP_MSCSR = 249, /* MS code for RFC 3442 */
DHCP_END = 255
};
/* SetFQDNHostName values - lsnybble used in flags
* byte (see buildmsg.c), hsnybble to create order
* and to allow 0x00 to mean disable
*/
enum FQQN {
FQDN_DISABLE = 0x00,
FQDN_NONE = 0x18,
FQDN_PTR = 0x20,
FQDN_BOTH = 0x31
};
struct fqdn
{
uint8_t flags;
uint8_t r1;
uint8_t r2;
char *name;
};
/* 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;
uint32_t leasedfrom;
uint8_t frominfo;
};
#define add_reqmask(var, val) (var[val >> 3] |= 1 << (val & 7))
#define del_reqmask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
#define has_reqmask(var, val) (var[val >> 3] & (1 << (val & 7)))
int make_reqmask(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

View File

@ -0,0 +1,6 @@
# Just echo our DHCP options we have
if [ "${reason}" = "TEST" ]; then
set | grep "^\(interface\|metric\|pid\|reason\|skip_hooks\)=" | sort
set | grep "^\(new_\|old_\)" | sort
fi

View File

@ -0,0 +1,5 @@
# Configure the MTU for the interface
if [ -n "${new_interface_mtu}" ]; then
ifconfig "${interface}" mtu "${new_interface_mtu}"
fi

View File

@ -0,0 +1,40 @@
# Generate /etc/resolv.conf
# Support resolvconf(8) if available
make_resolv_conf()
{
if [ -z "${new_domain_name_servers}" -a \
-z "${new_domain_name}" -a \
-z "${new_domain_search}" ]; then
return 0
fi
local x= conf="${signature}\n"
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}"
else
save_conf /etc/resolv.conf
printf "${conf}" > /etc/resolv.conf
fi
}
restore_resolv_conf()
{
if type resolvconf >/dev/null 2>&1; then
resolvconf -d "${interface}" -f
else
restore_conf /etc/resolv.conf || return 0
fi
}
case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) make_resolv_conf;;
EXPIRE|FAIL|IPV4LL|RELEASE|STOP) restore_resolv_conf;;
esac

View File

@ -0,0 +1,33 @@
# Lookup the hostname in DNS if not set
lookup_hostname()
{
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}" ]; then
export new_host_name="$(lookup_hostname)"
fi
}
case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;;
esac

View File

@ -0,0 +1,21 @@
# Set the hostname from DHCP data if required
need_hostname()
{
case "$(hostname)" in
""|"(none)"|localhost) [ -n "${new_host_name}" ];;
"${old_host_name}") true;;
*) false;;
esac
}
set_hostname()
{
if need_hostname; then
hostname "${new_host_name}"
fi
}
case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;;
esac

View File

@ -0,0 +1,51 @@
# Sample dhcpcd hook script for ntp
# 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
make_ntp_conf()
{
[ -z "${new_ntp_servers}" ] && return 0
local cf=/etc/ntp.conf."${interface}" x=
echo "${signature}" > "${cf}"
echo "restrict default noquery notrust nomodify" >> "${cf}"
echo "restrict 127.0.0.1" >> "${cf}"
for x in ${new_ntp_servers}; do
echo "restrict ${x} nomodify notrap noquery" >> "${cf}"
echo "server ${x}" >> "${cf}"
done
if [ ! -e /etc/ntp.conf ]; then
false
elif type cmp >/dev/null 2>&1; then
cmp -s /etc/ntp.conf "${cf}"
elif type diff >/dev/null 2>&1; then
diff -q /etc/ntp.conf "${cf}" >/dev/null
else
false
fi
if [ $? = 0 ]; then
rm -f "${cf}"
else
save_conf /etc/ntp.conf
mv -f "${cf}" /etc/ntp.conf
[ -n "${ntpd_restart_cmd}" ] && ${ntpd_restart_cmd}
fi
}
restore_ntp_conf()
{
restore_conf /etc/ntp.conf || return 0
[ -n "${ntpd_restart_cmd}" ] && ${ntpd_restart_cmd}
}
case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) make_ntp_conf;;
EXPIRE|FAIL|IPV4LL|RELEASE|STOP) restore_ntp_conf;;
esac

View File

@ -0,0 +1,108 @@
.\" 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 Jul 12, 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 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

View File

@ -0,0 +1,39 @@
#!/bin/sh
# dhcpcd client configuration script
# Handy functions for our hooks to use
signature="# Generated by dhcpcd for ${interface}"
save_conf()
{
if [ -f "$1" ]; then
rm -f "$1"-pre."${interface}"
mv -f "$1" "$1"-pre."${interface}"
fi
}
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.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

395
external/bsd/dhcpcd/dist/dhcpcd.8.in vendored Normal file
View File

@ -0,0 +1,395 @@
.\" 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 Jul 18, 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 , -classid Ar classid
.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
.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
.Rs
.%T "RFC 2131"
.Re
.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
will then write 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
will set 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 will probe for a valid IPv4LL address
.Po
aka Zeroconf, aka APIPA
.Pc .
Once obtained it will restart the process of looking for a DHCP server to get a
proper address.
.Pp
When using IPv4LL,
.Nm
will always succeed and return a 0 exit code. To disable this behaviour, you
can use the
.Fl L , -noipv4ll
option.
.Ss Hooking into DHCP events
.Nm
will run
.Pa @SCRIPT@ ,
or the script specified by the
.Fl c , -script
option.
This script will run 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
will send 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 , -classid Ar classid
Override the
.Ar classid
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.
.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 , -renew
Notifies an existing
.Nm
process running on the
.Ar interface
to renew it's lease. If
.Nm
is not running, then it starts up as normal.
.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 Broadcast to find servers to offer an address.
.Nm
will then request the address used.
You can use this option to skip the broadcast step and just request an
.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 broadcast 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 exactly 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.
.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 causes an existing
.Nm
process running on the
.Ar interface
to deconfigure the
.Ar interface
and exit.
.It Fl D , -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 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 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.
.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 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 .
.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

996
external/bsd/dhcpcd/dist/dhcpcd.c vendored Normal file
View File

@ -0,0 +1,996 @@
/*
* 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 "config.h"
#include "client.h"
#include "dhcpcd.h"
#include "dhcp.h"
#include "net.h"
#include "logger.h"
/* 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:TV"
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'},
{"classid", optional_argument, NULL, 'i'},
{"release", no_argument, NULL, 'k'},
{"leasetime", required_argument, NULL, 'l'},
{"metric", required_argument, NULL, 'm'},
{"renew", no_argument, NULL, 'n'},
{"option", required_argument, NULL, 'o'},
{"persistent", no_argument, NULL, 'p'},
{"quiet", no_argument, NULL, 'q'},
{"inform", optional_argument, NULL, 's'},
{"request", optional_argument, NULL, 'r'},
{"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'},
{"test", no_argument, NULL, 'T'},
{"variables", no_argument, NULL, 'V'},
{"help", no_argument, &dohelp, 1},
{"version", no_argument, &doversion, 1},
#ifdef THERE_IS_NO_FORK
{"daemonised", no_argument, NULL, 'z'},
{"skiproutes", required_argument, NULL, 'Z'},
#endif
#ifdef CMDLINE_COMPAT
{"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 THERE_IS_NO_FORK
char dhcpcd[PATH_MAX];
char **dhcpcd_argv = NULL;
int dhcpcd_argc = 0;
char *dhcpcd_skiproutes = NULL;
#define EXTRA_OPTS "zZ:"
#endif
#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)
{
#ifndef MINIMAL
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] <interface>\n");
#endif
}
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];
}
#ifndef MINIMAL
#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;
}
#endif
static int
parse_option(int opt, char *oarg, struct options *options)
{
int i;
char *p;
ssize_t s;
#ifndef MINIMAL
struct in_addr addr;
#endif
switch(opt) {
case 'b':
options->options |= DHCPCD_BACKGROUND;
break;
case 'c':
strlcpy(options->script, oarg, sizeof(options->script));
break;
case 'h':
#ifndef MINIMAL
if (oarg)
s = parse_string(options->hostname + 1,
MAXHOSTNAMELEN, oarg);
else
s = 0;
if (s == -1) {
logger(LOG_ERR, "hostname: %s", strerror(errno));
return -1;
}
options->hostname[0] = (uint8_t)s;
#endif
break;
case 'i':
#ifndef MINIMAL
if (oarg)
s = parse_string((char *)options->classid + 1,
CLASSID_MAX_LEN, oarg);
else
s = 0;
if (s == -1) {
logger(LOG_ERR, "classid: %s", strerror(errno));
return -1;
}
*options->classid = (uint8_t)s;
#endif
break;
case 'l':
#ifndef MINIMAL
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;
}
#endif
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_reqmask(options->reqmask, &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':
#ifndef MINIMAL
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;
}
#endif
break;
case 'v':
#ifndef MINIMAL
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;
}
#endif
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':
#ifndef MINIMAL
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 {
logger(LOG_ERR, "invalid value `%s' for FQDN",
oarg);
return -1;
}
#endif
break;
case 'G':
options->options &= ~DHCPCD_GATEWAY;
break;
case 'I':
#ifndef MINIMAL
/* Strings have a type of 0 */;
options->classid[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;
}
#endif
break;
case 'K':
options->options &= ~DHCPCD_LINK;
break;
case 'L':
options->options &= ~DHCPCD_IPV4LL;
break;
case 'O':
if (make_reqmask(options->reqmask, &optarg, -1) != 0 ||
make_reqmask(options->nomask, &optarg, 1) != 0)
{
logger(LOG_ERR, "unknown option `%s'", optarg);
return -1;
}
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;
}
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;
#ifdef THERE_IS_NO_FORK
char argvp[PATH_MAX];
char *path, *token;
struct stat sb;
#endif
closefrom(3);
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->classid[0] = snprintf((char *)options->classid + 1, CLASSID_MAX_LEN,
"%s %s", PACKAGE, VERSION);
#ifdef CMDLINE_COMPAT
add_reqmask(options->reqmask, DHCP_DNSSERVER);
add_reqmask(options->reqmask, DHCP_DNSDOMAIN);
add_reqmask(options->reqmask, DHCP_DNSSEARCH);
add_reqmask(options->reqmask, DHCP_NISSERVER);
add_reqmask(options->reqmask, DHCP_NISDOMAIN);
add_reqmask(options->reqmask, DHCP_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
#ifdef THERE_IS_NO_FORK
dhcpcd_argv = argv;
dhcpcd_argc = argc;
if (*argv[0] == '/' || *argv[0] == '.')
strncpy(argvp, argv[0], sizeof(argvp));
else {
p = path = xstrdup(getenv("PATH"));
while ((token = strsep(&p, ":"))) {
snprintf(argvp, sizeof(argvp), "%s/%s", token, argv[0]);
if (stat(argvp, &sb) == 0)
break;
}
free(path);
}
if (!realpath(argvp, dhcpcd)) {
logger(LOG_ERR, "unable to resolve the path `%s': %s\n",
argv[0], strerror(errno));
goto abort;
}
#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;
#ifdef THERE_IS_NO_FORK
case 'z':
options->options |= DHCPCD_DAEMONISED;
close_fds();
break;
case 'Z':
dhcpcd_skiproutes = xstrdup(optarg);
break;
#endif
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_reqmask(options->reqmask, DHCP_MTU);
break;
case 'N':
del_reqmask(options->reqmask, DHCP_NTPSERVER);
break;
case 'R':
del_reqmask(options->reqmask, DHCP_DNSSERVER);
del_reqmask(options->reqmask, DHCP_DNSDOMAIN);
del_reqmask(options->reqmask, DHCP_DNSSEARCH);
break;
case 'S':
add_reqmask(options->reqmask, DHCP_MSCSR);
break;
case 'Y':
del_reqmask(options->reqmask, DHCP_NISSERVER);
del_reqmask(options->reqmask, DHCP_NISDOMAIN);
break;
#endif
default:
i = parse_option(opt, optarg, options);
if (i == 1)
break;
if (i == 0)
usage();
goto abort;
}
}
if ((p = strchr(options->hostname, '.'))) {
if (options->fqdn == FQDN_DISABLE)
*p = '\0';
} else {
if (options->fqdn != FQDN_DISABLE) {
logger(LOG_WARNING, "hostname `%s' is not a FQDN",
options->hostname);
options->fqdn = FQDN_DISABLE;
}
}
if (options->fqdn != FQDN_DISABLE)
del_reqmask(options->reqmask, DHCP_HOSTNAME);
if (options->request_address.s_addr == 0 &&
(options->options & DHCPCD_INFORM ||
options->options & DHCPCD_REQUEST))
{
if (get_address(options->interface,
&options->request_address,
&options->request_netmask) != 1)
{
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;
}
if (geteuid())
logger(LOG_WARNING, PACKAGE " will not work correctly unless"
" run as root");
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);
chdir("/");
umask(022);
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;
}
}
if (sig != 0 && !(options->options & DHCPCD_DAEMONISED)) {
i = -1;
pid = read_pid(options->pidfile);
if (pid != 0)
logger(LOG_INFO, "sending signal %d to pid %d",
sig, pid);
if (!pid || (i = kill(pid, sig))) {
logger(sig == SIGALRM ? LOG_INFO : LOG_ERR,
""PACKAGE" not running");
unlink(options->pidfile);
}
if (i == 0) {
retval = EXIT_SUCCESS;
goto abort;
}
if (sig != SIGALRM)
goto abort;
}
if (!(options->options & DHCPCD_TEST) &&
!(options->options & DHCPCD_DAEMONISED))
{
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;
}
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;
writepid(pid_fd, getpid());
logger(LOG_INFO, PACKAGE " " VERSION " starting");
}
/* Terminate the encapsulated options */
if (options->vendor[0]) {
options->vendor[0]++;
options->vendor[options->vendor[0]] = DHCP_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);
#ifdef THERE_IS_NO_FORK
/* There may have been an error before the dhcp_run function
* clears this, so just do it here to be safe */
free(dhcpcd_skiproutes);
#endif
exit(retval);
/* NOTREACHED */
}

13
external/bsd/dhcpcd/dist/dhcpcd.conf vendored Normal file
View File

@ -0,0 +1,13 @@
# 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

View File

@ -0,0 +1,142 @@
.\" 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 Jun 30, 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 classid Ar string
Change the default classid sent from dhcpcd-version.
If not set then none is sent.
.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.
.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 nowait
Don't wait to obtain a DHCP lease, fork to the background right away.
.It Ic option Ar dhcp-option
Requests the
.Ar dhcp-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 seperated by commas, spaces or more option 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 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"
.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

97
external/bsd/dhcpcd/dist/dhcpcd.h vendored Normal file
View File

@ -0,0 +1,97 @@
/*
* 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 CLASSID_MAX_LEN 48
#define CLIENTID_MAX_LEN 48
#define USERCLASS_MAX_LEN 255
#define VENDOR_MAX_LEN 255
#ifdef THERE_IS_NO_FORK
extern char dhcpcd[PATH_MAX];
extern char **dhcpcd_argv;
extern int dhcpcd_argc;
extern char *dhcpcd_skiproutes;
#endif
#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 reqmask[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[MAXHOSTNAMELEN];
int fqdn;
uint8_t classid[CLASSID_MAX_LEN + 1];
char clientid[CLIENTID_MAX_LEN + 1];
uint8_t userclass[USERCLASS_MAX_LEN + 1];
uint8_t vendor[VENDOR_MAX_LEN + 1];
};
#endif

241
external/bsd/dhcpcd/dist/if-bsd.c vendored Normal file
View File

@ -0,0 +1,241 @@
/*
* 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;
}

118
external/bsd/dhcpcd/dist/logger.c vendored Normal file
View File

@ -0,0 +1,118 @@
/*
* 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};
struct logname {
int level;
const char *name;
};
static const struct logname const lognames[] = {
{ LOG_DEBUG, "debug" },
{ LOG_INFO, "info" },
{ LOG_WARNING, "warning" },
{ LOG_ERR, "error" },
{ -1, NULL }
};
int
logtolevel(const char *priority)
{
const struct logname *lt;
if (isdigit((unsigned char)*priority))
return atoi(priority);
for (lt = lognames; lt->name; lt++)
if (!strcasecmp(priority, lt->name))
return lt->level;
return -1;
}
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);
/* stdout, stderr may be re-directed to some kind of buffer.
* So we always flush to ensure it's written. */
fflush(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);
}

44
external/bsd/dhcpcd/dist/logger.h vendored Normal file
View File

@ -0,0 +1,44 @@
/*
* 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>
int logtolevel(const char *);
void setloglevel(int);
void setlogprefix(const char *);
void logger(int, const char *, ...) _PRINTF_LIKE (2, 3);
#endif

693
external/bsd/dhcpcd/dist/net.c vendored Normal file
View File

@ -0,0 +1,693 @@
/*
* 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 <poll.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;
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;
#ifdef AF_LINK
if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
memcpy(&sdl, &ifr->ifr_addr, sizeof(sdl));
*hwlen = sdl.sdl_alen;
memcpy(hwaddr, sdl.sdl_data + sdl.sdl_nlen,
(size_t)sdl.sdl_alen);
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;
}
}
}
}
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 = 1;
if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
goto eexit;
/* As we don't actually use this socket for anything, set
* the receiver buffer to 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;
}

176
external/bsd/dhcpcd/dist/net.h vendored Normal file
View File

@ -0,0 +1,176 @@
/*
* 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

126
external/bsd/dhcpcd/dist/signals.c vendored Normal file
View File

@ -0,0 +1,126 @@
/*
* 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 <poll.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);
}

39
external/bsd/dhcpcd/dist/signals.h vendored Normal file
View File

@ -0,0 +1,39 @@
/*
* 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
#include <poll.h>
int signal_init(void);
int signal_setup(void);
int signal_reset(void);
int signal_fd(void);
int signal_read(void);
#endif