Convert bridge span & int. list to SLIST()

2018-12-23 Thread Martin Pieuchot
Using SLIST() instead of TAILQ() is a step towards using lock-less
lists. 

As found in my previous attempts the interface list cannot be protected
by a mutex as long a if_enqueue() might grab the KERNEL_LOCK().  So I'm
heading towards using SRPL_*().

Ok?

Index: net/if_bridge.c
===
RCS file: /cvs/src/sys/net/if_bridge.c,v
retrieving revision 1.315
diff -u -p -r1.315 if_bridge.c
--- net/if_bridge.c 12 Dec 2018 14:19:15 -  1.315
+++ net/if_bridge.c 12 Dec 2018 14:27:21 -
@@ -108,6 +108,8 @@ voidbridgeattach(int);
 intbridge_ioctl(struct ifnet *, u_long, caddr_t);
 void   bridge_ifdetach(void *);
 void   bridge_spandetach(void *);
+intbridge_ifremove(struct bridge_iflist *);
+intbridge_spanremove(struct bridge_iflist *);
 intbridge_input(struct ifnet *, struct mbuf *, void *);
 void   bridge_process(struct ifnet *, struct mbuf *);
 void   bridgeintr_frame(struct bridge_softc *, struct ifnet *, struct mbuf *);
@@ -170,8 +172,8 @@ bridge_clone_create(struct if_clone *ifc
sc->sc_brtmax = BRIDGE_RTABLE_MAX;
sc->sc_brttimeout = BRIDGE_RTABLE_TIMEOUT;
timeout_set(>sc_brtimeout, bridge_rtage, sc);
-   TAILQ_INIT(>sc_iflist);
-   TAILQ_INIT(>sc_spanlist);
+   SLIST_INIT(>sc_iflist);
+   SLIST_INIT(>sc_spanlist);
for (i = 0; i < BRIDGE_RTABLE_SIZE; i++)
LIST_INIT(>sc_rts[i]);
arc4random_buf(>sc_hashkey, sizeof(sc->sc_hashkey));
@@ -216,10 +218,14 @@ bridge_clone_destroy(struct ifnet *ifp)
 
bridge_stop(sc);
bridge_rtflush(sc, IFBF_FLUSHALL);
-   while ((bif = TAILQ_FIRST(>sc_iflist)) != NULL)
+   while ((bif = SLIST_FIRST(>sc_iflist)) != NULL) {
+   SLIST_REMOVE_HEAD(>sc_iflist, bif_next);
bridge_delete(sc, bif);
-   while ((bif = TAILQ_FIRST(>sc_spanlist)) != NULL)
+   }
+   while ((bif = SLIST_FIRST(>sc_spanlist)) != NULL) {
+   SLIST_REMOVE_HEAD(>sc_spanlist, bif_next);
bridge_spandetach(bif);
+   }
 
bstp_destroy(sc->sc_stp);
 
@@ -249,7 +255,6 @@ bridge_delete(struct bridge_softc *sc, s
hook_disestablish(bif->ifp->if_detachhooks, bif->bif_dhcookie);
 
if_ih_remove(bif->ifp, bridge_input, NULL);
-   TAILQ_REMOVE(>sc_iflist, bif, next);
bridge_rtdelete(sc, bif->ifp, 0);
bridge_flushrule(bif);
free(bif, M_DEVBUF, sizeof *bif);
@@ -297,7 +302,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
}
 
/* If it's in the span list, it can't be a member. */
-   TAILQ_FOREACH(bif, >sc_spanlist, next) {
+   SLIST_FOREACH(bif, >sc_spanlist, bif_next) {
if (bif->ifp == ifs)
break;
}
@@ -338,7 +343,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
bif->bif_dhcookie = hook_establish(ifs->if_detachhooks, 0,
bridge_ifdetach, bif);
if_ih_insert(bif->ifp, bridge_input, NULL);
-   TAILQ_INSERT_TAIL(>sc_iflist, bif, next);
+   SLIST_INSERT_HEAD(>sc_iflist, bif, bif_next);
break;
case SIOCBRDGDEL:
if ((error = suser(curproc)) != 0)
@@ -353,7 +358,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
error = ESRCH;
break;
}
-   error = bridge_delete(sc, bif);
+   error = bridge_ifremove(bif);
break;
case SIOCBRDGIFS:
error = bridge_bifconf(sc, (struct ifbifconf *)data);
@@ -375,7 +380,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
error = EBUSY;
break;
}
-   TAILQ_FOREACH(bif, >sc_spanlist, next) {
+   SLIST_FOREACH(bif, >sc_spanlist, bif_next) {
if (bif->ifp == ifs)
break;
}
@@ -395,7 +400,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
bridge_spandetach, bif);
SIMPLEQ_INIT(>bif_brlin);
SIMPLEQ_INIT(>bif_brlout);
-   TAILQ_INSERT_TAIL(>sc_spanlist, bif, next);
+   SLIST_INSERT_HEAD(>sc_spanlist, bif, bif_next);
break;
case SIOCBRDGDELS:
if ((error = suser(curproc)) != 0)
@@ -405,15 +410,15 @@ bridge_ioctl(struct ifnet *ifp, u_long c
error = ENOENT;
break;
}
-   TAILQ_FOREACH(bif, >sc_spanlist, next) {
+   SLIST_FOREACH(bif, >sc_spanlist, bif_next) {
if (bif->ifp == ifs)
break;
}
if (bif == NULL) {
-   error = ENOENT;
+   error = ESRCH;
break;
}
- 

Re: MPLSv6 1/2: kernel diff

2018-12-23 Thread Martin Pieuchot
On 18/12/18(Tue) 12:13, Denis Fondras wrote:
> Here is a serie of diffs to enable MPLSv6, MPLS transport over IPv6.

Nice!

> First diff : allow mpe(4) to handle IPv6 trafic.

Comments below
 
> Index: net/if_ethersubr.c
> ===
> RCS file: /cvs/src/sys/net/if_ethersubr.c,v
> retrieving revision 1.255
> diff -u -p -r1.255 if_ethersubr.c
> --- net/if_ethersubr.c12 Dec 2018 05:38:26 -  1.255
> +++ net/if_ethersubr.c18 Dec 2018 11:03:33 -
> @@ -246,18 +246,28 @@ ether_resolve(struct ifnet *ifp, struct 
>   sizeof(eh->ether_dhost));
>   break;
>  #ifdef INET6
> +do_v6:
>   case AF_INET6:
>   error = nd6_resolve(ifp, rt, m, dst, eh->ether_dhost);
>   if (error)
>   return (error);
>   break;
>  #endif
> +do_v4:
>   case AF_INET:
> - case AF_MPLS:
>   error = arpresolve(ifp, rt, m, dst, eh->ether_dhost);
>   if (error)
>   return (error);
>   break;
> + case AF_MPLS:
> + switch (rt->rt_gateway->sa_family) {
> + case AF_INET:
> + goto do_v4;
> +#ifdef INET6
> + case AF_INET6:
> + goto do_v6;
> +#endif
> + }
>   default:
>   senderr(EHOSTUNREACH);
>   }

