Import dhcpcd-5.0.0
Major changes from dhcpcd-4 include * Single daemon can now run DHCP on multiple interfaces at the same time * Configuration profiles per interface, ssid, arping and fallback * Listens to 3rd party programs changing routing information * Supports DHCP INFORM over PPP * Can configure static options for destination address * Control socket so 3rd party program can control or listen directly to dhcpcd events * Is also a BOOTP client
This commit is contained in:
parent
a82ec647f5
commit
2158200f72
38
external/bsd/dhcpcd/dist/README
vendored
38
external/bsd/dhcpcd/dist/README
vendored
@ -1,12 +1,13 @@
|
||||
dhcpcd-4 - DHCP client daemon
|
||||
Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
dhcpcd - DHCP client daemon
|
||||
Copyright 2006-2009 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
|
||||
man dhcpcd.conf for configuration options
|
||||
man dhcpcd-run-hooks to learn how to hook scripts into dhcpcd events
|
||||
|
||||
|
||||
Notes
|
||||
@ -32,6 +33,12 @@ 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.
|
||||
|
||||
Some BSD systems do not allow the manipulation of automatically added subnet
|
||||
routes. You can find discussion here:
|
||||
http://mail-index.netbsd.org/tech-net/2008/12/03/msg000896.html
|
||||
BSD systems where this has been fixed are:
|
||||
NetBSD-5.99.6
|
||||
|
||||
|
||||
Hooks
|
||||
-----
|
||||
@ -43,28 +50,13 @@ 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-5.0 is only fully command line compatible with dhcpcd-4.0
|
||||
For compatibility with older versions, use dhcpcd-4.0
|
||||
|
||||
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 no longer sends a default ClientID for ethernet interfaces.
|
||||
This is so we can re-use the address the kernel DHCP client found.
|
||||
To retain the old behaviour of sending a default ClientID based on the
|
||||
dhcpcd no longer sends a default ClientID for ethernet interfaces.
|
||||
This is so we can re-use the address the kernel DHCP client found.
|
||||
To retain the old behaviour of sending a default ClientID based on the
|
||||
hardware address for interface, simply add the keyword clientid to dhcpcd.conf.
|
||||
If CMDLINE_COMPAT is defined, we renable the sending of ClientID by default
|
||||
AND adding clientid to dhcpcd.conf causes it NOT to be sent.
|
||||
|
||||
dhcpcd-4 is NOT fully commandline compatible with dhcpcd-2 and older and
|
||||
changes the meaning of some options.
|
||||
|
||||
|
||||
ChangeLog
|
||||
|
300
external/bsd/dhcpcd/dist/arp.c
vendored
Normal file
300
external/bsd/dhcpcd/dist/arp.c
vendored
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "arp.h"
|
||||
#include "bind.h"
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "eloop.h"
|
||||
#include "if-options.h"
|
||||
#include "ipv4ll.h"
|
||||
#include "net.h"
|
||||
|
||||
#define ARP_LEN \
|
||||
(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
|
||||
|
||||
static int
|
||||
send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip)
|
||||
{
|
||||
uint8_t arp_buffer[ARP_LEN];
|
||||
struct arphdr ar;
|
||||
size_t len;
|
||||
uint8_t *p;
|
||||
int retval;
|
||||
|
||||
ar.ar_hrd = htons(iface->family);
|
||||
ar.ar_pro = htons(ETHERTYPE_IP);
|
||||
ar.ar_hln = iface->hwlen;
|
||||
ar.ar_pln = sizeof(sip);
|
||||
ar.ar_op = htons(op);
|
||||
memcpy(arp_buffer, &ar, sizeof(ar));
|
||||
p = arp_buffer + sizeof(ar);
|
||||
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);
|
||||
len = p - arp_buffer;
|
||||
retval = send_raw_packet(iface, ETHERTYPE_ARP, arp_buffer, len);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_arp_failure(struct interface *iface)
|
||||
{
|
||||
if (IN_LINKLOCAL(htonl(iface->state->fail.s_addr))) {
|
||||
handle_ipv4ll_failure(iface);
|
||||
return;
|
||||
}
|
||||
if (iface->state->lease.frominfo)
|
||||
unlink(iface->leasefile);
|
||||
else
|
||||
send_decline(iface);
|
||||
close_sockets(iface);
|
||||
delete_timeout(NULL, iface);
|
||||
if (iface->state->lease.frominfo)
|
||||
start_interface(iface);
|
||||
else
|
||||
add_timeout_sec(DHCP_ARP_FAIL, start_interface, iface);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_arp_packet(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
uint8_t arp_buffer[ARP_LEN];
|
||||
struct arphdr ar;
|
||||
uint32_t reply_s;
|
||||
uint32_t reply_t;
|
||||
uint8_t *hw_s, *hw_t;
|
||||
ssize_t bytes;
|
||||
struct if_state *state = iface->state;
|
||||
struct if_options *opts = state->options;
|
||||
const char *hwaddr;
|
||||
struct in_addr ina;
|
||||
|
||||
state->fail.s_addr = 0;
|
||||
for(;;) {
|
||||
bytes = get_raw_packet(iface, ETHERTYPE_ARP,
|
||||
arp_buffer, sizeof(arp_buffer));
|
||||
if (bytes == 0 || bytes == -1)
|
||||
return;
|
||||
/* We must have a full ARP header */
|
||||
if ((size_t)bytes < sizeof(ar))
|
||||
continue;
|
||||
memcpy(&ar, arp_buffer, sizeof(ar));
|
||||
/* Protocol must be IP. */
|
||||
if (ar.ar_pro != htons(ETHERTYPE_IP))
|
||||
continue;
|
||||
if (ar.ar_pln != sizeof(reply_s))
|
||||
continue;
|
||||
/* Only these types are recognised */
|
||||
if (ar.ar_op != htons(ARPOP_REPLY) &&
|
||||
ar.ar_op != htons(ARPOP_REQUEST))
|
||||
continue;
|
||||
|
||||
/* Get pointers to the hardware addreses */
|
||||
hw_s = arp_buffer + sizeof(ar);
|
||||
hw_t = hw_s + ar.ar_hln + ar.ar_pln;
|
||||
/* Ensure we got all the data */
|
||||
if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
|
||||
continue;
|
||||
/* Ignore messages from ourself */
|
||||
if (ar.ar_hln == iface->hwlen &&
|
||||
memcmp(hw_s, iface->hwaddr, iface->hwlen) == 0)
|
||||
continue;
|
||||
/* Copy out the IP addresses */
|
||||
memcpy(&reply_s, hw_s + ar.ar_hln, ar.ar_pln);
|
||||
memcpy(&reply_t, hw_t + ar.ar_hln, ar.ar_pln);
|
||||
|
||||
/* Check for arping */
|
||||
if (state->arping_index &&
|
||||
state->arping_index <= opts->arping_len &&
|
||||
(reply_s == opts->arping[state->arping_index - 1] ||
|
||||
(reply_s == 0 &&
|
||||
reply_t == opts->arping[state->arping_index - 1])))
|
||||
{
|
||||
ina.s_addr = reply_s;
|
||||
hwaddr = hwaddr_ntoa((unsigned char *)hw_s,
|
||||
(size_t)ar.ar_hln);
|
||||
syslog(LOG_INFO,
|
||||
"%s: found %s on hardware address %s",
|
||||
iface->name, inet_ntoa(ina), hwaddr);
|
||||
if (select_profile(iface, hwaddr) == -1 &&
|
||||
errno == ENOENT)
|
||||
select_profile(iface, inet_ntoa(ina));
|
||||
close_sockets(iface);
|
||||
delete_timeout(NULL, iface);
|
||||
start_interface(iface);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check for conflict */
|
||||
if (state->offer &&
|
||||
(reply_s == state->offer->yiaddr ||
|
||||
(reply_s == 0 && reply_t == state->offer->yiaddr)))
|
||||
state->fail.s_addr = state->offer->yiaddr;
|
||||
|
||||
/* Handle IPv4LL conflicts */
|
||||
if (IN_LINKLOCAL(htonl(iface->addr.s_addr)) &&
|
||||
(reply_s == iface->addr.s_addr ||
|
||||
(reply_s == 0 && reply_t == iface->addr.s_addr)))
|
||||
state->fail.s_addr = iface->addr.s_addr;
|
||||
|
||||
if (state->fail.s_addr) {
|
||||
syslog(LOG_ERR, "%s: hardware address %s claims %s",
|
||||
iface->name,
|
||||
hwaddr_ntoa((unsigned char *)hw_s,
|
||||
(size_t)ar.ar_hln),
|
||||
inet_ntoa(state->fail));
|
||||
errno = EEXIST;
|
||||
handle_arp_failure(iface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
send_arp_announce(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
struct if_state *state = iface->state;
|
||||
struct timeval tv;
|
||||
|
||||
if (iface->arp_fd == -1) {
|
||||
open_socket(iface, ETHERTYPE_ARP);
|
||||
add_event(iface->arp_fd, handle_arp_packet, iface);
|
||||
}
|
||||
if (++state->claims < ANNOUNCE_NUM)
|
||||
syslog(LOG_DEBUG,
|
||||
"%s: sending ARP announce (%d of %d), "
|
||||
"next in %d.00 seconds",
|
||||
iface->name, state->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT);
|
||||
else
|
||||
syslog(LOG_DEBUG,
|
||||
"%s: sending ARP announce (%d of %d)",
|
||||
iface->name, state->claims, ANNOUNCE_NUM);
|
||||
if (send_arp(iface, ARPOP_REQUEST,
|
||||
state->new->yiaddr, state->new->yiaddr) == -1)
|
||||
syslog(LOG_ERR, "send_arp: %m");
|
||||
if (state->claims < ANNOUNCE_NUM) {
|
||||
add_timeout_sec(ANNOUNCE_WAIT, send_arp_announce, iface);
|
||||
return;
|
||||
}
|
||||
if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
|
||||
/* We should pretend to be at the end
|
||||
* of the DHCP negotation cycle unless we rebooted */
|
||||
if (state->interval != 0)
|
||||
state->interval = 64;
|
||||
state->probes = 0;
|
||||
state->claims = 0;
|
||||
tv.tv_sec = state->interval - DHCP_RAND_MIN;
|
||||
tv.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U);
|
||||
timernorm(&tv);
|
||||
add_timeout_tv(&tv, start_discover, iface);
|
||||
} else {
|
||||
delete_event(iface->arp_fd);
|
||||
close(iface->arp_fd);
|
||||
iface->arp_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
send_arp_probe(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
struct if_state *state = iface->state;
|
||||
struct in_addr addr;
|
||||
struct timeval tv;
|
||||
int arping = 0;
|
||||
|
||||
if (state->arping_index < state->options->arping_len) {
|
||||
addr.s_addr = state->options->arping[state->arping_index];
|
||||
arping = 1;
|
||||
} else if (state->offer) {
|
||||
if (state->offer->yiaddr)
|
||||
addr.s_addr = state->offer->yiaddr;
|
||||
else
|
||||
addr.s_addr = state->offer->ciaddr;
|
||||
} else
|
||||
addr.s_addr = iface->addr.s_addr;
|
||||
|
||||
if (iface->arp_fd == -1) {
|
||||
open_socket(iface, ETHERTYPE_ARP);
|
||||
add_event(iface->arp_fd, handle_arp_packet, iface);
|
||||
}
|
||||
if (state->probes == 0) {
|
||||
if (arping)
|
||||
syslog(LOG_INFO, "%s: searching for %s",
|
||||
iface->name, inet_ntoa(addr));
|
||||
else
|
||||
syslog(LOG_INFO, "%s: checking for %s",
|
||||
iface->name, inet_ntoa(addr));
|
||||
}
|
||||
if (++state->probes < PROBE_NUM) {
|
||||
tv.tv_sec = PROBE_MIN;
|
||||
tv.tv_usec = arc4random() % (PROBE_MAX_U - PROBE_MIN_U);
|
||||
timernorm(&tv);
|
||||
add_timeout_tv(&tv, send_arp_probe, iface);
|
||||
} else {
|
||||
tv.tv_sec = ANNOUNCE_WAIT;
|
||||
tv.tv_usec = 0;
|
||||
if (arping) {
|
||||
state->probes = 0;
|
||||
if (++state->arping_index < state->options->arping_len)
|
||||
add_timeout_tv(&tv, send_arp_probe, iface);
|
||||
else
|
||||
add_timeout_tv(&tv, start_interface, iface);
|
||||
} else
|
||||
add_timeout_tv(&tv, bind_interface, iface);
|
||||
}
|
||||
syslog(LOG_DEBUG,
|
||||
"%s: sending ARP probe (%d of %d), next in %0.2f seconds",
|
||||
iface->name, state->probes ? state->probes : PROBE_NUM, PROBE_NUM,
|
||||
timeval_to_double(&tv));
|
||||
if (send_arp(iface, ARPOP_REQUEST, 0, addr.s_addr) == -1)
|
||||
syslog(LOG_ERR, "send_arp: %m");
|
||||
}
|
||||
|
||||
void
|
||||
start_arping(struct interface *iface)
|
||||
{
|
||||
iface->state->probes = 0;
|
||||
iface->state->arping_index = 0;
|
||||
send_arp_probe(iface);
|
||||
}
|
49
external/bsd/dhcpcd/dist/arp.h
vendored
Normal file
49
external/bsd/dhcpcd/dist/arp.h
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 ARP_H
|
||||
#define ARP_H
|
||||
|
||||
/* These are for IPV4LL, RFC 3927.
|
||||
* We put them here as we use the timings for all ARP foo. */
|
||||
#define PROBE_WAIT 1
|
||||
#define PROBE_NUM 3
|
||||
#define PROBE_MIN 1
|
||||
#define PROBE_MAX 2
|
||||
#define ANNOUNCE_WAIT 2
|
||||
#define ANNOUNCE_NUM 2
|
||||
#define ANNOUNCE_INTERVAL 2
|
||||
#define MAX_CONFLICTS 10
|
||||
#define RATE_LIMIT_INTERVAL 60
|
||||
#define DEFEND_INTERVAL 10
|
||||
|
||||
#include "dhcpcd.h"
|
||||
|
||||
void send_arp_announce(void *);
|
||||
void send_arp_probe(void *);
|
||||
void start_arping(struct interface *);
|
||||
#endif
|
221
external/bsd/dhcpcd/dist/bind.c
vendored
Normal file
221
external/bsd/dhcpcd/dist/bind.c
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2009 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 <fcntl.h>
|
||||
#ifdef BSD
|
||||
# include <paths.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "arp.h"
|
||||
#include "bind.h"
|
||||
#include "common.h"
|
||||
#include "configure.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "eloop.h"
|
||||
#include "if-options.h"
|
||||
#include "net.h"
|
||||
#include "signals.h"
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
# define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
#ifndef THERE_IS_NO_FORK
|
||||
pid_t
|
||||
daemonise(void)
|
||||
{
|
||||
pid_t pid;
|
||||
sigset_t full;
|
||||
sigset_t old;
|
||||
char buf = '\0';
|
||||
int sidpipe[2], fd;
|
||||
|
||||
if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE))
|
||||
return 0;
|
||||
sigfillset(&full);
|
||||
sigprocmask(SIG_SETMASK, &full, &old);
|
||||
/* Setup a signal pipe so parent knows when to exit. */
|
||||
if (pipe(sidpipe) == -1) {
|
||||
syslog(LOG_ERR, "pipe: %m");
|
||||
return -1;
|
||||
}
|
||||
syslog(LOG_INFO, "forking to background");
|
||||
switch (pid = fork()) {
|
||||
case -1:
|
||||
syslog(LOG_ERR, "fork: %m");
|
||||
exit(EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
case 0:
|
||||
setsid();
|
||||
/* Notify parent it's safe to exit as we've detached. */
|
||||
close(sidpipe[0]);
|
||||
if (write(sidpipe[1], &buf, 1) == -1)
|
||||
syslog(LOG_ERR, "failed to notify parent: %m");
|
||||
close(sidpipe[1]);
|
||||
if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
|
||||
dup2(fd, STDIN_FILENO);
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
if (fd > STDERR_FILENO)
|
||||
close(fd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
signal_reset();
|
||||
/* Wait for child to detach */
|
||||
close(sidpipe[1]);
|
||||
if (read(sidpipe[0], &buf, 1) == -1)
|
||||
syslog(LOG_ERR, "failed to read child: %m");
|
||||
close(sidpipe[0]);
|
||||
break;
|
||||
}
|
||||
/* Done with the fd now */
|
||||
if (pid != 0) {
|
||||
writepid(pidfd, pid);
|
||||
close(pidfd);
|
||||
pidfd = -1;
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
options |= DHCPCD_DAEMONISED;
|
||||
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||
return pid;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
bind_interface(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
struct if_state *state = iface->state;
|
||||
struct if_options *ifo = state->options;
|
||||
struct dhcp_lease *lease = &state->lease;
|
||||
struct timeval tv;
|
||||
|
||||
/* We're binding an address now - ensure that sockets are closed */
|
||||
close_sockets(iface);
|
||||
state->reason = NULL;
|
||||
delete_timeout(handle_exit_timeout, NULL);
|
||||
if (clock_monotonic)
|
||||
get_monotonic(&lease->boundtime);
|
||||
state->xid = 0;
|
||||
free(state->old);
|
||||
state->old = state->new;
|
||||
state->new = state->offer;
|
||||
state->offer = NULL;
|
||||
get_lease(lease, state->new);
|
||||
if (ifo->options & DHCPCD_STATIC) {
|
||||
syslog(LOG_INFO, "%s: using static address %s",
|
||||
iface->name, inet_ntoa(lease->addr));
|
||||
lease->leasetime = ~0U;
|
||||
lease->net.s_addr = ifo->req_mask.s_addr;
|
||||
state->reason = "STATIC";
|
||||
} else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
|
||||
syslog(LOG_INFO, "%s: using IPv4LL address %s",
|
||||
iface->name, inet_ntoa(lease->addr));
|
||||
lease->leasetime = ~0U;
|
||||
state->reason = "IPV4LL";
|
||||
} else if (ifo->options & DHCPCD_INFORM) {
|
||||
if (ifo->req_addr.s_addr != 0)
|
||||
lease->addr.s_addr = ifo->req_addr.s_addr;
|
||||
else
|
||||
lease->addr.s_addr = iface->addr.s_addr;
|
||||
syslog(LOG_INFO, "%s: received approval for %s", iface->name,
|
||||
inet_ntoa(lease->addr));
|
||||
lease->leasetime = ~0U;
|
||||
state->reason = "INFORM";
|
||||
} else {
|
||||
if (gettimeofday(&tv, NULL) == 0)
|
||||
lease->leasedfrom = tv.tv_sec;
|
||||
else if (lease->frominfo)
|
||||
state->reason = "TIMEOUT";
|
||||
if (lease->leasetime == ~0U) {
|
||||
lease->renewaltime =
|
||||
lease->rebindtime =
|
||||
lease->leasetime;
|
||||
syslog(LOG_INFO, "%s: leased %s for infinity",
|
||||
iface->name, inet_ntoa(lease->addr));
|
||||
} else {
|
||||
if (lease->rebindtime == 0)
|
||||
lease->rebindtime = lease->leasetime * T2;
|
||||
else if (lease->rebindtime >= lease->leasetime) {
|
||||
lease->rebindtime = lease->leasetime * T2;
|
||||
syslog(LOG_ERR,
|
||||
"%s: rebind time greater than lease "
|
||||
"time, forcing to %u seconds",
|
||||
iface->name, lease->rebindtime);
|
||||
}
|
||||
if (lease->renewaltime == 0)
|
||||
lease->renewaltime = lease->leasetime * T1;
|
||||
else if (lease->renewaltime > lease->rebindtime) {
|
||||
lease->renewaltime = lease->leasetime * T1;
|
||||
syslog(LOG_ERR,
|
||||
"%s: renewal time greater than rebind "
|
||||
"time, forcing to %u seconds",
|
||||
iface->name, lease->renewaltime);
|
||||
}
|
||||
syslog(LOG_INFO,
|
||||
"%s: leased %s for %u seconds", iface->name,
|
||||
inet_ntoa(lease->addr), lease->leasetime);
|
||||
}
|
||||
}
|
||||
if (options & DHCPCD_TEST) {
|
||||
state->reason = "TEST";
|
||||
run_script(iface);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (state->reason == NULL) {
|
||||
if (state->old) {
|
||||
if (state->old->yiaddr == state->new->yiaddr &&
|
||||
lease->server.s_addr)
|
||||
state->reason = "RENEW";
|
||||
else
|
||||
state->reason = "REBIND";
|
||||
} else if (state->state == DHS_REBOOT)
|
||||
state->reason = "REBOOT";
|
||||
else
|
||||
state->reason = "BOUND";
|
||||
}
|
||||
if (lease->leasetime == ~0U)
|
||||
lease->renewaltime = lease->rebindtime = lease->leasetime;
|
||||
else {
|
||||
add_timeout_sec(lease->renewaltime, start_renew, iface);
|
||||
add_timeout_sec(lease->rebindtime, start_rebind, iface);
|
||||
add_timeout_sec(lease->leasetime, start_expire, iface);
|
||||
}
|
||||
configure(iface);
|
||||
daemonise();
|
||||
state->state = DHS_BOUND;
|
||||
if (ifo->options & DHCPCD_ARP) {
|
||||
state->claims = 0;
|
||||
send_arp_announce(iface);
|
||||
}
|
||||
}
|
39
external/bsd/dhcpcd/dist/bind.h
vendored
Normal file
39
external/bsd/dhcpcd/dist/bind.h
vendored
Normal 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 BIND_H
|
||||
#define BIND_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef THERE_IS_NO_FORK
|
||||
# define daemonise() {}
|
||||
#else
|
||||
pid_t daemonise(void);
|
||||
#endif
|
||||
|
||||
void bind_interface(void *);
|
||||
#endif
|
12
external/bsd/dhcpcd/dist/bpf.c
vendored
12
external/bsd/dhcpcd/dist/bpf.c
vendored
@ -39,12 +39,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "dhcp.h"
|
||||
#include "logger.h"
|
||||
#include "net.h"
|
||||
#include "bpf-filter.h"
|
||||
|
||||
@ -81,7 +81,7 @@ open_socket(struct interface *iface, int protocol)
|
||||
goto eexit;
|
||||
if (pv.bv_major != BPF_MAJOR_VERSION ||
|
||||
pv.bv_minor < BPF_MINOR_VERSION) {
|
||||
logger(LOG_ERR, "BPF version mismatch - recompile " PACKAGE);
|
||||
syslog(LOG_ERR, "BPF version mismatch - recompile");
|
||||
goto eexit;
|
||||
}
|
||||
|
||||
@ -136,7 +136,7 @@ eexit:
|
||||
|
||||
ssize_t
|
||||
send_raw_packet(const struct interface *iface, int protocol,
|
||||
const void *data, ssize_t len)
|
||||
const void *data, ssize_t len)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
struct ether_header hw;
|
||||
@ -160,7 +160,7 @@ send_raw_packet(const struct interface *iface, int protocol,
|
||||
* 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)
|
||||
void *data, ssize_t len)
|
||||
{
|
||||
int fd = -1;
|
||||
struct bpf_hdr packet;
|
||||
@ -184,7 +184,7 @@ get_raw_packet(struct interface *iface, int protocol,
|
||||
}
|
||||
bytes = -1;
|
||||
memcpy(&packet, iface->buffer + iface->buffer_pos,
|
||||
sizeof(packet));
|
||||
sizeof(packet));
|
||||
if (packet.bh_caplen != packet.bh_datalen)
|
||||
goto next; /* Incomplete packet, drop. */
|
||||
if (iface->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
|
||||
@ -197,7 +197,7 @@ get_raw_packet(struct interface *iface, int protocol,
|
||||
memcpy(data, payload, bytes);
|
||||
next:
|
||||
iface->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
|
||||
packet.bh_caplen);
|
||||
packet.bh_caplen);
|
||||
if (iface->buffer_pos >= iface->buffer_len)
|
||||
iface->buffer_len = iface->buffer_pos = 0;
|
||||
if (bytes != -1)
|
||||
|
124
external/bsd/dhcpcd/dist/common.c
vendored
124
external/bsd/dhcpcd/dist/common.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,6 +25,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
# include <mach/mach_time.h>
|
||||
# include <mach/kern_return.h>
|
||||
@ -33,7 +35,6 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef BSD
|
||||
# include <paths.h>
|
||||
@ -42,42 +43,76 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
# define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
int clock_monotonic = 0;
|
||||
int clock_monotonic;
|
||||
static char *lbuf;
|
||||
static size_t lbuf_len;
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
static void
|
||||
free_lbuf(void)
|
||||
{
|
||||
free(lbuf);
|
||||
}
|
||||
#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)
|
||||
* This means we read the whole line and avoid any nasty buffer overflows.
|
||||
* We strip leading space and avoid comment lines, making the code that calls
|
||||
* us smaller.
|
||||
* As we don't use threads, this API is clean too. */
|
||||
char *
|
||||
get_line(FILE * __restrict fp)
|
||||
{
|
||||
char *p;
|
||||
size_t last = 0;
|
||||
char *p, *e;
|
||||
size_t last;
|
||||
|
||||
while(!feof(fp)) {
|
||||
if (*line == NULL || last != 0) {
|
||||
*len += BUFSIZ;
|
||||
*line = xrealloc(*line, *len);
|
||||
again:
|
||||
if (feof(fp))
|
||||
return NULL;
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
if (lbuf == NULL)
|
||||
atexit(free_lbuf);
|
||||
#endif
|
||||
|
||||
last = 0;
|
||||
do {
|
||||
if (lbuf == NULL || last != 0) {
|
||||
lbuf_len += BUFSIZ;
|
||||
lbuf = xrealloc(lbuf, lbuf_len);
|
||||
}
|
||||
p = *line + last;
|
||||
p = lbuf + last;
|
||||
memset(p, 0, BUFSIZ);
|
||||
if (fgets(p, BUFSIZ, fp) == NULL)
|
||||
break;
|
||||
last += strlen(p);
|
||||
if (last && (*line)[last - 1] == '\n') {
|
||||
(*line)[last - 1] = '\0';
|
||||
if (last != 0 && lbuf[last - 1] == '\n') {
|
||||
lbuf[last - 1] = '\0';
|
||||
break;
|
||||
}
|
||||
} while(!feof(fp));
|
||||
if (last == 0)
|
||||
return NULL;
|
||||
|
||||
e = p + last - 1;
|
||||
for (p = lbuf; p < e; p++) {
|
||||
if (*p != ' ' && *p != '\t')
|
||||
break;
|
||||
}
|
||||
return last;
|
||||
if (p == e || *p == '#' || *p == ';')
|
||||
goto again;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Simple hack to return a random number without arc4random */
|
||||
@ -85,9 +120,9 @@ get_line(char **line, size_t *len, FILE *fp)
|
||||
uint32_t arc4random(void)
|
||||
{
|
||||
int fd;
|
||||
static unsigned long seed = 0;
|
||||
static unsigned long seed;
|
||||
|
||||
if (!seed) {
|
||||
if (seed == 0) {
|
||||
fd = open("/dev/urandom", 0);
|
||||
if (fd == -1 || read(fd, &seed, sizeof(seed)) == -1)
|
||||
seed = time(0);
|
||||
@ -140,32 +175,15 @@ closefrom(int fd)
|
||||
}
|
||||
#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)
|
||||
if ((flags = fcntl(fd, F_GETFD, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
{
|
||||
logger(LOG_ERR, "fcntl: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "fcntl: %m");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -176,10 +194,10 @@ set_nonblock(int fd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1
|
||||
|| fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
logger(LOG_ERR, "fcntl: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "fcntl: %m");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@ -199,7 +217,7 @@ get_monotonic(struct timeval *tp)
|
||||
struct timespec ts;
|
||||
static clockid_t posix_clock;
|
||||
|
||||
if (posix_clock_set == 0) {
|
||||
if (!posix_clock_set) {
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||
posix_clock = CLOCK_MONOTONIC;
|
||||
clock_monotonic = posix_clock_set = 1;
|
||||
@ -222,7 +240,7 @@ get_monotonic(struct timeval *tp)
|
||||
uint64_t nano;
|
||||
long rem;
|
||||
|
||||
if (posix_clock_set == 0) {
|
||||
if (!posix_clock_set) {
|
||||
if (mach_timebase_info(&info) == KERN_SUCCESS) {
|
||||
factor = (double)info.numer / (double)info.denom;
|
||||
clock_monotonic = posix_clock_set = 1;
|
||||
@ -245,7 +263,7 @@ get_monotonic(struct timeval *tp)
|
||||
|
||||
/* Something above failed, so fall back to gettimeofday */
|
||||
if (!posix_clock_set) {
|
||||
logger(LOG_WARNING, NO_MONOTONIC);
|
||||
syslog(LOG_WARNING, NO_MONOTONIC);
|
||||
posix_clock_set = 1;
|
||||
}
|
||||
return gettimeofday(tp, NULL);
|
||||
@ -281,9 +299,9 @@ xmalloc(size_t s)
|
||||
{
|
||||
void *value = malloc(s);
|
||||
|
||||
if (value)
|
||||
if (value != NULL)
|
||||
return value;
|
||||
logger(LOG_ERR, "memory exhausted");
|
||||
syslog(LOG_ERR, "memory exhausted (xalloc %zu bytes)", s);
|
||||
exit (EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@ -302,9 +320,9 @@ xrealloc(void *ptr, size_t s)
|
||||
{
|
||||
void *value = realloc(ptr, s);
|
||||
|
||||
if (value)
|
||||
return (value);
|
||||
logger(LOG_ERR, "memory exhausted");
|
||||
if (value != NULL)
|
||||
return value;
|
||||
syslog(LOG_ERR, "memory exhausted (xrealloc %zu bytes)", s);
|
||||
exit(EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@ -314,13 +332,13 @@ xstrdup(const char *str)
|
||||
{
|
||||
char *value;
|
||||
|
||||
if (!str)
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((value = strdup(str)))
|
||||
if ((value = strdup(str)) != NULL)
|
||||
return value;
|
||||
|
||||
logger(LOG_ERR, "memory exhausted");
|
||||
syslog(LOG_ERR, "memory exhausted (xstrdup)");
|
||||
exit(EXIT_FAILURE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
32
external/bsd/dhcpcd/dist/common.h
vendored
32
external/bsd/dhcpcd/dist/common.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,12 +37,37 @@
|
||||
|
||||
#define UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
|
||||
#define timeval_to_double(tv) ((tv)->tv_sec * 1.0 + (tv)->tv_usec * 1.0e-6)
|
||||
#define timernorm(tvp) \
|
||||
do { \
|
||||
while ((tvp)->tv_usec >= 1000000) { \
|
||||
(tvp)->tv_sec++; \
|
||||
(tvp)->tv_usec -= 1000000; \
|
||||
} \
|
||||
} while (0 /* CONSTCOND */);
|
||||
|
||||
#if __GNUC__ > 2 || defined(__INTEL_COMPILER)
|
||||
# define _unused __attribute__((__unused__))
|
||||
# define _noreturn __attribute__((__noreturn__))
|
||||
# define _packed __attribute__((__packed__))
|
||||
# define _unused __attribute__((__unused__))
|
||||
#else
|
||||
# define _noreturn
|
||||
# define _packed
|
||||
# define _unused
|
||||
#endif
|
||||
|
||||
/* We don't really need this as our supported systems define __restrict
|
||||
* automatically for us, but it is here for completeness. */
|
||||
#ifndef __restrict
|
||||
# if defined(__lint__)
|
||||
# define __restrict
|
||||
# elif __STDC_VERSION__ >= 199901L
|
||||
# define __restrict restrict
|
||||
# elif !(2 < __GNUC__ || (2 == __GNU_C && 95 <= __GNUC_VERSION__))
|
||||
# define __restrict
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
# ifdef __GLIBC__
|
||||
uint32_t arc4random(void);
|
||||
@ -71,10 +96,9 @@ size_t strlcpy(char *, const char *, size_t);
|
||||
int closefrom(int);
|
||||
#endif
|
||||
|
||||
int close_fds(void);
|
||||
int set_cloexec(int);
|
||||
int set_nonblock(int);
|
||||
ssize_t get_line(char **, size_t *, FILE *);
|
||||
char *get_line(FILE * __restrict);
|
||||
extern int clock_monotonic;
|
||||
int get_monotonic(struct timeval *);
|
||||
time_t uptime(void);
|
||||
|
18
external/bsd/dhcpcd/dist/config.h
vendored
18
external/bsd/dhcpcd/dist/config.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -28,16 +28,7 @@
|
||||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "4.0.13"
|
||||
|
||||
/*
|
||||
* 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
|
||||
#define VERSION "5.0.0"
|
||||
|
||||
/* Some systems do not have a working fork. */
|
||||
/* #define THERE_IS_NO_FORK */
|
||||
@ -69,7 +60,10 @@
|
||||
# define LEASEFILE DBDIR "/" PACKAGE "-%s.lease"
|
||||
#endif
|
||||
#ifndef PIDFILE
|
||||
# define PIDFILE RUNDIR "/" PACKAGE "-%s.pid"
|
||||
# define PIDFILE RUNDIR "/" PACKAGE "%s%s.pid"
|
||||
#endif
|
||||
#ifndef CONTROLSOCKET
|
||||
# define CONTROLSOCKET RUNDIR "/" PACKAGE ".sock"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
761
external/bsd/dhcpcd/dist/configure.c
vendored
761
external/bsd/dhcpcd/dist/configure.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
@ -35,19 +36,32 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "configure.h"
|
||||
#include "dhcp.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "logger.h"
|
||||
#include "if-options.h"
|
||||
#include "if-pref.h"
|
||||
#include "net.h"
|
||||
#include "signals.h"
|
||||
|
||||
#define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
|
||||
|
||||
/* Some systems have route metrics */
|
||||
#ifndef HAVE_ROUTE_METRIC
|
||||
# ifdef __linux__
|
||||
# define HAVE_ROUTE_METRIC 1
|
||||
# endif
|
||||
# ifndef HAVE_ROUTE_METRIC
|
||||
# define HAVE_ROUTE_METRIC 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
static struct rt *routes;
|
||||
|
||||
|
||||
static int
|
||||
exec_script(char *const *argv, char *const *env)
|
||||
@ -63,12 +77,12 @@ exec_script(char *const *argv, char *const *env)
|
||||
|
||||
switch (pid = vfork()) {
|
||||
case -1:
|
||||
logger(LOG_ERR, "vfork: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "vfork: %m");
|
||||
break;
|
||||
case 0:
|
||||
sigprocmask(SIG_SETMASK, &old, NULL);
|
||||
execve(argv[0], argv, env);
|
||||
logger(LOG_ERR, "%s: %s", argv[0], strerror(errno));
|
||||
syslog(LOG_ERR, "%s: %m", argv[0]);
|
||||
_exit(127);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
@ -79,70 +93,229 @@ exec_script(char *const *argv, char *const *env)
|
||||
return pid;
|
||||
}
|
||||
|
||||
int
|
||||
run_script(const struct options *options, const char *iface,
|
||||
const char *reason,
|
||||
const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
|
||||
static char *
|
||||
make_var(const char *prefix, const char *var)
|
||||
{
|
||||
char *const argv[2] = { UNCONST(options->script), NULL };
|
||||
char **env = NULL, **ep;
|
||||
char *path;
|
||||
ssize_t e, elen;
|
||||
pid_t pid;
|
||||
int status = 0;
|
||||
size_t len;
|
||||
char *v;
|
||||
|
||||
logger(LOG_DEBUG, "executing `%s', reason %s", options->script, reason);
|
||||
len = strlen(prefix) + strlen(var) + 2;
|
||||
v = xmalloc(len);
|
||||
snprintf(v, len, "%s_%s", prefix, var);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
append_config(char ***env, ssize_t *len,
|
||||
const char *prefix, const char *const *config)
|
||||
{
|
||||
ssize_t i, j, e1;
|
||||
char **ne, *eq;
|
||||
|
||||
if (config == NULL)
|
||||
return;
|
||||
|
||||
ne = *env;
|
||||
for (i = 0; config[i] != NULL; i++) {
|
||||
eq = strchr(config[i], '=');
|
||||
e1 = eq - config[i] + 1;
|
||||
for (j = 0; j < *len; j++) {
|
||||
if (strncmp(ne[j] + strlen(prefix) + 1,
|
||||
config[i], e1) == 0)
|
||||
{
|
||||
free(ne[j]);
|
||||
ne[j] = make_var(prefix, config[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == *len) {
|
||||
j++;
|
||||
ne = xrealloc(ne, sizeof(char *) * (j + 1));
|
||||
ne[j - 1] = make_var(prefix, config[i]);
|
||||
*len = j;
|
||||
}
|
||||
}
|
||||
*env = ne;
|
||||
}
|
||||
|
||||
static size_t
|
||||
arraytostr(const char *const *argv, char **s)
|
||||
{
|
||||
const char *const *ap;
|
||||
char *p;
|
||||
size_t len, l;
|
||||
|
||||
len = 0;
|
||||
ap = argv;
|
||||
while (*ap)
|
||||
len += strlen(*ap++) + 1;
|
||||
*s = p = xmalloc(len);
|
||||
ap = argv;
|
||||
while (*ap) {
|
||||
l = strlen(*ap) + 1;
|
||||
memcpy(p, *ap, l);
|
||||
p += l;
|
||||
ap++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
make_env(const struct interface *iface, char ***argv)
|
||||
{
|
||||
char **env, *p;
|
||||
ssize_t e, elen, l;
|
||||
const struct if_options *ifo = iface->state->options;
|
||||
const struct interface *ifp;
|
||||
|
||||
/* Make our env */
|
||||
elen = 5;
|
||||
elen = 7;
|
||||
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;
|
||||
e = strlen("interface") + strlen(iface->name) + 2;
|
||||
env[0] = xmalloc(e);
|
||||
snprintf(env[0], e, "interface=%s", iface->name);
|
||||
e = strlen("reason") + strlen(iface->state->reason) + 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);
|
||||
snprintf(env[1], e, "reason=%s", iface->state->reason);
|
||||
e = 20;
|
||||
env[2] = xmalloc(e);
|
||||
snprintf(env[2], e, "pid=%d", getpid());
|
||||
env[3] = xmalloc(e);
|
||||
snprintf(env[3], e, "pid=%d", getpid());
|
||||
snprintf(env[3], e, "ifmetric=%d", iface->metric);
|
||||
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);
|
||||
snprintf(env[4], e, "ifwireless=%d", iface->wireless);
|
||||
env[5] = xmalloc(e);
|
||||
snprintf(env[5], e, "ifflags=%u", iface->flags);
|
||||
l = e = strlen("interface_order=");
|
||||
for (ifp = ifaces; ifp; ifp = ifp->next)
|
||||
e += strlen(ifp->name) + 1;
|
||||
p = env[6] = xmalloc(e);
|
||||
strlcpy(p, "interface_order=", e);
|
||||
e -= l;
|
||||
p += l;
|
||||
for (ifp = ifaces; ifp; ifp = ifp->next) {
|
||||
l = strlcpy(p, ifp->name, e);
|
||||
p += l;
|
||||
e -= l;
|
||||
*p++ = ' ';
|
||||
e--;
|
||||
}
|
||||
*--p = '\0';
|
||||
if (*iface->state->profile) {
|
||||
e = strlen("profile=") + strlen(iface->state->profile) + 2;
|
||||
env[elen] = xmalloc(e);
|
||||
snprintf(env[elen++], e, "profile=%s", iface->state->profile);
|
||||
}
|
||||
if (iface->wireless) {
|
||||
e = strlen("new_ssid=") + strlen(iface->ssid) + 2;
|
||||
if (iface->state->new != NULL ||
|
||||
strcmp(iface->state->reason, "CARRIER") == 0)
|
||||
{
|
||||
env = xrealloc(env, sizeof(char *) * (elen + 2));
|
||||
env[elen] = xmalloc(e);
|
||||
snprintf(env[elen++], e, "new_ssid=%s", iface->ssid);
|
||||
}
|
||||
if (iface->state->old != NULL ||
|
||||
strcmp(iface->state->reason, "NOCARRIER") == 0)
|
||||
{
|
||||
env = xrealloc(env, sizeof(char *) * (elen + 2));
|
||||
env[elen] = xmalloc(e);
|
||||
snprintf(env[elen++], e, "old_ssid=%s", iface->ssid);
|
||||
}
|
||||
}
|
||||
if (dhcpn) {
|
||||
e = configure_env(NULL, NULL, dhcpn, options);
|
||||
if (iface->state->old) {
|
||||
e = configure_env(NULL, NULL, iface->state->old, ifo);
|
||||
if (e > 0) {
|
||||
env = xrealloc(env, sizeof(char *) * (elen + e + 1));
|
||||
elen += configure_env(env + elen, "new", dhcpn, options);
|
||||
elen += configure_env(env + elen, "old",
|
||||
iface->state->old, ifo);
|
||||
}
|
||||
append_config(&env, &elen, "old",
|
||||
(const char *const *)ifo->config);
|
||||
}
|
||||
if (iface->state->new) {
|
||||
e = configure_env(NULL, NULL, iface->state->new, ifo);
|
||||
if (e > 0) {
|
||||
env = xrealloc(env, sizeof(char *) * (elen + e + 1));
|
||||
elen += configure_env(env + elen, "new",
|
||||
iface->state->new, ifo);
|
||||
}
|
||||
append_config(&env, &elen, "new",
|
||||
(const char *const *)ifo->config);
|
||||
}
|
||||
|
||||
/* Add our base environment */
|
||||
if (options->environ) {
|
||||
if (ifo->environ) {
|
||||
e = 0;
|
||||
while (options->environ[e++])
|
||||
while (ifo->environ[e++])
|
||||
;
|
||||
env = xrealloc(env, sizeof(char *) * (elen + e + 1));
|
||||
e = 0;
|
||||
while (options->environ[e]) {
|
||||
env[elen + e] = xstrdup(options->environ[e]);
|
||||
while (ifo->environ[e]) {
|
||||
env[elen + e] = xstrdup(ifo->environ[e]);
|
||||
e++;
|
||||
}
|
||||
elen += e;
|
||||
}
|
||||
env[elen] = '\0';
|
||||
|
||||
*argv = env;
|
||||
return elen;
|
||||
}
|
||||
|
||||
int
|
||||
send_interface(int fd, const struct interface *iface)
|
||||
{
|
||||
char **env, **ep, *s;
|
||||
ssize_t elen;
|
||||
struct iovec iov[2];
|
||||
int retval;
|
||||
|
||||
retval = 0;
|
||||
make_env(iface, &env);
|
||||
elen = arraytostr((const char *const *)env, &s);
|
||||
iov[0].iov_base = &elen;
|
||||
iov[0].iov_len = sizeof(ssize_t);
|
||||
iov[1].iov_base = s;
|
||||
iov[1].iov_len = elen;
|
||||
retval = writev(fd, iov, 2);
|
||||
ep = env;
|
||||
while (*ep)
|
||||
free(*ep++);
|
||||
free(env);
|
||||
free(s);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
run_script(const struct interface *iface)
|
||||
{
|
||||
char *const argv[2] = { UNCONST(iface->state->options->script), NULL };
|
||||
char **env = NULL, **ep;
|
||||
char *path, *bigenv;
|
||||
ssize_t e, elen = 0;
|
||||
pid_t pid;
|
||||
int status = 0;
|
||||
const struct fd_list *fd;
|
||||
struct iovec iov[2];
|
||||
|
||||
syslog(LOG_DEBUG, "%s: executing `%s', reason %s",
|
||||
iface->name, argv[0], iface->state->reason);
|
||||
|
||||
/* Make our env */
|
||||
elen = make_env(iface, &env);
|
||||
env = xrealloc(env, sizeof(char *) * (elen + 2));
|
||||
/* Add path to it */
|
||||
path = getenv("PATH");
|
||||
if (path) {
|
||||
e = strlen("PATH") + strlen(path) + 2;
|
||||
env[elen] = xmalloc(e);
|
||||
snprintf(env[elen], e, "PATH=%s", path);
|
||||
} else
|
||||
env[elen] = xstrdup(DEFAULT_PATH);
|
||||
env[++elen] = '\0';
|
||||
|
||||
pid = exec_script(argv, env);
|
||||
if (pid == -1)
|
||||
status = -1;
|
||||
@ -150,13 +323,30 @@ run_script(const struct options *options, const char *iface,
|
||||
/* Wait for the script to finish */
|
||||
while (waitpid(pid, &status, 0) == -1) {
|
||||
if (errno != EINTR) {
|
||||
logger(LOG_ERR, "waitpid: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "waitpid: %m");
|
||||
status = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send to our listeners */
|
||||
bigenv = NULL;
|
||||
for (fd = fds; fd != NULL; fd = fd->next) {
|
||||
if (fd->listener) {
|
||||
if (bigenv == NULL) {
|
||||
elen = arraytostr((const char *const *)env,
|
||||
&bigenv);
|
||||
iov[0].iov_base = &elen;
|
||||
iov[0].iov_len = sizeof(ssize_t);
|
||||
iov[1].iov_base = bigenv;
|
||||
iov[1].iov_len = elen;
|
||||
}
|
||||
writev(fd->fd, iov, 2);
|
||||
}
|
||||
}
|
||||
free(bigenv);
|
||||
|
||||
/* Cleanup */
|
||||
ep = env;
|
||||
while (*ep)
|
||||
@ -166,251 +356,346 @@ run_script(const struct options *options, const char *iface,
|
||||
}
|
||||
|
||||
static struct rt *
|
||||
reverse_routes(struct rt *routes)
|
||||
find_route(struct rt *rts, const struct rt *r, struct rt **lrt,
|
||||
const struct rt *srt)
|
||||
{
|
||||
struct rt *rt;
|
||||
struct rt *rtn = NULL;
|
||||
|
||||
while (routes) {
|
||||
rt = routes->next;
|
||||
routes->next = rtn;
|
||||
rtn = routes;
|
||||
routes = rt;
|
||||
|
||||
if (lrt)
|
||||
*lrt = NULL;
|
||||
for (rt = rts; rt; rt = rt->next) {
|
||||
if (rt->dest.s_addr == r->dest.s_addr &&
|
||||
#if HAVE_ROUTE_METRIC
|
||||
(srt || (!rt->iface ||
|
||||
rt->iface->metric == r->iface->metric)) &&
|
||||
#endif
|
||||
(!srt || srt != rt) &&
|
||||
rt->net.s_addr == r->net.s_addr)
|
||||
return rt;
|
||||
if (lrt)
|
||||
*lrt = rt;
|
||||
}
|
||||
return rtn;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
desc_route(const char *cmd, const struct rt *rt, const char *ifname)
|
||||
{
|
||||
char addr[sizeof("000.000.000.000") + 1];
|
||||
|
||||
strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr));
|
||||
if (rt->gate.s_addr == INADDR_ANY)
|
||||
syslog(LOG_DEBUG, "%s: %s route to %s/%d", ifname, cmd,
|
||||
addr, inet_ntocidr(rt->net));
|
||||
else if (rt->gate.s_addr == rt->dest.s_addr &&
|
||||
rt->net.s_addr == INADDR_BROADCAST)
|
||||
syslog(LOG_DEBUG, "%s: %s host route to %s", ifname, cmd,
|
||||
addr);
|
||||
else if (rt->dest.s_addr == INADDR_ANY && rt->net.s_addr == INADDR_ANY)
|
||||
syslog(LOG_DEBUG, "%s: %s default route via %s", ifname, cmd,
|
||||
inet_ntoa(rt->gate));
|
||||
else
|
||||
syslog(LOG_DEBUG, "%s: %s route to %s/%d via %s", ifname, cmd,
|
||||
addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate));
|
||||
}
|
||||
|
||||
/* If something other than dhcpcd removes a route,
|
||||
* we need to remove it from our internal table. */
|
||||
int
|
||||
route_deleted(const struct rt *rt)
|
||||
{
|
||||
struct rt *f, *l;
|
||||
|
||||
f = find_route(routes, rt, &l, NULL);
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
desc_route("removing", f, f->iface->name);
|
||||
if (l)
|
||||
l->next = f->next;
|
||||
else
|
||||
routes = f->next;
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
delete_route(const struct interface *iface, struct rt *rt, int metric)
|
||||
n_route(struct rt *rt, const struct interface *iface)
|
||||
{
|
||||
char *addr;
|
||||
int retval;
|
||||
/* Don't set default routes if not asked to */
|
||||
if (rt->dest.s_addr == 0 &&
|
||||
rt->net.s_addr == 0 &&
|
||||
!(iface->state->options->options & DHCPCD_GATEWAY))
|
||||
return -1;
|
||||
|
||||
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, 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)
|
||||
desc_route("adding", rt, iface->name);
|
||||
if (!add_route(iface, &rt->dest, &rt->net, &rt->gate, iface->metric))
|
||||
return 0;
|
||||
if (errno == EEXIST) {
|
||||
/* Pretend we added the subnet route */
|
||||
if (rt->dest.s_addr == (iface->addr.s_addr & iface->net.s_addr) &&
|
||||
rt->net.s_addr == iface->net.s_addr &&
|
||||
rt->gate.s_addr == 0)
|
||||
return 0;
|
||||
routes = routes->next;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
syslog(LOG_ERR, "%s: add_route: %m", iface->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
configure_routes(struct interface *iface, const struct dhcp_message *dhcp,
|
||||
const struct options *options)
|
||||
c_route(struct rt *ort, struct rt *nrt, const struct interface *iface)
|
||||
{
|
||||
struct rt *rt, *ort;
|
||||
struct rt *rtn = NULL, *nr = NULL;
|
||||
int remember;
|
||||
int retval = 0;
|
||||
char *addr;
|
||||
/* Don't set default routes if not asked to */
|
||||
if (nrt->dest.s_addr == 0 &&
|
||||
nrt->net.s_addr == 0 &&
|
||||
!(iface->state->options->options & DHCPCD_GATEWAY))
|
||||
return -1;
|
||||
|
||||
ort = get_option_routes(dhcp);
|
||||
desc_route("changing", nrt, iface->name);
|
||||
/* We delete and add the route so that we can change metric.
|
||||
* This also has the nice side effect of flushing ARP entries so
|
||||
* we don't have to do that manually. */
|
||||
del_route(ort->iface, &ort->dest, &ort->net, &ort->gate,
|
||||
ort->iface->metric);
|
||||
if (!add_route(iface, &nrt->dest, &nrt->net, &nrt->gate,
|
||||
iface->metric))
|
||||
return 0;
|
||||
syslog(LOG_ERR, "%s: add_route: %m", iface->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
static int
|
||||
d_route(struct rt *rt, const struct interface *iface, int metric)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if (!rt) {
|
||||
rt = xmalloc(sizeof(*rt));
|
||||
rt->dest.s_addr = htonl(LINKLOCAL_ADDR);
|
||||
rt->net.s_addr = htonl(LINKLOCAL_MASK);
|
||||
rt->gate.s_addr = 0;
|
||||
rt->next = NULL;
|
||||
if (rtn)
|
||||
rtn->next = rt;
|
||||
else
|
||||
ort = rt;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now remove old routes we no longer use.
|
||||
* We should do this in reverse order. */
|
||||
iface->routes = reverse_routes(iface->routes);
|
||||
for (rt = iface->routes; rt; rt = rt->next)
|
||||
if (in_routes(ort, rt) != 0)
|
||||
delete_route(iface, 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, &rt->dest,
|
||||
&rt->net, &rt->gate,
|
||||
options->metric);
|
||||
retval += remember;
|
||||
|
||||
/* If we failed to add the route, we may have already added it
|
||||
ourselves. If so, remember it again. */
|
||||
if (remember < 0) {
|
||||
if (errno != EEXIST)
|
||||
logger(LOG_ERR, "add_route: %s",
|
||||
strerror(errno));
|
||||
if (in_routes(iface->routes, rt) == 0)
|
||||
remember = 1;
|
||||
}
|
||||
|
||||
/* This login is split from above due to the #ifdef below */
|
||||
if (remember >= 0) {
|
||||
if (nr) {
|
||||
rtn->next = xmalloc(sizeof(*rtn));
|
||||
rtn = rtn->next;
|
||||
} else {
|
||||
nr = rtn = xmalloc(sizeof(*rtn));
|
||||
}
|
||||
rtn->dest.s_addr = rt->dest.s_addr;
|
||||
rtn->net.s_addr = rt->net.s_addr;
|
||||
rtn->gate.s_addr = rt->gate.s_addr;
|
||||
rtn->next = NULL;
|
||||
}
|
||||
}
|
||||
free_routes(ort);
|
||||
free_routes(iface->routes);
|
||||
iface->routes = nr;
|
||||
desc_route("deleting", rt, iface->name);
|
||||
retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric);
|
||||
if (retval != 0 && errno != ENOENT && errno != ESRCH)
|
||||
syslog(LOG_ERR,"%s: del_route: %m", iface->name);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static struct rt *
|
||||
get_subnet_route(struct dhcp_message *dhcp)
|
||||
{
|
||||
in_addr_t addr, net;
|
||||
struct rt *rt;
|
||||
|
||||
addr = dhcp->yiaddr;
|
||||
if (addr == 0)
|
||||
addr = dhcp->ciaddr;
|
||||
/* Ensure we have all the needed values */
|
||||
if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1)
|
||||
net = get_netmask(addr);
|
||||
if (net == INADDR_BROADCAST || net == INADDR_ANY)
|
||||
return NULL;
|
||||
rt = malloc(sizeof(*rt));
|
||||
rt->dest.s_addr = addr & net;
|
||||
rt->net.s_addr = net;
|
||||
rt->gate.s_addr = 0;
|
||||
return rt;
|
||||
}
|
||||
|
||||
static struct rt *
|
||||
add_subnet_route(struct rt *rt, const struct interface *iface)
|
||||
{
|
||||
struct rt *r;
|
||||
|
||||
if (iface->net.s_addr == INADDR_BROADCAST ||
|
||||
iface->net.s_addr == INADDR_ANY ||
|
||||
(iface->state->options->options &
|
||||
(DHCPCD_INFORM | DHCPCD_STATIC) &&
|
||||
iface->state->options->req_addr.s_addr == INADDR_ANY))
|
||||
return rt;
|
||||
|
||||
r = xmalloc(sizeof(*r));
|
||||
r->dest.s_addr = iface->addr.s_addr & iface->net.s_addr;
|
||||
r->net.s_addr = iface->net.s_addr;
|
||||
r->gate.s_addr = 0;
|
||||
r->next = rt;
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct rt *
|
||||
get_routes(const struct interface *iface)
|
||||
{
|
||||
struct rt *rt, *nrt = NULL, *r = NULL;
|
||||
|
||||
if (iface->state->options->routes != NULL) {
|
||||
for (rt = iface->state->options->routes;
|
||||
rt != NULL;
|
||||
rt = rt->next)
|
||||
{
|
||||
if (rt->gate.s_addr == 0)
|
||||
break;
|
||||
if (r == NULL)
|
||||
r = nrt = xmalloc(sizeof(*r));
|
||||
else {
|
||||
r->next = xmalloc(sizeof(*r));
|
||||
r = r->next;
|
||||
}
|
||||
memcpy(r, rt, sizeof(*r));
|
||||
r->next = NULL;
|
||||
}
|
||||
return nrt;
|
||||
}
|
||||
|
||||
return get_option_routes(iface->state->new);
|
||||
}
|
||||
|
||||
static struct rt *
|
||||
add_destination_route(struct rt *rt, const struct interface *iface)
|
||||
{
|
||||
struct rt *r;
|
||||
|
||||
if (!(iface->flags & IFF_POINTOPOINT) ||
|
||||
!has_option_mask(iface->state->options->dstmask, DHO_ROUTER))
|
||||
return rt;
|
||||
r = xmalloc(sizeof(*r));
|
||||
r->dest.s_addr = INADDR_ANY;
|
||||
r->net.s_addr = INADDR_ANY;
|
||||
r->gate.s_addr = iface->dst.s_addr;
|
||||
r->next = rt;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
build_routes(void)
|
||||
{
|
||||
struct rt *nrs = NULL, *dnr, *or, *rt, *rtn, *rtl, *lrt = NULL;
|
||||
const struct interface *ifp;
|
||||
|
||||
for (ifp = ifaces; ifp; ifp = ifp->next) {
|
||||
if (ifp->state->new == NULL)
|
||||
continue;
|
||||
dnr = get_routes(ifp);
|
||||
dnr = add_subnet_route(dnr, ifp);
|
||||
dnr = add_destination_route(dnr, ifp);
|
||||
for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) {
|
||||
rt->iface = ifp;
|
||||
/* Is this route already in our table? */
|
||||
if ((find_route(nrs, rt, NULL, NULL)) != NULL)
|
||||
continue;
|
||||
/* Do we already manage it? */
|
||||
if ((or = find_route(routes, rt, &rtl, NULL))) {
|
||||
if (or->iface != ifp ||
|
||||
rt->gate.s_addr != or->gate.s_addr)
|
||||
{
|
||||
if (c_route(or, rt, ifp) != 0)
|
||||
continue;
|
||||
}
|
||||
if (rtl != NULL)
|
||||
rtl->next = or->next;
|
||||
else
|
||||
routes = or->next;
|
||||
free(or);
|
||||
} else {
|
||||
if (n_route(rt, ifp) != 0)
|
||||
continue;
|
||||
}
|
||||
if (dnr == rt)
|
||||
dnr = rtn;
|
||||
else if (lrt)
|
||||
lrt->next = rtn;
|
||||
rt->next = nrs;
|
||||
nrs = rt;
|
||||
}
|
||||
free_routes(dnr);
|
||||
}
|
||||
|
||||
/* Remove old routes we used to manage */
|
||||
for (rt = routes; rt; rt = rt->next) {
|
||||
if (find_route(nrs, rt, NULL, NULL) == NULL)
|
||||
d_route(rt, rt->iface, rt->iface->metric);
|
||||
}
|
||||
|
||||
free_routes(routes);
|
||||
routes = nrs;
|
||||
}
|
||||
|
||||
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);
|
||||
struct if_options *ifo;
|
||||
|
||||
ifo = iface->state->options;
|
||||
if (ifo->options & DHCPCD_INFORM ||
|
||||
(ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
|
||||
return 0;
|
||||
syslog(LOG_DEBUG, "%s: deleting IP address %s/%d",
|
||||
iface->name,
|
||||
inet_ntoa(iface->addr),
|
||||
inet_ntocidr(iface->net));
|
||||
retval = del_address(iface, &iface->addr, &iface->net);
|
||||
if (retval == -1 && errno != EADDRNOTAVAIL)
|
||||
logger(LOG_ERR, "del_address: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "del_address: %m");
|
||||
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)
|
||||
configure(struct interface *iface)
|
||||
{
|
||||
struct in_addr addr;
|
||||
struct in_addr net;
|
||||
struct in_addr brd;
|
||||
#ifdef __linux__
|
||||
struct in_addr dest;
|
||||
struct in_addr gate;
|
||||
#endif
|
||||
struct dhcp_message *dhcp = iface->state->new;
|
||||
struct dhcp_lease *lease = &iface->state->lease;
|
||||
struct if_options *ifo = iface->state->options;
|
||||
struct rt *rt;
|
||||
|
||||
/* Grab our IP config */
|
||||
if (dhcp == NULL)
|
||||
up = 0;
|
||||
else {
|
||||
addr.s_addr = dhcp->yiaddr;
|
||||
if (addr.s_addr == 0)
|
||||
addr.s_addr = lease->addr.s_addr;
|
||||
/* Ensure we have all the needed values */
|
||||
if (get_option_addr(&net.s_addr, dhcp, DHO_SUBNETMASK) == -1)
|
||||
net.s_addr = get_netmask(addr.s_addr);
|
||||
if (get_option_addr(&brd.s_addr, dhcp, DHO_BROADCAST) == -1)
|
||||
brd.s_addr = addr.s_addr | ~net.s_addr;
|
||||
}
|
||||
/* As we are now adjusting an interface, we need to ensure
|
||||
* we have them in the right order for routing and configuration. */
|
||||
sort_interfaces();
|
||||
|
||||
/* 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);
|
||||
if (dhcp == NULL) {
|
||||
build_routes();
|
||||
if (iface->addr.s_addr != 0)
|
||||
delete_address(iface);
|
||||
}
|
||||
|
||||
run_script(options, iface->name, reason, NULL, old);
|
||||
run_script(iface);
|
||||
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 &&
|
||||
if (!(ifo->options & DHCPCD_INFORM) ||
|
||||
!has_address(iface->name, &lease->addr, &lease->net))
|
||||
{
|
||||
syslog(LOG_DEBUG, "%s: adding IP address %s/%d",
|
||||
iface->name, inet_ntoa(lease->addr),
|
||||
inet_ntocidr(lease->net));
|
||||
if (add_address(iface,
|
||||
&lease->addr, &lease->net, &lease->brd) == -1 &&
|
||||
errno != EEXIST)
|
||||
{
|
||||
logger(LOG_ERR, "add_address: %s", strerror(errno));
|
||||
syslog(LOG_ERR, "add_address: %m");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now delete the old address if different */
|
||||
if (iface->addr.s_addr != addr.s_addr &&
|
||||
if (iface->addr.s_addr != lease->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, &dest, &net, &gate, options->metric);
|
||||
del_route(iface, &dest, &net, &gate, 0);
|
||||
}
|
||||
#endif
|
||||
iface->addr.s_addr = lease->addr.s_addr;
|
||||
iface->net.s_addr = lease->net.s_addr;
|
||||
|
||||
iface->addr.s_addr = addr.s_addr;
|
||||
iface->net.s_addr = net.s_addr;
|
||||
configure_routes(iface, dhcp, options);
|
||||
if (!lease->frominfo)
|
||||
/* We need to delete the subnet route to have our metric or
|
||||
* prefer the interface. */
|
||||
rt = get_subnet_route(dhcp);
|
||||
if (rt != NULL) {
|
||||
rt->iface = iface;
|
||||
if (!find_route(routes, rt, NULL, NULL))
|
||||
del_route(iface, &rt->dest, &rt->net, &rt->gate, 0);
|
||||
free(rt);
|
||||
}
|
||||
|
||||
build_routes();
|
||||
if (!iface->state->lease.frominfo &&
|
||||
!(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
|
||||
if (write_lease(iface, dhcp) == -1)
|
||||
logger(LOG_ERR, "write_lease: %s", strerror(errno));
|
||||
run_script(options, iface->name, reason, dhcp, old);
|
||||
syslog(LOG_ERR, "write_lease: %m");
|
||||
run_script(iface);
|
||||
return 0;
|
||||
}
|
||||
|
15
external/bsd/dhcpcd/dist/configure.h
vendored
15
external/bsd/dhcpcd/dist/configure.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -28,14 +28,11 @@
|
||||
#ifndef DHCPCONFIG_H
|
||||
#define DHCPCONFIG_H
|
||||
|
||||
#include "dhcpcd.h"
|
||||
#include "dhcp.h"
|
||||
#include "net.h"
|
||||
|
||||
int run_script(const struct options *, const char *, const char *,
|
||||
const struct dhcp_message *, const struct dhcp_message *);
|
||||
int configure(struct interface *, const char *,
|
||||
const struct dhcp_message *, const struct dhcp_message *,
|
||||
const struct dhcp_lease *, const struct options *, int);
|
||||
|
||||
int send_interface(int, const struct interface *);
|
||||
int run_script(const struct interface *);
|
||||
void build_routes(void);
|
||||
int configure(struct interface *);
|
||||
int route_deleted(const struct rt *);
|
||||
#endif
|
||||
|
206
external/bsd/dhcpcd/dist/control.c
vendored
Normal file
206
external/bsd/dhcpcd/dist/control.c
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2009 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/un.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "control.h"
|
||||
#include "eloop.h"
|
||||
|
||||
static int fd = -1;
|
||||
static char buffer[1024];
|
||||
static char *argvp[255];
|
||||
|
||||
struct sockaddr_un sun;
|
||||
struct fd_list *fds = NULL;
|
||||
|
||||
static void
|
||||
remove_control_data(void *arg)
|
||||
{
|
||||
struct fd_list *l, *last = NULL;
|
||||
|
||||
for (l = fds; l != NULL; l = l->next) {
|
||||
if (l == arg) {
|
||||
close(l->fd);
|
||||
delete_event(l->fd);
|
||||
if (last == NULL)
|
||||
fds = l->next;
|
||||
else
|
||||
last->next = l->next;
|
||||
free(l);
|
||||
break;
|
||||
}
|
||||
last = l;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_control_data(void *arg)
|
||||
{
|
||||
struct fd_list *l = arg;
|
||||
ssize_t bytes;
|
||||
int argc;
|
||||
char *e, *p;
|
||||
char **ap;
|
||||
|
||||
bytes = read(l->fd, buffer, sizeof(buffer) - 1);
|
||||
if (bytes == -1 || bytes == 0) {
|
||||
remove_control_data(l);
|
||||
return;
|
||||
}
|
||||
buffer[bytes] = '\0';
|
||||
p = buffer;
|
||||
e = buffer + bytes;
|
||||
argc = 0;
|
||||
ap = argvp;
|
||||
while (p < e && (size_t)argc < sizeof(argvp)) {
|
||||
argc++;
|
||||
*ap++ = p;
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
handle_args(l, argc, argvp);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
handle_control(_unused void *arg)
|
||||
{
|
||||
struct sockaddr_un run;
|
||||
socklen_t len;
|
||||
struct fd_list *l;
|
||||
int f;
|
||||
|
||||
len = sizeof(run);
|
||||
if ((f = accept(fd, (struct sockaddr *)&run, &len)) == -1)
|
||||
return;
|
||||
l = xmalloc(sizeof(*l));
|
||||
l->fd = f;
|
||||
l->listener = 0;
|
||||
l->next = fds;
|
||||
fds = l;
|
||||
add_event(l->fd, handle_control_data, l);
|
||||
}
|
||||
|
||||
static int
|
||||
make_sock(void)
|
||||
{
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
return -1;
|
||||
memset(&sun, 0, sizeof(sun));
|
||||
sun.sun_family = AF_UNIX;
|
||||
strlcpy(sun.sun_path, CONTROLSOCKET, sizeof(sun.sun_path));
|
||||
return sizeof(sun.sun_family) + strlen(sun.sun_path) + 1;
|
||||
}
|
||||
|
||||
int
|
||||
start_control(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
if ((len = make_sock()) == -1)
|
||||
return -1;
|
||||
unlink(CONTROLSOCKET);
|
||||
if (bind(fd, (struct sockaddr *)&sun, len) == -1 ||
|
||||
chmod(CONTROLSOCKET,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1 ||
|
||||
set_cloexec(fd) == -1 ||
|
||||
set_nonblock(fd) == -1 ||
|
||||
listen(fd, sizeof(fds)) == -1)
|
||||
{
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
add_event(fd, handle_control, NULL);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
stop_control(void)
|
||||
{
|
||||
int retval = 0;
|
||||
struct fd_list *l, *ll;
|
||||
|
||||
delete_event(fd);
|
||||
if (shutdown(fd, SHUT_RDWR) == -1)
|
||||
retval = 1;
|
||||
fd = -1;
|
||||
if (unlink(CONTROLSOCKET) == -1)
|
||||
retval = -1;
|
||||
|
||||
l = fds;
|
||||
while (l != NULL) {
|
||||
ll = l->next;
|
||||
delete_event(l->fd);
|
||||
shutdown(l->fd, SHUT_RDWR);
|
||||
free(l);
|
||||
l = ll;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
open_control(void)
|
||||
{
|
||||
int len;
|
||||
|
||||
if ((len = make_sock()) == -1)
|
||||
return -1;
|
||||
return connect(fd, (struct sockaddr *)&sun, len);
|
||||
}
|
||||
|
||||
int
|
||||
send_control(int argc, char * const *argv)
|
||||
{
|
||||
char *p = buffer;
|
||||
int i;
|
||||
size_t len;
|
||||
|
||||
if (argc > 255) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < argc; i++) {
|
||||
len = strlen(argv[i]) + 1;
|
||||
if ((p - buffer) + len > sizeof(buffer)) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
memcpy(p, argv[i], len);
|
||||
p += len;
|
||||
}
|
||||
return write(fd, buffer, p - buffer);
|
||||
}
|
45
external/bsd/dhcpcd/dist/control.h
vendored
Normal file
45
external/bsd/dhcpcd/dist/control.h
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 CONTROL_H
|
||||
#define CONTROL_H
|
||||
|
||||
#include "dhcpcd.h"
|
||||
|
||||
struct fd_list {
|
||||
int fd;
|
||||
int listener;
|
||||
struct fd_list *next;
|
||||
};
|
||||
extern struct fd_list *fds;
|
||||
|
||||
int start_control(void);
|
||||
int stop_control(void);
|
||||
int open_control(void);
|
||||
int send_control(int, char * const *);
|
||||
|
||||
#endif
|
307
external/bsd/dhcpcd/dist/dhcp.c
vendored
307
external/bsd/dhcpcd/dist/dhcp.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -57,7 +57,7 @@
|
||||
/* Our aggregate option buffer.
|
||||
* We ONLY use this when options are split, which for most purposes is
|
||||
* practically never. See RFC3396 for details. */
|
||||
static uint8_t *dhcp_opt_buffer = NULL;
|
||||
static uint8_t *opt_buffer;
|
||||
|
||||
struct dhcp_opt {
|
||||
uint8_t option;
|
||||
@ -67,8 +67,9 @@ struct dhcp_opt {
|
||||
|
||||
static const struct dhcp_opt const dhcp_opts[] = {
|
||||
{ 1, IPV4 | REQUEST, "subnet_mask" },
|
||||
/* RFC 3442 states that the CSR has to come before all other routes.
|
||||
* For completeness, we also specify static routes, then routers. */
|
||||
/* RFC 3442 states that the CSR has to come before all other
|
||||
* routes. For completeness, we also specify static routes,
|
||||
* then routers. */
|
||||
{ 121, RFC3442 | REQUEST, "classless_static_routes" },
|
||||
{ 249, RFC3442, "ms_classless_static_routes" },
|
||||
{ 33, IPV4 | ARRAY | REQUEST, "static_routes" },
|
||||
@ -160,22 +161,52 @@ static const struct dhcp_opt const dhcp_opts[] = {
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static const char *if_params[] = {
|
||||
"interface",
|
||||
"reason",
|
||||
"pid",
|
||||
"ifmetric",
|
||||
"ifwireless",
|
||||
"ifflags",
|
||||
"profile",
|
||||
"interface_order",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *dhcp_params[] = {
|
||||
"ip_address",
|
||||
"subnet_cidr",
|
||||
"network_number",
|
||||
"ssid",
|
||||
"filename",
|
||||
"server_name",
|
||||
NULL
|
||||
};
|
||||
|
||||
void
|
||||
print_options(void)
|
||||
{
|
||||
const struct dhcp_opt *opt;
|
||||
const char **p;
|
||||
|
||||
for (p = if_params; *p; p++)
|
||||
printf(" - %s\n", *p);
|
||||
|
||||
for (p = dhcp_params; *p; p++)
|
||||
printf(" %s\n", *p);
|
||||
|
||||
for (opt = dhcp_opts; opt->option; opt++)
|
||||
if (opt->var)
|
||||
printf("%03d %s\n", opt->option, opt->var);
|
||||
}
|
||||
|
||||
int make_option_mask(uint8_t *mask, char **opts, int add)
|
||||
int make_option_mask(uint8_t *mask, const char *opts, int add)
|
||||
{
|
||||
char *token, *p = *opts, *t;
|
||||
char *token, *o, *p, *t;
|
||||
const struct dhcp_opt *opt;
|
||||
int match, n;
|
||||
|
||||
o = p = xstrdup(opts);
|
||||
while ((token = strsep(&p, ", "))) {
|
||||
if (*token == '\0')
|
||||
continue;
|
||||
@ -192,22 +223,28 @@ int make_option_mask(uint8_t *mask, char **opts, int add)
|
||||
if (opt->option == n)
|
||||
match = 1;
|
||||
}
|
||||
if (match) {
|
||||
if (add == 1)
|
||||
if (match) {
|
||||
if (add == 2 && !(opt->type & IPV4)) {
|
||||
free(o);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
if (add == 1 || add == 2)
|
||||
add_option_mask(mask,
|
||||
opt->option);
|
||||
opt->option);
|
||||
else
|
||||
del_option_mask(mask,
|
||||
opt->option);
|
||||
opt->option);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!opt->option) {
|
||||
*opts = token;
|
||||
free(o);
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free(o);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -227,7 +264,9 @@ valid_length(uint8_t option, int dl, int *type)
|
||||
if (type)
|
||||
*type = opt->type;
|
||||
|
||||
if (opt->type == 0 || opt->type & STRING || opt->type & RFC3442)
|
||||
if (opt->type == 0 ||
|
||||
opt->type & STRING ||
|
||||
opt->type & RFC3442)
|
||||
return 0;
|
||||
|
||||
sz = 0;
|
||||
@ -246,11 +285,13 @@ valid_length(uint8_t option, int dl, int *type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
static void
|
||||
free_option_buffer(void)
|
||||
{
|
||||
free(dhcp_opt_buffer);
|
||||
free(opt_buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define get_option_raw(dhcp, opt) get_option(dhcp, opt, NULL, NULL)
|
||||
static const uint8_t *
|
||||
@ -269,12 +310,14 @@ get_option(const struct dhcp_message *dhcp, uint8_t opt, int *len, int *type)
|
||||
o = *p++;
|
||||
if (o == opt) {
|
||||
if (op) {
|
||||
if (!dhcp_opt_buffer) {
|
||||
dhcp_opt_buffer = xmalloc(sizeof(struct dhcp_message));
|
||||
if (!opt_buffer) {
|
||||
opt_buffer = xmalloc(sizeof(*dhcp));
|
||||
#ifdef DEBUG_MEMORY
|
||||
atexit(free_option_buffer);
|
||||
#endif
|
||||
}
|
||||
if (!bp)
|
||||
bp = dhcp_opt_buffer;
|
||||
bp = opt_buffer;
|
||||
memcpy(bp, op, ol);
|
||||
bp += ol;
|
||||
}
|
||||
@ -318,7 +361,7 @@ exit:
|
||||
*len = bl;
|
||||
if (bp) {
|
||||
memcpy(bp, op, ol);
|
||||
return (const uint8_t *)&dhcp_opt_buffer;
|
||||
return (const uint8_t *)&opt_buffer;
|
||||
}
|
||||
if (op)
|
||||
return op;
|
||||
@ -369,7 +412,8 @@ get_option_uint8(uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
|
||||
|
||||
if (!p)
|
||||
return -1;
|
||||
*i = *(p);
|
||||
if (i)
|
||||
*i = *(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -440,10 +484,8 @@ static ssize_t
|
||||
decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p)
|
||||
{
|
||||
const uint8_t *e;
|
||||
ssize_t bytes = 0;
|
||||
ssize_t b;
|
||||
ssize_t b, bytes = 0, ocets;
|
||||
uint8_t cidr;
|
||||
uint8_t ocets;
|
||||
struct in_addr addr;
|
||||
char *o = out;
|
||||
|
||||
@ -477,7 +519,7 @@ decode_rfc3442(char *out, ssize_t len, int pl, const uint8_t *p)
|
||||
/* If we have ocets then we have a destination and netmask */
|
||||
if (ocets > 0) {
|
||||
addr.s_addr = 0;
|
||||
memcpy(&addr.s_addr, p, (size_t)ocets);
|
||||
memcpy(&addr.s_addr, p, ocets);
|
||||
b = snprintf(o, len, "%s/%d", inet_ntoa(addr), cidr);
|
||||
p += ocets;
|
||||
} else
|
||||
@ -504,7 +546,7 @@ decode_rfc3442_rt(int dl, const uint8_t *data)
|
||||
const uint8_t *p = data;
|
||||
const uint8_t *e;
|
||||
uint8_t cidr;
|
||||
uint8_t ocets;
|
||||
size_t ocets;
|
||||
struct rt *routes = NULL;
|
||||
struct rt *rt = NULL;
|
||||
|
||||
@ -532,15 +574,9 @@ decode_rfc3442_rt(int dl, const uint8_t *data)
|
||||
ocets = (cidr + 7) / 8;
|
||||
/* If we have ocets then we have a destination and netmask */
|
||||
if (ocets > 0) {
|
||||
memcpy(&rt->dest.s_addr, p, (size_t)ocets);
|
||||
memset(&rt->net.s_addr, 255, (size_t)ocets - 1);
|
||||
memset((uint8_t *)&rt->net.s_addr +
|
||||
(ocets - 1),
|
||||
(256 - (1 << (32 - cidr) % 8)), 1);
|
||||
memcpy(&rt->dest.s_addr, p, ocets);
|
||||
p += ocets;
|
||||
} else {
|
||||
rt->dest.s_addr = 0;
|
||||
rt->net.s_addr = 0;
|
||||
rt->net.s_addr = htonl(~0U << (32 - cidr));
|
||||
}
|
||||
|
||||
/* Finally, snag the router */
|
||||
@ -745,17 +781,42 @@ encode_rfc1035(const char *src, uint8_t *dst)
|
||||
return p - dst;
|
||||
}
|
||||
|
||||
#define PUTADDR(_type, _val) \
|
||||
{ \
|
||||
*p++ = _type; \
|
||||
*p++ = 4; \
|
||||
memcpy(p, &_val.s_addr, 4); \
|
||||
p += 4; \
|
||||
#define PUTADDR(_type, _val) \
|
||||
{ \
|
||||
*p++ = _type; \
|
||||
*p++ = 4; \
|
||||
memcpy(p, &_val.s_addr, 4); \
|
||||
p += 4; \
|
||||
}
|
||||
|
||||
int
|
||||
dhcp_message_add_addr(struct dhcp_message *dhcp,
|
||||
uint8_t type, struct in_addr addr)
|
||||
{
|
||||
uint8_t *p;
|
||||
size_t len;
|
||||
|
||||
p = dhcp->options;
|
||||
while (*p != DHO_END) {
|
||||
p++;
|
||||
p += *p + 1;
|
||||
}
|
||||
|
||||
len = p - (uint8_t *)dhcp;
|
||||
if (len + 6 > sizeof(*dhcp)) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
PUTADDR(type, addr);
|
||||
*p = DHO_END;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
make_message(struct dhcp_message **message,
|
||||
const struct interface *iface, const struct dhcp_lease *lease,
|
||||
uint32_t xid, uint8_t type, const struct options *options)
|
||||
const struct interface *iface,
|
||||
uint8_t type)
|
||||
{
|
||||
struct dhcp_message *dhcp;
|
||||
uint8_t *m, *lp, *p;
|
||||
@ -763,21 +824,23 @@ make_message(struct dhcp_message **message,
|
||||
time_t up = uptime() - iface->start_uptime;
|
||||
uint32_t ul;
|
||||
uint16_t sz;
|
||||
const struct dhcp_opt *opt;
|
||||
size_t len;
|
||||
const char *hp;
|
||||
const struct dhcp_opt *opt;
|
||||
const struct if_options *ifo = iface->state->options;
|
||||
const struct dhcp_lease *lease = &iface->state->lease;
|
||||
|
||||
dhcp = xzalloc(sizeof (*dhcp));
|
||||
m = (uint8_t *)dhcp;
|
||||
p = dhcp->options;
|
||||
|
||||
if ((type == DHCP_INFORM ||
|
||||
type == DHCP_RELEASE ||
|
||||
type == DHCP_REQUEST) &&
|
||||
type == DHCP_RELEASE ||
|
||||
type == DHCP_REQUEST) &&
|
||||
!IN_LINKLOCAL(ntohl(iface->addr.s_addr)))
|
||||
{
|
||||
dhcp->ciaddr = iface->addr.s_addr;
|
||||
/* Just incase we haven't actually configured the address yet */
|
||||
/* In-case we haven't actually configured the address yet */
|
||||
if (type == DHCP_INFORM && iface->addr.s_addr == 0)
|
||||
dhcp->ciaddr = lease->addr.s_addr;
|
||||
/* Zero the address if we're currently on a different subnet */
|
||||
@ -809,7 +872,7 @@ make_message(struct dhcp_message **message,
|
||||
else
|
||||
dhcp->secs = htons(up);
|
||||
}
|
||||
dhcp->xid = xid;
|
||||
dhcp->xid = iface->state->xid;
|
||||
dhcp->cookie = htonl(MAGIC_COOKIE);
|
||||
|
||||
*p++ = DHO_MESSAGETYPE;
|
||||
@ -826,12 +889,17 @@ make_message(struct dhcp_message **message,
|
||||
if (type == DHCP_DECLINE ||
|
||||
type == DHCP_DISCOVER ||
|
||||
(type == DHCP_REQUEST &&
|
||||
lease->addr.s_addr != iface->addr.s_addr))
|
||||
lease->addr.s_addr != iface->addr.s_addr))
|
||||
{
|
||||
PUTADDR(DHO_IPADDRESS, lease->addr);
|
||||
if (lease->server.s_addr)
|
||||
PUTADDR(DHO_SERVERID, lease->server);
|
||||
}
|
||||
|
||||
if (type == DHCP_RELEASE) {
|
||||
if (lease->server.s_addr)
|
||||
PUTADDR(DHO_SERVERID, lease->server);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == DHCP_DECLINE) {
|
||||
@ -842,11 +910,6 @@ make_message(struct dhcp_message **message,
|
||||
p += len;
|
||||
}
|
||||
|
||||
if (type == DHCP_RELEASE) {
|
||||
if (lease->server.s_addr)
|
||||
PUTADDR(DHO_SERVERID, lease->server);
|
||||
}
|
||||
|
||||
if (type == DHCP_DISCOVER ||
|
||||
type == DHCP_INFORM ||
|
||||
type == DHCP_REQUEST)
|
||||
@ -862,24 +925,25 @@ make_message(struct dhcp_message **message,
|
||||
memcpy(p, &sz, 2);
|
||||
p += 2;
|
||||
|
||||
if (options->userclass[0]) {
|
||||
if (ifo->userclass[0]) {
|
||||
*p++ = DHO_USERCLASS;
|
||||
memcpy(p, options->userclass, options->userclass[0] + 1);
|
||||
p += options->userclass[0] + 1;
|
||||
memcpy(p, ifo->userclass, ifo->userclass[0] + 1);
|
||||
p += ifo->userclass[0] + 1;
|
||||
}
|
||||
|
||||
if (options->vendorclassid[0]) {
|
||||
if (ifo->vendorclassid[0]) {
|
||||
*p++ = DHO_VENDORCLASSID;
|
||||
memcpy(p, options->vendorclassid,
|
||||
options->vendorclassid[0] + 1);
|
||||
p += options->vendorclassid[0] + 1;
|
||||
memcpy(p, ifo->vendorclassid,
|
||||
ifo->vendorclassid[0] + 1);
|
||||
p += ifo->vendorclassid[0] + 1;
|
||||
}
|
||||
|
||||
|
||||
if (type != DHCP_INFORM) {
|
||||
if (options->leasetime != 0) {
|
||||
if (ifo->leasetime != 0) {
|
||||
*p++ = DHO_LEASETIME;
|
||||
*p++ = 4;
|
||||
ul = htonl(options->leasetime);
|
||||
ul = htonl(ifo->leasetime);
|
||||
memcpy(p, &ul, 4);
|
||||
p += 4;
|
||||
}
|
||||
@ -889,18 +953,18 @@ make_message(struct dhcp_message **message,
|
||||
* upto the first dot (the short hostname) as otherwise
|
||||
* confuses some DHCP servers when updating DNS.
|
||||
* The FQDN option should be used if a FQDN is required. */
|
||||
if (options->hostname[0]) {
|
||||
if (ifo->options & DHCPCD_HOSTNAME && ifo->hostname[0]) {
|
||||
*p++ = DHO_HOSTNAME;
|
||||
hp = strchr(options->hostname, '.');
|
||||
hp = strchr(ifo->hostname, '.');
|
||||
if (hp)
|
||||
len = hp - options->hostname;
|
||||
len = hp - ifo->hostname;
|
||||
else
|
||||
len = strlen(options->hostname);
|
||||
len = strlen(ifo->hostname);
|
||||
*p++ = len;
|
||||
memcpy(p, options->hostname, len);
|
||||
memcpy(p, ifo->hostname, len);
|
||||
p += len;
|
||||
}
|
||||
if (options->fqdn != FQDN_DISABLE) {
|
||||
if (ifo->fqdn != FQDN_DISABLE && ifo->hostname[0]) {
|
||||
/* IETF DHC-FQDN option (81), RFC4702 */
|
||||
*p++ = DHO_FQDN;
|
||||
lp = p;
|
||||
@ -915,19 +979,19 @@ make_message(struct dhcp_message **message,
|
||||
* N: 1 => Client requests Server to not
|
||||
* update DNS
|
||||
*/
|
||||
*p++ = (options->fqdn & 0x09) | 0x04;
|
||||
*p++ = (ifo->fqdn & 0x09) | 0x04;
|
||||
*p++ = 0; /* from server for PTR RR */
|
||||
*p++ = 0; /* from server for A RR if S=1 */
|
||||
ul = encode_rfc1035(options->hostname, p);
|
||||
ul = encode_rfc1035(ifo->hostname, p);
|
||||
*lp += ul;
|
||||
p += ul;
|
||||
}
|
||||
|
||||
/* vendor is already encoded correctly, so just add it */
|
||||
if (options->vendor[0]) {
|
||||
if (ifo->vendor[0]) {
|
||||
*p++ = DHO_VENDOR;
|
||||
memcpy(p, options->vendor, options->vendor[0] + 1);
|
||||
p += options->vendor[0] + 1;
|
||||
memcpy(p, ifo->vendor, ifo->vendor[0] + 1);
|
||||
p += ifo->vendor[0] + 1;
|
||||
}
|
||||
|
||||
*p++ = DHO_PARAMETERREQUESTLIST;
|
||||
@ -935,15 +999,12 @@ make_message(struct dhcp_message **message,
|
||||
*p++ = 0;
|
||||
for (opt = dhcp_opts; opt->option; opt++) {
|
||||
if (!(opt->type & REQUEST ||
|
||||
has_option_mask(options->requestmask, opt->option)))
|
||||
has_option_mask(ifo->requestmask, opt->option)))
|
||||
continue;
|
||||
if (type == DHCP_INFORM &&
|
||||
(opt->option == DHO_RENEWALTIME ||
|
||||
opt->option == DHO_REBINDTIME))
|
||||
continue;
|
||||
switch (opt->option) {
|
||||
case DHO_RENEWALTIME: /* FALLTHROUGH */
|
||||
case DHO_REBINDTIME:
|
||||
if (type == DHCP_INFORM)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
*p++ = opt->option;
|
||||
}
|
||||
*n_params = p - n_params - 1;
|
||||
@ -972,6 +1033,12 @@ write_lease(const struct interface *iface, const struct dhcp_message *dhcp)
|
||||
uint8_t l;
|
||||
uint8_t o = 0;
|
||||
|
||||
/* We don't write BOOTP leases */
|
||||
if (is_bootp(dhcp)) {
|
||||
unlink(iface->leasefile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open(iface->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0400);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
@ -1049,21 +1116,21 @@ print_string(char *s, ssize_t len, int dl, const uint8_t *data)
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case '"': /* FALLTHROUGH */
|
||||
case '\'': /* FALLTHROUGH */
|
||||
case '$': /* FALLTHROUGH */
|
||||
case '`': /* FALLTHROUGH */
|
||||
case '\\': /* FALLTHROUGH */
|
||||
if (s) {
|
||||
if (len < 3) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
*s++ = '\\';
|
||||
len--;
|
||||
case '"': /* FALLTHROUGH */
|
||||
case '\'': /* FALLTHROUGH */
|
||||
case '$': /* FALLTHROUGH */
|
||||
case '`': /* FALLTHROUGH */
|
||||
case '\\': /* FALLTHROUGH */
|
||||
if (s) {
|
||||
if (len < 3) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
bytes++;
|
||||
break;
|
||||
*s++ = '\\';
|
||||
len--;
|
||||
}
|
||||
bytes++;
|
||||
break;
|
||||
}
|
||||
if (s) {
|
||||
*s++ = c;
|
||||
@ -1116,17 +1183,22 @@ print_option(char *s, ssize_t len, int type, int dl, const uint8_t *data)
|
||||
if (!s) {
|
||||
if (type & UINT8)
|
||||
l = 3;
|
||||
else if (type & UINT16)
|
||||
else if (type & UINT16) {
|
||||
l = 5;
|
||||
else if (type & SINT16)
|
||||
dl /= 2;
|
||||
} else if (type & SINT16) {
|
||||
l = 6;
|
||||
else if (type & UINT32)
|
||||
dl /= 2;
|
||||
} else if (type & UINT32) {
|
||||
l = 10;
|
||||
else if (type & SINT32)
|
||||
dl /= 4;
|
||||
} else if (type & SINT32) {
|
||||
l = 11;
|
||||
else if (type & IPV4)
|
||||
dl /= 4;
|
||||
} else if (type & IPV4) {
|
||||
l = 16;
|
||||
else {
|
||||
dl /= 4;
|
||||
} else {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@ -1190,7 +1262,7 @@ setvar(char ***e, const char *prefix, const char *var, const char *value)
|
||||
|
||||
ssize_t
|
||||
configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
|
||||
const struct options *options)
|
||||
const struct if_options *ifo)
|
||||
{
|
||||
unsigned int i;
|
||||
const uint8_t *p;
|
||||
@ -1211,12 +1283,12 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
|
||||
for (opt = dhcp_opts; opt->option; opt++) {
|
||||
if (!opt->var)
|
||||
continue;
|
||||
if (has_option_mask(options->nomask, opt->option))
|
||||
if (has_option_mask(ifo->nomask, opt->option))
|
||||
continue;
|
||||
if (get_option_raw(dhcp, opt->option))
|
||||
e++;
|
||||
}
|
||||
if (dhcp->yiaddr)
|
||||
if (dhcp->yiaddr || dhcp->ciaddr)
|
||||
e += 5;
|
||||
if (*dhcp->bootfile && !(overl & 1))
|
||||
e++;
|
||||
@ -1226,10 +1298,10 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
|
||||
}
|
||||
|
||||
ep = env;
|
||||
if (dhcp->yiaddr) {
|
||||
if (dhcp->yiaddr || dhcp->ciaddr) {
|
||||
/* Set some useful variables that we derive from the DHCP
|
||||
* message but are not necessarily in the options */
|
||||
addr.s_addr = dhcp->yiaddr;
|
||||
addr.s_addr = dhcp->yiaddr ? dhcp->yiaddr : dhcp->ciaddr;
|
||||
setvar(&ep, prefix, "ip_address", inet_ntoa(addr));
|
||||
if (get_option_addr(&net.s_addr, dhcp, DHO_SUBNETMASK) == -1) {
|
||||
net.s_addr = get_netmask(addr.s_addr);
|
||||
@ -1254,7 +1326,7 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
|
||||
for (opt = dhcp_opts; opt->option; opt++) {
|
||||
if (!opt->var)
|
||||
continue;
|
||||
if (has_option_mask(options->nomask, opt->option))
|
||||
if (has_option_mask(ifo->nomask, opt->option))
|
||||
continue;
|
||||
val = NULL;
|
||||
p = get_option(dhcp, opt->option, &pl, NULL);
|
||||
@ -1277,3 +1349,30 @@ configure_env(char **env, const char *prefix, const struct dhcp_message *dhcp,
|
||||
|
||||
return ep - env;
|
||||
}
|
||||
|
||||
void
|
||||
get_lease(struct dhcp_lease *lease, const struct dhcp_message *dhcp)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
/* BOOTP does not set yiaddr for replies when ciaddr is set. */
|
||||
if (dhcp->yiaddr)
|
||||
lease->addr.s_addr = dhcp->yiaddr;
|
||||
else
|
||||
lease->addr.s_addr = dhcp->ciaddr;
|
||||
if (get_option_addr(&lease->net.s_addr, dhcp, DHO_SUBNETMASK) == -1)
|
||||
lease->net.s_addr = get_netmask(lease->addr.s_addr);
|
||||
if (get_option_addr(&lease->brd.s_addr, dhcp, DHO_BROADCAST) == -1)
|
||||
lease->brd.s_addr = lease->addr.s_addr | ~lease->net.s_addr;
|
||||
if (get_option_uint32(&lease->leasetime, dhcp, DHO_LEASETIME) == 0) {
|
||||
/* Ensure that we can use the lease */
|
||||
get_monotonic(&now);
|
||||
if (now.tv_sec + (time_t)lease->leasetime < now.tv_sec)
|
||||
lease->leasetime = ~0U; /* Infinite lease */
|
||||
} else
|
||||
lease->leasetime = ~0U; /* Default to infinite lease */
|
||||
if (get_option_uint32(&lease->renewaltime, dhcp, DHO_RENEWALTIME) != 0)
|
||||
lease->renewaltime = 0;
|
||||
if (get_option_uint32(&lease->rebindtime, dhcp, DHO_REBINDTIME) != 0)
|
||||
lease->rebindtime = 0;
|
||||
}
|
||||
|
60
external/bsd/dhcpcd/dist/dhcp.h
vendored
60
external/bsd/dhcpcd/dist/dhcp.h
vendored
@ -29,13 +29,10 @@
|
||||
#define DHCP_H
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.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
|
||||
@ -61,9 +58,26 @@
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
/* Constants taken from RFC 2131. */
|
||||
#define T1 0.5
|
||||
#define T2 0.875
|
||||
#define DHCP_BASE 4
|
||||
#define DHCP_MAX 64
|
||||
#define DHCP_RAND_MIN -1
|
||||
#define DHCP_RAND_MAX 1
|
||||
#define DHCP_ARP_FAIL 10
|
||||
|
||||
/* number of usecs in a second. */
|
||||
#define USECS_SECOND 1000000
|
||||
/* As we use timevals, we should use the usec part for
|
||||
* greater randomisation. */
|
||||
#define DHCP_RAND_MIN_U DHCP_RAND_MIN * USECS_SECOND
|
||||
#define DHCP_RAND_MAX_U DHCP_RAND_MAX * USECS_SECOND
|
||||
#define PROBE_MIN_U PROBE_MIN * USECS_SECOND
|
||||
#define PROBE_MAX_U PROBE_MAX * USECS_SECOND
|
||||
|
||||
/* DHCP options */
|
||||
enum DHO
|
||||
{
|
||||
enum DHO {
|
||||
DHO_PAD = 0,
|
||||
DHO_SUBNETMASK = 1,
|
||||
DHO_ROUTER = 3,
|
||||
@ -112,13 +126,9 @@ enum FQDN {
|
||||
#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)
|
||||
#define DHCP_UDP_LEN (14 + 20 + 8)
|
||||
#define DHCP_FIXED_LEN (DHCP_UDP_LEN + 226)
|
||||
#define DHCP_OPTION_LEN (MTU_MAX - DHCP_FIXED_LEN)
|
||||
|
||||
/* Some crappy DHCP servers require the BOOTP minimum length */
|
||||
#define BOOTP_MESSAGE_LENTH_MIN 300
|
||||
@ -140,11 +150,12 @@ struct dhcp_message {
|
||||
uint8_t bootfile[BOOTFILE_LEN]; /* boot file name */
|
||||
uint32_t cookie;
|
||||
uint8_t options[DHCP_OPTION_LEN]; /* message options - cookie */
|
||||
};
|
||||
} _packed;
|
||||
|
||||
struct dhcp_lease {
|
||||
struct in_addr addr;
|
||||
struct in_addr net;
|
||||
struct in_addr brd;
|
||||
uint32_t leasetime;
|
||||
uint32_t renewaltime;
|
||||
uint32_t rebindtime;
|
||||
@ -154,25 +165,34 @@ struct dhcp_lease {
|
||||
uint8_t frominfo;
|
||||
};
|
||||
|
||||
#include "dhcpcd.h"
|
||||
#include "if-options.h"
|
||||
#include "net.h"
|
||||
|
||||
#define add_option_mask(var, val) (var[val >> 3] |= 1 << (val & 7))
|
||||
#define del_option_mask(var, val) (var[val >> 3] &= ~(1 << (val & 7)))
|
||||
#define has_option_mask(var, val) (var[val >> 3] & (1 << (val & 7)))
|
||||
int make_option_mask(uint8_t *, char **, int);
|
||||
int make_option_mask(uint8_t *, const 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);
|
||||
#define is_bootp(m) (m && \
|
||||
!IN_LINKLOCAL(htonl((m)->yiaddr)) && \
|
||||
get_option_uint8(NULL, m, DHO_MESSAGETYPE) == -1)
|
||||
struct rt *get_option_routes(const struct dhcp_message *);
|
||||
ssize_t configure_env(char **, const char *, const struct dhcp_message *,
|
||||
const struct options *);
|
||||
const struct if_options *);
|
||||
|
||||
ssize_t make_message(struct dhcp_message **,
|
||||
const struct interface *, const struct dhcp_lease *,
|
||||
uint32_t, uint8_t, const struct options *);
|
||||
int dhcp_message_add_addr(struct dhcp_message *, uint8_t, struct in_addr);
|
||||
ssize_t make_message(struct dhcp_message **, const struct interface *,
|
||||
uint8_t);
|
||||
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);
|
||||
struct dhcp_message *read_lease(const struct interface *);
|
||||
void get_lease(struct dhcp_lease *, const struct dhcp_message *);
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Just echo our DHCP options we have
|
||||
|
||||
if [ "${reason}" = "TEST" ]; then
|
||||
if [ "$reason" = "TEST" ]; then
|
||||
set | grep "^\(interface\|metric\|pid\|reason\|skip_hooks\)=" | sort
|
||||
set | grep "^\(new_\|old_\)" | sort
|
||||
fi
|
||||
|
4
external/bsd/dhcpcd/dist/dhcpcd-hooks/10-mtu
vendored
4
external/bsd/dhcpcd/dist/dhcpcd-hooks/10-mtu
vendored
@ -1,5 +1,5 @@
|
||||
# Configure the MTU for the interface
|
||||
|
||||
if [ -n "${new_interface_mtu}" ]; then
|
||||
ifconfig "${interface}" mtu "${new_interface_mtu}"
|
||||
if [ -n "$new_interface_mtu" ]; then
|
||||
ifconfig "$interface" mtu "$new_interface_mtu"
|
||||
fi
|
||||
|
@ -6,102 +6,121 @@
|
||||
# Also, resolvconf can configure local nameservers such as bind
|
||||
# or dnsmasq. This is important as the libc resolver isn't that powerful.
|
||||
|
||||
resolv_conf_dir="${state_dir}/resolv.conf"
|
||||
resolv_conf_dir="$state_dir/resolv.conf"
|
||||
|
||||
build_resolv_conf()
|
||||
{
|
||||
local cf="/etc/resolv.conf.${interface}"
|
||||
local cf="$state_dir/resolv.conf.$interface"
|
||||
local interfaces= header= search= srvs= servers= x=
|
||||
|
||||
# Build a list of interfaces
|
||||
interfaces=$(list_interfaces "${resolv_conf_dir}")
|
||||
interfaces=$(list_interfaces "$resolv_conf_dir")
|
||||
|
||||
# Build the resolv.conf
|
||||
if [ -n "${interfaces}" ]; then
|
||||
if [ -n "$interfaces" ]; then
|
||||
# Build the header
|
||||
for x in ${interfaces}; do
|
||||
header="${header}${header:+, }${x}"
|
||||
header="$header${header:+, }$x"
|
||||
done
|
||||
|
||||
# Build the search list
|
||||
search=$(cd "${resolv_conf_dir}"; \
|
||||
domain=$(cd "$resolv_conf_dir"; \
|
||||
key_get_value "domain " ${interfaces})
|
||||
search=$(cd "$resolv_conf_dir"; \
|
||||
key_get_value "search " ${interfaces})
|
||||
[ -n "${search}" ] && search="search $(uniqify ${search})\n"
|
||||
set -- ${domain}
|
||||
unset domain
|
||||
if [ -n "$2" ]; then
|
||||
search="$search $@"
|
||||
elif [ -n "$1" ]; then
|
||||
domain="domain $1\n"
|
||||
fi
|
||||
[ -n "$search" ] && search="search $(uniqify $search)\n"
|
||||
|
||||
# Build the nameserver list
|
||||
srvs=$(cd "${resolv_conf_dir}"; \
|
||||
srvs=$(cd "$resolv_conf_dir"; \
|
||||
key_get_value "nameserver " ${interfaces})
|
||||
for x in $(uniqify ${srvs}); do
|
||||
servers="${servers}nameserver ${x}\n"
|
||||
servers="${servers}nameserver $x\n"
|
||||
done
|
||||
fi
|
||||
header="${signature_base}${header:+ ${from} }${header}"
|
||||
header="$signature_base${header:+ $from }$header"
|
||||
|
||||
# Assemble resolv.conf using our head and tail files
|
||||
[ -f "${cf}" ] && rm -f "${cf}"
|
||||
echo "${header}" > "${cf}"
|
||||
[ -f "$cf" ] && rm -f "$cf"
|
||||
echo "$header" > "$cf"
|
||||
if [ -f /etc/resolv.conf.head ]; then
|
||||
cat /etc/resolv.conf.head >> "${cf}"
|
||||
cat /etc/resolv.conf.head >> "$cf"
|
||||
else
|
||||
echo "# /etc/resolv.conf.head can replace this line" >> "${cf}"
|
||||
echo "# /etc/resolv.conf.head can replace this line" >> "$cf"
|
||||
fi
|
||||
printf "${search}${servers}" >> "${cf}"
|
||||
printf "$domain$search$servers" >> "$cf"
|
||||
if [ -f /etc/resolv.conf.tail ]; then
|
||||
cat /etc/resolv.conf.tail >> "${cf}"
|
||||
cat /etc/resolv.conf.tail >> "$cf"
|
||||
else
|
||||
echo "# /etc/resolv.conf.tail can replace this line" >> "${cf}"
|
||||
echo "# /etc/resolv.conf.tail can replace this line" >> "$cf"
|
||||
fi
|
||||
mv -f "${cf}" /etc/resolv.conf
|
||||
cat "$cf" > /etc/resolv.conf
|
||||
chmod 644 /etc/resolv.conf
|
||||
rm -f "$cf"
|
||||
}
|
||||
|
||||
add_resolv_conf()
|
||||
{
|
||||
local x= conf="${signature}\n"
|
||||
local x= conf="$signature\n"
|
||||
|
||||
# If we don't have any configuration, remove it
|
||||
if [ -z "${new_domain_name_servers}" -a \
|
||||
-z "${new_domain_name}" -a \
|
||||
-z "${new_domain_search}" ]; then
|
||||
if [ -z "$new_domain_name_servers" -a \
|
||||
-z "$new_domain_name" -a \
|
||||
-z "$new_domain_search" ]; then
|
||||
remove_resolv_conf
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [ -n "${new_domain_search}" ]; then
|
||||
conf="${conf}search ${new_domain_search}\n"
|
||||
elif [ -n "${new_domain_name}" ]; then
|
||||
conf="${conf}search ${new_domain_name}\n"
|
||||
if [ -n "$new_domain_name" ]; then
|
||||
set -- $new_domain_name
|
||||
new_domain_name="$1"
|
||||
conf="${conf}domain $new_domain_name\n"
|
||||
# Support RFC violating search in domain
|
||||
if [ -z "$new_domain_search" -a -n "$2" ]; then
|
||||
new_domain_search="$@"
|
||||
fi
|
||||
fi
|
||||
if [ -n "$new_domain_search" ]; then
|
||||
conf="${conf}search $new_domain_search\n"
|
||||
fi
|
||||
for x in ${new_domain_name_servers}; do
|
||||
conf="${conf}nameserver ${x}\n"
|
||||
conf="${conf}nameserver $x\n"
|
||||
done
|
||||
if type resolvconf >/dev/null 2>&1; then
|
||||
printf "${conf}" | resolvconf -a "${interface}"
|
||||
[ -n "$metric" ] && export IF_METRIC="$metric"
|
||||
printf "$conf" | resolvconf -a "$interface"
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [ -e "${resolv_conf_dir}/${interface}" ]; then
|
||||
rm -f "${resolv_conf_dir}/${interface}"
|
||||
if [ -e "$resolv_conf_dir/$interface" ]; then
|
||||
rm -f "$resolv_conf_dir/$interface"
|
||||
fi
|
||||
if [ ! -d "${resolv_conf_dir}" ]; then
|
||||
mkdir -p "${resolv_conf_dir}"
|
||||
if [ ! -d "$resolv_conf_dir" ]; then
|
||||
mkdir -p "$resolv_conf_dir"
|
||||
fi
|
||||
printf "${conf}" > "${resolv_conf_dir}/${interface}"
|
||||
printf "$conf" > "$resolv_conf_dir/$interface"
|
||||
build_resolv_conf
|
||||
}
|
||||
|
||||
remove_resolv_conf()
|
||||
{
|
||||
if type resolvconf >/dev/null 2>&1; then
|
||||
resolvconf -d "${interface}" -f
|
||||
resolvconf -d "$interface" -f
|
||||
else
|
||||
if [ -e "${resolv_conf_dir}/${interface}" ]; then
|
||||
rm -f "${resolv_conf_dir}/${interface}"
|
||||
if [ -e "$resolv_conf_dir/$interface" ]; then
|
||||
rm -f "$resolv_conf_dir/$interface"
|
||||
fi
|
||||
build_resolv_conf
|
||||
fi
|
||||
}
|
||||
|
||||
case "${reason}" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) add_resolv_conf;;
|
||||
PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP) remove_resolv_conf;;
|
||||
case "$reason" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) add_resolv_conf;;
|
||||
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) remove_resolv_conf;;
|
||||
esac
|
||||
|
@ -2,19 +2,19 @@
|
||||
|
||||
lookup_hostname()
|
||||
{
|
||||
[ -z "${new_ip_address}" ] && return 1
|
||||
[ -z "$new_ip_address" ] && return 1
|
||||
local h=
|
||||
# Silly ISC programs love to send error text to stdout
|
||||
if type dig >/dev/null 2>&1; then
|
||||
h=`dig +short -x ${new_ip_address}`
|
||||
h=$(dig +short -x $new_ip_address)
|
||||
if [ $? = 0 ]; then
|
||||
echo "${h}" | sed 's/\.$//'
|
||||
echo "$h" | sed 's/\.$//'
|
||||
return 0
|
||||
fi
|
||||
elif type host >/dev/null 2>&1; then
|
||||
h=`host ${new_ip_address}`
|
||||
h=$(host $new_ip_address)
|
||||
if [ $? = 0 ]; then
|
||||
echo "${h}" \
|
||||
echo "$h" \
|
||||
| sed 's/.* domain name pointer \(.*\)./\1/'
|
||||
return 0
|
||||
fi
|
||||
@ -24,11 +24,11 @@ lookup_hostname()
|
||||
|
||||
set_hostname()
|
||||
{
|
||||
if [ -z "${new_host_name}" -a -z "${new_fqdn_name}" ]; then
|
||||
if [ -z "$new_host_name" -a -z "$new_fqdn_name" ]; then
|
||||
export new_host_name="$(lookup_hostname)"
|
||||
fi
|
||||
}
|
||||
|
||||
case "${reason}" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;;
|
||||
case "$reason" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) set_hostname;;
|
||||
esac
|
||||
|
@ -4,8 +4,8 @@ need_hostname()
|
||||
{
|
||||
case "$(hostname)" in
|
||||
""|"(none)"|localhost|localhost.localdomain)
|
||||
[ -n "${new_host_name}" -o -n "${new_fqdn_name}" ];;
|
||||
"${old_host_name}"|"${old_fqdn_name}")
|
||||
[ -n "$new_host_name" -o -n "$new_fqdn_name" ];;
|
||||
"$old_host_name"|"$old_fqdn_name")
|
||||
true;;
|
||||
*)
|
||||
false;;
|
||||
@ -15,14 +15,14 @@ need_hostname()
|
||||
set_hostname()
|
||||
{
|
||||
if need_hostname; then
|
||||
if [ -n "${new_host_name}" ]; then
|
||||
hostname "${new_host_name}"
|
||||
if [ -n "$new_host_name" ]; then
|
||||
hostname "$new_host_name"
|
||||
else
|
||||
hostname "${new_fqdn_name}"
|
||||
hostname "$new_fqdn_name"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
case "${reason}" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) set_hostname;;
|
||||
case "$reason" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) set_hostname;;
|
||||
esac
|
||||
|
@ -18,58 +18,58 @@ elif [ -x /usr/local/etc/rc.d/ntpd ]; then
|
||||
ntpd_restart_cmd="/usr/local/etc/rc.d/ntpd status && /usr/local/etc/rc.d/ntpd restart"
|
||||
fi
|
||||
|
||||
ntp_conf_dir="${state_dir}/ntp.conf"
|
||||
ntp_conf_dir="$state_dir/ntp.conf"
|
||||
ntp_conf=${NTP_CONF:-/etc/ntp.conf}
|
||||
|
||||
build_ntp_conf()
|
||||
{
|
||||
local cf="${ntp_conf}.${interface}"
|
||||
local cf="$state_dir/ntp.conf.$interface"
|
||||
local interfaces= header= srvs= servers= x=
|
||||
|
||||
# Build a list of interfaces
|
||||
interfaces=$(list_interfaces "${ntp_conf_dir}")
|
||||
interfaces=$(list_interfaces "$ntp_conf_dir")
|
||||
|
||||
if [ -n "${interfaces}" ]; then
|
||||
if [ -n "$interfaces" ]; then
|
||||
# Build the header
|
||||
for x in ${interfaces}; do
|
||||
header="${header}${header:+, }${x}"
|
||||
header="$header${header:+, }$x"
|
||||
done
|
||||
|
||||
# Build a server list
|
||||
srvs=$(cd "${ntp_conf_dir}";
|
||||
key_get_value "server " ${interfaces})
|
||||
if [ -n "${srvs}" ]; then
|
||||
for x in $(uniqify ${srvs}); do
|
||||
servers="${servers}server ${x}\n"
|
||||
srvs=$(cd "$ntp_conf_dir";
|
||||
key_get_value "server " $interfaces)
|
||||
if [ -n "$srvs" ]; then
|
||||
for x in $(uniqify $srvs); do
|
||||
servers="${servers}server $x\n"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Merge our config into ntp.conf
|
||||
[ -e "${cf}" ] && rm -f "${cf}"
|
||||
remove_markers "${signature_base}" "${signature_base_end}" \
|
||||
/etc/ntp.conf > "${cf}"
|
||||
if [ -n "${servers}" ]; then
|
||||
echo "${signature_base}${header:+ ${from} }${header}" >> "${cf}"
|
||||
printf "${search}${servers}" >> "${cf}"
|
||||
echo "${signature_base_end}${header:+ ${from} }${header}" >> "${cf}"
|
||||
[ -e "$cf" ] && rm -f "$cf"
|
||||
remove_markers "$signature_base" "$signature_base_end" \
|
||||
"$ntp_conf" > "$cf"
|
||||
if [ -n "$servers" ]; then
|
||||
echo "$signature_base${header:+ $from }$header" >> "$cf"
|
||||
printf "$search$servers" >> "$cf"
|
||||
echo "$signature_base_end${header:+ $from }$header" >> "$cf"
|
||||
fi
|
||||
|
||||
# If we changed anything, restart ntpd
|
||||
if change_file "${ntp_conf}" "${cf}"; then
|
||||
[ -n "${ntpd_restart_cmd}" ] && eval ${ntpd_restart_cmd}
|
||||
if change_file "$ntp_conf" "$cf"; then
|
||||
[ -n "$ntpd_restart_cmd" ] && eval $ntpd_restart_cmd
|
||||
fi
|
||||
}
|
||||
|
||||
add_ntp_conf()
|
||||
{
|
||||
local cf="${ntp_conf_dir}/${interface}" x=
|
||||
local cf="$ntp_conf_dir/$interface" x=
|
||||
|
||||
[ -e "${cf}" ] && rm "${cf}"
|
||||
[ -d "${ntp_conf_dir}" ] || mkdir -p "${ntp_conf_dir}"
|
||||
if [ -n "${new_ntp_servers}" ]; then
|
||||
for x in ${new_ntp_servers}; do
|
||||
echo "server ${x}" >> "${cf}"
|
||||
[ -e "$cf" ] && rm "$cf"
|
||||
[ -d "$ntp_conf_dir" ] || mkdir -p "$ntp_conf_dir"
|
||||
if [ -n "$new_ntp_servers" ]; then
|
||||
for x in $new_ntp_servers; do
|
||||
echo "server $x" >> "$cf"
|
||||
done
|
||||
fi
|
||||
build_ntp_conf
|
||||
@ -77,13 +77,13 @@ add_ntp_conf()
|
||||
|
||||
remove_ntp_conf()
|
||||
{
|
||||
if [ -e "${ntp_conf_dir}/${interface}" ]; then
|
||||
rm "${ntp_conf_dir}/${interface}"
|
||||
if [ -e "$ntp_conf_dir/$interface" ]; then
|
||||
rm "$ntp_conf_dir/$interface"
|
||||
fi
|
||||
build_ntp_conf
|
||||
}
|
||||
|
||||
case "${reason}" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT) add_ntp_conf add;;
|
||||
PREINIT|EXPIRE|FAIL|IPV4LL|RELEASE|STOP) remove_ntp_conf del;;
|
||||
case "$reason" in
|
||||
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC) add_ntp_conf add;;
|
||||
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP) remove_ntp_conf del;;
|
||||
esac
|
||||
|
35
external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in
vendored
35
external/bsd/dhcpcd/dist/dhcpcd-run-hooks.8.in
vendored
@ -1,4 +1,4 @@
|
||||
.\" Copyright 2006-2008 Roy Marples
|
||||
.\" Copyright 2006-2009 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -22,7 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd August 14, 2008
|
||||
.Dd March 23, 2009
|
||||
.Dt DHCPCD.SH 8 SMM
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -69,9 +69,12 @@ argument.
|
||||
Here's a list of reasons why
|
||||
.Nm
|
||||
could be invoked:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width PREINIT
|
||||
.It Dv PREINIT
|
||||
dhcpcd is starting up and any pre-initialisation should be done.
|
||||
.It Dv CARRIER
|
||||
dhcpcd has detected the carrier is up.
|
||||
This is generally just a notification and no action need be taken.
|
||||
.It Dv INFORM
|
||||
dhcpcd informed a DHCP server about it's address and obtained other
|
||||
configuration details.
|
||||
@ -83,14 +86,30 @@ dhcpcd renewed it's lease.
|
||||
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 STATIC
|
||||
dhcpcd has been configured with a static configuration which has not been
|
||||
obtained from a DHCP server.
|
||||
.It Dv 3RDPARTY
|
||||
dhcpcd is monitoring the interface for a 3rd party to give it an IP address.
|
||||
.It Dv TIMEOUT
|
||||
dhcpcd failed to contact any DHCP servers but was able to use an old lease.
|
||||
.It Dv EXPIRE
|
||||
dhcpcd's lease or state expired and it failed to obtain a new one.
|
||||
.It Dv NAK
|
||||
dhcpcd received a NAK from the DHCP server.
|
||||
This should be treated as EXPIRE.
|
||||
.It Dv NOCARRIER
|
||||
dhcpcd lost the carrier.
|
||||
The cable may have been unplugged or association to the wireless point lost.
|
||||
.It Dv FAIL
|
||||
dhcpcd failed to operate on the interface.
|
||||
This normally happens when dhcpcd does not support the raw interface, which
|
||||
means it cannot work as a DHCP or ZeroConf client.
|
||||
Static configuration and DHCP INFORM is still allowed.
|
||||
.It Dv STOP
|
||||
dhcpcd stopped running on the interface.
|
||||
.It Dv TEST
|
||||
dhcpcd received an OFFER from a DHCP server but will not configure the
|
||||
interface.
|
||||
@ -109,6 +128,6 @@ in a lexical order and then finally
|
||||
.Sh SEE ALSO
|
||||
.Xr dhcpcd 8
|
||||
.Sh AUTHORS
|
||||
.An Roy Marples <roy@marples.name>
|
||||
.An Roy Marples Aq roy@marples.name
|
||||
.Sh BUGS
|
||||
Please report them to http://roy.marples.name/projects/dhcpcd
|
||||
|
92
external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in
vendored
92
external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in
vendored
@ -2,38 +2,47 @@
|
||||
# dhcpcd client configuration script
|
||||
|
||||
# Handy variables and functions for our hooks to use
|
||||
from="from"
|
||||
from=from
|
||||
signature_base="# Generated by dhcpcd"
|
||||
signature="${signature_base} ${from} ${interface}"
|
||||
signature="$signature_base $from $interface"
|
||||
signature_base_end="# End of dhcpcd"
|
||||
signature_end="${signature_base_end} ${from} ${interface}"
|
||||
state_dir="/var/run/dhcpcd"
|
||||
signature_end="$signature_base_end $from $interface"
|
||||
state_dir=/var/run/dhcpcd
|
||||
|
||||
# Ensure that all arguments are unique
|
||||
uniqify()
|
||||
{
|
||||
local result=
|
||||
|
||||
while [ -n "$1" ]; do
|
||||
case " ${result} " in
|
||||
*" $1 "*);;
|
||||
*) result="${result}${result:+ }$1";;
|
||||
local result= i=
|
||||
for i; do
|
||||
case " $result " in
|
||||
*" $i "*);;
|
||||
*) result="$result $i";;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
echo "${result}"
|
||||
echo "${result# *}"
|
||||
}
|
||||
|
||||
# List interface config files in a dir
|
||||
# We may wish to control the order at some point rather than just lexical
|
||||
# If dhcpcd is running as a single instance then it will have a list of
|
||||
# interfaces in the preferred order.
|
||||
# Otherwise we just use what we have.
|
||||
list_interfaces()
|
||||
{
|
||||
local x= interfaces=
|
||||
for x in "$1"/*; do
|
||||
[ -e "${x}" ] || continue
|
||||
interfaces="${interfaces}${interfaces:+ }${x##*/}"
|
||||
local i= x= ifaces=
|
||||
for i in $interface_order; do
|
||||
[ -e "$1/$i" ] && ifaces="$ifaces${ifaces:+ }$i"
|
||||
done
|
||||
echo "${interfaces}"
|
||||
for x in "$1"/*; do
|
||||
[ -e "$x" ] || continue
|
||||
for i in $interface_order; do
|
||||
if [ $i = "${x##*/}" ]; then
|
||||
unset x
|
||||
break
|
||||
fi
|
||||
done
|
||||
[ -n "$x" ] && ifaces="$ifaces${ifaces:+ }${x##*/}"
|
||||
done
|
||||
echo "$ifaces"
|
||||
}
|
||||
|
||||
# We normally use sed to extract values using a key from a list of files
|
||||
@ -44,14 +53,14 @@ key_get_value()
|
||||
|
||||
shift
|
||||
if type sed >/dev/null 2>&1; then
|
||||
sed -n "s/^${key}//p" $@
|
||||
sed -n "s/^$key//p" $@
|
||||
else
|
||||
for x; do
|
||||
while read line; do
|
||||
case "${line}" in
|
||||
"${key}"*) echo "${line##${key}}";;
|
||||
case "$line" in
|
||||
"$key"*) echo "${line##$key}";;
|
||||
esac
|
||||
done < "${x}"
|
||||
done < "$x"
|
||||
done
|
||||
fi
|
||||
}
|
||||
@ -64,16 +73,16 @@ remove_markers()
|
||||
|
||||
shift; shift
|
||||
if type sed >/dev/null 2>&1; then
|
||||
sed "/^${m1}/,/^${m2}/d" $@
|
||||
sed "/^$m1/,/^$m2/d" $@
|
||||
else
|
||||
for x; do
|
||||
while read line; do
|
||||
case "${line}" in
|
||||
"${m1}"*) in_marker=1;;
|
||||
"${m2}"*) in_marker=0;;
|
||||
*) [ ${in_marker} = 0 ] && echo "${line}";;
|
||||
case "$line" in
|
||||
"$m1"*) in_marker=1;;
|
||||
"$m2"*) in_marker=0;;
|
||||
*) [ $in_marker = 0 ] && echo "$line";;
|
||||
esac
|
||||
done < "${x}"
|
||||
done < "$x"
|
||||
done
|
||||
fi
|
||||
}
|
||||
@ -94,7 +103,8 @@ change_file()
|
||||
rm -f "$2"
|
||||
return 1
|
||||
fi
|
||||
mv -f "$2" "$1"
|
||||
cat "$2" > "$1"
|
||||
rm -f "$2"
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -102,17 +112,17 @@ change_file()
|
||||
save_conf()
|
||||
{
|
||||
if [ -f "$1" ]; then
|
||||
rm -f "$1"-pre."${interface}"
|
||||
mv -f "$1" "$1"-pre."${interface}"
|
||||
rm -f "$1-pre.$interface"
|
||||
cat "$1" > "$1-pre.$interface"
|
||||
fi
|
||||
}
|
||||
|
||||
# Restore a config file
|
||||
restore_conf()
|
||||
{
|
||||
[ -f "$1"-pre."${interface}" ] || return 1
|
||||
rm -f "$1"
|
||||
mv -f "$1"-pre."${interface}" "$1"
|
||||
[ -f "$1-pre.$interface" ] || return 1
|
||||
cat "$1-pre.$interface" > "$1"
|
||||
rm -f "$1-pre.$interface"
|
||||
}
|
||||
|
||||
|
||||
@ -125,14 +135,14 @@ for hook in \
|
||||
@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;;
|
||||
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}"
|
||||
if [ -f "$hook" ]; then
|
||||
. "$hook"
|
||||
fi
|
||||
done
|
||||
|
157
external/bsd/dhcpcd/dist/dhcpcd.8.in
vendored
157
external/bsd/dhcpcd/dist/dhcpcd.8.in
vendored
@ -1,4 +1,4 @@
|
||||
.\" Copyright 2006-2008 Roy Marples
|
||||
.\" Copyright 2006-2009 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -22,7 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd November 18, 2008
|
||||
.Dd April 24, 2009
|
||||
.Dt DHCPCD 8 SMM
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -30,7 +30,7 @@
|
||||
.Nd an RFC 2131 compliant DHCP client
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl bdknpqABDEGKLTV
|
||||
.Op Fl bdeknpqABDEGKLTV
|
||||
.Op Fl c , -script Ar script
|
||||
.Op Fl f , -config Ar file
|
||||
.Op Fl h , -hostname Ar hostname
|
||||
@ -43,19 +43,24 @@
|
||||
.Op Fl t , -timeout Ar seconds
|
||||
.Op Fl u , -userclass Ar class
|
||||
.Op Fl v , -vendor Ar code , Ar value
|
||||
.Op Fl y , -reboot Ar seconds
|
||||
.Op Fl z , -allowinterfaces Ar pattern
|
||||
.Op Fl C , -nohook Ar hook
|
||||
.Op Fl F , -fqdn Ar FQDN
|
||||
.Op Fl I , -clientid Ar clientid
|
||||
.Op Fl O , -nooption Ar option
|
||||
.Op Fl Q , -require Ar option
|
||||
.Op Fl X , -blacklist Ar address
|
||||
.Ar interface
|
||||
.Op Fl S , -static Ar value
|
||||
.Op Fl X , -blacklist Ar address Ns Op Ar /cidr
|
||||
.Op Fl Z , -denyinterfaces Ar pattern
|
||||
.Op interface
|
||||
.Op ...
|
||||
.Nm
|
||||
.Fl k , -release
|
||||
.Ar interface
|
||||
.Op interface
|
||||
.Nm
|
||||
.Fl x , -exit
|
||||
.Ar interface
|
||||
.Op interface
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is an implementation of the DHCP client specified in
|
||||
@ -80,6 +85,10 @@ sets the hostname to the one supplied by the DHCP server.
|
||||
.Nm
|
||||
then daemonises and waits for the lease renewal time to lapse.
|
||||
Then it attempts to renew its lease and reconfigure if the new lease changes.
|
||||
.Pp
|
||||
.Nm
|
||||
is also an implementation of the BOOTP client specified in
|
||||
.Li RFC 951 .
|
||||
.Ss Local Link configuration
|
||||
If
|
||||
.Nm
|
||||
@ -98,6 +107,28 @@ installed which always defeats IPv4LL probing.
|
||||
To disable this behaviour, you can use the
|
||||
.Fl L , -noipv4ll
|
||||
option.
|
||||
.Ss Multiple interfaces
|
||||
.Nm
|
||||
can be run per interface or as a single instance to manage all interfaces.
|
||||
If a list of interfaces are given on the command line, then
|
||||
.Nm
|
||||
only works with those interfaces, otherwise
|
||||
.Nm
|
||||
discovers available interfaces.
|
||||
If link management is enabled and no interfaces are given on the command line,
|
||||
.Nm
|
||||
forks to the background right away.
|
||||
.Pp
|
||||
Interfaces are preferred by carrier, DHCP lease/IPv4LL and then lowest metric.
|
||||
For systems that support route metrics, each route will be tagged with the
|
||||
metric, otherwise
|
||||
.Nm
|
||||
changes the routes to use the interface with the same route and the lowest
|
||||
metric.
|
||||
See options below for controlling what interfaces we allow and deny through
|
||||
the use of patterns. Also, see the BUGS section if
|
||||
.Nm
|
||||
runs on a BSD system.
|
||||
.Ss Hooking into DHCP events
|
||||
.Nm
|
||||
runs
|
||||
@ -141,6 +172,16 @@ Echo debug and informational messages to the console.
|
||||
Subsequent debug options stop
|
||||
.Nm
|
||||
from daemonising.
|
||||
.It Fl e , -reconfigure
|
||||
.Nm
|
||||
will re-apply IP address, routing and run
|
||||
.Xr dhcpcd-run-hooks 8
|
||||
for each interface.
|
||||
This is useful so that a 3rd party such as PPP or VPN can change the routing
|
||||
table and / or DNS, etc and then instruct dhcpcd to put things back afterwards.
|
||||
.Nm
|
||||
does not read a new configuration when this happens - you should rebind if you
|
||||
need that functionality.
|
||||
.It Fl f , -config Ar file
|
||||
Specify a config to load instead of
|
||||
.Pa @SYSCONFDIR@/dhcpcd.conf .
|
||||
@ -180,14 +221,11 @@ By default
|
||||
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.
|
||||
Metrics are used to prefer an interface over another one, lowest wins.
|
||||
.Nm
|
||||
will supply a default metic of 200 +
|
||||
.Xr if_nametoindex 3 .
|
||||
An extra 100 will be added for wireless interfaces.
|
||||
.It Fl o , -option Ar option
|
||||
Request the DHCP
|
||||
.Ar option
|
||||
@ -292,6 +330,14 @@ to deconfigure the
|
||||
and exit.
|
||||
.Nm
|
||||
then waits until this process has exited.
|
||||
.It Fl y , -reboot Ar seconds
|
||||
Allow
|
||||
.Ar reboot
|
||||
seconds before moving to the discover phase if we have an old lease to use.
|
||||
The default is 10 seconds.
|
||||
A setting if 0 seconds causes
|
||||
.Nm
|
||||
to skip the reboot phase and go straight into discover.
|
||||
.It Fl D , -duid
|
||||
Generate an
|
||||
.Li RFC 4361
|
||||
@ -316,9 +362,6 @@ hostname.
|
||||
Valid values for
|
||||
.Ar fqdn
|
||||
are disable, none, ptr and both.
|
||||
The current hostname or the hostname specified using the
|
||||
.Fl h , -hostname
|
||||
option must be a FQDN.
|
||||
.Nm
|
||||
itself never does any DNS updates.
|
||||
.Nm
|
||||
@ -348,6 +391,14 @@ Quiet
|
||||
.Nm
|
||||
on the command line, only warnings and errors will be displayed.
|
||||
The messages are still logged though.
|
||||
.It Fl z , -allowinterfaces Ar pattern
|
||||
When discovering interfaces, the interface name must match
|
||||
.Ar pattern
|
||||
which is a space or comma separated list of patterns passed to
|
||||
.Xr fnmatch 3 .
|
||||
If the same interface is matched in
|
||||
.Fl Z , -denyinterfaces
|
||||
then it is still denied.
|
||||
.It Fl A , -noarp
|
||||
Don't request or claim the address by ARP.
|
||||
This also disables IPv4LL.
|
||||
@ -360,7 +411,9 @@ 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:-
|
||||
So to stop
|
||||
.Nm
|
||||
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.
|
||||
@ -379,6 +432,26 @@ configure the interface and routing.
|
||||
Requires the
|
||||
.Ar option
|
||||
to be present in all DHCP messages, otherwise the message is ignored.
|
||||
To enforce that
|
||||
.Nm
|
||||
only responds to DHCP servers and not BOOTP servers, you can
|
||||
.Fl Q
|
||||
.Ar dhcp_message_type .
|
||||
.It Fl S, -static Ar value
|
||||
Configures a static
|
||||
.Ar value .
|
||||
If you set
|
||||
.Ic ip_address
|
||||
then
|
||||
.Nm
|
||||
will not attempt to obtain a lease and just use the value for the address with
|
||||
an infinite lease time.
|
||||
.Pp
|
||||
Here is an example which configures a static address, routes and dns.
|
||||
.D1 dhcpcd -S ip_address=192.168.0.10/24 \e
|
||||
.D1 -S routers=192.168.0.1 \e
|
||||
.D1 -S domain_name_servers=192.168.0.1 \e
|
||||
.D1 eth0
|
||||
.It Fl T, -test
|
||||
On receipt of OFFER messages just call
|
||||
.Pa @SCRIPT@
|
||||
@ -389,14 +462,31 @@ files.
|
||||
.It Fl V, -variables
|
||||
Display a list of option codes and the associated variable for use in
|
||||
.Xr dhcpcd-run-hooks 8 .
|
||||
.It Fl X, -blacklist Ar address
|
||||
Ignores all DHCP messages which have this
|
||||
.Ar address
|
||||
as the server ID.
|
||||
This may be expanded in future releases to ignore all packets
|
||||
matching either the IP or hardware
|
||||
.Ar address .
|
||||
Variables are prefixed with new_ and old_ unless the option number is -.
|
||||
Variables without an option are part of the DHCP message and cannot be
|
||||
directly requested.
|
||||
.It Fl X, -blacklist Ar address Ns Op Ar /cidr
|
||||
Ignore all packets from
|
||||
.Ar address Ns Op Ar /cidr .
|
||||
.It Fl Z , -denyinterfaces Ar pattern
|
||||
When discovering interfaces, the interface name must not match
|
||||
.Ar pattern
|
||||
which is a space or comma separated list of patterns passed to
|
||||
.Xr fnmatch 3 .
|
||||
.El
|
||||
.Sh 3RDPARTY LINK MANAGEMENT
|
||||
Some interfaces require configuration by 3rd parties, such as PPP or VPN.
|
||||
When an interface configuration in
|
||||
.Nm
|
||||
is marked as STATIC or INFORM without an address then
|
||||
.Nm
|
||||
will monitor the interface until an address is added or removed from it and
|
||||
act accordingly.
|
||||
For point to point interfaces (like PPP), a default route to it's
|
||||
destination is automatically added to the configuration.
|
||||
If the point to point interface if configured for INFORM, then
|
||||
.Nm
|
||||
unicasts INFORM to the destination, otherwise it defaults to STATIC.
|
||||
.Sh NOTES
|
||||
.Nm
|
||||
requires a Berkley Packet Filter, or BPF device on BSD based systems and a
|
||||
@ -429,10 +519,19 @@ running on the
|
||||
.Xr dhcpcd-run-hooks 8 ,
|
||||
.Xr resolv.conf 5 ,
|
||||
.Xr resolvconf 8 ,
|
||||
.Xr if_nametoindex 3 ,
|
||||
.Xr fnmatch 3
|
||||
.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.
|
||||
RFC 951, RFC 1534, 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>
|
||||
.An Roy Marples Aq roy@marples.name
|
||||
.Sh BUGS
|
||||
Please report them to http://roy.marples.name/projects/dhcpcd
|
||||
.Pp
|
||||
.Nm
|
||||
does not wait for commands to complete when sending them to the master
|
||||
.Nm
|
||||
process, nor does it echo its progress to stderr.
|
||||
This is a behaviour change from dhcpcd-4 and may need to be addressed if
|
||||
there is sufficient need.
|
||||
|
2373
external/bsd/dhcpcd/dist/dhcpcd.c
vendored
2373
external/bsd/dhcpcd/dist/dhcpcd.c
vendored
File diff suppressed because it is too large
Load Diff
6
external/bsd/dhcpcd/dist/dhcpcd.conf
vendored
6
external/bsd/dhcpcd/dist/dhcpcd.conf
vendored
@ -1,9 +1,11 @@
|
||||
# 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
|
||||
# We normally want to inform the DHCP server of our hostname for DDNS.
|
||||
hostname
|
||||
|
||||
# A list of options we should request from the DHCP server.
|
||||
option domain_name_servers, domain_name, domain_search, host_name
|
||||
# Most distros have ntp support.
|
||||
option ntp_servers
|
||||
|
||||
|
116
external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
vendored
116
external/bsd/dhcpcd/dist/dhcpcd.conf.5.in
vendored
@ -1,4 +1,4 @@
|
||||
.\" Copyright 2006-2008 Roy Marples
|
||||
.\" Copyright 2006-2009 Roy Marples
|
||||
.\" All rights reserved
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
@ -22,7 +22,7 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.Dd November 18, 2008
|
||||
.Dd April 18, 2009
|
||||
.Dt DHCPCD.CONF 5 SMM
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -44,17 +44,38 @@ Blank lines and lines starting with # are ignored.
|
||||
.Pp
|
||||
Here's a list of available options:
|
||||
.Bl -tag -width indent
|
||||
.It Ic allowinterfaces Ar pattern
|
||||
When discovering interfaces, the interface name must match
|
||||
.Ar pattern
|
||||
which is a space or comma separated list of patterns passed to
|
||||
.Xr fnmatch 3 .
|
||||
If the same interface is matched in
|
||||
.Ic denyinterfaces
|
||||
then it is still denied.
|
||||
.It Ic denyinterfaces Ar pattern
|
||||
When discovering interfaces, the interface name must not match
|
||||
.Ar pattern
|
||||
which is a space or comma separated list of patterns passed to
|
||||
.Xr fnmatch 3 .
|
||||
.It Ic arping Ar address Op address
|
||||
.Nm dhcpcd
|
||||
will arping each address in order before attempting DHCP.
|
||||
If an address is found, we will select the replying hardware address as the
|
||||
profile, otherwise the ip address.
|
||||
Example:
|
||||
.Pp
|
||||
.D1 interface bge0
|
||||
.D1 arping 192.168.0.1
|
||||
.Pp
|
||||
.D1 profile 192.168.0.1
|
||||
.D1 static ip_address=192.168.0.10/24
|
||||
.It Ic background
|
||||
Background immediately.
|
||||
This is useful for startup scripts which don't disable link messages for
|
||||
carrier status.
|
||||
.It Ic blacklist Ar address
|
||||
Ignores all DHCP messages which have this
|
||||
.Ar address
|
||||
as the server ID.
|
||||
This may be expanded in future releases to ignore all packets
|
||||
matching either the IP or hardware
|
||||
.Ar address .
|
||||
.It Ic blacklist Ar address Ns Op /cidr
|
||||
Ignores all packets from
|
||||
.Ar address Ns Op /cidr .
|
||||
.It Ic clientid Ar string
|
||||
Send the
|
||||
.Ar clientid .
|
||||
@ -77,18 +98,18 @@ 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 fallback Ar profile
|
||||
Fallback to using this profile if DHCP fails.
|
||||
This allows you to configure a static profile instead of using ZeroConf.
|
||||
.It Ic hostname Ar name
|
||||
Sends specified
|
||||
.Ar hostname
|
||||
.Ar hostname
|
||||
to the DHCP server so it can be registered in DNS. If
|
||||
.Ar hostname
|
||||
if a FQDN (ie, contains a .) then it will be encoded as such.
|
||||
.It Ic fqdn Op none | ptr | both
|
||||
none disables FQDN encoding, ptr just asks the DHCP server to update the PTR
|
||||
record of the host in DNS whereas both also updates the A record.
|
||||
The current hostname or the hostname specified using the
|
||||
.Ic hostname
|
||||
option must be a FQDN.
|
||||
.Nm dhcpcd
|
||||
itself never does any DNS updates.
|
||||
.Nm dhcpcd
|
||||
@ -100,6 +121,12 @@ Subsequent options are only parsed for this
|
||||
.It Ic leasetime Ar seconds
|
||||
Request a leasetime of
|
||||
.Ar seconds .
|
||||
.It Ic metric Ar metric
|
||||
Metrics are used to prefer an interface over another one, lowest wins.
|
||||
.Nm dhcpcd
|
||||
will supply a default metic of 200 +
|
||||
.Xr if_nametoindex 3 .
|
||||
An extra 100 will be added for wireless interfaces.
|
||||
.It Ic noarp
|
||||
Don't send any ARP requests.
|
||||
This also disables IPv4LL.
|
||||
@ -109,6 +136,11 @@ Don't install any default routes.
|
||||
Don't run this hook script.
|
||||
Matches full name, or prefixed with 2 numbers optionally ending with
|
||||
.Pa .sh .
|
||||
.Pp
|
||||
So to stop
|
||||
.Nm dhcpcd
|
||||
from touching your DNS or MTU settings you would do:-
|
||||
.D1 nohook resolv.conf, mtu
|
||||
.It Ic noipv4ll
|
||||
Don't attempt to obtain an IPv4LL address if we failed to get one via DHCP.
|
||||
See
|
||||
@ -126,8 +158,28 @@ It can be a variable to be used in
|
||||
.Xr dhcpcd-run-hooks 8
|
||||
or the numerical value.
|
||||
You can specify more options seperated by commas, spaces or more option lines.
|
||||
.Ic quiet
|
||||
.It Ic destination Ar option
|
||||
If
|
||||
.Nm
|
||||
detects an address added to a point to point interface (PPP, TUN, etc) then
|
||||
it will set the listed DHCP options to the destination address of the
|
||||
interface.
|
||||
.It Ic profile Ar name
|
||||
Subsequent options are only parsed for this profile
|
||||
.Ar name .
|
||||
.It Ic quiet
|
||||
Supress any dhcpcd output to the console, except for errors.
|
||||
.It Ic reboot Ar seconds
|
||||
Allow
|
||||
.Ar reboot
|
||||
seconds before moving to the discover phase if we have an old lease to use.
|
||||
The default is 10 seconds.
|
||||
A setting if 0 seconds causes
|
||||
.Nm dhcpcd
|
||||
to skip the reboot phase and go straight into discover.
|
||||
.It Ic release
|
||||
.Nm dhcpcd
|
||||
will release the lease prior to stopping the interface.
|
||||
.It Ic require Ar option
|
||||
Requires the
|
||||
.Ar option
|
||||
@ -136,11 +188,41 @@ It can be a variable to be used in
|
||||
.Xr dhcpcd-run-hooks 8
|
||||
or the numerical value.
|
||||
You can specify more options seperated by commas, spaces or more require lines.
|
||||
To enforce that
|
||||
.Nm dhcpcd
|
||||
only responds to DHCP servers and not BOOTP servers, you can
|
||||
.Ic require
|
||||
.Ar dhcp_message_type .
|
||||
.It Ic script Ar script
|
||||
Use
|
||||
.Ar script
|
||||
instead of the default
|
||||
.Pa @SCRIPT@ .
|
||||
.It Ic ssid Ar ssid
|
||||
Subsequent options are only parsed for this wireless
|
||||
.Ar ssid .
|
||||
.It Ic static Ar value
|
||||
Configures a static
|
||||
.Ar value .
|
||||
If you set
|
||||
.Ic ip_address
|
||||
then
|
||||
.Nm dhcpcd
|
||||
will not attempt to obtain a lease and just use the value for the address with
|
||||
an infinite lease time.
|
||||
.Pp
|
||||
Here is an example which configures a static address, routes and dns.
|
||||
.D1 interface eth0
|
||||
.D1 static ip_address=192.168.0.10/24
|
||||
.D1 static routers=192.168.0.1
|
||||
.D1 static domain_name_servers=192.168.0.1
|
||||
.Pp
|
||||
Here is an example for PPP which gives the destination a default route.
|
||||
It uses the special destination keyword to insert the destination address
|
||||
into the value.
|
||||
.D1 interface ppp0
|
||||
.D1 static ip_address=
|
||||
.D1 destination routers
|
||||
.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.
|
||||
@ -165,8 +247,10 @@ If not set then none is sent.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr dhcpcd-run-hooks 8 ,
|
||||
.Xr dhcpcd 8
|
||||
.Xr dhcpcd 8 ,
|
||||
.Xr if_nametoindex 3 ,
|
||||
.Xr fnmatch 3
|
||||
.Sh AUTHORS
|
||||
.An Roy Marples <roy@marples.name>
|
||||
.An Roy Marples Aq roy@marples.name
|
||||
.Sh BUGS
|
||||
Please report them to http://roy.marples.name/projects/dhcpcd
|
||||
|
161
external/bsd/dhcpcd/dist/dhcpcd.h
vendored
161
external/bsd/dhcpcd/dist/dhcpcd.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -28,68 +28,115 @@
|
||||
#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"
|
||||
#include "control.h"
|
||||
#include "dhcp.h"
|
||||
#include "if-options.h"
|
||||
|
||||
#define DEFAULT_TIMEOUT 30
|
||||
#define DEFAULT_LEASETIME 3600 /* 1 hour */
|
||||
#define HWADDR_LEN 20
|
||||
#define IF_SSIDSIZE 33
|
||||
#define PROFILE_LEN 64
|
||||
|
||||
#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */
|
||||
#define VENDORCLASSID_MAX_LEN 48
|
||||
#define CLIENTID_MAX_LEN 48
|
||||
#define USERCLASS_MAX_LEN 255
|
||||
#define VENDOR_MAX_LEN 255
|
||||
|
||||
#define DHCPCD_ARP (1 << 0)
|
||||
#define DHCPCD_DOMAIN (1 << 2)
|
||||
#define DHCPCD_GATEWAY (1 << 3)
|
||||
#define DHCPCD_LASTLEASE (1 << 7)
|
||||
#define DHCPCD_INFORM (1 << 8)
|
||||
#define DHCPCD_REQUEST (1 << 9)
|
||||
#define DHCPCD_IPV4LL (1 << 10)
|
||||
#define DHCPCD_DUID (1 << 11)
|
||||
#define DHCPCD_PERSISTENT (1 << 12)
|
||||
#define DHCPCD_DAEMONISE (1 << 14)
|
||||
#define DHCPCD_DAEMONISED (1 << 15)
|
||||
#define DHCPCD_TEST (1 << 16)
|
||||
#define DHCPCD_FORKED (1 << 17)
|
||||
#define DHCPCD_HOSTNAME (1 << 18)
|
||||
#define DHCPCD_CLIENTID (1 << 19)
|
||||
#define DHCPCD_LINK (1 << 20)
|
||||
#define DHCPCD_BACKGROUND (1 << 21)
|
||||
|
||||
struct options {
|
||||
char interface[IF_NAMESIZE];
|
||||
int metric;
|
||||
uint8_t requestmask[256 / 8];
|
||||
uint8_t requiremask[256 / 8];
|
||||
uint8_t nomask[256 / 8];
|
||||
uint32_t leasetime;
|
||||
time_t timeout;
|
||||
int options;
|
||||
|
||||
struct in_addr request_address;
|
||||
struct in_addr request_netmask;
|
||||
|
||||
char **environ;
|
||||
char script[PATH_MAX];
|
||||
char pidfile[PATH_MAX];
|
||||
|
||||
char hostname[HOSTNAME_MAX_LEN + 1]; /* We don't store the lenth */
|
||||
int fqdn;
|
||||
uint8_t vendorclassid[VENDORCLASSID_MAX_LEN + 2];
|
||||
char clientid[CLIENTID_MAX_LEN + 2];
|
||||
uint8_t userclass[USERCLASS_MAX_LEN + 2];
|
||||
uint8_t vendor[VENDOR_MAX_LEN + 2];
|
||||
|
||||
size_t blacklist_len;
|
||||
in_addr_t *blacklist;
|
||||
enum DHS {
|
||||
DHS_INIT,
|
||||
DHS_DISCOVER,
|
||||
DHS_REQUEST,
|
||||
DHS_BOUND,
|
||||
DHS_RENEW,
|
||||
DHS_REBIND,
|
||||
DHS_REBOOT,
|
||||
DHS_INFORM,
|
||||
DHS_RENEW_REQUESTED,
|
||||
DHS_INIT_IPV4LL,
|
||||
DHS_PROBE
|
||||
};
|
||||
|
||||
#define LINK_UP 1
|
||||
#define LINK_UNKNOWN 0
|
||||
#define LINK_DOWN -1
|
||||
|
||||
struct if_state {
|
||||
enum DHS state;
|
||||
char profile[PROFILE_LEN];
|
||||
struct if_options *options;
|
||||
struct dhcp_message *sent;
|
||||
struct dhcp_message *offer;
|
||||
struct dhcp_message *new;
|
||||
struct dhcp_message *old;
|
||||
struct dhcp_lease lease;
|
||||
const char *reason;
|
||||
time_t interval;
|
||||
time_t nakoff;
|
||||
uint32_t xid;
|
||||
int socket;
|
||||
int probes;
|
||||
int claims;
|
||||
int conflicts;
|
||||
time_t defend;
|
||||
struct in_addr fail;
|
||||
size_t arping_index;
|
||||
};
|
||||
|
||||
struct interface {
|
||||
char name[IF_NAMESIZE];
|
||||
struct if_state *state;
|
||||
|
||||
int flags;
|
||||
sa_family_t family;
|
||||
unsigned char hwaddr[HWADDR_LEN];
|
||||
size_t hwlen;
|
||||
int metric;
|
||||
int carrier;
|
||||
int arpable;
|
||||
int wireless;
|
||||
char ssid[IF_SSIDSIZE];
|
||||
|
||||
int raw_fd;
|
||||
int udp_fd;
|
||||
int arp_fd;
|
||||
size_t buffer_size, buffer_len, buffer_pos;
|
||||
unsigned char *buffer;
|
||||
|
||||
struct in_addr addr;
|
||||
struct in_addr net;
|
||||
struct in_addr dst;
|
||||
|
||||
char leasefile[PATH_MAX];
|
||||
time_t start_uptime;
|
||||
|
||||
unsigned char *clientid;
|
||||
|
||||
struct interface *next;
|
||||
};
|
||||
|
||||
extern int pidfd;
|
||||
extern int options;
|
||||
extern int ifac;
|
||||
extern char **ifav;
|
||||
extern int ifdc;
|
||||
extern char **ifdv;
|
||||
extern struct interface *ifaces;
|
||||
|
||||
struct interface *find_interface(const char *);
|
||||
int handle_args(struct fd_list *, int, char **);
|
||||
void handle_interface(int, const char *);
|
||||
void handle_ifa(int, const char *,
|
||||
struct in_addr *, struct in_addr *, struct in_addr *);
|
||||
void handle_exit_timeout(void *);
|
||||
void start_interface(void *);
|
||||
void start_discover(void *);
|
||||
void start_request(void *);
|
||||
void start_renew(void *);
|
||||
void start_rebind(void *);
|
||||
void start_reboot(struct interface *);
|
||||
void start_expire(void *);
|
||||
void send_decline(struct interface *);
|
||||
void close_sockets(struct interface *);
|
||||
void drop_config(struct interface *, const char *);
|
||||
int select_profile(struct interface *, const char *);
|
||||
|
||||
#endif
|
||||
|
99
external/bsd/dhcpcd/dist/duid.c
vendored
Normal file
99
external/bsd/dhcpcd/dist/duid.c
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define THIRTY_YEARS_IN_SECONDS 946707779
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "duid.h"
|
||||
#include "net.h"
|
||||
|
||||
size_t
|
||||
get_duid(unsigned char *duid, const struct interface *iface)
|
||||
{
|
||||
FILE *f;
|
||||
uint16_t type = 0;
|
||||
uint16_t hw = 0;
|
||||
uint32_t ul;
|
||||
time_t t;
|
||||
int x = 0;
|
||||
unsigned char *p = duid;
|
||||
size_t len = 0;
|
||||
char *line;
|
||||
|
||||
/* If we already have a DUID then use it as it's never supposed
|
||||
* to change once we have one even if the interfaces do */
|
||||
if ((f = fopen(DUID, "r"))) {
|
||||
while ((line = get_line(f))) {
|
||||
len = hwaddr_aton(NULL, line);
|
||||
if (len && len <= DUID_LEN) {
|
||||
hwaddr_aton(duid, line);
|
||||
break;
|
||||
}
|
||||
len = 0;
|
||||
}
|
||||
fclose(f);
|
||||
if (len)
|
||||
return len;
|
||||
} else {
|
||||
if (errno != ENOENT)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* No file? OK, lets make one based on our interface */
|
||||
if (!(f = fopen(DUID, "w")))
|
||||
return 0;
|
||||
type = htons(1); /* DUI-D-LLT */
|
||||
memcpy(p, &type, 2);
|
||||
p += 2;
|
||||
hw = htons(iface->family);
|
||||
memcpy(p, &hw, 2);
|
||||
p += 2;
|
||||
/* time returns seconds from jan 1 1970, but DUID-LLT is
|
||||
* seconds from jan 1 2000 modulo 2^32 */
|
||||
t = time(NULL) - THIRTY_YEARS_IN_SECONDS;
|
||||
ul = htonl(t & 0xffffffff);
|
||||
memcpy(p, &ul, 4);
|
||||
p += 4;
|
||||
/* Finally, add the MAC address of the interface */
|
||||
memcpy(p, iface->hwaddr, iface->hwlen);
|
||||
p += iface->hwlen;
|
||||
len = p - duid;
|
||||
x = fprintf(f, "%s\n", hwaddr_ntoa(duid, len));
|
||||
fclose(f);
|
||||
/* Failed to write the duid? scrub it, we cannot use it */
|
||||
if (x < 1) {
|
||||
len = 0;
|
||||
unlink(DUID);
|
||||
}
|
||||
return len;
|
||||
}
|
35
external/bsd/dhcpcd/dist/duid.h
vendored
Normal file
35
external/bsd/dhcpcd/dist/duid.h
vendored
Normal 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 DUID_H
|
||||
#define DUID_H
|
||||
|
||||
#include "net.h"
|
||||
|
||||
size_t get_duid(unsigned char *duid, const struct interface *iface);
|
||||
|
||||
#endif
|
351
external/bsd/dhcpcd/dist/eloop.c
vendored
Normal file
351
external/bsd/dhcpcd/dist/eloop.c
vendored
Normal file
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* 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/time.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <poll.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "eloop.h"
|
||||
|
||||
static struct timeval now;
|
||||
|
||||
static struct event {
|
||||
int fd;
|
||||
void (*callback)(void *);
|
||||
void *arg;
|
||||
struct event *next;
|
||||
} *events;
|
||||
static struct event *free_events;
|
||||
|
||||
static struct timeout {
|
||||
struct timeval when;
|
||||
void (*callback)(void *);
|
||||
void *arg;
|
||||
struct timeout *next;
|
||||
} *timeouts;
|
||||
static struct timeout *free_timeouts;
|
||||
|
||||
static struct pollfd *fds;
|
||||
static size_t fds_len;
|
||||
|
||||
void
|
||||
add_event(int fd, void (*callback)(void *), void *arg)
|
||||
{
|
||||
struct event *e, *last = NULL;
|
||||
|
||||
/* We should only have one callback monitoring the fd */
|
||||
for (e = events; e; e = e->next) {
|
||||
if (e->fd == fd) {
|
||||
e->callback = callback;
|
||||
e->arg = arg;
|
||||
return;
|
||||
}
|
||||
last = e;
|
||||
}
|
||||
|
||||
/* Allocate a new event if no free ones already allocated */
|
||||
if (free_events) {
|
||||
e = free_events;
|
||||
free_events = e->next;
|
||||
} else
|
||||
e = xmalloc(sizeof(*e));
|
||||
e->fd = fd;
|
||||
e->callback = callback;
|
||||
e->arg = arg;
|
||||
e->next = NULL;
|
||||
if (last)
|
||||
last->next = e;
|
||||
else
|
||||
events = e;
|
||||
}
|
||||
|
||||
void
|
||||
delete_event(int fd)
|
||||
{
|
||||
struct event *e, *last = NULL;
|
||||
|
||||
for (e = events; e; e = e->next) {
|
||||
if (e->fd == fd) {
|
||||
if (last)
|
||||
last->next = e->next;
|
||||
else
|
||||
events = e->next;
|
||||
e->next = free_events;
|
||||
free_events = e;
|
||||
break;
|
||||
}
|
||||
last = e;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
add_timeout_tv(const struct timeval *when, void (*callback)(void *), void *arg)
|
||||
{
|
||||
struct timeval w;
|
||||
struct timeout *t, *tt = NULL;
|
||||
|
||||
get_monotonic(&now);
|
||||
timeradd(&now, when, &w);
|
||||
/* Check for time_t overflow. */
|
||||
if (timercmp(&w, &now, <)) {
|
||||
errno = ERANGE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove existing timeout if present */
|
||||
for (t = timeouts; t; t = t->next) {
|
||||
if (t->callback == callback && t->arg == arg) {
|
||||
if (tt)
|
||||
tt->next = t->next;
|
||||
else
|
||||
timeouts = t->next;
|
||||
break;
|
||||
}
|
||||
tt = t;
|
||||
}
|
||||
|
||||
if (!t) {
|
||||
/* No existing, so allocate or grab one from the free pool */
|
||||
if (free_timeouts) {
|
||||
t = free_timeouts;
|
||||
free_timeouts = t->next;
|
||||
} else
|
||||
t = xmalloc(sizeof(*t));
|
||||
}
|
||||
|
||||
t->when.tv_sec = w.tv_sec;
|
||||
t->when.tv_usec = w.tv_usec;
|
||||
t->callback = callback;
|
||||
t->arg = arg;
|
||||
|
||||
/* The timeout list should be in chronological order,
|
||||
* soonest first.
|
||||
* This is the easiest algorithm - check the head, then middle
|
||||
* and finally the end. */
|
||||
if (!timeouts || timercmp(&t->when, &timeouts->when, <)) {
|
||||
t->next = timeouts;
|
||||
timeouts = t;
|
||||
return;
|
||||
}
|
||||
for (tt = timeouts; tt->next; tt = tt->next)
|
||||
if (timercmp(&t->when, &tt->next->when, <)) {
|
||||
t->next = tt->next;
|
||||
tt->next = t;
|
||||
return;
|
||||
}
|
||||
tt->next = t;
|
||||
t->next = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
add_timeout_sec(time_t when, void (*callback)(void *), void *arg)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = when;
|
||||
tv.tv_usec = 0;
|
||||
add_timeout_tv(&tv, callback, arg);
|
||||
}
|
||||
|
||||
/* This deletes all timeouts for the interface EXCEPT for ones with the
|
||||
* callbacks given. Handy for deleting everything apart from the expire
|
||||
* timeout. */
|
||||
void
|
||||
delete_timeouts(void *arg, void (*callback)(void *), ...)
|
||||
{
|
||||
struct timeout *t, *tt, *last = NULL;
|
||||
va_list va;
|
||||
void (*f)(void *);
|
||||
|
||||
for (t = timeouts; t && (tt = t->next, 1); t = tt) {
|
||||
if (t->arg == arg && t->callback != callback) {
|
||||
va_start(va, callback);
|
||||
while ((f = va_arg(va, void (*)(void *))))
|
||||
if (f == t->callback)
|
||||
break;
|
||||
va_end(va);
|
||||
if (!f) {
|
||||
if (last)
|
||||
last->next = t->next;
|
||||
else
|
||||
timeouts = t->next;
|
||||
t->next = free_timeouts;
|
||||
free_timeouts = t;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
last = t;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delete_timeout(void (*callback)(void *), void *arg)
|
||||
{
|
||||
struct timeout *t, *tt, *last = NULL;
|
||||
|
||||
for (t = timeouts; t && (tt = t->next, 1); t = tt) {
|
||||
if (t->arg == arg &&
|
||||
(!callback || t->callback == callback))
|
||||
{
|
||||
if (last)
|
||||
last->next = t->next;
|
||||
else
|
||||
timeouts = t->next;
|
||||
t->next = free_timeouts;
|
||||
free_timeouts = t;
|
||||
continue;
|
||||
}
|
||||
last = t;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
/* Define this to free all malloced memory.
|
||||
* Normally we don't do this as the OS will do it for us at exit,
|
||||
* but it's handy for debugging other leaks in valgrind. */
|
||||
static void
|
||||
cleanup(void)
|
||||
{
|
||||
struct event *e;
|
||||
struct timeout *t;
|
||||
|
||||
while (events) {
|
||||
e = events->next;
|
||||
free(events);
|
||||
events = e;
|
||||
}
|
||||
while (free_events) {
|
||||
e = free_events->next;
|
||||
free(free_events);
|
||||
free_events = e;
|
||||
}
|
||||
while (timeouts) {
|
||||
t = timeouts->next;
|
||||
free(timeouts);
|
||||
timeouts = t;
|
||||
}
|
||||
while (free_timeouts) {
|
||||
t = free_timeouts->next;
|
||||
free(free_timeouts);
|
||||
free_timeouts = t;
|
||||
}
|
||||
free(fds);
|
||||
}
|
||||
#endif
|
||||
|
||||
_noreturn void
|
||||
start_eloop(void)
|
||||
{
|
||||
int msecs, n;
|
||||
nfds_t nfds, i;
|
||||
struct event *e;
|
||||
struct timeout *t;
|
||||
struct timeval tv;
|
||||
|
||||
#ifdef DEBUG_MEMORY
|
||||
atexit(cleanup);
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
/* Run all timeouts first.
|
||||
* When we have one that has not yet occured,
|
||||
* calculate milliseconds until it does for use in poll. */
|
||||
if (timeouts) {
|
||||
if (timercmp(&now, &timeouts->when, >)) {
|
||||
t = timeouts;
|
||||
timeouts = timeouts->next;
|
||||
t->callback(t->arg);
|
||||
t->next = free_timeouts;
|
||||
free_timeouts = t;
|
||||
continue;
|
||||
}
|
||||
timersub(&timeouts->when, &now, &tv);
|
||||
if (tv.tv_sec > INT_MAX / 1000 ||
|
||||
(tv.tv_sec == INT_MAX / 1000 &&
|
||||
(tv.tv_usec + 999) / 1000 > INT_MAX % 1000))
|
||||
msecs = INT_MAX;
|
||||
else
|
||||
msecs = tv.tv_sec * 1000 +
|
||||
(tv.tv_usec + 999) / 1000;
|
||||
} else
|
||||
/* No timeouts, so wait forever. */
|
||||
msecs = -1;
|
||||
|
||||
/* Allocate memory for our pollfds as and when needed.
|
||||
* We don't bother shrinking it. */
|
||||
nfds = 0;
|
||||
for (e = events; e; e = e->next)
|
||||
nfds++;
|
||||
if (msecs == -1 && nfds == 0) {
|
||||
syslog(LOG_ERR, "nothing to do");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (nfds > fds_len) {
|
||||
free(fds);
|
||||
/* Allocate 5 more than we need for future use */
|
||||
fds_len = nfds + 5;
|
||||
fds = xmalloc(sizeof(*fds) * fds_len);
|
||||
}
|
||||
nfds = 0;
|
||||
for (e = events; e; e = e->next) {
|
||||
fds[nfds].fd = e->fd;
|
||||
fds[nfds].events = POLLIN;
|
||||
fds[nfds].revents = 0;
|
||||
nfds++;
|
||||
}
|
||||
n = poll(fds, nfds, msecs);
|
||||
if (n == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR) {
|
||||
get_monotonic(&now);
|
||||
continue;
|
||||
}
|
||||
syslog(LOG_ERR, "poll: %m");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Get the now time and process any triggered events. */
|
||||
get_monotonic(&now);
|
||||
if (n == 0)
|
||||
continue;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
if (!(fds[i].revents & (POLLIN | POLLHUP)))
|
||||
continue;
|
||||
for (e = events; e; e = e->next) {
|
||||
if (e->fd == fds[i].fd) {
|
||||
e->callback(e->arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
41
external/bsd/dhcpcd/dist/eloop.h
vendored
Normal file
41
external/bsd/dhcpcd/dist/eloop.h
vendored
Normal 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 ELOOP_H
|
||||
#define ELOOP_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
void add_event(int fd, void (*)(void *), void *);
|
||||
void delete_event(int fd);
|
||||
void add_timeout_sec(time_t, void (*)(void *), void *);
|
||||
void add_timeout_tv(const struct timeval *, void (*)(void *), void *);
|
||||
void delete_timeout(void (*)(void *), void *);
|
||||
void delete_timeouts(void *, void (*)(void *), ...);
|
||||
void start_eloop(void);
|
||||
|
||||
#endif
|
269
external/bsd/dhcpcd/dist/if-bsd.c
vendored
269
external/bsd/dhcpcd/dist/if-bsd.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,44 +25,108 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef __DragonFly__
|
||||
# include <netproto/802_11/ieee80211_ioctl.h>
|
||||
#else
|
||||
# include <net80211/ieee80211_ioctl.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "configure.h"
|
||||
#include "dhcp.h"
|
||||
#include "if-options.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
|
||||
#define ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
|
||||
|
||||
/* FIXME: Why do we need to check for sa_family 255 */
|
||||
#define COPYOUT(sin, sa) \
|
||||
sin.s_addr = ((sa) != NULL && ((sa)->sa_family == AF_INET || \
|
||||
(sa)->sa_family == 255)) \
|
||||
? \
|
||||
(((struct sockaddr_in *)sa)->sin_addr).s_addr : 0
|
||||
|
||||
static int a_fd = -1;
|
||||
static int r_fd = -1;
|
||||
|
||||
int
|
||||
if_address(const char *ifname, const struct in_addr *address,
|
||||
const struct in_addr *netmask, const struct in_addr *broadcast,
|
||||
int action)
|
||||
init_socket(void)
|
||||
{
|
||||
if ((a_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return -1;
|
||||
set_cloexec(a_fd);
|
||||
if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
|
||||
return -1;
|
||||
set_cloexec(r_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
getifssid(const char *ifname, char *ssid)
|
||||
{
|
||||
int retval = -1;
|
||||
#if defined(SIOCG80211NWID)
|
||||
struct ifreq ifr;
|
||||
struct ieee80211_nwid nwid;
|
||||
#elif defined(IEEE80211_IOC_SSID)
|
||||
struct ieee80211req ireq;
|
||||
char nwid[IEEE80211_NWID_LEN + 1];
|
||||
#endif
|
||||
|
||||
#if defined(SIOCG80211NWID) /* NetBSD */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
memset(&nwid, 0, sizeof(nwid));
|
||||
ifr.ifr_data = (void *)&nwid;
|
||||
if (ioctl(a_fd, SIOCG80211NWID, &ifr) == 0) {
|
||||
retval = nwid.i_len;
|
||||
memcpy(ssid, nwid.i_nwid, nwid.i_len);
|
||||
ssid[nwid.i_len] = '\0';
|
||||
}
|
||||
#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
|
||||
memset(&ireq, 0, sizeof(ireq));
|
||||
strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
|
||||
ireq.i_type = IEEE80211_IOC_SSID;
|
||||
ireq.i_val = -1;
|
||||
ireq.i_data = &nwid;
|
||||
if (ioctl(a_fd, SIOCG80211, &ireq) == 0) {
|
||||
retval = ireq.i_len;
|
||||
memcpy(ssid, nwid, ireq.i_len);
|
||||
ssid[ireq.i_len] = '\0';
|
||||
}
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
if_address(const struct interface *iface, 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 {
|
||||
@ -70,39 +134,36 @@ if_address(const char *ifname, const struct in_addr *address,
|
||||
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));
|
||||
strlcpy(ifa.ifra_name, iface->name, 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));
|
||||
#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) {
|
||||
if (action >= 0 && broadcast) {
|
||||
ADDADDR(ifa.ifra_broadaddr, broadcast);
|
||||
}
|
||||
#undef ADDADDR
|
||||
|
||||
if (action < 0)
|
||||
retval = ioctl(s, SIOCDIFADDR, &ifa);
|
||||
retval = ioctl(a_fd, SIOCDIFADDR, &ifa);
|
||||
else
|
||||
retval = ioctl(s, SIOCAIFADDR, &ifa);
|
||||
close(s);
|
||||
retval = ioctl(a_fd, SIOCAIFADDR, &ifa);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* ARGSUSED4 */
|
||||
int
|
||||
if_route(const struct interface *iface, const struct in_addr *dest,
|
||||
const struct in_addr *net, const struct in_addr *gate,
|
||||
_unused int metric, int action)
|
||||
const struct in_addr *net, const struct in_addr *gate,
|
||||
_unused int metric, int action)
|
||||
{
|
||||
int s;
|
||||
union sockunion {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
@ -121,21 +182,18 @@ if_route(const struct interface *iface, const struct in_addr *dest,
|
||||
size_t l;
|
||||
int retval = 0;
|
||||
|
||||
#define ADDSU(_su) { \
|
||||
l = SA_SIZE(&(_su.sa)); \
|
||||
memcpy(bp, &(_su), l); \
|
||||
bp += l; \
|
||||
}
|
||||
#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)); \
|
||||
ADDSU(su); \
|
||||
}
|
||||
|
||||
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
|
||||
return -1;
|
||||
#define ADDSU(_su) { \
|
||||
l = ROUNDUP(_su.sa.sa_len); \
|
||||
memcpy(bp, &(_su), l); \
|
||||
bp += l; \
|
||||
}
|
||||
#define ADDADDR(_a) { \
|
||||
memset (&su, 0, sizeof(su)); \
|
||||
su.sin.sin_family = AF_INET; \
|
||||
su.sin.sin_len = sizeof(su.sin); \
|
||||
memcpy (&su.sin.sin_addr, _a, sizeof(su.sin.sin_addr)); \
|
||||
ADDSU(su); \
|
||||
}
|
||||
|
||||
memset(&rtm, 0, sizeof(rtm));
|
||||
rtm.hdr.rtm_version = RTM_VERSION;
|
||||
@ -194,41 +252,59 @@ if_route(const struct interface *iface, const struct in_addr *dest,
|
||||
ADDADDR(&iface->addr);
|
||||
|
||||
rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
|
||||
if (write(s, &rtm, l) == -1)
|
||||
if (write(r_fd, &rtm, l) == -1)
|
||||
retval = -1;
|
||||
close(s);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int
|
||||
open_link_socket(struct interface *iface)
|
||||
open_link_socket(void)
|
||||
{
|
||||
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;
|
||||
if (fd != -1) {
|
||||
set_cloexec(fd);
|
||||
set_nonblock(fd);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void
|
||||
get_addrs(int type, char *cp, struct sockaddr **sa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTAX_MAX; i++) {
|
||||
if (type & (1 << i)) {
|
||||
sa[i] = (struct sockaddr *)cp;
|
||||
#ifdef DEBUG
|
||||
printf ("got %d %d %s\n", i, sa[i]->sa_family,
|
||||
inet_ntoa(((struct sockaddr_in *)sa[i])->
|
||||
sin_addr));
|
||||
#endif
|
||||
ADVANCE(cp, sa[i]);
|
||||
} else
|
||||
sa[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define BUFFER_LEN 2048
|
||||
int
|
||||
link_changed(struct interface *iface)
|
||||
manage_link(int fd)
|
||||
{
|
||||
char buffer[2048], *p;
|
||||
char buffer[2048], *p, *e, *cp;
|
||||
char ifname[IF_NAMESIZE];
|
||||
ssize_t bytes;
|
||||
struct rt_msghdr *rtm;
|
||||
struct if_announcemsghdr *ifan;
|
||||
struct if_msghdr *ifm;
|
||||
int i;
|
||||
struct ifa_msghdr *ifam;
|
||||
struct rt rt;
|
||||
struct sockaddr *sa, *rti_info[RTAX_MAX];
|
||||
|
||||
if ((i = if_nametoindex(iface->name)) == -1)
|
||||
return -1;
|
||||
for (;;) {
|
||||
bytes = recv(iface->link_fd, buffer, BUFFER_LEN, MSG_DONTWAIT);
|
||||
bytes = read(fd, buffer, BUFFER_LEN);
|
||||
if (bytes == -1) {
|
||||
if (errno == EAGAIN)
|
||||
return 0;
|
||||
@ -236,20 +312,59 @@ link_changed(struct interface *iface)
|
||||
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;
|
||||
e = buffer + bytes;
|
||||
for (p = buffer; p < e; p += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)(void *)p;
|
||||
switch(rtm->rtm_type) {
|
||||
case RTM_IFANNOUNCE:
|
||||
ifan = (struct if_announcemsghdr *)(void *)p;
|
||||
switch(ifan->ifan_what) {
|
||||
case IFAN_ARRIVAL:
|
||||
handle_interface(1, ifan->ifan_name);
|
||||
break;
|
||||
case IFAN_DEPARTURE:
|
||||
handle_interface(-1, ifan->ifan_name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RTM_IFINFO:
|
||||
ifm = (struct if_msghdr *)(void *)p;
|
||||
memset(ifname, 0, sizeof(ifname));
|
||||
if (if_indextoname(ifm->ifm_index, ifname))
|
||||
handle_interface(0, ifname);
|
||||
break;
|
||||
case RTM_DELETE:
|
||||
if (!(rtm->rtm_addrs & RTA_DST) ||
|
||||
!(rtm->rtm_addrs & RTA_GATEWAY) ||
|
||||
!(rtm->rtm_addrs & RTA_NETMASK))
|
||||
break;
|
||||
if (rtm->rtm_pid == getpid())
|
||||
break;
|
||||
cp = (char *)(void *)(rtm + 1);
|
||||
sa = (struct sockaddr *)(void *)cp;
|
||||
if (sa->sa_family != AF_INET)
|
||||
break;
|
||||
get_addrs(rtm->rtm_addrs, cp, rti_info);
|
||||
rt.iface = NULL;
|
||||
rt.next = NULL;
|
||||
COPYOUT(rt.dest, rti_info[RTAX_DST]);
|
||||
COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
|
||||
COPYOUT(rt.gate, rti_info[RTAX_GATEWAY]);
|
||||
route_deleted(&rt);
|
||||
break;
|
||||
case RTM_DELADDR:
|
||||
case RTM_NEWADDR:
|
||||
ifam = (struct ifa_msghdr *)(void *)p;
|
||||
cp = (char *)(void *)(ifam + 1);
|
||||
get_addrs(ifam->ifam_addrs, cp, rti_info);
|
||||
COPYOUT(rt.dest, rti_info[RTAX_IFA]);
|
||||
COPYOUT(rt.net, rti_info[RTAX_NETMASK]);
|
||||
COPYOUT(rt.gate, rti_info[RTAX_BRD]);
|
||||
if (if_indextoname(ifam->ifam_index, ifname))
|
||||
handle_ifa(rtm->rtm_type, ifname,
|
||||
&rt.dest, &rt.net, &rt.gate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
845
external/bsd/dhcpcd/dist/if-options.c
vendored
Normal file
845
external/bsd/dhcpcd/dist/if-options.c
vendored
Normal file
@ -0,0 +1,845 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2009 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 <arpa/inet.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "if-options.h"
|
||||
#include "net.h"
|
||||
|
||||
/* These options only make sense in the config file, so don't use any
|
||||
valid short options for them */
|
||||
#define O_BASE MAX('z', 'Z') + 1
|
||||
#define O_ARPING O_BASE + 1
|
||||
#define O_FALLBACK O_BASE + 2
|
||||
|
||||
const struct option cf_options[] = {
|
||||
{"background", no_argument, NULL, 'b'},
|
||||
{"script", required_argument, NULL, 'c'},
|
||||
{"debug", no_argument, NULL, 'd'},
|
||||
{"reconfigure", no_argument, NULL, 'e'},
|
||||
{"config", required_argument, NULL, 'f'},
|
||||
{"hostname", optional_argument, NULL, 'h'},
|
||||
{"vendorclassid", optional_argument, NULL, 'i'},
|
||||
{"release", no_argument, NULL, 'k'},
|
||||
{"leasetime", required_argument, NULL, 'l'},
|
||||
{"metric", required_argument, NULL, 'm'},
|
||||
{"rebind", no_argument, NULL, 'n'},
|
||||
{"option", required_argument, NULL, 'o'},
|
||||
{"persistent", no_argument, NULL, 'p'},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"request", optional_argument, NULL, 'r'},
|
||||
{"inform", optional_argument, NULL, 's'},
|
||||
{"timeout", required_argument, NULL, 't'},
|
||||
{"userclass", required_argument, NULL, 'u'},
|
||||
{"vendor", required_argument, NULL, 'v'},
|
||||
{"exit", no_argument, NULL, 'x'},
|
||||
{"allowinterfaces", required_argument, NULL, 'z'},
|
||||
{"reboot", required_argument, NULL, 'y'},
|
||||
{"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'},
|
||||
{"destination", required_argument, NULL, 'N'},
|
||||
{"nooption", optional_argument, NULL, 'O'},
|
||||
{"require", required_argument, NULL, 'Q'},
|
||||
{"static", required_argument, NULL, 'S'},
|
||||
{"test", no_argument, NULL, 'T'},
|
||||
{"variables", no_argument, NULL, 'V'},
|
||||
{"blacklist", required_argument, NULL, 'X'},
|
||||
{"denyinterfaces", required_argument, NULL, 'Z'},
|
||||
{"arping", required_argument, NULL, O_ARPING},
|
||||
{"fallback", required_argument, NULL, O_FALLBACK},
|
||||
{NULL, 0, NULL, '\0'}
|
||||
};
|
||||
|
||||
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)))
|
||||
{
|
||||
syslog(LOG_ERR, "`%s' out of range", s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int)n;
|
||||
}
|
||||
|
||||
static char *
|
||||
add_environ(struct if_options *ifo, const char *value, int uniq)
|
||||
{
|
||||
char **newlist;
|
||||
char **lst = ifo->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;
|
||||
ifo->environ = newlist;
|
||||
free(match);
|
||||
return newlist[i];
|
||||
}
|
||||
|
||||
#define parse_string(buf, len, arg) parse_string_hwaddr(buf, len, arg, 0)
|
||||
static ssize_t
|
||||
parse_string_hwaddr(char *sbuf, ssize_t slen, const char *str, int clid)
|
||||
{
|
||||
ssize_t l;
|
||||
const char *p;
|
||||
int i, punt_last = 0;
|
||||
char c[4];
|
||||
|
||||
/* If surrounded by quotes then it's a string */
|
||||
if (*str == '"') {
|
||||
str++;
|
||||
l = strlen(str);
|
||||
p = str + l - 1;
|
||||
if (*p == '"')
|
||||
punt_last = 1;
|
||||
} 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 && *str) {
|
||||
*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++;
|
||||
}
|
||||
if (punt_last)
|
||||
*--sbuf = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
static char **
|
||||
splitv(int *argc, char **argv, const char *arg)
|
||||
{
|
||||
char **v = argv;
|
||||
char *o = xstrdup(arg), *p, *t;
|
||||
|
||||
p = o;
|
||||
while ((t = strsep(&p, ", "))) {
|
||||
(*argc)++;
|
||||
v = xrealloc(v, sizeof(char *) * ((*argc)));
|
||||
v[(*argc) - 1] = xstrdup(t);
|
||||
}
|
||||
free(o);
|
||||
return v;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_addr(struct in_addr *addr, struct in_addr *net, const char *arg)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
if (arg == NULL || *arg == '\0') {
|
||||
if (addr != NULL)
|
||||
addr->s_addr = 0;
|
||||
if (net != NULL)
|
||||
net->s_addr = 0;
|
||||
return 0;
|
||||
}
|
||||
if ((p = strchr(arg, '/')) != NULL) {
|
||||
*p++ = '\0';
|
||||
if (net != NULL &&
|
||||
(sscanf(p, "%d", &i) != 1 ||
|
||||
inet_cidrtoaddr(i, net) != 0))
|
||||
{
|
||||
syslog(LOG_ERR, "`%s' is not a valid CIDR", p);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (addr != NULL && inet_aton(arg, addr) == 0) {
|
||||
syslog(LOG_ERR, "`%s' is not a valid IP address", arg);
|
||||
return -1;
|
||||
}
|
||||
if (p != NULL)
|
||||
*--p = '/';
|
||||
else if (net != NULL)
|
||||
net->s_addr = get_netmask(addr->s_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_option(struct if_options *ifo, int opt, const char *arg)
|
||||
{
|
||||
int i;
|
||||
char *p = NULL, *np;
|
||||
ssize_t s;
|
||||
struct in_addr addr, addr2;
|
||||
struct rt *rt;
|
||||
|
||||
switch(opt) {
|
||||
case 'e': /* FALLTHROUGH */
|
||||
case 'n': /* FALLTHROUGH */
|
||||
case 'x': /* FALLTHROUGH */
|
||||
case 'T': /* We need to handle non interface options */
|
||||
break;
|
||||
case 'b':
|
||||
ifo->options |= DHCPCD_BACKGROUND;
|
||||
break;
|
||||
case 'c':
|
||||
strlcpy(ifo->script, arg, sizeof(ifo->script));
|
||||
break;
|
||||
case 'd':
|
||||
ifo->options |= DHCPCD_DEBUG;
|
||||
break;
|
||||
case 'h':
|
||||
if (arg) {
|
||||
s = parse_string(ifo->hostname,
|
||||
HOSTNAME_MAX_LEN, arg);
|
||||
if (s == -1) {
|
||||
syslog(LOG_ERR, "hostname: %m");
|
||||
return -1;
|
||||
}
|
||||
if (s != 0 && ifo->hostname[0] == '.') {
|
||||
syslog(LOG_ERR,
|
||||
"hostname cannot begin with .");
|
||||
return -1;
|
||||
}
|
||||
ifo->hostname[s] = '\0';
|
||||
}
|
||||
if (ifo->hostname[0] == '\0')
|
||||
ifo->options &= ~DHCPCD_HOSTNAME;
|
||||
else
|
||||
ifo->options |= DHCPCD_HOSTNAME;
|
||||
break;
|
||||
case 'i':
|
||||
if (arg)
|
||||
s = parse_string((char *)ifo->vendorclassid + 1,
|
||||
VENDORCLASSID_MAX_LEN, arg);
|
||||
else
|
||||
s = 0;
|
||||
if (s == -1) {
|
||||
syslog(LOG_ERR, "vendorclassid: %m");
|
||||
return -1;
|
||||
}
|
||||
*ifo->vendorclassid = (uint8_t)s;
|
||||
break;
|
||||
case 'k':
|
||||
ifo->options |= DHCPCD_RELEASE;
|
||||
break;
|
||||
case 'l':
|
||||
if (*arg == '-') {
|
||||
syslog(LOG_ERR,
|
||||
"leasetime must be a positive value");
|
||||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
ifo->leasetime = (uint32_t)strtol(arg, NULL, 0);
|
||||
if (errno == EINVAL || errno == ERANGE) {
|
||||
syslog(LOG_ERR, "`%s' out of range", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
ifo->metric = atoint(arg);
|
||||
if (ifo->metric < 0) {
|
||||
syslog(LOG_ERR, "metric must be a positive value");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (make_option_mask(ifo->requestmask, arg, 1) != 0) {
|
||||
syslog(LOG_ERR, "unknown option `%s'", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
ifo->options |= DHCPCD_PERSISTENT;
|
||||
break;
|
||||
case 'q':
|
||||
ifo->options |= DHCPCD_QUIET;
|
||||
break;
|
||||
case 'r':
|
||||
ifo->options |= DHCPCD_REQUEST;
|
||||
if (parse_addr(&ifo->req_addr, NULL, arg) != 0)
|
||||
return -1;
|
||||
ifo->req_mask.s_addr = 0;
|
||||
break;
|
||||
case 's':
|
||||
ifo->options |= DHCPCD_INFORM | DHCPCD_PERSISTENT;
|
||||
ifo->options &= ~(DHCPCD_ARP | DHCPCD_STATIC);
|
||||
if (arg && *arg != '\0') {
|
||||
if (parse_addr(&ifo->req_addr, &ifo->req_mask,
|
||||
arg) != 0)
|
||||
return -1;
|
||||
} else {
|
||||
ifo->req_addr.s_addr = 0;
|
||||
ifo->req_mask.s_addr = 0;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
ifo->timeout = atoint(arg);
|
||||
if (ifo->timeout < 0) {
|
||||
syslog(LOG_ERR, "timeout must be a positive value");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
s = USERCLASS_MAX_LEN - ifo->userclass[0] - 1;
|
||||
s = parse_string((char *)ifo->userclass +
|
||||
ifo->userclass[0] + 2,
|
||||
s, arg);
|
||||
if (s == -1) {
|
||||
syslog(LOG_ERR, "userclass: %m");
|
||||
return -1;
|
||||
}
|
||||
if (s != 0) {
|
||||
ifo->userclass[ifo->userclass[0] + 1] = s;
|
||||
ifo->userclass[0] += s + 1;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
p = strchr(arg, ',');
|
||||
if (!p || !p[1]) {
|
||||
syslog(LOG_ERR, "invalid vendor format");
|
||||
return -1;
|
||||
}
|
||||
*p = '\0';
|
||||
i = atoint(arg);
|
||||
arg = p + 1;
|
||||
if (i < 1 || i > 254) {
|
||||
syslog(LOG_ERR, "vendor option should be between"
|
||||
" 1 and 254 inclusive");
|
||||
return -1;
|
||||
}
|
||||
s = VENDOR_MAX_LEN - ifo->vendor[0] - 2;
|
||||
if (inet_aton(arg, &addr) == 1) {
|
||||
if (s < 6) {
|
||||
s = -1;
|
||||
errno = ENOBUFS;
|
||||
} else
|
||||
memcpy(ifo->vendor + ifo->vendor[0] + 3,
|
||||
&addr.s_addr, sizeof(addr.s_addr));
|
||||
} else {
|
||||
s = parse_string((char *)ifo->vendor +
|
||||
ifo->vendor[0] + 3, s, arg);
|
||||
}
|
||||
if (s == -1) {
|
||||
syslog(LOG_ERR, "vendor: %m");
|
||||
return -1;
|
||||
}
|
||||
if (s != 0) {
|
||||
ifo->vendor[ifo->vendor[0] + 1] = i;
|
||||
ifo->vendor[ifo->vendor[0] + 2] = s;
|
||||
ifo->vendor[0] += s + 2;
|
||||
}
|
||||
break;
|
||||
case 'y':
|
||||
ifo->reboot = atoint(arg);
|
||||
if (ifo->reboot < 0) {
|
||||
syslog(LOG_ERR, "reboot must be a positive value");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
/* We only set this if we haven't got any interfaces */
|
||||
if (!ifaces)
|
||||
ifav = splitv(&ifac, ifav, arg);
|
||||
break;
|
||||
case 'A':
|
||||
ifo->options &= ~DHCPCD_ARP;
|
||||
/* IPv4LL requires ARP */
|
||||
ifo->options &= ~DHCPCD_IPV4LL;
|
||||
break;
|
||||
case 'B':
|
||||
ifo->options &= ~DHCPCD_DAEMONISE;
|
||||
break;
|
||||
case 'C':
|
||||
/* Commas to spaces for shell */
|
||||
while ((p = strchr(arg, ',')))
|
||||
*p = ' ';
|
||||
s = strlen("skip_hooks=") + strlen(arg) + 1;
|
||||
p = xmalloc(sizeof(char) * s);
|
||||
snprintf(p, s, "skip_hooks=%s", arg);
|
||||
add_environ(ifo, p, 0);
|
||||
free(p);
|
||||
break;
|
||||
case 'D':
|
||||
ifo->options |= DHCPCD_CLIENTID | DHCPCD_DUID;
|
||||
break;
|
||||
case 'E':
|
||||
ifo->options |= DHCPCD_LASTLEASE;
|
||||
break;
|
||||
case 'F':
|
||||
if (!arg) {
|
||||
ifo->fqdn = FQDN_BOTH;
|
||||
break;
|
||||
}
|
||||
if (strcmp(arg, "none") == 0)
|
||||
ifo->fqdn = FQDN_NONE;
|
||||
else if (strcmp(arg, "ptr") == 0)
|
||||
ifo->fqdn = FQDN_PTR;
|
||||
else if (strcmp(arg, "both") == 0)
|
||||
ifo->fqdn = FQDN_BOTH;
|
||||
else if (strcmp(arg, "disable") == 0)
|
||||
ifo->fqdn = FQDN_DISABLE;
|
||||
else {
|
||||
syslog(LOG_ERR, "invalid value `%s' for FQDN", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
ifo->options &= ~DHCPCD_GATEWAY;
|
||||
break;
|
||||
case 'I':
|
||||
/* Strings have a type of 0 */;
|
||||
ifo->clientid[1] = 0;
|
||||
if (arg)
|
||||
s = parse_string_hwaddr((char *)ifo->clientid + 1,
|
||||
CLIENTID_MAX_LEN, arg, 1);
|
||||
else
|
||||
s = 0;
|
||||
if (s == -1) {
|
||||
syslog(LOG_ERR, "clientid: %m");
|
||||
return -1;
|
||||
}
|
||||
ifo->options |= DHCPCD_CLIENTID;
|
||||
ifo->clientid[0] = (uint8_t)s;
|
||||
break;
|
||||
case 'K':
|
||||
ifo->options &= ~DHCPCD_LINK;
|
||||
break;
|
||||
case 'L':
|
||||
ifo->options &= ~DHCPCD_IPV4LL;
|
||||
break;
|
||||
case 'N':
|
||||
if (make_option_mask(ifo->dstmask, arg, 2) != 0) {
|
||||
if (errno == EINVAL)
|
||||
syslog(LOG_ERR, "option `%s' does not take"
|
||||
" an IPv4 address", arg);
|
||||
else
|
||||
syslog(LOG_ERR, "unknown otpion `%s'", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
if (make_option_mask(ifo->requestmask, arg, -1) != 0 ||
|
||||
make_option_mask(ifo->requiremask, arg, -1) != 0 ||
|
||||
make_option_mask(ifo->nomask, arg, 1) != 0)
|
||||
{
|
||||
syslog(LOG_ERR, "unknown option `%s'", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'Q':
|
||||
if (make_option_mask(ifo->requiremask, arg, 1) != 0 ||
|
||||
make_option_mask(ifo->requestmask, arg, 1) != 0)
|
||||
{
|
||||
syslog(LOG_ERR, "unknown option `%s'", arg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
p = strchr(arg, '=');
|
||||
if (p == NULL) {
|
||||
syslog(LOG_ERR, "static assignment required");
|
||||
return -1;
|
||||
}
|
||||
p++;
|
||||
if (strncmp(arg, "ip_address=", strlen("ip_address=")) == 0) {
|
||||
if (parse_addr(&ifo->req_addr, &ifo->req_mask, p) != 0)
|
||||
return -1;
|
||||
|
||||
ifo->options |= DHCPCD_STATIC;
|
||||
ifo->options &= ~DHCPCD_INFORM;
|
||||
} else if (strncmp(arg, "routes=", strlen("routes=")) == 0 ||
|
||||
strncmp(arg, "static_routes=", strlen("static_routes=")) == 0 ||
|
||||
strncmp(arg, "classless_static_routes=", strlen("classless_static_routes=")) == 0 ||
|
||||
strncmp(arg, "ms_classless_static_routes=", strlen("ms_classless_static_routes=")) == 0)
|
||||
{
|
||||
np = strchr(p, ' ');
|
||||
if (np == NULL) {
|
||||
syslog(LOG_ERR, "all routes need a gateway");
|
||||
return -1;
|
||||
}
|
||||
*np++ = '\0';
|
||||
while (*np == ' ')
|
||||
np++;
|
||||
if (ifo->routes == NULL) {
|
||||
rt = ifo->routes = xmalloc(sizeof(*rt));
|
||||
} else {
|
||||
rt = ifo->routes;
|
||||
while (rt->next)
|
||||
rt = rt->next;
|
||||
rt->next = xmalloc(sizeof(*rt));
|
||||
rt = rt->next;
|
||||
}
|
||||
rt->next = NULL;
|
||||
if (parse_addr(&rt->dest, &rt->net, p) == -1 ||
|
||||
parse_addr(&rt->gate, NULL, np) == -1)
|
||||
return -1;
|
||||
} else if (strncmp(arg, "routers=", strlen("routers=")) == 0) {
|
||||
if (ifo->routes == NULL) {
|
||||
rt = ifo->routes = xzalloc(sizeof(*rt));
|
||||
} else {
|
||||
rt = ifo->routes;
|
||||
while (rt->next)
|
||||
rt = rt->next;
|
||||
rt->next = xmalloc(sizeof(*rt));
|
||||
rt = rt->next;
|
||||
}
|
||||
rt->dest.s_addr = INADDR_ANY;
|
||||
rt->net.s_addr = INADDR_ANY;
|
||||
rt->next = NULL;
|
||||
if (parse_addr(&rt->gate, NULL, p) == -1)
|
||||
return -1;
|
||||
} else {
|
||||
s = 0;
|
||||
if (ifo->config != NULL) {
|
||||
while (ifo->config[s] != NULL) {
|
||||
if (strncmp(ifo->config[s], arg,
|
||||
p - arg) == 0)
|
||||
{
|
||||
free(ifo->config[s]);
|
||||
ifo->config[s] = xstrdup(arg);
|
||||
return 1;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
ifo->config = xrealloc(ifo->config,
|
||||
sizeof(char *) * (s + 2));
|
||||
ifo->config[s] = xstrdup(arg);
|
||||
ifo->config[s + 1] = NULL;
|
||||
}
|
||||
break;
|
||||
case 'X':
|
||||
if (parse_addr(&addr, &addr2, arg) != 0)
|
||||
return -1;
|
||||
if (strchr(arg, '/') == NULL)
|
||||
addr2.s_addr = INADDR_BROADCAST;
|
||||
ifo->blacklist = xrealloc(ifo->blacklist,
|
||||
sizeof(in_addr_t) * (ifo->blacklist_len + 2));
|
||||
ifo->blacklist[ifo->blacklist_len++] = addr.s_addr;
|
||||
ifo->blacklist[ifo->blacklist_len++] = addr2.s_addr;
|
||||
break;
|
||||
case 'Z':
|
||||
/* We only set this if we haven't got any interfaces */
|
||||
if (!ifaces)
|
||||
ifdv = splitv(&ifdc, ifdv, arg);
|
||||
break;
|
||||
case O_ARPING:
|
||||
if (parse_addr(&addr, NULL, arg) != 0)
|
||||
return -1;
|
||||
ifo->arping = xrealloc(ifo->arping,
|
||||
sizeof(in_addr_t) * (ifo->arping_len + 1));
|
||||
ifo->arping[ifo->arping_len++] = addr.s_addr;
|
||||
break;
|
||||
case O_FALLBACK:
|
||||
free(ifo->fallback);
|
||||
ifo->fallback = xstrdup(arg);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_config_line(struct if_options *ifo, const char *opt, char *line)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(cf_options) / sizeof(cf_options[0]); i++) {
|
||||
if (!cf_options[i].name ||
|
||||
strcmp(cf_options[i].name, opt) != 0)
|
||||
continue;
|
||||
|
||||
if (cf_options[i].has_arg == required_argument && !line) {
|
||||
fprintf(stderr,
|
||||
PACKAGE ": option requires an argument -- %s\n",
|
||||
opt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return parse_option(ifo, cf_options[i].val, line);
|
||||
}
|
||||
|
||||
fprintf(stderr, PACKAGE ": unknown option -- %s\n", opt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct if_options *
|
||||
read_config(const char *file,
|
||||
const char *ifname, const char *ssid, const char *profile)
|
||||
{
|
||||
struct if_options *ifo;
|
||||
FILE *f;
|
||||
char *line, *option, *p;
|
||||
int skip = 0, have_profile = 0;
|
||||
|
||||
/* Seed our default options */
|
||||
ifo = xzalloc(sizeof(*ifo));
|
||||
ifo->options |= DHCPCD_GATEWAY | DHCPCD_DAEMONISE;
|
||||
ifo->options |= DHCPCD_ARP | DHCPCD_IPV4LL | DHCPCD_LINK;
|
||||
ifo->timeout = DEFAULT_TIMEOUT;
|
||||
ifo->reboot = DEFAULT_REBOOT;
|
||||
ifo->metric = -1;
|
||||
strlcpy(ifo->script, SCRIPT, sizeof(ifo->script));
|
||||
gethostname(ifo->hostname, HOSTNAME_MAX_LEN);
|
||||
/* Ensure that the hostname is NULL terminated */
|
||||
ifo->hostname[HOSTNAME_MAX_LEN] = '\0';
|
||||
if (strcmp(ifo->hostname, "(none)") == 0 ||
|
||||
strcmp(ifo->hostname, "localhost") == 0)
|
||||
ifo->hostname[0] = '\0';
|
||||
ifo->vendorclassid[0] = snprintf((char *)ifo->vendorclassid + 1,
|
||||
VENDORCLASSID_MAX_LEN,
|
||||
"%s %s", PACKAGE, VERSION);
|
||||
|
||||
/* Parse our options file */
|
||||
f = fopen(file ? file : CONFIG, "r");
|
||||
if (!f)
|
||||
return ifo;
|
||||
|
||||
while ((line = get_line(f))) {
|
||||
option = strsep(&line, " \t");
|
||||
/* Trim trailing whitespace */
|
||||
if (line && *line) {
|
||||
p = line + strlen(line) - 1;
|
||||
while (p != line &&
|
||||
(*p == ' ' || *p == '\t') &&
|
||||
*(p - 1) != '\\')
|
||||
*p-- = '\0';
|
||||
}
|
||||
/* Start of an interface block, skip if not ours */
|
||||
if (strcmp(option, "interface") == 0) {
|
||||
if (ifname && line && strcmp(line, ifname) == 0)
|
||||
skip = 0;
|
||||
else
|
||||
skip = 1;
|
||||
continue;
|
||||
}
|
||||
/* Start of an ssid block, skip if not ours */
|
||||
if (strcmp(option, "ssid") == 0) {
|
||||
if (ssid && line && strcmp(line, ssid) == 0)
|
||||
skip = 0;
|
||||
else
|
||||
skip = 1;
|
||||
continue;
|
||||
}
|
||||
/* Start of a profile block, skip if not ours */
|
||||
if (strcmp(option, "profile") == 0) {
|
||||
if (profile && line && strcmp(line, profile) == 0) {
|
||||
skip = 0;
|
||||
have_profile = 1;
|
||||
} else
|
||||
skip = 1;
|
||||
continue;
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
if (parse_config_line(ifo, option, line) != 1)
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (profile && !have_profile) {
|
||||
free_options(ifo);
|
||||
errno = ENOENT;
|
||||
ifo = NULL;
|
||||
}
|
||||
|
||||
/* Terminate the encapsulated options */
|
||||
if (ifo && ifo->vendor[0]) {
|
||||
ifo->vendor[0]++;
|
||||
ifo->vendor[ifo->vendor[0]] = DHO_END;
|
||||
}
|
||||
return ifo;
|
||||
}
|
||||
|
||||
int
|
||||
add_options(struct if_options *ifo, int argc, char **argv)
|
||||
{
|
||||
int oi, opt, r = 1;
|
||||
|
||||
optind = 0;
|
||||
while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
|
||||
{
|
||||
r = parse_option(ifo, opt, optarg);
|
||||
if (r != 1)
|
||||
break;
|
||||
}
|
||||
/* Terminate the encapsulated options */
|
||||
if (r == 1 && ifo->vendor[0]) {
|
||||
ifo->vendor[0]++;
|
||||
ifo->vendor[ifo->vendor[0]] = DHO_END;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
free_options(struct if_options *ifo)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (ifo) {
|
||||
if (ifo->environ) {
|
||||
i = 0;
|
||||
while (ifo->environ[i])
|
||||
free(ifo->environ[i++]);
|
||||
free(ifo->environ);
|
||||
}
|
||||
if (ifo->config) {
|
||||
i = 0;
|
||||
while (ifo->config[i])
|
||||
free(ifo->config[i++]);
|
||||
free(ifo->config);
|
||||
}
|
||||
free_routes(ifo->routes);
|
||||
free(ifo->arping);
|
||||
free(ifo->blacklist);
|
||||
free(ifo->fallback);
|
||||
free(ifo);
|
||||
}
|
||||
}
|
113
external/bsd/dhcpcd/dist/if-options.h
vendored
Normal file
113
external/bsd/dhcpcd/dist/if-options.h
vendored
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2009 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 IF_OPTIONS_H
|
||||
#define IF_OPTIONS_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* Don't set any optional arguments here so we retain POSIX
|
||||
* compatibility with getopt */
|
||||
#define IF_OPTS "bc:def:h:i:kl:m:no:pqr:s:t:u:v:xy:z:ABC:DEF:GI:KLN:O:Q:TVX:Z:"
|
||||
|
||||
#define DEFAULT_TIMEOUT 30
|
||||
#define DEFAULT_REBOOT 10
|
||||
|
||||
#define HOSTNAME_MAX_LEN 250 /* 255 - 3 (FQDN) - 2 (DNS enc) */
|
||||
#define VENDORCLASSID_MAX_LEN 48
|
||||
#define CLIENTID_MAX_LEN 48
|
||||
#define USERCLASS_MAX_LEN 255
|
||||
#define VENDOR_MAX_LEN 255
|
||||
|
||||
#define DHCPCD_ARP (1 << 0)
|
||||
#define DHCPCD_RELEASE (1 << 1)
|
||||
#define DHCPCD_DOMAIN (1 << 2)
|
||||
#define DHCPCD_GATEWAY (1 << 3)
|
||||
#define DHCPCD_STATIC (1 << 4)
|
||||
#define DHCPCD_DEBUG (1 << 5)
|
||||
#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_MASTER (1 << 17)
|
||||
#define DHCPCD_HOSTNAME (1 << 18)
|
||||
#define DHCPCD_CLIENTID (1 << 19)
|
||||
#define DHCPCD_LINK (1 << 20)
|
||||
#define DHCPCD_QUIET (1 << 21)
|
||||
#define DHCPCD_BACKGROUND (1 << 22)
|
||||
|
||||
extern const struct option cf_options[];
|
||||
|
||||
struct if_options {
|
||||
int metric;
|
||||
uint8_t requestmask[256 / 8];
|
||||
uint8_t requiremask[256 / 8];
|
||||
uint8_t nomask[256 / 8];
|
||||
uint8_t dstmask[256 / 8];
|
||||
uint32_t leasetime;
|
||||
time_t timeout;
|
||||
time_t reboot;
|
||||
int options;
|
||||
|
||||
struct in_addr req_addr;
|
||||
struct in_addr req_mask;
|
||||
struct rt *routes;
|
||||
char **config;
|
||||
|
||||
char **environ;
|
||||
char script[PATH_MAX];
|
||||
|
||||
char hostname[HOSTNAME_MAX_LEN + 1]; /* We don't store the length */
|
||||
int fqdn;
|
||||
uint8_t vendorclassid[VENDORCLASSID_MAX_LEN + 2];
|
||||
char clientid[CLIENTID_MAX_LEN + 2];
|
||||
uint8_t userclass[USERCLASS_MAX_LEN + 2];
|
||||
uint8_t vendor[VENDOR_MAX_LEN + 2];
|
||||
|
||||
size_t blacklist_len;
|
||||
in_addr_t *blacklist;
|
||||
size_t arping_len;
|
||||
in_addr_t *arping;
|
||||
char *fallback;
|
||||
};
|
||||
|
||||
struct if_options *read_config(const char *,
|
||||
const char *, const char *, const char *);
|
||||
int add_options(struct if_options *, int, char **);
|
||||
void free_options(struct if_options *);
|
||||
|
||||
#endif
|
106
external/bsd/dhcpcd/dist/if-pref.c
vendored
Normal file
106
external/bsd/dhcpcd/dist/if-pref.c
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2009 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 "config.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "if-pref.h"
|
||||
#include "net.h"
|
||||
|
||||
/* Interface comparer for working out ordering. */
|
||||
static int
|
||||
ifcmp(struct interface *si, struct interface *ti)
|
||||
{
|
||||
int sill, till;
|
||||
|
||||
if (si->state && !ti->state)
|
||||
return -1;
|
||||
if (!si->state && ti->state)
|
||||
return 1;
|
||||
if (!si->state && !ti->state)
|
||||
return 0;
|
||||
/* If one has a lease and the other not, it takes precedence. */
|
||||
if (si->state->new && !ti->state->new)
|
||||
return -1;
|
||||
if (!si->state->new && ti->state->new)
|
||||
return 1;
|
||||
/* If we are either, they neither have a lease, or they both have.
|
||||
* We need to check for IPv4LL and make it non-preferred. */
|
||||
if (si->state->new) {
|
||||
sill = IN_LINKLOCAL(htonl(si->state->new->yiaddr));
|
||||
till = IN_LINKLOCAL(htonl(ti->state->new->yiaddr));
|
||||
if (!sill && till)
|
||||
return -1;
|
||||
if (sill && !till)
|
||||
return 1;
|
||||
}
|
||||
/* Then carrier status. */
|
||||
if (si->carrier > ti->carrier)
|
||||
return -1;
|
||||
if (si->carrier < ti->carrier)
|
||||
return 1;
|
||||
/* Finally, metric */
|
||||
if (si->metric < ti->metric)
|
||||
return -1;
|
||||
if (si->metric > ti->metric)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sort the interfaces into a preferred order - best first, worst last. */
|
||||
void
|
||||
sort_interfaces(void)
|
||||
{
|
||||
struct interface *sorted, *ifp, *ifn, *ift;
|
||||
|
||||
if (!ifaces || !ifaces->next)
|
||||
return;
|
||||
sorted = ifaces;
|
||||
ifaces = ifaces->next;
|
||||
sorted->next = NULL;
|
||||
for (ifp = ifaces; ifp && (ifn = ifp->next, 1); ifp = ifn) {
|
||||
/* Are we the new head? */
|
||||
if (ifcmp(ifp, sorted) == -1) {
|
||||
ifp->next = sorted;
|
||||
sorted = ifp;
|
||||
continue;
|
||||
}
|
||||
/* Do we fit in the middle? */
|
||||
for (ift = sorted; ift->next; ift = ift->next) {
|
||||
if (ifcmp(ifp, ift->next) == -1) {
|
||||
ifp->next = ift->next;
|
||||
ift->next = ifp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* We must be at the end */
|
||||
if (!ift->next) {
|
||||
ift->next = ifp;
|
||||
ifp->next = NULL;
|
||||
}
|
||||
}
|
||||
ifaces = sorted;
|
||||
}
|
34
external/bsd/dhcpcd/dist/if-pref.h
vendored
Normal file
34
external/bsd/dhcpcd/dist/if-pref.h
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 IF_PREF_H
|
||||
#define IF_PREF_H
|
||||
|
||||
#include "dhcpcd.h"
|
||||
|
||||
void sort_interfaces(void);
|
||||
#endif
|
132
external/bsd/dhcpcd/dist/ipv4ll.c
vendored
Normal file
132
external/bsd/dhcpcd/dist/ipv4ll.c
vendored
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 <errno.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "arp.h"
|
||||
#include "common.h"
|
||||
#include "dhcpcd.h"
|
||||
#include "eloop.h"
|
||||
#include "if-options.h"
|
||||
#include "ipv4ll.h"
|
||||
#include "net.h"
|
||||
|
||||
static struct dhcp_message*
|
||||
make_ipv4ll_lease(uint32_t old_addr)
|
||||
{
|
||||
uint32_t u32;
|
||||
struct dhcp_message *dhcp;
|
||||
uint8_t *p;
|
||||
|
||||
dhcp = xzalloc(sizeof(*dhcp));
|
||||
/* Put some LL options in */
|
||||
p = dhcp->options;
|
||||
*p++ = DHO_SUBNETMASK;
|
||||
*p++ = sizeof(u32);
|
||||
u32 = htonl(LINKLOCAL_MASK);
|
||||
memcpy(p, &u32, sizeof(u32));
|
||||
p += sizeof(u32);
|
||||
*p++ = DHO_BROADCAST;
|
||||
*p++ = sizeof(u32);
|
||||
u32 = htonl(LINKLOCAL_BRDC);
|
||||
memcpy(p, &u32, sizeof(u32));
|
||||
p += sizeof(u32);
|
||||
*p++ = DHO_END;
|
||||
|
||||
for (;;) {
|
||||
dhcp->yiaddr = htonl(LINKLOCAL_ADDR |
|
||||
(((uint32_t)abs((int)arc4random())
|
||||
% 0xFD00) + 0x0100));
|
||||
if (dhcp->yiaddr != old_addr &&
|
||||
IN_LINKLOCAL(ntohl(dhcp->yiaddr)))
|
||||
break;
|
||||
}
|
||||
return dhcp;
|
||||
}
|
||||
|
||||
void
|
||||
start_ipv4ll(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
|
||||
iface->state->probes = 0;
|
||||
iface->state->claims = 0;
|
||||
if (iface->addr.s_addr) {
|
||||
iface->state->conflicts = 0;
|
||||
if (IN_LINKLOCAL(htonl(iface->addr.s_addr))) {
|
||||
send_arp_announce(iface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* We maybe rebooting an IPv4LL address. */
|
||||
if (!iface->state->offer ||
|
||||
!IN_LINKLOCAL(htonl(iface->state->offer->yiaddr)))
|
||||
{
|
||||
syslog(LOG_INFO, "%s: probing for an IPv4LL address",
|
||||
iface->name);
|
||||
delete_timeout(NULL, iface);
|
||||
free(iface->state->offer);
|
||||
iface->state->offer = make_ipv4ll_lease(0);
|
||||
iface->state->lease.frominfo = 0;
|
||||
}
|
||||
send_arp_probe(iface);
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipv4ll_failure(void *arg)
|
||||
{
|
||||
struct interface *iface = arg;
|
||||
time_t up;
|
||||
|
||||
if (iface->state->fail.s_addr == iface->state->lease.addr.s_addr) {
|
||||
up = uptime();
|
||||
if (iface->state->defend + DEFEND_INTERVAL > up) {
|
||||
drop_config(iface, "EXPIRE");
|
||||
iface->state->conflicts = -1;
|
||||
} else {
|
||||
iface->state->defend = up;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
close_sockets(iface);
|
||||
free(iface->state->offer);
|
||||
iface->state->offer = NULL;
|
||||
if (++iface->state->conflicts > MAX_CONFLICTS) {
|
||||
syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address",
|
||||
iface->name);
|
||||
iface->state->interval = RATE_LIMIT_INTERVAL / 2;
|
||||
start_discover(iface);
|
||||
} else {
|
||||
add_timeout_sec(PROBE_WAIT, start_ipv4ll, iface);
|
||||
}
|
||||
}
|
33
external/bsd/dhcpcd/dist/ipv4ll.h
vendored
Normal file
33
external/bsd/dhcpcd/dist/ipv4ll.h
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 IPV4LL_H
|
||||
#define IPV4LL_H
|
||||
|
||||
void start_ipv4ll(void *);
|
||||
void handle_ipv4ll_failure(void *);
|
||||
#endif
|
519
external/bsd/dhcpcd/dist/net.c
vendored
519
external/bsd/dhcpcd/dist/net.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -27,45 +27,50 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <arpa/inet.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>
|
||||
#ifdef AF_LINK
|
||||
# include <net/if_dl.h>
|
||||
# include <net/if_types.h>
|
||||
#endif
|
||||
#include <netinet/in_systm.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
|
||||
#include <netinet/udp.h>
|
||||
#undef __FAVOR_BSD
|
||||
#ifdef SIOCGIFMEDIA
|
||||
#include <net/if_media.h>
|
||||
#ifdef AF_PACKET
|
||||
# include <netpacket/packet.h>
|
||||
#endif
|
||||
#include <arpa/inet.h>
|
||||
#ifdef AF_LINK
|
||||
# include <net/if_dl.h>
|
||||
#ifdef SIOCGIFMEDIA
|
||||
# include <net/if_media.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "common.h"
|
||||
#include "dhcp.h"
|
||||
#include "logger.h"
|
||||
#include "if-options.h"
|
||||
#include "net.h"
|
||||
#include "signals.h"
|
||||
|
||||
static char hwaddr_buffer[(HWADDR_LEN * 3) + 1];
|
||||
|
||||
int
|
||||
inet_ntocidr(struct in_addr address)
|
||||
{
|
||||
@ -76,7 +81,6 @@ inet_ntocidr(struct in_addr address)
|
||||
cidr++;
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return cidr;
|
||||
}
|
||||
|
||||
@ -85,7 +89,7 @@ inet_cidrtoaddr(int cidr, struct in_addr *addr)
|
||||
{
|
||||
int ocets;
|
||||
|
||||
if (cidr < 0 || cidr > 32) {
|
||||
if (cidr < 1 || cidr > 32) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
@ -94,8 +98,9 @@ inet_cidrtoaddr(int cidr, struct in_addr *addr)
|
||||
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);
|
||||
|
||||
memset((unsigned char *)&addr->s_addr + (ocets - 1),
|
||||
(256 - (1 << (32 - cidr) % 8)), 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -123,8 +128,7 @@ get_netmask(uint32_t addr)
|
||||
char *
|
||||
hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
|
||||
{
|
||||
static char buffer[(HWADDR_LEN * 3) + 1];
|
||||
char *p = buffer;
|
||||
char *p = hwaddr_buffer;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < hwlen && i < HWADDR_LEN; i++) {
|
||||
@ -135,7 +139,7 @@ hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
|
||||
|
||||
*p ++= '\0';
|
||||
|
||||
return buffer;
|
||||
return hwaddr_buffer;
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -176,114 +180,227 @@ hwaddr_aton(unsigned char *buffer, const char *addr)
|
||||
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)
|
||||
struct interface *
|
||||
init_interface(const char *ifname)
|
||||
{
|
||||
int s;
|
||||
struct ifconf ifc;
|
||||
int retval = 0, found = 0;
|
||||
int len = 10 * sizeof(struct ifreq);
|
||||
int lastlen = 0;
|
||||
char *p;
|
||||
union {
|
||||
char *buffer;
|
||||
struct ifreq *ifr;
|
||||
} ifreqs;
|
||||
struct sockaddr_in address;
|
||||
struct ifreq *ifr;
|
||||
struct sockaddr_in netmask;
|
||||
#ifdef AF_LINK
|
||||
struct sockaddr_dl *sdl;
|
||||
#endif
|
||||
struct ifreq ifr;
|
||||
struct interface *iface = NULL;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
|
||||
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return -1;
|
||||
return NULL;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
|
||||
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1)
|
||||
goto eexit;
|
||||
|
||||
free(ifc.ifc_buf);
|
||||
ifc.ifc_buf = NULL;
|
||||
len *= 2;
|
||||
iface = xzalloc(sizeof(*iface));
|
||||
strlcpy(iface->name, ifname, sizeof(iface->name));
|
||||
iface->flags = ifr.ifr_flags;
|
||||
/* We reserve the 100 range for virtual interfaces, if and when
|
||||
* we can work them out. */
|
||||
iface->metric = 200 + if_nametoindex(iface->name);
|
||||
if (getifssid(ifname, iface->ssid) != -1) {
|
||||
iface->wireless = 1;
|
||||
iface->metric += 100;
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef __linux__
|
||||
if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
|
||||
p += offsetof(struct ifreq, ifr_ifru) +
|
||||
ifr->ifr_addr.sa_len;
|
||||
else
|
||||
if (up_interface(ifname) != 0)
|
||||
goto eexit;
|
||||
snprintf(iface->leasefile, sizeof(iface->leasefile),
|
||||
LEASEFILE, ifname);
|
||||
/* 0 is a valid fd, so init to -1 */
|
||||
iface->raw_fd = -1;
|
||||
iface->udp_fd = -1;
|
||||
iface->arp_fd = -1;
|
||||
close(s);
|
||||
return iface;
|
||||
|
||||
eexit:
|
||||
free(iface);
|
||||
close(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
free_interface(struct interface *iface)
|
||||
{
|
||||
if (!iface)
|
||||
return;
|
||||
if (iface->state) {
|
||||
free_options(iface->state->options);
|
||||
free(iface->state->old);
|
||||
free(iface->state->new);
|
||||
free(iface->state->offer);
|
||||
free(iface->state);
|
||||
}
|
||||
free(iface->clientid);
|
||||
free(iface);
|
||||
}
|
||||
|
||||
struct interface *
|
||||
discover_interfaces(int argc, char * const *argv)
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
char *p;
|
||||
int i;
|
||||
struct interface *ifp, *ifs, *ifl;
|
||||
#ifdef __linux__
|
||||
char ifn[IF_NAMESIZE];
|
||||
#endif
|
||||
p += sizeof(*ifr);
|
||||
|
||||
if (strcmp(ifname, ifr->ifr_name) != 0)
|
||||
continue;
|
||||
|
||||
found = 1;
|
||||
|
||||
#ifdef AF_LINK
|
||||
if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
|
||||
sdl = xmalloc(ifr->ifr_addr.sa_len);
|
||||
memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
|
||||
*hwlen = sdl->sdl_alen;
|
||||
memcpy(hwaddr, LLADDR(sdl), *hwlen);
|
||||
free(sdl);
|
||||
const struct sockaddr_dl *sdl;
|
||||
#elif AF_PACKET
|
||||
const struct sockaddr_ll *sll;
|
||||
#endif
|
||||
|
||||
if (getifaddrs(&ifaddrs) == -1)
|
||||
return NULL;
|
||||
|
||||
ifs = ifl = NULL;
|
||||
for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
||||
#ifdef AF_LINK
|
||||
if (ifa->ifa_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
#elif AF_PACKET
|
||||
if (ifa->ifa_addr->sa_family != AF_PACKET)
|
||||
continue;
|
||||
#endif
|
||||
/* It's possible for an interface to have >1 AF_LINK.
|
||||
* For our purposes, we use the first one. */
|
||||
for (ifp = ifs; ifp; ifp = ifp->next)
|
||||
if (strcmp(ifp->name, ifa->ifa_name) == 0)
|
||||
break;
|
||||
if (ifp)
|
||||
continue;
|
||||
if (argc > 0) {
|
||||
for (i = 0; i < argc; i++) {
|
||||
#ifdef __linux__
|
||||
/* Check the real interface name */
|
||||
strlcpy(ifn, argv[i], sizeof(ifn));
|
||||
p = strchr(ifn, ':');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
if (strcmp(ifn, ifa->ifa_name) == 0)
|
||||
break;
|
||||
#else
|
||||
if (strcmp(argv[i], ifa->ifa_name) == 0)
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
if (i == argc)
|
||||
continue;
|
||||
p = argv[i];
|
||||
} else {
|
||||
for (i = 0; i < ifdc; i++)
|
||||
if (!fnmatch(ifdv[i], ifa->ifa_name, 0))
|
||||
break;
|
||||
if (i < ifdc)
|
||||
continue;
|
||||
for (i = 0; i < ifac; i++)
|
||||
if (!fnmatch(ifav[i], ifa->ifa_name, 0))
|
||||
break;
|
||||
if (ifac && i == ifac)
|
||||
continue;
|
||||
p = ifa->ifa_name;
|
||||
}
|
||||
if ((ifp = init_interface(p)) == NULL)
|
||||
continue;
|
||||
/* Don't allow loopback unless explicit */
|
||||
if (ifp->flags & IFF_LOOPBACK) {
|
||||
if (argc == 0 && ifac == 0) {
|
||||
free_interface(ifp);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
#ifdef AF_LINK
|
||||
sdl = (const struct sockaddr_dl *)(void *)ifa->ifa_addr;
|
||||
switch(sdl->sdl_type) {
|
||||
case IFT_ETHER:
|
||||
ifp->family = ARPHRD_ETHER;
|
||||
break;
|
||||
case IFT_IEEE1394:
|
||||
ifp->family = ARPHRD_IEEE1394;
|
||||
break;
|
||||
}
|
||||
ifp->hwlen = sdl->sdl_alen;
|
||||
#ifndef CLLADDR
|
||||
# define CLLADDR(s) ((const char *)((s)->sdl_data + (s)->sdl_nlen))
|
||||
#endif
|
||||
memcpy(ifp->hwaddr, CLLADDR(sdl), ifp->hwlen);
|
||||
#elif AF_PACKET
|
||||
sll = (const struct sockaddr_ll *)(void *)ifa->ifa_addr;
|
||||
ifp->family = sll->sll_hatype;
|
||||
ifp->hwlen = sll->sll_halen;
|
||||
if (ifp->hwlen != 0)
|
||||
memcpy(ifp->hwaddr, sll->sll_addr, ifp->hwlen);
|
||||
#endif
|
||||
}
|
||||
if (ifl)
|
||||
ifl->next = ifp;
|
||||
else
|
||||
ifs = ifp;
|
||||
ifl = ifp;
|
||||
}
|
||||
freeifaddrs(ifaddrs);
|
||||
return ifs;
|
||||
}
|
||||
|
||||
int
|
||||
do_address(const char *ifname,
|
||||
struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act)
|
||||
{
|
||||
struct ifaddrs *ifaddrs, *ifa;
|
||||
const struct sockaddr_in *a, *n, *d;
|
||||
int retval;
|
||||
|
||||
if (getifaddrs(&ifaddrs) == -1)
|
||||
return -1;
|
||||
|
||||
retval = 0;
|
||||
for (ifa = ifaddrs; ifa; ifa = ifa->ifa_next) {
|
||||
if (ifa->ifa_addr->sa_family != AF_INET ||
|
||||
strcmp(ifa->ifa_name, ifname) != 0)
|
||||
continue;
|
||||
a = (const struct sockaddr_in *)(void *)&ifa->ifa_addr;
|
||||
n = (const struct sockaddr_in *)(void *)&ifa->ifa_netmask;
|
||||
if (ifa->ifa_flags & IFF_POINTOPOINT)
|
||||
d = (const struct sockaddr_in *)(void *)
|
||||
&ifa->ifa_dstaddr;
|
||||
else
|
||||
d = NULL;
|
||||
if (act == 1) {
|
||||
addr->s_addr = a->sin_addr.s_addr;
|
||||
net->s_addr = n->sin_addr.s_addr;
|
||||
if (dst && ifa->ifa_flags & IFF_POINTOPOINT)
|
||||
dst->s_addr = d->sin_addr.s_addr;
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ifr->ifr_addr.sa_family == AF_INET) {
|
||||
memcpy(&address, &ifr->ifr_addr, sizeof(address));
|
||||
if (ioctl(s, SIOCGIFNETMASK, ifr) == -1)
|
||||
continue;
|
||||
memcpy(&netmask, &ifr->ifr_addr, sizeof(netmask));
|
||||
if (get) {
|
||||
addr->s_addr = address.sin_addr.s_addr;
|
||||
net->s_addr = netmask.sin_addr.s_addr;
|
||||
retval = 1;
|
||||
break;
|
||||
} else {
|
||||
if (address.sin_addr.s_addr == addr->s_addr &&
|
||||
(!net ||
|
||||
netmask.sin_addr.s_addr == net->s_addr))
|
||||
{
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addr->s_addr == a->sin_addr.s_addr &&
|
||||
(net == NULL || net->s_addr == n->sin_addr.s_addr))
|
||||
{
|
||||
retval = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!found)
|
||||
errno = ENXIO;
|
||||
close(s);
|
||||
free(ifc.ifc_buf);
|
||||
freeifaddrs(ifaddrs);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
up_interface(const char *ifname)
|
||||
{
|
||||
@ -348,103 +465,17 @@ carrier_status(const char *ifname)
|
||||
#ifdef SIOCGIFMEDIA
|
||||
if (retval == 1) {
|
||||
memset(&ifmr, 0, sizeof(ifmr));
|
||||
strncpy(ifmr.ifm_name, ifr.ifr_name, sizeof(ifmr.ifm_name));
|
||||
strlcpy(ifmr.ifm_name, ifr.ifr_name, sizeof(ifmr.ifm_name));
|
||||
retval = -1;
|
||||
if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 &&
|
||||
ifmr.ifm_status & IFM_AVALID)
|
||||
{
|
||||
if (!(ifmr.ifm_status & IFM_ACTIVE))
|
||||
retval = 0;
|
||||
}
|
||||
retval = (ifmr.ifm_status & IFM_ACTIVE) ? 1 : 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)
|
||||
@ -482,13 +513,11 @@ int
|
||||
open_udp_socket(struct interface *iface)
|
||||
{
|
||||
int s;
|
||||
union sockunion {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
} su;
|
||||
struct sockaddr_in sin;
|
||||
int n;
|
||||
#ifdef SO_BINDTODEVICE
|
||||
struct ifreq ifr;
|
||||
char *p;
|
||||
#endif
|
||||
|
||||
if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
|
||||
@ -500,7 +529,12 @@ open_udp_socket(struct interface *iface)
|
||||
#ifdef SO_BINDTODEVICE
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||
/* We can only bind to the real device */
|
||||
p = strchr(ifr.ifr_name, ':');
|
||||
if (p)
|
||||
*p = '\0';
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr,
|
||||
sizeof(ifr)) == -1)
|
||||
goto eexit;
|
||||
#endif
|
||||
/* As we don't use this socket for receiving, set the
|
||||
@ -508,11 +542,11 @@ open_udp_socket(struct interface *iface)
|
||||
n = 1;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
|
||||
goto eexit;
|
||||
memset(&su, 0, sizeof(su));
|
||||
su.sin.sin_family = AF_INET;
|
||||
su.sin.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
su.sin.sin_addr.s_addr = iface->addr.s_addr;
|
||||
if (bind(s, &su.sa, sizeof(su)) == -1)
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
sin.sin_addr.s_addr = iface->addr.s_addr;
|
||||
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1)
|
||||
goto eexit;
|
||||
|
||||
iface->udp_fd = s;
|
||||
@ -526,19 +560,16 @@ eexit:
|
||||
|
||||
ssize_t
|
||||
send_packet(const struct interface *iface, struct in_addr to,
|
||||
const uint8_t *data, ssize_t len)
|
||||
const uint8_t *data, ssize_t len)
|
||||
{
|
||||
union sockunion {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
} su;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
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));
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_addr.s_addr = to.s_addr;
|
||||
sin.sin_port = htons(DHCP_SERVER_PORT);
|
||||
return sendto(iface->udp_fd, data, len, 0,
|
||||
(struct sockaddr *)&sin, sizeof(sin));
|
||||
}
|
||||
|
||||
struct udp_dhcp_packet
|
||||
@ -574,7 +605,7 @@ checksum(const void *data, uint16_t len)
|
||||
|
||||
ssize_t
|
||||
make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length,
|
||||
struct in_addr source, struct in_addr dest)
|
||||
struct in_addr source, struct in_addr dest)
|
||||
{
|
||||
struct udp_dhcp_packet *udpp;
|
||||
struct ip *ip;
|
||||
@ -630,20 +661,30 @@ get_udp_data(const uint8_t **data, const uint8_t *udp)
|
||||
|
||||
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);
|
||||
return ntohs(packet.ip.ip_len) -
|
||||
sizeof(packet.ip) -
|
||||
sizeof(packet.udp);
|
||||
}
|
||||
|
||||
int
|
||||
valid_udp_packet(const uint8_t *data, size_t data_len)
|
||||
valid_udp_packet(const uint8_t *data, size_t data_len, struct in_addr *from)
|
||||
{
|
||||
struct udp_dhcp_packet packet;
|
||||
uint16_t bytes, udpsum;
|
||||
|
||||
if (data_len < sizeof(packet.ip)) {
|
||||
if (from)
|
||||
from->s_addr = INADDR_ANY;
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
memcpy(&packet, data, MIN(data_len, sizeof(packet)));
|
||||
if (from)
|
||||
from->s_addr = packet.ip.ip_src.s_addr;
|
||||
if (data_len > sizeof(packet)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
memcpy(&packet, data, data_len);
|
||||
if (checksum(&packet.ip, sizeof(packet.ip)) != 0) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
@ -671,35 +712,3 @@ valid_udp_packet(const uint8_t *data, size_t data_len)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
103
external/bsd/dhcpcd/dist/net.h
vendored
103
external/bsd/dhcpcd/dist/net.h
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -39,6 +39,8 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "dhcp.h"
|
||||
#include "dhcpcd.h"
|
||||
|
||||
#ifndef DUID_LEN
|
||||
# define DUID_LEN 128 + 2
|
||||
@ -57,7 +59,6 @@
|
||||
# define ARPHRD_INFINIBAND 32
|
||||
#endif
|
||||
|
||||
#define HWADDR_LEN 20
|
||||
|
||||
/* Work out if we have a private address or not
|
||||
* 10/8
|
||||
@ -65,9 +66,9 @@
|
||||
* 192.168/16
|
||||
*/
|
||||
#ifndef IN_PRIVATE
|
||||
# define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \
|
||||
((addr & 0xfff00000) == 0xac100000) || \
|
||||
((addr & IN_CLASSB_NET) == 0xc0a80000))
|
||||
# define IN_PRIVATE(addr) (((addr & IN_CLASSA_NET) == 0x0a000000) || \
|
||||
((addr & 0xfff00000) == 0xac100000) || \
|
||||
((addr & IN_CLASSB_NET) == 0xc0a80000))
|
||||
#endif
|
||||
|
||||
#define LINKLOCAL_ADDR 0xa9fe0000
|
||||
@ -78,51 +79,22 @@
|
||||
# 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;
|
||||
const struct interface *iface;
|
||||
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 getifssid(const char *, char *);
|
||||
struct interface *init_interface(const char *);
|
||||
struct interface *discover_interfaces(int, char * const *);
|
||||
void free_interface(struct interface *);
|
||||
int do_mtu(const char *, short int);
|
||||
#define get_mtu(iface) do_mtu(iface, 0)
|
||||
#define set_mtu(iface, mtu) do_mtu(iface, mtu)
|
||||
@ -131,47 +103,48 @@ 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 do_address(const char *,
|
||||
struct in_addr *, struct in_addr *, struct in_addr *, int);
|
||||
int if_address(const struct interface *,
|
||||
const struct in_addr *, const struct in_addr *,
|
||||
const struct in_addr *, int);
|
||||
#define add_address(iface, addr, net, brd) \
|
||||
if_address(iface, addr, net, brd, 1)
|
||||
#define del_address(iface, addr, net) \
|
||||
if_address(iface, addr, net, NULL, -1)
|
||||
#define has_address(iface, addr, net) \
|
||||
do_address(iface, addr, net, NULL, 0)
|
||||
#define get_address(iface, addr, net, dst) \
|
||||
do_address(iface, addr, net, dst, 1)
|
||||
|
||||
int if_route(const struct interface *,
|
||||
const struct in_addr *,const struct in_addr *,
|
||||
const struct in_addr *, int, int);
|
||||
#define add_route(iface, dest, mask, gate, metric) \
|
||||
int if_route(const struct interface *, const struct in_addr *,
|
||||
const struct in_addr *, const struct in_addr *, int, int);
|
||||
#define add_route(iface, dest, mask, gate, metric) \
|
||||
if_route(iface, dest, mask, gate, metric, 1)
|
||||
#define change_route(iface, dest, mask, gate, metric) \
|
||||
#define change_route(iface, dest, mask, gate, metric) \
|
||||
if_route(iface, dest, mask, gate, metric, 0)
|
||||
#define del_route(iface, dest, mask, gate, metric) \
|
||||
#define del_route(iface, dest, mask, gate, metric) \
|
||||
if_route(iface, dest, mask, gate, metric, -1)
|
||||
#define del_src_route(iface, dest, mask, gate, metric) \
|
||||
if_route(iface, dest, mask, gate, metric, -2)
|
||||
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);
|
||||
struct in_addr, struct in_addr);
|
||||
ssize_t get_udp_data(const uint8_t **, const uint8_t *);
|
||||
int valid_udp_packet(const uint8_t *, size_t);
|
||||
int valid_udp_packet(const uint8_t *, size_t, struct in_addr *);
|
||||
|
||||
int open_socket(struct interface *, int);
|
||||
ssize_t send_packet(const struct interface *, struct in_addr,
|
||||
const uint8_t *, ssize_t);
|
||||
const uint8_t *, ssize_t);
|
||||
ssize_t send_raw_packet(const struct interface *, int,
|
||||
const void *, ssize_t);
|
||||
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 init_socket(void);
|
||||
int open_link_socket(void);
|
||||
int manage_link(int);
|
||||
int carrier_status(const char *);
|
||||
#endif
|
||||
|
19
external/bsd/dhcpcd/dist/signals.c
vendored
19
external/bsd/dhcpcd/dist/signals.c
vendored
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
* Copyright 2006-2008 Roy Marples <roy@marples.name>
|
||||
* Copyright 2006-2009 Roy Marples <roy@marples.name>
|
||||
* All rights reserved
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -40,10 +40,12 @@
|
||||
static int signal_pipe[2];
|
||||
|
||||
static const int handle_sigs[] = {
|
||||
SIGHUP,
|
||||
SIGALRM,
|
||||
SIGHUP,
|
||||
SIGINT,
|
||||
SIGPIPE,
|
||||
SIGTERM,
|
||||
SIGINT
|
||||
SIGUSR1,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -52,17 +54,11 @@ signal_handler(int sig)
|
||||
int serrno = errno;
|
||||
|
||||
if (write(signal_pipe[1], &sig, sizeof(sig)) != sizeof(sig))
|
||||
syslog(LOG_ERR, "write signal %d: %s", sig, strerror(errno));
|
||||
syslog(LOG_ERR, "failed to write signal %d: %m", 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 */
|
||||
@ -95,7 +91,7 @@ signal_init(void)
|
||||
return -1;
|
||||
if (set_cloexec(signal_pipe[1]) == -1)
|
||||
return -1;
|
||||
return 0;
|
||||
return signal_pipe[0];
|
||||
}
|
||||
|
||||
static int
|
||||
@ -125,3 +121,4 @@ signal_reset(void)
|
||||
{
|
||||
return signal_handle(SIG_DFL);
|
||||
}
|
||||
|
||||
|
1
external/bsd/dhcpcd/dist/signals.h
vendored
1
external/bsd/dhcpcd/dist/signals.h
vendored
@ -31,7 +31,6 @@
|
||||
int signal_init(void);
|
||||
int signal_setup(void);
|
||||
int signal_reset(void);
|
||||
int signal_fd(void);
|
||||
int signal_read(void);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user