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);