The code in ospf6d is a bit broken when it comes to point-to-point links.
This diff fixes this by a) using the neighbor address instead of the unset
interface destination address and by b) matching the incomming packet
against all possible IPs of that interface.

I tripped on b) because my P2P interface has more than one link-local
address and the code just likes to select the wrong one.

This works for my case, please check I did not break something else.
-- 
:wq Claudio

Index: lsupdate.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/lsupdate.c,v
retrieving revision 1.18
diff -u -p -r1.18 lsupdate.c
--- lsupdate.c  15 Jul 2020 14:47:41 -0000      1.18
+++ lsupdate.c  6 Jan 2021 11:28:43 -0000
@@ -474,7 +474,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_pton(AF_INET6, AllDRouters, &addr);
        } else
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/packet.c,v
retrieving revision 1.17
diff -u -p -r1.17 packet.c
--- packet.c    23 Dec 2019 07:33:49 -0000      1.17
+++ packet.c    6 Jan 2021 11:52:08 -0000
@@ -82,12 +82,9 @@ send_packet(struct iface *iface, struct 
     struct in6_addr *dst)
 {
        struct sockaddr_in6     sa6;
-       struct msghdr           msg;
-       struct iovec            iov[1];
 
-       /* setup buffer */
+       /* setup sockaddr */
        bzero(&sa6, sizeof(sa6));
-
        sa6.sin6_family = AF_INET6;
        sa6.sin6_len = sizeof(sa6);
        sa6.sin6_addr = *dst;
@@ -104,15 +101,8 @@ send_packet(struct iface *iface, struct 
                        return (-1);
                }
 
-       bzero(&msg, sizeof(msg));
-       msg.msg_name = &sa6;
-       msg.msg_namelen = sizeof(sa6);
-       iov[0].iov_base = buf->buf;
-       iov[0].iov_len = ibuf_size(buf);
-       msg.msg_iov = iov;
-       msg.msg_iovlen = 1;
-
-       if (sendmsg(iface->fd, &msg, 0) == -1) {
+       if (sendto(iface->fd, buf->buf, ibuf_size(buf), 0,
+           (struct sockaddr *)&sa6, sizeof(sa6)) == -1) {
                log_warn("send_packet: error sending packet on interface %s",
                    iface->name);
                return (-1);
@@ -186,11 +176,16 @@ recv_packet(int fd, short event, void *b
         * AllDRouters is only valid for DR and BDR but this is checked later.
         */
        inet_pton(AF_INET6, AllSPFRouters, &addr);
-
        if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) {
                inet_pton(AF_INET6, AllDRouters, &addr);
                if (!IN6_ARE_ADDR_EQUAL(&dest, &addr)) {
-                       if (!IN6_ARE_ADDR_EQUAL(&dest, &iface->addr)) {
+                       struct iface_addr *ia;
+
+                       TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
+                               if (IN6_ARE_ADDR_EQUAL(&dest, &ia->addr))
+                                       break;
+                       }
+                       if (ia == NULL) {
                                log_debug("recv_packet: packet sent to wrong "
                                    "address %s, interface %s",
                                    log_in6addr(&dest), iface->name);

Reply via email to