summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ospfd/interface.c13
-rw-r--r--usr.sbin/ospfd/ospfe.c5
-rw-r--r--usr.sbin/ospfd/ospfe.h3
-rw-r--r--usr.sbin/ospfd/packet.c84
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);
}