summaryrefslogtreecommitdiff
path: root/usr.sbin/ospfd/kroute.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2006-11-17 08:55:32 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2006-11-17 08:55:32 +0000
commitaa748b97fe57f4635f47ab0336b87da3cb55858c (patch)
tree743416ed5e159cd87cda9bea1f0e9405f2a2f539 /usr.sbin/ospfd/kroute.c
parent78604d2745675cfadeb29e2681177ec9ec7a86b5 (diff)
Support for multiple networks on one interface. Until now only the main
address of a interface could be used. Now it is possible to specify a interface more than once if multiple networks are configured. An alternative network can be specified via e.g. interface em0:10.0.5.1. The old interface syntax without the IP still works and uses the main/first configured IP address. ospfd now needs to include the IP header on outgoing messages as it is not possible to specifiy the source address in sendto(2). Additionally all multicast joins and leaves have to be tracked. OK norby@
Diffstat (limited to 'usr.sbin/ospfd/kroute.c')
-rw-r--r--usr.sbin/ospfd/kroute.c124
1 files changed, 95 insertions, 29 deletions
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);