On 23/01/21(Sat) 21:59, Vitaliy Makkoveev wrote:
> Hello.
> 
> According the code `ifaddr’ struct has `ifa_refcnt’ field. Also it seems `ifa’
> could exist while corresponding `ifp’ was destroyed. Is this true for `rt’
> case? Should `ifa_refcnt' be bumped while you return `ifa’?

What is stored is a "struct rtentry".  This data structure is properly
refcounted in this diff.  When the last reference of `rt' is freed
ifafree() is called.  So there's no need to mess with `ifa' directly.


> > On 9 Jan 2021, at 20:50, Denis Fondras <[email protected]> wrote:
> > 
> > This diff place the user-set source address outside of struct art_root and 
> > make
> > the code more readable (to me).
> > 
> > Based on a concept by mpi@
> > 
> > Index: net/art.h
> > ===================================================================
> > RCS file: /cvs/src/sys/net/art.h,v
> > retrieving revision 1.20
> > diff -u -p -r1.20 art.h
> > --- net/art.h       12 Nov 2020 15:25:28 -0000      1.20
> > +++ net/art.h       9 Jan 2021 16:04:02 -0000
> > @@ -42,7 +42,6 @@ struct art_root {
> >     uint8_t                  ar_nlvl;       /* [I] Number of levels */
> >     uint8_t                  ar_alen;       /* [I] Address length in bits */
> >     uint8_t                  ar_off;        /* [I] Offset of key in bytes */
> > -   struct sockaddr         *source;        /* [K] optional src addr to use 
> > */
> > };
> > 
> > #define ISLEAF(e)   (((unsigned long)(e) & 1) == 0)
> > Index: net/route.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/route.c,v
> > retrieving revision 1.397
> > diff -u -p -r1.397 route.c
> > --- net/route.c     29 Oct 2020 21:15:27 -0000      1.397
> > +++ net/route.c     9 Jan 2021 16:04:02 -0000
> > @@ -1192,9 +1192,9 @@ rt_ifa_del(struct ifaddr *ifa, int flags
> >     if (flags & RTF_CONNECTED)
> >             prio = ifp->if_priority + RTP_CONNECTED;
> > 
> > -   rtable_clearsource(rdomain, ifa->ifa_addr);
> >     error = rtrequest_delete(&info, prio, ifp, &rt, rdomain);
> >     if (error == 0) {
> > +           rt_sourceclear(rt, rdomain);
> >             rtm_send(rt, RTM_DELETE, 0, rdomain);
> >             if (flags & RTF_LOCAL)
> >                     rtm_addr(RTM_DELADDR, ifa);
> > Index: net/route.h
> > ===================================================================
> > RCS file: /cvs/src/sys/net/route.h,v
> > retrieving revision 1.183
> > diff -u -p -r1.183 route.h
> > --- net/route.h     29 Oct 2020 21:15:27 -0000      1.183
> > +++ net/route.h     9 Jan 2021 16:04:02 -0000
> > @@ -478,6 +478,9 @@ int      rtrequest_delete(struct rt_addrinfo
> > int  rt_if_track(struct ifnet *);
> > int  rt_if_linkstate_change(struct rtentry *, void *, u_int);
> > int  rtdeletemsg(struct rtentry *, struct ifnet *, u_int);
> > +
> > +struct ifaddr      *rt_get_ifa(struct rtentry *, unsigned int);
> > +void                rt_sourceclear(struct rtentry *, unsigned int);
> > #endif /* _KERNEL */
> > 
> > #endif /* _NET_ROUTE_H_ */
> > Index: net/rtable.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/rtable.c,v
> > retrieving revision 1.72
> > diff -u -p -r1.72 rtable.c
> > --- net/rtable.c    7 Nov 2020 09:51:40 -0000       1.72
> > +++ net/rtable.c    9 Jan 2021 16:04:02 -0000
> > @@ -365,44 +365,6 @@ rtable_alloc(unsigned int rtableid, unsi
> >     return (art_alloc(rtableid, alen, off));
> > }
> > 
> > -int
> > -rtable_setsource(unsigned int rtableid, int af, struct sockaddr *src)
> > -{
> > -   struct art_root         *ar;
> > -
> > -   if ((ar = rtable_get(rtableid, af)) == NULL)
> > -           return (EAFNOSUPPORT);
> > -
> > -   ar->source = src;
> > -
> > -   return (0);
> > -}
> > -
> > -struct sockaddr *
> > -rtable_getsource(unsigned int rtableid, int af)
> > -{
> > -   struct art_root         *ar;
> > -
> > -   ar = rtable_get(rtableid, af);
> > -   if (ar == NULL)
> > -           return (NULL);
> > -
> > -   return (ar->source);
> > -}
> > -
> > -void
> > -rtable_clearsource(unsigned int rtableid, struct sockaddr *src)
> > -{
> > -   struct sockaddr *addr;
> > -
> > -   addr = rtable_getsource(rtableid, src->sa_family);
> > -   if (addr && (addr->sa_len == src->sa_len)) {
> > -           if (memcmp(src, addr, addr->sa_len) == 0) {
> > -                   rtable_setsource(rtableid, src->sa_family, NULL);
> > -           }
> > -   }
> > -}
> > -
> > struct rtentry *
> > rtable_lookup(unsigned int rtableid, struct sockaddr *dst,
> >     struct sockaddr *mask, struct sockaddr *gateway, uint8_t prio)
> > Index: net/rtable.h
> > ===================================================================
> > RCS file: /cvs/src/sys/net/rtable.h,v
> > retrieving revision 1.26
> > diff -u -p -r1.26 rtable.h
> > --- net/rtable.h    7 Nov 2020 09:51:40 -0000       1.26
> > +++ net/rtable.h    9 Jan 2021 16:04:02 -0000
> > @@ -39,9 +39,6 @@ unsigned int       rtable_l2(unsigned int);
> > unsigned int         rtable_loindex(unsigned int);
> > void                 rtable_l2set(unsigned int, unsigned int, unsigned int);
> > 
> > -int                 rtable_setsource(unsigned int, int, struct sockaddr *);
> > -struct sockaddr *rtable_getsource(unsigned int, int);
> > -void                rtable_clearsource(unsigned int, struct sockaddr *);
> > struct rtentry      *rtable_lookup(unsigned int, struct sockaddr *,
> >                  struct sockaddr *, struct sockaddr *, uint8_t);
> > struct rtentry      *rtable_match(unsigned int, struct sockaddr *, uint32_t 
> > *);
> > Index: net/rtsock.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/rtsock.c,v
> > retrieving revision 1.304
> > diff -u -p -r1.304 rtsock.c
> > --- net/rtsock.c    7 Nov 2020 09:51:40 -0000       1.304
> > +++ net/rtsock.c    9 Jan 2021 16:04:02 -0000
> > @@ -138,7 +138,8 @@ int              sysctl_iflist(int, struct walkarg 
> > int          sysctl_ifnames(struct walkarg *);
> > int          sysctl_rtable_rtstat(void *, size_t *, void *);
> > 
> > -int                 rt_setsource(unsigned int, struct sockaddr *);
> > +int                 rt_sourceset(struct rtentry *, unsigned int);
> > +struct rtentry     *rt_get_rt(int, unsigned int);
> > 
> > /*
> >  * Locks used to protect struct members
> > @@ -170,6 +171,14 @@ struct rtptable {
> > struct pool rtpcb_pool;
> > struct rtptable rtptable;
> > 
> > +struct rt_srcaddr {
> > +   LIST_ENTRY(rt_srcaddr)   rts_next;
> > +   unsigned int             rts_rtableid;
> > +   struct rtentry          *rts_rt;
> > +};
> > +
> > +LIST_HEAD(, rt_srcaddr)    srcaddr_h = LIST_HEAD_INITIALIZER(srcaddr_h);
> > +
> > /*
> >  * These flags and timeout are used for indicating to userland (via a
> >  * RTM_DESYNC msg) when the route socket has overflowed and messages
> > @@ -664,10 +673,7 @@ rtm_report(struct rtentry *rt, u_char ty
> >     ifp = if_get(rt->rt_ifidx);
> >     if (ifp != NULL) {
> >             info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
> > -           info.rti_info[RTAX_IFA] =
> > -               rtable_getsource(tableid, 
> > info.rti_info[RTAX_DST]->sa_family);
> > -           if (info.rti_info[RTAX_IFA] == NULL)
> > -                   info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
> > +           info.rti_info[RTAX_IFA] = rt_get_ifa(rt, tableid)->ifa_addr;
> >             if (ifp->if_flags & IFF_POINTOPOINT)
> >                     info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
> >     }
> > @@ -860,10 +866,28 @@ route_output(struct mbuf *m, struct sock
> >             if (info.rti_info[RTAX_IFA] == NULL) {
> >                     error = EINVAL;
> >                     goto fail;
> > +           } else if ((info.rti_info[RTAX_IFA]->sa_family == AF_INET6 &&
> > +               IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)
> > +               info.rti_info[RTAX_IFA])->sin6_addr)) ||
> > +               (info.rti_info[RTAX_IFA]->sa_family == AF_INET &&
> > +               ((struct sockaddr_in *)
> > +               info.rti_info[RTAX_IFA])->sin_addr.s_addr == 0)) {
> > +                   
> > rt_sourceclear(rt_get_rt(info.rti_info[RTAX_IFA]->sa_family,
> > +                       tableid), tableid);
> > +                   rtfree(rt);
> > +                   rt = NULL;
> > +           } else {
> > +                   rt = rtalloc(info.rti_info[RTAX_IFA], 0, tableid);
> > +                   if (rt == NULL || !ISSET(rt->rt_flags, RTF_LOCAL)) {
> > +                           error = EINVAL;
> > +                           goto fail;
> > +                   }
> > +                   NET_LOCK();
> > +                   error = rt_sourceset(rt, tableid);
> > +                   NET_UNLOCK();
> > +                   if (error != 0)
> > +                           goto fail;
> >             }
> > -           if ((error =
> > -               rt_setsource(tableid, info.rti_info[RTAX_IFA])) != 0)
> > -                   goto fail;
> >     } else {
> >             error = rtm_output(rtm, &rt, &info, prio, tableid);
> >             if (!error) {
> > @@ -873,9 +897,9 @@ route_output(struct mbuf *m, struct sock
> >                     rtm = rtm_report(rt, type, seq, tableid);
> >                     len = rtm->rtm_msglen;
> >             }
> > +           rtfree(rt);
> >     }
> > 
> > -   rtfree(rt);
> >     if (error) {
> >             rtm->rtm_errno = error;
> >     } else {
> > @@ -1687,10 +1711,7 @@ rtm_send(struct rtentry *rt, int cmd, in
> >     ifp = if_get(rt->rt_ifidx);
> >     if (ifp != NULL) {
> >             info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
> > -           info.rti_info[RTAX_IFA] =
> > -               rtable_getsource(rtableid, 
> > info.rti_info[RTAX_DST]->sa_family);
> > -           if (info.rti_info[RTAX_IFA] == NULL)
> > -                   info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
> > +           info.rti_info[RTAX_IFA] = rt_get_ifa(rt, rtableid)->ifa_addr;
> >     }
> > 
> >     rtm_miss(cmd, &info, rt->rt_flags, rt->rt_priority, rt->rt_ifidx, error,
> > @@ -1928,10 +1949,7 @@ sysctl_dumpentry(struct rtentry *rt, voi
> >     ifp = if_get(rt->rt_ifidx);
> >     if (ifp != NULL) {
> >             info.rti_info[RTAX_IFP] = sdltosa(ifp->if_sadl);
> > -           info.rti_info[RTAX_IFA] =
> > -               rtable_getsource(id, info.rti_info[RTAX_DST]->sa_family);
> > -           if (info.rti_info[RTAX_IFA] == NULL)
> > -                   info.rti_info[RTAX_IFA] = rt->rt_ifa->ifa_addr;
> > +           info.rti_info[RTAX_IFA] = rt_get_ifa(rt, id)->ifa_addr;
> >             if (ifp->if_flags & IFF_POINTOPOINT)
> >                     info.rti_info[RTAX_BRD] = rt->rt_ifa->ifa_dstaddr;
> >     }
> > @@ -2067,33 +2085,30 @@ sysctl_ifnames(struct walkarg *w)
> > }
> > 
> > int
> > -sysctl_source(int af, u_int tableid, struct walkarg *w)
> > +sysctl_source(int af, struct walkarg *w)
> > {
> > -   struct sockaddr *sa;
> > -   int              size, error = 0;
> > +   struct rt_srcaddr       *rtsa = NULL;
> > +   unsigned int             tableid = w->w_arg;
> > +   int                      error = 0;
> > 
> > -   sa = rtable_getsource(tableid, af);
> > -   if (sa) {
> > -           switch (sa->sa_family) {
> > -           case AF_INET:
> > -                   size = sizeof(struct sockaddr_in);
> > -                   break;
> > -#ifdef INET6
> > -           case AF_INET6:
> > -                   size = sizeof(struct sockaddr_in6);
> > -                   break;
> > -#endif
> > -           default:
> > -                   return (0);
> > -           }
> > -           w->w_needed += size;
> > +   LIST_FOREACH(rtsa, &srcaddr_h, rts_next) {
> > +           if (rtsa->rts_rtableid != tableid)
> > +                   continue;
> > +           if (af != 0 && rtsa->rts_rt->rt_dest->sa_family != af)
> > +                   continue;
> > +
> > +           w->w_needed += rtsa->rts_rt->rt_dest->sa_len;
> >             if (w->w_where && w->w_needed <= 0) {
> > -                   if ((error = copyout(sa, w->w_where, size)))
> > -                           return (error);
> > -                   w->w_where += size;
> > +                   error = copyout(rtsa->rts_rt->rt_ifa->ifa_addr,
> > +                       w->w_where, rtsa->rts_rt->rt_dest->sa_len);
> > +                   if (error == EAFNOSUPPORT)
> > +                           error = 0;
> > +                   if (error)
> > +                           break;
> > +                   w->w_where += rtsa->rts_rt->rt_dest->sa_len;
> >             }
> >     }
> > -   return (0);
> > +   return (error);
> > }
> > 
> > int
> > @@ -2171,16 +2186,7 @@ sysctl_rtable(int *name, u_int namelen, 
> >             if (!rtable_exists(tableid))
> >                     return (ENOENT);
> >             NET_LOCK();
> > -           for (i = 1; i <= AF_MAX; i++) {
> > -                   if (af != 0 && af != i)
> > -                           continue;
> > -
> > -                   error = sysctl_source(i, tableid, &w);
> > -                   if (error == EAFNOSUPPORT)
> > -                           error = 0;
> > -                   if (error)
> > -                           break;
> > -           }
> > +           error = sysctl_source(af, &w);
> >             NET_UNLOCK();
> >             break;
> >     }
> > @@ -2314,40 +2320,96 @@ rtm_validate_proposal(struct rt_addrinfo
> > }
> > 
> > int
> > -rt_setsource(unsigned int rtableid, struct sockaddr *src)
> > +rt_sourceset(struct rtentry *rt, unsigned int rtableid)
> > {
> > -   struct ifaddr   *ifa;
> > -   /*
> > -    * If source address is 0.0.0.0 or ::
> > -    * use automatic source selection
> > -    */
> > -   switch(src->sa_family) {
> > -   case AF_INET:
> > -           if(satosin(src)->sin_addr.s_addr == INADDR_ANY) {
> > -                   rtable_setsource(rtableid, AF_INET, NULL);
> > -                   return (0);
> > -           }
> > -           break;
> > -#ifdef INET6
> > -   case AF_INET6:
> > -           if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)) {
> > -                   rtable_setsource(rtableid, AF_INET6, NULL);
> > -                   return (0);
> > +   struct rt_srcaddr       *rtsa = NULL;
> > +
> > +   LIST_FOREACH(rtsa, &srcaddr_h, rts_next) {
> > +           if (rtsa->rts_rtableid == rtableid &&
> > +               rtsa->rts_rt->rt_dest->sa_family == rt->rt_dest->sa_family)
> > +                   break;
> > +   }
> > +   if (rtsa == NULL) {
> > +           if ((rtsa = malloc(sizeof(struct rt_srcaddr), M_IFADDR,
> > +               M_NOWAIT|M_ZERO)) == NULL)
> > +                   return (ENOMEM);
> > +           rtsa->rts_rtableid = rtableid;
> > +           rtsa->rts_rt = rt;
> > +           LIST_INSERT_HEAD(&srcaddr_h, rtsa, rts_next);
> > +   } else {
> > +           /* Update existing entry */
> > +           rtfree(rtsa->rts_rt);
> > +           rtsa->rts_rt = rt;
> > +   }
> > +
> > +   return (0);
> > +}
> > +
> > +/*
> > + * Return the 'ifa' associated to a given 'rt' unless a preferred
> > + * source address has been specified for the same routing table.
> > + */
> > +struct rtentry *
> > +rt_get_rt(int af, unsigned int rtableid)
> > +{
> > +   struct rt_srcaddr       *rtsa = NULL;
> > +
> > +   LIST_FOREACH(rtsa, &srcaddr_h, rts_next) {
> > +           if (rtsa->rts_rtableid == rtableid &&
> > +               rtsa->rts_rt->rt_dest->sa_family == af)
> > +                   break;
> > +   }
> > +   if (rtsa)
> > +           return (rtsa->rts_rt);
> > +
> > +   return (NULL);
> > +}
> > +
> > +struct ifaddr *
> > +rt_get_ifa(struct rtentry *rt, unsigned int rtableid)
> > +{
> > +   struct rt_srcaddr       *rtsa = NULL;
> > +   struct ifnet            *ifp = NULL;
> > +
> > +   if (ISSET(rt->rt_flags, RTF_HOST|RTF_LLINFO))
> > +           return (rt->rt_ifa);
> > +
> > +   LIST_FOREACH(rtsa, &srcaddr_h, rts_next) {
> > +           if (rtsa->rts_rtableid == rtableid &&
> > +               rtsa->rts_rt->rt_dest->sa_family == rt->rt_dest->sa_family)
> > +                   break;
> > +   }
> > +   if (rtsa != NULL && rtisvalid(rtsa->rts_rt)) {
> > +           struct rtentry  *nrt = rtsa->rts_rt;
> > +
> > +           ifp = if_get(nrt->rt_ifidx);
> > +           if (ifp != NULL) {
> > +                   if (ISSET(ifp->if_flags, IFF_UP)) {
> > +                           if_put(ifp);
> > +                           return (nrt->rt_ifa);
> > +                   }
> >             }
> > -           break;
> > -#endif
> > -   default:
> > -           return (EAFNOSUPPORT);
> >     }
> > +   return (rt->rt_ifa);
> > +}
> > 
> > -   /*
> > -    * Check if source address is assigned to an interface in the
> > -    * same rdomain
> > -    */
> > -   if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL)
> > -           return (EINVAL);
> > +void
> > +rt_sourceclear(struct rtentry *rt, unsigned int rtableid)
> > +{
> > +   struct rt_srcaddr       *rtsa = NULL;
> > 
> > -   return (rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr));
> > +   if (rt == NULL)
> > +           return;
> > +
> > +   LIST_FOREACH(rtsa, &srcaddr_h, rts_next) {
> > +           if (rtsa->rts_rtableid != rtableid)
> > +                   continue;
> > +           if (rtsa->rts_rt == rt) {
> > +                   LIST_REMOVE(rtsa, rts_next);
> > +                   free(rtsa, M_IFADDR, sizeof(struct rt_srcaddr));
> > +                   break;
> > +           }
> > +   }
> > }
> > 
> > /*
> > Index: netinet/in_pcb.c
> > ===================================================================
> > RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> > retrieving revision 1.252
> > diff -u -p -r1.252 in_pcb.c
> > --- netinet/in_pcb.c        7 Nov 2020 09:51:40 -0000       1.252
> > +++ netinet/in_pcb.c        9 Jan 2021 16:04:02 -0000
> > @@ -887,7 +887,6 @@ in_pcbselsrc(struct in_addr **insrc, str
> >     struct route *ro = &inp->inp_route;
> >     struct in_addr *laddr = &inp->inp_laddr;
> >     u_int rtableid = inp->inp_rtableid;
> > -   struct sockaddr *ip4_source = NULL;
> > 
> >     struct sockaddr_in *sin2;
> >     struct in_ifaddr *ia = NULL;
> > @@ -951,30 +950,11 @@ in_pcbselsrc(struct in_addr **insrc, str
> >     }
> > 
> >     /*
> > -    * If we found a route, use the address
> > -    * corresponding to the outgoing interface.
> > +    * If we found a route, use the address corresponding to the
> > +    * outgoing interface or the preferred source address if set.
> >      */
> >     if (ro->ro_rt != NULL)
> > -           ia = ifatoia(ro->ro_rt->rt_ifa);
> > -
> > -   /*
> > -    * Use preferred source address if :
> > -    * - destination is not onlink
> > -    * - preferred source addresss is set
> > -    * - output interface is UP
> > -    */
> > -   if (ro->ro_rt && !(ro->ro_rt->rt_flags & RTF_LLINFO) &&
> > -       !(ro->ro_rt->rt_flags & RTF_HOST)) {
> > -           ip4_source = rtable_getsource(rtableid, AF_INET);
> > -           if (ip4_source != NULL) {
> > -                   struct ifaddr *ifa;
> > -                   if ((ifa = ifa_ifwithaddr(ip4_source, rtableid)) !=
> > -                       NULL && ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) {
> > -                           *insrc = &satosin(ip4_source)->sin_addr;
> > -                           return (0);
> > -                   }
> > -           }
> > -   }
> > +           ia = ifatoia(rt_get_ifa(ro->ro_rt, rtableid));
> > 
> >     if (ia == NULL)
> >             return (EADDRNOTAVAIL);
> > Index: netinet/ip_icmp.c
> > ===================================================================
> > RCS file: /cvs/src/sys/netinet/ip_icmp.c,v
> > retrieving revision 1.184
> > diff -u -p -r1.184 ip_icmp.c
> > --- netinet/ip_icmp.c       20 Dec 2020 21:15:47 -0000      1.184
> > +++ netinet/ip_icmp.c       9 Jan 2021 16:04:02 -0000
> > @@ -745,7 +745,7 @@ icmp_reflect(struct mbuf *m, struct mbuf
> >                     return (EHOSTUNREACH);
> >             }
> > 
> > -           ia = ifatoia(rt->rt_ifa);
> > +           ia = ifatoia(rt_get_ifa(rt, rtableid));
> >     }
> > 
> >     ip->ip_dst = ip->ip_src;
> > Index: netinet6/icmp6.c
> > ===================================================================
> > RCS file: /cvs/src/sys/netinet6/icmp6.c,v
> > retrieving revision 1.233
> > diff -u -p -r1.233 icmp6.c
> > --- netinet6/icmp6.c        28 Oct 2020 17:27:35 -0000      1.233
> > +++ netinet6/icmp6.c        9 Jan 2021 16:04:02 -0000
> > @@ -1163,7 +1163,10 @@ icmp6_reflect(struct mbuf **mp, size_t o
> >                     rtfree(rt);
> >                     goto bad;
> >             }
> > -           ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t, rtableid);
> > +           ia6 = ifatoia6(rt_get_ifa(rt, rtableid));
> > +           if (ia6 == NULL)
> > +                   ia6 = in6_ifawithscope(rt->rt_ifa->ifa_ifp, &t,
> > +                       rtableid);
> >             if (ia6 != NULL)
> >                     src = &ia6->ia_addr.sin6_addr;
> >             if (src == NULL)
> > Index: netinet6/in6_src.c
> > ===================================================================
> > RCS file: /cvs/src/sys/netinet6/in6_src.c,v
> > retrieving revision 1.84
> > diff -u -p -r1.84 in6_src.c
> > --- netinet6/in6_src.c      7 Nov 2020 09:51:40 -0000       1.84
> > +++ netinet6/in6_src.c      9 Jan 2021 16:04:02 -0000
> > @@ -100,7 +100,6 @@ in6_pcbselsrc(struct in6_addr **in6src, 
> >     struct in6_addr *laddr = &inp->inp_laddr6;
> >     u_int rtableid = inp->inp_rtableid;
> >     struct ifnet *ifp = NULL;
> > -   struct sockaddr *ip6_source = NULL;
> >     struct in6_addr *dst;
> >     struct in6_ifaddr *ia6 = NULL;
> >     struct in6_pktinfo *pi = NULL;
> > @@ -208,32 +207,16 @@ in6_pcbselsrc(struct in6_addr **in6src, 
> >      */
> > 
> >     if (ro->ro_rt) {
> > -           ifp = if_get(ro->ro_rt->rt_ifidx);
> > -           if (ifp != NULL) {
> > -                   ia6 = in6_ifawithscope(ifp, dst, rtableid);
> > -                   if_put(ifp);
> > +           ia6 = ifatoia6(rt_get_ifa(ro->ro_rt, rtableid));
> > +           if (ia6 == NULL) {
> > +                   ifp = if_get(ro->ro_rt->rt_ifidx);
> > +                   if (ifp != NULL) {
> > +                           ia6 = in6_ifawithscope(ifp, dst, rtableid);
> > +                           if_put(ifp);
> > +                   }
> >             }
> >             if (ia6 == NULL) /* xxx scope error ?*/
> >                     ia6 = ifatoia6(ro->ro_rt->rt_ifa);
> > -   }
> > -
> > -   /*
> > -    * Use preferred source address if :
> > -    * - destination is not onlink
> > -    * - preferred source addresss is set
> > -    * - output interface is UP
> > -    */
> > -   if (ro->ro_rt && !(ro->ro_rt->rt_flags & RTF_LLINFO) &&
> > -       !(ro->ro_rt->rt_flags & RTF_HOST)) {
> > -           ip6_source = rtable_getsource(rtableid, AF_INET6);
> > -           if (ip6_source != NULL) {
> > -                   struct ifaddr *ifa;
> > -                   if ((ifa = ifa_ifwithaddr(ip6_source, rtableid)) !=
> > -                       NULL && ISSET(ifa->ifa_ifp->if_flags, IFF_UP)) {
> > -                           *in6src = &satosin6(ip6_source)->sin6_addr;
> > -                           return (0);
> > -                   }
> > -           }
> >     }
> > 
> >     if (ia6 == NULL)
> > 
> 

Reply via email to