]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Move route state into it's own flag.
authorRoy Marples <roy@marples.name>
Tue, 28 Jul 2015 13:58:31 +0000 (13:58 +0000)
committerRoy Marples <roy@marples.name>
Tue, 28 Jul 2015 13:58:31 +0000 (13:58 +0000)
Instead of setting the interface MTU directly, set the MTU for each of the
routes derived from the DHCP message in the same way we do for IPv6 RA.

12 files changed:
dhcp.c
dhcp.h
dhcpcd-hooks/10-mtu [deleted file]
dhcpcd-hooks/Makefile
dhcpcd.8.in
dhcpcd.conf
dhcpcd.conf.5.in
if-bsd.c
if-linux.c
ipv4.c
ipv4.h
ipv4ll.c

diff --git a/dhcp.c b/dhcp.c
index 713b3be44db9d4995187b7aa54fdc88010b46239..e7fc9e46050b56b88a4dccbbb903c8d94f550e59 100644 (file)
--- a/dhcp.c
+++ b/dhcp.c
@@ -275,6 +275,23 @@ get_option_uint32(struct dhcpcd_ctx *ctx,
        return 0;
 }
 
+static int
+get_option_uint16(struct dhcpcd_ctx *ctx,
+    uint16_t *i, const struct dhcp_message *dhcp, uint8_t option)
+{
+       const uint8_t *p;
+       size_t len;
+       uint16_t d;
+
+       p = get_option(ctx, dhcp, option, &len);
+       if (!p || len < (ssize_t)sizeof(d))
+               return -1;
+       memcpy(&d, p, sizeof(d));
+       if (i)
+               *i = ntohs(d);
+       return 0;
+}
+
 static int
 get_option_uint8(struct dhcpcd_ctx *ctx,
     uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
@@ -583,7 +600,7 @@ route_netmask(uint32_t ip_in)
 /* We need to obey routing options.
  * If we have a CSR then we only use that.
  * Otherwise we add static routes and then routers. */
-struct rt_head *
+static struct rt_head *
 get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
 {
        struct if_options *ifo = ifp->options;
@@ -689,6 +706,40 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
        return routes;
 }
 
+uint16_t
+dhcp_get_mtu(const struct interface *ifp)
+{
+       const struct dhcp_message *dhcp;
+       uint16_t mtu;
+
+       if ((dhcp = D_CSTATE(ifp)->new) == NULL ||
+           has_option_mask(ifp->options->nomask, DHO_MTU) ||
+           get_option_uint16(ifp->ctx, &mtu, dhcp, DHO_MTU) == -1)
+               return 0;
+       return mtu;
+}
+
+/* Grab our routers from the DHCP message and apply any MTU value
+ * the message contains */
+struct rt_head *
+dhcp_get_routes(struct interface *ifp)
+{
+       struct rt_head *routes;
+       uint16_t mtu;
+       const struct dhcp_message *dhcp;
+
+       dhcp = D_CSTATE(ifp)->new;
+       routes = get_option_routes(ifp, dhcp);
+       if ((mtu = dhcp_get_mtu(ifp)) != 0) {
+               struct rt *rt;
+
+               TAILQ_FOREACH(rt, routes, next) {
+                       rt->mtu = mtu;
+               }
+       }
+       return routes;
+}
+
 #define PUTADDR(_type, _val)                                                 \
        {                                                                     \
                *p++ = _type;                                                 \
diff --git a/dhcp.h b/dhcp.h
index daa4f56000568b1e14d172e99bf216ea746df626..1495aafbd438d187d05472b7c7093f4ad8635dfd 100644 (file)
--- a/dhcp.h
+++ b/dhcp.h
@@ -245,8 +245,8 @@ int get_option_addr(struct dhcpcd_ctx *,struct in_addr *,
     const struct dhcp_message *, uint8_t);
 #define IS_BOOTP(i, m) ((m) != NULL &&                                             \
            get_option_uint8((i)->ctx, NULL, (m), DHO_MESSAGETYPE) == -1)
-struct rt_head *get_option_routes(struct interface *,
-    const struct dhcp_message *);
+uint16_t dhcp_get_mtu(const struct interface *);
+struct rt_head *dhcp_get_routes(struct interface *);
 ssize_t dhcp_env(char **, const char *, const struct dhcp_message *,
     const struct interface *);
 
diff --git a/dhcpcd-hooks/10-mtu b/dhcpcd-hooks/10-mtu
deleted file mode 100644 (file)
index f563624..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# Configure the MTU for the interface
-
-mtu_dir="$state_dir/mtu"
-
-set_mtu()
-{
-       local mtu=$1
-
-       if [ -w /sys/class/net/$interface/mtu ]; then
-               echo "$mtu" >/sys/class/net/$interface/mtu
-       else
-               ifconfig "$interface" mtu "$mtu"
-       fi
-}
-
-# Only set interface MTU on either a DHCP option recieved or a static
-# configuration for IPv4 which is wrapped in the DHCP setup.
-# IPv6 MTU is done via routing.
-if [ "$ifsuffix" = ".dhcp" ]; then
-       if [ "$reason" = PREINIT -a -e "$mtu_dir/$interface" ]; then
-               rm "$mtu_dir/$interface"
-       elif [ -n "$new_interface_mtu" ] && $if_up; then
-               # The smalled MTU dhcpcd can work with is 576
-               if [ "$new_interface_mtu" -ge 576 ]; then
-                       if set_mtu "$new_interface_mtu"; then
-                               syslog info "MTU set to $new_interface_mtu"
-                               # Save the MTU so we can restore it later
-                               if [ ! -e "$mtu_dir/$interface" ]; then
-                                       mkdir -p "$mtu_dir"
-                                       echo "$ifmtu" > "$mtu_dir/$interface"
-                               fi
-                       fi
-               fi
-       elif [ -e "$mtu_dir/$interface" ]; then
-               if $if_up || $if_down; then
-                       # No MTU in this state, so restore the prior MTU
-                       mtu=$(cat "$mtu_dir/$interface")
-                       syslog info "MTU restored to $mtu"
-                       set_mtu "$mtu"
-                       rm "$mtu_dir/$interface"
-               fi
-       fi
-fi
index 6328509000ef33296a7cfeac5c21ac910dc8b8ba..24c9726d67fd0e4619706241e8c1b719363c04aa 100644 (file)
@@ -4,7 +4,7 @@ include ${TOP}/iconfig.mk
 
 SCRIPTSDIR=    ${LIBEXECDIR}/dhcpcd-hooks
 SCRIPTS=       01-test 02-dump
-SCRIPTS+=      10-mtu 10-wpa_supplicant 15-timezone 20-resolv.conf
+SCRIPTS+=      10-wpa_supplicant 15-timezone 20-resolv.conf
 SCRIPTS+=      29-lookup-hostname 30-hostname
 SCRIPTS+=      ${HOOKSCRIPTS}
 
index 9f29a505ea6a78ea28859f488d254d7391c16807..4d46d52e70f6d5a284f1ec1605f27c438c957f7d 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd July 3, 2015
+.Dd July 28, 2015
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -551,8 +551,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
 .Pp
 So to stop
 .Nm
-from touching your DNS or MTU settings you would do:-
-.D1 dhcpcd -C resolv.conf -C mtu eth0
+from touching your DNS settings you would do:-
+.D1 dhcpcd -C resolv.conf eth0
 .It Fl G , Fl Fl nogateway
 Don't set any default routes.
 .It Fl H , Fl Fl xidhwaddr
index e5a19cd8b083401201784004da85814989b3b73d..3108599405a156847cb15b8c6c3c814ca5482507 100644 (file)
@@ -28,9 +28,8 @@ option domain_name_servers, domain_name, domain_search, host_name
 option classless_static_routes
 # Most distributions have NTP support.
 option ntp_servers
-# Respect the network MTU.
-# Some interface drivers reset when changing the MTU so disabled by default.
-#option interface_mtu
+# Respect the network MTU. This is applied to DHCP routes.
+option interface_mtu
 
 # A ServerID is required by RFC2131.
 require dhcp_server_identifier
index d70255730144a87a69bb2a791876da66d17d0491..1f9dbf52ba8bba811f1eb500bab82f5f5e786ace 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd July 22, 2015
+.Dd July 28, 2015
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -430,8 +430,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
 .Pp
 So to stop
 .Nm dhcpcd
-from touching your DNS or MTU settings you would do:-
-.D1 nohook resolv.conf, mtu
+from touching your DNS settings or starting wpa_supplicant you would do:-
+.D1 nohook resolv.conf, wpa_supplicant
 .It Ic noipv4
 Don't attempt to configure an IPv4 address.
 .It Ic noipv4ll
index 2f0c1fff753992e8685db424d3d035cbe3d28806..23864e7680acda27a611291f48c61e2db59f8ff8 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -500,6 +500,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
 
        get_addrs(rtm->rtm_addrs, cp, rti_info);
        memset(rt, 0, sizeof(*rt));
+       rt->flags = (unsigned int)rtm->rtm_flags;
        COPYOUT(rt->dest, rti_info[RTAX_DST]);
        if (rtm->rtm_addrs & RTA_NETMASK)
                COPYOUT(rt->net, rti_info[RTAX_NETMASK]);
@@ -508,6 +509,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
        COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
        COPYOUT(rt->src, rti_info[RTAX_IFA]);
 
+       if (rtm->rtm_inits & RTV_MTU)
+               rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
+
        if (rtm->rtm_index)
                rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
        else if (rtm->rtm_addrs & RTA_IFP) {
@@ -516,6 +520,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
                sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
                rt->iface = if_findsdl(ctx, sdl);
        }
+
        /* If we don't have an interface and it's a host route, it maybe
         * to a local ip via the loopback interface. */
        if (rt->iface == NULL &&
@@ -658,6 +663,11 @@ if_route(unsigned char cmd, const struct rt *rt)
 
                if (rtm.hdr.rtm_addrs & RTA_IFA)
                        ADDADDR(&state->addr);
+
+               if (rt->mtu) {
+                       rtm.hdr.rtm_inits |= RTV_MTU;
+                       rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
+               }
        }
 
 #undef ADDADDR
@@ -897,6 +907,9 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
                ipv6_mask(&rt->net, 128);
        COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
 
+       if (rtm->rtm_inits & RTV_MTU)
+               rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
+
        if (rtm->rtm_index)
                rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
        else if (rtm->rtm_addrs & RTA_IFP) {
index 8b08822a77d67fe730c2f12faa7812797b0fcb2c..727c2c94fdc4d6eb331fdf7a7736b1b938ffd87b 100644 (file)
@@ -922,6 +922,27 @@ add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
        return 0;
 }
 
+static int
+rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
+    unsigned short type, uint32_t data)
+{
+       unsigned short len = RTA_LENGTH(sizeof(data));
+       struct rtattr *subrta;
+
+       if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
+               errno = ENOBUFS;
+               return -1;
+       }
+
+       subrta = (struct rtattr*)(void *)
+           (((char*)rta) + RTA_ALIGN(rta->rta_len));
+       subrta->rta_type = type;
+       subrta->rta_len = len;
+       memcpy(RTA_DATA(subrta), &data, sizeof(data));
+       rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
+       return 0;
+}
+
 #ifdef HAVE_NL80211_H
 static struct nlattr *
 nla_next(struct nlattr *nla, size_t *rem)
