diff options
Diffstat (limited to 'usr.sbin')
-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); } |