Re: rad(8) and carp interfaces

2019-09-07 Thread Sebastian Benoit
ok

Florian Obser(flor...@openbsd.org) on 2019.09.07 09:11:36 +0200:
> On Fri, Sep 06, 2019 at 09:15:16PM +0200, Sebastian Benoit wrote:
> > Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200:
> > > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote:
> > > > Hi,
> > > > 
> > > > I've a pair of redundant routers, which need to run rad(8) on the
> > > > internal interfaces.
> > > > 
> > > > But using carp, on the inactive router, rad complains every
> > > > time it tries to send a RA:
> > > > 
> > > >  rad[65590]: sendmsg on carp2: Can't assign requested address
> > > > 
> > > > Which I can understand since it currently doesnt "own" the shared IPv6
> > > > address of the carp interface.
> > > > 
> > > > Is there a way to configure rad to avoid these errors?
> > > > How do other people handle the situation?
> > > > 
> > > > Thanks in advance,
> > > > -- 
> > > > Matthieu Herrb
> > > > 
> > > 
> > > This should keep the noise down.
> > > 
> > > OK?
> > 
> > comment inline
> > 
> > >   if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
> > > - log_debug("keeping interface %s", name);
> > > - ra_iface->removed = 0;
> > > + ra_iface->link_state = link_state;
> > > + if (link_state == LINK_STATE_DOWN) {
> > 
> > note that there are some (physical) interfaces that do not report a link
> > state and thus are unknown even when they can send packets.
> 
> I know, observe how I don't care about UP but rather DOWN.
> 
> > Use the LINK_STATE_IS_UP() macro here.
> 
> Probably best to use !LINK_STATE_IS_UP() :P
> 
> > 
> > Do we need to consider the case of an interface being administratively down
> > here (!(ifap->flags & IFF_UP))?.
> 
> I checked, no. sendmsg doesn't error out, the packet is just not going
> out. I would leave it at that.
> 
> diff --git frontend.c frontend.c
> index 8178b058629..3cf52fb4127 100644
> --- frontend.c
> +++ frontend.c
> @@ -104,6 +104,7 @@ struct ra_iface {
>   charconf_name[IF_NAMESIZE];
>   uint32_tif_index;
>   int removed;
> + int link_state;
>   int prefix_count;
>   size_t  datalen;
>   uint8_t data[RA_MAX_SIZE];
> @@ -117,6 +118,7 @@ void   frontend_startup(void);
>  void  icmp6_receive(int, short, void *);
>  void  join_all_routers_mcast_group(struct ra_iface *);
>  void  leave_all_routers_mcast_group(struct ra_iface *);
> +int   get_link_state(char *);
>  void  merge_ra_interface(char *, char *);
>  void  merge_ra_interfaces(void);
>  struct ra_iface  *find_ra_iface_by_id(uint32_t);
> @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, 
> char *if_name)
>   return (NULL);
>  }
>  
> +int
> +get_link_state(char *if_name)
> +{
> + struct ifaddrs  *ifap, *ifa;
> + int  ls = LINK_STATE_UNKNOWN;
> +
> + if (getifaddrs() != 0) {
> + log_warn("getifaddrs");
> + return LINK_STATE_UNKNOWN;
> + }
> + for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> + if (ifa->ifa_addr->sa_family != AF_LINK)
> + continue;
> + if (strcmp(if_name, ifa->ifa_name) != 0)
> + continue;
> +
> + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
> + break;
> + }
> + freeifaddrs(ifap);
> + return ls;
> +}
> +
>  void
>  merge_ra_interface(char *name, char *conf_name)
>  {
>   struct ra_iface *ra_iface;
>   uint32_t if_index;
> + int  link_state;
> +
> + link_state = get_link_state(name);
>  
>   if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
> - log_debug("keeping interface %s", name);
> - ra_iface->removed = 0;
> + ra_iface->link_state = link_state;
> + if (!LINK_STATE_IS_UP(link_state)) {
> + log_debug("%s down, ignoring", name);
> + ra_iface->removed = 1;
> + } else {
> + log_debug("keeping interface %s", name);
> + ra_iface->removed = 0;
> + }
> + return;
> + }
> +
> + if (!LINK_STATE_IS_UP(link_state)) {
> + log_debug("%s down, ignoring", name);
>   return;
>   }
>  
>   log_debug("new interface %s", name);
>   if ((if_index = if_nametoindex(name)) == 0)
>   return;
> +
>   log_debug("adding interface %s", name);
>   if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
>   fatal("%s", __func__);
> @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct 
> sockaddr_in6 *to)
>   ssize_t  len;
>   

