diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-09-27 14:37:39 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-09-27 14:37:39 +0000 |
commit | 27df79a3bb55ddf927c7d170e13484a61a4c83e9 (patch) | |
tree | 36155b8595481c6dcb4965f5c9722460e985c30a /usr.sbin/ospfd | |
parent | bf892e9aa654f770f43d0b73b184b8a18b409fb4 (diff) |
Use IP_RECVIF to get the incomming interface of OSPF packets. Now we use
the source address and the interface index to find the corresponding
struct interface which is less error prone. OK norby@
Diffstat (limited to 'usr.sbin/ospfd')
-rw-r--r-- | usr.sbin/ospfd/interface.c | 13 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.c | 5 | ||||
-rw-r--r-- | usr.sbin/ospfd/ospfe.h | 3 | ||||
-rw-r--r-- | usr.sbin/ospfd/packet.c | 84 |
4 files changed, 72 insertions, 33 deletions
diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c index acac1d35b64..112f022e37e 100644 --- a/usr.sbin/ospfd/interface.c +++ b/usr.sbin/ospfd/interface.c @@ -1,4 +1,4 @@ -/* $OpenBSD: interface.c,v 1.52 2006/08/18 11:54:28 claudio Exp $ */ +/* $OpenBSD: interface.c,v 1.53 2006/09/27 14:37:38 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -698,6 +698,17 @@ if_set_tos(int fd, int tos) return (0); } +int +if_set_recvif(int fd, int enable) +{ + if (setsockopt(fd, IPPROTO_IP, IP_RECVIF, &enable, + sizeof(enable)) < 0) { + log_warn("if_set_recvif: error setting IP_RECVIF"); + return (-1); + } + return (0); +} + void if_set_recvbuf(int fd) { diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c index 5d6bc467c10..59833170181 100644 --- a/usr.sbin/ospfd/ospfe.c +++ b/usr.sbin/ospfd/ospfe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.c,v 1.47 2006/06/02 18:49:55 norby Exp $ */ +/* $OpenBSD: ospfe.c,v 1.48 2006/09/27 14:37:38 claudio Exp $ */ /* * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> @@ -106,7 +106,8 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2], if (if_set_tos(xconf->ospf_socket, IPTOS_PREC_INTERNETCONTROL) == -1) fatal("if_set_tos"); - + if (if_set_recvif(xconf->ospf_socket, 1) == -1) + fatal("if_set_recvif"); if_set_recvbuf(xconf->ospf_socket); oeconf = xconf; diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h index 2f2e6282afc..5558892696a 100644 --- a/usr.sbin/ospfd/ospfe.h +++ b/usr.sbin/ospfd/ospfe.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ospfe.h,v 1.31 2006/06/02 18:49:55 norby Exp $ */ +/* $OpenBSD: ospfe.h,v 1.32 2006/09/27 14:37:38 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -147,6 +147,7 @@ int if_leave_group(struct iface *, struct in_addr *); int if_set_mcast(struct iface *); int if_set_mcast_ttl(int, u_int8_t); int if_set_tos(int, int); +int if_set_recvif(int, int); void if_set_recvbuf(int); int if_set_mcast_loop(int); diff --git a/usr.sbin/ospfd/packet.c b/usr.sbin/ospfd/packet.c index 2497d8fe519..e57b28375c1 100644 --- a/usr.sbin/ospfd/packet.c +++ b/usr.sbin/ospfd/packet.c @@ -1,4 +1,4 @@ -/* $OpenBSD: packet.c,v 1.20 2006/03/09 13:31:57 claudio Exp $ */ +/* $OpenBSD: packet.c,v 1.21 2006/09/27 14:37:38 claudio Exp $ */ /* * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org> @@ -18,11 +18,13 @@ #include <sys/types.h> #include <sys/socket.h> +#include <sys/uio.h> #include <netinet/in.h> #include <netinet/in_systm.h> #include <netinet/ip.h> #include <arpa/inet.h> +#include <net/if_dl.h> #include <errno.h> #include <event.h> @@ -37,7 +39,7 @@ int ip_hdr_sanity_check(const struct ip *, u_int16_t); int ospf_hdr_sanity_check(const struct ip *, struct ospf_hdr *, u_int16_t, const struct iface *); -struct iface *find_iface(struct ospfd_conf *, struct in_addr); +struct iface *find_iface(struct ospfd_conf *, unsigned int, struct in_addr); int gen_ospf_hdr(struct buf *buf, struct iface *iface, u_int8_t type) @@ -80,28 +82,51 @@ send_packet(struct iface *iface, void *pkt, size_t len, struct sockaddr_in *dst) void recv_packet(int fd, short event, void *bula) { - struct ospfd_conf *xconf = bula; + char cbuf[CMSG_SPACE(sizeof(struct sockaddr_dl))]; + struct msghdr msg; + struct iovec iov; struct ip ip_hdr; + struct in_addr addr; + struct ospfd_conf *xconf = bula; struct ospf_hdr *ospf_hdr; struct iface *iface; struct nbr *nbr = NULL; - struct in_addr addr; char *buf; + struct cmsghdr *cmsg; ssize_t r; u_int16_t len; int l; + unsigned int ifindex = 0; if (event != EV_READ) return; /* setup buffer */ - buf = pkt_ptr; - - if ((r = recvfrom(fd, buf, READ_BUF_SIZE, 0, NULL, NULL)) == -1) { + bzero(&msg, sizeof(msg)); + iov.iov_base = buf = pkt_ptr; + iov.iov_len = READ_BUF_SIZE; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + + if ((r = recvmsg(fd, &msg, 0)) == -1) { if (errno != EAGAIN && errno != EINTR) - log_debug("recv_packet: error receiving packet"); + log_debug("recv_packet: read error: %s", + strerror(errno)); return; } + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVIF) { + ifindex = ((struct sockaddr_dl *) + CMSG_DATA(cmsg))->sdl_index; + break; + } + } len = (u_int16_t)r; @@ -117,7 +142,7 @@ recv_packet(int fd, short event, void *bula) len -= l; /* find a matching interface */ - if ((iface = find_iface(xconf, ip_hdr.ip_src)) == NULL) { + if ((iface = find_iface(xconf, ifindex, ip_hdr.ip_src)) == NULL) { log_debug("recv_packet: cannot find valid interface"); return; } @@ -142,7 +167,7 @@ recv_packet(int fd, short event, void *bula) /* OSPF header sanity checks */ if (len < sizeof(*ospf_hdr)) { - log_warnx("recv_packet: bad packet size"); + log_debug("recv_packet: bad packet size"); return; } ospf_hdr = (struct ospf_hdr *)buf; @@ -262,7 +287,7 @@ ospf_hdr_sanity_check(const struct ip *ip_hdr, struct ospf_hdr *ospf_hdr, } struct iface * -find_iface(struct ospfd_conf *xconf, struct in_addr src) +find_iface(struct ospfd_conf *xconf, unsigned int ifindex, struct in_addr src) { struct area *area = NULL; struct iface *iface = NULL; @@ -270,27 +295,28 @@ find_iface(struct ospfd_conf *xconf, struct in_addr src) /* returned interface needs to be active */ LIST_FOREACH(area, &xconf->area_list, entry) { LIST_FOREACH(iface, &area->iface_list, entry) { - if (iface->fd > 0 && - (iface->type == IF_TYPE_POINTOPOINT) && - (iface->dst.s_addr == src.s_addr) && - !iface->passive) - return (iface); - - if (iface->fd > 0 && (iface->addr.s_addr & - iface->mask.s_addr) == (src.s_addr & - iface->mask.s_addr) && !iface->passive && - iface->type != IF_TYPE_VIRTUALLINK) { - return (iface); + switch (iface->type) { + case IF_TYPE_VIRTUALLINK: + if ((src.s_addr == iface->dst.s_addr) && + !iface->passive) + return (iface); + break; + case IF_TYPE_POINTOPOINT: + if (ifindex == iface->ifindex && + iface->dst.s_addr == src.s_addr && + !iface->passive) + return (iface); + break; + default: + if (ifindex == iface->ifindex && + (iface->addr.s_addr & iface->mask.s_addr) == + (src.s_addr & iface->mask.s_addr) && + !iface->passive) + return (iface); + break; } } } - LIST_FOREACH(area, &xconf->area_list, entry) - LIST_FOREACH(iface, &area->iface_list, entry) - if ((iface->type == IF_TYPE_VIRTUALLINK) && - (src.s_addr == iface->dst.s_addr)) { - return (iface); - } - return (NULL); } |