@@ -1374,6 +1395,17 @@ if_route(unsigned char cmd, const struct rt *rt)
        if (rt->metric)
                add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
 
+       if (cmd != RTM_DELETE && rt->mtu) {
+               char metricsbuf[32];
+               struct rtattr *metrics = (void *)metricsbuf;
+
+               metrics->rta_type = RTA_METRICS;
+               metrics->rta_len = RTA_LENGTH(0);
+               rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
+               add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
+                   RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics));
+       }
+
        if (send_netlink(rt->iface->ctx, NULL,
            NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
                retval = -1;
@@ -1488,27 +1520,6 @@ if_address6(const struct ipv6_addr *ap, int action)
        return retval;
 }
 
-static int
-rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
-    unsigned short type, uint32_t data)
-{
-       unsigned short len = RTA_LENGTH(sizeof(data));
-       struct rtattr *subrta;
-
-       if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
-               errno = ENOBUFS;
-               return -1;
-       }
-
-       subrta = (struct rtattr*)(void *)
-           (((char*)rta) + RTA_ALIGN(rta->rta_len));
-       subrta->rta_type = type;
-       subrta->rta_len = len;
-       memcpy(RTA_DATA(subrta), &data, sizeof(data));
-       rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
-       return 0;
-}
-
 int
 if_route6(unsigned char cmd, const struct rt6 *rt)
 {
@@ -1565,7 +1576,7 @@ if_route6(unsigned char cmd, const struct rt6 *rt)
                        add_attr_32(&nlm.hdr, sizeof(nlm),
                            RTA_PRIORITY, rt->metric);
        }