Re: rad(8) and carp interfaces

2019-09-07 Thread Florian Obser
On Fri, Sep 06, 2019 at 09:15:16PM +0200, Sebastian Benoit wrote:
> Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200:
> > On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote:
> > > Hi,
> > > 
> > > I've a pair of redundant routers, which need to run rad(8) on the
> > > internal interfaces.
> > > 
> > > But using carp, on the inactive router, rad complains every
> > > time it tries to send a RA:
> > > 
> > >  rad[65590]: sendmsg on carp2: Can't assign requested address
> > > 
> > > Which I can understand since it currently doesnt "own" the shared IPv6
> > > address of the carp interface.
> > > 
> > > Is there a way to configure rad to avoid these errors?
> > > How do other people handle the situation?
> > > 
> > > Thanks in advance,
> > > -- 
> > > Matthieu Herrb
> > > 
> > 
> > This should keep the noise down.
> > 
> > OK?
> 
> comment inline
> 
> > if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
> > -   log_debug("keeping interface %s", name);
> > -   ra_iface->removed = 0;
> > +   ra_iface->link_state = link_state;
> > +   if (link_state == LINK_STATE_DOWN) {
> 
> note that there are some (physical) interfaces that do not report a link
> state and thus are unknown even when they can send packets.

I know, observe how I don't care about UP but rather DOWN.

> Use the LINK_STATE_IS_UP() macro here.

Probably best to use !LINK_STATE_IS_UP() :P

> 
> Do we need to consider the case of an interface being administratively down
> here (!(ifap->flags & IFF_UP))?.

I checked, no. sendmsg doesn't error out, the packet is just not going
out. I would leave it at that.

diff --git frontend.c frontend.c
index 8178b058629..3cf52fb4127 100644
--- frontend.c
+++ frontend.c
@@ -104,6 +104,7 @@ struct ra_iface {
charconf_name[IF_NAMESIZE];
uint32_tif_index;
int removed;
+   int link_state;
int prefix_count;
size_t  datalen;
uint8_t data[RA_MAX_SIZE];
@@ -117,6 +118,7 @@ void frontend_startup(void);
 voidicmp6_receive(int, short, void *);
 voidjoin_all_routers_mcast_group(struct ra_iface *);
 voidleave_all_routers_mcast_group(struct ra_iface *);
+int get_link_state(char *);
 voidmerge_ra_interface(char *, char *);
 voidmerge_ra_interfaces(void);
 struct ra_iface*find_ra_iface_by_id(uint32_t);
@@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, char 
*if_name)
return (NULL);
 }
 
+int
+get_link_state(char *if_name)
+{
+   struct ifaddrs  *ifap, *ifa;
+   int  ls = LINK_STATE_UNKNOWN;
+
+   if (getifaddrs() != 0) {
+   log_warn("getifaddrs");
+   return LINK_STATE_UNKNOWN;
+   }
+   for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+   if (ifa->ifa_addr->sa_family != AF_LINK)
+   continue;
+   if (strcmp(if_name, ifa->ifa_name) != 0)
+   continue;
+
+   ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
+   break;
+   }
+   freeifaddrs(ifap);
+   return ls;
+}
+
 void
 merge_ra_interface(char *name, char *conf_name)
 {
struct ra_iface *ra_iface;
uint32_t if_index;
+   int  link_state;
+
+   link_state = get_link_state(name);
 
if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
-   log_debug("keeping interface %s", name);
-   ra_iface->removed = 0;
+   ra_iface->link_state = link_state;
+   if (!LINK_STATE_IS_UP(link_state)) {
+   log_debug("%s down, ignoring", name);
+   ra_iface->removed = 1;
+   } else {
+   log_debug("keeping interface %s", name);
+   ra_iface->removed = 0;
+   }
+   return;
+   }
+
+   if (!LINK_STATE_IS_UP(link_state)) {
+   log_debug("%s down, ignoring", name);
return;
}
 
