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.
+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.
# Should work for both GNU make and BSD make
-VERSION = 3.0.12_pre1
+VERSION = 3.0.12_pre2
CFLAGS ?= -O2 -pipe
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");
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;
}
}
- 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)
/* 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);
/* 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. */
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
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)
/* 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;
}
}
-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;
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;
" [-u userclass] [-F [none | ptr | both]] [-I clientID]\n");
}
-
int main(int argc, char **argv)
{
options_t options;
int ch;
int option_index = 0;
char prefix[IF_NAMESIZE + 3];
+ pid_t pid;
const struct option longopts[] =
{
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);
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);
#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));
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));
}
#endif
+ strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
{
logger (LOG_ERR, "ioctl SIOCGIFFLAGS: %s", strerror (errno));
}
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));
}
ADDADDR (ifa.ifra_addr, address);
+ ADDADDR (ifa.ifra_mask, netmask);
if (! del)
{
- ADDADDR (ifa.ifra_mask, netmask);
ADDADDR (ifa.ifra_broadaddr, broadcast);
}
struct iovec iov;
struct msghdr msg;
static unsigned int seq;
- char buffer[16384];
+ char buffer[256];
+ int bytes;
union
{
char *buffer;
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;
}
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;
}
{
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;
/* 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);
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;
}
}
{
struct nlmsghdr hdr;
struct ifaddrmsg ifa;
- char buffer[256];
+ char buffer[64];
}
nlm;
uint32_t mask = htonl (netmask.s_addr);
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;
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,
{
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);
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++;
}
char infofile[PATH_MAX];
struct in_addr previous_address;
+ struct in_addr previous_netmask;
route_t *previous_routes;
long start_uptime;
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,