From: Roy Marples Date: Tue, 20 Feb 2007 22:57:10 +0000 (+0000) Subject: Test to see if the pid in the pidfile is actually running before claiming X-Git-Tag: v3.2.3~314 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffb6d9d1b8d380996173262d6e13f72326f05bdd;p=thirdparty%2Fdhcpcd.git Test to see if the pid in the pidfile is actually running before claiming that we are. Fix the error since 3.0.6. We now ensure that our renewal and rebind times are sane. Fix flushing interfaces for systems without getifaddrs and >1 interface. All netlink error messages are now prefixed with netlink. --- diff --git a/ChangeLog b/ChangeLog index 229758ed..f04c0904 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Test to see if the pid in the pidfile is actually running before claiming +that we are. +Fix the `netlink message truncated` error since 3.0.6. +We now ensure that our renewal and rebind times are sane. +Fix flushing interfaces for systems without getifaddrs and >1 interface. +All netlink error messages are now prefixed with netlink. Add DHCP over FireWire 1394 (RFC 2855) and InfiniBand (RFC 4390) support. We should add support for DUIDs (RFC4361) as well. diff --git a/Makefile b/Makefile index 551c000a..077c51cd 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Should work for both GNU make and BSD make -VERSION = 3.0.12_pre1 +VERSION = 3.0.12_pre2 CFLAGS ?= -O2 -pipe diff --git a/client.c b/client.c index d069d5a2..ec60f3ab 100644 --- a/client.c +++ b/client.c @@ -174,7 +174,8 @@ int dhcp_run (const options_t *options) if (timeout > 0 || (options->timeout == 0 && (state != STATE_INIT || xid))) { - if (options->timeout == 0 || dhcp->leasetime == (unsigned) -1) + if (options->timeout == 0 || + (dhcp->leasetime == (unsigned) -1 && state == STATE_BOUND)) { int retry = 0; logger (LOG_DEBUG, "waiting on select for infinity"); @@ -471,8 +472,15 @@ int dhcp_run (const options_t *options) case STATE_INIT: if (type == DHCP_OFFER) { - logger (LOG_INFO, "offered lease of %s", - inet_ntoa (dhcp->address)); + char *addr = strdup (inet_ntoa (dhcp->address)); + if (dhcp->servername) + logger (LOG_INFO, "offered %s from %s `%s'", + addr, inet_ntoa (dhcp->serveraddress), + dhcp->servername); + else + logger (LOG_INFO, "offered %s from %s", + addr, inet_ntoa (dhcp->serveraddress)); + free (addr); SEND_MESSAGE (DHCP_REQUEST); state = STATE_REQUESTING; @@ -512,40 +520,69 @@ int dhcp_run (const options_t *options) } } - if (! dhcp->leasetime) + if (dhcp->leasetime == (unsigned) -1) { - dhcp->leasetime = DEFAULT_TIMEOUT; - logger(LOG_INFO, - "no lease time supplied, assuming %d seconds", - dhcp->leasetime); + dhcp->renewaltime = dhcp->rebindtime = dhcp->leasetime; + timeout = 1; /* So we select on infinity */ + logger (LOG_INFO, "leased %s for infinity", + inet_ntoa (dhcp->address)); } - - if (! dhcp->renewaltime) + else { - dhcp->renewaltime = dhcp->leasetime / 2; - logger (LOG_INFO, - "no renewal time supplied, assuming %d seconds", - dhcp->renewaltime); - } + if (! dhcp->leasetime) + { + dhcp->leasetime = DEFAULT_TIMEOUT; + logger(LOG_INFO, + "no lease time supplied, assuming %d seconds", + dhcp->leasetime); + } + else + logger (LOG_INFO, "leased %s for %u seconds", + inet_ntoa (dhcp->address), dhcp->leasetime); - if (! dhcp->rebindtime) - { - dhcp->rebindtime = (dhcp->leasetime * 0x7) >> 3; - logger (LOG_INFO, - "no rebind time supplied, assuming %d seconds", - dhcp->rebindtime); - } + if (dhcp->rebindtime >= dhcp->leasetime) + { + dhcp->rebindtime = (dhcp->leasetime * 0.875); + logger (LOG_ERR, "rebind time greater than lease " + "time, forcing to %u seconds", + dhcp->rebindtime); + } - if (dhcp->leasetime == (unsigned) -1) - logger (LOG_INFO, "leased %s for infinity", - inet_ntoa (dhcp->address)); - else - logger (LOG_INFO, "leased %s for %u seconds", - inet_ntoa (dhcp->address), - dhcp->leasetime, dhcp->renewaltime); + if (dhcp->renewaltime > dhcp->rebindtime) + { + + dhcp->renewaltime = (dhcp->leasetime * 0.5); + logger (LOG_ERR, "renewal time greater than rebind time, " + "forcing to %u seconds", + dhcp->renewaltime); + } + + if (! dhcp->renewaltime) + { + dhcp->renewaltime = (dhcp->leasetime * 0.5); + logger (LOG_INFO, + "no renewal time supplied, assuming %d seconds", + dhcp->renewaltime); + } + else + logger (LOG_DEBUG, "renew in %u seconds", + dhcp->renewaltime); + + if (! dhcp->rebindtime) + { + dhcp->rebindtime = (dhcp->leasetime * 0.875); + logger (LOG_INFO, + "no rebind time supplied, assuming %d seconds", + dhcp->rebindtime); + } + else + logger (LOG_DEBUG, "rebind in %u seconds", + dhcp->rebindtime); + + timeout = dhcp->renewaltime; + } state = STATE_BOUND; - timeout = dhcp->renewaltime; xid = 0; if (configure (options, iface, dhcp) < 0 && ! daemonised) diff --git a/configure.c b/configure.c index 184a9be9..79877eb9 100644 --- a/configure.c +++ b/configure.c @@ -468,8 +468,10 @@ int configure (const options_t *options, interface_t *iface, /* Only reset things if we had set them before */ if (iface->previous_address.s_addr != 0) { - del_address (iface->name, iface->previous_address); + del_address (iface->name, iface->previous_address, + iface->previous_netmask); memset (&iface->previous_address, 0, sizeof (struct in_addr)); + memset (&iface->previous_netmask, 0, sizeof (struct in_addr)); restore_resolv (iface->name); @@ -486,7 +488,7 @@ int configure (const options_t *options, interface_t *iface, /* Now delete the old address if different */ if (iface->previous_address.s_addr != dhcp->address.s_addr && iface->previous_address.s_addr != 0) - del_address (iface->name, iface->previous_address); + del_address (iface->name, iface->previous_address, iface->previous_netmask); #ifdef __linux__ /* On linux, we need to change the subnet route to have our metric. */ @@ -602,10 +604,13 @@ int configure (const options_t *options, interface_t *iface, write_info (iface, dhcp, options); - if (iface->previous_address.s_addr != dhcp->address.s_addr) + if (iface->previous_address.s_addr != dhcp->address.s_addr || + iface->previous_netmask.s_addr != dhcp->netmask.s_addr) { memcpy (&iface->previous_address, &dhcp->address, sizeof (struct in_addr)); + memcpy (&iface->previous_netmask, + &dhcp->netmask, sizeof (struct in_addr)); exec_script (options->script, iface->infofile, "new"); } else diff --git a/dhcp.c b/dhcp.c index 3b81b486..6f3c0717 100644 --- a/dhcp.c +++ b/dhcp.c @@ -296,9 +296,9 @@ static unsigned long getnetmask (unsigned long ip_in) seperated string. Returns length of string (including terminating zero) or zero on error. out may be NULL to just determine output length. */ -static unsigned int decode_search (u_char *p, int len, char *out) +static unsigned int decode_search (const unsigned char *p, int len, char *out) { - u_char *r, *q = p; + const unsigned char *r, *q = p; unsigned int count = 0, l, hops; while (q - p < len) @@ -358,9 +358,9 @@ static unsigned int decode_search (u_char *p, int len, char *out) /* Add our classless static routes to the routes variable * and return the last route set */ -static route_t *decodeCSR(unsigned char *p, int len) +static route_t *decodeCSR(const unsigned char *p, int len) { - unsigned char *q = p; + const unsigned char *q = p; int cidr; int ocets; route_t *first; @@ -455,7 +455,7 @@ void free_dhcp (dhcp_t *dhcp) } } -static void dhcp_add_address(address_t *address, unsigned char *data, int length) +static void dhcp_add_address(address_t *address, const unsigned char *data, int length) { int i; address_t *p = address; @@ -474,8 +474,8 @@ static void dhcp_add_address(address_t *address, unsigned char *data, int length int parse_dhcpmessage (dhcp_t *dhcp, const dhcpmessage_t *message) { - unsigned char *p = message->options; - unsigned char *end = message->options; /* Add size later for gcc-3 issue */ + const unsigned char *p = message->options; + const unsigned char *end = p; /* Add size later for gcc-3 issue */ unsigned char option; unsigned char length; unsigned int len = 0; diff --git a/dhcpcd.c b/dhcpcd.c index 2dcb5537..24c5c160 100644 --- a/dhcpcd.c +++ b/dhcpcd.c @@ -100,7 +100,6 @@ static void usage () " [-u userclass] [-F [none | ptr | both]] [-I clientID]\n"); } - int main(int argc, char **argv) { options_t options; @@ -110,6 +109,7 @@ int main(int argc, char **argv) int ch; int option_index = 0; char prefix[IF_NAMESIZE + 3]; + pid_t pid; const struct option longopts[] = { @@ -344,7 +344,7 @@ int main(int argc, char **argv) if (options.signal != 0) { int killed = -1; - pid_t pid = read_pid (options.pidfile); + pid = read_pid (options.pidfile); if (pid != 0) logger (LOG_INFO, "sending signal %d to pid %d", options.signal, pid); @@ -377,7 +377,7 @@ int main(int argc, char **argv) exit (EXIT_FAILURE); } - if (read_pid (options.pidfile)) + if ((pid = read_pid (options.pidfile)) > 0 && kill (pid, 0) == 0) { logger (LOG_ERR, ""PACKAGE" already running (%s)", options.pidfile); exit (EXIT_FAILURE); diff --git a/interface.c b/interface.c index 3da3eaf9..bb40864b 100644 --- a/interface.c +++ b/interface.c @@ -181,6 +181,7 @@ interface_t *read_interface (const char *ifname, int metric) #ifdef __linux__ /* Do something with the metric parameter to satisfy the compiler warning */ metric = 0; + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCGIFHWADDR, &ifr) <0) { logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror (errno)); @@ -207,6 +208,7 @@ interface_t *read_interface (const char *ifname, int metric) family = ifr.ifr_hwaddr.sa_family; #else ifr.ifr_metric = metric; + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl (s, SIOCSIFMETRIC, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno)); @@ -215,6 +217,7 @@ interface_t *read_interface (const char *ifname, int metric) } #endif + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno)); @@ -223,6 +226,7 @@ interface_t *read_interface (const char *ifname, int metric) } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCSIFFLAGS: %s", strerror (errno)); @@ -281,9 +285,9 @@ static int do_address (const char *ifname, struct in_addr address, } ADDADDR (ifa.ifra_addr, address); + ADDADDR (ifa.ifra_mask, netmask); if (! del) { - ADDADDR (ifa.ifra_mask, netmask); ADDADDR (ifa.ifra_broadaddr, broadcast); } @@ -448,7 +452,8 @@ static int send_netlink(struct nlmsghdr *hdr) struct iovec iov; struct msghdr msg; static unsigned int seq; - char buffer[16384]; + char buffer[256]; + int bytes; union { char *buffer; @@ -496,25 +501,25 @@ static int send_netlink(struct nlmsghdr *hdr) while (1) { - int bytes = recvmsg(s, &msg, 0); iov.iov_len = sizeof (buffer); + bytes = recvmsg(s, &msg, 0); if (bytes < 0) { if (errno != EINTR) - logger (LOG_ERR, "overrun"); + logger (LOG_ERR, "netlink: overrun"); continue; } if (bytes == 0) { - logger (LOG_ERR, "EOF on netlink"); + logger (LOG_ERR, "netlink: EOF"); goto eexit; } if (msg.msg_namelen != sizeof (nl)) { - logger (LOG_ERR, "sender address length == %d", msg.msg_namelen); + logger (LOG_ERR, "netlink: sender address length mismatch"); goto eexit; } @@ -526,9 +531,9 @@ static int send_netlink(struct nlmsghdr *hdr) if (l < 0 || len > bytes) { if (msg.msg_flags & MSG_TRUNC) - logger (LOG_ERR, "truncated message"); + logger (LOG_ERR, "netlink: truncated message"); else - logger (LOG_ERR, "malformed message"); + logger (LOG_ERR, "netlink: malformed message"); goto eexit; } @@ -543,7 +548,7 @@ static int send_netlink(struct nlmsghdr *hdr) { struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h.nlm); if ((unsigned) l < sizeof (struct nlmsgerr)) - logger (LOG_ERR, "truncated error message"); + logger (LOG_ERR, "netlink: truncated error message"); else { errno = -err->error; @@ -555,12 +560,12 @@ static int send_netlink(struct nlmsghdr *hdr) /* Don't report on something already existing */ if (errno != EEXIST) - logger (LOG_ERR, "RTNETLINK answers: %s", strerror (errno)); + logger (LOG_ERR, "netlink: %s", strerror (errno)); } goto eexit; } - logger (LOG_ERR, "unexpected reply"); + logger (LOG_ERR, "netlink: unexpected reply"); next: bytes -= NLMSG_ALIGN (len); h.buffer += NLMSG_ALIGN (len); @@ -568,13 +573,13 @@ next: if (msg.msg_flags & MSG_TRUNC) { - logger (LOG_ERR, "message truncated"); + logger (LOG_ERR, "netlink: truncated message"); continue; } if (bytes) { - logger (LOG_ERR, "remnant of size %d", bytes); + logger (LOG_ERR, "netlink: remnant of size %d", bytes); goto eexit; } } @@ -637,7 +642,7 @@ static int do_address(const char *ifname, { struct nlmsghdr hdr; struct ifaddrmsg ifa; - char buffer[256]; + char buffer[64]; } nlm; uint32_t mask = htonl (netmask.s_addr); @@ -649,6 +654,8 @@ static int do_address(const char *ifname, nlm.hdr.nlmsg_len = NLMSG_LENGTH (sizeof (struct ifaddrmsg)); nlm.hdr.nlmsg_flags = NLM_F_REQUEST; + if (! del) + nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; nlm.hdr.nlmsg_type = del ? RTM_DELADDR : RTM_NEWADDR; nlm.ifa.ifa_index = if_nametoindex (ifname); nlm.ifa.ifa_family = AF_INET; @@ -772,14 +779,18 @@ int add_address (const char *ifname, struct in_addr address, return (do_address (ifname, address, netmask, broadcast, 0)); } -int del_address (const char *ifname, struct in_addr address) +int del_address (const char *ifname, + struct in_addr address, struct in_addr netmask) { struct in_addr t; + char *addr = strdup (inet_ntoa (address)); - logger (LOG_INFO, "deleting IP address %s", inet_ntoa (address)); + logger (LOG_INFO, "deleting IP address %s netmask %s", addr, + inet_ntoa (netmask)); + free (addr); memset (&t, 0, sizeof (t)); - return (do_address (ifname, address, t, t, 1)); + return (do_address (ifname, address, netmask, t, 1)); } int add_route (const char *ifname, struct in_addr destination, @@ -818,15 +829,16 @@ int flush_addresses (const char *ifname) { struct sockaddr *sa; struct sockaddr_in *sin; - } us; + } us_a, us_m; if (strcmp (p->ifa_name, ifname) != 0) continue; - us.sa = p->ifa_addr; + us_a.sa = p->ifa_addr; + us_m.sa = p->ifa_netmask; - if (us.sin->sin_family == AF_INET) - if (del_address (ifname, us.sin->sin_addr) < 0) + if (us_a.sin->sin_family == AF_INET) + if (del_address (ifname, us_a.sin->sin_addr, us_m.sin->sin_addr) < 0) retval = -1; } freeifaddrs (ifap); @@ -874,14 +886,13 @@ int flush_addresses (const char *ifname) ifr = ifrs; for (i = 0; i < nifs; i++) { - struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr; + struct sockaddr_in *addr = (struct sockaddr_in *) &ifr->ifr_addr; + struct sockaddr_in *netm = (struct sockaddr_in *) &ifr->ifr_netmask; - if (ifr->ifr_addr.sa_family != AF_INET - || strcmp (ifname, ifr->ifr_name) != 0) - continue; - - if (del_address (ifname, in->sin_addr) < 0) - retval = -1; + if (ifr->ifr_addr.sa_family == AF_INET + && strcmp (ifname, ifr->ifr_name) == 0) + if (del_address (ifname, addr->sin_addr, netm->sin_addr) < 0) + retval = -1; ifr++; } diff --git a/interface.h b/interface.h index d174dc8d..3d96537a 100644 --- a/interface.h +++ b/interface.h @@ -71,6 +71,7 @@ typedef struct interface_t char infofile[PATH_MAX]; struct in_addr previous_address; + struct in_addr previous_netmask; route_t *previous_routes; long start_uptime; @@ -82,7 +83,8 @@ interface_t *read_interface (const char *ifname, int metric); int add_address (const char *ifname, struct in_addr address, struct in_addr netmask, struct in_addr broadcast); -int del_address (const char *ifname, struct in_addr address); +int del_address (const char *ifname, struct in_addr address, + struct in_addr netmask); int flush_addresses (const char *ifname); int add_route (const char *ifname, struct in_addr destination,