summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/ChangeLog7
-rw-r--r--zebra/rtadv.c40
2 files changed, 27 insertions, 20 deletions
diff --git a/zebra/ChangeLog b/zebra/ChangeLog
index 718de625..5adcbcee 100644
--- a/zebra/ChangeLog
+++ b/zebra/ChangeLog
@@ -1,3 +1,10 @@
+2004-08-11 Greg Troxel <gdt@fnord.ir.bbn.com>
+
+ * rtadv.c (rtadv_send_packet): Allocate space for control messages
+ more carefully; it was wrong on NetBSD/sparc where CMSG alignment
+ is to 8 bytes instead of 4, and overwriting the address. Use the
+ provided macros for determining lengths.
+
2004-07-23 Sowmini Varadhan <Sowmini.Varadhan@Sun.COM>
* if_ioctl_solaris.c: HAVE_IPV6 ifdef fixups
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index c95e75d8..082a1b36 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -157,14 +157,7 @@ rtadv_send_packet (int sock, struct interface *ifp)
#ifdef HAVE_SOCKADDR_DL
struct sockaddr_dl *sdl;
#endif /* HAVE_SOCKADDR_DL */
- /*
- * XXX: Alignment padding follows cmsghdr, and there is not
- * necessarily a portable way to determine this. Add 16 bytes as a
- * pessimistic assumption. (NetBSD/i386 aligns to 4, and
- * NetBSD/sparc to 8.) Note check below that buf is not
- * overwritten. A better fix is needed.
- */
- char adata [sizeof (struct cmsghdr) + 16 + sizeof (struct in6_pktinfo)];
+ static void *adata = NULL;
unsigned char buf[RTADV_MSG_SIZE];
struct nd_router_advert *rtadv;
int ret;
@@ -173,6 +166,21 @@ rtadv_send_packet (int sock, struct interface *ifp)
u_char all_nodes_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
listnode node;
+ /*
+ * Allocate control message bufffer. This is dynamic because
+ * CMSG_SPACE is not guaranteed not to call a function. Note that
+ * the size will be different on different architectures due to
+ * differing alignment rules.
+ */
+ if (adata == NULL)
+ {
+ /* XXX Free on shutdown. */
+ adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
+
+ if (adata == NULL)
+ zlog_err("rtadv_send_packet: can't malloc control data\n");
+ }
+
/* Logging of packet. */
if (IS_ZEBRA_DEBUG_PACKET)
zlog_info ("Router advertisement send to %s", ifp->name);
@@ -275,25 +283,17 @@ rtadv_send_packet (int sock, struct interface *ifp)
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = (void *) adata;
- msg.msg_controllen = sizeof adata;
- msg.msg_flags = MSG_DONTROUTE;
+ msg.msg_controllen = CMSG_LEN(sizeof(struct in6_pktinfo));
+ msg.msg_flags = 0;
iov.iov_base = buf;
iov.iov_len = len;
- cmsgptr = (struct cmsghdr *)adata;
- cmsgptr->cmsg_len = sizeof adata;
+ cmsgptr = CMSG_FIRSTHDR(&msg);
+ cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsgptr->cmsg_level = IPPROTO_IPV6;
cmsgptr->cmsg_type = IPV6_PKTINFO;
- /* XXX Check that we do not overwrite buf. */
pkt = (struct in6_pktinfo *) CMSG_DATA (cmsgptr);
- if ((void *) &pkt->ipi6_ifindex + sizeof(pkt->ipi6_ifindex)
- > (void *) &addr)
- {
- zlog_err ("rtadv_send_packet: NOT overwriting address\n");
- return;
- }
-
memset (&pkt->ipi6_addr, 0, sizeof (struct in6_addr));
pkt->ipi6_ifindex = ifp->ifindex;