Re: explicitly check broadcast addresses on some ifa_ifwithaddr() uses

2015-12-03 Thread Vincent Gross
On 12/02/15 20:06, Martin Pieuchot wrote:
> On 02/12/15(Wed) 16:18, Vincent Gross wrote:
>> When fed a broadcast address, ifa_ifwitaddr() returns the unicast ifa
>> whose broadcast address match the input. This is used mainly to select
>> ifa, and there can be trouble when you have 2 ifas on the same range
>> (e.g. 10.0.0.1/24@em0 & 10.0.0.20/24@em1) :
>>
>> netinet/ip_mroute.c:814
>> net/route.c:785
>> netinet/ip_divert.c:143
>> net/if_vxlan.c:241
>>
>> There are also places where broadcast addresses should not be tolerated :
>>
>> netinet/ip_input.c:1061  broadcast address is not a module identifier
>> netinet/ip_input.c:1141  see above
>> netinet/ip_input.c:1197  see above
>> netinet6/*:  no broadcast in ipv6
>> net/route.c:562: gateway shall never be a broadcast addr
>> net/route.c:713: see above
>>
>> This diff removes broadcast matching from ifa_ifwithaddr, and
>> adds or rewrites checks where necessary.
>>
>> Comments ? Ok ?
> 
> Looks good to me.  Some nits below.

Nits applied.

Anyone else ?


Index: sys/net/if.c
===
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.417
diff -u -p -r1.417 if.c
--- sys/net/if.c2 Dec 2015 16:35:52 -   1.417
+++ sys/net/if.c3 Dec 2015 07:59:53 -
@@ -1179,13 +1179,6 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
 
if (equal(addr, ifa->ifa_addr))
return (ifa);
-
-   /* IPv6 doesn't have broadcast */
-   if ((ifp->if_flags & IFF_BROADCAST) &&
-   ifa->ifa_broadaddr &&
-   ifa->ifa_broadaddr->sa_len != 0 &&
-   equal(ifa->ifa_broadaddr, addr))
-   return (ifa);
}
}
return (NULL);
Index: sys/netinet/in_pcb.c
===
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.190
diff -u -p -r1.190 in_pcb.c
--- sys/netinet/in_pcb.c2 Dec 2015 22:13:44 -   1.190
+++ sys/netinet/in_pcb.c3 Dec 2015 07:59:53 -
@@ -332,14 +332,13 @@ in_pcbbind(struct inpcb *inp, struct mbu
 
ia = ifatoia(ifa_ifwithaddr(sintosa(sin),
inp->inp_rtableid));
-   if (ia == NULL)
-   return (EADDRNOTAVAIL);
 
/* SOCK_RAW does not use in_pcbbind() */
-   if (so->so_type != SOCK_DGRAM &&
-   sin->sin_addr.s_addr !=
-   ia->ia_addr.sin_addr.s_addr)
-   return (EADDRNOTAVAIL);
+   if (ia == NULL &&
+   (so->so_type != SOCK_DGRAM ||
+   !in_broadcast(sin->sin_addr,
+   inp->inp_rtableid)))
+   return (EADDRNOTAVAIL);
}
}
if (lport) {
@@ -353,7 +352,8 @@ in_pcbbind(struct inpcb *inp, struct mbu
t = in_pcblookup(table, _addr, 0,
>sin_addr, lport, INPLOOKUP_WILDCARD,
inp->inp_rtableid);
-   if (t && (so->so_euid != 
t->inp_socket->so_euid))
+   if (t &&
+   (so->so_euid != t->inp_socket->so_euid))
return (EADDRINUSE);
}
t = in_pcblookup(table, _addr, 0,
Index: sys/netinet/ip_output.c
===
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.311
diff -u -p -r1.311 ip_output.c
--- sys/netinet/ip_output.c 2 Dec 2015 20:50:20 -   1.311
+++ sys/netinet/ip_output.c 3 Dec 2015 07:59:53 -
@@ -1368,13 +1368,12 @@ ip_setmoptions(int optname, struct ip_mo
sin.sin_family = AF_INET;
sin.sin_addr = addr;
ia = ifatoia(ifa_ifwithaddr(sintosa(), rtableid));
-   if (ia && in_hosteq(sin.sin_addr, ia->ia_addr.sin_addr))
-   ifp = ia->ia_ifp;
-   if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+   if (ia == NULL ||
+   (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) {
error = EADDRNOTAVAIL;
break;
}
-   imo->imo_ifidx = ifp->if_index;
+   imo->imo_ifidx = ia->ia_ifp->if_index;
break;
 
case IP_MULTICAST_TTL:
@@ -1542,12 +1541,11 @@ ip_setmoptions(int optname, struct ip_mo

Re: explicitly check broadcast addresses on some ifa_ifwithaddr() uses

2015-12-03 Thread Vincent Gross
On 12/03/15 10:21, Vincent Gross wrote:
> On 12/02/15 20:06, Martin Pieuchot wrote:
>> On 02/12/15(Wed) 16:18, Vincent Gross wrote:
>>> When fed a broadcast address, ifa_ifwitaddr() returns the unicast ifa
>>> whose broadcast address match the input. This is used mainly to select
>>> ifa, and there can be trouble when you have 2 ifas on the same range
>>> (e.g. 10.0.0.1/24@em0 & 10.0.0.20/24@em1) :
>>>
>>> netinet/ip_mroute.c:814
>>> net/route.c:785
>>> netinet/ip_divert.c:143
>>> net/if_vxlan.c:241
>>>
>>> There are also places where broadcast addresses should not be tolerated :
>>>
>>> netinet/ip_input.c:1061  broadcast address is not a module identifier
>>> netinet/ip_input.c:1141  see above
>>> netinet/ip_input.c:1197  see above
>>> netinet6/*:  no broadcast in ipv6
>>> net/route.c:562: gateway shall never be a broadcast addr
>>> net/route.c:713: see above
>>>
>>> This diff removes broadcast matching from ifa_ifwithaddr, and
>>> adds or rewrites checks where necessary.
>>>
>>> Comments ? Ok ?
>>
>> Looks good to me.  Some nits below.
> 
> Nits applied.
> 
> Anyone else ?

bluhm@ spotted one case where in_broadcast was needed.

ok ?

Index: sys/net/if.c
===
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.418
diff -u -p -r1.418 if.c
--- sys/net/if.c3 Dec 2015 12:22:51 -   1.418
+++ sys/net/if.c3 Dec 2015 13:48:58 -
@@ -1220,13 +1220,6 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
 
if (equal(addr, ifa->ifa_addr))
return (ifa);
-
-   /* IPv6 doesn't have broadcast */
-   if ((ifp->if_flags & IFF_BROADCAST) &&
-   ifa->ifa_broadaddr &&
-   ifa->ifa_broadaddr->sa_len != 0 &&
-   equal(ifa->ifa_broadaddr, addr))
-   return (ifa);
}
}
return (NULL);
Index: sys/net/route.c
===
RCS file: /cvs/src/sys/net/route.c,v
retrieving revision 1.283
diff -u -p -r1.283 route.c
--- sys/net/route.c 2 Dec 2015 16:49:58 -   1.283
+++ sys/net/route.c 3 Dec 2015 13:49:00 -
@@ -539,7 +539,9 @@ rtredirect(struct sockaddr *dst, struct 
 bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
if (rt != NULL && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
error = EINVAL;
-   else if (ifa_ifwithaddr(gateway, rdomain) != NULL)
+   else if (ifa_ifwithaddr(gateway, rdomain) != NULL ||
+   (gateway->sa_family = AF_INET &&
+   in_broadcast(satosin(gateway)->sin_addr, rdomain)))
error = EHOSTUNREACH;
if (error)
goto done;
Index: sys/netinet/in_pcb.c
===
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.191
diff -u -p -r1.191 in_pcb.c
--- sys/netinet/in_pcb.c3 Dec 2015 09:49:15 -   1.191
+++ sys/netinet/in_pcb.c3 Dec 2015 13:49:00 -
@@ -332,14 +332,13 @@ in_pcbbind(struct inpcb *inp, struct mbu
 
ia = ifatoia(ifa_ifwithaddr(sintosa(sin),
inp->inp_rtableid));
-   if (ia == NULL)
-   return (EADDRNOTAVAIL);
 
/* SOCK_RAW does not use in_pcbbind() */
-   if (so->so_type != SOCK_DGRAM &&
-   sin->sin_addr.s_addr !=
-   ia->ia_addr.sin_addr.s_addr)
-   return (EADDRNOTAVAIL);
+   if (ia == NULL &&
+   (so->so_type != SOCK_DGRAM ||
+   !in_broadcast(sin->sin_addr,
+   inp->inp_rtableid)))
+   return (EADDRNOTAVAIL);
}
}
if (lport) {
@@ -353,7 +352,8 @@ in_pcbbind(struct inpcb *inp, struct mbu
t = in_pcblookup(table, _addr, 0,
>sin_addr, lport, INPLOOKUP_WILDCARD,
inp->inp_rtableid);
-   if (t && (so->so_euid != 
t->inp_socket->so_euid))
+   if (t &&
+   (so->so_euid != t->inp_socket->so_euid))
return (EADDRINUSE);
}
t = in_pcblookup(table, _addr, 0,
Index: sys/netinet/ip_output.c
===
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.311
diff -u -p 

Re: explicitly check broadcast addresses on some ifa_ifwithaddr() uses

2015-12-03 Thread Alexander Bluhm
On Thu, Dec 03, 2015 at 02:52:59PM +0100, Vincent Gross wrote:
> bluhm@ spotted one case where in_broadcast was needed.
> 
> ok ?

OK bluhm@

> 
> Index: sys/net/if.c
> ===
> RCS file: /cvs/src/sys/net/if.c,v
> retrieving revision 1.418
> diff -u -p -r1.418 if.c
> --- sys/net/if.c  3 Dec 2015 12:22:51 -   1.418
> +++ sys/net/if.c  3 Dec 2015 13:48:58 -
> @@ -1220,13 +1220,6 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
>  
>   if (equal(addr, ifa->ifa_addr))
>   return (ifa);
> -
> - /* IPv6 doesn't have broadcast */
> - if ((ifp->if_flags & IFF_BROADCAST) &&
> - ifa->ifa_broadaddr &&
> - ifa->ifa_broadaddr->sa_len != 0 &&
> - equal(ifa->ifa_broadaddr, addr))
> - return (ifa);
>   }
>   }
>   return (NULL);
> Index: sys/net/route.c
> ===
> RCS file: /cvs/src/sys/net/route.c,v
> retrieving revision 1.283
> diff -u -p -r1.283 route.c
> --- sys/net/route.c   2 Dec 2015 16:49:58 -   1.283
> +++ sys/net/route.c   3 Dec 2015 13:49:00 -
> @@ -539,7 +539,9 @@ rtredirect(struct sockaddr *dst, struct 
>bcmp((caddr_t)(a1), (caddr_t)(a2), (a1)->sa_len) == 0)
>   if (rt != NULL && (!equal(src, rt->rt_gateway) || rt->rt_ifa != ifa))
>   error = EINVAL;
> - else if (ifa_ifwithaddr(gateway, rdomain) != NULL)
> + else if (ifa_ifwithaddr(gateway, rdomain) != NULL ||
> + (gateway->sa_family = AF_INET &&
> + in_broadcast(satosin(gateway)->sin_addr, rdomain)))
>   error = EHOSTUNREACH;
>   if (error)
>   goto done;
> Index: sys/netinet/in_pcb.c
> ===
> RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> retrieving revision 1.191
> diff -u -p -r1.191 in_pcb.c
> --- sys/netinet/in_pcb.c  3 Dec 2015 09:49:15 -   1.191
> +++ sys/netinet/in_pcb.c  3 Dec 2015 13:49:00 -
> @@ -332,14 +332,13 @@ in_pcbbind(struct inpcb *inp, struct mbu
>  
>   ia = ifatoia(ifa_ifwithaddr(sintosa(sin),
>   inp->inp_rtableid));
> - if (ia == NULL)
> - return (EADDRNOTAVAIL);
>  
>   /* SOCK_RAW does not use in_pcbbind() */
> - if (so->so_type != SOCK_DGRAM &&
> - sin->sin_addr.s_addr !=
> - ia->ia_addr.sin_addr.s_addr)
> - return (EADDRNOTAVAIL);
> + if (ia == NULL &&
> + (so->so_type != SOCK_DGRAM ||
> + !in_broadcast(sin->sin_addr,
> + inp->inp_rtableid)))
> + return (EADDRNOTAVAIL);
>   }
>   }
>   if (lport) {
> @@ -353,7 +352,8 @@ in_pcbbind(struct inpcb *inp, struct mbu
>   t = in_pcblookup(table, _addr, 0,
>   >sin_addr, lport, INPLOOKUP_WILDCARD,
>   inp->inp_rtableid);
> - if (t && (so->so_euid != 
> t->inp_socket->so_euid))
> + if (t &&
> + (so->so_euid != t->inp_socket->so_euid))
>   return (EADDRINUSE);
>   }
>   t = in_pcblookup(table, _addr, 0,
> Index: sys/netinet/ip_output.c
> ===
> RCS file: /cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.311
> diff -u -p -r1.311 ip_output.c
> --- sys/netinet/ip_output.c   2 Dec 2015 20:50:20 -   1.311
> +++ sys/netinet/ip_output.c   3 Dec 2015 13:49:01 -
> @@ -1368,13 +1368,12 @@ ip_setmoptions(int optname, struct ip_mo
>   sin.sin_family = AF_INET;
>   sin.sin_addr = addr;
>   ia = ifatoia(ifa_ifwithaddr(sintosa(), rtableid));
> - if (ia && in_hosteq(sin.sin_addr, ia->ia_addr.sin_addr))
> - ifp = ia->ia_ifp;
> - if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
> + if (ia == NULL ||
> + (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) {
>   error = EADDRNOTAVAIL;
>   break;
>   }
> - imo->imo_ifidx = ifp->if_index;
> + imo->imo_ifidx = ia->ia_ifp->if_index;
>   break;
>  
>   case IP_MULTICAST_TTL:
> @@ -1542,12 +1541,11 @@ ip_setmoptions(int optname, struct ip_mo
>

explicitly check broadcast addresses on some ifa_ifwithaddr() uses

2015-12-02 Thread Vincent Gross
When fed a broadcast address, ifa_ifwitaddr() returns the unicast ifa
whose broadcast address match the input. This is used mainly to select
ifa, and there can be trouble when you have 2 ifas on the same range
(e.g. 10.0.0.1/24@em0 & 10.0.0.20/24@em1) :

netinet/ip_mroute.c:814
net/route.c:785
netinet/ip_divert.c:143
net/if_vxlan.c:241

There are also places where broadcast addresses should not be tolerated :

netinet/ip_input.c:1061  broadcast address is not a module identifier
netinet/ip_input.c:1141  see above
netinet/ip_input.c:1197  see above
netinet6/*:  no broadcast in ipv6
net/route.c:562: gateway shall never be a broadcast addr
net/route.c:713: see above

This diff removes broadcast matching from ifa_ifwithaddr, and
adds or rewrites checks where necessary.

Comments ? Ok ?

Index: sys/net/if.c
===
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.416
diff -u -p -r1.416 if.c
--- sys/net/if.c2 Dec 2015 08:47:00 -   1.416
+++ sys/net/if.c2 Dec 2015 15:17:26 -
@@ -1178,13 +1178,6 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
 
if (equal(addr, ifa->ifa_addr))
return (ifa);
-
-   /* IPv6 doesn't have broadcast */
-   if ((ifp->if_flags & IFF_BROADCAST) &&
-   ifa->ifa_broadaddr &&
-   ifa->ifa_broadaddr->sa_len != 0 &&
-   equal(ifa->ifa_broadaddr, addr))
-   return (ifa);
}
}
return (NULL);
Index: sys/netinet/in_pcb.c
===
RCS file: /cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.188
diff -u -p -r1.188 in_pcb.c
--- sys/netinet/in_pcb.c30 Oct 2015 09:39:42 -  1.188
+++ sys/netinet/in_pcb.c2 Dec 2015 15:17:26 -
@@ -328,14 +328,12 @@ in_pcbbind(struct inpcb *inp, struct mbu
 
ia = ifatoia(ifa_ifwithaddr(sintosa(sin),
inp->inp_rtableid));
-   if (ia == NULL)
-   return (EADDRNOTAVAIL);
 
/* SOCK_RAW does not use in_pcbbind() */
-   if (so->so_type != SOCK_DGRAM &&
-   sin->sin_addr.s_addr !=
-   ia->ia_addr.sin_addr.s_addr)
-   return (EADDRNOTAVAIL);
+   if (ia == NULL &&
+   (so->so_type != SOCK_DGRAM ||
+   !in_broadcast(sin->sin_addr, 
inp->inp_rtableid)))
+   return (EADDRNOTAVAIL);
}
}
if (lport) {
Index: sys/netinet/ip_output.c
===
RCS file: /cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.310
diff -u -p -r1.310 ip_output.c
--- sys/netinet/ip_output.c 2 Dec 2015 13:29:26 -   1.310
+++ sys/netinet/ip_output.c 2 Dec 2015 15:17:27 -
@@ -1387,9 +1387,8 @@ ip_setmoptions(int optname, struct ip_mo
sin.sin_family = AF_INET;
sin.sin_addr = addr;
ia = ifatoia(ifa_ifwithaddr(sintosa(), rtableid));
-   if (ia && in_hosteq(sin.sin_addr, ia->ia_addr.sin_addr))
-   ifp = ia->ia_ifp;
-   if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
+   if (ia == NULL || (ifp = ia->ia_ifp) == NULL ||
+   (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) {
error = EADDRNOTAVAIL;
break;
}
@@ -1561,12 +1560,11 @@ ip_setmoptions(int optname, struct ip_mo
sin.sin_family = AF_INET;
sin.sin_addr = mreq->imr_interface;
ia = ifatoia(ifa_ifwithaddr(sintosa(), rtableid));
-   if (ia && in_hosteq(sin.sin_addr, ia->ia_addr.sin_addr))
-   ifp = ia->ia_ifp;
-   else {
+   if (ia == NULL) {
error = EADDRNOTAVAIL;
break;
}
+   ifp = ia->ia_ifp;
}
/*
 * Find the membership in the membership array.
Index: sys/netinet/raw_ip.c
===
RCS file: /cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.84
diff -u -p -r1.84 raw_ip.c
--- sys/netinet/raw_ip.c28 Jul 2015 12:22:07 -  1.84
+++ sys/netinet/raw_ip.c2 Dec 2015 15:17:27 -
@@ -473,6 +473,7 @@ 

Re: explicitly check broadcast addresses on some ifa_ifwithaddr() uses

2015-12-02 Thread Martin Pieuchot
On 02/12/15(Wed) 16:18, Vincent Gross wrote:
> When fed a broadcast address, ifa_ifwitaddr() returns the unicast ifa
> whose broadcast address match the input. This is used mainly to select
> ifa, and there can be trouble when you have 2 ifas on the same range
> (e.g. 10.0.0.1/24@em0 & 10.0.0.20/24@em1) :
> 
> netinet/ip_mroute.c:814
> net/route.c:785
> netinet/ip_divert.c:143
> net/if_vxlan.c:241
> 
> There are also places where broadcast addresses should not be tolerated :
> 
> netinet/ip_input.c:1061  broadcast address is not a module identifier
> netinet/ip_input.c:1141  see above
> netinet/ip_input.c:1197  see above
> netinet6/*:  no broadcast in ipv6
> net/route.c:562: gateway shall never be a broadcast addr
> net/route.c:713: see above
> 
> This diff removes broadcast matching from ifa_ifwithaddr, and
> adds or rewrites checks where necessary.
> 
> Comments ? Ok ?

Looks good to me.  Some nits below.

> Index: sys/netinet/in_pcb.c
> ===
> RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> retrieving revision 1.188
> diff -u -p -r1.188 in_pcb.c
> --- sys/netinet/in_pcb.c  30 Oct 2015 09:39:42 -  1.188
> +++ sys/netinet/in_pcb.c  2 Dec 2015 15:17:26 -
> @@ -328,14 +328,12 @@ in_pcbbind(struct inpcb *inp, struct mbu
>  
>   ia = ifatoia(ifa_ifwithaddr(sintosa(sin),
>   inp->inp_rtableid));
> - if (ia == NULL)
> - return (EADDRNOTAVAIL);
>  
>   /* SOCK_RAW does not use in_pcbbind() */
> - if (so->so_type != SOCK_DGRAM &&
> - sin->sin_addr.s_addr !=
> - ia->ia_addr.sin_addr.s_addr)
> - return (EADDRNOTAVAIL);
> + if (ia == NULL &&
> + (so->so_type != SOCK_DGRAM ||
> + !in_broadcast(sin->sin_addr, inp->inp_rtable
id)))
^
Code should fit in 80 columns.

> + return (EADDRNOTAVAIL);
>   }
>   }
>   if (lport) {
> Index: sys/netinet/ip_output.c
> ===
> RCS file: /cvs/src/sys/netinet/ip_output.c,v
> retrieving revision 1.310
> diff -u -p -r1.310 ip_output.c
> --- sys/netinet/ip_output.c   2 Dec 2015 13:29:26 -   1.310
> +++ sys/netinet/ip_output.c   2 Dec 2015 15:17:27 -
> @@ -1387,9 +1387,8 @@ ip_setmoptions(int optname, struct ip_mo
>   sin.sin_family = AF_INET;
>   sin.sin_addr = addr;
>   ia = ifatoia(ifa_ifwithaddr(sintosa(), rtableid));
> - if (ia && in_hosteq(sin.sin_addr, ia->ia_addr.sin_addr))
> - ifp = ia->ia_ifp;
> - if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
> + if (ia == NULL || (ifp = ia->ia_ifp) == NULL ||

ia_ifp MUST not be NULL since you got it from the per-ifp list, so need
to check for NULL.

> + (ia->ia_ifp->if_flags & IFF_MULTICAST) == 0) {
>   error = EADDRNOTAVAIL;
>   break;
>   }