log_debug("new interface %s", name);
if ((if_index = if_nametoindex(name)) == 0)
return;
+
log_debug("adding interface %s", name);
if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
fatal("%s", __func__);
@@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 
*to)
ssize_t  len;
int  hoplimit = 255;
 
+   if (!LINK_STATE_IS_UP(ra_iface->link_state))
+   return;
+
sndmhdr.msg_name = to;
sndmhdr.msg_iov[0].iov_base = ra_iface->data;

Re: rad(8) and carp interfaces

2019-09-06 Thread Sebastian Benoit
Florian Obser(flor...@openbsd.org) on 2019.09.06 16:51:35 +0200:
> On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote:
> > Hi,
> > 
> > I've a pair of redundant routers, which need to run rad(8) on the
> > internal interfaces.
> > 
> > But using carp, on the inactive router, rad complains every
> > time it tries to send a RA:
> > 
> >  rad[65590]: sendmsg on carp2: Can't assign requested address
> > 
> > Which I can understand since it currently doesnt "own" the shared IPv6
> > address of the carp interface.
> > 
> > Is there a way to configure rad to avoid these errors?
> > How do other people handle the situation?
> > 
> > Thanks in advance,
> > -- 
> > Matthieu Herrb
> > 
> 
> This should keep the noise down.
> 
> OK?

comment inline

> 
> diff --git frontend.c frontend.c
> index 8178b058629..920e9b7077c 100644
> --- frontend.c
> +++ frontend.c
> @@ -104,6 +104,7 @@ struct ra_iface {
>   charconf_name[IF_NAMESIZE];
>   uint32_tif_index;
>   int removed;
> + int link_state;
>   int prefix_count;
>   size_t  datalen;
>   uint8_t data[RA_MAX_SIZE];
> @@ -117,6 +118,7 @@ void   frontend_startup(void);
>  void  icmp6_receive(int, short, void *);
>  void  join_all_routers_mcast_group(struct ra_iface *);
>  void  leave_all_routers_mcast_group(struct ra_iface *);
> +int   get_link_state(char *);
>  void  merge_ra_interface(char *, char *);
>  void  merge_ra_interfaces(void);
>  struct ra_iface  *find_ra_iface_by_id(uint32_t);
> @@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, 
> char *if_name)
>   return (NULL);
>  }
>  
> +int
> +get_link_state(char *if_name)
> +{
> + struct ifaddrs  *ifap, *ifa;
> + int  ls = LINK_STATE_UNKNOWN;
> +
> + if (getifaddrs() != 0) {
> + log_warn("getifaddrs");
> + return LINK_STATE_UNKNOWN;
> + }
> + for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
> + if (ifa->ifa_addr->sa_family != AF_LINK)
> + continue;
> + if (strcmp(if_name, ifa->ifa_name) != 0)
> + continue;
> +
> + ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
> + break;
> + }
> + freeifaddrs(ifap);
> + return ls;
> +}
> +
>  void
>  merge_ra_interface(char *name, char *conf_name)
>  {
>   struct ra_iface *ra_iface;
>   uint32_t if_index;
> + int  link_state;
> +
> + link_state = get_link_state(name);
>  
>   if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
> - log_debug("keeping interface %s", name);
> - ra_iface->removed = 0;
> + ra_iface->link_state = link_state;
> + if (link_state == LINK_STATE_DOWN) {

note that there are some (physical) interfaces that do not report a link
state and thus are unknown even when they can send packets.
Use the LINK_STATE_IS_UP() macro here.

Do we need to consider the case of an interface being administratively down
here (!(ifap->flags & IFF_UP))?.


> + log_debug("%s down, ignoring", name);
> + ra_iface->removed = 1;
> + } else {
> + log_debug("keeping interface %s", name);
> + ra_iface->removed = 0;
> + }
> + return;
> + }
> +
> + if (link_state == LINK_STATE_DOWN) {
> + log_debug("%s down, ignoring", name);
>   return;
>   }
>  
>   log_debug("new interface %s", name);
>   if ((if_index = if_nametoindex(name)) == 0)
>   return;
> +
>   log_debug("adding interface %s", name);
>   if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
>   fatal("%s", __func__);
> @@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct 
> sockaddr_in6 *to)
>   ssize_t  len;
>   int  hoplimit = 255;
>  
> + if (ra_iface->link_state == LINK_STATE_DOWN)
> + return;
> +
>   sndmhdr.msg_name = to;
>   sndmhdr.msg_iov[0].iov_base = ra_iface->data;
>   sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;
> 
> 
> -- 
> I'm not entirely sure you are real.
> 



