From f08761da93e16f0d2afcd64d81db349325665e44 Mon Sep 17 00:00:00 2001 From: roy Date: Wed, 28 Mar 2012 10:19:31 +0000 Subject: [PATCH] * Fixed a potential segfault with IPv6 option handling * Add a suffix to all our config files so that RA never stamps on IPv4 * All valgrind errors fixed on FreeBSD (with ./configure --debug=YES) * When started with an interface list, respect that with signal handling * Fix a potential route table corruption if we failed to add a route --- external/bsd/dhcpcd/dist/configure.c | 50 ++++++++++--------- external/bsd/dhcpcd/dist/defs.h | 2 +- .../dhcpcd/dist/dhcpcd-hooks/20-resolv.conf | 16 +++--- .../bsd/dhcpcd/dist/dhcpcd-hooks/50-ntp.conf | 8 +-- .../bsd/dhcpcd/dist/dhcpcd-hooks/50-ypbind | 8 +-- external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in | 17 ++++--- external/bsd/dhcpcd/dist/dhcpcd.c | 29 +++++++---- external/bsd/dhcpcd/dist/if-bsd.c | 38 +++++++++----- external/bsd/dhcpcd/dist/ipv6rs.c | 4 +- external/bsd/dhcpcd/dist/net.c | 16 ++++++ external/bsd/dhcpcd/dist/net.h | 15 ++---- 11 files changed, 121 insertions(+), 82 deletions(-) diff --git a/external/bsd/dhcpcd/dist/configure.c b/external/bsd/dhcpcd/dist/configure.c index e61184becc8b..88ff5d9add60 100644 --- a/external/bsd/dhcpcd/dist/configure.c +++ b/external/bsd/dhcpcd/dist/configure.c @@ -435,9 +435,10 @@ find_route(struct rt *rts, const struct rt *r, struct rt **lrt, } static void -desc_route(const char *cmd, const struct rt *rt, const char *ifname) +desc_route(const char *cmd, const struct rt *rt) { char addr[sizeof("000.000.000.000") + 1]; + const char *ifname = rt->iface->name; strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr)); if (rt->gate.s_addr == INADDR_ANY) @@ -465,7 +466,7 @@ route_deleted(const struct rt *rt) f = find_route(routes, rt, &l, NULL); if (f == NULL) return 0; - desc_route("removing", f, f->iface->name); + desc_route("removing", f); if (l) l->next = f->next; else @@ -475,59 +476,60 @@ route_deleted(const struct rt *rt) } static int -n_route(struct rt *rt, const struct interface *iface) +n_route(struct rt *rt) { /* Don't set default routes if not asked to */ if (rt->dest.s_addr == 0 && rt->net.s_addr == 0 && - !(iface->state->options->options & DHCPCD_GATEWAY)) + !(rt->iface->state->options->options & DHCPCD_GATEWAY)) return -1; - desc_route("adding", rt, iface->name); - if (!add_route(iface, &rt->dest, &rt->net, &rt->gate, iface->metric)) + desc_route("adding", rt); + if (!add_route(rt)) return 0; if (errno == EEXIST) { /* Pretend we added the subnet route */ - if (rt->dest.s_addr == (iface->addr.s_addr & iface->net.s_addr) && - rt->net.s_addr == iface->net.s_addr && + if (rt->dest.s_addr == + (rt->iface->addr.s_addr & rt->iface->net.s_addr) && + rt->net.s_addr == rt->iface->net.s_addr && rt->gate.s_addr == 0) return 0; else return -1; } - syslog(LOG_ERR, "%s: add_route: %m", iface->name); + syslog(LOG_ERR, "%s: add_route: %m", rt->iface->name); return -1; } static int -c_route(struct rt *ort, struct rt *nrt, const struct interface *iface) +c_route(struct rt *ort, struct rt *nrt) { /* Don't set default routes if not asked to */ if (nrt->dest.s_addr == 0 && nrt->net.s_addr == 0 && - !(iface->state->options->options & DHCPCD_GATEWAY)) + !(nrt->iface->state->options->options & DHCPCD_GATEWAY)) return -1; - desc_route("changing", nrt, iface->name); + desc_route("changing", nrt); /* We delete and add the route so that we can change metric. * This also has the nice side effect of flushing ARP entries so * we don't have to do that manually. */ - del_route(ort->iface, &ort->dest, &ort->net, &ort->gate, ort->metric); - if (!add_route(iface, &nrt->dest, &nrt->net, &nrt->gate, nrt->metric)) + del_route(ort); + if (!add_route(nrt)) return 0; - syslog(LOG_ERR, "%s: add_route: %m", iface->name); + syslog(LOG_ERR, "%s: add_route: %m", nrt->iface->name); return -1; } static int -d_route(struct rt *rt, const struct interface *iface, int metric) +d_route(struct rt *rt) { int retval; - desc_route("deleting", rt, iface->name); - retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric); + desc_route("deleting", rt); + retval = del_route(rt); if (retval != 0 && errno != ENOENT && errno != ESRCH) - syslog(LOG_ERR,"%s: del_route: %m", iface->name); + syslog(LOG_ERR,"%s: del_route: %m", rt->iface->name); return retval; } @@ -712,7 +714,7 @@ build_routes(void) rt->gate.s_addr != or->gate.s_addr || rt->metric != or->metric) { - if (c_route(or, rt, ifp) != 0) + if (c_route(or, rt) != 0) continue; } if (rtl != NULL) @@ -721,7 +723,7 @@ build_routes(void) routes = or->next; free(or); } else { - if (n_route(rt, ifp) != 0) + if (n_route(rt) != 0) continue; } if (dnr == rt) @@ -730,6 +732,7 @@ build_routes(void) lrt->next = rtn; rt->next = nrs; nrs = rt; + rt = lrt; /* When we loop this makes lrt correct */ } free_routes(dnr); } @@ -737,7 +740,7 @@ build_routes(void) /* Remove old routes we used to manage */ for (rt = routes; rt; rt = rt->next) { if (find_route(nrs, rt, NULL, NULL) == NULL) - d_route(rt, rt->iface, rt->iface->metric); + d_route(rt); } free_routes(routes); @@ -817,8 +820,9 @@ configure(struct interface *iface) rt = get_subnet_route(dhcp); if (rt != NULL) { rt->iface = iface; + rt->metric = 0; if (!find_route(routes, rt, NULL, NULL)) - del_route(iface, &rt->dest, &rt->net, &rt->gate, 0); + del_route(rt); free(rt); } diff --git a/external/bsd/dhcpcd/dist/defs.h b/external/bsd/dhcpcd/dist/defs.h index 84fdcc2b53ad..b4f238097876 100644 --- a/external/bsd/dhcpcd/dist/defs.h +++ b/external/bsd/dhcpcd/dist/defs.h @@ -28,7 +28,7 @@ #define CONFIG_H #define PACKAGE "dhcpcd" -#define VERSION "5.5.5" +#define VERSION "5.5.6" #ifndef CONFIG # define CONFIG SYSCONFDIR "/" PACKAGE ".conf" diff --git a/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf b/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf index b4dd5f385edf..42aff68bb977 100644 --- a/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf +++ b/external/bsd/dhcpcd/dist/dhcpcd-hooks/20-resolv.conf @@ -12,7 +12,7 @@ NL=" build_resolv_conf() { - local cf="$state_dir/resolv.conf.$interface$if_suffix" + local cf="$state_dir/resolv.conf.$ifname" local interfaces= header= search= srvs= servers= x= # Build a list of interfaces @@ -114,25 +114,25 @@ add_resolv_conf() done if type resolvconf >/dev/null 2>&1; then [ -n "$ifmetric" ] && export IF_METRIC="$ifmetric" - printf %s "$conf" | resolvconf -a "$interface$if_suffix" + printf %s "$conf" | resolvconf -a "$ifname" return $? fi - if [ -e "$resolv_conf_dir/$interface$if_suffix" ]; then - rm -f "$resolv_conf_dir/$interface$if_suffix" + if [ -e "$resolv_conf_dir/$ifname" ]; then + rm -f "$resolv_conf_dir/$ifname" fi [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir" - printf %s "$conf" > "$resolv_conf_dir/$interface$if_suffix" + printf %s "$conf" > "$resolv_conf_dir/$ifname" build_resolv_conf } remove_resolv_conf() { if type resolvconf >/dev/null 2>&1; then - resolvconf -d "$interface$if_suffix" -f + resolvconf -d "$ifname" -f else - if [ -e "$resolv_conf_dir/$interface$if_suffix" ]; then - rm -f "$resolv_conf_dir/$interface$if_suffix" + if [ -e "$resolv_conf_dir/$ifname" ]; then + rm -f "$resolv_conf_dir/$ifname" fi build_resolv_conf fi diff --git a/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ntp.conf b/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ntp.conf index 83e71bf03583..adbe62024b74 100644 --- a/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ntp.conf +++ b/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ntp.conf @@ -25,7 +25,7 @@ NL=" build_ntp_conf() { - local cf="$state_dir/ntp.conf.$interface" + local cf="$state_dir/ntp.conf.$ifname" local interfaces= header= srvs= servers= x= # Build a list of interfaces @@ -75,7 +75,7 @@ build_ntp_conf() add_ntp_conf() { - local cf="$ntp_conf_dir/$interface" x= + local cf="$ntp_conf_dir/$ifname" x= [ -e "$cf" ] && rm "$cf" [ -d "$ntp_conf_dir" ] || mkdir -p "$ntp_conf_dir" @@ -89,8 +89,8 @@ add_ntp_conf() remove_ntp_conf() { - if [ -e "$ntp_conf_dir/$interface" ]; then - rm "$ntp_conf_dir/$interface" + if [ -e "$ntp_conf_dir/$ifname" ]; then + rm "$ntp_conf_dir/$ifname" fi build_ntp_conf } diff --git a/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ypbind b/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ypbind index f63660e5081c..25e009d7fc2b 100644 --- a/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ypbind +++ b/external/bsd/dhcpcd/dist/dhcpcd-hooks/50-ypbind @@ -20,12 +20,12 @@ best_domain() make_yp_binding() { [ -d "$ypbind_dir" ] || mkdir -p "$ypbind_dir" - echo "$new_nis_domain" >"$ypbind_dir/$interface" + echo "$new_nis_domain" >"$ypbind_dir/$ifname" local nd="$(best_domain)" local cf=/var/yp/binding/"$new_nis_domain".ypservers if [ -n "$new_nis_servers" ]; then - local ncf="$cf.$interface" x= + local ncf="$cf.$ifname" x= rm -f "$ncf" for x in $new_nis_servers; do echo "$x" >>"$ncf" @@ -46,7 +46,7 @@ make_yp_binding() restore_yp_binding() { - rm -f "$ypbind_dir/$interface" + rm -f "$ypbind_dir/$ifname" local nd="$(best_domain)" # We need to stop ypbind if there is no best domain # otherwise it will just stall as we cannot set domainname @@ -64,7 +64,7 @@ restore_yp_binding() } if [ "$reason" = PREINIT ]; then - rm -f "$ypbind_dir/$interface" + rm -f "$ypbind_dir/$ifname" elif $if_up || $if_down; then if [ -n "$new_nis_domain" ]; then if valid_domainname "$new_nis_domain"; then diff --git a/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in b/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in index dc7dfeb9e13b..2125f9a2857e 100644 --- a/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in +++ b/external/bsd/dhcpcd/dist/dhcpcd-run-hooks.in @@ -2,19 +2,20 @@ # dhcpcd client configuration script # Handy variables and functions for our hooks to use +if [ "$reason" = ROUTERADVERT ]; then + ifsuffix=":ra" +else + ifsuffix= +fi +ifname="$interface$ifsuffix" + from=from signature_base="# Generated by dhcpcd" -signature="$signature_base $from $interface" +signature="$signature_base $from $ifname" signature_base_end="# End of dhcpcd" -signature_end="$signature_base_end $from $interface" +signature_end="$signature_base_end $from $ifname" state_dir=/var/run/dhcpcd -if [ "$reason" = ROUTERADVERT ]; then - if_suffix=":ra" -else - if_suffix= -fi - # Ensure that all arguments are unique uniqify() { diff --git a/external/bsd/dhcpcd/dist/dhcpcd.c b/external/bsd/dhcpcd/dist/dhcpcd.c index ad591dcf37bd..d46e88a948a2 100644 --- a/external/bsd/dhcpcd/dist/dhcpcd.c +++ b/external/bsd/dhcpcd/dist/dhcpcd.c @@ -146,15 +146,24 @@ read_pid(void) static void usage(void) { - printf("usage: "PACKAGE" [-dgknpqwxyADEGHJKLOTV] [-c script] [-f file]" - " [-e var=val]\n" - " [-h hostname] [-i classID ] [-l leasetime]" - " [-m metric] [-o option]\n" - " [-r ipaddr] [-s ipaddr] [-t timeout]" - " [-u userclass]\n" - " [-F none|ptr|both] [-I clientID] [-C hookscript]" - " [-Q option]\n" - " [-X ipaddr] \n"); + +printf("usage: "PACKAGE"\t[-ABbDdEGgHJKkLnpqTVw]\n" + "\t\t[-C, --nohook hook] [-c, --script script]\n" + "\t\t[-e, --env value] [-F, --fqdn FQDN] [-f, --config file]\n" + "\t\t[-h, --hostname hostname] [-I, --clientid clientid]\n" + "\t\t[-i, --vendorclassid vendorclassid] [-l, --leasetime seconds]\n" + "\t\t[-m, --metric metric] [-O, --nooption option]\n" + "\t\t[-o, --option option] [-Q, --require option]\n" + "\t\t[-r, --request address] [-S, --static value]\n" + "\t\t[-s, --inform address[/cidr]] [-t, --timeout seconds]\n" + "\t\t[-u, --userclass class] [-v, --vendor code, value]\n" + "\t\t[-W, --whitelist address[/cidr]] [-y, --reboot seconds]\n" + "\t\t[-X, --blacklist address[/cidr]] [-Z, --denyinterfaces pattern]\n" + "\t\t[-z, --allowinterfaces pattern] [interface] [...]\n" + " "PACKAGE"\t-k, --release [interface]\n" + " "PACKAGE"\t-U, --dumplease interface\n" + " "PACKAGE"\t-v, --version\n" + " "PACKAGE"\t-x, --exit [interface]\n"); } static void @@ -1524,7 +1533,7 @@ handle_signal(_unused void *arg) ifo->options |= DHCPCD_DAEMONISED; options = ifo->options; free_options(ifo); - reconf_reboot(1, 0, NULL, 0); + reconf_reboot(1, ifc, ifv, 0); return; case SIGHUP: syslog(LOG_INFO, "received SIGHUP, releasing"); diff --git a/external/bsd/dhcpcd/dist/if-bsd.c b/external/bsd/dhcpcd/dist/if-bsd.c index c959b5e41bad..c3ffcace8df8 100644 --- a/external/bsd/dhcpcd/dist/if-bsd.c +++ b/external/bsd/dhcpcd/dist/if-bsd.c @@ -90,6 +90,15 @@ if_conf(_unused struct interface *iface) return 0; } +#ifdef DEBUG_MEMORY +static void +cleanup(void) +{ + + free(link_buf); +} +#endif + int init_sockets(void) { @@ -129,6 +138,7 @@ getifssid(const char *ifname, char *ssid) strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name)); ireq.i_type = IEEE80211_IOC_SSID; ireq.i_val = -1; + memset(nwid, 0, sizeof(nwid)); ireq.i_data = &nwid; if (ioctl(socket_afnet, SIOCG80211, &ireq) == 0) { retval = ireq.i_len; @@ -177,9 +187,7 @@ if_address(const struct interface *iface, const struct in_addr *address, /* ARGSUSED4 */ int -if_route(const struct interface *iface, const struct in_addr *dest, - const struct in_addr *net, const struct in_addr *gate, - _unused int metric, int action) +if_route(const struct rt *rt, int action) { union sockunion { struct sockaddr sa; @@ -223,12 +231,13 @@ if_route(const struct interface *iface, const struct in_addr *dest, rtm.hdr.rtm_type = RTM_DELETE; rtm.hdr.rtm_flags = RTF_UP; /* None interface subnet routes are static. */ - if (gate->s_addr != INADDR_ANY || - net->s_addr != iface->net.s_addr || - dest->s_addr != (iface->addr.s_addr & iface->net.s_addr)) + if (rt->gate.s_addr != INADDR_ANY || + rt->net.s_addr != rt->iface->net.s_addr || + rt->dest.s_addr != (rt->iface->addr.s_addr & rt->iface->net.s_addr)) rtm.hdr.rtm_flags |= RTF_STATIC; rtm.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY; - if (dest->s_addr == gate->s_addr && net->s_addr == INADDR_BROADCAST) + if (rt->dest.s_addr == rt->gate.s_addr && + rt->net.s_addr == INADDR_BROADCAST) rtm.hdr.rtm_flags |= RTF_HOST; else { rtm.hdr.rtm_addrs |= RTA_NETMASK; @@ -238,23 +247,23 @@ if_route(const struct interface *iface, const struct in_addr *dest, rtm.hdr.rtm_addrs |= RTA_IFA; } - ADDADDR(dest); + ADDADDR(&rt->dest); if (rtm.hdr.rtm_flags & RTF_HOST || !(rtm.hdr.rtm_flags & RTF_STATIC)) { /* Make us a link layer socket for the host gateway */ memset(&su, 0, sizeof(su)); su.sdl.sdl_len = sizeof(struct sockaddr_dl); - link_addr(iface->name, &su.sdl); + link_addr(rt->iface->name, &su.sdl); ADDSU(su); } else - ADDADDR(gate); + ADDADDR(&rt->gate); if (rtm.hdr.rtm_addrs & RTA_NETMASK) - ADDADDR(net); + ADDADDR(&rt->net); if (rtm.hdr.rtm_addrs & RTA_IFA) - ADDADDR(&iface->addr); + ADDADDR(&rt->iface->addr); rtm.hdr.rtm_msglen = l = bp - (char *)&rtm; if (write(r_fd, &rtm, l) == -1) @@ -267,6 +276,11 @@ open_link_socket(void) { int fd; +#ifdef DEBUG_MEMORY + if (link_buf == NULL) + atexit(cleanup); +#endif + fd = socket(PF_ROUTE, SOCK_RAW, 0); if (fd != -1) { set_cloexec(fd); diff --git a/external/bsd/dhcpcd/dist/ipv6rs.c b/external/bsd/dhcpcd/dist/ipv6rs.c index 8ebdbd89f257..df969340626e 100644 --- a/external/bsd/dhcpcd/dist/ipv6rs.c +++ b/external/bsd/dhcpcd/dist/ipv6rs.c @@ -533,7 +533,8 @@ ipv6rs_handledata(_unused void *arg) rap->options = rao; rao->type = ndo->nd_opt_type; rao->option = opt; - } + } else + free(opt); if (lifetime == ~0U) timerclear(&rao->expire); else { @@ -751,7 +752,6 @@ ipv6rs_start(struct interface *ifp) /* Always make a new probe as the underlying hardware * address could have changed. */ - free(ifp->rs); ipv6rs_makeprobe(ifp); if (ifp->rs == NULL) return -1; diff --git a/external/bsd/dhcpcd/dist/net.c b/external/bsd/dhcpcd/dist/net.c index 14322b190a6f..d8c972ce98ae 100644 --- a/external/bsd/dhcpcd/dist/net.c +++ b/external/bsd/dhcpcd/dist/net.c @@ -74,6 +74,21 @@ static char hwaddr_buffer[(HWADDR_LEN * 3) + 1]; int socket_afnet = -1; +#if defined(__FreeBSD__) && defined(DEBUG_MEMORY) +/* FreeBSD does not zero the struct, causing valgrind errors */ +unsigned int +if_nametoindex(const char *ifname) +{ + struct ifreq ifr; + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + if (ioctl(socket_afnet, SIOCGIFINDEX, &ifr) != -1) + return ifr.ifr_index; + return 0; +} +#endif + int inet_ntocidr(struct in_addr address) { @@ -242,6 +257,7 @@ free_interface(struct interface *iface) free(iface->state->offer); free(iface->state); } + free(iface->buffer); free(iface->clientid); free(iface); } diff --git a/external/bsd/dhcpcd/dist/net.h b/external/bsd/dhcpcd/dist/net.h index 9d83e2137af1..f1817983ee43 100644 --- a/external/bsd/dhcpcd/dist/net.h +++ b/external/bsd/dhcpcd/dist/net.h @@ -124,16 +124,11 @@ int if_address(const struct interface *, #define get_address(iface, addr, net, dst) \ do_address(iface, addr, net, dst, 1) -int if_route(const struct interface *, const struct in_addr *, - const struct in_addr *, const struct in_addr *, int, int); -#define add_route(iface, dest, mask, gate, metric) \ - if_route(iface, dest, mask, gate, metric, 1) -#define change_route(iface, dest, mask, gate, metric) \ - if_route(iface, dest, mask, gate, metric, 0) -#define del_route(iface, dest, mask, gate, metric) \ - if_route(iface, dest, mask, gate, metric, -1) -#define del_src_route(iface, dest, mask, gate, metric) \ - if_route(iface, dest, mask, gate, metric, -2) +int if_route(const struct rt *rt, int); +#define add_route(rt) if_route(rt, 1) +#define change_route(rt) if_route(rt, 0) +#define del_route(rt) if_route(rt, -1) +#define del_src_route(rt) if_route(rt, -2); void free_routes(struct rt *); int open_udp_socket(struct interface *);