On Fri, Nov 15, 2019 at 06:06:42PM +0100, Remi Locherer wrote:
> On Mon, Nov 04, 2019 at 02:01:57PM +0200, Kapetanakis Giannis wrote:
> > On 25/10/2019 13:57, Remi Locherer wrote:
> > > Hi tech@,
> > >
> > > earlier this year I sent a diff that allowed to change an interface
> > > from broadcast to point-to-point.
> > >
> > > https://marc.info/?l=openbsd-tech&m=156132923203704&w=2
> > >
> > > It turned out that this was not sufficient. It made the adjacency
> > > come up in p2p mode (no selection of DR or BDR) but didn't set a valid
> > > next hop for routes learned over this p2p link. Actually the next hop was
> > > 0.0.0.0 which was never installed into the routing table.
> > >
> > > This is because for P2P interfaces the neighbor address is not taken from
> > > the received hello but from the "destination" parameter configured on the
> > > interface. Since this is not set on a broadcast interface the address is
> > > 0.0.0.0.
> > >
> > > My new diff changes this. Now also for P2P links the IP address of the
> > > neighbor is taken from the hello packets (src address). This on it's own
> > > would make it simpler to interfere with the routing from remote. One could
> > > send unicast ospf hello messages and potentially disrupt the routing 
> > > setup.
> > > I believe I mitigated this with an additional check I committed in August:
> > > only hello messages sent to the multicast address are now processed.
> > >
> > > The config looks like this:
> > >
> > > area 0.0.0.0 {
> > >   interface em0 {
> > >           type p2p
> > >   }
> > > }
> > >
> > > It would be nice to get test reports for this new feature (check the fib
> > > and routing table!) and also test reports with real p2p2 interfaces (gif
> > > or gre).
> > >
> > > Of course OKs are also welcome. ;-)
> > >
> > > Remi
> > 
> > 
> > Hi,
> > 
> > From first test seems to work :)
> > 
> > looking forward test it for IPv6 as well
> > 
> > thanks
> > 
> > Giannis
> 
> 
> Anyone willing to OK this?

See inline.

> Index: hello.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/hello.c,v
> retrieving revision 1.24
> diff -u -p -r1.24 hello.c
> --- hello.c   12 Aug 2019 20:21:58 -0000      1.24
> +++ hello.c   21 Sep 2019 22:06:17 -0000
> @@ -189,14 +189,13 @@ recv_hello(struct iface *iface, struct i
>               nbr->dr.s_addr = hello.d_rtr;
>               nbr->bdr.s_addr = hello.bd_rtr;
>               nbr->priority = hello.rtr_priority;
> -             /* XXX neighbor address shouldn't be stored on virtual links */
> -             nbr->addr.s_addr = src.s_addr;
> +             nbr_update_addr(nbr->peerid, src);
>       }
>  
>       if (nbr->addr.s_addr != src.s_addr) {
>               log_warnx("%s: neighbor ID %s changed its IP address",
>                   __func__, inet_ntoa(nbr->id));
> -             nbr->addr.s_addr = src.s_addr;
> +             nbr_update_addr(nbr->peerid, src);
>       }
>  
>       nbr->options = hello.opts;
> Index: lsupdate.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/lsupdate.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 lsupdate.c
> --- lsupdate.c        15 Jul 2019 18:26:39 -0000      1.46
> +++ lsupdate.c        15 Aug 2019 21:10:13 -0000
> @@ -470,7 +470,7 @@ ls_retrans_timer(int fd, short event, vo
>                       /* ls_retrans_list_free retriggers the timer */
>                       return;
>               } else if (nbr->iface->type == IF_TYPE_POINTOPOINT)
> -                     memcpy(&addr, &nbr->iface->dst, sizeof(addr));
> +                     memcpy(&addr, &nbr->addr, sizeof(addr));
>               else
>                       inet_aton(AllDRouters, &addr);
>       } else
> Index: neighbor.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/neighbor.c,v
> retrieving revision 1.48
> diff -u -p -r1.48 neighbor.c
> --- neighbor.c        9 Feb 2018 02:14:03 -0000       1.48
> +++ neighbor.c        21 Sep 2019 15:28:43 -0000
> @@ -312,6 +312,7 @@ nbr_new(u_int32_t nbr_id, struct iface *
>       bzero(&rn, sizeof(rn));
>       rn.id.s_addr = nbr->id.s_addr;
>       rn.area_id.s_addr = nbr->iface->area->id.s_addr;
> +     rn.addr.s_addr = nbr->addr.s_addr;
>       rn.ifindex = nbr->iface->ifindex;
>       rn.state = nbr->state;
>       rn.self = self;
> @@ -347,6 +348,23 @@ nbr_del(struct nbr *nbr)
>       LIST_REMOVE(nbr, hash);
>  
>       free(nbr);
> +}
> +
> +int