Re: rad(8) and carp interfaces

2019-09-06 Thread Florian Obser
On Wed, Sep 04, 2019 at 06:07:35PM +0200, Matthieu Herrb wrote:
> Hi,
> 
> I've a pair of redundant routers, which need to run rad(8) on the
> internal interfaces.
> 
> But using carp, on the inactive router, rad complains every
> time it tries to send a RA:
> 
>  rad[65590]: sendmsg on carp2: Can't assign requested address
> 
> Which I can understand since it currently doesnt "own" the shared IPv6
> address of the carp interface.
> 
> Is there a way to configure rad to avoid these errors?
> How do other people handle the situation?
> 
> Thanks in advance,
> -- 
> Matthieu Herrb
> 

This should keep the noise down.

OK?

diff --git frontend.c frontend.c
index 8178b058629..920e9b7077c 100644
--- frontend.c
+++ frontend.c
@@ -104,6 +104,7 @@ struct ra_iface {
charconf_name[IF_NAMESIZE];
uint32_tif_index;
int removed;
+   int link_state;
int prefix_count;
size_t  datalen;
uint8_t data[RA_MAX_SIZE];
@@ -117,6 +118,7 @@ void frontend_startup(void);
 voidicmp6_receive(int, short, void *);
 voidjoin_all_routers_mcast_group(struct ra_iface *);
 voidleave_all_routers_mcast_group(struct ra_iface *);
+int get_link_state(char *);
 voidmerge_ra_interface(char *, char *);
 voidmerge_ra_interfaces(void);
 struct ra_iface*find_ra_iface_by_id(uint32_t);
@@ -720,21 +722,59 @@ find_ra_iface_conf(struct ra_iface_conf_head *head, char 
*if_name)
return (NULL);
 }
 
+int
+get_link_state(char *if_name)
+{
+   struct ifaddrs  *ifap, *ifa;
+   int  ls = LINK_STATE_UNKNOWN;
+
+   if (getifaddrs() != 0) {
+   log_warn("getifaddrs");
+   return LINK_STATE_UNKNOWN;
+   }
+   for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+   if (ifa->ifa_addr->sa_family != AF_LINK)
+   continue;
+   if (strcmp(if_name, ifa->ifa_name) != 0)
+   continue;
+
+   ls = ((struct if_data*)ifa->ifa_data)->ifi_link_state;
+   break;
+   }
+   freeifaddrs(ifap);
+   return ls;
+}
+
 void
 merge_ra_interface(char *name, char *conf_name)
 {
struct ra_iface *ra_iface;
uint32_t if_index;
+   int  link_state;
+
+   link_state = get_link_state(name);
 
if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
-   log_debug("keeping interface %s", name);
-   ra_iface->removed = 0;
+   ra_iface->link_state = link_state;
+   if (link_state == LINK_STATE_DOWN) {
+   log_debug("%s down, ignoring", name);
+   ra_iface->removed = 1;
+   } else {
+   log_debug("keeping interface %s", name);
+   ra_iface->removed = 0;
+   }
+   return;
+   }
+
+   if (link_state == LINK_STATE_DOWN) {
+   log_debug("%s down, ignoring", name);
return;
}
 
