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



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
+nbr_update_addr(u_int32_t peerid, struct in_addr addr) {
+
+       struct nbr              *nbr = NULL;
+
+       nbr = nbr_find_peerid(peerid);
+       if (nbr == NULL)
+               return (1);
+
+       /* 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));
+
+       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;
+               }
+
                strlcpy(i->dependon, xi->dependon,
                        sizeof(i->dependon));
                i->depend_ok = xi->depend_ok;
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");

Reply via email to