If the kernel fails to clone an entry, report rtrequest(9) error.
authormpi <mpi@openbsd.org>
Sat, 10 Feb 2018 09:17:56 +0000 (09:17 +0000)
committermpi <mpi@openbsd.org>
Sat, 10 Feb 2018 09:17:56 +0000 (09:17 +0000)
ok claudio@, jmatthew@

sys/net/route.c

index cd02de7..acd6c1d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: route.c,v 1.370 2018/02/08 13:50:48 mpi Exp $ */
+/*     $OpenBSD: route.c,v 1.371 2018/02/10 09:17:56 mpi Exp $ */
 /*     $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $      */
 
 /*
@@ -159,7 +159,7 @@ int rtflushclone1(struct rtentry *, void *, u_int);
 void   rtflushclone(unsigned int, struct rtentry *);
 int    rt_ifa_purge_walker(struct rtentry *, void *, unsigned int);
 struct rtentry *rt_match(struct sockaddr *, uint32_t *, int, unsigned int);
-struct rtentry *rt_clone(struct rtentry *, struct sockaddr *, unsigned int);
+int    rt_clone(struct rtentry **, struct sockaddr *, unsigned int);
 struct sockaddr *rt_plentosa(sa_family_t, int, struct sockaddr_in6 *);
 
 #ifdef DDB
@@ -238,21 +238,19 @@ rt_match(struct sockaddr *dst, uint32_t *src, int flags, unsigned int tableid)
        }
 
        if (ISSET(rt->rt_flags, RTF_CLONING) && ISSET(flags, RT_RESOLVE))
-               rt = rt_clone(rt, dst, tableid);
+               rt_clone(&rt, dst, tableid);
 
        rt->rt_use++;
        return (rt);
 }
 
-struct rtentry *
-rt_clone(struct rtentry *rt, struct sockaddr *dst, unsigned int rtableid)
+int
+rt_clone(struct rtentry **rtp, struct sockaddr *dst, unsigned int rtableid)
 {
        struct rt_addrinfo       info;
-       struct rtentry          *rt0;
+       struct rtentry          *rt = *rtp;
        int                      error = 0;
 
-       rt0 = rt;
-
        memset(&info, 0, sizeof(info));
        info.rti_info[RTAX_DST] = dst;
 
@@ -271,10 +269,11 @@ rt_clone(struct rtentry *rt, struct sockaddr *dst, unsigned int rtableid)
        } else {
                /* Inform listeners of the new route */
                rtm_send(rt, RTM_ADD, 0, rtableid);
-               rtfree(rt0);
+               rtfree(*rtp);
+               *rtp = rt;
        }
        KERNEL_UNLOCK();
-       return (rt);
+       return (error);
 }
 
 /*
@@ -381,6 +380,7 @@ rt_setgwroute(struct rtentry *rt, u_int rtableid)
 {
        struct rtentry *prt, *nhrt;
        unsigned int rdomain = rtable_l2(rtableid);
+       int error;
 
        NET_ASSERT_LOCKED();
 
@@ -423,7 +423,12 @@ rt_setgwroute(struct rtentry *rt, u_int rtableid)
                        return (EHOSTUNREACH);
                }
 
-               nhrt = rt_clone(prt, rt->rt_gateway, rtable_l2(rtableid));
+               error = rt_clone(&prt, rt->rt_gateway, rdomain);
+               if (error) {
+                       rtfree(prt);
+                       return (error);
+               }
+               nhrt = prt;
        }
 
        /*