From: Roy Marples Date: Wed, 27 Jun 2007 00:11:11 +0000 (+0000) Subject: Fix adding of routes on the BSDs. X-Git-Tag: v3.2.3~243 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f106d9a9277ec22ca392621f62df0c383eb19615;p=thirdparty%2Fdhcpcd.git Fix adding of routes on the BSDs. --- diff --git a/ChangeLog b/ChangeLog index 712368a9..733aeeee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ +Fix adding of routes on the BSDs. ROOTPATH should work correctly again, thanks to danhien. We now have 6 hostname options, which should satisfy everyone. Fix arp compilation warning on GCC-4.2.0. @@ -11,7 +12,7 @@ Create a DUID-LLT according to RFC 3315 and store it in peristent file. config.h now has the compile time options, instead of being dotted around. Added -E option, which reads the last info file and uses the information there if we timeout and the lease is still valid, thanks to Roberto Angelino. -Compiles ok on NetBSD, but doesn't add routes yet - thanks to Gabor Z. Papp. +Compiles ok on NetBSD thanks to Gabor Z. Papp. If the current hostname contains dots then send it as a FQDN. Ensure that static routes are always added before routers. Use getnameinfo instead of gethostbyaddr. diff --git a/interface.c b/interface.c index 323fc9f6..556a7189 100644 --- a/interface.c +++ b/interface.c @@ -453,17 +453,21 @@ static int do_route (const char *ifname, struct rtm { struct rt_msghdr hdr; - struct sockaddr_in destination; - union - { - struct sockaddr sa; - struct sockaddr_in sin; - struct sockaddr_dl sdl; - struct sockaddr_storage sss; /* added to avoid memory overrun */ - } gateway; - struct sockaddr_in netmask; + char buffer[sizeof (struct sockaddr_storage) * 3]; } rtm; + char *bp = rtm.buffer; static int seq; + union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; +#ifdef INET6 + struct sockaddr_in6 sin6; +#endif + struct sockaddr_dl sdl; + struct sockaddr_storage ss; + } su; + + int l; if (! ifname) return -1; @@ -476,7 +480,7 @@ static int do_route (const char *ifname, logger (LOG_INFO, "%s route to %s/%d", change ? "changing" : del ? "removing" : "adding", dstd, inet_ntocidr (netmask)); - else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY) + else if (destination.s_addr == INADDR_ANY) logger (LOG_INFO, "%s default route via %s", change ? "changing" : del ? "removing" : "adding", inet_ntoa (gateway)); @@ -499,26 +503,27 @@ static int do_route (const char *ifname, rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD; rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC; - if (netmask.s_addr == INADDR_BROADCAST) + if (netmask.s_addr == INADDR_BROADCAST) rtm.hdr.rtm_flags |= RTF_HOST; else rtm.hdr.rtm_flags |= RTF_GATEWAY; + /* This order is important */ rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; -#define ADDADDR(_var, _addr) \ - _var.sin_family = AF_INET; \ - _var.sin_len = sizeof (struct sockaddr_in); \ - memcpy (&_var.sin_addr, &_addr, sizeof (struct in_addr)); +#define ADDADDR(_addr) \ + memset (&su, 0, sizeof (struct sockaddr_storage)); \ + su.sin.sin_family = AF_INET; \ + su.sin.sin_len = sizeof (struct sockaddr_in); \ + memcpy (&su.sin.sin_addr, &_addr, sizeof (struct in_addr)); \ + l = SA_SIZE (&(su.sa)); \ + memcpy (bp, &(su), l); \ + bp += l; + + ADDADDR (destination); - ADDADDR (rtm.destination, destination); if (netmask.s_addr == INADDR_BROADCAST) { struct ifaddrs *ifap, *ifa; - union - { - struct sockaddr *sa; - struct sockaddr_dl *sdl; - } us; if (getifaddrs (&ifap)) { logger (LOG_ERR, "getifaddrs: %s", strerror (errno)); @@ -533,21 +538,20 @@ static int do_route (const char *ifname, if (strcmp (ifname, ifa->ifa_name)) continue; - us.sa = ifa->ifa_addr; - memcpy (&rtm.gateway.sdl, us.sdl, us.sdl->sdl_len); + l = SA_SIZE (ifa->ifa_addr); + memcpy (bp, ifa->ifa_addr, l); + bp += l; break; } freeifaddrs (ifap); } else { - ADDADDR (rtm.gateway.sin, gateway); + ADDADDR (gateway); } - ADDADDR (rtm.netmask, netmask); - + ADDADDR (netmask); #undef ADDADDR rtm.hdr.rtm_msglen = sizeof (rtm); - if (write(s, &rtm, sizeof (rtm)) < 0) { /* Don't report error about routes already existing */ if (errno != EEXIST)