summaryrefslogtreecommitdiff
path: root/sys/net/if.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net/if.c')
-rw-r--r--sys/net/if.c149
1 files changed, 134 insertions, 15 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 2670eba4e5d..22ad590d968 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: if.c,v 1.24 1999/11/20 18:51:58 espie Exp $ */
+/* $OpenBSD: if.c,v 1.25 1999/12/08 06:50:17 itojun Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -53,6 +82,7 @@
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/radix.h>
+
#include <net/route.h>
#ifdef INET
@@ -65,6 +95,12 @@
#endif
#endif
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#endif
+
#ifdef IPFILTER
#include <netinet/ip_fil_compat.h>
#include <netinet/ip_fil.h>
@@ -85,6 +121,14 @@ int if_detach_rtdelete __P((struct radix_node *, void *));
int ifqmaxlen = IFQ_MAXLEN;
void if_slowtimo __P((void *arg));
+#ifdef INET6
+/*
+ * XXX: declare here to avoid to include many inet6 related files..
+ * should be more generalized?
+ */
+extern void nd6_setmtu __P((struct ifnet *));
+#endif
+
/*
* Network interface utility routines.
*
@@ -103,7 +147,8 @@ ifinit()
}
int if_index = 0;
-struct ifaddr **ifnet_addrs;
+struct ifaddr **ifnet_addrs = NULL;
+struct ifnet **ifindex2ifnet = NULL;
/*
* Attach an interface to the
@@ -120,16 +165,43 @@ if_attachsetup(ifp)
static int if_indexlim = 8;
ifp->if_index = ++if_index;
- if (ifnet_addrs == 0 || if_index >= if_indexlim) {
- unsigned int n = (if_indexlim <<= 1) * sizeof(ifa);
- struct ifaddr **q = (struct ifaddr **)
- malloc(n, M_IFADDR, M_WAITOK);
+
+ /*
+ * We have some arrays that should be indexed by if_index.
+ * since if_index will grow dynamically, they should grow too.
+ * struct ifadd **ifnet_addrs
+ * struct ifnet **ifindex2ifnet
+ */
+ if (ifnet_addrs == 0 || ifindex2ifnet == 0 || if_index >= if_indexlim) {
+ size_t n;
+ caddr_t q;
+
+ while (if_index >= if_indexlim)
+ if_indexlim <<= 1;
+
+ /* grow ifnet_addrs */
+ n = if_indexlim * sizeof(ifa);
+ q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
+ bzero(q, n);
if (ifnet_addrs) {
- bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
+ bcopy((caddr_t)ifnet_addrs, q, n/2);
free((caddr_t)ifnet_addrs, M_IFADDR);
}
- ifnet_addrs = q;
+ ifnet_addrs = (struct ifaddr **)q;
+
+ /* grow ifindex2ifnet */
+ n = if_indexlim * sizeof(struct ifnet *);
+ q = (caddr_t)malloc(n, M_IFADDR, M_WAITOK);
+ bzero(q, n);
+ if (ifindex2ifnet) {
+ bcopy((caddr_t)ifindex2ifnet, q, n/2);
+ free((caddr_t)ifindex2ifnet, M_IFADDR);
+ }
+ ifindex2ifnet = (struct ifnet **)q;
}
+
+ ifindex2ifnet[if_index] = ifp;
+
/*
* create a Link Level name for this device
*/
@@ -151,7 +223,7 @@ if_attachsetup(ifp)
sdl->sdl_nlen = namelen;
sdl->sdl_index = ifp->if_index;
sdl->sdl_type = ifp->if_type;
- ifnet_addrs[if_index - 1] = ifa;
+ ifnet_addrs[if_index] = ifa;
ifa->ifa_ifp = ifp;
ifa->ifa_rtrequest = link_rtrequest;
TAILQ_INSERT_HEAD(&ifp->if_addrlist, ifa, ifa_list);
@@ -301,6 +373,8 @@ ifa_ifwithaddr(addr)
if (equal(addr, ifa->ifa_addr))
return (ifa);
if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
+ /* IP6 doesn't have broadcast */
+ ifa->ifa_broadaddr->sa_len != 0 &&
equal(ifa->ifa_broadaddr, addr))
return (ifa);
}
@@ -346,7 +420,7 @@ ifa_ifwithnet(addr)
if (af == AF_LINK) {
register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
if (sdl->sdl_index && sdl->sdl_index <= if_index)
- return (ifnet_addrs[sdl->sdl_index - 1]);
+ return (ifnet_addrs[sdl->sdl_index]);
}
for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
@@ -495,6 +569,9 @@ if_up(ifp)
pfctlinput(PRC_IFUP, ifa->ifa_addr);
#endif
rt_ifmsg(ifp);
+#ifdef INET6
+ in6_if_up(ifp);
+#endif
}
/*
@@ -555,6 +632,35 @@ ifunit(name)
return (NULL);
}
+
+/*
+ * Map interface name in a sockaddr_dl to
+ * interface structure pointer.
+ */
+struct ifnet *
+if_withname(sa)
+ struct sockaddr *sa;
+{
+ char ifname[IFNAMSIZ+1];
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+ if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) ||
+ (sdl->sdl_nlen > IFNAMSIZ) )
+ return NULL;
+
+ /*
+ * ifunit wants a null-terminated name. It may not be null-terminated
+ * in the sockaddr. We don't want to change the caller's sockaddr,
+ * and there might not be room to put the trailing null anyway, so we
+ * make a local copy that we know we can null terminate safely.
+ */
+
+ bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen);
+ ifname[sdl->sdl_nlen] = '\0';
+ return ifunit(ifname);
+}
+
+
/*
* Interface ioctls.
*/
@@ -567,7 +673,8 @@ ifioctl(so, cmd, data, p)
{
register struct ifnet *ifp;
register struct ifreq *ifr;
- int error;
+ int error = 0;
+ short oif_flags;
switch (cmd) {
@@ -579,6 +686,7 @@ ifioctl(so, cmd, data, p)
ifp = ifunit(ifr->ifr_name);
if (ifp == 0)
return (ENXIO);
+ oif_flags = ifp->if_flags;
switch (cmd) {
case SIOCGIFFLAGS:
@@ -628,13 +736,14 @@ ifioctl(so, cmd, data, p)
case SIOCGIFMEDIA:
if (ifp->if_ioctl == 0)
return (EOPNOTSUPP);
- return ((*ifp->if_ioctl)(ifp, cmd, data));
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+ break;
default:
if (so->so_proto == 0)
return (EOPNOTSUPP);
#if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4)
- return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
+ error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
(struct mbuf *) cmd, (struct mbuf *) data,
(struct mbuf *) ifp));
#else
@@ -686,12 +795,22 @@ ifioctl(so, cmd, data, p)
case OSIOCGIFNETMASK:
*(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
}
- return (error);
}
#endif
+ break;
}
- return (0);
+
+ if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
+#ifdef INET6
+ if ((ifp->if_flags & IFF_UP) != 0) {
+ int s = splimp();
+ in6_if_up(ifp);
+ splx(s);
+ }
+#endif
+ }
+ return (error);
}
/*