From: Roy Marples Date: Thu, 28 Dec 2006 18:44:16 +0000 (+0000) Subject: Add static routes before any default routes as a router may require a host X-Git-Tag: v3.2.3~329 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11a02f26df40049eea9b88ee64f586d8fbd27cd5;p=thirdparty%2Fdhcpcd.git Add static routes before any default routes as a router may require a host route in the static routes. --- diff --git a/ChangeLog b/ChangeLog index 11a243a2..a5c83b73 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +Add static routes before any default routes as a router may require a host +route in the static routes. + dhcpcd-3.0.8 Fix arp checking. linux header asm/types.h doesn't work with c99 which is just wrong, diff --git a/configure.c b/configure.c index e88bbfb9..c7b26920 100644 --- a/configure.c +++ b/configure.c @@ -426,7 +426,7 @@ int configure (const options_t *options, interface_t *iface, #ifdef __linux__ /* On linux, we need to change the subnet route to have our metric. */ if (iface->previous_address.s_addr != dhcp->address.s_addr - && options->metric > 0) + && options->metric > 0 && dhcp->netmask.s_addr != INADDR_BROADCAST) { struct in_addr td; struct in_addr tg; diff --git a/dhcp.c b/dhcp.c index 85427ac7..72ba37b3 100644 --- a/dhcp.c +++ b/dhcp.c @@ -165,8 +165,8 @@ size_t send_message (const interface_t *iface, const dhcp_t *dhcp, *p++ = DHCP_CSR; /* RFC 3442 states classless static routes should be before routers * and static routes as classless static routes override them both */ - *p++ = DHCP_ROUTERS; *p++ = DHCP_STATICROUTE; + *p++ = DHCP_ROUTERS; *p++ = DHCP_HOSTNAME; *p++ = DHCP_DNSSEARCH; *p++ = DHCP_DNSDOMAIN; diff --git a/interface.c b/interface.c index a8e7f422..2990817a 100644 --- a/interface.c +++ b/interface.c @@ -115,7 +115,7 @@ interface_t *read_interface (const char *ifname, int metric) for (p = ifap; p; p = p->ifa_next) { union - { + { struct sockaddr *sa; struct sockaddr_dl *sdl; } us; @@ -130,11 +130,11 @@ interface_t *read_interface (const char *ifname, int metric) /* && us.sdl->sdl_type != IFT_ISO88025)) */ - { - logger (LOG_ERR, "interface is not Ethernet"); - freeifaddrs (ifap); - return NULL; - } + { + logger (LOG_ERR, "interface is not Ethernet"); + freeifaddrs (ifap); + return NULL; + } memcpy (hwaddr, us.sdl->sdl_data + us.sdl->sdl_nlen, ETHER_ADDR_LEN); family = us.sdl->sdl_type; @@ -278,13 +278,19 @@ static int do_route (const char *ifname, int change, int del) { int s; - char *destd; + char *dstd; char *gend; struct rtm { struct rt_msghdr hdr; struct sockaddr_in destination; - struct sockaddr_in gateway; + 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; } rtm; static int seq; @@ -295,13 +301,22 @@ static int do_route (const char *ifname, /* Do something with metric to satisfy compiler warnings */ metric = 0; - destd = strdup (inet_ntoa (destination)); + dstd = strdup (inet_ntoa (destination)); gend = strdup (inet_ntoa (netmask)); - logger (LOG_INFO, "%s route to %s (%s) via %s", - change ? "changing" : del ? "removing" : "adding", - destd, gend, inet_ntoa(gateway)); - if (destd) - free (destd); + if (gateway.s_addr == destination.s_addr) + logger (LOG_INFO, "%s route to %s (%s)", + change ? "changing" : del ? "removing" : "adding", + dstd, gend); + else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY) + logger (LOG_INFO, "%s default route via %s", + change ? "changing" : del ? "removing" : "adding", + inet_ntoa (gateway)); + else + logger (LOG_INFO, "%s route to %s (%s) via %s", + change ? "changing" : del ? "removing" : "adding", + dstd, gend, inet_ntoa (gateway)); + if (dstd) + free (dstd); if (gend) free (gend); @@ -317,9 +332,11 @@ static int do_route (const char *ifname, rtm.hdr.rtm_seq = ++seq; rtm.hdr.rtm_type = change ? RTM_CHANGE : del ? RTM_DELETE : RTM_ADD; - rtm.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; - if (netmask.s_addr == 0xffffffff) + rtm.hdr.rtm_flags = RTF_UP | RTF_STATIC; + if (netmask.s_addr == INADDR_BROADCAST) rtm.hdr.rtm_flags |= RTF_HOST; + else + rtm.hdr.rtm_flags |= RTF_GATEWAY; rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; @@ -329,7 +346,40 @@ static int do_route (const char *ifname, memcpy (&_var.sin_addr, &_addr, sizeof (struct in_addr)); ADDADDR (rtm.destination, destination); - ADDADDR (rtm.gateway, gateway); + 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)); + return -1; + } + + for (ifa = ifap; ifa; ifa = ifa->ifa_next) + { + if (ifa->ifa_addr->sa_family != AF_LINK) + continue; + + if (strcmp (ifname, ifa->ifa_name)) + continue; + + us.sa = ifa->ifa_addr; + memcpy (&rtm.gateway.sdl, us.sdl, us.sdl->sdl_len); + break; + } + freeifaddrs (ifap); + } + else + { + ADDADDR (rtm.gateway.sin, gateway); + } + ADDADDR (rtm.netmask, netmask); #undef ADDADDR @@ -369,10 +419,10 @@ static int send_netlink(struct nlmsghdr *hdr) static unsigned int seq; char buffer[16384]; union - { - char *buffer; - struct nlmsghdr *nlm; - } h; + { + char *buffer; + struct nlmsghdr *nlm; + } h; if ((s = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0) { @@ -504,7 +554,7 @@ eexit: } #define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((ptrdiff_t) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len))) + ((struct rtattr *) (((ptrdiff_t) (nmsg)) + NLMSG_ALIGN ((nmsg)->nlmsg_len))) static int add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type, const void *data, int alen) @@ -532,7 +582,7 @@ static int add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, { int len = RTA_LENGTH (sizeof (uint32_t)); struct rtattr *rta; - + if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen) { logger (LOG_ERR, "add_attr32: message exceeded bound of %d\n", maxlen); @@ -610,9 +660,18 @@ static int do_route (const char *ifname, dstd = strdup (inet_ntoa (destination)); gend = strdup (inet_ntoa (netmask)); - logger (LOG_INFO, "%s route to %s (%s) via %s, metric %d", - change ? "changing" : del ? "removing" : "adding", - dstd, gend, inet_ntoa (gateway), metric); + if (gateway.s_addr == destination.s_addr) + logger (LOG_INFO, "%s route to %s (%s) metric %d", + change ? "changing" : del ? "removing" : "adding", + dstd, gend, metric); + else if (destination.s_addr == INADDR_ANY && netmask.s_addr == INADDR_ANY) + logger (LOG_INFO, "%s default route via %s metric %d", + change ? "changing" : del ? "removing" : "adding", + inet_ntoa (gateway), metric); + else + logger (LOG_INFO, "%s route to %s (%s) via %s metric %d", + change ? "changing" : del ? "removing" : "adding", + dstd, gend, inet_ntoa (gateway), metric); if (dstd) free (dstd); if (gend) @@ -636,7 +695,8 @@ static int do_route (const char *ifname, { nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; nlm.rt.rtm_protocol = RTPROT_BOOT; - if (gateway.s_addr == 0) + if (gateway.s_addr == INADDR_ANY || + netmask.s_addr == INADDR_BROADCAST) nlm.rt.rtm_scope = RT_SCOPE_LINK; else nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE; @@ -652,7 +712,7 @@ static int do_route (const char *ifname, add_attr_l (&nlm.hdr, sizeof (nlm), RTA_DST, &destination.s_addr, sizeof (destination.s_addr)); - if (gateway.s_addr != 0) + if (gateway.s_addr != INADDR_ANY && gateway.s_addr != destination.s_addr) add_attr_l (&nlm.hdr, sizeof (nlm), RTA_GATEWAY, &gateway.s_addr, sizeof (gateway.s_addr)); @@ -684,7 +744,7 @@ int add_address (const char *ifname, struct in_addr address, int del_address (const char *ifname, struct in_addr address) { struct in_addr t; - + logger (LOG_INFO, "deleting IP address %s", inet_ntoa (address)); memset (&t, 0, sizeof (t)); @@ -724,7 +784,7 @@ int flush_addresses (const char *ifname) for (p = ifap; p; p = p->ifa_next) { union - { + { struct sockaddr *sa; struct sockaddr_in *sin; } us; diff --git a/socket.c b/socket.c index 1001320b..07909086 100644 --- a/socket.c +++ b/socket.c @@ -112,7 +112,7 @@ void make_dhcp_packet(struct udp_dhcp_packet *packet, ip->ip_len = udp->uh_ulen; udp->uh_sum = checksum ((unsigned char *) packet, sizeof (struct udp_dhcp_packet)); - + ip->ip_v = IPVERSION; ip->ip_hl = 5; ip->ip_id = 0; @@ -180,7 +180,7 @@ eexit: } #if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) \ -|| defined(__APPLE__) + || defined(__APPLE__) /* Credit where credit is due :) The below BPF filter is taken from ISC DHCP */ @@ -373,7 +373,7 @@ int get_packet (const interface_t *iface, unsigned char *data, { int len = -1; union - { + { unsigned char *buffer; struct ether_header *hw; } hdr; @@ -398,7 +398,7 @@ int get_packet (const interface_t *iface, unsigned char *data, if (valid_dhcp_packet (payload) >= 0) { union - { + { unsigned char *buffer; struct udp_dhcp_packet *packet; } pay; @@ -411,7 +411,7 @@ int get_packet (const interface_t *iface, unsigned char *data, /* Update the buffer_pos pointer */ bpf.buffer += - BPF_WORDALIGN (bpf.packet->bh_hdrlen + bpf.packet->bh_caplen); + BPF_WORDALIGN (bpf.packet->bh_hdrlen + bpf.packet->bh_caplen); if (bpf.buffer - buffer < *buffer_len) *buffer_pos = bpf.buffer - buffer; else @@ -508,10 +508,10 @@ int get_packet (const interface_t *iface, unsigned char *data, { long bytes; union - { + { unsigned char *buffer; struct udp_dhcp_packet *packet; - } pay; + } pay; /* We don't use the given buffer, but we need to rewind the position */ *buffer_pos = 0; @@ -563,7 +563,7 @@ int get_packet (const interface_t *iface, unsigned char *data, return -1; memcpy(data, &pay.packet->dhcp, - bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp))); + bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp))); return bytes - (sizeof (pay.packet->ip) + sizeof (pay.packet->udp)); }