summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospfd/interface.c159
-rw-r--r--usr.sbin/ospfd/kroute.c124
-rw-r--r--usr.sbin/ospfd/ospfd.h11
-rw-r--r--usr.sbin/ospfd/ospfe.c11
-rw-r--r--usr.sbin/ospfd/ospfe.h7
-rw-r--r--usr.sbin/ospfd/packet.c39
-rw-r--r--usr.sbin/ospfd/parse.y41
7 files changed, 253 insertions, 139 deletions
diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c
index 112f022e37e..f2e952e137a 100644
--- a/usr.sbin/ospfd/interface.c
+++ b/usr.sbin/ospfd/interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.c,v 1.53 2006/09/27 14:37:38 claudio Exp $ */
+/* $OpenBSD: interface.c,v 1.54 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -148,12 +148,9 @@ if_fsm(struct iface *iface, enum iface_event event)
}
struct iface *
-if_new(struct kif *kif)
+if_new(struct kif *kif, struct kif_addr *ka)
{
- struct sockaddr_in *sain;
struct iface *iface;
- struct ifreq *ifr;
- int s;
if ((iface = calloc(1, sizeof(*iface))) == NULL)
err(1, "if_new: calloc");
@@ -177,14 +174,6 @@ if_new(struct kif *kif)
strlcpy(iface->name, kif->ifname, sizeof(iface->name));
- if ((ifr = calloc(1, sizeof(*ifr))) == NULL)
- err(1, "if_new: calloc");
-
- /* set up ifreq */
- strlcpy(ifr->ifr_name, kif->ifname, sizeof(ifr->ifr_name));
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- err(1, "if_new: socket");
-
/* get type */
if (kif->flags & IFF_POINTOPOINT)
iface->type = IF_TYPE_POINTOPOINT;
@@ -203,29 +192,13 @@ if_new(struct kif *kif)
iface->linkstate = kif->link_state;
iface->media_type = kif->media_type;
- /* get address */
- if (ioctl(s, SIOCGIFADDR, ifr) < 0)
- err(1, "if_new: cannot get address");
- sain = (struct sockaddr_in *)&ifr->ifr_addr;
- iface->addr = sain->sin_addr;
-
- /* get mask */
- if (ioctl(s, SIOCGIFNETMASK, ifr) < 0)
- err(1, "if_new: cannot get mask");
- sain = (struct sockaddr_in *)&ifr->ifr_addr;
- iface->mask = sain->sin_addr;
-
- /* get p2p dst address */
+ /* set address, mask and p2p addr */
+ iface->addr = ka->addr;
+ iface->mask = ka->mask;
if (kif->flags & IFF_POINTOPOINT) {
- if (ioctl(s, SIOCGIFDSTADDR, ifr) < 0)
- err(1, "if_new: cannot get dst addr");
- sain = (struct sockaddr_in *)&ifr->ifr_addr;
- iface->dst = sain->sin_addr;
+ iface->dst = ka->dstbrd;
}
- free(ifr);
- close(s);
-
return (iface);
}
@@ -355,11 +328,8 @@ if_act_start(struct iface *iface)
switch (iface->type) {
case IF_TYPE_POINTOPOINT:
inet_aton(AllSPFRouters, &addr);
- if (if_join_group(iface, &addr)) {
- log_warnx("if_act_start: error joining group %s, "
- "interface %s", inet_ntoa(addr), iface->name);
+ if (if_join_group(iface, &addr))
return (-1);
- }
iface->state = IF_STA_POINTTOPOINT;
break;
case IF_TYPE_VIRTUALLINK:
@@ -372,11 +342,8 @@ if_act_start(struct iface *iface)
return (-1);
case IF_TYPE_BROADCAST:
inet_aton(AllSPFRouters, &addr);
- if (if_join_group(iface, &addr)) {
- log_warnx("if_act_start: error joining group %s, "
- "interface %s", inet_ntoa(addr), iface->name);
+ if (if_join_group(iface, &addr))
return (-1);
- }
if (iface->priority == 0) {
iface->state = IF_STA_DROTHER;
} else {
@@ -513,20 +480,12 @@ start:
inet_aton(AllDRouters, &addr);
if (old_state & IF_STA_DRORBDR &&
(iface->state & IF_STA_DRORBDR) == 0) {
- if (if_leave_group(iface, &addr)) {
- log_warnx("if_act_elect: "
- "error leaving group %s, interface %s",
- inet_ntoa(addr), iface->name);
+ if (if_leave_group(iface, &addr))
return (-1);
- }
} else if ((old_state & IF_STA_DRORBDR) == 0 &&
iface->state & IF_STA_DRORBDR) {
- if (if_join_group(iface, &addr)) {
- log_warnx("if_act_elect: "
- "error joining group %s, interface %s",
- inet_ntoa(addr), iface->name);
+ if (if_join_group(iface, &addr))
return (-1);
- }
}
LIST_FOREACH(nbr, &iface->nbr_list, entry) {
@@ -674,31 +633,6 @@ if_to_ctl(struct iface *iface)
/* misc */
int
-if_set_mcast_ttl(int fd, u_int8_t ttl)
-{
- if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
- (char *)&ttl, sizeof(ttl)) < 0) {
- log_warn("if_set_mcast_ttl: error setting "
- "IP_MULTICAST_TTL to %d", ttl);
- return (-1);
- }
-
- return (0);
-}
-
-int
-if_set_tos(int fd, int tos)
-{
- if (setsockopt(fd, IPPROTO_IP, IP_TOS,
- (int *)&tos, sizeof(tos)) < 0) {
- log_warn("if_set_tos: error setting IP_TOS to 0x%x", tos);
- return (-1);
- }
-
- return (0);
-}
-
-int
if_set_recvif(int fd, int enable)
{
if (setsockopt(fd, IPPROTO_IP, IP_RECVIF, &enable,
@@ -720,21 +654,52 @@ if_set_recvbuf(int fd)
bsize /= 2;
}
+/*
+ * only one JOIN or DROP per interface and address is allowed so we need
+ * to keep track of what is added and removed.
+ */
+struct if_group_count {
+ LIST_ENTRY(if_group_count) entry;
+ struct in_addr addr;
+ unsigned int ifindex;
+ int count;
+};
+
+LIST_HEAD(,if_group_count) ifglist = LIST_HEAD_INITIALIZER(ifglist);
+
int
if_join_group(struct iface *iface, struct in_addr *addr)
{
- struct ip_mreq mreq;
+ struct ip_mreq mreq;
+ struct if_group_count *ifg;
switch (iface->type) {
case IF_TYPE_POINTOPOINT:
case IF_TYPE_BROADCAST:
+ LIST_FOREACH(ifg, &ifglist, entry)
+ if (iface->ifindex == ifg->ifindex &&
+ addr->s_addr == ifg->addr.s_addr)
+ break;
+ if (ifg == NULL) {
+ if ((ifg = calloc(1, sizeof(*ifg))) == NULL)
+ fatal("if_join_group");
+ ifg->addr.s_addr = addr->s_addr;
+ ifg->ifindex = iface->ifindex;
+ LIST_INSERT_HEAD(&ifglist, ifg, entry);
+ }
+
+ if (ifg->count++ != 0)
+ /* already joined */
+ return (0);
+
mreq.imr_multiaddr.s_addr = addr->s_addr;
mreq.imr_interface.s_addr = iface->addr.s_addr;
if (setsockopt(iface->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
(void *)&mreq, sizeof(mreq)) < 0) {
- log_debug("if_join_group: error IP_ADD_MEMBERSHIP, "
- "interface %s", iface->name);
+ log_warn("if_join_group: error IP_ADD_MEMBERSHIP, "
+ "interface %s address %s", iface->name,
+ inet_ntoa(*addr));
return (-1);
}
break;
@@ -754,20 +719,37 @@ if_join_group(struct iface *iface, struct in_addr *addr)
int
if_leave_group(struct iface *iface, struct in_addr *addr)
{
- struct ip_mreq mreq;
+ struct ip_mreq mreq;
+ struct if_group_count *ifg;
switch (iface->type) {
case IF_TYPE_POINTOPOINT:
case IF_TYPE_BROADCAST:
+ LIST_FOREACH(ifg, &ifglist, entry)
+ if (iface->ifindex == ifg->ifindex &&
+ addr->s_addr == ifg->addr.s_addr)
+ break;
+
+ /* if interface is not found just try to drop membership */
+ if (ifg && --ifg->count != 0)
+ /* others still joined */
+ return (0);
+
mreq.imr_multiaddr.s_addr = addr->s_addr;
mreq.imr_interface.s_addr = iface->addr.s_addr;
if (setsockopt(iface->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
(void *)&mreq, sizeof(mreq)) < 0) {
- log_debug("if_leave_group: error IP_DROP_MEMBERSHIP, "
- "interface %s", iface->name);
+ log_warn("if_leave_group: error IP_DROP_MEMBERSHIP, "
+ "interface %s address %s", iface->name,
+ inet_ntoa(*addr));
return (-1);
}
+
+ if (ifg) {
+ LIST_REMOVE(ifg, entry);
+ free(ifg);
+ }
break;
case IF_TYPE_POINTOMULTIPOINT:
case IF_TYPE_VIRTUALLINK:
@@ -821,3 +803,16 @@ if_set_mcast_loop(int fd)
return (0);
}
+
+int
+if_set_ip_hdrincl(int fd)
+{
+ int hincl = 1;
+
+ if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof(hincl)) < 0) {
+ log_warn("if_set_ip_hdrincl: error setting IP_HDRINCL");
+ return (-1);
+ }
+
+ return (0);
+}
diff --git a/usr.sbin/ospfd/kroute.c b/usr.sbin/ospfd/kroute.c
index f85c9b24e4f..a33f91688f1 100644
--- a/usr.sbin/ospfd/kroute.c
+++ b/usr.sbin/ospfd/kroute.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kroute.c,v 1.34 2006/11/16 15:55:29 henning Exp $ */
+/* $OpenBSD: kroute.c,v 1.35 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -54,6 +54,7 @@ struct kroute_node {
struct kif_node {
RB_ENTRY(kif_node) entry;
+ TAILQ_HEAD(, kif_addr) addrs;
struct kif k;
};
@@ -488,13 +489,24 @@ kif_find(int ifindex)
}
struct kif *
-kif_findname(char *ifname)
+kif_findname(char *ifname, struct in_addr addr, struct kif_addr **kap)
{
struct kif_node *kif;
+ struct kif_addr *ka;
RB_FOREACH(kif, kif_tree, &kit)
- if (!strcmp(ifname, kif->k.ifname))
+ if (!strcmp(ifname, kif->k.ifname)) {
+ ka = TAILQ_FIRST(&kif->addrs);
+ if (addr.s_addr != 0) {
+ TAILQ_FOREACH(ka, &kif->addrs, entry) {
+ if (addr.s_addr == ka->addr.s_addr)
+ break;
+ }
+ }
+ if (kap != NULL)
+ *kap = ka;
return (&kif->k);
+ }
return (NULL);
}
@@ -514,11 +526,17 @@ kif_insert(struct kif_node *kif)
int
kif_remove(struct kif_node *kif)
{
+ struct kif_addr *ka;
+
if (RB_REMOVE(kif_tree, &kit, kif) == NULL) {
log_warnx("RB_REMOVE(kif_tree, &kit, kif)");
return (-1);
}
+ while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) {
+ TAILQ_REMOVE(&kif->addrs, ka, entry);
+ free(ka);
+ }
free(kif);
return (0);
}
@@ -894,10 +912,14 @@ fetchifs(int ifindex)
size_t len;
int mib[6];
char *buf, *next, *lim;
- struct if_msghdr ifm;
- struct kif_node *kif;
+ struct rt_msghdr *rtm;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct kif_node *kif = NULL;
+ struct kif_addr *kaddr;
struct sockaddr *sa, *rti_info[RTAX_MAX];
struct sockaddr_dl *sdl;
+ struct sockaddr_in *sain;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
@@ -921,32 +943,37 @@ fetchifs(int ifindex)
}
lim = buf + len;
- for (next = buf; next < lim; next += ifm.ifm_msglen) {
- memcpy(&ifm, next, sizeof(ifm));
- if (ifm.ifm_type != RTM_IFINFO)
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (rtm->rtm_version != RTM_VERSION)
continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)rtm;
+ sa = (struct sockaddr *)(next + sizeof(*ifm));
+ get_rtaddrs(ifm->ifm_addrs, sa, rti_info);
- sa = (struct sockaddr *)(next + sizeof(ifm));
- get_rtaddrs(ifm.ifm_addrs, sa, rti_info);
-
- if ((kif = calloc(1, sizeof(struct kif_node))) == NULL) {
- log_warn("fetchifs");
- free(buf);
- return (-1);
- }
+ if ((kif = calloc(1, sizeof(struct kif_node))) ==
+ NULL) {
+ log_warn("fetchifs");
+ free(buf);
+ return (-1);
+ }
- kif->k.ifindex = ifm.ifm_index;
- kif->k.flags = ifm.ifm_flags;
- kif->k.link_state = ifm.ifm_data.ifi_link_state;
- kif->k.media_type = ifm.ifm_data.ifi_type;
- kif->k.baudrate = ifm.ifm_data.ifi_baudrate;
- kif->k.mtu = ifm.ifm_data.ifi_mtu;
- kif->k.nh_reachable = (kif->k.flags & IFF_UP) &&
- (ifm.ifm_data.ifi_link_state == LINK_STATE_UP ||
- (ifm.ifm_data.ifi_link_state == LINK_STATE_UNKNOWN &&
- ifm.ifm_data.ifi_type != IFT_CARP));
- if ((sa = rti_info[RTAX_IFP]) != NULL)
- if (sa->sa_family == AF_LINK) {
+ kif->k.ifindex = ifm->ifm_index;
+ kif->k.flags = ifm->ifm_flags;
+ kif->k.link_state = ifm->ifm_data.ifi_link_state;
+ kif->k.media_type = ifm->ifm_data.ifi_type;
+ kif->k.baudrate = ifm->ifm_data.ifi_baudrate;
+ kif->k.mtu = ifm->ifm_data.ifi_mtu;
+ kif->k.nh_reachable = (kif->k.flags & IFF_UP) &&
+ (ifm->ifm_data.ifi_link_state == LINK_STATE_UP ||
+ (ifm->ifm_data.ifi_link_state ==
+ LINK_STATE_UNKNOWN &&
+ ifm->ifm_data.ifi_type != IFT_CARP));
+ TAILQ_INIT(&kif->addrs);
+ if ((sa = rti_info[RTAX_IFP]) != NULL &&
+ sa->sa_family == AF_LINK) {
sdl = (struct sockaddr_dl *)sa;
if (sdl->sdl_nlen >= sizeof(kif->k.ifname))
memcpy(kif->k.ifname, sdl->sdl_data,
@@ -957,7 +984,46 @@ fetchifs(int ifindex)
/* string already terminated via calloc() */
}
- kif_insert(kif);
+ kif_insert(kif);
+ break;
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+ if (kif && ifam->ifam_index != kif->k.ifindex)
+ fatalx("fetchifs: bad interafce table");
+ if (kif == NULL || (ifam->ifam_addrs &
+ (RTA_NETMASK | RTA_IFA | RTA_BRD)) == 0)
+ break;
+ sa = (struct sockaddr *)(next + sizeof(*ifam));
+ get_rtaddrs(ifam->ifam_addrs, sa, rti_info);
+
+ if ((sa = rti_info[RTAX_IFA]) != NULL &&
+ sa->sa_family == AF_INET) {
+ if ((kaddr = calloc(1,
+ sizeof(struct kif_addr))) == NULL) {
+ log_warn("fetchifs");
+ free(buf);
+ return (-1);
+ }
+
+ sain = (struct sockaddr_in *)sa;
+ kaddr->addr = sain->sin_addr;
+
+ if ((sa = rti_info[RTAX_NETMASK]) != NULL) {
+ sain = (struct sockaddr_in *)sa;
+ kaddr->mask = sain->sin_addr;
+ } else
+ kaddr->mask.s_addr = INADDR_NONE;
+
+ if ((sa = rti_info[RTAX_BRD]) != NULL) {
+ sain = (struct sockaddr_in *)sa;
+ kaddr->dstbrd = sain->sin_addr;
+ } else
+ kaddr->dstbrd.s_addr = INADDR_NONE;
+
+ TAILQ_INSERT_TAIL(&kif->addrs, kaddr, entry);
+ }
+ break;
+ }
}
free(buf);
return (0);
diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h
index b8039d357d3..6121643ee9c 100644
--- a/usr.sbin/ospfd/ospfd.h
+++ b/usr.sbin/ospfd/ospfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfd.h,v 1.60 2006/06/28 10:53:39 norby Exp $ */
+/* $OpenBSD: ospfd.h,v 1.61 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -408,6 +408,13 @@ struct kroute {
u_int8_t prefixlen;
};
+struct kif_addr {
+ TAILQ_ENTRY(kif_addr) entry;
+ struct in_addr addr;
+ struct in_addr mask;
+ struct in_addr dstbrd;
+};
+
struct kif {
char ifname[IF_NAMESIZE];
u_long baudrate;
@@ -557,7 +564,7 @@ void kr_fib_decouple(void);
void kr_dispatch_msg(int, short, void *);
void kr_show_route(struct imsg *);
void kr_ifinfo(char *, pid_t);
-struct kif *kif_findname(char *);
+struct kif *kif_findname(char *, struct in_addr, struct kif_addr **);
u_int8_t mask2prefixlen(in_addr_t);
in_addr_t prefixlen2mask(u_int8_t);
diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c
index 59833170181..471ccf60870 100644
--- a/usr.sbin/ospfd/ospfe.c
+++ b/usr.sbin/ospfd/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.48 2006/09/27 14:37:38 claudio Exp $ */
+/* $OpenBSD: ospfe.c,v 1.49 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -97,15 +97,10 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
fatal("error creating raw socket");
/* set some defaults */
- if (if_set_mcast_ttl(xconf->ospf_socket,
- IP_DEFAULT_MULTICAST_TTL) == -1)
- fatal("if_set_mcast_ttl");
-
if (if_set_mcast_loop(xconf->ospf_socket) == -1)
fatal("if_set_mcast_loop");
-
- if (if_set_tos(xconf->ospf_socket, IPTOS_PREC_INTERNETCONTROL) == -1)
- fatal("if_set_tos");
+ if (if_set_ip_hdrincl(xconf->ospf_socket) == -1)
+ fatal("if_set_ip_hdrincl");
if (if_set_recvif(xconf->ospf_socket, 1) == -1)
fatal("if_set_recvif");
if_set_recvbuf(xconf->ospf_socket);
diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h
index 5558892696a..822b887b914 100644
--- a/usr.sbin/ospfd/ospfe.h
+++ b/usr.sbin/ospfd/ospfe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.h,v 1.32 2006/09/27 14:37:38 claudio Exp $ */
+/* $OpenBSD: ospfe.h,v 1.33 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -132,7 +132,7 @@ void orig_net_lsa(struct iface *);
/* interface.c */
int if_fsm(struct iface *, enum iface_event);
-struct iface *if_new(struct kif *);
+struct iface *if_new(struct kif *, struct kif_addr *);
void if_del(struct iface *);
void if_init(struct ospfd_conf *, struct iface *);
@@ -145,11 +145,10 @@ struct ctl_iface *if_to_ctl(struct iface *);
int if_join_group(struct iface *, struct in_addr *);
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);
+int if_set_ip_hdrincl(int);
/* lsack.c */
int delay_lsa_ack(struct iface *, struct lsa_hdr *);
diff --git a/usr.sbin/ospfd/packet.c b/usr.sbin/ospfd/packet.c
index e57b28375c1..2f6ac3438b9 100644
--- a/usr.sbin/ospfd/packet.c
+++ b/usr.sbin/ospfd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.21 2006/09/27 14:37:38 claudio Exp $ */
+/* $OpenBSD: packet.c,v 1.22 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -61,6 +61,36 @@ gen_ospf_hdr(struct buf *buf, struct iface *iface, u_int8_t type)
int
send_packet(struct iface *iface, void *pkt, size_t len, struct sockaddr_in *dst)
{
+ struct msghdr msg;
+ struct iovec iov[2];
+ struct ip ip_hdr;
+
+ /* setup IP hdr */
+ bzero(&ip_hdr, sizeof(ip_hdr));
+ ip_hdr.ip_v = IPVERSION;
+ ip_hdr.ip_hl = sizeof(ip_hdr) >> 2;
+ ip_hdr.ip_tos = IPTOS_PREC_INTERNETCONTROL;
+ ip_hdr.ip_len = htons(len + sizeof(ip_hdr));
+ ip_hdr.ip_id = 0; /* 0 means kernel set appropriate value */
+ ip_hdr.ip_off = 0;
+ ip_hdr.ip_ttl = iface->type != IF_TYPE_VIRTUALLINK ?
+ IP_DEFAULT_MULTICAST_TTL : MAXTTL;
+ ip_hdr.ip_p = IPPROTO_OSPF;
+ ip_hdr.ip_sum = 0;
+ ip_hdr.ip_src = iface->addr;
+ ip_hdr.ip_dst = dst->sin_addr;
+
+ /* setup buffer */
+ bzero(&msg, sizeof(msg));
+ iov[0].iov_base = &ip_hdr;
+ iov[0].iov_len = sizeof(ip_hdr);
+ iov[1].iov_base = pkt;
+ iov[1].iov_len = len;
+ msg.msg_name = dst;
+ msg.msg_namelen = sizeof(*dst);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+
/* set outgoing interface for multicast traffic */
if (IN_MULTICAST(ntohl(dst->sin_addr.s_addr)))
if (if_set_mcast(iface) == -1) {
@@ -69,8 +99,7 @@ send_packet(struct iface *iface, void *pkt, size_t len, struct sockaddr_in *dst)
return (-1);
}
- if (sendto(iface->fd, pkt, len, 0,
- (struct sockaddr *)dst, sizeof(*dst)) == -1 ) {
+ if (sendmsg(iface->fd, &msg, 0) == -1) {
log_warn("send_packet: error sending packet on interface %s",
iface->name);
return (-1);
@@ -105,8 +134,6 @@ recv_packet(int fd, short event, void *bula)
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;
@@ -143,7 +170,7 @@ recv_packet(int fd, short event, void *bula)
/* find a matching interface */
if ((iface = find_iface(xconf, ifindex, ip_hdr.ip_src)) == NULL) {
- log_debug("recv_packet: cannot find valid interface");
+ /* XXX add a counter here */
return;
}
diff --git a/usr.sbin/ospfd/parse.y b/usr.sbin/ospfd/parse.y
index a3aec6f318d..857df2c0a0e 100644
--- a/usr.sbin/ospfd/parse.y
+++ b/usr.sbin/ospfd/parse.y
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.y,v 1.37 2006/10/29 19:29:09 claudio Exp $ */
+/* $OpenBSD: parse.y,v 1.38 2006/11/17 08:55:31 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -93,7 +93,7 @@ struct sym {
int symset(const char *, const char *, int);
char *symget(const char *);
struct area *conf_get_area(struct in_addr);
-struct iface *conf_get_if(struct kif *);
+struct iface *conf_get_if(struct kif *, struct kif_addr *);
typedef struct {
union {
@@ -413,15 +413,39 @@ areaoptsl : interface
;
interface : INTERFACE STRING {
- struct kif *kif;
+ struct kif *kif;
+ struct kif_addr *ka = NULL;
+ char *s;
+ struct in_addr addr;
+
+ s = strchr($2, ':');
+ if (s) {
+ *s++ = '\0';
+ if (inet_aton(s, &addr) == 0) {
+ yyerror(
+ "error parsing interface address");
+ free($2);
+ YYERROR;
+ }
+ } else
+ addr.s_addr = 0;
- if ((kif = kif_findname($2)) == NULL) {
+ if ((kif = kif_findname($2, addr, &ka)) == NULL) {
yyerror("unknown interface %s", $2);
free($2);
YYERROR;
}
+ if (ka == NULL) {
+ if (s)
+ yyerror("address %s not configured on "
+ "interface %s", s, $2);
+ else
+ yyerror("unnumbered interface %s", $2);
+ free($2);
+ YYERROR;
+ }
free($2);
- iface = conf_get_if(kif);
+ iface = conf_get_if(kif, ka);
if (iface == NULL)
YYERROR;
iface->area = area;
@@ -880,20 +904,21 @@ conf_get_area(struct in_addr id)
}
struct iface *
-conf_get_if(struct kif *kif)
+conf_get_if(struct kif *kif, struct kif_addr *ka)
{
struct area *a;
struct iface *i;
LIST_FOREACH(a, &conf->area_list, entry)
LIST_FOREACH(i, &a->iface_list, entry)
- if (i->ifindex == kif->ifindex) {
+ if (i->ifindex == kif->ifindex &&
+ i->addr.s_addr == ka->addr.s_addr) {
yyerror("interface %s already configured",
kif->ifname);
return (NULL);
}
- i = if_new(kif);
+ i = if_new(kif, ka);
i->auth_keyid = 1;
return (i);