When dhclient obtains a lease, it runs dhclient-script and expects

it to configure the interface.  When the script is complete, dhclient
monitors the routing socket and will terminate if its address is
deleted or if its interface is removed or brought down.

Because the routing socket is already open when dhclient-script is
run, dhclient ignores address deletions for 10 seconds after the
script was run.

If the address that will be obtained is already configured on the
interface before dhclient starts, and if dhclient-script takes more
than 10 seconds (perhaps due to dhclient-*-hooks latencies), on script
completion, dhclient will immediately and silently exit when it sees
the RTM_DELADDR routing message resulting from the script reassigning
the address to the interface.

This change logs dhclient's reason for exiting and also changes the
10 second timeout to be effective from completion of dhclient-script
rather than from when it was started.

We now ignore RTM_DELADDR and RTM_NEWADDR messages when the message
contains no interface address (which should not happen) rather than
exiting.

Not reviewed by:	brooks (timeout)
MFC after:		3 weeks
This commit is contained in:
Brian Somers 2010-07-07 06:06:54 +00:00
parent 7ec5a4bd22
commit 6964abef83
1 changed files with 30 additions and 16 deletions

View File

@ -126,7 +126,7 @@ int fork_privchld(int, int);
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
time_t scripttime;
static time_t scripttime;
int
findproto(char *cp, int n)
@ -204,7 +204,7 @@ disassoc(void *arg)
void
routehandler(struct protocol *p)
{
char msg[2048];
char msg[2048], *addr;
struct rt_msghdr *rtm;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
@ -224,13 +224,6 @@ routehandler(struct protocol *p)
switch (rtm->rtm_type) {
case RTM_NEWADDR:
/*
* XXX: If someone other than us adds our address,
* we should assume they are taking over from us,
* delete the lease record, and exit without modifying
* the interface.
*/
break;
case RTM_DELADDR:
ifam = (struct ifa_msghdr *)rtm;
@ -243,7 +236,7 @@ routehandler(struct protocol *p)
sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
if (sa == NULL)
goto die;
break;
if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
error("king bula sez: len mismatch");
@ -255,21 +248,42 @@ routehandler(struct protocol *p)
if (addr_eq(a, l->address))
break;
if (l == NULL) /* deleted addr is not the one we set */
if (l == NULL) /* added/deleted addr is not the one we set */
break;
goto die;
addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
if (rtm->rtm_type == RTM_NEWADDR) {
/*
* XXX: If someone other than us adds our address,
* should we assume they are taking over from us,
* delete the lease record, and exit without modifying
* the interface?
*/
warning("My address (%s) was re-added", addr);
} else {
warning("My address (%s) was deleted, dhclient exiting",
addr);
goto die;
}
break;
case RTM_IFINFO:
ifm = (struct if_msghdr *)rtm;
if (ifm->ifm_index != ifi->index)
break;
if ((rtm->rtm_flags & RTF_UP) == 0)
if ((rtm->rtm_flags & RTF_UP) == 0) {
warning("Interface %s is down, dhclient exiting",
ifi->name);
goto die;
}
break;
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *)rtm;
if (ifan->ifan_what == IFAN_DEPARTURE &&
ifan->ifan_index == ifi->index)
ifan->ifan_index == ifi->index) {
warning("Interface %s is gone, dhclient exiting",
ifi->name);
goto die;
}
break;
case RTM_IEEE80211:
ifan = (struct if_announcemsghdr *)rtm;
@ -2110,8 +2124,6 @@ script_go(void)
struct buf *buf;
int ret;
scripttime = time(NULL);
hdr.code = IMSG_SCRIPT_GO;
hdr.len = sizeof(struct imsg_hdr);
@ -2132,6 +2144,8 @@ script_go(void)
error("received corrupted message");
buf_read(privfd, &ret, sizeof(ret));
scripttime = time(NULL);
return (ret);
}