Since the callers of nbr_update_addr() don't use the return value make
this a void function.

> +nbr_update_addr(u_int32_t peerid, struct in_addr addr) {
> +

Fix bad placement of {

> +     struct nbr              *nbr = NULL;
> +
> +     nbr = nbr_find_peerid(peerid);
> +     if (nbr == NULL)
> +             return (1);

Why passing peerid to this function to look up the neighbor again when the
functions are called like this?
                nbr_update_addr(nbr->peerid, src);

Why not just pass struct nbr *nbr? Would also remove a possible error case.

> +
> +     /* XXX neighbor address shouldn't be stored on virtual links */
> +     nbr->addr.s_addr = addr.s_addr;
> +     ospfe_imsg_compose_rde(IMSG_NEIGHBOR_ADDR, peerid, 0, &addr,
> +         sizeof(addr));

Another option is to just add this ospfe_imsg_compose_rde() to the two
places where the addr is updated.

> +
> +     return (0);
>  }
>  
>  struct nbr *
> Index: ospfd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/ospfd.c,v
> retrieving revision 1.108
> diff -u -p -r1.108 ospfd.c
> --- ospfd.c   16 May 2019 05:49:22 -0000      1.108
> +++ ospfd.c   23 Jun 2019 21:06:44 -0000
> @@ -911,6 +911,22 @@ merge_interfaces(struct area *a, struct 
>                               if_fsm(i, IF_EVT_UP);
>               }
>  
> +             if (i->p2p != xi->p2p) {
> +                     /* re-add interface to enable or disable DR election */
> +                     if (ospfd_process == PROC_OSPF_ENGINE)
> +                             if_fsm(i, IF_EVT_DOWN);
> +                     else if (ospfd_process == PROC_RDE_ENGINE)
> +                             rde_nbr_iface_del(i);
> +                     LIST_REMOVE(i, entry);
> +                     if_del(i);
> +                     LIST_REMOVE(xi, entry);
> +                     LIST_INSERT_HEAD(&a->iface_list, xi, entry);
> +                     xi->area = a;
> +                     if (ospfd_process == PROC_OSPF_ENGINE)
> +                             xi->state = IF_STA_NEW;
> +                     continue;
> +             }

This is one big hammer. Would be nice to be a bit softer, also should this
code be before
                log_debug("merge_interfaces: proc %d area %s merging "
                    "interface %s", ospfd_process, inet_ntoa(a->id), i->name);

Since it re-adds an interface. If so it should also have its own
log_debug(). At least I think it makes little sense to merge most of the
interface to just remove it and re-add it.

> +
>               strlcpy(i->dependon, xi->dependon,
>                       sizeof(i->dependon));
>               i->depend_ok = xi->depend_ok;

Unrelated but I feel this code should be moved up before
                if (i->passive != xi->passive) {
                        ...
                }

> Index: ospfd.conf.5
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/ospfd.conf.5,v
> retrieving revision 1.57
> diff -u -p -r1.57 ospfd.conf.5
> --- ospfd.conf.5      10 Jun 2019 06:07:15 -0000      1.57
> +++ ospfd.conf.5      23 Jun 2019 22:10:32 -0000
> @@ -419,6 +419,9 @@ Router.
>  .It Ic transmit-delay Ar seconds
>  Set the transmit delay.
>  The default value is 1; valid range is 1\-3600 seconds.
> +.It Ic type p2p
> +Set the interface type to point to point.
> +This disables the election of a DR and BDR for the given interface.
>  .El
>  .Sh FILES
>  .Bl -tag -width "/etc/ospfd.conf" -compact
> Index: ospfd.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/ospfd.h,v
> retrieving revision 1.104
> diff -u -p -r1.104 ospfd.h
> --- ospfd.h   16 May 2019 05:49:22 -0000      1.104
> +++ ospfd.h   21 Sep 2019 10:25:32 -0000
> @@ -107,6 +107,7 @@ enum imsg_type {
>       IMSG_IFINFO,
>       IMSG_NEIGHBOR_UP,
>       IMSG_NEIGHBOR_DOWN,
> +     IMSG_NEIGHBOR_ADDR,
>       IMSG_NEIGHBOR_CHANGE,
>       IMSG_NEIGHBOR_CAPA,
>       IMSG_NETWORK_ADD,
> @@ -363,6 +364,7 @@ struct iface {
>       u_int8_t                 linkstate;
>       u_int8_t                 priority;
>       u_int8_t                 passive;
> +     u_int8_t                 p2p;
>  };
>  
>  struct ifaddrchange {
> Index: ospfe.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/ospfe.h,v
> retrieving revision 1.46
> diff -u -p -r1.46 ospfe.h
> --- ospfe.h   25 Oct 2014 03:23:49 -0000      1.46
> +++ ospfe.h   21 Sep 2019 15:27:08 -0000
> @@ -204,6 +204,7 @@ void               lsa_cache_put(struct lsa_ref *, s
>  void          nbr_init(u_int32_t);
>  struct nbr   *nbr_new(u_int32_t, struct iface *, int);
>  void          nbr_del(struct nbr *);
> +int           nbr_update_addr(u_int32_t, struct in_addr);
>  
>  struct nbr   *nbr_find_id(struct iface *, u_int32_t);
>  struct nbr   *nbr_find_peerid(u_int32_t);
> Index: parse.y
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/parse.y,v
> retrieving revision 1.98
> diff -u -p -r1.98 parse.y
> --- parse.y   7 Jun 2019 04:57:45 -0000       1.98
> +++ parse.y   24 Oct 2019 20:09:11 -0000
> @@ -129,7 +129,7 @@ typedef struct {
>  %token       AREA INTERFACE ROUTERID FIBPRIORITY FIBUPDATE REDISTRIBUTE 
> RTLABEL
>  %token       RDOMAIN RFC1583COMPAT STUB ROUTER SPFDELAY SPFHOLDTIME EXTTAG
>  %token       AUTHKEY AUTHTYPE AUTHMD AUTHMDKEYID
> -%token       METRIC PASSIVE
> +%token       METRIC P2P PASSIVE
>  %token       HELLOINTERVAL FASTHELLOINTERVAL TRANSMITDELAY
>  %token       RETRANSMITINTERVAL ROUTERDEADTIME ROUTERPRIORITY
>  %token       SET TYPE
> @@ -743,6 +743,10 @@ interfaceopts_l  : interfaceopts_l interf
>               ;
>  
>  interfaceoptsl       : PASSIVE               { iface->passive = 1; }
> +             | TYPE P2P              {
> +                     iface->p2p = 1;
> +                     iface->type = IF_TYPE_POINTOPOINT;
> +             }
>               | DEMOTE STRING         {
>                       if (strlcpy(iface->demote_group, $2,
>                           sizeof(iface->demote_group)) >=
> @@ -833,6 +837,7 @@ lookup(char *s)
>               {"msec",                MSEC},
>               {"no",                  NO},
>               {"on",                  ON},
> +             {"p2p",                 P2P},
>               {"passive",             PASSIVE},
>               {"rdomain",             RDOMAIN},
>               {"redistribute",        REDISTRIBUTE},
> Index: printconf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/printconf.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 printconf.c
> --- printconf.c       28 Dec 2018 19:25:10 -0000      1.20
> +++ printconf.c       23 Jun 2019 22:05:55 -0000
> @@ -149,6 +149,9 @@ print_iface(struct iface *iface)
>               printf("\t\trouter-priority %d\n", iface->priority);
>               printf("\t\ttransmit-delay %d\n", iface->transmit_delay);
>  
> +             if (iface->p2p)
> +                     printf("\t\ttype p2p\n");
> +
>               printf("\t\tauth-type %s\n", if_auth_name(iface->auth_type));
>               switch (iface->auth_type) {
>               case AUTH_TYPE_NONE:
> Index: rde.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/rde.c,v
> retrieving revision 1.109
> diff -u -p -r1.109 rde.c
> --- rde.c     5 Feb 2018 12:11:28 -0000       1.109
> +++ rde.c     21 Sep 2019 12:17:09 -0000
> @@ -257,6 +257,7 @@ rde_dispatch_imsg(int fd, short event, v
>       struct timespec          tp;
>       struct lsa              *lsa;
>       struct area             *area;
> +     struct in_addr           addr;
>       struct vertex           *v;
>       char                    *buf;
>       ssize_t                  n;
> @@ -300,6 +301,17 @@ rde_dispatch_imsg(int fd, short event, v
>                       break;
>               case IMSG_NEIGHBOR_DOWN:
>                       rde_nbr_del(rde_nbr_find(imsg.hdr.peerid));
> +                     break;
> +             case IMSG_NEIGHBOR_ADDR:
> +                     if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr))
> +                             fatalx("invalid size of OE request");
> +                     memcpy(&addr, imsg.data, sizeof(addr));
> +
> +                     nbr = rde_nbr_find(imsg.hdr.peerid);
> +                     if (nbr == NULL)
> +                             break;
> +
> +                     nbr->addr.s_addr = addr.s_addr;
>                       break;
>               case IMSG_NEIGHBOR_CHANGE:
>                       if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
> Index: rde.h
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/rde.h,v
> retrieving revision 1.39
> diff -u -p -r1.39 rde.h
> --- rde.h     14 Mar 2015 02:22:09 -0000      1.39
> +++ rde.h     19 Sep 2019 13:46:43 -0000
> @@ -66,6 +66,7 @@ struct rde_nbr {
>       LIST_ENTRY(rde_nbr)              entry, hash;
>       struct in_addr                   id;
>       struct in_addr                   area_id;
> +     struct in_addr                   addr;
>       TAILQ_HEAD(, rde_req_entry)      req_list;
>       struct area                     *area;
>       struct iface                    *iface;
> Index: rde_spf.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/ospfd/rde_spf.c,v
> retrieving revision 1.77
> diff -u -p -r1.77 rde_spf.c
> --- rde_spf.c 4 Apr 2019 19:57:08 -0000       1.77
> +++ rde_spf.c 29 Sep 2019 21:08:49 -0000
> @@ -373,6 +373,7 @@ calc_nexthop(struct vertex *dst, struct 
>  {
>       struct v_nexthop        *vn;
>       struct iface            *iface;
> +     struct rde_nbr          *nbr;
>       int                      i;
>  
>       /* case 1 */
> @@ -382,10 +383,14 @@ calc_nexthop(struct vertex *dst, struct 
>                       if (rtr_link->type != LINK_TYPE_POINTTOPOINT)
>                               fatalx("inconsistent SPF tree");
>                       LIST_FOREACH(iface, &area->iface_list, entry) {
> -                             if (rtr_link->data == iface->addr.s_addr) {
> -                                     vertex_nexthop_add(dst, parent,
> -                                         iface->dst.s_addr);
> -                                     return;
> +                             if (rtr_link->data != iface->addr.s_addr)
> +                                     continue;
> +                             LIST_FOREACH(nbr, &area->nbr_list, entry) {
> +                                     if (nbr->ifindex == iface->ifindex) {
> +                                             vertex_nexthop_add(dst, parent,
> +                                                 nbr->addr.s_addr);
> +                                             return;
> +                                     }
>                               }
>                       }
>                       fatalx("no interface found for interface");
> 

Apart for the comments about nbr_update_addr() this diff is fine by me.

-- 
:wq Claudio

Reply via email to