This makes ether_resolve() (aka ether_output()) even more spaghetti for MPLS.

I know this is not your code, but is it possible to do better than that?
The current logic hides an encapsulation.  For example would it be possible
to call ether_resolve() recursively in the AF_MPLS case?

> Index: net/if_mpe.c
> ===
> RCS file: /cvs/src/sys/net/if_mpe.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 if_mpe.c
> --- net/if_mpe.c  9 Jan 2018 15:24:24 -   1.64
> +++ net/if_mpe.c  18 Dec 2018 11:03:33 -
> @@ -85,7 +85,7 @@ mpe_clone_create(struct if_clone *ifc, i
>   mpeif->sc_unit = unit;
>   ifp = >sc_if;
>   snprintf(ifp->if_xname, sizeof ifp->if_xname, "mpe%d", unit);
> - ifp->if_flags = IFF_POINTOPOINT;
> + ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST;

You added this flag because the nd6 codes relies on it, right?  But does
this reflect reality?

>   ifp->if_xflags = IFXF_CLONED;
>   ifp->if_softc = mpeif;
>   ifp->if_mtu = MPE_MTU;
> @@ -157,6 +157,16 @@ mpestart(struct ifnet *ifp0)
>   sizeof(in_addr_t));
>   m_adj(m, sizeof(in_addr_t));
>   break;
> +#ifdef INET6
> + case AF_INET6:
> + memset(sa, 0, sizeof(struct sockaddr_in6));
> + satosin6(sa)->sin6_family = af;
> + satosin6(sa)->sin6_len = sizeof(struct sockaddr_in6);
> + bcopy(mtod(m, caddr_t), (sa)->sin6_addr,
> + sizeof(struct in6_addr));
> + m_adj(m, sizeof(struct in6_addr));
> + break;
> +#endif
>   default:
>   m_freem(m);
>   continue;
> @@ -204,6 +214,9 @@ mpeoutput(struct ifnet *ifp, struct mbuf
>   int error;
>   int off;
>   in_addr_t   addr;
> +#ifdef INET6
> + struct in6_addr addr6;
> +#endif
>   u_int8_top = 0;
>  
>  #ifdef DIAGNOSTIC
> @@ -251,6 +264,39 @@ mpeoutput(struct ifnet *ifp, struct mbuf
>   m_copyback(m, sizeof(sa_family_t), sizeof(in_addr_t),
>   , M_NOWAIT);
>   break;
> +#ifdef INET6
> + case AF_INET6:
> + if (!rt || !(rt->rt_flags & RTF_MPLS)) {

I know you copied past, but checking for rt != NULL should be avoided.
You should use rtisvalid().  Could you please merge the blocks related
to rtentry.  I general if you can reduce the copy/paste between v4 & v6
that would be great!

Another style neat, we use the ISSET() macro for checking RTF_* flags ;)

> + m_freem(m);
> + error = ENETUNREACH;
> + goto out;
> + }
> + shim.shim_label = ((struct rt_mpls *)rt->rt_llinfo)->mpls_label;
> + shim.shim_label |= MPLS_BOS_MASK;
> + op =  ((struct rt_mpls *)rt->rt_llinfo)->mpls_operation;
> + if (op != MPLS_OP_PUSH) {
> + m_freem(m);
> + error = ENETUNREACH;
> + goto out;
> + }
> + if (mpls_mapttl_ip) {
> + struct ip6_hdr  *ip6;
> + ip6 = mtod(m, struct ip6_hdr *);
> + shim.shim_label |= htonl(ip6->ip6_hops) & 

Re: Another attempt to bypass ifqs on interfaces

2018-12-23 Thread Martin Pieuchot
On 20/12/18(Thu) 11:35, David Gwynne wrote:
> My last attempt in "let etherip(4) output directly to the ip stack"
> didn't go so well. This one at least doesn't break bridge(4) on
> Ethernet.

It breaks it on mpw(4).

> This diff effectively turns if_enqueue into a per interface function
> pointer. Things still call if_enqueue(), which does some pf stuff, and then
> it calls ifp->if_enqueue. By default, that function pointer is
> if_enqueue_ifq() which puts the packet on the interface send queues.
> 
> Ethernet interfaces intercept the call to if_enqueue_ifq(). They get set
> up to call ether_enqueue, which does the bridge stuff and then calls
> ac->ac_enqueue, which shadows the ifp->if_enqueue functionality.

Why do we need two abstraction layers?  It feels weird to have
pseudo-drivers rely on a pointer in 'struct arpcom', because
they don't necessarily need this structure.

> This takes Ethernet bridge(4) knowledge out of the generic interface
> code. Non-Ethernet things that want to bypass ifqs can override
> ifp->if_enqueue. Ethernet things can override ac->ac_enqueue.

Why take it out of the generic?  We spent a lot of energy putting it
there, now you're taking the opposite direction.  So let's spread
NBRIDGE > 1 all over the stack again?

> This diff includes a change to vlan(4) to take advantage of this. It
> overrides ac_enqueue with vlan_enqueue(). So a packet sent out a vlan
> interface will go into if_enqueue(), which will call ether_enqueue()
> because ether_ifattach set that up. ether_enqueue() will call
> ac->ac_enqueue which is vlan_enqueue on vlan interfaces, which will
> eventually call if_enqueue() on the parent interface.

I like the idea behind vlan_transmit().  

> 
> There are some things I'd like to try if this goes in. eg, it may be
> possible to have ether_enqueue simple call ac->ac_enqueue, and let
> bridge(4) swap it out with bridge_enqueue code. Doing that now would
> complicate the diff though.

Why?  What's the gain?

> Anyway, how's this look, esp relative to the previous diff?

It looks better but I'm afraid this diff still breaks stuff, I'd
suggest you to keep your fix simple.  I'm afraid with all the
abstractions that you're introducing.  They look like premature
optimizations to me.

One more comment below.

> Index: net/if.c
> ===
> RCS file: /cvs/src/sys/net/if.c,v
> retrieving revision 1.569
> diff -u -p -r1.569 if.c
> --- net/if.c  11 Dec 2018 22:08:57 -  1.569
> +++ net/if.c  19 Dec 2018 06:48:37 -
> @@ -683,34 +685,33 @@ if_qstart_compat(struct ifqueue *ifq)
>  int
>  if_enqueue(struct ifnet *ifp, struct mbuf *m)
>  {
> - unsigned int idx;
> - struct ifqueue *ifq;
> - int error;
> -
>  #if NPF > 0
>   if (m->m_pkthdr.pf.delay > 0)
>   return (pf_delay_pkt(m, ifp->if_index));
> -#endif
> -
> -#if NBRIDGE > 0
> - if (ifp->if_bridgeport && (m->m_flags & M_PROTO1) == 0) {
> - KERNEL_LOCK();
> - error = bridge_output(ifp, m, NULL, NULL);
> - KERNEL_UNLOCK();
> - return (error);
> - }
> -#endif
>  
> -#if NPF > 0
>   pf_pkt_addr_changed(m);
>  #endif   /* NPF > 0 */

Are you sure calling pf_pkt_addr_changed() before bridge_output() won't
create any unwanted side effect?  In any case I'd suggest keeping this
separated, to be able to revert it easily :D



Re: mg: Delete region

2018-12-23 Thread Ingo Schwarze
Hi Hiltjo,

Hiltjo Posthuma wrote on Sun, Dec 23, 2018 at 03:34:12PM +0100:

> Shouldn't these kind of diffs be OK'd by other developers before
> committing though?

Not necessarily.  When a developer focusses on work in a particular
area and takes responsibility to fix anything that breaks there,
in particular when few or no others work in the area, that developer
owns that code.  When few others work in an area, requiring the
code owner to get OKs for each and every improvement can be detrimental
because on the one hand, it can slow down development for little
benefit, and on the other hand, it can put undue strees on the few
others who occasionally look at that code, too.  Both getting and
giving OKs can be frustrating and time-consuming.

Espie doesn't ask for OKs in pkg_add(1), not even for major changes,
unless he is worried whether or not some general direction is
desired.  Neither do i in mandoc(1).  Neither does landry@ in firefox
nor robert@ in chrome.  And so on.

Even though i don't use mg(1), my impression is that lum@ owns that
code nowadays, that almost the only other developer occasionally
contributing to it is florian@, and that these two have been doing
a very decent job during the last few years: i haven't noticed any
complaints about their work on mg(1).

Unless other *developers* request a backout, the code owner gets to
decide about the details of the way forward.  And "the current
behaviour is already better than what was there last week, and i'll
work on it next week for further improvements" is definitely an
adequate response.

Yours,
  Ingo



Re: mandoc -T html default style

2018-12-23 Thread Todd C. Miller
On Fri, 21 Dec 2018 00:10:10 +0100, Ingo Schwarze wrote:

> I see the point, and it makes sense to me.
>
> So in case people want a sensible default for "-O style=" as suggested,
> where should the file go?
>
> Maybe /usr/share/misc/mandoc.css ?

That would be fine with me.  I definitely think it should be installed
somewhere.  I found it odd that I had to look for mandoc.css in the
source tree when I needed it.

 - todd

 - todd



Re: mg: Delete region

2018-12-23 Thread Hiltjo Posthuma
On Sun, Dec 23, 2018 at 01:58:16PM +, Mark Lumsden wrote:
> On Sun, 23 Dec 2018, Hiltjo Posthuma wrote:
> 
> > Date: Sun, 23 Dec 2018 13:43:32 +0100
> > From: Hiltjo Posthuma 
> > To: Mark Lumsden 
> > Cc: Leonid Bobrov , tech@openbsd.org
> > Subject: Re: mg: Delete region
> > 
> > On Thu, Dec 20, 2018 at 06:44:15AM +, Mark Lumsden wrote:
> > > hmm, you are correct. I'm trying to remember which machine I tested
> > > on that made me come to that conclusion.
> > > 
> > > On Thu, 20 Dec 2018, Leonid Bobrov wrote:
> > > 
> > > > Date: Thu, 20 Dec 2018 06:43:02 +0200
> > > > From: Leonid Bobrov 
> > > > To: Mark Lumsden , tech@openbsd.org
> > > > Subject: Re: mg: Delete region
> > > > 
> > > > I tried this in GNU Emacs and it didn't place the killed region into the
> > > > kill buffer. It only places it into the kill buffer if you pressed C-w
> > > > 
> > > 
> > 
> > Hi,
> > 
> > Can this change get reverted upstream until it is properly tested (and 
> > OK'd),
> > please?
> > 
> > -- 
> > Kind regards,
> > Hiltjo
> > 
> 
> Its should be trivial to make it behave as emacs does. I should get time in
> about a week to have a look. Personally I don't think it needs reverted
> since it is more useful having it behave as it does just now than
> previously. But if someone wants to do so they are free to do that.

Shouldn't these kind of diffs be OK'd by other developers before committing
though?

Backspace should just delete a character backwards and not have some
context-specific behaviour. A person can just bind kill-region to some key if
deletion is wanted. This should not be in the C code.

I reverted the change locally. I use marked regions with other actions all the
time and this change makes mg unusable for me.

-- 
Kind regards,
Hiltjo



Re: mg: Delete region

2018-12-23 Thread Mark Lumsden

On Sun, 23 Dec 2018, Hiltjo Posthuma wrote:


Date: Sun, 23 Dec 2018 13:43:32 +0100
From: Hiltjo Posthuma 
To: Mark Lumsden 
Cc: Leonid Bobrov , tech@openbsd.org
Subject: Re: mg: Delete region

On Thu, Dec 20, 2018 at 06:44:15AM +, Mark Lumsden wrote:

hmm, you are correct. I'm trying to remember which machine I tested
on that made me come to that conclusion.

On Thu, 20 Dec 2018, Leonid Bobrov wrote:


Date: Thu, 20 Dec 2018 06:43:02 +0200
From: Leonid Bobrov 
To: Mark Lumsden , tech@openbsd.org
Subject: Re: mg: Delete region

I tried this in GNU Emacs and it didn't place the killed region into the
kill buffer. It only places it into the kill buffer if you pressed C-w





Hi,

Can this change get reverted upstream until it is properly tested (and OK'd),
please?

--
Kind regards,
Hiltjo



Its should be trivial to make it behave as emacs does. I should get time 
in about a week to have a look. Personally I don't think it needs reverted
since it is more useful having it behave as it does just now than 
previously. But if someone wants to do so they are free to do that.




Re: mg: Delete region

2018-12-23 Thread Hiltjo Posthuma
On Thu, Dec 20, 2018 at 06:44:15AM +, Mark Lumsden wrote:
> hmm, you are correct. I'm trying to remember which machine I tested
> on that made me come to that conclusion.
> 
> On Thu, 20 Dec 2018, Leonid Bobrov wrote:
> 
> > Date: Thu, 20 Dec 2018 06:43:02 +0200
> > From: Leonid Bobrov 
> > To: Mark Lumsden , tech@openbsd.org
> > Subject: Re: mg: Delete region
> > 
> > I tried this in GNU Emacs and it didn't place the killed region into the
> > kill buffer. It only places it into the kill buffer if you pressed C-w
> > 
> 

Hi,

Can this change get reverted upstream until it is properly tested (and OK'd),
please?

-- 
Kind regards,
Hiltjo



Re: MPLS pseudowire over IPv6 1/2: ifconfig(8) diff

2018-12-23 Thread Denis Fondras
On Sun, Dec 23, 2018 at 10:05:01AM +, Jason McIntyre wrote:
> unless you're trying somehow to emphasise that both types of address are
> supported, you could simplify the text to just:
> 
>   The
>   .Ar dest-address
>   is used to find ...
> 

Thank you for your input.

Index: ifconfig.8
===
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.324
diff -u -p -r1.324 ifconfig.8
--- ifconfig.8  16 Nov 2018 12:25:29 -  1.324
+++ ifconfig.8  23 Dec 2018 10:22:56 -
@@ -1344,8 +1344,7 @@ is another 20-bit number which will be u
 Sets the destination address where this mpw should output.
 The
 .Ar dest-address
-is an IPv4 address that will be used to find the nexthop in the MPLS
-network.
+is used to find the nexthop in the MPLS network.
 .El
 .Sh PAIR
 .nr nS 1
Index: ifconfig.c
===
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.387
diff -u -p -r1.387 ifconfig.c
--- ifconfig.c  29 Nov 2018 00:12:34 -  1.387
+++ ifconfig.c  23 Dec 2018 10:22:57 -
@@ -3802,8 +3802,9 @@ mpe_status(void)
 void
 mpw_status(void)
 {
-   struct sockaddr_in *sin;
-   struct ifmpwreq imr;
+   struct sockaddr_storage *ss;
+   struct ifmpwreq  imr;
+   char hbuf[NI_MAXHOST];
 
bzero(, sizeof(imr));
ifr.ifr_data = (caddr_t) 
@@ -3842,11 +3843,19 @@ mpw_status(void)
else
printf("remote %u\n", imr.imr_rshim.shim_label);
 
-   sin = (struct sockaddr_in *) _nexthop;
-   if (sin->sin_addr.s_addr == 0)
-   printf("\tneighbor: none\n");
-   else
-   printf("\tneighbor: %s\n", inet_ntoa(sin->sin_addr));
+   printf("\tneighbor: ");
+   switch (imr.imr_nexthop.ss_family) {
+   case AF_INET6:
+   case AF_INET:
+   ss = (struct sockaddr_storage *) _nexthop;
+   if (getnameinfo((struct sockaddr *)ss, ss->ss_len, hbuf,
+   sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
+   strlcpy(hbuf, "???", sizeof(hbuf));
+   printf("%s\n", hbuf);
+   break;
+   default:
+   printf("none\n");
+   }
 }
 
 /* ARGSUSED */
@@ -3870,6 +3879,7 @@ void
 process_mpw_commands(void)
 {
struct  sockaddr_in *sin, *sinn;
+   struct  sockaddr_in6 *sin6, *sin6n;
struct  ifmpwreq imr;
 
if (wconfig == 0)
@@ -3899,14 +3909,29 @@ process_mpw_commands(void)
imrsave.imr_rshim.shim_label = imr.imr_rshim.shim_label;
}
 
-   sin = (struct sockaddr_in *) _nexthop;
-   sinn = (struct sockaddr_in *) _nexthop;
-   if (sin->sin_addr.s_addr == 0) {
-   if (sinn->sin_addr.s_addr == 0)
+   switch (imrsave.imr_nexthop.ss_family) {
+   case AF_INET6:
+   case AF_INET:
+   /* neighbor was set earlier, nothing to do */
+   break;
+   default:
+   switch (imr.imr_nexthop.ss_family) {
+   case AF_INET6:
+   sin6 = (struct sockaddr_in6 *) _nexthop;
+   sin6n = (struct sockaddr_in6 *) _nexthop;
+   sin6->sin6_family = sin6n->sin6_family;
+   memcpy(>sin6_addr, >sin6_addr,
+   sizeof(struct in6_addr));
+   break;
+   case AF_INET:
+   sin = (struct sockaddr_in *) _nexthop;
+   sinn = (struct sockaddr_in *) _nexthop;
+   sin->sin_family = sinn->sin_family;
+   sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+   break;
+   default:
errx(1, "mpw neighbor address not specified");
-
-   sin->sin_family = sinn->sin_family;
-   sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+   }
}
 
ifr.ifr_data = (caddr_t) 
@@ -3949,14 +3974,41 @@ void
 setmpwneighbor(const char *value, int d)
 {
struct sockaddr_in *sin;
+   struct sockaddr_in6 *sin6;
+   struct addrinfo hints, *res;
+   int rv;
 
wconfig = 1;
 
-   sin = (struct sockaddr_in *) _nexthop;
-   if (inet_aton(value, >sin_addr) == 0)
+   memset(, 0, sizeof(hints));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_protocol = 0;
+   hints.ai_flags = AI_PASSIVE;
+
+   rv = getaddrinfo(value, NULL, , );
+   if (rv != 0)
+   errx(1, "neighbor %s: %s", value, gai_strerror(rv));
+
+   switch (res->ai_family) {
+   case AF_INET:
+   sin = (struct sockaddr_in *) _nexthop;
+   sin->sin_family = res->ai_family;
+   sin->sin_addr.s_addr =
+   ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
+   break;
+  

Re: MPLS pseudowire over IPv6 1/2: ifconfig(8) diff

2018-12-23 Thread Jason McIntyre
On Sun, Dec 23, 2018 at 10:28:30AM +0100, Denis Fondras wrote:
> On Sat, Dec 22, 2018 at 11:42:36PM +0100, Klemens Nanni wrote:
> > I have no clue about MPLS, so this feedback is code-wise only:
> > 
> > Did you consider using more AF agnostic code for parsing the IP address?
> > 
> 
> You are right, it is simpler. Thank you for the clue :)
> 
> Updated diff :
> 
> Index: ifconfig.8
> ===
> RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
> retrieving revision 1.324
> diff -u -p -r1.324 ifconfig.8
> --- ifconfig.816 Nov 2018 12:25:29 -  1.324
> +++ ifconfig.823 Dec 2018 09:25:36 -
> @@ -1344,7 +1344,7 @@ is another 20-bit number which will be u
>  Sets the destination address where this mpw should output.
>  The
>  .Ar dest-address
> -is an IPv4 address that will be used to find the nexthop in the MPLS
> +is an IPv4 or IPv6 address that will be used to find the nexthop in the MPLS
>  network.
>  .El
>  .Sh PAIR

morning.

unless you're trying somehow to emphasise that both types of address are
supported, you could simplify the text to just:

The
.Ar dest-address
is used to find ...

jmc



Re: MPLS pseudowire over IPv6 1/2: ifconfig(8) diff

2018-12-23 Thread Denis Fondras
On Sat, Dec 22, 2018 at 11:42:36PM +0100, Klemens Nanni wrote:
> I have no clue about MPLS, so this feedback is code-wise only:
> 
> Did you consider using more AF agnostic code for parsing the IP address?
> 

You are right, it is simpler. Thank you for the clue :)

Updated diff :

Index: ifconfig.8
===
RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
retrieving revision 1.324
diff -u -p -r1.324 ifconfig.8
--- ifconfig.8  16 Nov 2018 12:25:29 -  1.324
+++ ifconfig.8  23 Dec 2018 09:25:36 -
@@ -1344,7 +1344,7 @@ is another 20-bit number which will be u
 Sets the destination address where this mpw should output.
 The
 .Ar dest-address
-is an IPv4 address that will be used to find the nexthop in the MPLS
+is an IPv4 or IPv6 address that will be used to find the nexthop in the MPLS
 network.
 .El
 .Sh PAIR
Index: ifconfig.c
===
RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
retrieving revision 1.387
diff -u -p -r1.387 ifconfig.c
--- ifconfig.c  29 Nov 2018 00:12:34 -  1.387
+++ ifconfig.c  23 Dec 2018 09:25:36 -
@@ -3802,8 +3802,9 @@ mpe_status(void)
 void
 mpw_status(void)
 {
-   struct sockaddr_in *sin;
-   struct ifmpwreq imr;
+   struct sockaddr_storage *ss;
+   struct ifmpwreq  imr;
+   char hbuf[NI_MAXHOST];
 
bzero(, sizeof(imr));
ifr.ifr_data = (caddr_t) 
@@ -3842,11 +3843,19 @@ mpw_status(void)
else
printf("remote %u\n", imr.imr_rshim.shim_label);
 
-   sin = (struct sockaddr_in *) _nexthop;
-   if (sin->sin_addr.s_addr == 0)
-   printf("\tneighbor: none\n");
-   else
-   printf("\tneighbor: %s\n", inet_ntoa(sin->sin_addr));
+   printf("\tneighbor: ");
+   switch (imr.imr_nexthop.ss_family) {
+   case AF_INET6:
+   case AF_INET:
+   ss = (struct sockaddr_storage *) _nexthop;
+   if (getnameinfo((struct sockaddr *)ss, ss->ss_len, hbuf,
+   sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
+   strlcpy(hbuf, "???", sizeof(hbuf));
+   printf("%s\n", hbuf);
+   break;
+   default:
+   printf("none\n");
+   }
 }
 
 /* ARGSUSED */
@@ -3870,6 +3879,7 @@ void
 process_mpw_commands(void)
 {
struct  sockaddr_in *sin, *sinn;
+   struct  sockaddr_in6 *sin6, *sin6n;
struct  ifmpwreq imr;
 
if (wconfig == 0)
@@ -3899,14 +3909,29 @@ process_mpw_commands(void)
imrsave.imr_rshim.shim_label = imr.imr_rshim.shim_label;
}
 
-   sin = (struct sockaddr_in *) _nexthop;
-   sinn = (struct sockaddr_in *) _nexthop;
-   if (sin->sin_addr.s_addr == 0) {
-   if (sinn->sin_addr.s_addr == 0)
+   switch (imrsave.imr_nexthop.ss_family) {
+   case AF_INET6:
+   case AF_INET:
+   /* neighbor was set earlier, nothing to do */
+   break;
+   default:
+   switch (imr.imr_nexthop.ss_family) {
+   case AF_INET6:
+   sin6 = (struct sockaddr_in6 *) _nexthop;
+   sin6n = (struct sockaddr_in6 *) _nexthop;
+   sin6->sin6_family = sin6n->sin6_family;
+   memcpy(>sin6_addr, >sin6_addr,
+   sizeof(struct in6_addr));
+   break;
+   case AF_INET:
+   sin = (struct sockaddr_in *) _nexthop;
+   sinn = (struct sockaddr_in *) _nexthop;
+   sin->sin_family = sinn->sin_family;
+   sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+   break;
+   default:
errx(1, "mpw neighbor address not specified");
-
-   sin->sin_family = sinn->sin_family;
-   sin->sin_addr.s_addr = sinn->sin_addr.s_addr;
+   }
}
 
ifr.ifr_data = (caddr_t) 
@@ -3949,14 +3974,41 @@ void
 setmpwneighbor(const char *value, int d)
 {
struct sockaddr_in *sin;
+   struct sockaddr_in6 *sin6;
+   struct addrinfo hints, *res;
+   int rv;
 
wconfig = 1;
 
-   sin = (struct sockaddr_in *) _nexthop;
-   if (inet_aton(value, >sin_addr) == 0)
+   memset(, 0, sizeof(hints));
+   hints.ai_family = AF_UNSPEC;
+   hints.ai_socktype = SOCK_DGRAM;
+   hints.ai_protocol = 0;
+   hints.ai_flags = AI_PASSIVE;
+
+   rv = getaddrinfo(value, NULL, , );
+   if (rv != 0)
+   errx(1, "neighbor %s: %s", value, gai_strerror(rv));
+
+   switch (res->ai_family) {
+   case AF_INET:
+   sin = (struct sockaddr_in *) _nexthop;
+   sin->sin_family = res->ai_family;
+   sin->sin_addr.s_addr =
+   ((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr;
+