-       if (cmd == RTM_ADD && rt->mtu) {
+       if (cmd != RTM_DELETE && rt->mtu) {
                char metricsbuf[32];
                struct rtattr *metrics = (void *)metricsbuf;
 
diff --git a/ipv4.c b/ipv4.c
index 462585cbf9f9f76b7c443d382ee954c55a470037..022c0e7845a84717333d84544fe48d264e2ad9c2 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -385,6 +385,7 @@ ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, struct rt *rt)
 static int
 nc_route(struct rt *ort, struct rt *nrt)
 {
+       int change;
 
        /* Don't set default routes if not asked to */
        if (nrt->dest.s_addr == 0 &&
@@ -394,6 +395,7 @@ nc_route(struct rt *ort, struct rt *nrt)
 
        desc_route(ort == NULL ? "adding" : "changing", nrt);
 
+       change = 0;
        if (ort == NULL) {
                ort = ipv4_findrt(nrt->iface->ctx, nrt, 0);
                if (ort &&
@@ -403,8 +405,12 @@ nc_route(struct rt *ort, struct rt *nrt)
                    ort->metric == nrt->metric &&
 #endif
                    ort->gate.s_addr == nrt->gate.s_addr)))
-                       return 0;
-       } else if (ort->flags & STATE_FAKE && !(nrt->flags & STATE_FAKE) &&
+               {
+                       if (ort->mtu == nrt->mtu)
+                               return 0;
+                       change = 1;
+               }
+       } else if (ort->state & STATE_FAKE && !(nrt->state & STATE_FAKE) &&
            ort->iface == nrt->iface &&
 #ifdef HAVE_ROUTE_METRIC
            ort->metric == nrt->metric &&
@@ -412,7 +418,27 @@ nc_route(struct rt *ort, struct rt *nrt)
            ort->dest.s_addr == nrt->dest.s_addr &&
            ort->net.s_addr ==  nrt->net.s_addr &&
            ort->gate.s_addr == nrt->gate.s_addr)
-               return 0;
+       {
+               if (ort->mtu == nrt->mtu)
+                       return 0;
+               change = 1;
+       }
+
+#ifdef RTF_CLONING
+       /* BSD can set routes to be cloning routes.
+        * Cloned routes inherit the parent flags.
+        * As such, we need to delete and re-add the route to flush children
+        * to correct the flags. */
+       if (change && ort != NULL && ort->flags & RTF_CLONING)
+               change = 0;
+#endif
+
+       if (change) {
+               if (if_route(RTM_CHANGE, nrt) == 0)
+                       return 0;
+               if (errno != ESRCH)
+                       logger(nrt->iface->ctx, LOG_ERR, "if_route (CHG): %m");
+       }
 
 #ifdef HAVE_ROUTE_METRIC
        /* With route metrics, we can safely add the new route before
@@ -474,7 +500,7 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
                return rt;
 #endif
 
-       if ((r = malloc(sizeof(*r))) == NULL) {
+       if ((r = calloc(1, sizeof(*r))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                ipv4_freeroutes(rt);
                return NULL;
@@ -482,6 +508,7 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
        r->dest.s_addr = s->addr.s_addr & s->net.s_addr;
        r->net.s_addr = s->net.s_addr;
        r->gate.s_addr = INADDR_ANY;
+       r->mtu = dhcp_get_mtu(ifp);
        r->src = s->addr;
 
        TAILQ_INSERT_HEAD(rt, r, next);
@@ -502,8 +529,7 @@ add_loopback_route(struct rt_head *rt, const struct interface *ifp)
        if (s->addr.s_addr == INADDR_ANY)
                return rt;
 
-       r = malloc(sizeof(*r));
-       if (r == NULL) {
+       if ((r = calloc(1, sizeof(*r))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                ipv4_freeroutes(rt);
                return NULL;
@@ -511,6 +537,7 @@ add_loopback_route(struct rt_head *rt, const struct interface *ifp)
        r->dest = s->addr;
        r->net.s_addr = INADDR_BROADCAST;
        r->gate.s_addr = htonl(INADDR_LOOPBACK);
+       r->mtu = dhcp_get_mtu(ifp);
        r->src = s->addr;
        TAILQ_INSERT_HEAD(rt, r, next);
        return rt;
@@ -531,8 +558,7 @@ get_routes(struct interface *ifp)
                TAILQ_FOREACH(rt, ifp->options->routes, next) {
                        if (rt->gate.s_addr == 0)
                                break;
-                       r = malloc(sizeof(*r));
-                       if (r == NULL) {
+                       if ((r = calloc(1, sizeof(*r))) == NULL) {
                                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                                ipv4_freeroutes(nrt);
                                return NULL;
@@ -541,7 +567,7 @@ get_routes(struct interface *ifp)
                        TAILQ_INSERT_TAIL(nrt, r, next);
                }
        } else
-               nrt = get_option_routes(ifp, D_STATE(ifp)->new);
+               nrt = dhcp_get_routes(ifp);
 
        /* Copy our address as the source address */
        if (nrt) {
@@ -566,8 +592,7 @@ add_destination_route(struct rt_head *rt, const struct interface *ifp)
            (state = D_CSTATE(ifp)) == NULL)
                return rt;
 
-       r = malloc(sizeof(*r));
-       if (r == NULL) {
+       if ((r = calloc(1, sizeof(*r))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                ipv4_freeroutes(rt);
                return NULL;
@@ -575,6 +600,8 @@ add_destination_route(struct rt_head *rt, const struct interface *ifp)
        r->dest.s_addr = INADDR_ANY;
        r->net.s_addr = INADDR_ANY;
        r->gate.s_addr = state->dst.s_addr;
+       r->mtu = dhcp_get_mtu(ifp);
+       r->src = state->addr;
        TAILQ_INSERT_HEAD(rt, r, next);
        return rt;
 }
@@ -639,8 +666,7 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
                            "%s: router %s requires a host route",
                            ifp->name, inet_ntoa(rtp->gate));
                }
-               rtn = malloc(sizeof(*rtn));
-               if (rtn == NULL) {
+               if ((rtn = calloc(1, sizeof(*rtn))) == NULL) {
                        logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
                        ipv4_freeroutes(rt);
                        return NULL;
@@ -648,6 +674,8 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
                rtn->dest.s_addr = rtp->gate.s_addr;
                rtn->net.s_addr = htonl(INADDR_BROADCAST);
                rtn->gate.s_addr = htonl(INADDR_ANY);
+               rtn->mtu = dhcp_get_mtu(ifp);
+               rtn->src = state->addr;
                TAILQ_INSERT_BEFORE(rtp, rtn, next);
        }
        return rt;
@@ -660,10 +688,10 @@ ipv4_doroute(struct rt *rt, struct rt_head *nrs)
        struct rt *or;
 
        state = D_CSTATE(rt->iface);
+       rt->state = state->added & STATE_FAKE;
 #ifdef HAVE_ROUTE_METRIC
        rt->metric = rt->iface->metric;
 #endif
-       rt->flags = state->added & STATE_FAKE;
        /* Is this route already in our table? */
        if ((find_route(nrs, rt, NULL)) != NULL)
                return 0;
@@ -671,13 +699,14 @@ ipv4_doroute(struct rt *rt, struct rt_head *nrs)
        if ((or = find_route(rt->iface->ctx->ipv4_routes, rt, NULL))) {
                if (state->added & STATE_FAKE)
                        return 0;
-               if (or->flags & STATE_FAKE ||
+               if (or->state & STATE_FAKE ||
                    or->iface != rt->iface ||
 #ifdef HAVE_ROUTE_METRIC
                    rt->metric != or->metric ||
 #endif
                    rt->src.s_addr != or->src.s_addr ||
-                   rt->gate.s_addr != or->gate.s_addr)
+                   rt->gate.s_addr != or->gate.s_addr ||
+                   rt->mtu != or->mtu)
                {
                        if (c_route(or, rt) != 0)
                                return 0;
@@ -686,16 +715,20 @@ ipv4_doroute(struct rt *rt, struct rt_head *nrs)
                free(or);
        } else {
                if (state->added & STATE_FAKE) {
-                       or = ipv4_findrt(rt->iface->ctx, rt, 1);
-                       if (or == NULL ||
-                           or->gate.s_addr != rt->gate.s_addr)
+                       if ((or = ipv4_findrt(rt->iface->ctx, rt, 1)) == NULL)
                                return 0;
+                       rt->iface = or->iface;
+                       rt->gate.s_addr = or->gate.s_addr;
+#ifdef HAVE_ROUTE_METRIC
+                       rt->metric = or->metric;
+#endif
+                       rt->mtu = or->mtu;
+                       rt->flags = or->flags;
                } else {
                        if (n_route(rt) != 0)
                                return 0;
                }
        }
-       rt->flags |= STATE_ADDED;
        return 1;
 }
 
diff --git a/ipv4.h b/ipv4.h
index 53f94e1c20338e826e725dfe11b28b03cfe4e2d9..913aa46d3340ecbdc926d0c04d8dd551ee89ebf9 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -61,8 +61,10 @@ struct rt {
 #ifdef HAVE_ROUTE_METRIC
        unsigned int metric;
 #endif
+       unsigned int mtu;
        struct in_addr src;
        unsigned int flags;
+       unsigned int state;
 };
 TAILQ_HEAD(rt_head, rt);
 
index 564f98f4d529151bdaf89ed0a889f27fdfa93dbb..4815df4bb6ebc059f21939026872e38a9601c698 100644 (file)
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -87,7 +87,7 @@ ipv4ll_subnet_route(const struct interface *ifp)
            state->addr.s_addr == INADDR_ANY)
                return NULL;
 
-       if ((rt = malloc(sizeof(*rt))) == NULL) {
+       if ((rt = calloc(1, sizeof(*rt))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
                return NULL;
        }
@@ -110,7 +110,7 @@ ipv4ll_default_route(const struct interface *ifp)
            state->addr.s_addr == INADDR_ANY)
                return NULL;
 
-       if ((rt = malloc(sizeof(*rt))) == NULL) {
+       if ((rt = calloc(1, sizeof(*rt))) == NULL) {
                logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
                return NULL;
        }