On 10/03/14(Mon) 15:28, Martin Pieuchot wrote:
> Diff below splits in_addprefix() into two functions, one for adding a
> route to host (for point-to-point interfaces) and one for adding a
> route prefix.
>
> This simplifies a lot the RTF_* flags logic and will make it easier
> to create routes to loopback in a near future. The only difference
> it introduces is that the (new) code to add a route to host no longer
> check for an associated carp interface to move the route from/to it.
>
> I'd also like to remove the magic to check if there's already a route
> to the same destination, but that'll be for another diff.
Did somebody at least *tried* this diff? Did somebody read it? Any ok?
> Index: netinet/in.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/netinet/in.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 in.c
> --- netinet/in.c 21 Jan 2014 10:18:26 -0000 1.91
> +++ netinet/in.c 10 Mar 2014 12:38:20 -0000
> @@ -94,8 +94,10 @@ int in_lifaddr_ioctl(struct socket *, u_
> struct ifnet *);
>
> void in_purgeaddr(struct ifaddr *);
> -int in_addprefix(struct in_ifaddr *, int);
> +int in_addprefix(struct in_ifaddr *);
> int in_scrubprefix(struct in_ifaddr *);
> +int in_addhost(struct in_ifaddr *);
> +int in_scrubhost(struct in_ifaddr *);
>
> /* Return 1 if an internet address is for a directly connected host */
> int
> @@ -608,7 +610,10 @@ in_lifaddr_ioctl(struct socket *so, u_lo
> void
> in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
> {
> - in_scrubprefix(ia);
> + if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
> + in_scrubprefix(ia);
> + else
> + in_scrubhost(ia);
> }
>
> /*
> @@ -621,7 +626,7 @@ in_ifinit(struct ifnet *ifp, struct in_i
> {
> u_int32_t i = sin->sin_addr.s_addr;
> struct sockaddr_in oldaddr;
> - int s = splnet(), flags = RTF_UP, error = 0;
> + int s = splnet(), error = 0;
>
> if (newaddr)
> TAILQ_INSERT_TAIL(&in_ifaddr, ia, ia_list);
> @@ -681,13 +686,15 @@ in_ifinit(struct ifnet *ifp, struct in_i
> }
> } else if (ifp->if_flags & IFF_LOOPBACK) {
> ia->ia_dstaddr = ia->ia_addr;
> - flags |= RTF_HOST;
> } else if (ifp->if_flags & IFF_POINTOPOINT) {
> if (ia->ia_dstaddr.sin_family != AF_INET)
> goto out;
> - flags |= RTF_HOST;
> }
> - error = in_addprefix(ia, flags);
> +
> + if ((ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0)
> + error = in_addprefix(ia);
> + else
> + error = in_addhost(ia);
>
> /*
> * If the interface supports multicast, join the "all hosts"
> @@ -739,51 +746,118 @@ in_purgeaddr(struct ifaddr *ifa)
> ifafree(&ia->ia_ifa);
> }
>
> -#define rtinitflags(x) \
> - ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
> - ? RTF_HOST : 0)
> +int
> +in_addhost(struct in_ifaddr *ia0)
> +{
> + struct in_ifaddr *ia;
> + struct in_addr dst;
> + int error;
> +
> + dst = ia0->ia_dstaddr.sin_addr;
> +
> + /*
> + * If an interface already have a route to the same
> + * destination don't do anything.
> + */
> + TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> + if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
> + continue;
> +
> + if (dst.s_addr != ia->ia_dstaddr.sin_addr.s_addr)
> + continue;
> +
> + if ((ia->ia_flags & IFA_ROUTE) == 0)
> + continue;
> +
> + return (0);
> + }
> +
> + error = rtinit(&ia0->ia_ifa, RTM_ADD, RTF_UP | RTF_HOST);
> + if (!error)
> + ia0->ia_flags |= IFA_ROUTE;
> +
> + return (error);
> +}
> +
> +int
> +in_scrubhost(struct in_ifaddr *ia0)
> +{
> + struct in_ifaddr *ia;
> + struct in_addr dst;
> + int error;
> +
> + if ((ia0->ia_flags & IFA_ROUTE) == 0)
> + return (0);
> +
> + dst = ia0->ia_dstaddr.sin_addr;
> +
> + /*
> + * Because we only add one route for a given destination at
> + * a time, here we need to do some magic to move this route
> + * to another interface if it has the same destination.
> + */
> + TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> + if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
> + continue;
> +
> + if (dst.s_addr != ia->ia_dstaddr.sin_addr.s_addr)
> + continue;
> +
> + if ((ia->ia_flags & IFA_ROUTE) != 0)
> + continue;
> +
> + rtinit(&ia0->ia_ifa, RTM_DELETE, RTF_HOST);
> + ia0->ia_flags &= ~IFA_ROUTE;
> + error = rtinit(&ia->ia_ifa, RTM_ADD, RTF_UP | RTF_HOST);
> + if (!error)
> + ia->ia_flags |= IFA_ROUTE;
> +
> + return (error);
> + }
> +
> + rtinit(&ia0->ia_ifa, RTM_DELETE, RTF_HOST);
> + ia0->ia_flags &= ~IFA_ROUTE;
> +
> + return (0);
> +}
>
> /*
> * add a route to prefix ("connected route" in cisco terminology).
> * does nothing if there's some interface address with the same prefix
> already.
> */
> int
> -in_addprefix(struct in_ifaddr *target, int flags)
> +in_addprefix(struct in_ifaddr *ia0)
> {
> struct in_ifaddr *ia;
> - struct in_addr prefix, mask, p;
> + struct in_addr prefix, mask, p, m;
> int error;
>
> - if ((flags & RTF_HOST) != 0)
> - prefix = target->ia_dstaddr.sin_addr;
> - else {
> - prefix = target->ia_addr.sin_addr;
> - mask = target->ia_sockmask.sin_addr;
> - prefix.s_addr &= mask.s_addr;
> - }
> + prefix = ia0->ia_addr.sin_addr;
> + mask = ia0->ia_sockmask.sin_addr;
> + prefix.s_addr &= mask.s_addr;
>
> TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> - if (ia->ia_ifp->if_rdomain != target->ia_ifp->if_rdomain)
> + if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
> continue;
> - if (rtinitflags(ia)) {
> - p = ia->ia_dstaddr.sin_addr;
> - if (prefix.s_addr != p.s_addr)
> - continue;
> - } else {
> - p = ia->ia_addr.sin_addr;
> - p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
> - if (prefix.s_addr != p.s_addr ||
> - mask.s_addr != ia->ia_sockmask.sin_addr.s_addr)
> - continue;
> - }
> +
> + if ((ia->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
> + continue;
> +
> if ((ia->ia_flags & IFA_ROUTE) == 0)
> continue;
> +
> + p = ia->ia_addr.sin_addr;
> + m = ia->ia_sockmask.sin_addr;
> + p.s_addr &= m.s_addr;
> +
> + if (prefix.s_addr != p.s_addr || mask.s_addr != m.s_addr)
> + continue;
> +
> #if NCARP > 0
> /* move to a real interface instead of carp interface */
> if (ia->ia_ifp->if_type == IFT_CARP &&
> - target->ia_ifp->if_type != IFT_CARP) {
> - rtinit(&(ia->ia_ifa), (int)RTM_DELETE,
> - rtinitflags(ia));
> + ia0->ia_ifp->if_type != IFT_CARP) {
> + rtinit(&ia->ia_ifa, RTM_DELETE, 0);
> ia->ia_flags &= ~IFA_ROUTE;
> break;
> }
> @@ -798,9 +872,9 @@ in_addprefix(struct in_ifaddr *target, i
> /*
> * noone seem to have prefix route. insert it.
> */
> - error = rtinit(&target->ia_ifa, (int)RTM_ADD, flags);
> + error = rtinit(&ia0->ia_ifa, RTM_ADD, RTF_UP);
> if (!error)
> - target->ia_flags |= IFA_ROUTE;
> + ia0->ia_flags |= IFA_ROUTE;
> return error;
> }
>
> @@ -810,64 +884,54 @@ in_addprefix(struct in_ifaddr *target, i
> * with the same prefix (otherwise we lose the route mistakenly).
> */
> int
> -in_scrubprefix(struct in_ifaddr *target)
> +in_scrubprefix(struct in_ifaddr *ia0)
> {
> struct in_ifaddr *ia;
> struct in_addr prefix, mask, p, m;
> int error;
>
> - if ((target->ia_flags & IFA_ROUTE) == 0)
> + if ((ia0->ia_flags & IFA_ROUTE) == 0)
> return 0;
>
> - if (rtinitflags(target)) {
> - prefix = target->ia_dstaddr.sin_addr;
> - mask.s_addr = INADDR_BROADCAST;
> - } else {
> - prefix = target->ia_addr.sin_addr;
> - mask = target->ia_sockmask.sin_addr;
> - prefix.s_addr &= mask.s_addr;
> - }
> + prefix = ia0->ia_addr.sin_addr;
> + mask = ia0->ia_sockmask.sin_addr;
> + prefix.s_addr &= mask.s_addr;
>
> TAILQ_FOREACH(ia, &in_ifaddr, ia_list) {
> - if (rtinitflags(ia)) {
> - p = ia->ia_dstaddr.sin_addr;
> - m.s_addr = INADDR_BROADCAST;
> - } else {
> - p = ia->ia_addr.sin_addr;
> - m = ia->ia_sockmask.sin_addr;
> - p.s_addr &= m.s_addr;
> - }
> + if (ia->ia_ifp->if_rdomain != ia0->ia_ifp->if_rdomain)
> + continue;
>
> - if (ia->ia_ifp->if_rdomain != target->ia_ifp->if_rdomain)
> + if ((ia->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
> continue;
> - if (prefix.s_addr != p.s_addr ||
> - mask.s_addr != m.s_addr)
> +
> + if ((ia->ia_flags & IFA_ROUTE) != 0)
> continue;
> +
> + p = ia->ia_addr.sin_addr;
> + m = ia->ia_sockmask.sin_addr;
> + p.s_addr &= m.s_addr;
> +
> + if (prefix.s_addr != p.s_addr || mask.s_addr != m.s_addr)
> + continue;
> +
> /*
> * if we got a matching prefix route, move IFA_ROUTE to him
> */
> - if ((ia->ia_flags & IFA_ROUTE) == 0) {
> - rtinit(&(target->ia_ifa), (int)RTM_DELETE,
> - rtinitflags(target));
> - target->ia_flags &= ~IFA_ROUTE;
> -
> - error = rtinit(&ia->ia_ifa, (int)RTM_ADD,
> - rtinitflags(ia) | RTF_UP);
> - if (error == 0)
> - ia->ia_flags |= IFA_ROUTE;
> - return error;
> - }
> + rtinit(&ia0->ia_ifa, RTM_DELETE, 0);
> + ia0->ia_flags &= ~IFA_ROUTE;
> + error = rtinit(&ia->ia_ifa, RTM_ADD, RTF_UP);
> + if (error == 0)
> + ia->ia_flags |= IFA_ROUTE;
> + return error;
> }
>
> /*
> * noone seem to have prefix route. remove it.
> */
> - rtinit(&(target->ia_ifa), (int)RTM_DELETE, rtinitflags(target));
> - target->ia_flags &= ~IFA_ROUTE;
> + rtinit(&ia0->ia_ifa, RTM_DELETE, 0);
> + ia0->ia_flags &= ~IFA_ROUTE;
> return 0;
> }
> -
> -#undef rtinitflags
>
> /*
> * Return 1 if the address might be a local broadcast address.
>