if.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Use is subject to license terms.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Copyright (c) 1983, 1993
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * The Regents of the University of California. All rights reserved.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Redistribution and use in source and binary forms, with or without
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * modification, are permitted provided that the following conditions
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 1. Redistributions of source code must retain the above copyright
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * notice, this list of conditions and the following disclaimer.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 2. Redistributions in binary form must reproduce the above copyright
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * notice, this list of conditions and the following disclaimer in the
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * documentation and/or other materials provided with the distribution.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 3. All advertising materials mentioning features or use of this software
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * must display the following acknowledgment:
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This product includes software developed by the University of
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * California, Berkeley and its contributors.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * 4. Neither the name of the University nor the names of its contributors
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * may be used to endorse or promote products derived from this software
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * without specific prior written permission.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * SUCH DAMAGE.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * $FreeBSD: src/sbin/routed/if.c,v 1.8 2000/08/11 08:24:38 sheldonh Exp $
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar#pragma ident "%Z%%M% %I% %E% SMI"
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* linked list of all interfaces */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Acceptable sizes (in number of interfaces) for the interface hash
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * tables. These must all be prime. The interface hash tables all
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * start with a size of hash_table_sizes[0], and increase as needed.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarsize_t hash_table_sizes[] = { 67, 131, 257, 521, 1031, 2053, 4099, 0 };
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar size_t htbl_link_off; /* offset of the linkage structure */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar size_t htbl_key_off; /* offset of the key value (rehash) */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Get first element -- for iteration */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ((htbl)->htbl_ptrs[(htbl)->htbl_hash((arg), 0) % (htbl)->htbl_size])
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Add an element to a hash */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar hash_link((htbl), (htbl)->htbl_hash((strp), (htbl)->htbl_key_off), \
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikaruint_t tot_interfaces; /* # of remote and local interfaces */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikaruint_t rip_interfaces; /* # of interfaces doing RIP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikaruint_t ripout_interfaces; /* # of interfaces advertising RIP */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikaruint_t fwd_interfaces; /* # of interfaces ip_forwarding=1 */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic boolean_t foundloopback; /* valid flag for loopaddr */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarin_addr_t loopaddr; /* our address on loopback */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarboolean_t have_ripv1_out; /* have a RIPv1 interface */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic void if_bad(struct interface *, boolean_t);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic boolean_t addrouteforif(struct interface *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarstatic int get_if_kstats(struct interface *, struct phyi_data *);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Table of all interfaces, hashed by interface address. For remote
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * interfaces, the gateway address is used.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL, ahash, offsetof(struct interface, int_ahash),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Table of broadcast capable interfaces, hashed by interface broadcast
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL, ahash, offsetof(struct interface, int_bhash),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Table of physical_interface structures (lists of interfaces by ifIndex),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * hashed by interface index.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL, ihash, offsetof(struct physical_interface, phyi_link),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar offsetof(struct physical_interface, phyi_index),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Table of all interfaces, hashed by interface name.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar NULL, nhash, offsetof(struct interface, int_nhash),
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Hash based on an IP address. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return ((uint_t)*(const in_addr_t *)((const char *)arg + voffs));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar return ((uint_t)*(const uint32_t *)((const char *)arg + voffs));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar i = ((i<<1) & 0x7fffffff) | ((i>>30) & 0x00000003);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Add an element to the head of the list.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarlink_in(void **head, void *strp, size_t loffs)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* LINTED: alignment known to be good. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar hlp = (struct hlinkage *)((char *)strp + loffs);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ((struct hlinkage *)((char *)*head + loffs))->hl_prev =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Remove from a list */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar /* LINTED: alignment known to be good. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar hlp = (struct hlinkage *)((char *)strp + loffs);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((*hlp->hl_prev = hlp->hl_next) != NULL) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ((struct hlinkage *)((char *)hlp->hl_next + loffs))->hl_prev =
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Add to a hash */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarhash_link(struct htbl *htbl, uint_t hval, void *strp)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (htbl->htbl_grow && htbl->htbl_ifcount >= htbl->htbl_size * 5)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar hep = &htbl->htbl_ptrs[hval % htbl->htbl_size];
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Remove from a hash */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void) strcpy(dummy_phyi.phyi_name, "wildcard");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void) strcpy(dummy_ifp.int_name, "wildcard");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dummy_ifp.int_dstaddr = dummy_ifp.int_addr = INADDR_NONE;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dummy_ifp.int_state = (IS_BROKE|IS_PASSIVE|IS_NO_RIP|IS_NO_RDISC);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dummy_ifp.int_std_mask = std_mask(dummy_ifp.int_addr);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dummy_ifp.int_std_net = dummy_ifp.int_net & dummy_ifp.int_std_mask;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar dummy_ifp.int_std_addr = htonl(dummy_ifp.int_std_net);
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* allocate the interface hash tables */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ahash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar bhash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar ihash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar nhash_tbl.htbl_ptrs = calloc(initial_size, sizeof (void *));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar BADERR(_B_FALSE, "Unable to allocate interface tables");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar void **new_ptrs, **saved_old_ptrs, **old_ptrs;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((new_size = hash_table_sizes[htbl->htbl_size_index + 1]) == 0)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((new_ptrs = calloc(new_size, sizeof (void *))) == NULL) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * This is not fatal since we already have a
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * functional, yet crowded, interface table.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar msglog("%sunable to grow interface hash table: %s",
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar saved_old_ptrs = old_ptrs = htbl->htbl_ptrs;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * Go through the list of structures, and re-link each into
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * this new table.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar while (old_size-- > 0) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Link a new interface into the lists and hash tables. */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikarif_link(struct interface *ifp, uint32_t ifindex)
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar link_in((void **)&ifnet, ifp, offsetof(struct interface, int_link));
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar phyi != NULL; phyi = phyi->phyi_link.hl_next) {
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar phyi = rtmalloc(sizeof (*phyi), "physical_interface");
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar (void) strncpy(phyi->phyi_name, ifp->int_name,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar link_in((void **)&phyi->phyi_interface, ifp,
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* Find the interface with an address */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar boolean_t bcast, /* notice IFF_BROADCAST address */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar boolean_t remote) /* include IS_REMOTE interfaces */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar for (ifp = HFIRST(&ahash_tbl, &addr); ifp != NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!(ifp->int_state & (IS_BROKE | IS_PASSIVE)))
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar for (ifp = HFIRST(&bhash_tbl, &addr); ifp != NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if (!(ifp->int_state & (IS_BROKE | IS_PASSIVE)))
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar/* find the interface with the specified name ("hme0" for example) */
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar for (ifp = HFIRST(&nhash_tbl, name); ifp != NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * If there is no known interface, maybe there is a
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar * new interface. So just once look for new interfaces.
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar for (ifp = HFIRST(&ahash_tbl, &addr); ifp != NULL;
c39526b769298791ff5b0b6c5e761f49aabaeb4ePramod Gunjikar if ((ifp->int_state & IS_REMOTE) && ifp->int_addr == addr)
return (ifp);
return (NULL);
struct interface *
return (ifp);
return (NULL);
struct interface *
return (NULL);
ifscan();
struct interface *
return (ifp);
return (ifp);
ifscan();
return (maybe);
return (mask);
if (mask == 0) {
if (mask == 0)
return (mask);
return (mask);
if (addr == 0)
struct interface *
int best_pref = 0;
int pref;
pref = 0;
pref++;
return (best_ifp);
return (_B_TRUE);
return (_B_TRUE);
return (_B_FALSE);
if (!resurrected) {
if (wasbroken) {
return (_B_TRUE);
return (_B_TRUE);
return (_B_FALSE);
ifscan(void)
char *buf;
int sock;
goto calculate_lifc_len;
goto calculate_lifc_len;
ifindex = 0;
if (!(prev_complaints &
if (!foundloopback) {
if (!supplier_set)
set_supplier();
if (myaddr == 0) {
myname);
if (myaddr != 0 &&
return (_B_FALSE);
return (_B_TRUE);
return (_B_FALSE);
return (_B_TRUE);
return (_B_FALSE);