diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-11-17 08:55:32 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2006-11-17 08:55:32 +0000 |
commit | aa748b97fe57f4635f47ab0336b87da3cb55858c (patch) | |
tree | 743416ed5e159cd87cda9bea1f0e9405f2a2f539 /usr.sbin/ospfd/kroute.c | |
parent | 78604d2745675cfadeb29e2681177ec9ec7a86b5 (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.c | 124 |
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); |