mirror of
https://github.com/rsmarples/dhcpcd.git
synced 2024-11-24 10:35:03 +08:00
We now do ARP checking by default as recommended by RFC 2131.
Add RFC 3927 (aka IPV4LL aka APIPA) support by default.
This commit is contained in:
parent
ff711cf766
commit
77659ce035
@ -1,3 +1,5 @@
|
||||
We now do ARP checking by default as recommended by RFC 2131.
|
||||
Add RFC 3927 (aka IPV4LL aka APIPA) support by default.
|
||||
Suport DHCP option (52) overload.
|
||||
Added -T test option. This just sends a DHCP_DISCOVER message and then
|
||||
prints the configuration data to stdout - we don't request a lease,
|
||||
|
4
Makefile
4
Makefile
@ -1,4 +1,4 @@
|
||||
VERSION = 3.1.0_pre4
|
||||
VERSION = 3.1.0_pre5
|
||||
CFLAGS ?= -O2 -pipe
|
||||
|
||||
# Should work for both GNU make and BSD make
|
||||
@ -47,7 +47,7 @@ TARGET = $(SBIN_TARGETS)
|
||||
|
||||
dhcpcd_H = version.h
|
||||
dhcpcd_OBJS = arp.o client.o common.o configure.o dhcp.o dhcpcd.o duid.o \
|
||||
info.o interface.o logger.o signals.o socket.o
|
||||
info.o interface.o ipv4ll.o logger.o signals.o socket.o
|
||||
|
||||
# By default we don't need to link to anything
|
||||
# Except on Darwin where we need -lresolv, so they need to uncomment this
|
||||
|
95
arp.c
95
arp.c
@ -31,6 +31,7 @@
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -42,8 +43,11 @@
|
||||
#include "logger.h"
|
||||
#include "socket.h"
|
||||
|
||||
/* Longer is safer and slower - 2 seconds seems a happy medium */
|
||||
#define TIMEOUT 2
|
||||
/* These are really for IPV4LL */
|
||||
#define NPROBES 3
|
||||
#define PROBE_INTERVAL 200000
|
||||
#define NCLAIMS 2
|
||||
#define CLAIM_INTERVAL 200000
|
||||
|
||||
/* Linux does not seem to define these handy macros */
|
||||
#ifndef ar_sha
|
||||
@ -64,22 +68,14 @@
|
||||
#define IP_MIN_FRAME_LENGTH 46
|
||||
|
||||
#ifdef ENABLE_ARP
|
||||
int arp_check (interface_t *iface, struct in_addr address)
|
||||
|
||||
static int send_arp (interface_t *iface, int op, struct in_addr sip,
|
||||
unsigned char *taddr, struct in_addr tip)
|
||||
{
|
||||
struct arphdr *arp;
|
||||
struct arphdr *reply = NULL;
|
||||
long timeout = 0;
|
||||
unsigned char *buffer;
|
||||
int arpsize = arphdr_len2 (iface->hwlen, sizeof (struct in_addr));
|
||||
int retval = 0;
|
||||
int retval;
|
||||
|
||||
if (! iface->arpable) {
|
||||
logger (LOG_DEBUG, "arp_check: interface `%s' is not ARPable",
|
||||
iface->name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
inet_aton ("192.168.0.3", &address);
|
||||
arp = xmalloc (arpsize);
|
||||
memset (arp, 0, arpsize);
|
||||
|
||||
@ -87,18 +83,41 @@ int arp_check (interface_t *iface, struct in_addr address)
|
||||
arp->ar_pro = htons (ETHERTYPE_IP);
|
||||
arp->ar_hln = iface->hwlen;
|
||||
arp->ar_pln = sizeof (struct in_addr);
|
||||
arp->ar_op = htons (ARPOP_REQUEST);
|
||||
arp->ar_op = htons (op);
|
||||
memcpy (ar_sha (arp), &iface->hwaddr, arp->ar_hln);
|
||||
memcpy (ar_tpa (arp), &address, arp->ar_pln);
|
||||
memcpy (ar_spa (arp), &sip, arp->ar_pln);
|
||||
if (taddr)
|
||||
memcpy (ar_tha (arp), taddr, arp->ar_hln);
|
||||
memcpy (ar_tpa (arp), &tip, arp->ar_pln);
|
||||
|
||||
retval = send_packet (iface, ETHERTYPE_ARP,
|
||||
(unsigned char *) arp, arphdr_len (arp));
|
||||
free (arp);
|
||||
return (retval);
|
||||
}
|
||||
|
||||
int arp_claim (interface_t *iface, struct in_addr address)
|
||||
{
|
||||
struct arphdr *reply = NULL;
|
||||
long timeout = 0;
|
||||
unsigned char *buffer;
|
||||
int retval = -1;
|
||||
int nprobes = 0;
|
||||
int nclaims = 0;
|
||||
struct in_addr null_address;
|
||||
|
||||
if (! iface->arpable) {
|
||||
logger (LOG_DEBUG, "interface `%s' is not ARPable", iface->name);
|
||||
return (0);
|
||||
}
|
||||
|
||||
logger (LOG_INFO, "checking %s is available on attached networks",
|
||||
inet_ntoa (address));
|
||||
|
||||
open_socket (iface, true);
|
||||
send_packet (iface, ETHERTYPE_ARP, (unsigned char *) arp,
|
||||
arphdr_len (arp));
|
||||
if (! open_socket (iface, true))
|
||||
return (0);
|
||||
|
||||
timeout = uptime() + TIMEOUT;
|
||||
memset (&null_address, 0, sizeof (null_address));
|
||||
|
||||
buffer = xmalloc (sizeof (char *) * iface->buffer_length);
|
||||
|
||||
@ -111,21 +130,40 @@ int arp_check (interface_t *iface, struct in_addr address)
|
||||
int buflen = sizeof (char *) * iface->buffer_length;
|
||||
fd_set rset;
|
||||
int bytes;
|
||||
int s;
|
||||
|
||||
tv.tv_sec = timeout - uptime();
|
||||
tv.tv_usec = 0;
|
||||
|
||||
if (tv.tv_sec < 1)
|
||||
break; /* Time out */
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout;
|
||||
|
||||
FD_ZERO (&rset);
|
||||
FD_SET (iface->fd, &rset);
|
||||
if (select (FD_SETSIZE, &rset, NULL, NULL, &tv) == 0)
|
||||
errno = 0;
|
||||
if ((s = select (FD_SETSIZE, &rset, NULL, NULL, &tv)) == -1) {
|
||||
if (errno != EINTR)
|
||||
logger (LOG_ERR, "select: `%s'", strerror (errno));
|
||||
break;
|
||||
|
||||
} else if (s == 0) {
|
||||
/* Timed out */
|
||||
if (nprobes < NPROBES) {
|
||||
nprobes ++;
|
||||
timeout = PROBE_INTERVAL;
|
||||
logger (LOG_DEBUG, "sending ARP probe #%d", nprobes);
|
||||
send_arp (iface, ARPOP_REQUEST, null_address, NULL, address);
|
||||
} else if (nclaims < NCLAIMS) {
|
||||
nclaims ++;
|
||||
timeout = CLAIM_INTERVAL;
|
||||
logger (LOG_DEBUG, "sending ARP claim #%d", nclaims);
|
||||
send_arp (iface, ARPOP_REQUEST, address, iface->hwaddr, address);
|
||||
} else {
|
||||
/* No replies, so done */
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! FD_ISSET (iface->fd, &rset))
|
||||
continue;
|
||||
|
||||
|
||||
memset (buffer, 0, buflen);
|
||||
while (bufpos != 0) {
|
||||
union {
|
||||
@ -171,7 +209,6 @@ int arp_check (interface_t *iface, struct in_addr address)
|
||||
eexit:
|
||||
close (iface->fd);
|
||||
iface->fd = -1;
|
||||
free (arp);
|
||||
free (buffer);
|
||||
free (reply);
|
||||
return (retval);
|
||||
|
2
arp.h
2
arp.h
@ -25,7 +25,7 @@
|
||||
|
||||
#include "interface.h"
|
||||
|
||||
int arp_check (interface_t *iface, struct in_addr address);
|
||||
int arp_claim (interface_t *iface, struct in_addr address);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
128
client.c
128
client.c
@ -51,6 +51,9 @@
|
||||
#include "dhcpcd.h"
|
||||
#include "info.h"
|
||||
#include "interface.h"
|
||||
#ifdef ENABLE_IPV4LL
|
||||
# include "ipv4ll.h"
|
||||
#endif
|
||||
#include "logger.h"
|
||||
#include "signals.h"
|
||||
#include "socket.h"
|
||||
@ -132,32 +135,9 @@ static bool daemonise (int *pidfd)
|
||||
return (true);
|
||||
}
|
||||
|
||||
static unsigned long random_xid (void)
|
||||
{
|
||||
static int initialized;
|
||||
|
||||
if (! initialized) {
|
||||
int fd;
|
||||
unsigned long seed;
|
||||
|
||||
fd = open ("/dev/urandom", 0);
|
||||
if (fd < 0 || read (fd, &seed, sizeof(seed)) < 0) {
|
||||
logger (LOG_WARNING, "Could not load seed from /dev/urandom: %s",
|
||||
strerror (errno));
|
||||
seed = time (0);
|
||||
}
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
srand(seed);
|
||||
initialized++;
|
||||
}
|
||||
|
||||
return rand();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_INFO
|
||||
static bool get_old_lease (interface_t *iface, dhcp_t *dhcp, long *timeout)
|
||||
static bool get_old_lease (const options_t *options, interface_t *iface,
|
||||
dhcp_t *dhcp, long *timeout)
|
||||
{
|
||||
struct timeval tv;
|
||||
unsigned int offset = 0;
|
||||
@ -170,6 +150,21 @@ static bool get_old_lease (interface_t *iface, dhcp_t *dhcp, long *timeout)
|
||||
memset (&dhcp->serveraddress, 0, sizeof (struct in_addr));
|
||||
memset (dhcp->servername, 0, sizeof (dhcp->servername));
|
||||
|
||||
#ifdef ENABLE_ARP
|
||||
/* Check that no-one is using the address */
|
||||
if ((options->dolastlease ||
|
||||
IN_LINKLOCAL (dhcp->address.s_addr)) &&
|
||||
arp_claim (iface, dhcp->address)) {
|
||||
memset (&dhcp->address, 0, sizeof (struct in_addr));
|
||||
memset (&dhcp->netmask, 0, sizeof (struct in_addr));
|
||||
memset (&dhcp->broadcast, 0, sizeof (struct in_addr));
|
||||
return (false);
|
||||
}
|
||||
|
||||
/* Ok, lets use this */
|
||||
if (IN_LINKLOCAL (dhcp->address.s_addr))
|
||||
return (true);
|
||||
#endif
|
||||
|
||||
/* Ensure that we can still use the lease */
|
||||
if (gettimeofday (&tv, NULL) == -1) {
|
||||
@ -191,7 +186,6 @@ static bool get_old_lease (interface_t *iface, dhcp_t *dhcp, long *timeout)
|
||||
if (timeout)
|
||||
*timeout = dhcp->renewaltime - offset;
|
||||
iface->start_uptime = uptime ();
|
||||
logger (LOG_INFO, "using last known IP address %s", inet_ntoa (dhcp->address));
|
||||
return (true);
|
||||
}
|
||||
#endif
|
||||
@ -241,7 +235,7 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
(options->doinform || options->dorequest))
|
||||
{
|
||||
#ifdef ENABLE_INFO
|
||||
if (! get_old_lease (iface, dhcp, NULL))
|
||||
if (! get_old_lease (options, iface, dhcp, NULL))
|
||||
#endif
|
||||
{
|
||||
free (dhcp);
|
||||
@ -374,7 +368,7 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
{
|
||||
logger (LOG_INFO, "received SIGHUP, releasing lease");
|
||||
SOCKET_MODE (SOCKET_OPEN);
|
||||
xid = random_xid ();
|
||||
xid = random ();
|
||||
if ((open_socket (iface, false)) >= 0)
|
||||
SEND_MESSAGE (DHCP_RELEASE);
|
||||
SOCKET_MODE (SOCKET_CLOSED);
|
||||
@ -395,7 +389,11 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
/* timed out */
|
||||
switch (state) {
|
||||
case STATE_INIT:
|
||||
if (iface->previous_address.s_addr != 0 && ! options->doinform) {
|
||||
if (iface->previous_address.s_addr != 0 &&
|
||||
#ifdef ENABLE_IPV4LL
|
||||
! IN_LINKLOCAL (iface->previous_address.s_addr) &&
|
||||
#endif
|
||||
! options->doinform) {
|
||||
logger (LOG_ERR, "lost lease");
|
||||
xid = 0;
|
||||
SOCKET_MODE (SOCKET_CLOSED);
|
||||
@ -404,31 +402,64 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
}
|
||||
|
||||
if (xid == 0)
|
||||
xid = random_xid ();
|
||||
xid = random ();
|
||||
else {
|
||||
SOCKET_MODE (SOCKET_CLOSED);
|
||||
logger (LOG_ERR, "timed out");
|
||||
|
||||
free_dhcp (dhcp);
|
||||
memset (dhcp, 0, sizeof (dhcp_t));
|
||||
#ifdef ENABLE_INFO
|
||||
if (options->dolastlease) {
|
||||
if (! get_old_lease (iface, dhcp, &timeout))
|
||||
if (! daemonised ||
|
||||
configure (options, iface, dhcp, true))
|
||||
{
|
||||
retval = EXIT_FAILURE;
|
||||
goto eexit;
|
||||
}
|
||||
if (! get_old_lease (options, iface, dhcp, &timeout)) {
|
||||
if (options->dolastlease) {
|
||||
retval = EXIT_FAILURE;
|
||||
goto eexit;
|
||||
}
|
||||
|
||||
free_dhcp (dhcp);
|
||||
memset (dhcp, 0, sizeof (dhcp_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_IPV4LL
|
||||
if (! dhcp->address.s_addr ||
|
||||
(! IN_LINKLOCAL (dhcp->address.s_addr) &&
|
||||
! options->dolastlease))
|
||||
{
|
||||
logger (LOG_INFO, "probing for an IPV4LL address");
|
||||
free_dhcp (dhcp);
|
||||
memset (dhcp, 0, sizeof (dhcp_t));
|
||||
if (ipv4ll_get_address (iface, dhcp) == -1)
|
||||
break;
|
||||
timeout = dhcp->renewaltime;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (ENABLE_INFO) || defined (ENABLE_IPV4LL)
|
||||
if (dhcp->address.s_addr)
|
||||
{
|
||||
if (configure (options, iface, dhcp, true) < 0 &&
|
||||
! daemonised)
|
||||
{
|
||||
retval = EXIT_FAILURE;
|
||||
goto eexit;
|
||||
}
|
||||
|
||||
state = STATE_BOUND;
|
||||
if (! daemonised && options->daemonise) {
|
||||
if ((daemonise (pidfd)) < 0) {
|
||||
retval = -1;
|
||||
retval = EXIT_FAILURE;
|
||||
goto eexit;
|
||||
}
|
||||
daemonised = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
timeout = dhcp->renewaltime;
|
||||
xid = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! daemonised) {
|
||||
retval = EXIT_FAILURE;
|
||||
goto eexit;
|
||||
@ -456,10 +487,19 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
break;
|
||||
case STATE_BOUND:
|
||||
case STATE_RENEW_REQUESTED:
|
||||
#ifdef ENABLE_IPV4LL
|
||||
if (IN_LINKLOCAL (dhcp->address.s_addr)) {
|
||||
memset (&dhcp->address, 0, sizeof (struct in_addr));
|
||||
state = STATE_INIT;
|
||||
xid = 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
state = STATE_RENEWING;
|
||||
xid = random_xid ();
|
||||
xid = random ();
|
||||
case STATE_RENEWING:
|
||||
iface->start_uptime = uptime ();
|
||||
free_dhcp (dhcp);
|
||||
logger (LOG_INFO, "renewing lease of %s", inet_ntoa
|
||||
(dhcp->address));
|
||||
SOCKET_MODE (SOCKET_OPEN);
|
||||
@ -472,7 +512,7 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
memset (&dhcp->address, 0, sizeof (struct in_addr));
|
||||
SOCKET_MODE (SOCKET_OPEN);
|
||||
if (xid == 0)
|
||||
xid = random_xid ();
|
||||
xid = random ();
|
||||
SEND_MESSAGE (DHCP_REQUEST);
|
||||
timeout = dhcp->leasetime - dhcp->rebindtime;
|
||||
state = STATE_REQUESTING;
|
||||
@ -604,7 +644,7 @@ int dhcp_run (const options_t *options, int *pidfd)
|
||||
if (options->doarp && iface->previous_address.s_addr !=
|
||||
dhcp->address.s_addr)
|
||||
{
|
||||
if (arp_check (iface, dhcp->address)) {
|
||||
if (arp_claim (iface, dhcp->address)) {
|
||||
SOCKET_MODE (SOCKET_OPEN);
|
||||
SEND_MESSAGE (DHCP_DECLINE);
|
||||
SOCKET_MODE (SOCKET_CLOSED);
|
||||
|
25
common.c
25
common.c
@ -23,10 +23,33 @@
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "logger.h"
|
||||
|
||||
/* OK, this should be in dhcpcd.c
|
||||
* It's here to make dhcpcd more readable */
|
||||
#ifdef __linux__
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
void srandomdev (void) {
|
||||
int fd;
|
||||
unsigned long seed;
|
||||
|
||||
fd = open ("/dev/urandom", 0);
|
||||
if (fd == -1 || read (fd, &seed, sizeof(seed)) == -1) {
|
||||
logger (LOG_WARNING, "Could not load seed from /dev/urandom: %s",
|
||||
strerror (errno));
|
||||
seed = time (0);
|
||||
}
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
|
||||
srandom (seed);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* strlcpy is nice, shame glibc does not define it */
|
||||
#ifdef __GLIBC__
|
||||
# if ! defined(__UCLIBC__) && ! defined (__dietlibc__)
|
||||
@ -65,7 +88,6 @@ long uptime (void)
|
||||
}
|
||||
#elif __APPLE__
|
||||
/* Darwin doesn't appear to have an uptime, so try and make one ourselves */
|
||||
#include <sys/time.h>
|
||||
long uptime (void)
|
||||
{
|
||||
struct timeval tv;
|
||||
@ -82,7 +104,6 @@ long uptime (void)
|
||||
return tv.tv_sec - start;
|
||||
}
|
||||
#else
|
||||
#include <time.h>
|
||||
long uptime (void)
|
||||
{
|
||||
struct timespec tp;
|
||||
|
4
common.h
4
common.h
@ -32,6 +32,10 @@ size_t strlcpy (char *dst, const char *src, size_t size);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
void srandomdev (void);
|
||||
#endif
|
||||
|
||||
long uptime (void);
|
||||
void *xmalloc (size_t size);
|
||||
char *xstrdup (const char *str);
|
||||
|
4
config.h
4
config.h
@ -33,6 +33,10 @@
|
||||
/* Define this to enable some compatability with 1.x and 2.x info files */
|
||||
// #define ENABLE_INFO_COMPAT
|
||||
|
||||
/* IPV4LL, aka ZeroConf, aka APIPA, aka RFC 3927.
|
||||
* Needs ARP. */
|
||||
#define ENABLE_IPV4LL
|
||||
|
||||
/* We will auto create a DUID_LLT file if it doesn't exist.
|
||||
* You can always create your own DUID file that just contains the
|
||||
* hex string that represents the DUID.
|
||||
|
41
dhcpcd.8
41
dhcpcd.8
@ -1,6 +1,6 @@
|
||||
.\" $Id$
|
||||
.\"
|
||||
.TH DHCPCD 8 "12 Jul 2007" "dhcpcd 3.1"
|
||||
.TH DHCPCD 8 "18 Jul 2007" "dhcpcd 3.1"
|
||||
|
||||
.SH NAME
|
||||
dhcpcd \- DHCP client daemon
|
||||
@ -9,7 +9,7 @@ dhcpcd \- DHCP client daemon
|
||||
.in +.5i
|
||||
.ti -.5i
|
||||
dhcpcd
|
||||
\%[\-adknpEGHMNRTY]
|
||||
\%[\-dknpAEGHMLNRTY]
|
||||
\%[\-c\ script]
|
||||
\%[\-h\ hostname]
|
||||
\%[\-i\ vendorClassID]
|
||||
@ -26,27 +26,26 @@ dhcpcd
|
||||
.SH DESCRIPTION
|
||||
.B dhcpcd
|
||||
is an implementation of the DHCP client specified in
|
||||
.B RFC2131.
|
||||
.B RFC 2131.
|
||||
|
||||
It gets the host information (IP address, netmask, broadcast address,
|
||||
etc.) from a DHCP server and configures the network interface of the
|
||||
machine on which it is running. It also tries to renew the lease time
|
||||
according to
|
||||
.B RFC2131.
|
||||
.B RFC 2131.
|
||||
|
||||
If
|
||||
.B dhcpcd
|
||||
fails to get a lease then we attempt Dynamic Configuration of IPv4
|
||||
Link-Local Addresses unless the
|
||||
.B \-L
|
||||
option is given.
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI interface
|
||||
Specifies the network interface name (eth0, eth1, etc.).
|
||||
.TP
|
||||
.BI \-a
|
||||
Do an
|
||||
.B ARP
|
||||
check on the IP address give to us by the DHCP server. We may need to do this
|
||||
if a client on the same network segment has the same IP address, however we do
|
||||
not do this by default as most DHCP servers test the IP briefly with an ICMP
|
||||
Echo request before assigning the IP address.
|
||||
.TP
|
||||
.BI \-c \ script
|
||||
.B dhcpcd
|
||||
will try to execute
|
||||
@ -187,6 +186,11 @@ fixed hardware addresses. You can specify more than one user class, but the
|
||||
total length must be less than 255 characters, -1 character for each user
|
||||
class.
|
||||
.TP
|
||||
.BI \-A
|
||||
Don't do an
|
||||
.B ARP
|
||||
check on the IP address.
|
||||
.TP
|
||||
.BI \-E
|
||||
Will read
|
||||
.I /var/lib/dhcpcd/dhcpcd-<interface>.info
|
||||
@ -266,6 +270,10 @@ and store the DUID part in
|
||||
uses the MAC address of the network interface. If \fB-I\fR is not given
|
||||
an option then we use the MAC address of the network interface.
|
||||
.TP
|
||||
.BI \-L
|
||||
Prevents dhcpcd from probing for IPV4LL addresses. IPV4LL is otherwise
|
||||
known as ZeroConf or APIPA and is \fBRFC 3927\fR.
|
||||
.TP
|
||||
.BI \-M
|
||||
Prevents
|
||||
.B dhcpcd
|
||||
@ -353,13 +361,16 @@ is attached.
|
||||
.SH SEE ALSO
|
||||
.LP
|
||||
.I Dynamic Host Configuration Protocol,
|
||||
RFC2132
|
||||
RFC 2131
|
||||
.LP
|
||||
.I DHCP Options and BOOTP Vendor Extensions,
|
||||
RFC2132
|
||||
RFC 2132
|
||||
.LP
|
||||
.I Dynamic Configuration of IPv4 Link-Local Addresses,
|
||||
RFC 3927
|
||||
.LP
|
||||
.I DHCP FQDN Option specification,
|
||||
RFC4702
|
||||
RFC 4702
|
||||
|
||||
.SH BUGS
|
||||
Please report them to http://dhcpcd.berlios.de or http://bugs.gentoo.org.
|
||||
|
27
dhcpcd.c
27
dhcpcd.c
@ -118,6 +118,7 @@ int main(int argc, char **argv)
|
||||
{"nogateway", no_argument, NULL, 'G'},
|
||||
{"sethostname", no_argument, NULL, 'H'},
|
||||
{"clientid", optional_argument, NULL, 'I'},
|
||||
{"noipv4ll", no_argument, NULL, 'L'},
|
||||
{"nomtu", no_argument, NULL, 'M'},
|
||||
{"nontp", no_argument, NULL, 'N'},
|
||||
{"nodns", no_argument, NULL, 'R'},
|
||||
@ -139,7 +140,7 @@ int main(int argc, char **argv)
|
||||
snprintf (options.classid, CLASS_ID_MAX_LEN, "%s %s", PACKAGE, VERSION);
|
||||
options.classid_len = strlen (options.classid);
|
||||
|
||||
options.doarp = false;
|
||||
options.doarp = true;
|
||||
options.dodns = true;
|
||||
options.domtu = true;
|
||||
options.donis = true;
|
||||
@ -147,6 +148,7 @@ int main(int argc, char **argv)
|
||||
options.dogateway = true;
|
||||
options.daemonise = true;
|
||||
options.doinform = false;
|
||||
options.doipv4ll = true;
|
||||
options.timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
gethostname (options.hostname, sizeof (options.hostname));
|
||||
@ -156,7 +158,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Don't set any optional arguments here so we retain POSIX
|
||||
* compatibility with getopt */
|
||||
while ((opt = getopt_long(argc, argv, "ac:dh:i:kl:m:npr:s:t:u:EF:GHI:MNRTY",
|
||||
while ((opt = getopt_long(argc, argv, "c:dh:i:kl:m:npr:s:t:u:AEF:GHI:LMNRTY",
|
||||
longopts, &option_index)) != -1)
|
||||
{
|
||||
switch (opt) {
|
||||
@ -167,14 +169,6 @@ int main(int argc, char **argv)
|
||||
longopts[option_index].name);
|
||||
exit (EXIT_FAILURE);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
#ifndef ENABLE_ARP
|
||||
logger (LOG_ERR, "arp support not compiled into dhcpcd");
|
||||
exit (EXIT_FAILURE);
|
||||
#endif
|
||||
options.doarp = true;
|
||||
break;
|
||||
case 'c':
|
||||
options.script = optarg;
|
||||
break;
|
||||
@ -283,6 +277,13 @@ int main(int argc, char **argv)
|
||||
options.userclass_len += (strlen (optarg)) + 1;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
#ifndef ENABLE_ARP
|
||||
logger (LOG_ERR, "arp support not compiled into dhcpcd");
|
||||
exit (EXIT_FAILURE);
|
||||
#endif
|
||||
options.doarp = false;
|
||||
break;
|
||||
case 'E':
|
||||
#ifndef ENABLE_INFO
|
||||
logger (LOG_ERR, "info support not compiled into dhcpcd");
|
||||
@ -325,6 +326,9 @@ int main(int argc, char **argv)
|
||||
options.clientid_len = -1;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
options.doipv4ll = false;
|
||||
break;
|
||||
case 'M':
|
||||
options.domtu = false;
|
||||
break;
|
||||
@ -477,6 +481,9 @@ int main(int argc, char **argv)
|
||||
logger (LOG_INFO, PACKAGE " " VERSION " starting");
|
||||
}
|
||||
|
||||
/* Seed random */
|
||||
srandomdev ();
|
||||
|
||||
if (dhcp_run (&options, &pidfd)) {
|
||||
if (pidfd > -1)
|
||||
close (pidfd);
|
||||
|
1
dhcpcd.h
1
dhcpcd.h
@ -61,6 +61,7 @@ typedef struct options_t {
|
||||
bool dolastlease;
|
||||
bool doinform;
|
||||
bool dorequest;
|
||||
bool doipv4ll;
|
||||
|
||||
struct in_addr request_address;
|
||||
struct in_addr request_netmask;
|
||||
|
63
ipv4ll.c
Normal file
63
ipv4ll.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon -
|
||||
* Copyright 2006-2007 Roy Marples <uberlord@gentoo.org>
|
||||
*
|
||||
* dhcpcd is an RFC2131 compliant DHCP client daemon.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "arp.h"
|
||||
#include "ipv4ll.h"
|
||||
|
||||
#ifdef ENABLE_IPV4LL
|
||||
|
||||
#ifndef ENABLE_ARP
|
||||
#error IPV4LL requires ARP
|
||||
#endif
|
||||
|
||||
#define IPV4LL_LEASETIME 10
|
||||
|
||||
int ipv4ll_get_address (interface_t *iface, dhcp_t *dhcp) {
|
||||
struct in_addr addr;
|
||||
|
||||
while (1) {
|
||||
addr.s_addr = htonl (LINKLOCAL_ADDR |
|
||||
((abs (random ()) % 0xFD00) + 0x0100));
|
||||
errno = 0;
|
||||
if (! arp_claim (iface, addr))
|
||||
break;
|
||||
/* Our ARP may have been interrupted */
|
||||
if (errno == EINTR)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
dhcp->address.s_addr = addr.s_addr;
|
||||
dhcp->netmask.s_addr = htonl (LINKLOCAL_MASK);
|
||||
dhcp->broadcast.s_addr = htonl (LINKLOCAL_BRDC);
|
||||
|
||||
/* Finally configure some DHCP like lease times */
|
||||
dhcp->leasetime = IPV4LL_LEASETIME;
|
||||
dhcp->renewaltime = (dhcp->leasetime * 0.5);
|
||||
dhcp->rebindtime = (dhcp->leasetime * 0.875);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
37
ipv4ll.h
Normal file
37
ipv4ll.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon -
|
||||
* Copyright 2005 - 2007 Roy Marples <uberlord@gentoo.org>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef IPV4LL_H
|
||||
#define IPV4LL_H
|
||||
|
||||
#ifdef ENABLE_IPV4LL
|
||||
|
||||
#include "dhcp.h"
|
||||
#include "interface.h"
|
||||
|
||||
#define LINKLOCAL_ADDR 0xa9fe0000
|
||||
#define LINKLOCAL_MASK 0xffff0000
|
||||
#define LINKLOCAL_BRDC 0xa9feffff
|
||||
|
||||
#define IN_LINKLOCAL(addr) ((ntohl (addr) & IN_CLASSB_NET) == LINKLOCAL_ADDR)
|
||||
|
||||
int ipv4ll_get_address (interface_t *iface, dhcp_t *dhcp);
|
||||
|
||||
#endif
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user