1*8a16b7a1SPedro F. Giffuni /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 47b6ab19dSGarrett Wollman * Copyright (c) 1983, 1993 57b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 67b6ab19dSGarrett Wollman * 77b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 87b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 97b6ab19dSGarrett Wollman * are met: 107b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 127b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 137b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 147b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 167b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 177b6ab19dSGarrett Wollman * without specific prior written permission. 187b6ab19dSGarrett Wollman * 197b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 207b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 217b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 227b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 237b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 247b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 257b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 267b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 277b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 287b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 297b6ab19dSGarrett Wollman * SUCH DAMAGE. 30c90fe7dcSMark Murray * 317f3dea24SPeter Wemm * $FreeBSD$ 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 34b108792dSUlrich Spörlein #include <stdint.h> 35b108792dSUlrich Spörlein 367b6ab19dSGarrett Wollman #include "defs.h" 377b6ab19dSGarrett Wollman #include "pathnames.h" 387b6ab19dSGarrett Wollman 39caa79e36SBruce M Simpson #ifdef __NetBSD__ 402c7a9781SMark Murray __RCSID("$NetBSD$"); 41caa79e36SBruce M Simpson #elif defined(__FreeBSD__) 42caa79e36SBruce M Simpson __RCSID("$FreeBSD$"); 43caa79e36SBruce M Simpson #else 44caa79e36SBruce M Simpson __RCSID("$Revision: 2.27 $"); 45caa79e36SBruce M Simpson #ident "$Revision: 2.27 $" 462c7a9781SMark Murray #endif 4792e7a424SStefan Farfeleder 4838ae6523SPoul-Henning Kamp struct ifhead ifnet = LIST_HEAD_INITIALIZER(ifnet); /* all interfaces */ 4913e403fdSAntoine Brodin struct ifhead remote_if = LIST_HEAD_INITIALIZER(remote_if); /* remote interfaces */ 50d5b718b3SGarrett Wollman 51d5b718b3SGarrett Wollman /* hash table for all interfaces, big enough to tolerate ridiculous 52d5b718b3SGarrett Wollman * numbers of IP aliases. Crazy numbers of aliases such as 7000 53d5b718b3SGarrett Wollman * still will not do well, but not just in looking up interfaces 54d5b718b3SGarrett Wollman * by name or address. 55d5b718b3SGarrett Wollman */ 56d5b718b3SGarrett Wollman #define AHASH_LEN 211 /* must be prime */ 57cdb877c3SGarrett Wollman #define AHASH(a) &ahash_tbl[(a)%AHASH_LEN] 58f2ca6d8aSPoul-Henning Kamp static struct interface *ahash_tbl[AHASH_LEN]; 59d5b718b3SGarrett Wollman 60d5b718b3SGarrett Wollman #define BHASH_LEN 211 /* must be prime */ 61cdb877c3SGarrett Wollman #define BHASH(a) &bhash_tbl[(a)%BHASH_LEN] 62f2ca6d8aSPoul-Henning Kamp static struct interface *bhash_tbl[BHASH_LEN]; 63d5b718b3SGarrett Wollman 64d5b718b3SGarrett Wollman 65d5b718b3SGarrett Wollman /* hash for physical interface names. 66d5b718b3SGarrett Wollman * Assume there are never more 100 or 200 real interfaces, and that 67337e72d0SGarrett Wollman * aliases are put on the end of the hash chains. 68d5b718b3SGarrett Wollman */ 69d5b718b3SGarrett Wollman #define NHASH_LEN 97 70f2ca6d8aSPoul-Henning Kamp static struct interface *nhash_tbl[NHASH_LEN]; 71d5b718b3SGarrett Wollman 727b6ab19dSGarrett Wollman int tot_interfaces; /* # of remote and local interfaces */ 737b6ab19dSGarrett Wollman int rip_interfaces; /* # of interfaces doing RIP */ 74f2ca6d8aSPoul-Henning Kamp static int foundloopback; /* valid flag for loopaddr */ 757b6ab19dSGarrett Wollman naddr loopaddr; /* our address on loopback */ 76f2ca6d8aSPoul-Henning Kamp static struct rt_spare loop_rts; 777b6ab19dSGarrett Wollman 787b6ab19dSGarrett Wollman struct timeval ifinit_timer; 79337e72d0SGarrett Wollman static struct timeval last_ifinit; 802c7a9781SMark Murray #define IF_RESCAN_DELAY() (last_ifinit.tv_sec == now.tv_sec \ 812c7a9781SMark Murray && last_ifinit.tv_usec == now.tv_usec \ 822c7a9781SMark Murray && timercmp(&ifinit_timer, &now, >)) 837b6ab19dSGarrett Wollman 847b6ab19dSGarrett Wollman int have_ripv1_out; /* have a RIPv1 interface */ 85f2ca6d8aSPoul-Henning Kamp static int have_ripv1_in; 867b6ab19dSGarrett Wollman 877b6ab19dSGarrett Wollman 88f2ca6d8aSPoul-Henning Kamp static void if_bad(struct interface *); 89f2ca6d8aSPoul-Henning Kamp static int addrouteforif(struct interface *); 90f2ca6d8aSPoul-Henning Kamp 91cdb877c3SGarrett Wollman static struct interface** 922c7a9781SMark Murray nhash(char *p) 93cdb877c3SGarrett Wollman { 942c7a9781SMark Murray u_int i; 95cdb877c3SGarrett Wollman 96cdb877c3SGarrett Wollman for (i = 0; *p != '\0'; p++) { 97cdb877c3SGarrett Wollman i = ((i<<1) & 0x7fffffff) | ((i>>31) & 1); 98cdb877c3SGarrett Wollman i ^= *p; 99cdb877c3SGarrett Wollman } 100cdb877c3SGarrett Wollman return &nhash_tbl[i % NHASH_LEN]; 101cdb877c3SGarrett Wollman } 102cdb877c3SGarrett Wollman 103cdb877c3SGarrett Wollman 104337e72d0SGarrett Wollman /* Link a new interface into the lists and hash tables. 105337e72d0SGarrett Wollman */ 106d5b718b3SGarrett Wollman void 107d5b718b3SGarrett Wollman if_link(struct interface *ifp) 108d5b718b3SGarrett Wollman { 109d5b718b3SGarrett Wollman struct interface **hifp; 110d5b718b3SGarrett Wollman 11138ae6523SPoul-Henning Kamp LIST_INSERT_HEAD(&ifnet, ifp, int_list); 112d5b718b3SGarrett Wollman 113d5b718b3SGarrett Wollman hifp = AHASH(ifp->int_addr); 114d5b718b3SGarrett Wollman ifp->int_ahash_prev = hifp; 115562c5a82SPedro F. Giffuni if ((ifp->int_ahash = *hifp) != NULL) 116d5b718b3SGarrett Wollman (*hifp)->int_ahash_prev = &ifp->int_ahash; 117d5b718b3SGarrett Wollman *hifp = ifp; 118d5b718b3SGarrett Wollman 119d5b718b3SGarrett Wollman if (ifp->int_if_flags & IFF_BROADCAST) { 120d5b718b3SGarrett Wollman hifp = BHASH(ifp->int_brdaddr); 121d5b718b3SGarrett Wollman ifp->int_bhash_prev = hifp; 122562c5a82SPedro F. Giffuni if ((ifp->int_bhash = *hifp) != NULL) 123d5b718b3SGarrett Wollman (*hifp)->int_bhash_prev = &ifp->int_bhash; 124d5b718b3SGarrett Wollman *hifp = ifp; 125d5b718b3SGarrett Wollman } 126d5b718b3SGarrett Wollman 1276b6b8280SPoul-Henning Kamp if (ifp->int_state & IS_REMOTE) 1286b6b8280SPoul-Henning Kamp LIST_INSERT_HEAD(&remote_if, ifp, remote_list); 129d5b718b3SGarrett Wollman 130cdb877c3SGarrett Wollman hifp = nhash(ifp->int_name); 131d5b718b3SGarrett Wollman if (ifp->int_state & IS_ALIAS) { 132337e72d0SGarrett Wollman /* put aliases on the end of the hash chain */ 133562c5a82SPedro F. Giffuni while (*hifp != NULL) 134d5b718b3SGarrett Wollman hifp = &(*hifp)->int_nhash; 135d5b718b3SGarrett Wollman } 136d5b718b3SGarrett Wollman ifp->int_nhash_prev = hifp; 137562c5a82SPedro F. Giffuni if ((ifp->int_nhash = *hifp) != NULL) 138d5b718b3SGarrett Wollman (*hifp)->int_nhash_prev = &ifp->int_nhash; 139d5b718b3SGarrett Wollman *hifp = ifp; 140d5b718b3SGarrett Wollman } 141d5b718b3SGarrett Wollman 142d5b718b3SGarrett Wollman 1437b6ab19dSGarrett Wollman /* Find the interface with an address 1447b6ab19dSGarrett Wollman */ 1457b6ab19dSGarrett Wollman struct interface * 1467b6ab19dSGarrett Wollman ifwithaddr(naddr addr, 1477b6ab19dSGarrett Wollman int bcast, /* notice IFF_BROADCAST address */ 1487b6ab19dSGarrett Wollman int remote) /* include IS_REMOTE interfaces */ 1497b6ab19dSGarrett Wollman { 150562c5a82SPedro F. Giffuni struct interface *ifp, *possible = NULL; 1517b6ab19dSGarrett Wollman 152d5b718b3SGarrett Wollman remote = (remote == 0) ? IS_REMOTE : 0; 153d5b718b3SGarrett Wollman 154d5b718b3SGarrett Wollman for (ifp = *AHASH(addr); ifp; ifp = ifp->int_ahash) { 155d5b718b3SGarrett Wollman if (ifp->int_addr != addr) 1567b6ab19dSGarrett Wollman continue; 157d5b718b3SGarrett Wollman if ((ifp->int_state & remote) != 0) 158d5b718b3SGarrett Wollman continue; 159d5b718b3SGarrett Wollman if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0) 1607b6ab19dSGarrett Wollman return ifp; 1617b6ab19dSGarrett Wollman possible = ifp; 1627b6ab19dSGarrett Wollman } 163d5b718b3SGarrett Wollman 164d5b718b3SGarrett Wollman if (possible || !bcast) 165d5b718b3SGarrett Wollman return possible; 166d5b718b3SGarrett Wollman 167d5b718b3SGarrett Wollman for (ifp = *BHASH(addr); ifp; ifp = ifp->int_bhash) { 168d5b718b3SGarrett Wollman if (ifp->int_brdaddr != addr) 169d5b718b3SGarrett Wollman continue; 170d5b718b3SGarrett Wollman if ((ifp->int_state & remote) != 0) 171d5b718b3SGarrett Wollman continue; 172d5b718b3SGarrett Wollman if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0) 173d5b718b3SGarrett Wollman return ifp; 174d5b718b3SGarrett Wollman possible = ifp; 1757b6ab19dSGarrett Wollman } 1767b6ab19dSGarrett Wollman 1777b6ab19dSGarrett Wollman return possible; 1787b6ab19dSGarrett Wollman } 1797b6ab19dSGarrett Wollman 1807b6ab19dSGarrett Wollman 1817b6ab19dSGarrett Wollman /* find the interface with a name 1827b6ab19dSGarrett Wollman */ 183f2ca6d8aSPoul-Henning Kamp static struct interface * 1847b6ab19dSGarrett Wollman ifwithname(char *name, /* "ec0" or whatever */ 1857b6ab19dSGarrett Wollman naddr addr) /* 0 or network address */ 1867b6ab19dSGarrett Wollman { 1877b6ab19dSGarrett Wollman struct interface *ifp; 1887b6ab19dSGarrett Wollman 189337e72d0SGarrett Wollman for (;;) { 190562c5a82SPedro F. Giffuni for (ifp = *nhash(name); ifp != NULL; ifp = ifp->int_nhash) { 191d5b718b3SGarrett Wollman /* If the network address is not specified, 192d5b718b3SGarrett Wollman * ignore any alias interfaces. Otherwise, look 193d5b718b3SGarrett Wollman * for the interface with the target name and address. 194d5b718b3SGarrett Wollman */ 1957b6ab19dSGarrett Wollman if (!strcmp(ifp->int_name, name) 196d5b718b3SGarrett Wollman && ((addr == 0 && !(ifp->int_state & IS_ALIAS)) 197d5b718b3SGarrett Wollman || (ifp->int_addr == addr))) 1987b6ab19dSGarrett Wollman return ifp; 1997b6ab19dSGarrett Wollman } 200337e72d0SGarrett Wollman 201337e72d0SGarrett Wollman /* If there is no known interface, maybe there is a 202337e72d0SGarrett Wollman * new interface. So just once look for new interfaces. 203337e72d0SGarrett Wollman */ 2042c7a9781SMark Murray if (IF_RESCAN_DELAY()) 2057b6ab19dSGarrett Wollman return 0; 206337e72d0SGarrett Wollman ifinit(); 207337e72d0SGarrett Wollman } 2087b6ab19dSGarrett Wollman } 2097b6ab19dSGarrett Wollman 2107b6ab19dSGarrett Wollman 2117b6ab19dSGarrett Wollman struct interface * 212caa79e36SBruce M Simpson ifwithindex(u_short ifindex, 2132c7a9781SMark Murray int rescan_ok) 2147b6ab19dSGarrett Wollman { 2157b6ab19dSGarrett Wollman struct interface *ifp; 2167b6ab19dSGarrett Wollman 2172c7a9781SMark Murray for (;;) { 21838ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) { 219caa79e36SBruce M Simpson if (ifp->int_index == ifindex) 2207b6ab19dSGarrett Wollman return ifp; 2217b6ab19dSGarrett Wollman } 2222c7a9781SMark Murray 2232c7a9781SMark Murray /* If there is no known interface, maybe there is a 2242c7a9781SMark Murray * new interface. So just once look for new interfaces. 2252c7a9781SMark Murray */ 2262c7a9781SMark Murray if (!rescan_ok 2272c7a9781SMark Murray || IF_RESCAN_DELAY()) 2287b6ab19dSGarrett Wollman return 0; 2292c7a9781SMark Murray ifinit(); 2302c7a9781SMark Murray } 2317b6ab19dSGarrett Wollman } 2327b6ab19dSGarrett Wollman 2337b6ab19dSGarrett Wollman 2347b6ab19dSGarrett Wollman /* Find an interface from which the specified address 2357b6ab19dSGarrett Wollman * should have come from. Used for figuring out which 23671965874SGarrett Wollman * interface a packet came in on. 2377b6ab19dSGarrett Wollman */ 2387b6ab19dSGarrett Wollman struct interface * 2397b6ab19dSGarrett Wollman iflookup(naddr addr) 2407b6ab19dSGarrett Wollman { 2417b6ab19dSGarrett Wollman struct interface *ifp, *maybe; 242caa79e36SBruce M Simpson int once = 0; 2437b6ab19dSGarrett Wollman 244562c5a82SPedro F. Giffuni maybe = NULL; 24571965874SGarrett Wollman for (;;) { 24638ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) { 2477b6ab19dSGarrett Wollman if (ifp->int_if_flags & IFF_POINTOPOINT) { 2487b6ab19dSGarrett Wollman /* finished with a match */ 249d5b718b3SGarrett Wollman if (ifp->int_dstaddr == addr) 2507b6ab19dSGarrett Wollman return ifp; 2517b6ab19dSGarrett Wollman 2527b6ab19dSGarrett Wollman } else { 2537b6ab19dSGarrett Wollman /* finished with an exact match */ 2547b6ab19dSGarrett Wollman if (ifp->int_addr == addr) 2557b6ab19dSGarrett Wollman return ifp; 2567b6ab19dSGarrett Wollman 2577b6ab19dSGarrett Wollman /* Look for the longest approximate match. 2587b6ab19dSGarrett Wollman */ 2597b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_net, ifp->int_mask) 260562c5a82SPedro F. Giffuni && (maybe == NULL 2617b6ab19dSGarrett Wollman || ifp->int_mask > maybe->int_mask)) 2627b6ab19dSGarrett Wollman maybe = ifp; 2637b6ab19dSGarrett Wollman } 2647b6ab19dSGarrett Wollman } 2657b6ab19dSGarrett Wollman 266562c5a82SPedro F. Giffuni if (maybe != NULL || once || IF_RESCAN_DELAY()) 2677b6ab19dSGarrett Wollman return maybe; 268caa79e36SBruce M Simpson once = 1; 26971965874SGarrett Wollman 27071965874SGarrett Wollman /* If there is no known interface, maybe there is a 27171965874SGarrett Wollman * new interface. So just once look for new interfaces. 27271965874SGarrett Wollman */ 27371965874SGarrett Wollman ifinit(); 27471965874SGarrett Wollman } 2757b6ab19dSGarrett Wollman } 2767b6ab19dSGarrett Wollman 2777b6ab19dSGarrett Wollman 2787b6ab19dSGarrett Wollman /* Return the classical netmask for an IP address. 2797b6ab19dSGarrett Wollman */ 28071965874SGarrett Wollman naddr /* host byte order */ 28171965874SGarrett Wollman std_mask(naddr addr) /* network byte order */ 2827b6ab19dSGarrett Wollman { 283fd8e4ebcSMike Barcroft addr = ntohl(addr); /* was a host, not a network */ 2847b6ab19dSGarrett Wollman 2857b6ab19dSGarrett Wollman if (addr == 0) /* default route has mask 0 */ 2867b6ab19dSGarrett Wollman return 0; 2877b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) 2887b6ab19dSGarrett Wollman return IN_CLASSA_NET; 2897b6ab19dSGarrett Wollman if (IN_CLASSB(addr)) 2907b6ab19dSGarrett Wollman return IN_CLASSB_NET; 2917b6ab19dSGarrett Wollman return IN_CLASSC_NET; 2927b6ab19dSGarrett Wollman } 2937b6ab19dSGarrett Wollman 2947b6ab19dSGarrett Wollman 2957b6ab19dSGarrett Wollman /* Find the netmask that would be inferred by RIPv1 listeners 2967b6ab19dSGarrett Wollman * on the given interface for a given network. 2977b6ab19dSGarrett Wollman * If no interface is specified, look for the best fitting interface. 2987b6ab19dSGarrett Wollman */ 2997b6ab19dSGarrett Wollman naddr 3007b6ab19dSGarrett Wollman ripv1_mask_net(naddr addr, /* in network byte order */ 3017b6ab19dSGarrett Wollman struct interface *ifp) /* as seen on this interface */ 3027b6ab19dSGarrett Wollman { 3032c7a9781SMark Murray struct r1net *r1p; 3047b6ab19dSGarrett Wollman naddr mask = 0; 3057b6ab19dSGarrett Wollman 3067b6ab19dSGarrett Wollman if (addr == 0) /* default always has 0 mask */ 3077b6ab19dSGarrett Wollman return mask; 3087b6ab19dSGarrett Wollman 309562c5a82SPedro F. Giffuni if (ifp != NULL && ifp->int_ripv1_mask != HOST_MASK) { 3107b6ab19dSGarrett Wollman /* If the target network is that of the associated interface 3117b6ab19dSGarrett Wollman * on which it arrived, then use the netmask of the interface. 3127b6ab19dSGarrett Wollman */ 3137b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_net, ifp->int_std_mask)) 3147b6ab19dSGarrett Wollman mask = ifp->int_ripv1_mask; 3157b6ab19dSGarrett Wollman 3167b6ab19dSGarrett Wollman } else { 3177b6ab19dSGarrett Wollman /* Examine all interfaces, and if it the target seems 3187b6ab19dSGarrett Wollman * to have the same network number of an interface, use the 3197b6ab19dSGarrett Wollman * netmask of that interface. If there is more than one 3207b6ab19dSGarrett Wollman * such interface, prefer the interface with the longest 3217b6ab19dSGarrett Wollman * match. 3227b6ab19dSGarrett Wollman */ 32338ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) { 3247b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_std_net, ifp->int_std_mask) 3252c7a9781SMark Murray && ifp->int_ripv1_mask > mask 3262c7a9781SMark Murray && ifp->int_ripv1_mask != HOST_MASK) 3277b6ab19dSGarrett Wollman mask = ifp->int_ripv1_mask; 3287b6ab19dSGarrett Wollman } 3292c7a9781SMark Murray 3302c7a9781SMark Murray } 3312c7a9781SMark Murray 3322c7a9781SMark Murray /* check special definitions */ 3332c7a9781SMark Murray if (mask == 0) { 334562c5a82SPedro F. Giffuni for (r1p = r1nets; r1p != NULL; r1p = r1p->r1net_next) { 3352c7a9781SMark Murray if (on_net(addr, r1p->r1net_net, r1p->r1net_match) 3362c7a9781SMark Murray && r1p->r1net_mask > mask) 3372c7a9781SMark Murray mask = r1p->r1net_mask; 3387b6ab19dSGarrett Wollman } 3397b6ab19dSGarrett Wollman 3407b6ab19dSGarrett Wollman /* Otherwise, make the classic A/B/C guess. 3417b6ab19dSGarrett Wollman */ 3427b6ab19dSGarrett Wollman if (mask == 0) 3437b6ab19dSGarrett Wollman mask = std_mask(addr); 3442c7a9781SMark Murray } 3457b6ab19dSGarrett Wollman 3467b6ab19dSGarrett Wollman return mask; 3477b6ab19dSGarrett Wollman } 3487b6ab19dSGarrett Wollman 3497b6ab19dSGarrett Wollman 3507b6ab19dSGarrett Wollman naddr 3517b6ab19dSGarrett Wollman ripv1_mask_host(naddr addr, /* in network byte order */ 3527b6ab19dSGarrett Wollman struct interface *ifp) /* as seen on this interface */ 3537b6ab19dSGarrett Wollman { 3547b6ab19dSGarrett Wollman naddr mask = ripv1_mask_net(addr, ifp); 3557b6ab19dSGarrett Wollman 3567b6ab19dSGarrett Wollman 3577b6ab19dSGarrett Wollman /* If the computed netmask does not mask the address, 3587b6ab19dSGarrett Wollman * then assume it is a host address 3597b6ab19dSGarrett Wollman */ 3607b6ab19dSGarrett Wollman if ((ntohl(addr) & ~mask) != 0) 3617b6ab19dSGarrett Wollman mask = HOST_MASK; 3627b6ab19dSGarrett Wollman return mask; 3637b6ab19dSGarrett Wollman } 3647b6ab19dSGarrett Wollman 3657b6ab19dSGarrett Wollman 3669d5abbddSJens Schweikhardt /* See if an IP address looks reasonable as a destination. 3677b6ab19dSGarrett Wollman */ 3687b6ab19dSGarrett Wollman int /* 0=bad */ 3697b6ab19dSGarrett Wollman check_dst(naddr addr) 3707b6ab19dSGarrett Wollman { 371fd8e4ebcSMike Barcroft addr = ntohl(addr); 3727b6ab19dSGarrett Wollman 3737b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) { 3747b6ab19dSGarrett Wollman if (addr == 0) 3757b6ab19dSGarrett Wollman return 1; /* default */ 3767b6ab19dSGarrett Wollman 3777b6ab19dSGarrett Wollman addr >>= IN_CLASSA_NSHIFT; 3787b6ab19dSGarrett Wollman return (addr != 0 && addr != IN_LOOPBACKNET); 3797b6ab19dSGarrett Wollman } 3807b6ab19dSGarrett Wollman 3817b6ab19dSGarrett Wollman return (IN_CLASSB(addr) || IN_CLASSC(addr)); 3827b6ab19dSGarrett Wollman } 3837b6ab19dSGarrett Wollman 3847b6ab19dSGarrett Wollman 385d5b718b3SGarrett Wollman /* See a new interface duplicates an existing interface. 386d5b718b3SGarrett Wollman */ 387d5b718b3SGarrett Wollman struct interface * 38871965874SGarrett Wollman check_dup(naddr addr, /* IP address, so network byte order */ 38971965874SGarrett Wollman naddr dstaddr, /* ditto */ 39071965874SGarrett Wollman naddr mask, /* mask, so host byte order */ 391d5b718b3SGarrett Wollman int if_flags) 392d5b718b3SGarrett Wollman { 393d5b718b3SGarrett Wollman struct interface *ifp; 394d5b718b3SGarrett Wollman 39538ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) { 396d5b718b3SGarrett Wollman if (ifp->int_mask != mask) 397d5b718b3SGarrett Wollman continue; 398d5b718b3SGarrett Wollman 3992c7a9781SMark Murray if (!iff_up(ifp->int_if_flags)) 400d5b718b3SGarrett Wollman continue; 401d5b718b3SGarrett Wollman 4022c7a9781SMark Murray /* The local address can only be shared with a point-to-point 4032c7a9781SMark Murray * link. 404d5b718b3SGarrett Wollman */ 405caa79e36SBruce M Simpson if ((!(ifp->int_state & IS_REMOTE) || !(if_flags & IS_REMOTE)) 406caa79e36SBruce M Simpson && ifp->int_addr == addr 407d5b718b3SGarrett Wollman && (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0)) 408d5b718b3SGarrett Wollman return ifp; 409d5b718b3SGarrett Wollman 410d5b718b3SGarrett Wollman if (on_net(ifp->int_dstaddr, ntohl(dstaddr),mask)) 411d5b718b3SGarrett Wollman return ifp; 412d5b718b3SGarrett Wollman } 413d5b718b3SGarrett Wollman return 0; 414d5b718b3SGarrett Wollman } 415d5b718b3SGarrett Wollman 416d5b718b3SGarrett Wollman 417d5b718b3SGarrett Wollman /* See that a remote gateway is reachable. 418d5b718b3SGarrett Wollman * Note that the answer can change as real interfaces come and go. 419d5b718b3SGarrett Wollman */ 420d5b718b3SGarrett Wollman int /* 0=bad */ 421d5b718b3SGarrett Wollman check_remote(struct interface *ifp) 422d5b718b3SGarrett Wollman { 423d5b718b3SGarrett Wollman struct rt_entry *rt; 424d5b718b3SGarrett Wollman 425d5b718b3SGarrett Wollman /* do not worry about other kinds */ 426d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_REMOTE)) 427d5b718b3SGarrett Wollman return 1; 428d5b718b3SGarrett Wollman 429d5b718b3SGarrett Wollman rt = rtfind(ifp->int_addr); 430562c5a82SPedro F. Giffuni if (rt != NULL 431d5b718b3SGarrett Wollman && rt->rt_ifp != 0 432d5b718b3SGarrett Wollman &&on_net(ifp->int_addr, 433d5b718b3SGarrett Wollman rt->rt_ifp->int_net, rt->rt_ifp->int_mask)) 434d5b718b3SGarrett Wollman return 1; 435d5b718b3SGarrett Wollman 436d5b718b3SGarrett Wollman /* the gateway cannot be reached directly from one of our 437d5b718b3SGarrett Wollman * interfaces 438d5b718b3SGarrett Wollman */ 439d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 440d5b718b3SGarrett Wollman msglog("unreachable gateway %s in "_PATH_GATEWAYS, 441d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_addr)); 442d5b718b3SGarrett Wollman if_bad(ifp); 443d5b718b3SGarrett Wollman } 444d5b718b3SGarrett Wollman return 0; 445d5b718b3SGarrett Wollman } 446d5b718b3SGarrett Wollman 447d5b718b3SGarrett Wollman 4487b6ab19dSGarrett Wollman /* Delete an interface. 4497b6ab19dSGarrett Wollman */ 4507b6ab19dSGarrett Wollman static void 4517b6ab19dSGarrett Wollman ifdel(struct interface *ifp) 4527b6ab19dSGarrett Wollman { 4537b6ab19dSGarrett Wollman struct interface *ifp1; 4547b6ab19dSGarrett Wollman 4557b6ab19dSGarrett Wollman 4567b6ab19dSGarrett Wollman trace_if("Del", ifp); 4577b6ab19dSGarrett Wollman 4587b6ab19dSGarrett Wollman ifp->int_state |= IS_BROKE; 4597b6ab19dSGarrett Wollman 46038ae6523SPoul-Henning Kamp LIST_REMOVE(ifp, int_list); 461d5b718b3SGarrett Wollman *ifp->int_ahash_prev = ifp->int_ahash; 462d5b718b3SGarrett Wollman if (ifp->int_ahash != 0) 463d5b718b3SGarrett Wollman ifp->int_ahash->int_ahash_prev = ifp->int_ahash_prev; 464cdb877c3SGarrett Wollman *ifp->int_nhash_prev = ifp->int_nhash; 465cdb877c3SGarrett Wollman if (ifp->int_nhash != 0) 466cdb877c3SGarrett Wollman ifp->int_nhash->int_nhash_prev = ifp->int_nhash_prev; 467d5b718b3SGarrett Wollman if (ifp->int_if_flags & IFF_BROADCAST) { 468d5b718b3SGarrett Wollman *ifp->int_bhash_prev = ifp->int_bhash; 469d5b718b3SGarrett Wollman if (ifp->int_bhash != 0) 470d5b718b3SGarrett Wollman ifp->int_bhash->int_bhash_prev = ifp->int_bhash_prev; 471d5b718b3SGarrett Wollman } 4726b6b8280SPoul-Henning Kamp if (ifp->int_state & IS_REMOTE) 4736b6b8280SPoul-Henning Kamp LIST_REMOVE(ifp, remote_list); 4747b6ab19dSGarrett Wollman 4757b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 476d5b718b3SGarrett Wollman /* delete aliases when the main interface dies 4777b6ab19dSGarrett Wollman */ 47838ae6523SPoul-Henning Kamp LIST_FOREACH(ifp1, &ifnet, int_list) { 4797b6ab19dSGarrett Wollman if (ifp1 != ifp 4807b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 4817b6ab19dSGarrett Wollman ifdel(ifp1); 4827b6ab19dSGarrett Wollman } 4837b6ab19dSGarrett Wollman 48468b22388SPoul-Henning Kamp if ((ifp->int_if_flags & IFF_MULTICAST) && rip_sock >= 0) { 48568b22388SPoul-Henning Kamp struct group_req gr; 48668b22388SPoul-Henning Kamp struct sockaddr_in *sin; 48768b22388SPoul-Henning Kamp 48868b22388SPoul-Henning Kamp memset(&gr, 0, sizeof(gr)); 48968b22388SPoul-Henning Kamp gr.gr_interface = ifp->int_index; 49068b22388SPoul-Henning Kamp sin = (struct sockaddr_in *)&gr.gr_group; 49168b22388SPoul-Henning Kamp sin->sin_family = AF_INET; 49268b22388SPoul-Henning Kamp #ifdef _HAVE_SIN_LEN 49368b22388SPoul-Henning Kamp sin->sin_len = sizeof(struct sockaddr_in); 4947b6ab19dSGarrett Wollman #endif 49568b22388SPoul-Henning Kamp sin->sin_addr.s_addr = htonl(INADDR_RIP_GROUP); 49668b22388SPoul-Henning Kamp if (setsockopt(rip_sock, IPPROTO_IP, MCAST_LEAVE_GROUP, 49768b22388SPoul-Henning Kamp &gr, sizeof(gr)) < 0 4987b6ab19dSGarrett Wollman && errno != EADDRNOTAVAIL 4997b6ab19dSGarrett Wollman && !TRACEACTIONS) 50068b22388SPoul-Henning Kamp LOGERR("setsockopt(MCAST_LEAVE_GROUP RIP)"); 501d5b718b3SGarrett Wollman if (rip_sock_mcast == ifp) 502562c5a82SPedro F. Giffuni rip_sock_mcast = NULL; 5037b6ab19dSGarrett Wollman } 5047b6ab19dSGarrett Wollman if (ifp->int_rip_sock >= 0) { 5057b6ab19dSGarrett Wollman (void)close(ifp->int_rip_sock); 5067b6ab19dSGarrett Wollman ifp->int_rip_sock = -1; 5077b6ab19dSGarrett Wollman fix_select(); 5087b6ab19dSGarrett Wollman } 5097b6ab19dSGarrett Wollman 5107b6ab19dSGarrett Wollman tot_interfaces--; 5117b6ab19dSGarrett Wollman if (!IS_RIP_OFF(ifp->int_state)) 5127b6ab19dSGarrett Wollman rip_interfaces--; 5137b6ab19dSGarrett Wollman 5147b6ab19dSGarrett Wollman /* Zap all routes associated with this interface. 5152c7a9781SMark Murray * Assume routes just using gateways beyond this interface 5162c7a9781SMark Murray * will timeout naturally, and have probably already died. 5177b6ab19dSGarrett Wollman */ 5187b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_bad, 0); 5197b6ab19dSGarrett Wollman 5207b6ab19dSGarrett Wollman set_rdisc_mg(ifp, 0); 5217b6ab19dSGarrett Wollman if_bad_rdisc(ifp); 5227b6ab19dSGarrett Wollman } 5237b6ab19dSGarrett Wollman 5247b6ab19dSGarrett Wollman free(ifp); 5257b6ab19dSGarrett Wollman } 5267b6ab19dSGarrett Wollman 5277b6ab19dSGarrett Wollman 5287b6ab19dSGarrett Wollman /* Mark an interface ill. 5297b6ab19dSGarrett Wollman */ 5307b6ab19dSGarrett Wollman void 5317b6ab19dSGarrett Wollman if_sick(struct interface *ifp) 5327b6ab19dSGarrett Wollman { 5337b6ab19dSGarrett Wollman if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) { 5347b6ab19dSGarrett Wollman ifp->int_state |= IS_SICK; 535d5b718b3SGarrett Wollman ifp->int_act_time = NEVER; 5367b6ab19dSGarrett Wollman trace_if("Chg", ifp); 5377b6ab19dSGarrett Wollman 5387b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 5397b6ab19dSGarrett Wollman } 5407b6ab19dSGarrett Wollman } 5417b6ab19dSGarrett Wollman 5427b6ab19dSGarrett Wollman 5437b6ab19dSGarrett Wollman /* Mark an interface dead. 5447b6ab19dSGarrett Wollman */ 545f2ca6d8aSPoul-Henning Kamp static void 5467b6ab19dSGarrett Wollman if_bad(struct interface *ifp) 5477b6ab19dSGarrett Wollman { 5487b6ab19dSGarrett Wollman struct interface *ifp1; 5497b6ab19dSGarrett Wollman 5507b6ab19dSGarrett Wollman 5517b6ab19dSGarrett Wollman if (ifp->int_state & IS_BROKE) 5527b6ab19dSGarrett Wollman return; 5537b6ab19dSGarrett Wollman 5547b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 5557b6ab19dSGarrett Wollman 5567b6ab19dSGarrett Wollman ifp->int_state |= (IS_BROKE | IS_SICK); 557d5b718b3SGarrett Wollman ifp->int_act_time = NEVER; 558d5b718b3SGarrett Wollman ifp->int_query_time = NEVER; 5592c7a9781SMark Murray ifp->int_data.ts = now.tv_sec; 5607b6ab19dSGarrett Wollman 5617b6ab19dSGarrett Wollman trace_if("Chg", ifp); 5627b6ab19dSGarrett Wollman 5637b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 56438ae6523SPoul-Henning Kamp LIST_FOREACH(ifp1, &ifnet, int_list) { 5657b6ab19dSGarrett Wollman if (ifp1 != ifp 5667b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 5677b6ab19dSGarrett Wollman if_bad(ifp1); 5687b6ab19dSGarrett Wollman } 5697b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_bad, 0); 5707b6ab19dSGarrett Wollman if_bad_rdisc(ifp); 5717b6ab19dSGarrett Wollman } 5727b6ab19dSGarrett Wollman } 5737b6ab19dSGarrett Wollman 5747b6ab19dSGarrett Wollman 5757b6ab19dSGarrett Wollman /* Mark an interface alive 5767b6ab19dSGarrett Wollman */ 5777b6ab19dSGarrett Wollman int /* 1=it was dead */ 5787b6ab19dSGarrett Wollman if_ok(struct interface *ifp, 5792c7a9781SMark Murray const char *type) 5807b6ab19dSGarrett Wollman { 5817b6ab19dSGarrett Wollman struct interface *ifp1; 5827b6ab19dSGarrett Wollman 5837b6ab19dSGarrett Wollman 5847b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 5857b6ab19dSGarrett Wollman if (ifp->int_state & IS_SICK) { 586d5b718b3SGarrett Wollman trace_act("%sinterface %s to %s working better", 5877b6ab19dSGarrett Wollman type, 588d5b718b3SGarrett Wollman ifp->int_name, naddr_ntoa(ifp->int_dstaddr)); 5897b6ab19dSGarrett Wollman ifp->int_state &= ~IS_SICK; 5907b6ab19dSGarrett Wollman } 5917b6ab19dSGarrett Wollman return 0; 5927b6ab19dSGarrett Wollman } 5937b6ab19dSGarrett Wollman 5947b6ab19dSGarrett Wollman msglog("%sinterface %s to %s restored", 595d5b718b3SGarrett Wollman type, ifp->int_name, naddr_ntoa(ifp->int_dstaddr)); 5967b6ab19dSGarrett Wollman ifp->int_state &= ~(IS_BROKE | IS_SICK); 5977b6ab19dSGarrett Wollman ifp->int_data.ts = 0; 5987b6ab19dSGarrett Wollman 5997b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 60038ae6523SPoul-Henning Kamp LIST_FOREACH(ifp1, &ifnet, int_list) { 6017b6ab19dSGarrett Wollman if (ifp1 != ifp 6027b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 6037b6ab19dSGarrett Wollman if_ok(ifp1, type); 6047b6ab19dSGarrett Wollman } 6057b6ab19dSGarrett Wollman if_ok_rdisc(ifp); 6067b6ab19dSGarrett Wollman } 607d5b718b3SGarrett Wollman 608d5b718b3SGarrett Wollman if (ifp->int_state & IS_REMOTE) { 609d5b718b3SGarrett Wollman if (!addrouteforif(ifp)) 610d5b718b3SGarrett Wollman return 0; 611d5b718b3SGarrett Wollman } 6127b6ab19dSGarrett Wollman return 1; 6137b6ab19dSGarrett Wollman } 6147b6ab19dSGarrett Wollman 6157b6ab19dSGarrett Wollman 6167b6ab19dSGarrett Wollman /* disassemble routing message 6177b6ab19dSGarrett Wollman */ 6187b6ab19dSGarrett Wollman void 6197b6ab19dSGarrett Wollman rt_xaddrs(struct rt_addrinfo *info, 6207b6ab19dSGarrett Wollman struct sockaddr *sa, 6217b6ab19dSGarrett Wollman struct sockaddr *lim, 6227b6ab19dSGarrett Wollman int addrs) 6237b6ab19dSGarrett Wollman { 6247b6ab19dSGarrett Wollman int i; 6257b6ab19dSGarrett Wollman #ifdef _HAVE_SA_LEN 6267b6ab19dSGarrett Wollman static struct sockaddr sa_zero; 6277b6ab19dSGarrett Wollman #endif 6287b6ab19dSGarrett Wollman 6292c7a9781SMark Murray memset(info, 0, sizeof(*info)); 6307b6ab19dSGarrett Wollman info->rti_addrs = addrs; 6317b6ab19dSGarrett Wollman for (i = 0; i < RTAX_MAX && sa < lim; i++) { 6327b6ab19dSGarrett Wollman if ((addrs & (1 << i)) == 0) 6337b6ab19dSGarrett Wollman continue; 6347b6ab19dSGarrett Wollman info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero; 6350b46c085SLuigi Rizzo sa = (struct sockaddr *)((char*)(sa) + SA_SIZE(sa)); 6367b6ab19dSGarrett Wollman } 6377b6ab19dSGarrett Wollman } 6387b6ab19dSGarrett Wollman 6397b6ab19dSGarrett Wollman 6407b6ab19dSGarrett Wollman /* Find the network interfaces which have configured themselves. 6417b6ab19dSGarrett Wollman * This must be done regularly, if only for extra addresses 6427b6ab19dSGarrett Wollman * that come and go on interfaces. 6437b6ab19dSGarrett Wollman */ 6447b6ab19dSGarrett Wollman void 6457b6ab19dSGarrett Wollman ifinit(void) 6467b6ab19dSGarrett Wollman { 647960b861bSPoul-Henning Kamp static struct ifa_msghdr *sysctl_buf; 6487b6ab19dSGarrett Wollman static size_t sysctl_buf_size = 0; 6497b6ab19dSGarrett Wollman uint complaints = 0; 6507b6ab19dSGarrett Wollman static u_int prev_complaints = 0; 6517b6ab19dSGarrett Wollman # define COMP_NOT_INET 0x001 652d5b718b3SGarrett Wollman # define COMP_NOADDR 0x002 653d5b718b3SGarrett Wollman # define COMP_BADADDR 0x004 654d5b718b3SGarrett Wollman # define COMP_NODST 0x008 655d5b718b3SGarrett Wollman # define COMP_NOBADR 0x010 656d5b718b3SGarrett Wollman # define COMP_NOMASK 0x020 657d5b718b3SGarrett Wollman # define COMP_DUP 0x040 658d5b718b3SGarrett Wollman # define COMP_BAD_METRIC 0x080 659d5b718b3SGarrett Wollman # define COMP_NETMASK 0x100 6607b6ab19dSGarrett Wollman 6617b6ab19dSGarrett Wollman struct interface ifs, ifs0, *ifp, *ifp1; 6627b6ab19dSGarrett Wollman struct rt_entry *rt; 6637b6ab19dSGarrett Wollman size_t needed; 6647b6ab19dSGarrett Wollman int mib[6]; 6657b6ab19dSGarrett Wollman struct if_msghdr *ifm; 666960b861bSPoul-Henning Kamp void *ifam_lim; 667960b861bSPoul-Henning Kamp struct ifa_msghdr *ifam, *ifam2; 6687b6ab19dSGarrett Wollman int in, ierr, out, oerr; 6697b6ab19dSGarrett Wollman struct intnet *intnetp; 6707b6ab19dSGarrett Wollman struct rt_addrinfo info; 6717b6ab19dSGarrett Wollman #ifdef SIOCGIFMETRIC 6727b6ab19dSGarrett Wollman struct ifreq ifr; 6737b6ab19dSGarrett Wollman #endif 6747b6ab19dSGarrett Wollman 6757b6ab19dSGarrett Wollman 676337e72d0SGarrett Wollman last_ifinit = now; 6777b6ab19dSGarrett Wollman ifinit_timer.tv_sec = now.tv_sec + (supplier 6787b6ab19dSGarrett Wollman ? CHECK_ACT_INTERVAL 6797b6ab19dSGarrett Wollman : CHECK_QUIET_INTERVAL); 6807b6ab19dSGarrett Wollman 68190100551SPhilippe Charnier /* mark all interfaces so we can get rid of those that disappear */ 68238ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) 6837b6ab19dSGarrett Wollman ifp->int_state &= ~(IS_CHECKED | IS_DUP); 6847b6ab19dSGarrett Wollman 6857b6ab19dSGarrett Wollman /* Fetch the interface list, without too many system calls 6867b6ab19dSGarrett Wollman * since we do it repeatedly. 6877b6ab19dSGarrett Wollman */ 6887b6ab19dSGarrett Wollman mib[0] = CTL_NET; 6897b6ab19dSGarrett Wollman mib[1] = PF_ROUTE; 6907b6ab19dSGarrett Wollman mib[2] = 0; 6917b6ab19dSGarrett Wollman mib[3] = AF_INET; 6927b6ab19dSGarrett Wollman mib[4] = NET_RT_IFLIST; 6937b6ab19dSGarrett Wollman mib[5] = 0; 6947b6ab19dSGarrett Wollman for (;;) { 6957b6ab19dSGarrett Wollman if ((needed = sysctl_buf_size) != 0) { 6967b6ab19dSGarrett Wollman if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0) 6977b6ab19dSGarrett Wollman break; 6982c7a9781SMark Murray /* retry if the table grew */ 6997b6ab19dSGarrett Wollman if (errno != ENOMEM && errno != EFAULT) 7002c7a9781SMark Murray BADERR(1, "ifinit: sysctl(RT_IFLIST)"); 7017b6ab19dSGarrett Wollman free(sysctl_buf); 7027b6ab19dSGarrett Wollman needed = 0; 7037b6ab19dSGarrett Wollman } 7047b6ab19dSGarrett Wollman if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) 7052c7a9781SMark Murray BADERR(1,"ifinit: sysctl(RT_IFLIST) estimate"); 7062c7a9781SMark Murray sysctl_buf = rtmalloc(sysctl_buf_size = needed, 7072c7a9781SMark Murray "ifinit sysctl"); 7087b6ab19dSGarrett Wollman } 7097b6ab19dSGarrett Wollman 710960b861bSPoul-Henning Kamp /* XXX: thanks to malloc(3), alignment can be presumed OK */ 711960b861bSPoul-Henning Kamp ifam_lim = (char *)sysctl_buf + needed; 712960b861bSPoul-Henning Kamp for (ifam = sysctl_buf; (void *)ifam < ifam_lim; ifam = ifam2) { 7137b6ab19dSGarrett Wollman 7147b6ab19dSGarrett Wollman ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen); 7157b6ab19dSGarrett Wollman 716caa79e36SBruce M Simpson #ifdef RTM_OIFINFO 717caa79e36SBruce M Simpson if (ifam->ifam_type == RTM_OIFINFO) 718caa79e36SBruce M Simpson continue; /* just ignore compat message */ 719caa79e36SBruce M Simpson #endif 7207b6ab19dSGarrett Wollman if (ifam->ifam_type == RTM_IFINFO) { 721d5b718b3SGarrett Wollman struct sockaddr_dl *sdl; 722d5b718b3SGarrett Wollman 7237b6ab19dSGarrett Wollman ifm = (struct if_msghdr *)ifam; 7247b6ab19dSGarrett Wollman /* make prototype structure for the IP aliases 7257b6ab19dSGarrett Wollman */ 7262c7a9781SMark Murray memset(&ifs0, 0, sizeof(ifs0)); 7277b6ab19dSGarrett Wollman ifs0.int_rip_sock = -1; 7287b6ab19dSGarrett Wollman ifs0.int_index = ifm->ifm_index; 7297b6ab19dSGarrett Wollman ifs0.int_if_flags = ifm->ifm_flags; 7307b6ab19dSGarrett Wollman ifs0.int_state = IS_CHECKED; 73171965874SGarrett Wollman ifs0.int_query_time = NEVER; 7327b6ab19dSGarrett Wollman ifs0.int_act_time = now.tv_sec; 7337b6ab19dSGarrett Wollman ifs0.int_data.ts = now.tv_sec; 7347b6ab19dSGarrett Wollman ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets; 7357b6ab19dSGarrett Wollman ifs0.int_data.ierrors = ifm->ifm_data.ifi_ierrors; 7367b6ab19dSGarrett Wollman ifs0.int_data.opackets = ifm->ifm_data.ifi_opackets; 7377b6ab19dSGarrett Wollman ifs0.int_data.oerrors = ifm->ifm_data.ifi_oerrors; 7387b6ab19dSGarrett Wollman #ifdef sgi 7397b6ab19dSGarrett Wollman ifs0.int_data.odrops = ifm->ifm_data.ifi_odrops; 7407b6ab19dSGarrett Wollman #endif 7417b6ab19dSGarrett Wollman sdl = (struct sockaddr_dl *)(ifm + 1); 7427b6ab19dSGarrett Wollman sdl->sdl_data[sdl->sdl_nlen] = 0; 743d5b718b3SGarrett Wollman strncpy(ifs0.int_name, sdl->sdl_data, 744d5b718b3SGarrett Wollman MIN(sizeof(ifs0.int_name), sdl->sdl_nlen)); 7457b6ab19dSGarrett Wollman continue; 7467b6ab19dSGarrett Wollman } 7477b6ab19dSGarrett Wollman if (ifam->ifam_type != RTM_NEWADDR) { 7487b6ab19dSGarrett Wollman logbad(1,"ifinit: out of sync"); 7497b6ab19dSGarrett Wollman continue; 7507b6ab19dSGarrett Wollman } 7517b6ab19dSGarrett Wollman rt_xaddrs(&info, (struct sockaddr *)(ifam+1), 7527b6ab19dSGarrett Wollman (struct sockaddr *)ifam2, 7537b6ab19dSGarrett Wollman ifam->ifam_addrs); 7547b6ab19dSGarrett Wollman 755d5b718b3SGarrett Wollman /* Prepare for the next address of this interface, which 756d5b718b3SGarrett Wollman * will be an alias. 757d5b718b3SGarrett Wollman * Do not output RIP or Router-Discovery packets via aliases. 758d5b718b3SGarrett Wollman */ 7592c7a9781SMark Murray memcpy(&ifs, &ifs0, sizeof(ifs)); 7602c7a9781SMark Murray ifs0.int_state |= (IS_ALIAS | IS_NO_RIP_OUT | IS_NO_RDISC); 761d5b718b3SGarrett Wollman 7627b6ab19dSGarrett Wollman if (INFO_IFA(&info) == 0) { 7632c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 7647b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NOADDR)) 7657b6ab19dSGarrett Wollman msglog("%s has no address", 766d5b718b3SGarrett Wollman ifs.int_name); 7677b6ab19dSGarrett Wollman complaints |= COMP_NOADDR; 7687b6ab19dSGarrett Wollman } 7697b6ab19dSGarrett Wollman continue; 7707b6ab19dSGarrett Wollman } 7717b6ab19dSGarrett Wollman if (INFO_IFA(&info)->sa_family != AF_INET) { 7722c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 7737b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NOT_INET)) 774d5b718b3SGarrett Wollman trace_act("%s: not AF_INET", 775d5b718b3SGarrett Wollman ifs.int_name); 7767b6ab19dSGarrett Wollman complaints |= COMP_NOT_INET; 7777b6ab19dSGarrett Wollman } 7787b6ab19dSGarrett Wollman continue; 7797b6ab19dSGarrett Wollman } 7807b6ab19dSGarrett Wollman 7817b6ab19dSGarrett Wollman ifs.int_addr = S_ADDR(INFO_IFA(&info)); 7827b6ab19dSGarrett Wollman 7837b6ab19dSGarrett Wollman if (ntohl(ifs.int_addr)>>24 == 0 7847b6ab19dSGarrett Wollman || ntohl(ifs.int_addr)>>24 == 0xff) { 7852c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 7867b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_BADADDR)) 7877b6ab19dSGarrett Wollman msglog("%s has a bad address", 788d5b718b3SGarrett Wollman ifs.int_name); 7897b6ab19dSGarrett Wollman complaints |= COMP_BADADDR; 7907b6ab19dSGarrett Wollman } 7917b6ab19dSGarrett Wollman continue; 7927b6ab19dSGarrett Wollman } 7937b6ab19dSGarrett Wollman 794d5b718b3SGarrett Wollman if (ifs.int_if_flags & IFF_LOOPBACK) { 795e53915c9SPoul-Henning Kamp ifs.int_state |= IS_NO_RIP | IS_NO_RDISC; 79652146665SMaxim Konovalov if (ifs.int_addr == htonl(INADDR_LOOPBACK)) 797e53915c9SPoul-Henning Kamp ifs.int_state |= IS_PASSIVE; 7987b6ab19dSGarrett Wollman ifs.int_dstaddr = ifs.int_addr; 799d5b718b3SGarrett Wollman ifs.int_mask = HOST_MASK; 800d5b718b3SGarrett Wollman ifs.int_ripv1_mask = HOST_MASK; 801d5b718b3SGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_dstaddr); 802d5b718b3SGarrett Wollman ifs.int_net = ntohl(ifs.int_dstaddr); 803d5b718b3SGarrett Wollman if (!foundloopback) { 804d5b718b3SGarrett Wollman foundloopback = 1; 805d5b718b3SGarrett Wollman loopaddr = ifs.int_addr; 8062c7a9781SMark Murray loop_rts.rts_gate = loopaddr; 8072c7a9781SMark Murray loop_rts.rts_router = loopaddr; 8087b6ab19dSGarrett Wollman } 8097b6ab19dSGarrett Wollman 8107b6ab19dSGarrett Wollman } else if (ifs.int_if_flags & IFF_POINTOPOINT) { 8117b6ab19dSGarrett Wollman if (INFO_BRD(&info) == 0 8127b6ab19dSGarrett Wollman || INFO_BRD(&info)->sa_family != AF_INET) { 8132c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 8147b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NODST)) 8157b6ab19dSGarrett Wollman msglog("%s has a bad" 8167b6ab19dSGarrett Wollman " destination address", 817d5b718b3SGarrett Wollman ifs.int_name); 8187b6ab19dSGarrett Wollman complaints |= COMP_NODST; 8197b6ab19dSGarrett Wollman } 8207b6ab19dSGarrett Wollman continue; 8217b6ab19dSGarrett Wollman } 8227b6ab19dSGarrett Wollman ifs.int_dstaddr = S_ADDR(INFO_BRD(&info)); 8237b6ab19dSGarrett Wollman if (ntohl(ifs.int_dstaddr)>>24 == 0 8247b6ab19dSGarrett Wollman || ntohl(ifs.int_dstaddr)>>24 == 0xff) { 8252c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 8267b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NODST)) 8277b6ab19dSGarrett Wollman msglog("%s has a bad" 8287b6ab19dSGarrett Wollman " destination address", 829d5b718b3SGarrett Wollman ifs.int_name); 8307b6ab19dSGarrett Wollman complaints |= COMP_NODST; 8317b6ab19dSGarrett Wollman } 8327b6ab19dSGarrett Wollman continue; 8337b6ab19dSGarrett Wollman } 8347b6ab19dSGarrett Wollman ifs.int_mask = HOST_MASK; 8357b6ab19dSGarrett Wollman ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info))); 8367b6ab19dSGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_dstaddr); 8377b6ab19dSGarrett Wollman ifs.int_net = ntohl(ifs.int_dstaddr); 8387b6ab19dSGarrett Wollman 8397b6ab19dSGarrett Wollman } else { 840d5b718b3SGarrett Wollman if (INFO_MASK(&info) == 0) { 8412c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 842d5b718b3SGarrett Wollman if (!(prev_complaints & COMP_NOMASK)) 843d5b718b3SGarrett Wollman msglog("%s has no netmask", 844d5b718b3SGarrett Wollman ifs.int_name); 845d5b718b3SGarrett Wollman complaints |= COMP_NOMASK; 846d5b718b3SGarrett Wollman } 8477b6ab19dSGarrett Wollman continue; 8487b6ab19dSGarrett Wollman } 849d5b718b3SGarrett Wollman ifs.int_dstaddr = ifs.int_addr; 850d5b718b3SGarrett Wollman ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info))); 851d5b718b3SGarrett Wollman ifs.int_ripv1_mask = ifs.int_mask; 852d5b718b3SGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_addr); 853d5b718b3SGarrett Wollman ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask; 854d5b718b3SGarrett Wollman if (ifs.int_mask != ifs.int_std_mask) 855d5b718b3SGarrett Wollman ifs.int_state |= IS_SUBNET; 856d5b718b3SGarrett Wollman 857d5b718b3SGarrett Wollman if (ifs.int_if_flags & IFF_BROADCAST) { 858d5b718b3SGarrett Wollman if (INFO_BRD(&info) == 0) { 8592c7a9781SMark Murray if (iff_up(ifs.int_if_flags)) { 860d5b718b3SGarrett Wollman if (!(prev_complaints 861d5b718b3SGarrett Wollman & COMP_NOBADR)) 862d5b718b3SGarrett Wollman msglog("%s has" 863d5b718b3SGarrett Wollman "no broadcast address", 864d5b718b3SGarrett Wollman ifs.int_name); 865d5b718b3SGarrett Wollman complaints |= COMP_NOBADR; 866d5b718b3SGarrett Wollman } 867d5b718b3SGarrett Wollman continue; 868d5b718b3SGarrett Wollman } 869d5b718b3SGarrett Wollman ifs.int_brdaddr = S_ADDR(INFO_BRD(&info)); 870d5b718b3SGarrett Wollman } 871d5b718b3SGarrett Wollman } 8727b6ab19dSGarrett Wollman ifs.int_std_net = ifs.int_net & ifs.int_std_mask; 8737b6ab19dSGarrett Wollman ifs.int_std_addr = htonl(ifs.int_std_net); 8747b6ab19dSGarrett Wollman 8757b6ab19dSGarrett Wollman /* Use a minimum metric of one. Treat the interface metric 8767b6ab19dSGarrett Wollman * (default 0) as an increment to the hop count of one. 8777b6ab19dSGarrett Wollman * 8787b6ab19dSGarrett Wollman * The metric obtained from the routing socket dump of 8797b6ab19dSGarrett Wollman * interface addresses is wrong. It is not set by the 8807b6ab19dSGarrett Wollman * SIOCSIFMETRIC ioctl. 8817b6ab19dSGarrett Wollman */ 8827b6ab19dSGarrett Wollman #ifdef SIOCGIFMETRIC 883d5b718b3SGarrett Wollman strncpy(ifr.ifr_name, ifs.int_name, sizeof(ifr.ifr_name)); 8847b6ab19dSGarrett Wollman if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) { 8857b6ab19dSGarrett Wollman DBGERR(1, "ioctl(SIOCGIFMETRIC)"); 8867b6ab19dSGarrett Wollman ifs.int_metric = 0; 8877b6ab19dSGarrett Wollman } else { 8887b6ab19dSGarrett Wollman ifs.int_metric = ifr.ifr_metric; 8897b6ab19dSGarrett Wollman } 8907b6ab19dSGarrett Wollman #else 8917b6ab19dSGarrett Wollman ifs.int_metric = ifam->ifam_metric; 8927b6ab19dSGarrett Wollman #endif 8937b6ab19dSGarrett Wollman if (ifs.int_metric > HOPCNT_INFINITY) { 8947b6ab19dSGarrett Wollman ifs.int_metric = 0; 8957b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_BAD_METRIC) 8962c7a9781SMark Murray && iff_up(ifs.int_if_flags)) { 8977b6ab19dSGarrett Wollman complaints |= COMP_BAD_METRIC; 8987b6ab19dSGarrett Wollman msglog("%s has a metric of %d", 899d5b718b3SGarrett Wollman ifs.int_name, ifs.int_metric); 9007b6ab19dSGarrett Wollman } 9017b6ab19dSGarrett Wollman } 9027b6ab19dSGarrett Wollman 9037b6ab19dSGarrett Wollman /* See if this is a familiar interface. 9047b6ab19dSGarrett Wollman * If so, stop worrying about it if it is the same. 9057b6ab19dSGarrett Wollman * Start it over if it now is to somewhere else, as happens 9067b6ab19dSGarrett Wollman * frequently with PPP and SLIP. 9077b6ab19dSGarrett Wollman */ 908d5b718b3SGarrett Wollman ifp = ifwithname(ifs.int_name, ((ifs.int_state & IS_ALIAS) 9097b6ab19dSGarrett Wollman ? ifs.int_addr 9107b6ab19dSGarrett Wollman : 0)); 911562c5a82SPedro F. Giffuni if (ifp != NULL) { 9127b6ab19dSGarrett Wollman ifp->int_state |= IS_CHECKED; 9137b6ab19dSGarrett Wollman 9147b6ab19dSGarrett Wollman if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags) 9157b6ab19dSGarrett Wollman & (IFF_BROADCAST 9167b6ab19dSGarrett Wollman | IFF_LOOPBACK 9177b6ab19dSGarrett Wollman | IFF_POINTOPOINT 9187b6ab19dSGarrett Wollman | IFF_MULTICAST)) 9197b6ab19dSGarrett Wollman || 0 != ((ifp->int_state ^ ifs.int_state) 9207b6ab19dSGarrett Wollman & IS_ALIAS) 9217b6ab19dSGarrett Wollman || ifp->int_addr != ifs.int_addr 9227b6ab19dSGarrett Wollman || ifp->int_brdaddr != ifs.int_brdaddr 9237b6ab19dSGarrett Wollman || ifp->int_dstaddr != ifs.int_dstaddr 9247b6ab19dSGarrett Wollman || ifp->int_mask != ifs.int_mask 9257b6ab19dSGarrett Wollman || ifp->int_metric != ifs.int_metric) { 9267b6ab19dSGarrett Wollman /* Forget old information about 9277b6ab19dSGarrett Wollman * a changed interface. 9287b6ab19dSGarrett Wollman */ 929d5b718b3SGarrett Wollman trace_act("interface %s has changed", 9307b6ab19dSGarrett Wollman ifp->int_name); 9317b6ab19dSGarrett Wollman ifdel(ifp); 932562c5a82SPedro F. Giffuni ifp = NULL; 9337b6ab19dSGarrett Wollman } 9347b6ab19dSGarrett Wollman } 9357b6ab19dSGarrett Wollman 936562c5a82SPedro F. Giffuni if (ifp != NULL) { 9377b6ab19dSGarrett Wollman /* The primary representative of an alias worries 9387b6ab19dSGarrett Wollman * about how things are working. 9397b6ab19dSGarrett Wollman */ 9407b6ab19dSGarrett Wollman if (ifp->int_state & IS_ALIAS) 9417b6ab19dSGarrett Wollman continue; 9427b6ab19dSGarrett Wollman 9437b6ab19dSGarrett Wollman /* note interfaces that have been turned off 9447b6ab19dSGarrett Wollman */ 9452c7a9781SMark Murray if (!iff_up(ifs.int_if_flags)) { 9462c7a9781SMark Murray if (iff_up(ifp->int_if_flags)) { 9477b6ab19dSGarrett Wollman msglog("interface %s to %s turned off", 9487b6ab19dSGarrett Wollman ifp->int_name, 949d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr)); 9507b6ab19dSGarrett Wollman if_bad(ifp); 9512c7a9781SMark Murray ifp->int_if_flags &= ~IFF_UP; 9522c7a9781SMark Murray } else if (now.tv_sec>(ifp->int_data.ts 9532c7a9781SMark Murray + CHECK_BAD_INTERVAL)) { 9542c7a9781SMark Murray trace_act("interface %s has been off" 955b108792dSUlrich Spörlein " %jd seconds; forget it", 9562c7a9781SMark Murray ifp->int_name, 957b108792dSUlrich Spörlein (intmax_t)now.tv_sec - 9589940236eSPoul-Henning Kamp ifp->int_data.ts); 9592c7a9781SMark Murray ifdel(ifp); 9600b279f8cSPedro F. Giffuni ifp = NULL; 9617b6ab19dSGarrett Wollman } 9627b6ab19dSGarrett Wollman continue; 9637b6ab19dSGarrett Wollman } 9647b6ab19dSGarrett Wollman /* or that were off and are now ok */ 9652c7a9781SMark Murray if (!iff_up(ifp->int_if_flags)) { 9662c7a9781SMark Murray ifp->int_if_flags |= IFF_UP; 9677b6ab19dSGarrett Wollman (void)if_ok(ifp, ""); 9687b6ab19dSGarrett Wollman } 9697b6ab19dSGarrett Wollman 9707b6ab19dSGarrett Wollman /* If it has been long enough, 9717b6ab19dSGarrett Wollman * see if the interface is broken. 9727b6ab19dSGarrett Wollman */ 9737b6ab19dSGarrett Wollman if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL) 9747b6ab19dSGarrett Wollman continue; 9757b6ab19dSGarrett Wollman 9767b6ab19dSGarrett Wollman in = ifs.int_data.ipackets - ifp->int_data.ipackets; 9777b6ab19dSGarrett Wollman ierr = ifs.int_data.ierrors - ifp->int_data.ierrors; 9787b6ab19dSGarrett Wollman out = ifs.int_data.opackets - ifp->int_data.opackets; 9797b6ab19dSGarrett Wollman oerr = ifs.int_data.oerrors - ifp->int_data.oerrors; 9807b6ab19dSGarrett Wollman #ifdef sgi 9817b6ab19dSGarrett Wollman /* Through at least IRIX 6.2, PPP and SLIP 9827b6ab19dSGarrett Wollman * count packets dropped by the filters. 9837b6ab19dSGarrett Wollman * But FDDI rings stuck non-operational count 9847b6ab19dSGarrett Wollman * dropped packets as they wait for improvement. 9857b6ab19dSGarrett Wollman */ 9867b6ab19dSGarrett Wollman if (!(ifp->int_if_flags & IFF_POINTOPOINT)) 9877b6ab19dSGarrett Wollman oerr += (ifs.int_data.odrops 9887b6ab19dSGarrett Wollman - ifp->int_data.odrops); 9897b6ab19dSGarrett Wollman #endif 9907b6ab19dSGarrett Wollman /* If the interface just awoke, restart the counters. 9917b6ab19dSGarrett Wollman */ 9927b6ab19dSGarrett Wollman if (ifp->int_data.ts == 0) { 9937b6ab19dSGarrett Wollman ifp->int_data = ifs.int_data; 9947b6ab19dSGarrett Wollman continue; 9957b6ab19dSGarrett Wollman } 9967b6ab19dSGarrett Wollman ifp->int_data = ifs.int_data; 9977b6ab19dSGarrett Wollman 99890100551SPhilippe Charnier /* Withhold judgment when the short error 9997b6ab19dSGarrett Wollman * counters wrap or the interface is reset. 10007b6ab19dSGarrett Wollman */ 10017b6ab19dSGarrett Wollman if (ierr < 0 || in < 0 || oerr < 0 || out < 0) { 10027b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, 10037b6ab19dSGarrett Wollman now.tv_sec+CHECK_BAD_INTERVAL); 10047b6ab19dSGarrett Wollman continue; 10057b6ab19dSGarrett Wollman } 10067b6ab19dSGarrett Wollman 10077b6ab19dSGarrett Wollman /* Withhold judgement when there is no traffic 10087b6ab19dSGarrett Wollman */ 10097b6ab19dSGarrett Wollman if (in == 0 && out == 0 && ierr == 0 && oerr == 0) 10107b6ab19dSGarrett Wollman continue; 10117b6ab19dSGarrett Wollman 10127b6ab19dSGarrett Wollman /* It is bad if input or output is not working. 10137b6ab19dSGarrett Wollman * Require presistent problems before marking it dead. 10147b6ab19dSGarrett Wollman */ 10157b6ab19dSGarrett Wollman if ((in <= ierr && ierr > 0) 10167b6ab19dSGarrett Wollman || (out <= oerr && oerr > 0)) { 10177b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_SICK)) { 10187b6ab19dSGarrett Wollman trace_act("interface %s to %s" 10197b6ab19dSGarrett Wollman " sick: in=%d ierr=%d" 1020d5b718b3SGarrett Wollman " out=%d oerr=%d", 10217b6ab19dSGarrett Wollman ifp->int_name, 1022d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr), 10237b6ab19dSGarrett Wollman in, ierr, out, oerr); 10247b6ab19dSGarrett Wollman if_sick(ifp); 10257b6ab19dSGarrett Wollman continue; 10267b6ab19dSGarrett Wollman } 10277b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 1028d5b718b3SGarrett Wollman msglog("interface %s to %s broken:" 10297b6ab19dSGarrett Wollman " in=%d ierr=%d out=%d oerr=%d", 10307b6ab19dSGarrett Wollman ifp->int_name, 1031d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr), 10327b6ab19dSGarrett Wollman in, ierr, out, oerr); 10337b6ab19dSGarrett Wollman if_bad(ifp); 10347b6ab19dSGarrett Wollman } 10357b6ab19dSGarrett Wollman continue; 10367b6ab19dSGarrett Wollman } 10377b6ab19dSGarrett Wollman 10387b6ab19dSGarrett Wollman /* otherwise, it is active and healthy 10397b6ab19dSGarrett Wollman */ 10407b6ab19dSGarrett Wollman ifp->int_act_time = now.tv_sec; 10417b6ab19dSGarrett Wollman (void)if_ok(ifp, ""); 10427b6ab19dSGarrett Wollman continue; 10437b6ab19dSGarrett Wollman } 10447b6ab19dSGarrett Wollman 10457b6ab19dSGarrett Wollman /* This is a new interface. 10467b6ab19dSGarrett Wollman * If it is dead, forget it. 10477b6ab19dSGarrett Wollman */ 10482c7a9781SMark Murray if (!iff_up(ifs.int_if_flags)) 10497b6ab19dSGarrett Wollman continue; 10507b6ab19dSGarrett Wollman 1051d5b718b3SGarrett Wollman /* If it duplicates an existing interface, 1052d5b718b3SGarrett Wollman * complain about it, mark the other one 10537b6ab19dSGarrett Wollman * duplicated, and forget this one. 10547b6ab19dSGarrett Wollman */ 1055d5b718b3SGarrett Wollman ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask, 1056d5b718b3SGarrett Wollman ifs.int_if_flags); 1057562c5a82SPedro F. Giffuni if (ifp != NULL) { 10582c7a9781SMark Murray /* Ignore duplicates of itself, caused by having 10592c7a9781SMark Murray * IP aliases on the same network. 10602c7a9781SMark Murray */ 10612c7a9781SMark Murray if (!strcmp(ifp->int_name, ifs.int_name)) 10622c7a9781SMark Murray continue; 10632c7a9781SMark Murray 10647b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_DUP)) { 10657b6ab19dSGarrett Wollman complaints |= COMP_DUP; 106671965874SGarrett Wollman msglog("%s (%s%s%s) is duplicated by" 106771965874SGarrett Wollman " %s (%s%s%s)", 106871965874SGarrett Wollman ifs.int_name, 106971965874SGarrett Wollman addrname(ifs.int_addr,ifs.int_mask,1), 107071965874SGarrett Wollman ((ifs.int_if_flags & IFF_POINTOPOINT) 107171965874SGarrett Wollman ? "-->" : ""), 107271965874SGarrett Wollman ((ifs.int_if_flags & IFF_POINTOPOINT) 107371965874SGarrett Wollman ? naddr_ntoa(ifs.int_dstaddr) : ""), 107471965874SGarrett Wollman ifp->int_name, 107571965874SGarrett Wollman addrname(ifp->int_addr,ifp->int_mask,1), 107671965874SGarrett Wollman ((ifp->int_if_flags & IFF_POINTOPOINT) 107771965874SGarrett Wollman ? "-->" : ""), 107871965874SGarrett Wollman ((ifp->int_if_flags & IFF_POINTOPOINT) 107971965874SGarrett Wollman ? naddr_ntoa(ifp->int_dstaddr) : "")); 10807b6ab19dSGarrett Wollman } 10817b6ab19dSGarrett Wollman ifp->int_state |= IS_DUP; 10827b6ab19dSGarrett Wollman continue; 1083d5b718b3SGarrett Wollman } 10847b6ab19dSGarrett Wollman 1085e53915c9SPoul-Henning Kamp if (0 == (ifs.int_if_flags & (IFF_POINTOPOINT | IFF_BROADCAST | IFF_LOOPBACK))) { 1086d5b718b3SGarrett Wollman trace_act("%s is neither broadcast, point-to-point," 1087d5b718b3SGarrett Wollman " nor loopback", 1088d5b718b3SGarrett Wollman ifs.int_name); 1089d5b718b3SGarrett Wollman if (!(ifs.int_state & IFF_MULTICAST)) 1090d5b718b3SGarrett Wollman ifs.int_state |= IS_NO_RDISC; 1091d5b718b3SGarrett Wollman } 10927b6ab19dSGarrett Wollman 1093d5b718b3SGarrett Wollman 1094d5b718b3SGarrett Wollman /* It is new and ok. Add it to the list of interfaces 10957b6ab19dSGarrett Wollman */ 10962c7a9781SMark Murray ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit ifp"); 10972c7a9781SMark Murray memcpy(ifp, &ifs, sizeof(*ifp)); 1098d5b718b3SGarrett Wollman get_parms(ifp); 1099d5b718b3SGarrett Wollman if_link(ifp); 11007b6ab19dSGarrett Wollman trace_if("Add", ifp); 11017b6ab19dSGarrett Wollman 11027b6ab19dSGarrett Wollman /* Notice likely bad netmask. 11037b6ab19dSGarrett Wollman */ 11047b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NETMASK) 1105d5b718b3SGarrett Wollman && !(ifp->int_if_flags & IFF_POINTOPOINT) 1106d5b718b3SGarrett Wollman && ifp->int_addr != RIP_DEFAULT) { 110738ae6523SPoul-Henning Kamp LIST_FOREACH(ifp1, &ifnet, int_list) { 11087b6ab19dSGarrett Wollman if (ifp1->int_mask == ifp->int_mask) 11097b6ab19dSGarrett Wollman continue; 11107b6ab19dSGarrett Wollman if (ifp1->int_if_flags & IFF_POINTOPOINT) 11117b6ab19dSGarrett Wollman continue; 1112d5b718b3SGarrett Wollman if (ifp1->int_dstaddr == RIP_DEFAULT) 1113d5b718b3SGarrett Wollman continue; 11148b336df1SSheldon Hearn /* ignore aliases on the right network */ 11158b336df1SSheldon Hearn if (!strcmp(ifp->int_name, ifp1->int_name)) 11168b336df1SSheldon Hearn continue; 1117d5b718b3SGarrett Wollman if (on_net(ifp->int_dstaddr, 11187b6ab19dSGarrett Wollman ifp1->int_net, ifp1->int_mask) 1119d5b718b3SGarrett Wollman || on_net(ifp1->int_dstaddr, 11207b6ab19dSGarrett Wollman ifp->int_net, ifp->int_mask)) { 11217b6ab19dSGarrett Wollman msglog("possible netmask problem" 1122d5b718b3SGarrett Wollman " between %s:%s and %s:%s", 11237b6ab19dSGarrett Wollman ifp->int_name, 11247b6ab19dSGarrett Wollman addrname(htonl(ifp->int_net), 11257b6ab19dSGarrett Wollman ifp->int_mask, 1), 11267b6ab19dSGarrett Wollman ifp1->int_name, 11277b6ab19dSGarrett Wollman addrname(htonl(ifp1->int_net), 11287b6ab19dSGarrett Wollman ifp1->int_mask, 1)); 11297b6ab19dSGarrett Wollman complaints |= COMP_NETMASK; 11307b6ab19dSGarrett Wollman } 11317b6ab19dSGarrett Wollman } 11327b6ab19dSGarrett Wollman } 11337b6ab19dSGarrett Wollman 1134d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 11357b6ab19dSGarrett Wollman /* Count the # of directly connected networks. 11367b6ab19dSGarrett Wollman */ 11377b6ab19dSGarrett Wollman if (!(ifp->int_if_flags & IFF_LOOPBACK)) 11387b6ab19dSGarrett Wollman tot_interfaces++; 11397b6ab19dSGarrett Wollman if (!IS_RIP_OFF(ifp->int_state)) 11407b6ab19dSGarrett Wollman rip_interfaces++; 11417b6ab19dSGarrett Wollman 1142d5b718b3SGarrett Wollman /* turn on router discovery and RIP If needed */ 11437b6ab19dSGarrett Wollman if_ok_rdisc(ifp); 11447b6ab19dSGarrett Wollman rip_on(ifp); 11457b6ab19dSGarrett Wollman } 1146d5b718b3SGarrett Wollman } 11477b6ab19dSGarrett Wollman 1148d5b718b3SGarrett Wollman /* If we are multi-homed and have at least two interfaces 11497b6ab19dSGarrett Wollman * listening to RIP, then output by default. 11507b6ab19dSGarrett Wollman */ 11517b6ab19dSGarrett Wollman if (!supplier_set && rip_interfaces > 1) 11527b6ab19dSGarrett Wollman set_supplier(); 11537b6ab19dSGarrett Wollman 11547b6ab19dSGarrett Wollman /* If we are multi-homed, optionally advertise a route to 11557b6ab19dSGarrett Wollman * our main address. 11567b6ab19dSGarrett Wollman */ 11570b279f8cSPedro F. Giffuni if ((advertise_mhome && ifp) 11587b6ab19dSGarrett Wollman || (tot_interfaces > 1 11597b6ab19dSGarrett Wollman && mhome 1160562c5a82SPedro F. Giffuni && (ifp = ifwithaddr(myaddr, 0, 0)) != NULL 11617b6ab19dSGarrett Wollman && foundloopback)) { 11627b6ab19dSGarrett Wollman advertise_mhome = 1; 11637b6ab19dSGarrett Wollman rt = rtget(myaddr, HOST_MASK); 1164562c5a82SPedro F. Giffuni if (rt != NULL) { 11657b6ab19dSGarrett Wollman if (rt->rt_ifp != ifp 11667b6ab19dSGarrett Wollman || rt->rt_router != loopaddr) { 11677b6ab19dSGarrett Wollman rtdelete(rt); 1168562c5a82SPedro F. Giffuni rt = NULL; 11697b6ab19dSGarrett Wollman } else { 11702c7a9781SMark Murray loop_rts.rts_ifp = ifp; 11712c7a9781SMark Murray loop_rts.rts_metric = 0; 11722c7a9781SMark Murray loop_rts.rts_time = rt->rt_time; 11737b6ab19dSGarrett Wollman rtchange(rt, rt->rt_state | RS_MHOME, 11742c7a9781SMark Murray &loop_rts, 0); 11757b6ab19dSGarrett Wollman } 11767b6ab19dSGarrett Wollman } 1177562c5a82SPedro F. Giffuni if (rt == NULL) { 11782c7a9781SMark Murray loop_rts.rts_ifp = ifp; 11792c7a9781SMark Murray loop_rts.rts_metric = 0; 11802c7a9781SMark Murray rtadd(myaddr, HOST_MASK, RS_MHOME, &loop_rts); 11812c7a9781SMark Murray } 11827b6ab19dSGarrett Wollman } 11837b6ab19dSGarrett Wollman 118438ae6523SPoul-Henning Kamp LIST_FOREACH_SAFE(ifp, &ifnet, int_list, ifp1) { 11857b6ab19dSGarrett Wollman /* Forget any interfaces that have disappeared. 11867b6ab19dSGarrett Wollman */ 11877b6ab19dSGarrett Wollman if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) { 1188d5b718b3SGarrett Wollman trace_act("interface %s has disappeared", 11897b6ab19dSGarrett Wollman ifp->int_name); 11907b6ab19dSGarrett Wollman ifdel(ifp); 11917b6ab19dSGarrett Wollman continue; 11927b6ab19dSGarrett Wollman } 11937b6ab19dSGarrett Wollman 11947b6ab19dSGarrett Wollman if ((ifp->int_state & IS_BROKE) 11957b6ab19dSGarrett Wollman && !(ifp->int_state & IS_PASSIVE)) 11967b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 11977b6ab19dSGarrett Wollman 11987b6ab19dSGarrett Wollman /* If we ever have a RIPv1 interface, assume we always will. 11997b6ab19dSGarrett Wollman * It might come back if it ever goes away. 12007b6ab19dSGarrett Wollman */ 12017b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier) 12027b6ab19dSGarrett Wollman have_ripv1_out = 1; 12037b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_NO_RIPV1_IN)) 12047b6ab19dSGarrett Wollman have_ripv1_in = 1; 12057b6ab19dSGarrett Wollman } 12067b6ab19dSGarrett Wollman 120738ae6523SPoul-Henning Kamp LIST_FOREACH(ifp, &ifnet, int_list) { 12087b6ab19dSGarrett Wollman /* Ensure there is always a network route for interfaces, 12097b6ab19dSGarrett Wollman * after any dead interfaces have been deleted, which 12107b6ab19dSGarrett Wollman * might affect routes for point-to-point links. 12117b6ab19dSGarrett Wollman */ 1212d5b718b3SGarrett Wollman if (!addrouteforif(ifp)) 1213d5b718b3SGarrett Wollman continue; 12147b6ab19dSGarrett Wollman 12157b6ab19dSGarrett Wollman /* Add routes to the local end of point-to-point interfaces 12167b6ab19dSGarrett Wollman * using loopback. 12177b6ab19dSGarrett Wollman */ 12187b6ab19dSGarrett Wollman if ((ifp->int_if_flags & IFF_POINTOPOINT) 12197b6ab19dSGarrett Wollman && !(ifp->int_state & IS_REMOTE) 12207b6ab19dSGarrett Wollman && foundloopback) { 12217b6ab19dSGarrett Wollman /* Delete any routes to the network address through 12227b6ab19dSGarrett Wollman * foreign routers. Remove even static routes. 12237b6ab19dSGarrett Wollman */ 12242c7a9781SMark Murray del_static(ifp->int_addr, HOST_MASK, 0, 0); 12257b6ab19dSGarrett Wollman rt = rtget(ifp->int_addr, HOST_MASK); 1226562c5a82SPedro F. Giffuni if (rt != NULL && rt->rt_router != loopaddr) { 12277b6ab19dSGarrett Wollman rtdelete(rt); 1228562c5a82SPedro F. Giffuni rt = NULL; 12297b6ab19dSGarrett Wollman } 1230562c5a82SPedro F. Giffuni if (rt != NULL) { 12317b6ab19dSGarrett Wollman if (!(rt->rt_state & RS_LOCAL) 12327b6ab19dSGarrett Wollman || rt->rt_metric > ifp->int_metric) { 12337b6ab19dSGarrett Wollman ifp1 = ifp; 12347b6ab19dSGarrett Wollman } else { 12357b6ab19dSGarrett Wollman ifp1 = rt->rt_ifp; 12367b6ab19dSGarrett Wollman } 12372c7a9781SMark Murray loop_rts.rts_ifp = ifp1; 12382c7a9781SMark Murray loop_rts.rts_metric = 0; 12392c7a9781SMark Murray loop_rts.rts_time = rt->rt_time; 12407b6ab19dSGarrett Wollman rtchange(rt, ((rt->rt_state & ~RS_NET_SYN) 12417b6ab19dSGarrett Wollman | (RS_IF|RS_LOCAL)), 12422c7a9781SMark Murray &loop_rts, 0); 12437b6ab19dSGarrett Wollman } else { 12442c7a9781SMark Murray loop_rts.rts_ifp = ifp; 12452c7a9781SMark Murray loop_rts.rts_metric = 0; 12467b6ab19dSGarrett Wollman rtadd(ifp->int_addr, HOST_MASK, 12472c7a9781SMark Murray (RS_IF | RS_LOCAL), &loop_rts); 12487b6ab19dSGarrett Wollman } 12497b6ab19dSGarrett Wollman } 12507b6ab19dSGarrett Wollman } 12517b6ab19dSGarrett Wollman 12527b6ab19dSGarrett Wollman /* add the authority routes */ 1253562c5a82SPedro F. Giffuni for (intnetp = intnets; intnetp != NULL; 1254562c5a82SPedro F. Giffuni intnetp = intnetp->intnet_next) { 12557b6ab19dSGarrett Wollman rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask); 1256562c5a82SPedro F. Giffuni if (rt != NULL 12577b6ab19dSGarrett Wollman && !(rt->rt_state & RS_NO_NET_SYN) 12587b6ab19dSGarrett Wollman && !(rt->rt_state & RS_NET_INT)) { 12597b6ab19dSGarrett Wollman rtdelete(rt); 1260562c5a82SPedro F. Giffuni rt = NULL; 12617b6ab19dSGarrett Wollman } 1262562c5a82SPedro F. Giffuni if (rt == NULL) { 1263562c5a82SPedro F. Giffuni loop_rts.rts_ifp = NULL; 12642c7a9781SMark Murray loop_rts.rts_metric = intnetp->intnet_metric-1; 12657b6ab19dSGarrett Wollman rtadd(intnetp->intnet_addr, intnetp->intnet_mask, 12662c7a9781SMark Murray RS_NET_SYN | RS_NET_INT, &loop_rts); 12672c7a9781SMark Murray } 12687b6ab19dSGarrett Wollman } 12697b6ab19dSGarrett Wollman 12707b6ab19dSGarrett Wollman prev_complaints = complaints; 12717b6ab19dSGarrett Wollman } 12727b6ab19dSGarrett Wollman 12737b6ab19dSGarrett Wollman 12747b6ab19dSGarrett Wollman static void 12757b6ab19dSGarrett Wollman check_net_syn(struct interface *ifp) 12767b6ab19dSGarrett Wollman { 12777b6ab19dSGarrett Wollman struct rt_entry *rt; 12782c7a9781SMark Murray static struct rt_spare new; 12797b6ab19dSGarrett Wollman 12807b6ab19dSGarrett Wollman 12817b6ab19dSGarrett Wollman /* Turn on the need to automatically synthesize a network route 12827b6ab19dSGarrett Wollman * for this interface only if we are running RIPv1 on some other 12837b6ab19dSGarrett Wollman * interface that is on a different class-A,B,or C network. 12847b6ab19dSGarrett Wollman */ 12857b6ab19dSGarrett Wollman if (have_ripv1_out || have_ripv1_in) { 12867b6ab19dSGarrett Wollman ifp->int_state |= IS_NEED_NET_SYN; 12877b6ab19dSGarrett Wollman rt = rtget(ifp->int_std_addr, ifp->int_std_mask); 1288562c5a82SPedro F. Giffuni if (rt != NULL 12897b6ab19dSGarrett Wollman && 0 == (rt->rt_state & RS_NO_NET_SYN) 12907b6ab19dSGarrett Wollman && (!(rt->rt_state & RS_NET_SYN) 12917b6ab19dSGarrett Wollman || rt->rt_metric > ifp->int_metric)) { 12927b6ab19dSGarrett Wollman rtdelete(rt); 1293562c5a82SPedro F. Giffuni rt = NULL; 12947b6ab19dSGarrett Wollman } 1295562c5a82SPedro F. Giffuni if (rt == NULL) { 12962c7a9781SMark Murray new.rts_ifp = ifp; 12972c7a9781SMark Murray new.rts_gate = ifp->int_addr; 12982c7a9781SMark Murray new.rts_router = ifp->int_addr; 12992c7a9781SMark Murray new.rts_metric = ifp->int_metric; 13007b6ab19dSGarrett Wollman rtadd(ifp->int_std_addr, ifp->int_std_mask, 13012c7a9781SMark Murray RS_NET_SYN, &new); 13022c7a9781SMark Murray } 13037b6ab19dSGarrett Wollman 13047b6ab19dSGarrett Wollman } else { 13057b6ab19dSGarrett Wollman ifp->int_state &= ~IS_NEED_NET_SYN; 13067b6ab19dSGarrett Wollman 13077b6ab19dSGarrett Wollman rt = rtget(ifp->int_std_addr, 13087b6ab19dSGarrett Wollman ifp->int_std_mask); 1309562c5a82SPedro F. Giffuni if (rt != NULL 13107b6ab19dSGarrett Wollman && (rt->rt_state & RS_NET_SYN) 13117b6ab19dSGarrett Wollman && rt->rt_ifp == ifp) 13127b6ab19dSGarrett Wollman rtbad_sub(rt); 13137b6ab19dSGarrett Wollman } 13147b6ab19dSGarrett Wollman } 13157b6ab19dSGarrett Wollman 13167b6ab19dSGarrett Wollman 13177b6ab19dSGarrett Wollman /* Add route for interface if not currently installed. 13187b6ab19dSGarrett Wollman * Create route to other end if a point-to-point link, 13197b6ab19dSGarrett Wollman * otherwise a route to this (sub)network. 13207b6ab19dSGarrett Wollman */ 1321f2ca6d8aSPoul-Henning Kamp static int /* 0=bad interface */ 13227b6ab19dSGarrett Wollman addrouteforif(struct interface *ifp) 13237b6ab19dSGarrett Wollman { 13247b6ab19dSGarrett Wollman struct rt_entry *rt; 13252c7a9781SMark Murray static struct rt_spare new; 13262c7a9781SMark Murray naddr dst; 13277b6ab19dSGarrett Wollman 13287b6ab19dSGarrett Wollman 13297b6ab19dSGarrett Wollman /* skip sick interfaces 13307b6ab19dSGarrett Wollman */ 13317b6ab19dSGarrett Wollman if (ifp->int_state & IS_BROKE) 1332d5b718b3SGarrett Wollman return 0; 13337b6ab19dSGarrett Wollman 13347b6ab19dSGarrett Wollman /* If the interface on a subnet, then install a RIPv1 route to 13357b6ab19dSGarrett Wollman * the network as well (unless it is sick). 13367b6ab19dSGarrett Wollman */ 13377b6ab19dSGarrett Wollman if (ifp->int_state & IS_SUBNET) 13387b6ab19dSGarrett Wollman check_net_syn(ifp); 13397b6ab19dSGarrett Wollman 1340d5b718b3SGarrett Wollman dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) 1341d5b718b3SGarrett Wollman ? ifp->int_dstaddr 1342d5b718b3SGarrett Wollman : htonl(ifp->int_net)); 1343d5b718b3SGarrett Wollman 13442c7a9781SMark Murray new.rts_ifp = ifp; 13452c7a9781SMark Murray new.rts_router = ifp->int_addr; 13462c7a9781SMark Murray new.rts_gate = ifp->int_addr; 13472c7a9781SMark Murray new.rts_metric = ifp->int_metric; 13482c7a9781SMark Murray new.rts_time = now.tv_sec; 13492c7a9781SMark Murray 13507b6ab19dSGarrett Wollman /* If we are going to send packets to the gateway, 13517b6ab19dSGarrett Wollman * it must be reachable using our physical interfaces 13527b6ab19dSGarrett Wollman */ 1353d5b718b3SGarrett Wollman if ((ifp->int_state & IS_REMOTE) 135471965874SGarrett Wollman && !(ifp->int_state & IS_EXTERNAL) 1355d5b718b3SGarrett Wollman && !check_remote(ifp)) 1356d5b718b3SGarrett Wollman return 0; 13577b6ab19dSGarrett Wollman 13587b6ab19dSGarrett Wollman /* We are finished if the correct main interface route exists. 13597b6ab19dSGarrett Wollman * The right route must be for the right interface, not synthesized 13607b6ab19dSGarrett Wollman * from a subnet, be a "gateway" or not as appropriate, and so forth. 13617b6ab19dSGarrett Wollman */ 13622c7a9781SMark Murray del_static(dst, ifp->int_mask, 0, 0); 13637b6ab19dSGarrett Wollman rt = rtget(dst, ifp->int_mask); 1364562c5a82SPedro F. Giffuni if (rt != NULL) { 13657b6ab19dSGarrett Wollman if ((rt->rt_ifp != ifp 13667b6ab19dSGarrett Wollman || rt->rt_router != ifp->int_addr) 13677b6ab19dSGarrett Wollman && (!(ifp->int_state & IS_DUP) 13687b6ab19dSGarrett Wollman || rt->rt_ifp == 0 13697b6ab19dSGarrett Wollman || (rt->rt_ifp->int_state & IS_BROKE))) { 13707b6ab19dSGarrett Wollman rtdelete(rt); 1371562c5a82SPedro F. Giffuni rt = NULL; 13727b6ab19dSGarrett Wollman } else { 13737b6ab19dSGarrett Wollman rtchange(rt, ((rt->rt_state | RS_IF) 13747b6ab19dSGarrett Wollman & ~(RS_NET_SYN | RS_LOCAL)), 13752c7a9781SMark Murray &new, 0); 13767b6ab19dSGarrett Wollman } 13777b6ab19dSGarrett Wollman } 1378562c5a82SPedro F. Giffuni if (rt == NULL) { 13797b6ab19dSGarrett Wollman if (ifp->int_transitions++ > 0) 1380d5b718b3SGarrett Wollman trace_act("re-install interface %s", 13817b6ab19dSGarrett Wollman ifp->int_name); 13827b6ab19dSGarrett Wollman 13832c7a9781SMark Murray rtadd(dst, ifp->int_mask, RS_IF, &new); 13847b6ab19dSGarrett Wollman } 1385d5b718b3SGarrett Wollman 1386d5b718b3SGarrett Wollman return 1; 13877b6ab19dSGarrett Wollman } 1388