compromise fixes for duped keys
[unix-history] / usr / src / sys / net / rtsock.c
index d8d15b4..60edf79 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)rtsock.c    8.2 (Berkeley) %G%
+ *     @(#)rtsock.c    8.4 (Berkeley) %G%
  */
 
 #include <sys/param.h>
  */
 
 #include <sys/param.h>
@@ -54,6 +54,7 @@ route_usrreq(so, req, m, nam, control)
        register int error = 0;
        register struct rawcb *rp = sotorawcb(so);
        int s;
        register int error = 0;
        register struct rawcb *rp = sotorawcb(so);
        int s;
+
        if (req == PRU_ATTACH) {
                MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
                if (so->so_pcb = (caddr_t)rp)
        if (req == PRU_ATTACH) {
                MALLOC(rp, struct rawcb *, sizeof(*rp), M_PCB, M_WAITOK);
                if (so->so_pcb = (caddr_t)rp)
@@ -104,6 +105,8 @@ route_output(m, so)
        register struct rt_msghdr *rtm = 0;
        register struct rtentry *rt = 0;
        struct rtentry *saved_nrt = 0;
        register struct rt_msghdr *rtm = 0;
        register struct rtentry *rt = 0;
        struct rtentry *saved_nrt = 0;
+       struct radix_node_head *rnh;
+       struct radix_node_head *rnh;
        struct rt_addrinfo info;
        int len, error = 0;
        struct ifnet *ifp = 0;
        struct rt_addrinfo info;
        int len, error = 0;
        struct ifnet *ifp = 0;
@@ -138,7 +141,7 @@ route_output(m, so)
                senderr(EINVAL);
        if (genmask) {
                struct radix_node *t;
                senderr(EINVAL);
        if (genmask) {
                struct radix_node *t;
-               t = rn_addmask((caddr_t)genmask, 1, 2);
+               t = rn_addmask((caddr_t)genmask, 0, 1);
                if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
                        genmask = (struct sockaddr *)(t->rn_key);
                else
                if (t && Bcmp(genmask, t->rn_key, *(u_char *)genmask) == 0)
                        genmask = (struct sockaddr *)(t->rn_key);
                else
@@ -161,34 +164,28 @@ route_output(m, so)
 
        case RTM_DELETE:
                error = rtrequest(RTM_DELETE, dst, gate, netmask,
 
        case RTM_DELETE:
                error = rtrequest(RTM_DELETE, dst, gate, netmask,
-                               rtm->rtm_flags, (struct rtentry **)0);
+                               rtm->rtm_flags, &saved_nrt);
+               if (error == 0) {
+                       if ((rt = saved_nrt)->rt_refcnt <= 0)
+                               rt->rt_refcnt++;
+                       goto report;
+               }
                break;
 
        case RTM_GET:
        case RTM_CHANGE:
        case RTM_LOCK:
                break;
 
        case RTM_GET:
        case RTM_CHANGE:
        case RTM_LOCK:
-               rt = rtalloc1(dst, 0);
-               if (rt == 0)
+               if ((rnh = rt_tables[dst->sa_family]) == 0)
+                       senderr(EAFNOSUPPORT);
+               else if (rt = (struct rtentry *)
+                               rnh->rnh_lookup(dst, netmask, rnh))
+                       rt->rt_refcnt++;
+               else
                        senderr(ESRCH);
                        senderr(ESRCH);
-               if (rtm->rtm_type != RTM_GET) {/* XXX: too grotty */
-                       struct radix_node *rn;
-                       extern struct radix_node_head *mask_rnhead;
-
-                       if (Bcmp(dst, rt_key(rt), dst->sa_len) != 0)
-                               senderr(ESRCH);
-                       if (netmask && (rn = rn_search(netmask,
-                                           mask_rnhead->rnh_treetop)))
-                               netmask = (struct sockaddr *)rn->rn_key;
-                       for (rn = rt->rt_nodes; rn; rn = rn->rn_dupedkey)
-                               if (netmask == (struct sockaddr *)rn->rn_mask)
-                                       break;
-                       if (rn == 0)
-                               senderr(ETOOMANYREFS);
-                       rt = (struct rtentry *)rn;
-               }
                switch(rtm->rtm_type) {
 
                case RTM_GET:
                switch(rtm->rtm_type) {
 
                case RTM_GET:
+               report:
                        dst = rt_key(rt);
                        gate = rt->rt_gateway;
                        netmask = rt_mask(rt);
                        dst = rt_key(rt);
                        gate = rt->rt_gateway;
                        netmask = rt_mask(rt);
@@ -203,7 +200,7 @@ route_output(m, so)
                                        ifaaddr = 0;
                            }
                        }
                                        ifaaddr = 0;
                            }
                        }
-                       len = rt_msg2(RTM_GET, &info, (caddr_t)0,
+                       len = rt_msg2(rtm->rtm_type, &info, (caddr_t)0,
                                (struct walkarg *)0);
                        if (len > rtm->rtm_msglen) {
                                struct rt_msghdr *new_rtm;
                                (struct walkarg *)0);
                        if (len > rtm->rtm_msglen) {
                                struct rt_msghdr *new_rtm;
@@ -213,7 +210,7 @@ route_output(m, so)
                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
                                Free(rtm); rtm = new_rtm;
                        }
                                Bcopy(rtm, new_rtm, rtm->rtm_msglen);
                                Free(rtm); rtm = new_rtm;
                        }
-                       (void)rt_msg2(RTM_GET, &info, (caddr_t)rtm,
+                       (void)rt_msg2(rtm->rtm_type, &info, (caddr_t)rtm,
                                (struct walkarg *)0);
                        rtm->rtm_flags = rt->rt_flags;
                        rtm->rtm_rmx = rt->rt_rmx;
                                (struct walkarg *)0);
                        rtm->rtm_flags = rt->rt_flags;
                        rtm->rtm_rmx = rt->rt_rmx;
@@ -274,7 +271,6 @@ flush:
                else 
                        rtm->rtm_flags |= RTF_DONE;
        }
                else 
                        rtm->rtm_flags |= RTF_DONE;
        }
-cleanup:
        if (rt)
                rtfree(rt);
     {
        if (rt)
                rtfree(rt);
     {
@@ -535,7 +531,6 @@ rt_missmsg(type, rtinfo, flags, error)
 {
        register struct rt_msghdr *rtm;
        register struct mbuf *m;
 {
        register struct rt_msghdr *rtm;
        register struct mbuf *m;
-       register int i;
        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
 
        if (route_cb.any_count == 0)
        struct sockaddr *sa = rtinfo->rti_info[RTAX_DST];
 
        if (route_cb.any_count == 0)
@@ -649,9 +644,8 @@ sysctl_dumpentry(rn, w)
        struct radix_node *rn;
        register struct walkarg *w;
 {
        struct radix_node *rn;
        register struct walkarg *w;
 {
-       register struct sockaddr *sa;
        register struct rtentry *rt = (struct rtentry *)rn;
        register struct rtentry *rt = (struct rtentry *)rn;
-       int n, error = 0, size;
+       int error = 0, size;
        struct rt_addrinfo info;
 
        if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
        struct rt_addrinfo info;
 
        if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg))
@@ -687,7 +681,6 @@ sysctl_iflist(af, w)
        register struct ifnet *ifp;
        register struct ifaddr *ifa;
        struct  rt_addrinfo info;
        register struct ifnet *ifp;
        register struct ifaddr *ifa;
        struct  rt_addrinfo info;
-       struct  sockaddr *sa;
        int     len, error = 0;
 
        bzero((caddr_t)&info, sizeof(info));
        int     len, error = 0;
 
        bzero((caddr_t)&info, sizeof(info));