log_debug("new interface %s", name);
if ((if_index = if_nametoindex(name)) == 0)
return;
+
log_debug("adding interface %s", name);
if ((ra_iface = calloc(1, sizeof(*ra_iface))) == NULL)
fatal("%s", __func__);
@@ -1135,6 +1175,9 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 
*to)
ssize_t  len;
int  hoplimit = 255;
 
+   if (ra_iface->link_state == LINK_STATE_DOWN)
+   return;
+
sndmhdr.msg_name = to;
sndmhdr.msg_iov[0].iov_base = ra_iface->data;
sndmhdr.msg_iov[0].iov_len = ra_iface->datalen;


-- 
I'm not entirely sure you are real.



Re: rad(8) and carp interfaces

2019-09-05 Thread Klemens Nanni
On Thu, Sep 05, 2019 at 10:32:25AM +0200, Sebastian Benoit wrote:
> Unrelated, but noticed by florian, this bit in the manpage is no longer
> needed since he removed soii for link-local adresses in
> sys/netinet6/in6_ifattach.c rev 1.114
Good catch, OK kn.



Re: rad(8) and carp interfaces

2019-09-05 Thread Sebastian Benoit
Matthieu Herrb(matth...@openbsd.org) on 2019.09.04 18:07:35 +0200:
> Hi,
> 
> I've a pair of redundant routers, which need to run rad(8) on the
> internal interfaces.
> 
> But using carp, on the inactive router, rad complains every
> time it tries to send a RA:
> 
>  rad[65590]: sendmsg on carp2: Can't assign requested address
> 
> Which I can understand since it currently doesnt "own" the shared IPv6
> address of the carp interface.

correct. rad(8) needs to look at the interface state to not try sending on
a (carp) interface that is in backup state, or just not print this warning
at all. It is possible to monitor the link state since the frontend process
already has a route socket and could certainly track the link state, buts
its a little bit of work.
 
> Is there a way to configure rad to avoid these errors?

At the moment none other than patching out the log_warn().

> How do other people handle the situation?
> 
> Thanks in advance,
> -- 
> Matthieu Herrb
> 

Unrelated, but noticed by florian, this bit in the manpage is no longer
needed since he removed soii for link-local adresses in
sys/netinet6/in6_ifattach.c rev 1.114

ok?

diff b31eb29f59f3580445ea0341b271e321d53958a6 /opt/git/benoit/src
blob - d93e64d4648dfe25a5c76faac3994780d1ce02f8
file + usr.sbin/rad/rad.8
--- usr.sbin/rad/rad.8
+++ usr.sbin/rad/rad.8
@@ -146,15 +146,3 @@ The
 .Nm
 program was written by
 .An Florian Obser Aq Mt flor...@openbsd.org .
-.Sh CAVEATS
-When running
-.Nm
-on a
-.Xr carp 4
-interface, it is recommended to either disable SOIIs (persistent Semantically
-Opaque Interface Identifiers) on the interface with
-.Xr ifconfig 8 ,
-or ensure that all CARP peers have the same SOII key stored in
-.Pa /etc/soii.key .
-Otherwise the default IPv6 router's link-local address will change during CARP
-failover, which temporarily disrupts connectivity of IPv6 autoconf clients.



rad(8) and carp interfaces

2019-09-04 Thread Matthieu Herrb
Hi,

I've a pair of redundant routers, which need to run rad(8) on the
internal interfaces.

But using carp, on the inactive router, rad complains every
time it tries to send a RA:

 rad[65590]: sendmsg on carp2: Can't assign requested address

Which I can understand since it currently doesnt "own" the shared IPv6
address of the carp interface.

Is there a way to configure rad to avoid these errors?
How do other people handle the situation?

Thanks in advance,
-- 
Matthieu Herrb