17b6ab19dSGarrett Wollman /* 27b6ab19dSGarrett Wollman * Copyright (c) 1983, 1993 37b6ab19dSGarrett Wollman * The Regents of the University of California. All rights reserved. 47b6ab19dSGarrett Wollman * 57b6ab19dSGarrett Wollman * Redistribution and use in source and binary forms, with or without 67b6ab19dSGarrett Wollman * modification, are permitted provided that the following conditions 77b6ab19dSGarrett Wollman * are met: 87b6ab19dSGarrett Wollman * 1. Redistributions of source code must retain the above copyright 97b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer. 107b6ab19dSGarrett Wollman * 2. Redistributions in binary form must reproduce the above copyright 117b6ab19dSGarrett Wollman * notice, this list of conditions and the following disclaimer in the 127b6ab19dSGarrett Wollman * documentation and/or other materials provided with the distribution. 137b6ab19dSGarrett Wollman * 3. All advertising materials mentioning features or use of this software 147b6ab19dSGarrett Wollman * must display the following acknowledgement: 157b6ab19dSGarrett Wollman * This product includes software developed by the University of 167b6ab19dSGarrett Wollman * California, Berkeley and its contributors. 177b6ab19dSGarrett Wollman * 4. Neither the name of the University nor the names of its contributors 187b6ab19dSGarrett Wollman * may be used to endorse or promote products derived from this software 197b6ab19dSGarrett Wollman * without specific prior written permission. 207b6ab19dSGarrett Wollman * 217b6ab19dSGarrett Wollman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227b6ab19dSGarrett Wollman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237b6ab19dSGarrett Wollman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247b6ab19dSGarrett Wollman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257b6ab19dSGarrett Wollman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267b6ab19dSGarrett Wollman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277b6ab19dSGarrett Wollman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287b6ab19dSGarrett Wollman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297b6ab19dSGarrett Wollman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307b6ab19dSGarrett Wollman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317b6ab19dSGarrett Wollman * SUCH DAMAGE. 327b6ab19dSGarrett Wollman */ 337b6ab19dSGarrett Wollman 347b6ab19dSGarrett Wollman #if !defined(lint) && !defined(sgi) && !defined(__NetBSD__) 357b6ab19dSGarrett Wollman static char sccsid[] = "@(#)if.c 8.1 (Berkeley) 6/5/93"; 367b6ab19dSGarrett Wollman #elif defined(__NetBSD__) 377b6ab19dSGarrett Wollman static char rcsid[] = "$NetBSD$"; 387b6ab19dSGarrett Wollman #endif 39d5b718b3SGarrett Wollman #ident "$Revision: 1.18 $" 407b6ab19dSGarrett Wollman 417b6ab19dSGarrett Wollman #include "defs.h" 427b6ab19dSGarrett Wollman #include "pathnames.h" 437b6ab19dSGarrett Wollman 447b6ab19dSGarrett Wollman struct interface *ifnet; /* all interfaces */ 45d5b718b3SGarrett Wollman 46d5b718b3SGarrett Wollman /* hash table for all interfaces, big enough to tolerate ridiculous 47d5b718b3SGarrett Wollman * numbers of IP aliases. Crazy numbers of aliases such as 7000 48d5b718b3SGarrett Wollman * still will not do well, but not just in looking up interfaces 49d5b718b3SGarrett Wollman * by name or address. 50d5b718b3SGarrett Wollman */ 51d5b718b3SGarrett Wollman #define AHASH_LEN 211 /* must be prime */ 52d5b718b3SGarrett Wollman #define AHASH(a) &ahash[(a)%AHASH_LEN] 53d5b718b3SGarrett Wollman struct interface *ahash[AHASH_LEN]; 54d5b718b3SGarrett Wollman 55d5b718b3SGarrett Wollman #define BHASH_LEN 211 /* must be prime */ 56d5b718b3SGarrett Wollman #define BHASH(a) &bhash[(a)%BHASH_LEN] 57d5b718b3SGarrett Wollman struct interface *bhash[BHASH_LEN]; 58d5b718b3SGarrett Wollman 59d5b718b3SGarrett Wollman struct interface *remote_if; /* remote interfaces */ 60d5b718b3SGarrett Wollman 61d5b718b3SGarrett Wollman /* hash for physical interface names. 62d5b718b3SGarrett Wollman * Assume there are never more 100 or 200 real interfaces, and that 63d5b718b3SGarrett Wollman * aliases put on the end of the hash chains. 64d5b718b3SGarrett Wollman */ 65d5b718b3SGarrett Wollman #define NHASH_LEN 97 66d5b718b3SGarrett Wollman struct interface *nhash[NHASH_LEN]; 67d5b718b3SGarrett Wollman 687b6ab19dSGarrett Wollman int tot_interfaces; /* # of remote and local interfaces */ 697b6ab19dSGarrett Wollman int rip_interfaces; /* # of interfaces doing RIP */ 707b6ab19dSGarrett Wollman int foundloopback; /* valid flag for loopaddr */ 717b6ab19dSGarrett Wollman naddr loopaddr; /* our address on loopback */ 727b6ab19dSGarrett Wollman 737b6ab19dSGarrett Wollman struct timeval ifinit_timer; 747b6ab19dSGarrett Wollman 757b6ab19dSGarrett Wollman int have_ripv1_out; /* have a RIPv1 interface */ 767b6ab19dSGarrett Wollman int have_ripv1_in; 777b6ab19dSGarrett Wollman 787b6ab19dSGarrett Wollman 79d5b718b3SGarrett Wollman void 80d5b718b3SGarrett Wollman if_link(struct interface *ifp) 81d5b718b3SGarrett Wollman { 82d5b718b3SGarrett Wollman int i; 83d5b718b3SGarrett Wollman char *p; 84d5b718b3SGarrett Wollman struct interface **hifp; 85d5b718b3SGarrett Wollman 86d5b718b3SGarrett Wollman ifp->int_prev = &ifnet; 87d5b718b3SGarrett Wollman ifp->int_next = ifnet; 88d5b718b3SGarrett Wollman if (ifnet != 0) 89d5b718b3SGarrett Wollman ifnet->int_prev = &ifp->int_next; 90d5b718b3SGarrett Wollman ifnet = ifp; 91d5b718b3SGarrett Wollman 92d5b718b3SGarrett Wollman hifp = AHASH(ifp->int_addr); 93d5b718b3SGarrett Wollman ifp->int_ahash_prev = hifp; 94d5b718b3SGarrett Wollman ifp->int_ahash = *hifp; 95d5b718b3SGarrett Wollman if ((ifp->int_ahash = *hifp) != 0) 96d5b718b3SGarrett Wollman (*hifp)->int_ahash_prev = &ifp->int_ahash; 97d5b718b3SGarrett Wollman *hifp = ifp; 98d5b718b3SGarrett Wollman 99d5b718b3SGarrett Wollman if (ifp->int_if_flags & IFF_BROADCAST) { 100d5b718b3SGarrett Wollman hifp = BHASH(ifp->int_brdaddr); 101d5b718b3SGarrett Wollman ifp->int_bhash = *hifp; 102d5b718b3SGarrett Wollman ifp->int_bhash_prev = hifp; 103d5b718b3SGarrett Wollman if ((ifp->int_bhash = *hifp) != 0) 104d5b718b3SGarrett Wollman (*hifp)->int_bhash_prev = &ifp->int_bhash; 105d5b718b3SGarrett Wollman *hifp = ifp; 106d5b718b3SGarrett Wollman } 107d5b718b3SGarrett Wollman 108d5b718b3SGarrett Wollman if (ifp->int_state & IS_REMOTE) { 109d5b718b3SGarrett Wollman ifp->int_rlink_prev = &remote_if; 110d5b718b3SGarrett Wollman ifp->int_rlink = remote_if; 111d5b718b3SGarrett Wollman if (remote_if != 0) 112d5b718b3SGarrett Wollman remote_if->int_rlink_prev = &ifp->int_rlink; 113d5b718b3SGarrett Wollman remote_if = ifp; 114d5b718b3SGarrett Wollman } 115d5b718b3SGarrett Wollman 116d5b718b3SGarrett Wollman for (i = 0, p = ifp->int_name; *p != '\0'; p++) 117d5b718b3SGarrett Wollman i += *p; 118d5b718b3SGarrett Wollman hifp = &nhash[i % NHASH_LEN]; 119d5b718b3SGarrett Wollman if (ifp->int_state & IS_ALIAS) { 120d5b718b3SGarrett Wollman while (*hifp != 0) 121d5b718b3SGarrett Wollman hifp = &(*hifp)->int_nhash; 122d5b718b3SGarrett Wollman } 123d5b718b3SGarrett Wollman ifp->int_nhash = *hifp; 124d5b718b3SGarrett Wollman ifp->int_nhash_prev = hifp; 125d5b718b3SGarrett Wollman if ((ifp->int_nhash = *hifp) != 0) 126d5b718b3SGarrett Wollman (*hifp)->int_nhash_prev = &ifp->int_nhash; 127d5b718b3SGarrett Wollman *hifp = ifp; 128d5b718b3SGarrett Wollman } 129d5b718b3SGarrett Wollman 130d5b718b3SGarrett Wollman 1317b6ab19dSGarrett Wollman /* Find the interface with an address 1327b6ab19dSGarrett Wollman */ 1337b6ab19dSGarrett Wollman struct interface * 1347b6ab19dSGarrett Wollman ifwithaddr(naddr addr, 1357b6ab19dSGarrett Wollman int bcast, /* notice IFF_BROADCAST address */ 1367b6ab19dSGarrett Wollman int remote) /* include IS_REMOTE interfaces */ 1377b6ab19dSGarrett Wollman { 1387b6ab19dSGarrett Wollman struct interface *ifp, *possible = 0; 1397b6ab19dSGarrett Wollman 140d5b718b3SGarrett Wollman remote = (remote == 0) ? IS_REMOTE : 0; 141d5b718b3SGarrett Wollman 142d5b718b3SGarrett Wollman for (ifp = *AHASH(addr); ifp; ifp = ifp->int_ahash) { 143d5b718b3SGarrett Wollman if (ifp->int_addr != addr) 1447b6ab19dSGarrett Wollman continue; 145d5b718b3SGarrett Wollman if ((ifp->int_state & remote) != 0) 146d5b718b3SGarrett Wollman continue; 147d5b718b3SGarrett Wollman if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0) 1487b6ab19dSGarrett Wollman return ifp; 1497b6ab19dSGarrett Wollman possible = ifp; 1507b6ab19dSGarrett Wollman } 151d5b718b3SGarrett Wollman 152d5b718b3SGarrett Wollman if (possible || !bcast) 153d5b718b3SGarrett Wollman return possible; 154d5b718b3SGarrett Wollman 155d5b718b3SGarrett Wollman for (ifp = *BHASH(addr); ifp; ifp = ifp->int_bhash) { 156d5b718b3SGarrett Wollman if (ifp->int_brdaddr != addr) 157d5b718b3SGarrett Wollman continue; 158d5b718b3SGarrett Wollman if ((ifp->int_state & remote) != 0) 159d5b718b3SGarrett Wollman continue; 160d5b718b3SGarrett Wollman if ((ifp->int_state & (IS_BROKE | IS_PASSIVE)) == 0) 161d5b718b3SGarrett Wollman return ifp; 162d5b718b3SGarrett Wollman possible = ifp; 1637b6ab19dSGarrett Wollman } 1647b6ab19dSGarrett Wollman 1657b6ab19dSGarrett Wollman return possible; 1667b6ab19dSGarrett Wollman } 1677b6ab19dSGarrett Wollman 1687b6ab19dSGarrett Wollman 1697b6ab19dSGarrett Wollman /* find the interface with a name 1707b6ab19dSGarrett Wollman */ 1717b6ab19dSGarrett Wollman struct interface * 1727b6ab19dSGarrett Wollman ifwithname(char *name, /* "ec0" or whatever */ 1737b6ab19dSGarrett Wollman naddr addr) /* 0 or network address */ 1747b6ab19dSGarrett Wollman { 1757b6ab19dSGarrett Wollman struct interface *ifp; 176d5b718b3SGarrett Wollman int i; 177d5b718b3SGarrett Wollman char *p; 1787b6ab19dSGarrett Wollman 179d5b718b3SGarrett Wollman for (i = 0, p = name; *p != '\0'; p++) 180d5b718b3SGarrett Wollman i += *p; 181d5b718b3SGarrett Wollman for (ifp = nhash[i % NHASH_LEN]; ifp != 0; ifp = ifp->int_nhash) { 182d5b718b3SGarrett Wollman /* If the network address is not specified, 183d5b718b3SGarrett Wollman * ignore any alias interfaces. Otherwise, look 184d5b718b3SGarrett Wollman * for the interface with the target name and address. 185d5b718b3SGarrett Wollman */ 1867b6ab19dSGarrett Wollman if (!strcmp(ifp->int_name, name) 187d5b718b3SGarrett Wollman && ((addr == 0 && !(ifp->int_state & IS_ALIAS)) 188d5b718b3SGarrett Wollman || (ifp->int_addr == addr))) 1897b6ab19dSGarrett Wollman return ifp; 1907b6ab19dSGarrett Wollman } 1917b6ab19dSGarrett Wollman return 0; 1927b6ab19dSGarrett Wollman } 1937b6ab19dSGarrett Wollman 1947b6ab19dSGarrett Wollman 1957b6ab19dSGarrett Wollman struct interface * 1967b6ab19dSGarrett Wollman ifwithindex(u_short index) 1977b6ab19dSGarrett Wollman { 1987b6ab19dSGarrett Wollman struct interface *ifp; 1997b6ab19dSGarrett Wollman 2007b6ab19dSGarrett Wollman 2017b6ab19dSGarrett Wollman for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { 2027b6ab19dSGarrett Wollman if (ifp->int_index == index) 2037b6ab19dSGarrett Wollman return ifp; 2047b6ab19dSGarrett Wollman } 2057b6ab19dSGarrett Wollman return 0; 2067b6ab19dSGarrett Wollman } 2077b6ab19dSGarrett Wollman 2087b6ab19dSGarrett Wollman 2097b6ab19dSGarrett Wollman /* Find an interface from which the specified address 2107b6ab19dSGarrett Wollman * should have come from. Used for figuring out which 2117b6ab19dSGarrett Wollman * interface a packet came in on -- for tracing. 2127b6ab19dSGarrett Wollman */ 2137b6ab19dSGarrett Wollman struct interface * 2147b6ab19dSGarrett Wollman iflookup(naddr addr) 2157b6ab19dSGarrett Wollman { 2167b6ab19dSGarrett Wollman struct interface *ifp, *maybe; 2177b6ab19dSGarrett Wollman 2187b6ab19dSGarrett Wollman maybe = 0; 2197b6ab19dSGarrett Wollman for (ifp = ifnet; ifp; ifp = ifp->int_next) { 2207b6ab19dSGarrett Wollman if (ifp->int_if_flags & IFF_POINTOPOINT) { 2217b6ab19dSGarrett Wollman /* finished with a match */ 222d5b718b3SGarrett Wollman if (ifp->int_dstaddr == addr) 2237b6ab19dSGarrett Wollman return ifp; 2247b6ab19dSGarrett Wollman 2257b6ab19dSGarrett Wollman } else { 2267b6ab19dSGarrett Wollman /* finished with an exact match */ 2277b6ab19dSGarrett Wollman if (ifp->int_addr == addr) 2287b6ab19dSGarrett Wollman return ifp; 2297b6ab19dSGarrett Wollman 2307b6ab19dSGarrett Wollman /* Look for the longest approximate match. 2317b6ab19dSGarrett Wollman */ 2327b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_net, ifp->int_mask) 2337b6ab19dSGarrett Wollman && (maybe == 0 2347b6ab19dSGarrett Wollman || ifp->int_mask > maybe->int_mask)) 2357b6ab19dSGarrett Wollman maybe = ifp; 2367b6ab19dSGarrett Wollman } 2377b6ab19dSGarrett Wollman } 2387b6ab19dSGarrett Wollman 2397b6ab19dSGarrett Wollman return maybe; 2407b6ab19dSGarrett Wollman } 2417b6ab19dSGarrett Wollman 2427b6ab19dSGarrett Wollman 2437b6ab19dSGarrett Wollman /* Return the classical netmask for an IP address. 2447b6ab19dSGarrett Wollman */ 2457b6ab19dSGarrett Wollman naddr 2467b6ab19dSGarrett Wollman std_mask(naddr addr) /* in network order */ 2477b6ab19dSGarrett Wollman { 2487b6ab19dSGarrett Wollman NTOHL(addr); /* was a host, not a network */ 2497b6ab19dSGarrett Wollman 2507b6ab19dSGarrett Wollman if (addr == 0) /* default route has mask 0 */ 2517b6ab19dSGarrett Wollman return 0; 2527b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) 2537b6ab19dSGarrett Wollman return IN_CLASSA_NET; 2547b6ab19dSGarrett Wollman if (IN_CLASSB(addr)) 2557b6ab19dSGarrett Wollman return IN_CLASSB_NET; 2567b6ab19dSGarrett Wollman return IN_CLASSC_NET; 2577b6ab19dSGarrett Wollman } 2587b6ab19dSGarrett Wollman 2597b6ab19dSGarrett Wollman 2607b6ab19dSGarrett Wollman /* Find the netmask that would be inferred by RIPv1 listeners 2617b6ab19dSGarrett Wollman * on the given interface for a given network. 2627b6ab19dSGarrett Wollman * If no interface is specified, look for the best fitting interface. 2637b6ab19dSGarrett Wollman */ 2647b6ab19dSGarrett Wollman naddr 2657b6ab19dSGarrett Wollman ripv1_mask_net(naddr addr, /* in network byte order */ 2667b6ab19dSGarrett Wollman struct interface *ifp) /* as seen on this interface */ 2677b6ab19dSGarrett Wollman { 2687b6ab19dSGarrett Wollman naddr mask = 0; 2697b6ab19dSGarrett Wollman 2707b6ab19dSGarrett Wollman if (addr == 0) /* default always has 0 mask */ 2717b6ab19dSGarrett Wollman return mask; 2727b6ab19dSGarrett Wollman 2737b6ab19dSGarrett Wollman if (ifp != 0) { 2747b6ab19dSGarrett Wollman /* If the target network is that of the associated interface 2757b6ab19dSGarrett Wollman * on which it arrived, then use the netmask of the interface. 2767b6ab19dSGarrett Wollman */ 2777b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_net, ifp->int_std_mask)) 2787b6ab19dSGarrett Wollman mask = ifp->int_ripv1_mask; 2797b6ab19dSGarrett Wollman 2807b6ab19dSGarrett Wollman } else { 2817b6ab19dSGarrett Wollman /* Examine all interfaces, and if it the target seems 2827b6ab19dSGarrett Wollman * to have the same network number of an interface, use the 2837b6ab19dSGarrett Wollman * netmask of that interface. If there is more than one 2847b6ab19dSGarrett Wollman * such interface, prefer the interface with the longest 2857b6ab19dSGarrett Wollman * match. 2867b6ab19dSGarrett Wollman */ 2877b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { 2887b6ab19dSGarrett Wollman if (on_net(addr, ifp->int_std_net, ifp->int_std_mask) 2897b6ab19dSGarrett Wollman && ifp->int_ripv1_mask > mask) 2907b6ab19dSGarrett Wollman mask = ifp->int_ripv1_mask; 2917b6ab19dSGarrett Wollman } 2927b6ab19dSGarrett Wollman } 2937b6ab19dSGarrett Wollman 2947b6ab19dSGarrett Wollman /* Otherwise, make the classic A/B/C guess. 2957b6ab19dSGarrett Wollman */ 2967b6ab19dSGarrett Wollman if (mask == 0) 2977b6ab19dSGarrett Wollman mask = std_mask(addr); 2987b6ab19dSGarrett Wollman 2997b6ab19dSGarrett Wollman return mask; 3007b6ab19dSGarrett Wollman } 3017b6ab19dSGarrett Wollman 3027b6ab19dSGarrett Wollman 3037b6ab19dSGarrett Wollman naddr 3047b6ab19dSGarrett Wollman ripv1_mask_host(naddr addr, /* in network byte order */ 3057b6ab19dSGarrett Wollman struct interface *ifp) /* as seen on this interface */ 3067b6ab19dSGarrett Wollman { 3077b6ab19dSGarrett Wollman naddr mask = ripv1_mask_net(addr, ifp); 3087b6ab19dSGarrett Wollman 3097b6ab19dSGarrett Wollman 3107b6ab19dSGarrett Wollman /* If the computed netmask does not mask the address, 3117b6ab19dSGarrett Wollman * then assume it is a host address 3127b6ab19dSGarrett Wollman */ 3137b6ab19dSGarrett Wollman if ((ntohl(addr) & ~mask) != 0) 3147b6ab19dSGarrett Wollman mask = HOST_MASK; 3157b6ab19dSGarrett Wollman return mask; 3167b6ab19dSGarrett Wollman } 3177b6ab19dSGarrett Wollman 3187b6ab19dSGarrett Wollman 3197b6ab19dSGarrett Wollman /* See if a IP address looks reasonable as a destination 3207b6ab19dSGarrett Wollman */ 3217b6ab19dSGarrett Wollman int /* 0=bad */ 3227b6ab19dSGarrett Wollman check_dst(naddr addr) 3237b6ab19dSGarrett Wollman { 3247b6ab19dSGarrett Wollman NTOHL(addr); 3257b6ab19dSGarrett Wollman 3267b6ab19dSGarrett Wollman if (IN_CLASSA(addr)) { 3277b6ab19dSGarrett Wollman if (addr == 0) 3287b6ab19dSGarrett Wollman return 1; /* default */ 3297b6ab19dSGarrett Wollman 3307b6ab19dSGarrett Wollman addr >>= IN_CLASSA_NSHIFT; 3317b6ab19dSGarrett Wollman return (addr != 0 && addr != IN_LOOPBACKNET); 3327b6ab19dSGarrett Wollman } 3337b6ab19dSGarrett Wollman 3347b6ab19dSGarrett Wollman return (IN_CLASSB(addr) || IN_CLASSC(addr)); 3357b6ab19dSGarrett Wollman } 3367b6ab19dSGarrett Wollman 3377b6ab19dSGarrett Wollman 338d5b718b3SGarrett Wollman /* See a new interface duplicates an existing interface. 339d5b718b3SGarrett Wollman */ 340d5b718b3SGarrett Wollman struct interface * 341d5b718b3SGarrett Wollman check_dup(naddr addr, 342d5b718b3SGarrett Wollman naddr dstaddr, 343d5b718b3SGarrett Wollman naddr mask, 344d5b718b3SGarrett Wollman int if_flags) 345d5b718b3SGarrett Wollman { 346d5b718b3SGarrett Wollman struct interface *ifp; 347d5b718b3SGarrett Wollman 348d5b718b3SGarrett Wollman for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) { 349d5b718b3SGarrett Wollman if (ifp->int_mask != mask) 350d5b718b3SGarrett Wollman continue; 351d5b718b3SGarrett Wollman 352d5b718b3SGarrett Wollman if (!iff_alive(ifp->int_if_flags)) 353d5b718b3SGarrett Wollman continue; 354d5b718b3SGarrett Wollman 355d5b718b3SGarrett Wollman /* The local address can only be shared with a point-to- 356d5b718b3SGarrett Wollman * point link. 357d5b718b3SGarrett Wollman */ 358d5b718b3SGarrett Wollman if (ifp->int_addr == addr 359d5b718b3SGarrett Wollman && (((if_flags|ifp->int_if_flags) & IFF_POINTOPOINT) == 0)) 360d5b718b3SGarrett Wollman return ifp; 361d5b718b3SGarrett Wollman 362d5b718b3SGarrett Wollman if (on_net(ifp->int_dstaddr, ntohl(dstaddr),mask)) 363d5b718b3SGarrett Wollman return ifp; 364d5b718b3SGarrett Wollman } 365d5b718b3SGarrett Wollman return 0; 366d5b718b3SGarrett Wollman } 367d5b718b3SGarrett Wollman 368d5b718b3SGarrett Wollman 369d5b718b3SGarrett Wollman /* See that a remote gateway is reachable. 370d5b718b3SGarrett Wollman * Note that the answer can change as real interfaces come and go. 371d5b718b3SGarrett Wollman */ 372d5b718b3SGarrett Wollman int /* 0=bad */ 373d5b718b3SGarrett Wollman check_remote(struct interface *ifp) 374d5b718b3SGarrett Wollman { 375d5b718b3SGarrett Wollman struct rt_entry *rt; 376d5b718b3SGarrett Wollman 377d5b718b3SGarrett Wollman /* do not worry about other kinds */ 378d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_REMOTE)) 379d5b718b3SGarrett Wollman return 1; 380d5b718b3SGarrett Wollman 381d5b718b3SGarrett Wollman rt = rtfind(ifp->int_addr); 382d5b718b3SGarrett Wollman if (rt != 0 383d5b718b3SGarrett Wollman && rt->rt_ifp != 0 384d5b718b3SGarrett Wollman &&on_net(ifp->int_addr, 385d5b718b3SGarrett Wollman rt->rt_ifp->int_net, rt->rt_ifp->int_mask)) 386d5b718b3SGarrett Wollman return 1; 387d5b718b3SGarrett Wollman 388d5b718b3SGarrett Wollman /* the gateway cannot be reached directly from one of our 389d5b718b3SGarrett Wollman * interfaces 390d5b718b3SGarrett Wollman */ 391d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 392d5b718b3SGarrett Wollman msglog("unreachable gateway %s in "_PATH_GATEWAYS, 393d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_addr)); 394d5b718b3SGarrett Wollman if_bad(ifp); 395d5b718b3SGarrett Wollman } 396d5b718b3SGarrett Wollman return 0; 397d5b718b3SGarrett Wollman } 398d5b718b3SGarrett Wollman 399d5b718b3SGarrett Wollman 4007b6ab19dSGarrett Wollman /* Delete an interface. 4017b6ab19dSGarrett Wollman */ 4027b6ab19dSGarrett Wollman static void 4037b6ab19dSGarrett Wollman ifdel(struct interface *ifp) 4047b6ab19dSGarrett Wollman { 4057b6ab19dSGarrett Wollman struct ip_mreq m; 4067b6ab19dSGarrett Wollman struct interface *ifp1; 4077b6ab19dSGarrett Wollman 4087b6ab19dSGarrett Wollman 4097b6ab19dSGarrett Wollman trace_if("Del", ifp); 4107b6ab19dSGarrett Wollman 4117b6ab19dSGarrett Wollman ifp->int_state |= IS_BROKE; 4127b6ab19dSGarrett Wollman 4137b6ab19dSGarrett Wollman /* unlink the interface 4147b6ab19dSGarrett Wollman */ 415d5b718b3SGarrett Wollman *ifp->int_prev = ifp->int_next; 4167b6ab19dSGarrett Wollman if (ifp->int_next != 0) 4177b6ab19dSGarrett Wollman ifp->int_next->int_prev = ifp->int_prev; 418d5b718b3SGarrett Wollman *ifp->int_ahash_prev = ifp->int_ahash; 419d5b718b3SGarrett Wollman if (ifp->int_ahash != 0) 420d5b718b3SGarrett Wollman ifp->int_ahash->int_ahash_prev = ifp->int_ahash_prev; 421d5b718b3SGarrett Wollman if (ifp->int_if_flags & IFF_BROADCAST) { 422d5b718b3SGarrett Wollman *ifp->int_bhash_prev = ifp->int_bhash; 423d5b718b3SGarrett Wollman if (ifp->int_bhash != 0) 424d5b718b3SGarrett Wollman ifp->int_bhash->int_bhash_prev = ifp->int_bhash_prev; 425d5b718b3SGarrett Wollman } 426d5b718b3SGarrett Wollman if (ifp->int_state & IS_REMOTE) { 427d5b718b3SGarrett Wollman *ifp->int_rlink_prev = ifp->int_rlink; 428d5b718b3SGarrett Wollman if (ifp->int_rlink != 0) 429d5b718b3SGarrett Wollman ifp->int_rlink->int_rlink_prev = ifp->int_rlink_prev; 430d5b718b3SGarrett Wollman } 4317b6ab19dSGarrett Wollman 4327b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 433d5b718b3SGarrett Wollman /* delete aliases when the main interface dies 4347b6ab19dSGarrett Wollman */ 4357b6ab19dSGarrett Wollman for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) { 4367b6ab19dSGarrett Wollman if (ifp1 != ifp 4377b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 4387b6ab19dSGarrett Wollman ifdel(ifp1); 4397b6ab19dSGarrett Wollman } 4407b6ab19dSGarrett Wollman 4417b6ab19dSGarrett Wollman if ((ifp->int_if_flags & IFF_MULTICAST) 4427b6ab19dSGarrett Wollman #ifdef MCAST_PPP_BUG 4437b6ab19dSGarrett Wollman && !(ifp->int_if_flags & IFF_POINTOPOINT) 4447b6ab19dSGarrett Wollman #endif 4457b6ab19dSGarrett Wollman && rip_sock >= 0) { 4467b6ab19dSGarrett Wollman m.imr_multiaddr.s_addr = htonl(INADDR_RIP_GROUP); 4477b6ab19dSGarrett Wollman m.imr_interface.s_addr = ((ifp->int_if_flags 4487b6ab19dSGarrett Wollman & IFF_POINTOPOINT) 4497b6ab19dSGarrett Wollman ? ifp->int_dstaddr 4507b6ab19dSGarrett Wollman : ifp->int_addr); 4517b6ab19dSGarrett Wollman if (setsockopt(rip_sock,IPPROTO_IP,IP_DROP_MEMBERSHIP, 4527b6ab19dSGarrett Wollman &m, sizeof(m)) < 0 4537b6ab19dSGarrett Wollman && errno != EADDRNOTAVAIL 4547b6ab19dSGarrett Wollman && !TRACEACTIONS) 4557b6ab19dSGarrett Wollman LOGERR("setsockopt(IP_DROP_MEMBERSHIP RIP)"); 456d5b718b3SGarrett Wollman if (rip_sock_mcast == ifp) 457d5b718b3SGarrett Wollman rip_sock_mcast = 0; 4587b6ab19dSGarrett Wollman } 4597b6ab19dSGarrett Wollman if (ifp->int_rip_sock >= 0) { 4607b6ab19dSGarrett Wollman (void)close(ifp->int_rip_sock); 4617b6ab19dSGarrett Wollman ifp->int_rip_sock = -1; 4627b6ab19dSGarrett Wollman fix_select(); 4637b6ab19dSGarrett Wollman } 4647b6ab19dSGarrett Wollman 4657b6ab19dSGarrett Wollman tot_interfaces--; 4667b6ab19dSGarrett Wollman if (!IS_RIP_OFF(ifp->int_state)) 4677b6ab19dSGarrett Wollman rip_interfaces--; 4687b6ab19dSGarrett Wollman 4697b6ab19dSGarrett Wollman /* Zap all routes associated with this interface. 4707b6ab19dSGarrett Wollman * Assume routes just using gateways beyond this interface will 4717b6ab19dSGarrett Wollman * timeout naturally, and have probably already died. 4727b6ab19dSGarrett Wollman */ 4737b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_bad, 0); 4747b6ab19dSGarrett Wollman 4757b6ab19dSGarrett Wollman set_rdisc_mg(ifp, 0); 4767b6ab19dSGarrett Wollman if_bad_rdisc(ifp); 4777b6ab19dSGarrett Wollman } 4787b6ab19dSGarrett Wollman 4797b6ab19dSGarrett Wollman free(ifp); 4807b6ab19dSGarrett Wollman } 4817b6ab19dSGarrett Wollman 4827b6ab19dSGarrett Wollman 4837b6ab19dSGarrett Wollman /* Mark an interface ill. 4847b6ab19dSGarrett Wollman */ 4857b6ab19dSGarrett Wollman void 4867b6ab19dSGarrett Wollman if_sick(struct interface *ifp) 4877b6ab19dSGarrett Wollman { 4887b6ab19dSGarrett Wollman if (0 == (ifp->int_state & (IS_SICK | IS_BROKE))) { 4897b6ab19dSGarrett Wollman ifp->int_state |= IS_SICK; 490d5b718b3SGarrett Wollman ifp->int_act_time = NEVER; 4917b6ab19dSGarrett Wollman trace_if("Chg", ifp); 4927b6ab19dSGarrett Wollman 4937b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 4947b6ab19dSGarrett Wollman } 4957b6ab19dSGarrett Wollman } 4967b6ab19dSGarrett Wollman 4977b6ab19dSGarrett Wollman 4987b6ab19dSGarrett Wollman /* Mark an interface dead. 4997b6ab19dSGarrett Wollman */ 5007b6ab19dSGarrett Wollman void 5017b6ab19dSGarrett Wollman if_bad(struct interface *ifp) 5027b6ab19dSGarrett Wollman { 5037b6ab19dSGarrett Wollman struct interface *ifp1; 5047b6ab19dSGarrett Wollman 5057b6ab19dSGarrett Wollman 5067b6ab19dSGarrett Wollman if (ifp->int_state & IS_BROKE) 5077b6ab19dSGarrett Wollman return; 5087b6ab19dSGarrett Wollman 5097b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 5107b6ab19dSGarrett Wollman 5117b6ab19dSGarrett Wollman ifp->int_state |= (IS_BROKE | IS_SICK); 512d5b718b3SGarrett Wollman ifp->int_act_time = NEVER; 513d5b718b3SGarrett Wollman ifp->int_query_time = NEVER; 5147b6ab19dSGarrett Wollman ifp->int_data.ts = 0; 5157b6ab19dSGarrett Wollman 5167b6ab19dSGarrett Wollman trace_if("Chg", ifp); 5177b6ab19dSGarrett Wollman 5187b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 5197b6ab19dSGarrett Wollman for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) { 5207b6ab19dSGarrett Wollman if (ifp1 != ifp 5217b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 5227b6ab19dSGarrett Wollman if_bad(ifp1); 5237b6ab19dSGarrett Wollman } 5247b6ab19dSGarrett Wollman (void)rn_walktree(rhead, walk_bad, 0); 5257b6ab19dSGarrett Wollman if_bad_rdisc(ifp); 5267b6ab19dSGarrett Wollman } 5277b6ab19dSGarrett Wollman } 5287b6ab19dSGarrett Wollman 5297b6ab19dSGarrett Wollman 5307b6ab19dSGarrett Wollman /* Mark an interface alive 5317b6ab19dSGarrett Wollman */ 5327b6ab19dSGarrett Wollman int /* 1=it was dead */ 5337b6ab19dSGarrett Wollman if_ok(struct interface *ifp, 5347b6ab19dSGarrett Wollman char *type) 5357b6ab19dSGarrett Wollman { 5367b6ab19dSGarrett Wollman struct interface *ifp1; 5377b6ab19dSGarrett Wollman 5387b6ab19dSGarrett Wollman 5397b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 5407b6ab19dSGarrett Wollman if (ifp->int_state & IS_SICK) { 541d5b718b3SGarrett Wollman trace_act("%sinterface %s to %s working better", 5427b6ab19dSGarrett Wollman type, 543d5b718b3SGarrett Wollman ifp->int_name, naddr_ntoa(ifp->int_dstaddr)); 5447b6ab19dSGarrett Wollman ifp->int_state &= ~IS_SICK; 5457b6ab19dSGarrett Wollman } 5467b6ab19dSGarrett Wollman return 0; 5477b6ab19dSGarrett Wollman } 5487b6ab19dSGarrett Wollman 5497b6ab19dSGarrett Wollman msglog("%sinterface %s to %s restored", 550d5b718b3SGarrett Wollman type, ifp->int_name, naddr_ntoa(ifp->int_dstaddr)); 5517b6ab19dSGarrett Wollman ifp->int_state &= ~(IS_BROKE | IS_SICK); 5527b6ab19dSGarrett Wollman ifp->int_data.ts = 0; 5537b6ab19dSGarrett Wollman 5547b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 5557b6ab19dSGarrett Wollman for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) { 5567b6ab19dSGarrett Wollman if (ifp1 != ifp 5577b6ab19dSGarrett Wollman && !strcmp(ifp->int_name, ifp1->int_name)) 5587b6ab19dSGarrett Wollman if_ok(ifp1, type); 5597b6ab19dSGarrett Wollman } 5607b6ab19dSGarrett Wollman if_ok_rdisc(ifp); 5617b6ab19dSGarrett Wollman } 562d5b718b3SGarrett Wollman 563d5b718b3SGarrett Wollman if (ifp->int_state & IS_REMOTE) { 564d5b718b3SGarrett Wollman if (!addrouteforif(ifp)) 565d5b718b3SGarrett Wollman return 0; 566d5b718b3SGarrett Wollman } 5677b6ab19dSGarrett Wollman return 1; 5687b6ab19dSGarrett Wollman } 5697b6ab19dSGarrett Wollman 5707b6ab19dSGarrett Wollman 5717b6ab19dSGarrett Wollman /* disassemble routing message 5727b6ab19dSGarrett Wollman */ 5737b6ab19dSGarrett Wollman void 5747b6ab19dSGarrett Wollman rt_xaddrs(struct rt_addrinfo *info, 5757b6ab19dSGarrett Wollman struct sockaddr *sa, 5767b6ab19dSGarrett Wollman struct sockaddr *lim, 5777b6ab19dSGarrett Wollman int addrs) 5787b6ab19dSGarrett Wollman { 5797b6ab19dSGarrett Wollman int i; 5807b6ab19dSGarrett Wollman #ifdef _HAVE_SA_LEN 5817b6ab19dSGarrett Wollman static struct sockaddr sa_zero; 5827b6ab19dSGarrett Wollman #endif 5837b6ab19dSGarrett Wollman #ifdef sgi 5847b6ab19dSGarrett Wollman #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \ 5857b6ab19dSGarrett Wollman : sizeof(__uint64_t)) 5867b6ab19dSGarrett Wollman #else 5877b6ab19dSGarrett Wollman #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \ 5887b6ab19dSGarrett Wollman : sizeof(long)) 5897b6ab19dSGarrett Wollman #endif 5907b6ab19dSGarrett Wollman 5917b6ab19dSGarrett Wollman 5927b6ab19dSGarrett Wollman bzero(info, sizeof(*info)); 5937b6ab19dSGarrett Wollman info->rti_addrs = addrs; 5947b6ab19dSGarrett Wollman for (i = 0; i < RTAX_MAX && sa < lim; i++) { 5957b6ab19dSGarrett Wollman if ((addrs & (1 << i)) == 0) 5967b6ab19dSGarrett Wollman continue; 5977b6ab19dSGarrett Wollman #ifdef _HAVE_SA_LEN 5987b6ab19dSGarrett Wollman info->rti_info[i] = (sa->sa_len != 0) ? sa : &sa_zero; 5997b6ab19dSGarrett Wollman sa = (struct sockaddr *)((char*)(sa) 6007b6ab19dSGarrett Wollman + ROUNDUP(sa->sa_len)); 6017b6ab19dSGarrett Wollman #else 6027b6ab19dSGarrett Wollman info->rti_info[i] = sa; 6037b6ab19dSGarrett Wollman sa = (struct sockaddr *)((char*)(sa) 6047b6ab19dSGarrett Wollman + ROUNDUP(_FAKE_SA_LEN_DST(sa))); 6057b6ab19dSGarrett Wollman #endif 6067b6ab19dSGarrett Wollman } 6077b6ab19dSGarrett Wollman } 6087b6ab19dSGarrett Wollman 6097b6ab19dSGarrett Wollman 6107b6ab19dSGarrett Wollman /* Find the network interfaces which have configured themselves. 6117b6ab19dSGarrett Wollman * This must be done regularly, if only for extra addresses 6127b6ab19dSGarrett Wollman * that come and go on interfaces. 6137b6ab19dSGarrett Wollman */ 6147b6ab19dSGarrett Wollman void 6157b6ab19dSGarrett Wollman ifinit(void) 6167b6ab19dSGarrett Wollman { 6177b6ab19dSGarrett Wollman static char *sysctl_buf; 6187b6ab19dSGarrett Wollman static size_t sysctl_buf_size = 0; 6197b6ab19dSGarrett Wollman uint complaints = 0; 6207b6ab19dSGarrett Wollman static u_int prev_complaints = 0; 6217b6ab19dSGarrett Wollman # define COMP_NOT_INET 0x001 622d5b718b3SGarrett Wollman # define COMP_NOADDR 0x002 623d5b718b3SGarrett Wollman # define COMP_BADADDR 0x004 624d5b718b3SGarrett Wollman # define COMP_NODST 0x008 625d5b718b3SGarrett Wollman # define COMP_NOBADR 0x010 626d5b718b3SGarrett Wollman # define COMP_NOMASK 0x020 627d5b718b3SGarrett Wollman # define COMP_DUP 0x040 628d5b718b3SGarrett Wollman # define COMP_BAD_METRIC 0x080 629d5b718b3SGarrett Wollman # define COMP_NETMASK 0x100 6307b6ab19dSGarrett Wollman 6317b6ab19dSGarrett Wollman struct interface ifs, ifs0, *ifp, *ifp1; 6327b6ab19dSGarrett Wollman struct rt_entry *rt; 6337b6ab19dSGarrett Wollman size_t needed; 6347b6ab19dSGarrett Wollman int mib[6]; 6357b6ab19dSGarrett Wollman struct if_msghdr *ifm; 6367b6ab19dSGarrett Wollman struct ifa_msghdr *ifam, *ifam_lim, *ifam2; 6377b6ab19dSGarrett Wollman int in, ierr, out, oerr; 6387b6ab19dSGarrett Wollman struct intnet *intnetp; 6397b6ab19dSGarrett Wollman struct rt_addrinfo info; 6407b6ab19dSGarrett Wollman #ifdef SIOCGIFMETRIC 6417b6ab19dSGarrett Wollman struct ifreq ifr; 6427b6ab19dSGarrett Wollman #endif 6437b6ab19dSGarrett Wollman 6447b6ab19dSGarrett Wollman 6457b6ab19dSGarrett Wollman ifinit_timer.tv_sec = now.tv_sec + (supplier 6467b6ab19dSGarrett Wollman ? CHECK_ACT_INTERVAL 6477b6ab19dSGarrett Wollman : CHECK_QUIET_INTERVAL); 6487b6ab19dSGarrett Wollman 6497b6ab19dSGarrett Wollman /* mark all interfaces so we can get rid of thost that disappear */ 6507b6ab19dSGarrett Wollman for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) 6517b6ab19dSGarrett Wollman ifp->int_state &= ~(IS_CHECKED | IS_DUP); 6527b6ab19dSGarrett Wollman 6537b6ab19dSGarrett Wollman /* Fetch the interface list, without too many system calls 6547b6ab19dSGarrett Wollman * since we do it repeatedly. 6557b6ab19dSGarrett Wollman */ 6567b6ab19dSGarrett Wollman mib[0] = CTL_NET; 6577b6ab19dSGarrett Wollman mib[1] = PF_ROUTE; 6587b6ab19dSGarrett Wollman mib[2] = 0; 6597b6ab19dSGarrett Wollman mib[3] = AF_INET; 6607b6ab19dSGarrett Wollman mib[4] = NET_RT_IFLIST; 6617b6ab19dSGarrett Wollman mib[5] = 0; 6627b6ab19dSGarrett Wollman for (;;) { 6637b6ab19dSGarrett Wollman if ((needed = sysctl_buf_size) != 0) { 6647b6ab19dSGarrett Wollman if (sysctl(mib, 6, sysctl_buf,&needed, 0, 0) >= 0) 6657b6ab19dSGarrett Wollman break; 6667b6ab19dSGarrett Wollman if (errno != ENOMEM && errno != EFAULT) 6677b6ab19dSGarrett Wollman BADERR(1, "ifinit: get interface table"); 6687b6ab19dSGarrett Wollman free(sysctl_buf); 6697b6ab19dSGarrett Wollman needed = 0; 6707b6ab19dSGarrett Wollman } 6717b6ab19dSGarrett Wollman if (sysctl(mib, 6, 0, &needed, 0, 0) < 0) 6727b6ab19dSGarrett Wollman BADERR(1,"ifinit: route-sysctl-estimate"); 6737b6ab19dSGarrett Wollman sysctl_buf = rtmalloc(sysctl_buf_size = needed, "ifinit"); 6747b6ab19dSGarrett Wollman } 6757b6ab19dSGarrett Wollman 6767b6ab19dSGarrett Wollman ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed); 6777b6ab19dSGarrett Wollman for (ifam = (struct ifa_msghdr *)sysctl_buf; 6787b6ab19dSGarrett Wollman ifam < ifam_lim; 6797b6ab19dSGarrett Wollman ifam = ifam2) { 6807b6ab19dSGarrett Wollman 6817b6ab19dSGarrett Wollman ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen); 6827b6ab19dSGarrett Wollman 6837b6ab19dSGarrett Wollman if (ifam->ifam_type == RTM_IFINFO) { 684d5b718b3SGarrett Wollman struct sockaddr_dl *sdl; 685d5b718b3SGarrett Wollman 6867b6ab19dSGarrett Wollman ifm = (struct if_msghdr *)ifam; 6877b6ab19dSGarrett Wollman /* make prototype structure for the IP aliases 6887b6ab19dSGarrett Wollman */ 6897b6ab19dSGarrett Wollman bzero(&ifs0, sizeof(ifs0)); 6907b6ab19dSGarrett Wollman ifs0.int_rip_sock = -1; 6917b6ab19dSGarrett Wollman ifs0.int_index = ifm->ifm_index; 6927b6ab19dSGarrett Wollman ifs0.int_if_flags = ifm->ifm_flags; 6937b6ab19dSGarrett Wollman ifs0.int_state = IS_CHECKED; 6947b6ab19dSGarrett Wollman ifs0.int_act_time = now.tv_sec; 6957b6ab19dSGarrett Wollman ifs0.int_data.ts = now.tv_sec; 6967b6ab19dSGarrett Wollman ifs0.int_data.ipackets = ifm->ifm_data.ifi_ipackets; 6977b6ab19dSGarrett Wollman ifs0.int_data.ierrors = ifm->ifm_data.ifi_ierrors; 6987b6ab19dSGarrett Wollman ifs0.int_data.opackets = ifm->ifm_data.ifi_opackets; 6997b6ab19dSGarrett Wollman ifs0.int_data.oerrors = ifm->ifm_data.ifi_oerrors; 7007b6ab19dSGarrett Wollman #ifdef sgi 7017b6ab19dSGarrett Wollman ifs0.int_data.odrops = ifm->ifm_data.ifi_odrops; 7027b6ab19dSGarrett Wollman #endif 7037b6ab19dSGarrett Wollman sdl = (struct sockaddr_dl *)(ifm + 1); 7047b6ab19dSGarrett Wollman sdl->sdl_data[sdl->sdl_nlen] = 0; 705d5b718b3SGarrett Wollman strncpy(ifs0.int_name, sdl->sdl_data, 706d5b718b3SGarrett Wollman MIN(sizeof(ifs0.int_name), sdl->sdl_nlen)); 7077b6ab19dSGarrett Wollman continue; 7087b6ab19dSGarrett Wollman } 7097b6ab19dSGarrett Wollman if (ifam->ifam_type != RTM_NEWADDR) { 7107b6ab19dSGarrett Wollman logbad(1,"ifinit: out of sync"); 7117b6ab19dSGarrett Wollman continue; 7127b6ab19dSGarrett Wollman } 7137b6ab19dSGarrett Wollman rt_xaddrs(&info, (struct sockaddr *)(ifam+1), 7147b6ab19dSGarrett Wollman (struct sockaddr *)ifam2, 7157b6ab19dSGarrett Wollman ifam->ifam_addrs); 7167b6ab19dSGarrett Wollman 717d5b718b3SGarrett Wollman /* Prepare for the next address of this interface, which 718d5b718b3SGarrett Wollman * will be an alias. 719d5b718b3SGarrett Wollman * Do not output RIP or Router-Discovery packets via aliases. 720d5b718b3SGarrett Wollman */ 721d5b718b3SGarrett Wollman bcopy(&ifs0, &ifs, sizeof(ifs)); 722d5b718b3SGarrett Wollman ifs0.int_state |= (IS_ALIAS | IS_NO_RIP | IS_NO_RDISC); 723d5b718b3SGarrett Wollman 7247b6ab19dSGarrett Wollman if (INFO_IFA(&info) == 0) { 7257b6ab19dSGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 7267b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NOADDR)) 7277b6ab19dSGarrett Wollman msglog("%s has no address", 728d5b718b3SGarrett Wollman ifs.int_name); 7297b6ab19dSGarrett Wollman complaints |= COMP_NOADDR; 7307b6ab19dSGarrett Wollman } 7317b6ab19dSGarrett Wollman continue; 7327b6ab19dSGarrett Wollman } 7337b6ab19dSGarrett Wollman if (INFO_IFA(&info)->sa_family != AF_INET) { 7347b6ab19dSGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 7357b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NOT_INET)) 736d5b718b3SGarrett Wollman trace_act("%s: not AF_INET", 737d5b718b3SGarrett Wollman ifs.int_name); 7387b6ab19dSGarrett Wollman complaints |= COMP_NOT_INET; 7397b6ab19dSGarrett Wollman } 7407b6ab19dSGarrett Wollman continue; 7417b6ab19dSGarrett Wollman } 7427b6ab19dSGarrett Wollman 7437b6ab19dSGarrett Wollman ifs.int_addr = S_ADDR(INFO_IFA(&info)); 7447b6ab19dSGarrett Wollman 7457b6ab19dSGarrett Wollman if (ntohl(ifs.int_addr)>>24 == 0 7467b6ab19dSGarrett Wollman || ntohl(ifs.int_addr)>>24 == 0xff) { 7477b6ab19dSGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 7487b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_BADADDR)) 7497b6ab19dSGarrett Wollman msglog("%s has a bad address", 750d5b718b3SGarrett Wollman ifs.int_name); 7517b6ab19dSGarrett Wollman complaints |= COMP_BADADDR; 7527b6ab19dSGarrett Wollman } 7537b6ab19dSGarrett Wollman continue; 7547b6ab19dSGarrett Wollman } 7557b6ab19dSGarrett Wollman 756d5b718b3SGarrett Wollman if (ifs.int_if_flags & IFF_LOOPBACK) { 757d5b718b3SGarrett Wollman ifs.int_state |= IS_PASSIVE | IS_NO_RIP | IS_NO_RDISC; 7587b6ab19dSGarrett Wollman ifs.int_dstaddr = ifs.int_addr; 759d5b718b3SGarrett Wollman ifs.int_mask = HOST_MASK; 760d5b718b3SGarrett Wollman ifs.int_ripv1_mask = HOST_MASK; 761d5b718b3SGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_dstaddr); 762d5b718b3SGarrett Wollman ifs.int_net = ntohl(ifs.int_dstaddr); 763d5b718b3SGarrett Wollman if (!foundloopback) { 764d5b718b3SGarrett Wollman foundloopback = 1; 765d5b718b3SGarrett Wollman loopaddr = ifs.int_addr; 7667b6ab19dSGarrett Wollman } 7677b6ab19dSGarrett Wollman 7687b6ab19dSGarrett Wollman } else if (ifs.int_if_flags & IFF_POINTOPOINT) { 7697b6ab19dSGarrett Wollman if (INFO_BRD(&info) == 0 7707b6ab19dSGarrett Wollman || INFO_BRD(&info)->sa_family != AF_INET) { 7717b6ab19dSGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 7727b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NODST)) 7737b6ab19dSGarrett Wollman msglog("%s has a bad" 7747b6ab19dSGarrett Wollman " destination address", 775d5b718b3SGarrett Wollman ifs.int_name); 7767b6ab19dSGarrett Wollman complaints |= COMP_NODST; 7777b6ab19dSGarrett Wollman } 7787b6ab19dSGarrett Wollman continue; 7797b6ab19dSGarrett Wollman } 7807b6ab19dSGarrett Wollman ifs.int_dstaddr = S_ADDR(INFO_BRD(&info)); 7817b6ab19dSGarrett Wollman if (ntohl(ifs.int_dstaddr)>>24 == 0 7827b6ab19dSGarrett Wollman || ntohl(ifs.int_dstaddr)>>24 == 0xff) { 7837b6ab19dSGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 7847b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NODST)) 7857b6ab19dSGarrett Wollman msglog("%s has a bad" 7867b6ab19dSGarrett Wollman " destination address", 787d5b718b3SGarrett Wollman ifs.int_name); 7887b6ab19dSGarrett Wollman complaints |= COMP_NODST; 7897b6ab19dSGarrett Wollman } 7907b6ab19dSGarrett Wollman continue; 7917b6ab19dSGarrett Wollman } 7927b6ab19dSGarrett Wollman ifs.int_mask = HOST_MASK; 7937b6ab19dSGarrett Wollman ifs.int_ripv1_mask = ntohl(S_ADDR(INFO_MASK(&info))); 7947b6ab19dSGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_dstaddr); 7957b6ab19dSGarrett Wollman ifs.int_net = ntohl(ifs.int_dstaddr); 7967b6ab19dSGarrett Wollman 7977b6ab19dSGarrett Wollman } else { 798d5b718b3SGarrett Wollman if (INFO_MASK(&info) == 0) { 799d5b718b3SGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 800d5b718b3SGarrett Wollman if (!(prev_complaints & COMP_NOMASK)) 801d5b718b3SGarrett Wollman msglog("%s has no netmask", 802d5b718b3SGarrett Wollman ifs.int_name); 803d5b718b3SGarrett Wollman complaints |= COMP_NOMASK; 804d5b718b3SGarrett Wollman } 8057b6ab19dSGarrett Wollman continue; 8067b6ab19dSGarrett Wollman } 807d5b718b3SGarrett Wollman ifs.int_dstaddr = ifs.int_addr; 808d5b718b3SGarrett Wollman ifs.int_mask = ntohl(S_ADDR(INFO_MASK(&info))); 809d5b718b3SGarrett Wollman ifs.int_ripv1_mask = ifs.int_mask; 810d5b718b3SGarrett Wollman ifs.int_std_mask = std_mask(ifs.int_addr); 811d5b718b3SGarrett Wollman ifs.int_net = ntohl(ifs.int_addr) & ifs.int_mask; 812d5b718b3SGarrett Wollman if (ifs.int_mask != ifs.int_std_mask) 813d5b718b3SGarrett Wollman ifs.int_state |= IS_SUBNET; 814d5b718b3SGarrett Wollman 815d5b718b3SGarrett Wollman if (ifs.int_if_flags & IFF_BROADCAST) { 816d5b718b3SGarrett Wollman if (INFO_BRD(&info) == 0) { 817d5b718b3SGarrett Wollman if (iff_alive(ifs.int_if_flags)) { 818d5b718b3SGarrett Wollman if (!(prev_complaints 819d5b718b3SGarrett Wollman & COMP_NOBADR)) 820d5b718b3SGarrett Wollman msglog("%s has" 821d5b718b3SGarrett Wollman "no broadcast address", 822d5b718b3SGarrett Wollman ifs.int_name); 823d5b718b3SGarrett Wollman complaints |= COMP_NOBADR; 824d5b718b3SGarrett Wollman } 825d5b718b3SGarrett Wollman continue; 826d5b718b3SGarrett Wollman } 827d5b718b3SGarrett Wollman ifs.int_brdaddr = S_ADDR(INFO_BRD(&info)); 828d5b718b3SGarrett Wollman } 829d5b718b3SGarrett Wollman } 8307b6ab19dSGarrett Wollman ifs.int_std_net = ifs.int_net & ifs.int_std_mask; 8317b6ab19dSGarrett Wollman ifs.int_std_addr = htonl(ifs.int_std_net); 8327b6ab19dSGarrett Wollman 8337b6ab19dSGarrett Wollman /* Use a minimum metric of one. Treat the interface metric 8347b6ab19dSGarrett Wollman * (default 0) as an increment to the hop count of one. 8357b6ab19dSGarrett Wollman * 8367b6ab19dSGarrett Wollman * The metric obtained from the routing socket dump of 8377b6ab19dSGarrett Wollman * interface addresses is wrong. It is not set by the 8387b6ab19dSGarrett Wollman * SIOCSIFMETRIC ioctl. 8397b6ab19dSGarrett Wollman */ 8407b6ab19dSGarrett Wollman #ifdef SIOCGIFMETRIC 841d5b718b3SGarrett Wollman strncpy(ifr.ifr_name, ifs.int_name, sizeof(ifr.ifr_name)); 8427b6ab19dSGarrett Wollman if (ioctl(rt_sock, SIOCGIFMETRIC, &ifr) < 0) { 8437b6ab19dSGarrett Wollman DBGERR(1, "ioctl(SIOCGIFMETRIC)"); 8447b6ab19dSGarrett Wollman ifs.int_metric = 0; 8457b6ab19dSGarrett Wollman } else { 8467b6ab19dSGarrett Wollman ifs.int_metric = ifr.ifr_metric; 8477b6ab19dSGarrett Wollman } 8487b6ab19dSGarrett Wollman #else 8497b6ab19dSGarrett Wollman ifs.int_metric = ifam->ifam_metric; 8507b6ab19dSGarrett Wollman #endif 8517b6ab19dSGarrett Wollman if (ifs.int_metric > HOPCNT_INFINITY) { 8527b6ab19dSGarrett Wollman ifs.int_metric = 0; 8537b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_BAD_METRIC) 8547b6ab19dSGarrett Wollman && iff_alive(ifs.int_if_flags)) { 8557b6ab19dSGarrett Wollman complaints |= COMP_BAD_METRIC; 8567b6ab19dSGarrett Wollman msglog("%s has a metric of %d", 857d5b718b3SGarrett Wollman ifs.int_name, ifs.int_metric); 8587b6ab19dSGarrett Wollman } 8597b6ab19dSGarrett Wollman } 8607b6ab19dSGarrett Wollman 8617b6ab19dSGarrett Wollman /* See if this is a familiar interface. 8627b6ab19dSGarrett Wollman * If so, stop worrying about it if it is the same. 8637b6ab19dSGarrett Wollman * Start it over if it now is to somewhere else, as happens 8647b6ab19dSGarrett Wollman * frequently with PPP and SLIP. 8657b6ab19dSGarrett Wollman */ 866d5b718b3SGarrett Wollman ifp = ifwithname(ifs.int_name, ((ifs.int_state & IS_ALIAS) 8677b6ab19dSGarrett Wollman ? ifs.int_addr 8687b6ab19dSGarrett Wollman : 0)); 8697b6ab19dSGarrett Wollman if (ifp != 0) { 8707b6ab19dSGarrett Wollman ifp->int_state |= IS_CHECKED; 8717b6ab19dSGarrett Wollman 8727b6ab19dSGarrett Wollman if (0 != ((ifp->int_if_flags ^ ifs.int_if_flags) 8737b6ab19dSGarrett Wollman & (IFF_BROADCAST 8747b6ab19dSGarrett Wollman | IFF_LOOPBACK 8757b6ab19dSGarrett Wollman | IFF_POINTOPOINT 8767b6ab19dSGarrett Wollman | IFF_MULTICAST)) 8777b6ab19dSGarrett Wollman || 0 != ((ifp->int_state ^ ifs.int_state) 8787b6ab19dSGarrett Wollman & IS_ALIAS) 8797b6ab19dSGarrett Wollman || ifp->int_addr != ifs.int_addr 8807b6ab19dSGarrett Wollman || ifp->int_brdaddr != ifs.int_brdaddr 8817b6ab19dSGarrett Wollman || ifp->int_dstaddr != ifs.int_dstaddr 8827b6ab19dSGarrett Wollman || ifp->int_mask != ifs.int_mask 8837b6ab19dSGarrett Wollman || ifp->int_metric != ifs.int_metric) { 8847b6ab19dSGarrett Wollman /* Forget old information about 8857b6ab19dSGarrett Wollman * a changed interface. 8867b6ab19dSGarrett Wollman */ 887d5b718b3SGarrett Wollman trace_act("interface %s has changed", 8887b6ab19dSGarrett Wollman ifp->int_name); 8897b6ab19dSGarrett Wollman ifdel(ifp); 8907b6ab19dSGarrett Wollman ifp = 0; 8917b6ab19dSGarrett Wollman } 8927b6ab19dSGarrett Wollman } 8937b6ab19dSGarrett Wollman 8947b6ab19dSGarrett Wollman if (ifp != 0) { 8957b6ab19dSGarrett Wollman /* The primary representative of an alias worries 8967b6ab19dSGarrett Wollman * about how things are working. 8977b6ab19dSGarrett Wollman */ 8987b6ab19dSGarrett Wollman if (ifp->int_state & IS_ALIAS) 8997b6ab19dSGarrett Wollman continue; 9007b6ab19dSGarrett Wollman 9017b6ab19dSGarrett Wollman /* note interfaces that have been turned off 9027b6ab19dSGarrett Wollman */ 9037b6ab19dSGarrett Wollman if (!iff_alive(ifs.int_if_flags)) { 9047b6ab19dSGarrett Wollman if (iff_alive(ifp->int_if_flags)) { 9057b6ab19dSGarrett Wollman msglog("interface %s to %s turned off", 9067b6ab19dSGarrett Wollman ifp->int_name, 907d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr)); 9087b6ab19dSGarrett Wollman if_bad(ifp); 9097b6ab19dSGarrett Wollman ifp->int_if_flags &= ~IFF_UP_RUNNING; 9107b6ab19dSGarrett Wollman } 9117b6ab19dSGarrett Wollman continue; 9127b6ab19dSGarrett Wollman } 9137b6ab19dSGarrett Wollman /* or that were off and are now ok */ 9147b6ab19dSGarrett Wollman if (!iff_alive(ifp->int_if_flags)) { 9157b6ab19dSGarrett Wollman ifp->int_if_flags |= IFF_UP_RUNNING; 9167b6ab19dSGarrett Wollman (void)if_ok(ifp, ""); 9177b6ab19dSGarrett Wollman } 9187b6ab19dSGarrett Wollman 9197b6ab19dSGarrett Wollman /* If it has been long enough, 9207b6ab19dSGarrett Wollman * see if the interface is broken. 9217b6ab19dSGarrett Wollman */ 9227b6ab19dSGarrett Wollman if (now.tv_sec < ifp->int_data.ts+CHECK_BAD_INTERVAL) 9237b6ab19dSGarrett Wollman continue; 9247b6ab19dSGarrett Wollman 9257b6ab19dSGarrett Wollman in = ifs.int_data.ipackets - ifp->int_data.ipackets; 9267b6ab19dSGarrett Wollman ierr = ifs.int_data.ierrors - ifp->int_data.ierrors; 9277b6ab19dSGarrett Wollman out = ifs.int_data.opackets - ifp->int_data.opackets; 9287b6ab19dSGarrett Wollman oerr = ifs.int_data.oerrors - ifp->int_data.oerrors; 9297b6ab19dSGarrett Wollman #ifdef sgi 9307b6ab19dSGarrett Wollman /* Through at least IRIX 6.2, PPP and SLIP 9317b6ab19dSGarrett Wollman * count packets dropped by the filters. 9327b6ab19dSGarrett Wollman * But FDDI rings stuck non-operational count 9337b6ab19dSGarrett Wollman * dropped packets as they wait for improvement. 9347b6ab19dSGarrett Wollman */ 9357b6ab19dSGarrett Wollman if (!(ifp->int_if_flags & IFF_POINTOPOINT)) 9367b6ab19dSGarrett Wollman oerr += (ifs.int_data.odrops 9377b6ab19dSGarrett Wollman - ifp->int_data.odrops); 9387b6ab19dSGarrett Wollman #endif 9397b6ab19dSGarrett Wollman /* If the interface just awoke, restart the counters. 9407b6ab19dSGarrett Wollman */ 9417b6ab19dSGarrett Wollman if (ifp->int_data.ts == 0) { 9427b6ab19dSGarrett Wollman ifp->int_data = ifs.int_data; 9437b6ab19dSGarrett Wollman continue; 9447b6ab19dSGarrett Wollman } 9457b6ab19dSGarrett Wollman ifp->int_data = ifs.int_data; 9467b6ab19dSGarrett Wollman 9477b6ab19dSGarrett Wollman /* Withhold judgement when the short error 9487b6ab19dSGarrett Wollman * counters wrap or the interface is reset. 9497b6ab19dSGarrett Wollman */ 9507b6ab19dSGarrett Wollman if (ierr < 0 || in < 0 || oerr < 0 || out < 0) { 9517b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, 9527b6ab19dSGarrett Wollman now.tv_sec+CHECK_BAD_INTERVAL); 9537b6ab19dSGarrett Wollman continue; 9547b6ab19dSGarrett Wollman } 9557b6ab19dSGarrett Wollman 9567b6ab19dSGarrett Wollman /* Withhold judgement when there is no traffic 9577b6ab19dSGarrett Wollman */ 9587b6ab19dSGarrett Wollman if (in == 0 && out == 0 && ierr == 0 && oerr == 0) 9597b6ab19dSGarrett Wollman continue; 9607b6ab19dSGarrett Wollman 9617b6ab19dSGarrett Wollman /* It is bad if input or output is not working. 9627b6ab19dSGarrett Wollman * Require presistent problems before marking it dead. 9637b6ab19dSGarrett Wollman */ 9647b6ab19dSGarrett Wollman if ((in <= ierr && ierr > 0) 9657b6ab19dSGarrett Wollman || (out <= oerr && oerr > 0)) { 9667b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_SICK)) { 9677b6ab19dSGarrett Wollman trace_act("interface %s to %s" 9687b6ab19dSGarrett Wollman " sick: in=%d ierr=%d" 969d5b718b3SGarrett Wollman " out=%d oerr=%d", 9707b6ab19dSGarrett Wollman ifp->int_name, 971d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr), 9727b6ab19dSGarrett Wollman in, ierr, out, oerr); 9737b6ab19dSGarrett Wollman if_sick(ifp); 9747b6ab19dSGarrett Wollman continue; 9757b6ab19dSGarrett Wollman } 9767b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_BROKE)) { 977d5b718b3SGarrett Wollman msglog("interface %s to %s broken:" 9787b6ab19dSGarrett Wollman " in=%d ierr=%d out=%d oerr=%d", 9797b6ab19dSGarrett Wollman ifp->int_name, 980d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr), 9817b6ab19dSGarrett Wollman in, ierr, out, oerr); 9827b6ab19dSGarrett Wollman if_bad(ifp); 9837b6ab19dSGarrett Wollman } 9847b6ab19dSGarrett Wollman continue; 9857b6ab19dSGarrett Wollman } 9867b6ab19dSGarrett Wollman 9877b6ab19dSGarrett Wollman /* otherwise, it is active and healthy 9887b6ab19dSGarrett Wollman */ 9897b6ab19dSGarrett Wollman ifp->int_act_time = now.tv_sec; 9907b6ab19dSGarrett Wollman (void)if_ok(ifp, ""); 9917b6ab19dSGarrett Wollman continue; 9927b6ab19dSGarrett Wollman } 9937b6ab19dSGarrett Wollman 9947b6ab19dSGarrett Wollman /* This is a new interface. 9957b6ab19dSGarrett Wollman * If it is dead, forget it. 9967b6ab19dSGarrett Wollman */ 9977b6ab19dSGarrett Wollman if (!iff_alive(ifs.int_if_flags)) 9987b6ab19dSGarrett Wollman continue; 9997b6ab19dSGarrett Wollman 1000d5b718b3SGarrett Wollman /* If it duplicates an existing interface, 1001d5b718b3SGarrett Wollman * complain about it, mark the other one 10027b6ab19dSGarrett Wollman * duplicated, and forget this one. 10037b6ab19dSGarrett Wollman */ 1004d5b718b3SGarrett Wollman ifp = check_dup(ifs.int_addr,ifs.int_dstaddr,ifs.int_mask, 1005d5b718b3SGarrett Wollman ifs.int_if_flags); 1006d5b718b3SGarrett Wollman if (ifp != 0) { 10077b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_DUP)) { 10087b6ab19dSGarrett Wollman complaints |= COMP_DUP; 1009d5b718b3SGarrett Wollman msglog("%s is duplicated by %s at %s to %s", 1010d5b718b3SGarrett Wollman ifs.int_name, ifp->int_name, 1011d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_addr), 1012d5b718b3SGarrett Wollman naddr_ntoa(ifp->int_dstaddr)); 10137b6ab19dSGarrett Wollman } 10147b6ab19dSGarrett Wollman ifp->int_state |= IS_DUP; 10157b6ab19dSGarrett Wollman continue; 1016d5b718b3SGarrett Wollman } 10177b6ab19dSGarrett Wollman 1018d5b718b3SGarrett Wollman if (0 == (ifs.int_if_flags & (IFF_POINTOPOINT | IFF_BROADCAST)) 1019d5b718b3SGarrett Wollman && !(ifs.int_state & IS_PASSIVE)) { 1020d5b718b3SGarrett Wollman trace_act("%s is neither broadcast, point-to-point," 1021d5b718b3SGarrett Wollman " nor loopback", 1022d5b718b3SGarrett Wollman ifs.int_name); 1023d5b718b3SGarrett Wollman if (!(ifs.int_state & IFF_MULTICAST)) 1024d5b718b3SGarrett Wollman ifs.int_state |= IS_NO_RDISC; 1025d5b718b3SGarrett Wollman } 10267b6ab19dSGarrett Wollman 1027d5b718b3SGarrett Wollman 1028d5b718b3SGarrett Wollman /* It is new and ok. Add it to the list of interfaces 10297b6ab19dSGarrett Wollman */ 10307b6ab19dSGarrett Wollman ifp = (struct interface *)rtmalloc(sizeof(*ifp), "ifinit"); 10317b6ab19dSGarrett Wollman bcopy(&ifs, ifp, sizeof(*ifp)); 1032d5b718b3SGarrett Wollman get_parms(ifp); 1033d5b718b3SGarrett Wollman if_link(ifp); 10347b6ab19dSGarrett Wollman trace_if("Add", ifp); 10357b6ab19dSGarrett Wollman 10367b6ab19dSGarrett Wollman /* Notice likely bad netmask. 10377b6ab19dSGarrett Wollman */ 10387b6ab19dSGarrett Wollman if (!(prev_complaints & COMP_NETMASK) 1039d5b718b3SGarrett Wollman && !(ifp->int_if_flags & IFF_POINTOPOINT) 1040d5b718b3SGarrett Wollman && ifp->int_addr != RIP_DEFAULT) { 10417b6ab19dSGarrett Wollman for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) { 10427b6ab19dSGarrett Wollman if (ifp1->int_mask == ifp->int_mask) 10437b6ab19dSGarrett Wollman continue; 10447b6ab19dSGarrett Wollman if (ifp1->int_if_flags & IFF_POINTOPOINT) 10457b6ab19dSGarrett Wollman continue; 1046d5b718b3SGarrett Wollman if (ifp1->int_dstaddr == RIP_DEFAULT) 1047d5b718b3SGarrett Wollman continue; 1048d5b718b3SGarrett Wollman if (on_net(ifp->int_dstaddr, 10497b6ab19dSGarrett Wollman ifp1->int_net, ifp1->int_mask) 1050d5b718b3SGarrett Wollman || on_net(ifp1->int_dstaddr, 10517b6ab19dSGarrett Wollman ifp->int_net, ifp->int_mask)) { 10527b6ab19dSGarrett Wollman msglog("possible netmask problem" 1053d5b718b3SGarrett Wollman " between %s:%s and %s:%s", 10547b6ab19dSGarrett Wollman ifp->int_name, 10557b6ab19dSGarrett Wollman addrname(htonl(ifp->int_net), 10567b6ab19dSGarrett Wollman ifp->int_mask, 1), 10577b6ab19dSGarrett Wollman ifp1->int_name, 10587b6ab19dSGarrett Wollman addrname(htonl(ifp1->int_net), 10597b6ab19dSGarrett Wollman ifp1->int_mask, 1)); 10607b6ab19dSGarrett Wollman complaints |= COMP_NETMASK; 10617b6ab19dSGarrett Wollman } 10627b6ab19dSGarrett Wollman } 10637b6ab19dSGarrett Wollman } 10647b6ab19dSGarrett Wollman 1065d5b718b3SGarrett Wollman if (!(ifp->int_state & IS_ALIAS)) { 10667b6ab19dSGarrett Wollman /* Count the # of directly connected networks. 10677b6ab19dSGarrett Wollman */ 10687b6ab19dSGarrett Wollman if (!(ifp->int_if_flags & IFF_LOOPBACK)) 10697b6ab19dSGarrett Wollman tot_interfaces++; 10707b6ab19dSGarrett Wollman if (!IS_RIP_OFF(ifp->int_state)) 10717b6ab19dSGarrett Wollman rip_interfaces++; 10727b6ab19dSGarrett Wollman 1073d5b718b3SGarrett Wollman /* turn on router discovery and RIP If needed */ 10747b6ab19dSGarrett Wollman if_ok_rdisc(ifp); 10757b6ab19dSGarrett Wollman rip_on(ifp); 10767b6ab19dSGarrett Wollman } 1077d5b718b3SGarrett Wollman } 10787b6ab19dSGarrett Wollman 1079d5b718b3SGarrett Wollman /* If we are multi-homed and have at least two interfaces 10807b6ab19dSGarrett Wollman * listening to RIP, then output by default. 10817b6ab19dSGarrett Wollman */ 10827b6ab19dSGarrett Wollman if (!supplier_set && rip_interfaces > 1) 10837b6ab19dSGarrett Wollman set_supplier(); 10847b6ab19dSGarrett Wollman 10857b6ab19dSGarrett Wollman /* If we are multi-homed, optionally advertise a route to 10867b6ab19dSGarrett Wollman * our main address. 10877b6ab19dSGarrett Wollman */ 10887b6ab19dSGarrett Wollman if (advertise_mhome 10897b6ab19dSGarrett Wollman || (tot_interfaces > 1 10907b6ab19dSGarrett Wollman && mhome 10917b6ab19dSGarrett Wollman && (ifp = ifwithaddr(myaddr, 0, 0)) != 0 10927b6ab19dSGarrett Wollman && foundloopback)) { 10937b6ab19dSGarrett Wollman advertise_mhome = 1; 10947b6ab19dSGarrett Wollman rt = rtget(myaddr, HOST_MASK); 10957b6ab19dSGarrett Wollman if (rt != 0) { 10967b6ab19dSGarrett Wollman if (rt->rt_ifp != ifp 10977b6ab19dSGarrett Wollman || rt->rt_router != loopaddr) { 10987b6ab19dSGarrett Wollman rtdelete(rt); 10997b6ab19dSGarrett Wollman rt = 0; 11007b6ab19dSGarrett Wollman } else { 11017b6ab19dSGarrett Wollman rtchange(rt, rt->rt_state | RS_MHOME, 11027b6ab19dSGarrett Wollman loopaddr, loopaddr, 11037b6ab19dSGarrett Wollman 0, 0, ifp, rt->rt_time, 0); 11047b6ab19dSGarrett Wollman } 11057b6ab19dSGarrett Wollman } 11067b6ab19dSGarrett Wollman if (rt == 0) 11077b6ab19dSGarrett Wollman rtadd(myaddr, HOST_MASK, loopaddr, loopaddr, 11087b6ab19dSGarrett Wollman 0, 0, RS_MHOME, ifp); 11097b6ab19dSGarrett Wollman } 11107b6ab19dSGarrett Wollman 11117b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp1) { 11127b6ab19dSGarrett Wollman ifp1 = ifp->int_next; /* because we may delete it */ 11137b6ab19dSGarrett Wollman 11147b6ab19dSGarrett Wollman /* Forget any interfaces that have disappeared. 11157b6ab19dSGarrett Wollman */ 11167b6ab19dSGarrett Wollman if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) { 1117d5b718b3SGarrett Wollman trace_act("interface %s has disappeared", 11187b6ab19dSGarrett Wollman ifp->int_name); 11197b6ab19dSGarrett Wollman ifdel(ifp); 11207b6ab19dSGarrett Wollman continue; 11217b6ab19dSGarrett Wollman } 11227b6ab19dSGarrett Wollman 11237b6ab19dSGarrett Wollman if ((ifp->int_state & IS_BROKE) 11247b6ab19dSGarrett Wollman && !(ifp->int_state & IS_PASSIVE)) 11257b6ab19dSGarrett Wollman LIM_SEC(ifinit_timer, now.tv_sec+CHECK_BAD_INTERVAL); 11267b6ab19dSGarrett Wollman 11277b6ab19dSGarrett Wollman /* If we ever have a RIPv1 interface, assume we always will. 11287b6ab19dSGarrett Wollman * It might come back if it ever goes away. 11297b6ab19dSGarrett Wollman */ 11307b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_NO_RIPV1_OUT) && supplier) 11317b6ab19dSGarrett Wollman have_ripv1_out = 1; 11327b6ab19dSGarrett Wollman if (!(ifp->int_state & IS_NO_RIPV1_IN)) 11337b6ab19dSGarrett Wollman have_ripv1_in = 1; 11347b6ab19dSGarrett Wollman } 11357b6ab19dSGarrett Wollman 11367b6ab19dSGarrett Wollman for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) { 11377b6ab19dSGarrett Wollman /* Ensure there is always a network route for interfaces, 11387b6ab19dSGarrett Wollman * after any dead interfaces have been deleted, which 11397b6ab19dSGarrett Wollman * might affect routes for point-to-point links. 11407b6ab19dSGarrett Wollman */ 1141d5b718b3SGarrett Wollman if (!addrouteforif(ifp)) 1142d5b718b3SGarrett Wollman continue; 11437b6ab19dSGarrett Wollman 11447b6ab19dSGarrett Wollman /* Add routes to the local end of point-to-point interfaces 11457b6ab19dSGarrett Wollman * using loopback. 11467b6ab19dSGarrett Wollman */ 11477b6ab19dSGarrett Wollman if ((ifp->int_if_flags & IFF_POINTOPOINT) 11487b6ab19dSGarrett Wollman && !(ifp->int_state & IS_REMOTE) 11497b6ab19dSGarrett Wollman && foundloopback) { 11507b6ab19dSGarrett Wollman /* Delete any routes to the network address through 11517b6ab19dSGarrett Wollman * foreign routers. Remove even static routes. 11527b6ab19dSGarrett Wollman */ 11537b6ab19dSGarrett Wollman del_static(ifp->int_addr, HOST_MASK, 0); 11547b6ab19dSGarrett Wollman rt = rtget(ifp->int_addr, HOST_MASK); 11557b6ab19dSGarrett Wollman if (rt != 0 && rt->rt_router != loopaddr) { 11567b6ab19dSGarrett Wollman rtdelete(rt); 11577b6ab19dSGarrett Wollman rt = 0; 11587b6ab19dSGarrett Wollman } 11597b6ab19dSGarrett Wollman if (rt != 0) { 11607b6ab19dSGarrett Wollman if (!(rt->rt_state & RS_LOCAL) 11617b6ab19dSGarrett Wollman || rt->rt_metric > ifp->int_metric) { 11627b6ab19dSGarrett Wollman ifp1 = ifp; 11637b6ab19dSGarrett Wollman } else { 11647b6ab19dSGarrett Wollman ifp1 = rt->rt_ifp; 11657b6ab19dSGarrett Wollman } 11667b6ab19dSGarrett Wollman rtchange(rt,((rt->rt_state & ~RS_NET_SYN) 11677b6ab19dSGarrett Wollman | (RS_IF|RS_LOCAL)), 11687b6ab19dSGarrett Wollman loopaddr, loopaddr, 11697b6ab19dSGarrett Wollman 0, 0, ifp1, rt->rt_time, 0); 11707b6ab19dSGarrett Wollman } else { 11717b6ab19dSGarrett Wollman rtadd(ifp->int_addr, HOST_MASK, 11727b6ab19dSGarrett Wollman loopaddr, loopaddr, 11737b6ab19dSGarrett Wollman 0, 0, (RS_IF | RS_LOCAL), ifp); 11747b6ab19dSGarrett Wollman } 11757b6ab19dSGarrett Wollman } 11767b6ab19dSGarrett Wollman } 11777b6ab19dSGarrett Wollman 11787b6ab19dSGarrett Wollman /* add the authority routes */ 11797b6ab19dSGarrett Wollman for (intnetp = intnets; intnetp!=0; intnetp = intnetp->intnet_next) { 11807b6ab19dSGarrett Wollman rt = rtget(intnetp->intnet_addr, intnetp->intnet_mask); 11817b6ab19dSGarrett Wollman if (rt != 0 11827b6ab19dSGarrett Wollman && !(rt->rt_state & RS_NO_NET_SYN) 11837b6ab19dSGarrett Wollman && !(rt->rt_state & RS_NET_INT)) { 11847b6ab19dSGarrett Wollman rtdelete(rt); 11857b6ab19dSGarrett Wollman rt = 0; 11867b6ab19dSGarrett Wollman } 11877b6ab19dSGarrett Wollman if (rt == 0) 11887b6ab19dSGarrett Wollman rtadd(intnetp->intnet_addr, intnetp->intnet_mask, 11897b6ab19dSGarrett Wollman loopaddr, loopaddr, intnetp->intnet_metric-1, 11907b6ab19dSGarrett Wollman 0, RS_NET_SYN | RS_NET_INT, 0); 11917b6ab19dSGarrett Wollman } 11927b6ab19dSGarrett Wollman 11937b6ab19dSGarrett Wollman prev_complaints = complaints; 11947b6ab19dSGarrett Wollman } 11957b6ab19dSGarrett Wollman 11967b6ab19dSGarrett Wollman 11977b6ab19dSGarrett Wollman static void 11987b6ab19dSGarrett Wollman check_net_syn(struct interface *ifp) 11997b6ab19dSGarrett Wollman { 12007b6ab19dSGarrett Wollman struct rt_entry *rt; 12017b6ab19dSGarrett Wollman 12027b6ab19dSGarrett Wollman 12037b6ab19dSGarrett Wollman /* Turn on the need to automatically synthesize a network route 12047b6ab19dSGarrett Wollman * for this interface only if we are running RIPv1 on some other 12057b6ab19dSGarrett Wollman * interface that is on a different class-A,B,or C network. 12067b6ab19dSGarrett Wollman */ 12077b6ab19dSGarrett Wollman if (have_ripv1_out || have_ripv1_in) { 12087b6ab19dSGarrett Wollman ifp->int_state |= IS_NEED_NET_SYN; 12097b6ab19dSGarrett Wollman rt = rtget(ifp->int_std_addr, ifp->int_std_mask); 12107b6ab19dSGarrett Wollman if (rt != 0 12117b6ab19dSGarrett Wollman && 0 == (rt->rt_state & RS_NO_NET_SYN) 12127b6ab19dSGarrett Wollman && (!(rt->rt_state & RS_NET_SYN) 12137b6ab19dSGarrett Wollman || rt->rt_metric > ifp->int_metric)) { 12147b6ab19dSGarrett Wollman rtdelete(rt); 12157b6ab19dSGarrett Wollman rt = 0; 12167b6ab19dSGarrett Wollman } 12177b6ab19dSGarrett Wollman if (rt == 0) 12187b6ab19dSGarrett Wollman rtadd(ifp->int_std_addr, ifp->int_std_mask, 12197b6ab19dSGarrett Wollman ifp->int_addr, ifp->int_addr, 12207b6ab19dSGarrett Wollman ifp->int_metric, 0, RS_NET_SYN, ifp); 12217b6ab19dSGarrett Wollman 12227b6ab19dSGarrett Wollman } else { 12237b6ab19dSGarrett Wollman ifp->int_state &= ~IS_NEED_NET_SYN; 12247b6ab19dSGarrett Wollman 12257b6ab19dSGarrett Wollman rt = rtget(ifp->int_std_addr, 12267b6ab19dSGarrett Wollman ifp->int_std_mask); 12277b6ab19dSGarrett Wollman if (rt != 0 12287b6ab19dSGarrett Wollman && (rt->rt_state & RS_NET_SYN) 12297b6ab19dSGarrett Wollman && rt->rt_ifp == ifp) 12307b6ab19dSGarrett Wollman rtbad_sub(rt); 12317b6ab19dSGarrett Wollman } 12327b6ab19dSGarrett Wollman } 12337b6ab19dSGarrett Wollman 12347b6ab19dSGarrett Wollman 12357b6ab19dSGarrett Wollman /* Add route for interface if not currently installed. 12367b6ab19dSGarrett Wollman * Create route to other end if a point-to-point link, 12377b6ab19dSGarrett Wollman * otherwise a route to this (sub)network. 12387b6ab19dSGarrett Wollman */ 1239d5b718b3SGarrett Wollman int /* 0=bad interface */ 12407b6ab19dSGarrett Wollman addrouteforif(struct interface *ifp) 12417b6ab19dSGarrett Wollman { 12427b6ab19dSGarrett Wollman struct rt_entry *rt; 12437b6ab19dSGarrett Wollman naddr dst, gate; 12447b6ab19dSGarrett Wollman 12457b6ab19dSGarrett Wollman 12467b6ab19dSGarrett Wollman /* skip sick interfaces 12477b6ab19dSGarrett Wollman */ 12487b6ab19dSGarrett Wollman if (ifp->int_state & IS_BROKE) 1249d5b718b3SGarrett Wollman return 0; 12507b6ab19dSGarrett Wollman 12517b6ab19dSGarrett Wollman /* If the interface on a subnet, then install a RIPv1 route to 12527b6ab19dSGarrett Wollman * the network as well (unless it is sick). 12537b6ab19dSGarrett Wollman */ 12547b6ab19dSGarrett Wollman if (ifp->int_state & IS_SUBNET) 12557b6ab19dSGarrett Wollman check_net_syn(ifp); 12567b6ab19dSGarrett Wollman 1257d5b718b3SGarrett Wollman gate = ifp->int_addr; 1258d5b718b3SGarrett Wollman dst = (0 != (ifp->int_if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) 1259d5b718b3SGarrett Wollman ? ifp->int_dstaddr 1260d5b718b3SGarrett Wollman : htonl(ifp->int_net)); 1261d5b718b3SGarrett Wollman 12627b6ab19dSGarrett Wollman /* If we are going to send packets to the gateway, 12637b6ab19dSGarrett Wollman * it must be reachable using our physical interfaces 12647b6ab19dSGarrett Wollman */ 1265d5b718b3SGarrett Wollman if ((ifp->int_state & IS_REMOTE) 1266d5b718b3SGarrett Wollman && !(ifp->int_state && IS_EXTERNAL) 1267d5b718b3SGarrett Wollman && !check_remote(ifp)) 1268d5b718b3SGarrett Wollman return 0; 12697b6ab19dSGarrett Wollman 12707b6ab19dSGarrett Wollman /* We are finished if the correct main interface route exists. 12717b6ab19dSGarrett Wollman * The right route must be for the right interface, not synthesized 12727b6ab19dSGarrett Wollman * from a subnet, be a "gateway" or not as appropriate, and so forth. 12737b6ab19dSGarrett Wollman */ 12747b6ab19dSGarrett Wollman del_static(dst, ifp->int_mask, 0); 12757b6ab19dSGarrett Wollman rt = rtget(dst, ifp->int_mask); 12767b6ab19dSGarrett Wollman if (rt != 0) { 12777b6ab19dSGarrett Wollman if ((rt->rt_ifp != ifp 12787b6ab19dSGarrett Wollman || rt->rt_router != ifp->int_addr) 12797b6ab19dSGarrett Wollman && (!(ifp->int_state & IS_DUP) 12807b6ab19dSGarrett Wollman || rt->rt_ifp == 0 12817b6ab19dSGarrett Wollman || (rt->rt_ifp->int_state & IS_BROKE))) { 12827b6ab19dSGarrett Wollman rtdelete(rt); 12837b6ab19dSGarrett Wollman rt = 0; 12847b6ab19dSGarrett Wollman } else { 12857b6ab19dSGarrett Wollman rtchange(rt, ((rt->rt_state | RS_IF) 12867b6ab19dSGarrett Wollman & ~(RS_NET_SYN | RS_LOCAL)), 12877b6ab19dSGarrett Wollman ifp->int_addr, ifp->int_addr, 12887b6ab19dSGarrett Wollman ifp->int_metric, 0, ifp, now.tv_sec, 0); 12897b6ab19dSGarrett Wollman } 12907b6ab19dSGarrett Wollman } 12917b6ab19dSGarrett Wollman if (rt == 0) { 12927b6ab19dSGarrett Wollman if (ifp->int_transitions++ > 0) 1293d5b718b3SGarrett Wollman trace_act("re-install interface %s", 12947b6ab19dSGarrett Wollman ifp->int_name); 12957b6ab19dSGarrett Wollman 12967b6ab19dSGarrett Wollman rtadd(dst, ifp->int_mask, gate, gate, 12977b6ab19dSGarrett Wollman ifp->int_metric, 0, RS_IF, ifp); 12987b6ab19dSGarrett Wollman } 1299d5b718b3SGarrett Wollman 1300d5b718b3SGarrett Wollman return 1; 13017b6ab19dSGarrett Wollman } 1302