Hi,

> I think we should not allow at all empty source addresses, as it can
> make things confusing when troubleshooting. goda@ yasuoka@ reyk@ :
> what is your take on this ?

I have the same opinion of you.  Since tunneling protocol like vxlan
(or etherip) is used with statically assigned IP address I don't see
any reason to omit specifying the source address.

--yasuoka

On Thu, 1 Dec 2016 08:35:34 +0100
Vincent Gross <vgr...@openbsd.org> wrote:
> On Tue, 29 Nov 2016 17:03:44 +0100
> Martin Pieuchot <m...@openbsd.org> wrote:
> 
>> Diff below removes the 'struct route_in6' argument from
>> in6_selectsrc().
>> 
>> It is only used by in6_pcbselsrc() so move the code there.  This
>> reduces differences with IPv4 and help me to get rid of 'struct
>> route*'.
>> 
>> ok?
> 
> Reads ok, not tested yet.
> 
> Your diff is interesting in that is helped me to find a bug
> in vxlan(4).
> 
> Build a tunnel like this:
> $ doas ifconfig pair11 rdomain 11
> $ doas ifconfig pair12 rdomain 12 patch pair11
> $ doas ifconfig pair11 inet6 fd03::11/64 up
> $ doas ifconfig pair12 inet6 fd03::12/64 up
> $ doas ifconfig vxlan11 rdomain 11 tunneldomain 11 vnetid 10
> $ doas ifconfig vxlan12 rdomain 12 tunneldomain 12 vnetid 10
> $ doas ifconfig vxlan11 inet6 fd06::11/64 tunnel :: fd03::12 up
> $ doas ifconfig vxlan12 inet6 fd06::12/64 tunnel :: fd03::11 up
> 
> Watch ping6 fail:
> $ ping6 -V 11 fd06::12
> 
> Tweak the vxlans and see pings flow
> $ doas ifconfig vxlan11 tunnel fd03::11 fd03::12
> $ doas ifconfig vxlan12 tunnel fd03::12 fd03::11
> $ ping6 -V 11 fd06::11
> 
> 
> I think we should not allow at all empty source addresses, as it can
> make things confusing when troubleshooting. goda@ yasuoka@ reyk@ :
> what is your take on this ?
> 
> 
>> 
>> Index: net/if_vxlan.c
>> ===================================================================
>> RCS file: /cvs/src/sys/net/if_vxlan.c,v
>> retrieving revision 1.52
>> diff -u -p -r1.52 if_vxlan.c
>> --- net/if_vxlan.c   29 Nov 2016 10:09:57 -0000      1.52
>> +++ net/if_vxlan.c   29 Nov 2016 15:52:41 -0000
>> @@ -768,7 +768,7 @@ vxlan_encap6(struct ifnet *ifp, struct m
>>              ip6->ip6_hlim = ip6_defhlim;
>>  
>>      if (IN6_IS_ADDR_UNSPECIFIED(&satosin6(src)->sin6_addr)) {
>> -            error = in6_selectsrc(&in6a, satosin6(dst), NULL,
>> NULL,
>> +            error = in6_selectsrc(&in6a, satosin6(dst), NULL,
>>                  sc->sc_rdomain);
>>              if (error != 0) {
>>                      m_freem(m);
>> Index: netinet6/in6_src.c
>> ===================================================================
>> RCS file: /cvs/src/sys/netinet6/in6_src.c,v
>> retrieving revision 1.80
>> diff -u -p -r1.80 in6_src.c
>> --- netinet6/in6_src.c       2 Sep 2016 13:53:44 -0000       1.80
>> +++ netinet6/in6_src.c       29 Nov 2016 15:56:56 -0000
>> @@ -99,7 +99,6 @@ in6_pcbselsrc(struct in6_addr **in6src, 
>>      struct route_in6 *ro = &inp->inp_route6;
>>      struct in6_addr *laddr = &inp->inp_laddr6;
>>      u_int rtableid = inp->inp_rtableid;
>> -
>>      struct ifnet *ifp = NULL;
>>      struct in6_addr *dst;
>>      struct in6_ifaddr *ia6 = NULL;
>> @@ -172,7 +171,55 @@ in6_pcbselsrc(struct in6_addr **in6src, 
>>              return (0);
>>      }
>>  
>> -    return in6_selectsrc(in6src, dstsock, mopts, ro, rtableid);
>> +    error = in6_selectsrc(in6src, dstsock, mopts, rtableid);
>> +    if (error != EADDRNOTAVAIL)
>> +            return (error);
>> +
>> +    /*
>> +     * If route is known or can be allocated now,
>> +     * our src addr is taken from the i/f, else punt.
>> +     */
>> +    if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid != rtableid) ||
>> +        !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst)) {
>> +            rtfree(ro->ro_rt);
>> +            ro->ro_rt = NULL;
>> +    }
>> +    if (ro->ro_rt == NULL) {
>> +            struct sockaddr_in6 *sa6;
>> +
>> +            /* No route yet, so try to acquire one */
>> +            bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
>> +            ro->ro_tableid = rtableid;
>> +            sa6 = &ro->ro_dst;
>> +            sa6->sin6_family = AF_INET6;
>> +            sa6->sin6_len = sizeof(struct sockaddr_in6);
>> +            sa6->sin6_addr = *dst;
>> +            sa6->sin6_scope_id = dstsock->sin6_scope_id;
>> +            ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst),
>> +                RT_RESOLVE, ro->ro_tableid);
>> +    }
>> +
>> +    /*
>> +     * in_pcbconnect() checks out IFF_LOOPBACK to skip using
>> +     * the address. But we don't know why it does so.
>> +     * It is necessary to ensure the scope even for lo0
>> +     * so doesn't check out IFF_LOOPBACK.
>> +     */
>> +
>> +    if (ro->ro_rt) {
>> +            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);
>> +    }
>> +    if (ia6 == NULL)
>> +            return (EHOSTUNREACH);  /* no route */
>> +
>> +    *in6src = &ia6->ia_addr.sin6_addr;
>> +    return (0);
>>  }
>>  
>>  /*
>> @@ -183,7 +230,7 @@ in6_pcbselsrc(struct in6_addr **in6src, 
>>   */
>>  int
>>  in6_selectsrc(struct in6_addr **in6src, struct sockaddr_in6 *dstsock,
>> -    struct ip6_moptions *mopts, struct route_in6 *ro, u_int rtableid)
>> +    struct ip6_moptions *mopts, unsigned int rtableid)
>>  {
>>      struct ifnet *ifp = NULL;
>>      struct in6_addr *dst;
>> @@ -239,54 +286,6 @@ in6_selectsrc(struct in6_addr **in6src, 
>>                      *in6src = &ia6->ia_addr.sin6_addr;
>>                      return (0);
>>              }
>> -    }
>> -
>> -    /*
>> -     * If route is known or can be allocated now,
>> -     * our src addr is taken from the i/f, else punt.
>> -     */
>> -    if (ro) {
>> -            if (!rtisvalid(ro->ro_rt) || (ro->ro_tableid !=
>> rtableid) ||
>> -                !IN6_ARE_ADDR_EQUAL(&ro->ro_dst.sin6_addr, dst))
>> {
>> -                    rtfree(ro->ro_rt);
>> -                    ro->ro_rt = NULL;
>> -            }
>> -            if (ro->ro_rt == NULL) {
>> -                    struct sockaddr_in6 *sa6;
>> -
>> -                    /* No route yet, so try to acquire one */
>> -                    bzero(&ro->ro_dst, sizeof(struct
>> sockaddr_in6));
>> -                    ro->ro_tableid = rtableid;
>> -                    sa6 = &ro->ro_dst;
>> -                    sa6->sin6_family = AF_INET6;
>> -                    sa6->sin6_len = sizeof(struct sockaddr_in6);
>> -                    sa6->sin6_addr = *dst;
>> -                    sa6->sin6_scope_id = dstsock->sin6_scope_id;
>> -                    ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst),
>> -                        RT_RESOLVE, ro->ro_tableid);
>> -            }
>> -
>> -            /*
>> -             * in_pcbconnect() checks out IFF_LOOPBACK to skip
>> using
>> -             * the address. But we don't know why it does so.
>> -             * It is necessary to ensure the scope even for lo0
>> -             * so doesn't check out IFF_LOOPBACK.
>> -             */
>> -
>> -            if (ro->ro_rt) {
>> -                    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);
>> -            }
>> -            if (ia6 == NULL)
>> -                    return (EHOSTUNREACH);  /* no route */
>> -
>> -            *in6src = &ia6->ia_addr.sin6_addr;
>> -            return (0);
>>      }
>>  
>>      return (EADDRNOTAVAIL);
>> Index: netinet6/ip6_var.h
>> ===================================================================
>> RCS file: /cvs/src/sys/netinet6/ip6_var.h,v
>> retrieving revision 1.64
>> diff -u -p -r1.64 ip6_var.h
>> --- netinet6/ip6_var.h       24 Aug 2016 09:41:12 -0000      1.64
>> +++ netinet6/ip6_var.h       29 Nov 2016 15:58:04 -0000
>> @@ -297,7 +297,7 @@ int      none_input(struct mbuf **, int *, in
>>  int in6_pcbselsrc(struct in6_addr **, struct sockaddr_in6 *,
>>          struct inpcb *, struct ip6_pktopts *);
>>  int in6_selectsrc(struct in6_addr **, struct sockaddr_in6 *,
>> -        struct ip6_moptions *, struct route_in6 *, u_int);
>> +        struct ip6_moptions *, unsigned int);
>>  struct rtentry *in6_selectroute(struct sockaddr_in6 *, struct
>> ip6_pktopts *, struct route_in6 *, unsigned int rtableid);
>>  
> 

Reply via email to