summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/if.c149
-rw-r--r--sys/net/if.h43
-rw-r--r--sys/net/if_ethersubr.c80
-rw-r--r--sys/net/if_faith.c323
-rw-r--r--sys/net/if_fddisubr.c26
-rw-r--r--sys/net/if_gif.c552
-rw-r--r--sys/net/if_gif.h86
-rw-r--r--sys/net/if_loop.c106
-rw-r--r--sys/net/if_ppp.c8
-rw-r--r--sys/net/if_tun.c14
-rw-r--r--sys/net/if_types.h8
-rw-r--r--sys/net/net_osdep.c87
-rw-r--r--sys/net/net_osdep.h149
-rw-r--r--sys/net/ppp_defs.h3
-rw-r--r--sys/net/route.c248
-rw-r--r--sys/net/route.h38
-rw-r--r--sys/net/rtsock.c126
17 files changed, 1990 insertions, 56 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);
}
/*
diff --git a/sys/net/if.h b/sys/net/if.h
index 2fed82f3649..9c4c29acb00 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.13 1999/08/08 00:43:00 niklas Exp $ */
+/* $OpenBSD: if.h,v 1.14 1999/12/08 06:50:17 itojun Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -111,6 +111,7 @@ TAILQ_HEAD(ifnet_head, ifnet); /* the actual queue head */
* Note: this is the same size as a generic device's external name.
*/
#define IFNAMSIZ 16
+#define IF_NAMESIZE IFNAMSIZ
struct ifnet { /* and the entries */
void *if_softc; /* lower-level data for this if */
@@ -143,6 +144,7 @@ struct ifnet { /* and the entries */
int ifq_maxlen;
int ifq_drops;
} if_snd; /* output queue */
+ struct ifprefix *if_prefixlist; /* linked list of prefixes per if */
};
#define if_mtu if_data.ifi_mtu
#define if_type if_data.ifi_type
@@ -244,6 +246,20 @@ struct ifaddr {
#define IFA_ROUTE RTF_UP /* route installed */
/*
+ * The prefix structure contains information about one prefix
+ * of an interface. They are maintained by the different address families,
+ * are allocated and attached when an prefix or an address is set,
+ * and are linked together so all prfefixes for an interface can be located.
+ */
+struct ifprefix {
+ struct sockaddr *ifpr_prefix; /* prefix of interface */
+ struct ifnet *ifpr_ifp; /* back-pointer to interface */
+ struct ifprefix *ifpr_next;
+ u_char ifpr_plen; /* prefix length in bits */
+ u_char ifpr_type; /* protocol dependent prefix type */
+};
+
+/*
* Message format for use in obtaining information about interfaces
* from sysctl and the routing socket.
*/
@@ -331,16 +347,31 @@ struct ifconf {
#define ifc_req ifc_ifcu.ifcu_req /* array of structures returned */
};
+/*
+ * Structure for SIOC[AGD]LIFADDR
+ */
+struct if_laddrreq {
+ char iflr_name[IFNAMSIZ];
+ unsigned int flags;
+#define IFLR_PREFIX 0x8000 /* in: prefix given out: kernel fills id */
+ unsigned int prefixlen; /* in/out */
+ struct sockaddr_storage addr; /* in/out */
+ struct sockaddr_storage dstaddr; /* out */
+};
+
struct if_nameindex {
unsigned int if_index;
char *if_name;
};
+#ifndef _KERNEL
+__BEGIN_DECLS
unsigned int if_nametoindex __P((const char *));
char *if_indextoname __P((unsigned int, char *));
struct if_nameindex *if_nameindex __P((void));
-
-#define if_freenameindex(x) free(x)
+__END_DECLS
+#define if_freenameindex(x) free(x)
+#endif
#include <net/if_arp.h>
@@ -353,6 +384,11 @@ struct if_nameindex *if_nameindex __P((void));
}
struct ifnet_head ifnet;
+struct ifnet **ifindex2ifnet;
+#if 0
+struct ifnet loif[];
+#endif
+int if_index;
void ether_ifattach __P((struct ifnet *));
void ether_ifdetach __P((struct ifnet *));
@@ -375,6 +411,7 @@ void ifinit __P((void));
int ifioctl __P((struct socket *, u_long, caddr_t, struct proc *));
int ifpromisc __P((struct ifnet *, int));
struct ifnet *ifunit __P((char *));
+struct ifnet *if_withname __P((struct sockaddr *));
struct ifaddr *ifa_ifwithaddr __P((struct sockaddr *));
struct ifaddr *ifa_ifwithaf __P((int));
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index c22ba6d04ea..3513c322bf5 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: if_ethersubr.c,v 1.31 1999/09/01 21:38:48 jason Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.32 1999/12/08 06:50:17 itojun Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 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) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -79,6 +108,14 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <net/if_bridge.h>
#endif
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+#endif
+
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
@@ -118,7 +155,7 @@ extern u_char aarp_org_code[ 3 ];
#include <sys/socketvar.h>
#endif
-#ifdef INET6
+#if 0 /*NRL INET6*/
#include <netinet6/in6.h>
#include <netinet6/in6_var.h>
#endif /* INET6 */
@@ -249,6 +286,18 @@ ether_output(ifp, m0, dst, rt0)
etype = htons(ETHERTYPE_IP);
break;
#endif
+#ifdef INET6
+ case AF_INET6:
+#ifndef OLDIP6OUTPUT
+ if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
+ return(0); /* it must be impossible, but... */
+#else
+ if (!nd6_resolve(ifp, rt, m, dst, (u_char *)edst))
+ return(0); /* if not yet resolves */
+#endif
+ etype = htons(ETHERTYPE_IPV6);
+ break;
+#endif
#ifdef NS
case AF_NS:
etype = htons(ETHERTYPE_NS);
@@ -273,7 +322,7 @@ ether_output(ifp, m0, dst, rt0)
mcopy = m_copy(m, 0, (int)M_COPYALL);
break;
#endif
-#ifdef INET6
+#if 0 /*NRL INET6*/
case AF_INET6:
/*
* The bottom line here is to either queue the outgoing packet
@@ -285,7 +334,7 @@ ether_output(ifp, m0, dst, rt0)
* If multicast dest., then use IPv6 -> Ethernet
* mcast mapping. Really simple.
*/
- ETHER_MAP_IN6_MULTICAST(((struct sockaddr_in6 *)dst)->sin6_addr,
+ ETHER_MAP_IPV6_MULTICAST(&((struct sockaddr_in6 *)dst)->sin6_addr,
edst);
} else {
/* Do unicast neighbor discovery stuff. */
@@ -583,7 +632,7 @@ decapsulate:
*/
case ETHERTYPE_IPV6:
schednetisr(NETISR_IPV6);
- inq = &ipv6intrq;
+ inq = &ip6intrq;
break;
#endif /* INET6 */
#ifdef IPX
@@ -828,9 +877,9 @@ u_char ether_ipmulticast_min[6] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
u_char ether_ipmulticast_max[6] = { 0x01, 0x00, 0x5e, 0x7f, 0xff, 0xff };
#ifdef INET6
-u_char ether_ipv6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
-u_char ether_ipv6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
-#endif /* INET6 */
+u_char ether_ip6multicast_min[6] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
+u_char ether_ip6multicast_max[6] = { 0x33, 0x33, 0xff, 0xff, 0xff, 0xff };
+#endif
/*
* Add an Ethernet multicast address or range of addresses to the list for a
@@ -877,17 +926,18 @@ ether_addmulti(ifr, ac)
#endif
#ifdef INET6
case AF_INET6:
- sin6 = (struct sockaddr_in6 *)&(ifr->ifr_addr);
+ sin6 = (struct sockaddr_in6 *)
+ &(((struct in6_ifreq *)ifr)->ifr_addr);
if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
/*
* An unspecified IPv6 address means listen to all
* of the IPv6 multicast addresses on this Ethernet.
* (Multicast routers like this.)
*/
- bcopy(ether_ipv6multicast_min, addrlo, ETHER_ADDR_LEN);
- bcopy(ether_ipv6multicast_max, addrhi, ETHER_ADDR_LEN);
+ bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
+ bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
} else {
- ETHER_MAP_IN6_MULTICAST(sin6->sin6_addr, addrlo);
+ ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
}
break;
@@ -996,10 +1046,10 @@ ether_delmulti(ifr, ac)
* possibly all-routers for this interface afterwards
* is not a bad idea.)
*/
- bcopy(ether_ipv6multicast_min, addrlo, ETHER_ADDR_LEN);
- bcopy(ether_ipv6multicast_max, addrhi, ETHER_ADDR_LEN);
+ bcopy(ether_ip6multicast_min, addrlo, ETHER_ADDR_LEN);
+ bcopy(ether_ip6multicast_max, addrhi, ETHER_ADDR_LEN);
} else {
- ETHER_MAP_IN6_MULTICAST(sin6->sin6_addr, addrlo);
+ ETHER_MAP_IPV6_MULTICAST(&sin6->sin6_addr, addrlo);
bcopy(addrlo, addrhi, ETHER_ADDR_LEN);
}
break;
diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c
new file mode 100644
index 00000000000..baadb22e398
--- /dev/null
+++ b/sys/net/if_faith.c
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1982, 1986, 1993
+ * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ */
+/*
+ * derived from
+ * @(#)if_loop.c 8.1 (Berkeley) 6/10/93
+ * Id: if_loop.c,v 1.22 1996/06/19 16:24:10 wollman Exp
+ */
+
+/*
+ * Loopback interface driver for protocol testing and timing.
+ */
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include "opt_inet.h"
+#endif
+
+#include "faith.h"
+#if NFAITH > 0
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/sockio.h>
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/time.h>
+#ifdef __bsdi__
+#include <machine/cpu.h>
+#endif
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6.h>
+#endif
+
+#include "bpfilter.h"
+
+#include <net/net_osdep.h>
+
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+static int faithioctl __P((struct ifnet *, int, caddr_t));
+#else
+static int faithioctl __P((struct ifnet *, u_long, caddr_t));
+#endif
+int faithoutput __P((struct ifnet *, register struct mbuf *, struct sockaddr *,
+ register struct rtentry *));
+static void faithrtrequest __P((int, struct rtentry *, struct sockaddr *));
+
+#ifdef __FreeBSD__
+void faithattach __P((void *));
+PSEUDO_SET(faithattach, if_faith);
+#else
+void faithattach __P((int));
+#endif
+
+static struct ifnet faithif[NFAITH];
+
+#define FAITHMTU 1500
+
+/* ARGSUSED */
+void
+faithattach(faith)
+#ifdef __FreeBSD__
+ void *faith;
+#else
+ int faith;
+#endif
+{
+ register struct ifnet *ifp;
+ register int i;
+
+ for (i = 0; i < NFAITH; i++) {
+ ifp = &faithif[i];
+ bzero(ifp, sizeof(faithif[i]));
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sprintf(ifp->if_xname, "faith%d", i);
+#else
+ ifp->if_name = "faith";
+ ifp->if_unit = i;
+#endif
+ ifp->if_mtu = FAITHMTU;
+ /* Change to BROADCAST experimentaly to announce its prefix. */
+ ifp->if_flags = /* IFF_LOOPBACK */ IFF_BROADCAST | IFF_MULTICAST;
+ ifp->if_ioctl = faithioctl;
+ ifp->if_output = faithoutput;
+ ifp->if_type = IFT_FAITH;
+ ifp->if_hdrlen = 0;
+ ifp->if_addrlen = 0;
+ if_attach(ifp);
+#if NBPFILTER > 0
+#ifdef HAVE_OLD_BPF
+ bpfattach(ifp, DLT_NULL, sizeof(u_int));
+#else
+ bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
+#endif
+#endif
+ }
+}
+
+int
+faithoutput(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ register struct mbuf *m;
+ struct sockaddr *dst;
+ register struct rtentry *rt;
+{
+ int s, isr;
+ register struct ifqueue *ifq = 0;
+
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("faithoutput no HDR");
+#if NBPFILTER > 0
+ /* BPF write needs to be handled specially */
+ if (dst->sa_family == AF_UNSPEC) {
+ dst->sa_family = *(mtod(m, int *));
+ m->m_len -= sizeof(int);
+ m->m_pkthdr.len -= sizeof(int);
+ m->m_data += sizeof(int);
+ }
+
+ if (ifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a faith header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = dst->sa_family;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+#ifdef HAVE_OLD_BPF
+ bpf_mtap(ifp, &m0);
+#else
+ bpf_mtap(ifp->if_bpf, &m0);
+#endif
+ }
+#endif
+
+ if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
+ m_freem(m);
+ return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
+ rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
+ }
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+ switch (dst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
+ default:
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ /* XXX do we need more sanity checks? */
+
+ m->m_pkthdr.rcvif = ifp;
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq);
+ m_freem(m);
+ splx(s);
+ return (ENOBUFS);
+ }
+ IF_ENQUEUE(ifq, m);
+ schednetisr(isr);
+ ifp->if_ipackets++;
+ ifp->if_ibytes += m->m_pkthdr.len;
+ splx(s);
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+faithrtrequest(cmd, rt, sa)
+ int cmd;
+ struct rtentry *rt;
+ struct sockaddr *sa;
+{
+ if (rt) {
+ rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu; /* for ISO */
+ /*
+ * For optimal performance, the send and receive buffers
+ * should be at least twice the MTU plus a little more for
+ * overhead.
+ */
+ rt->rt_rmx.rmx_recvpipe =
+ rt->rt_rmx.rmx_sendpipe = 3 * FAITHMTU;
+ }
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+static int
+faithioctl(ifp, cmd, data)
+ register struct ifnet *ifp;
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+ int cmd;
+#else
+ u_long cmd;
+#endif
+ caddr_t data;
+{
+ register struct ifaddr *ifa;
+ register struct ifreq *ifr = (struct ifreq *)data;
+ register int error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP | IFF_RUNNING;
+ ifa = (struct ifaddr *)data;
+ ifa->ifa_rtrequest = faithrtrequest;
+ /*
+ * Everything else is done at a higher level.
+ */
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifr == 0) {
+ error = EAFNOSUPPORT; /* XXX */
+ break;
+ }
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ break;
+#endif
+
+ default:
+ error = EAFNOSUPPORT;
+ break;
+ }
+ break;
+
+#ifdef SIOCSIFMTU
+#ifndef __OpenBSD__
+ case SIOCSIFMTU:
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+#endif
+#endif
+
+ case SIOCSIFFLAGS:
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+#endif /* NFAITH > 0 */
diff --git a/sys/net/if_fddisubr.c b/sys/net/if_fddisubr.c
index 4a3f3668307..74c7c0944b7 100644
--- a/sys/net/if_fddisubr.c
+++ b/sys/net/if_fddisubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_fddisubr.c,v 1.19 1999/07/28 20:02:41 fgsch Exp $ */
+/* $OpenBSD: if_fddisubr.c,v 1.20 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: if_fddisubr.c,v 1.5 1996/05/07 23:20:21 christos Exp $ */
/*
@@ -86,6 +86,14 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netipx/ipx_if.h>
#endif
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#endif
+#include <netinet6/nd6.h>
+#endif
+
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
@@ -194,6 +202,19 @@ fddi_output(ifp, m0, dst, rt0)
#endif
#ifdef INET6
case AF_INET6:
+#ifdef OLDIP6OUTPUT
+ if (!nd6_resolve(ifp, rt, m, dst, edst))
+ return (0); /* if not yet resolved */
+#else
+ if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst))
+ return 0;
+#endif
+ type = htons(ETHERTYPE_IPV6);
+ break;
+#endif
+#if 0 /*NRL IPv6*/
+#ifdef INET6
+ case AF_INET6:
/*
* The bottom line here is to either queue the outgoing packet
* in the discovery engine, or fill in edst with something
@@ -214,6 +235,7 @@ fddi_output(ifp, m0, dst, rt0)
type = htons(ETHERTYPE_IPV6);
break;
#endif /* INET6 */
+#endif
#ifdef IPX
case AF_IPX:
type = htons(ETHERTYPE_IPX);
@@ -492,7 +514,7 @@ fddi_input(ifp, fh, m)
#ifdef INET6
case ETHERTYPE_IPV6:
schednetisr(NETISR_IPV6);
- inq = &ipv6intrq;
+ inq = &ip6intrq;
break;
#endif /* INET6 */
#ifdef IPX
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
new file mode 100644
index 00000000000..4be073575d3
--- /dev/null
+++ b/sys/net/if_gif.c
@@ -0,0 +1,552 @@
+/* $OpenBSD: if_gif.c,v 1.1 1999/12/08 06:50:18 itojun 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.
+ */
+
+/*
+ * gif.c
+ */
+
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
+#include "opt_inet.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#include <sys/malloc.h>
+#endif
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/errno.h>
+#if defined(__FreeBSD__) || __FreeBSD__ >= 3
+/*nothing*/
+#else
+#include <sys/ioctl.h>
+#endif
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/in_gif.h>
+#endif /* INET */
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_gif.h>
+#endif /* INET6 */
+
+#include <net/if_gif.h>
+
+#include "gif.h"
+#include "bpfilter.h"
+
+#include <net/net_osdep.h>
+
+#if NGIF > 0
+
+#ifdef __FreeBSD__
+void gifattach __P((void *));
+#else
+void gifattach __P((int));
+#endif
+
+/*
+ * gif global variable definitions
+ */
+int ngif = NGIF; /* number of interfaces */
+struct gif_softc *gif = 0;
+
+void
+gifattach(dummy)
+#ifdef __FreeBSD__
+ void *dummy;
+#else
+ int dummy;
+#endif
+{
+ register struct gif_softc *sc;
+ register int i;
+
+ gif = sc = malloc (ngif * sizeof(struct gif_softc), M_DEVBUF, M_WAIT);
+ bzero(sc, ngif * sizeof(struct gif_softc));
+ for (i = 0; i < ngif; sc++, i++) {
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+ sprintf(sc->gif_if.if_xname, "gif%d", i);
+#else
+ sc->gif_if.if_name = "gif";
+ sc->gif_if.if_unit = i;
+#endif
+ sc->gif_if.if_mtu = GIF_MTU;
+ sc->gif_if.if_flags = IFF_POINTOPOINT | IFF_MULTICAST;
+ sc->gif_if.if_ioctl = gif_ioctl;
+ sc->gif_if.if_output = gif_output;
+ sc->gif_if.if_type = IFT_GIF;
+ if_attach(&sc->gif_if);
+#if NBPFILTER > 0
+#ifdef HAVE_OLD_BPF
+ bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
+#else
+ bpfattach(&sc->gif_if.if_bpf, &sc->gif_if, DLT_NULL, sizeof(u_int));
+#endif
+#endif
+ }
+}
+
+#ifdef __FreeBSD__
+PSEUDO_SET(gifattach, if_gif);
+#endif
+
+int
+gif_output(ifp, m, dst, rt)
+ struct ifnet *ifp;
+ struct mbuf *m;
+ struct sockaddr *dst;
+ struct rtentry *rt; /* added in net2 */
+{
+ register struct gif_softc *sc = (struct gif_softc*)ifp;
+ int error = 0;
+ static int called = 0; /* XXX: MUTEX */
+ int calllimit = 10; /* XXX: adhoc */
+
+ /*
+ * gif may cause infinite recursion calls when misconfigured.
+ * We'll prevent this by introducing upper limit.
+ * XXX: this mechanism may introduce another problem about
+ * mutual exclusion of the variable CALLED, especially if we
+ * use kernel thread.
+ */
+ if (++called >= calllimit) {
+ log(LOG_NOTICE,
+ "gif_output: recursively called too many times(%d)\n",
+ called);
+ m_freem(m);
+ error = EIO; /* is there better errno? */
+ goto end;
+ }
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+ getmicrotime(&ifp->if_lastchange);
+#else
+ ifp->if_lastchange = time;
+#endif
+ m->m_flags &= ~(M_BCAST|M_MCAST);
+ if (!(ifp->if_flags & IFF_UP) ||
+#if 0
+ sc->gif_flags & GIFF_INUSE ||
+#endif
+ sc->gif_psrc == NULL || sc->gif_pdst == NULL) {
+ m_freem(m);
+ error = ENETDOWN;
+ goto end;
+ }
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = dst->sa_family;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+#ifdef HAVE_OLD_BPF
+ bpf_mtap(ifp, &m0);
+#else
+ bpf_mtap(ifp->if_bpf, &m0);
+#endif
+ }
+#endif
+ ifp->if_opackets++;
+ ifp->if_obytes += m->m_pkthdr.len;
+#if 0
+ s = splnet();
+ sc->gif_flags |= GIFF_INUSE;
+#endif
+
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ error = in_gif_output(ifp, dst->sa_family, m, rt);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ error = in6_gif_output(ifp, dst->sa_family, m, rt);
+ break;
+#endif
+ default:
+ m_freem(m);
+ error = ENETDOWN;
+ }
+#if 0
+ sc->gif_flags &= ~GIFF_INUSE;
+ splx(s);
+#endif
+
+ end:
+ called = 0; /* reset recursion counter */
+ if (error) ifp->if_oerrors++;
+ return error;
+}
+
+void
+gif_input(m, af, gifp)
+ struct mbuf *m;
+ int af;
+ struct ifnet *gifp;
+{
+ int s, isr;
+ register struct ifqueue *ifq = 0;
+
+ if (gifp == NULL) {
+ /* just in case */
+ m_freem(m);
+ return;
+ }
+
+ if (m->m_pkthdr.rcvif)
+ m->m_pkthdr.rcvif = gifp;
+
+#if NBPFILTER > 0
+ if (gifp->if_bpf) {
+ /*
+ * We need to prepend the address family as
+ * a four byte field. Cons up a dummy header
+ * to pacify bpf. This is safe because bpf
+ * will only read from the mbuf (i.e., it won't
+ * try to free it or keep a pointer a to it).
+ */
+ struct mbuf m0;
+ u_int af = AF_INET6;
+
+ m0.m_next = m;
+ m0.m_len = 4;
+ m0.m_data = (char *)&af;
+
+#ifdef HAVE_OLD_BPF
+ bpf_mtap(gifp, &m0);
+#else
+ bpf_mtap(gifp->if_bpf, &m0);
+#endif
+ }
+#endif /*NBPFILTER > 0*/
+
+ /*
+ * Put the packet to the network layer input queue according to the
+ * specified address family.
+ * Note: older versions of gif_input directly called network layer
+ * input functions, e.g. ip6_input, here. We changed the policy to
+ * prevent too many recursive calls of such input functions, which
+ * might cause kernel panic. But the change may introduce another
+ * problem; if the input queue is full, packets are discarded.
+ * We believed it rarely occurs and changed the policy. If we find
+ * it occurs more times than we thought, we may change the policy
+ * again.
+ */
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ ifq = &ipintrq;
+ isr = NETISR_IP;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
+ default:
+ m_freem(m);
+ return;
+ }
+
+ s = splimp();
+ if (IF_QFULL(ifq)) {
+ IF_DROP(ifq); /* update statistics */
+ m_freem(m);
+ splx(s);
+ return;
+ }
+ IF_ENQUEUE(ifq, m);
+ /* we need schednetisr since the address family may change */
+ schednetisr(isr);
+ gifp->if_ipackets++;
+ gifp->if_ibytes += m->m_pkthdr.len;
+ splx(s);
+
+ return;
+}
+
+
+int
+gif_ioctl(ifp, cmd, data)
+ struct ifnet *ifp;
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+ int cmd;
+#else
+ u_long cmd;
+#endif
+ caddr_t data;
+{
+ struct gif_softc *sc = (struct gif_softc*)ifp;
+ struct ifreq *ifr = (struct ifreq*)data;
+ int error = 0, size;
+ struct sockaddr *sa, *dst, *src;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ break;
+
+ case SIOCSIFDSTADDR:
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET: /* IP supports Multicast */
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6: /* IP6 supports Multicast */
+ break;
+#endif /* INET6 */
+ default: /* Other protocols doesn't support Multicast */
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /*not FreeBSD3*/
+ break;
+
+#ifdef SIOCSIFMTU /* xxx */
+#ifndef __OpenBSD__
+ case SIOCGIFMTU:
+ break;
+ case SIOCSIFMTU:
+ {
+#ifdef __bsdi__
+ short mtu;
+ mtu = *(short *)ifr->ifr_data;
+#else
+ u_long mtu;
+ mtu = ifr->ifr_mtu;
+#endif
+ if (mtu < GIF_MTU_MIN || mtu > GIF_MTU_MAX) {
+ return (EINVAL);
+ }
+ ifp->if_mtu = mtu;
+ }
+ break;
+#endif
+#endif /* SIOCSIFMTU */
+
+ case SIOCSIFPHYADDR:
+#ifdef INET6
+ case SIOCSIFPHYADDR_IN6:
+#endif /* INET6 */
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ src = (struct sockaddr *)
+ &(((struct in_aliasreq *)data)->ifra_addr);
+ dst = (struct sockaddr *)
+ &(((struct in_aliasreq *)data)->ifra_dstaddr);
+
+ /* only one gif can have dst = INADDR_ANY */
+#define satosaddr(sa) (((struct sockaddr_in *)(sa))->sin_addr.s_addr)
+
+ if (satosaddr(dst) == INADDR_ANY) {
+ int i;
+ struct gif_softc *sc2;
+
+ for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
+ if (sc2 == sc) continue;
+ if (sc2->gif_pdst &&
+ satosaddr(sc2->gif_pdst)
+ == INADDR_ANY) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ }
+ }
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ src = (struct sockaddr *)
+ &(((struct in6_aliasreq *)data)->ifra_addr);
+ dst = (struct sockaddr *)
+ &(((struct in6_aliasreq *)data)->ifra_dstaddr);
+
+ /* only one gif can have dst = in6addr_any */
+#define satoin6(sa) (&((struct sockaddr_in6 *)(sa))->sin6_addr)
+
+ if (IN6_IS_ADDR_UNSPECIFIED(satoin6(dst))) {
+ int i;
+ struct gif_softc *sc2;
+
+ for (i = 0, sc2 = gif; i < ngif; i++, sc2++) {
+ if (sc2 == sc) continue;
+ if (sc2->gif_pdst &&
+ IN6_IS_ADDR_UNSPECIFIED(
+ satoin6(sc2->gif_pdst)
+ )) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ }
+ }
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EPROTOTYPE;
+ goto bad;
+ break;
+ }
+ if (sc->gif_psrc != NULL)
+ free((caddr_t)sc->gif_psrc, M_IFADDR);
+ if (sc->gif_pdst != NULL)
+ free((caddr_t)sc->gif_pdst, M_IFADDR);
+
+ sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
+ bzero((caddr_t)sa, size);
+ bcopy((caddr_t)src, (caddr_t)sa, size);
+ sc->gif_psrc = sa;
+
+ sa = (struct sockaddr *)malloc(size, M_IFADDR, M_WAITOK);
+ bzero((caddr_t)sa, size);
+ bcopy((caddr_t)dst, (caddr_t)sa, size);
+ sc->gif_pdst = sa;
+
+ ifp->if_flags |= (IFF_UP|IFF_RUNNING);
+ if_up(ifp); /* send up RTM_IFINFO */
+
+ break;
+
+ case SIOCGIFPSRCADDR:
+#ifdef INET6
+ case SIOCGIFPSRCADDR_IN6:
+#endif /* INET6 */
+ if (sc->gif_psrc == NULL) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ src = sc->gif_psrc;
+ switch (sc->gif_psrc->sa_family) {
+#ifdef INET
+ case AF_INET:
+ dst = &ifr->ifr_addr;
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ dst = (struct sockaddr *)
+ &(((struct in6_ifreq *)data)->ifr_addr);
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ bcopy((caddr_t)src, (caddr_t)dst, size);
+ break;
+
+ case SIOCGIFPDSTADDR:
+#ifdef INET6
+ case SIOCGIFPDSTADDR_IN6:
+#endif /* INET6 */
+ if (sc->gif_pdst == NULL) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ src = sc->gif_pdst;
+ switch (sc->gif_pdst->sa_family) {
+#ifdef INET
+ case AF_INET:
+ dst = &ifr->ifr_addr;
+ size = sizeof(struct sockaddr_in);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ dst = (struct sockaddr *)
+ &(((struct in6_ifreq *)data)->ifr_addr);
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif /* INET6 */
+ default:
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ bcopy((caddr_t)src, (caddr_t)dst, size);
+ break;
+
+ case SIOCSIFFLAGS:
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ bad:
+ return error;
+}
+#endif /*NGIF > 0*/
diff --git a/sys/net/if_gif.h b/sys/net/if_gif.h
new file mode 100644
index 00000000000..1b4307d3642
--- /dev/null
+++ b/sys/net/if_gif.h
@@ -0,0 +1,86 @@
+/* $OpenBSD: if_gif.h,v 1.1 1999/12/08 06:50:18 itojun 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.
+ */
+
+/*
+ * if_gif.h
+ */
+
+#ifndef _NET_IF_GIF_H_
+#define _NET_IF_GIF_H_
+
+
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
+#if defined(_KERNEL) && !defined(_LKM)
+#include "opt_inet.h"
+#endif
+#endif
+
+#include <netinet/in.h>
+/* xxx sigh, why route have struct route instead of pointer? */
+
+struct gif_softc {
+ struct ifnet gif_if; /* common area */
+ struct sockaddr *gif_psrc; /* Physical src addr */
+ struct sockaddr *gif_pdst; /* Physical dst addr */
+ union {
+ struct route gifscr_ro; /* xxx */
+#ifdef INET6
+ struct route_in6 gifscr_ro6; /* xxx */
+#endif
+ } gifsc_gifscr;
+ int gif_flags;
+};
+
+#define gif_ro gifsc_gifscr.gifscr_ro
+#ifdef INET6
+#define gif_ro6 gifsc_gifscr.gifscr_ro6
+#endif
+
+#define GIFF_INUSE 0x1 /* gif is in use */
+
+#define GIF_MTU (1280) /* Default MTU */
+#define GIF_MTU_MIN (1280) /* Minimum MTU */
+#define GIF_MTU_MAX (8192) /* Maximum MTU */
+
+extern int ngif;
+extern struct gif_softc *gif;
+
+/* Prototypes */
+void gif_input __P((struct mbuf *, int, struct ifnet *));
+int gif_output __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
+#if defined(__FreeBSD__) && __FreeBSD__ < 3
+int gif_ioctl __P((struct ifnet *, int, caddr_t));
+#else
+int gif_ioctl __P((struct ifnet *, u_long, caddr_t));
+#endif
+
+#endif /* _NET_IF_GIF_H_ */
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index 57dbd3fe733..46eb07ec1fb 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: if_loop.c,v 1.11 1999/01/08 00:56:45 deraadt Exp $ */
+/* $OpenBSD: if_loop.c,v 1.12 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: if_loop.c,v 1.15 1996/05/07 02:40:33 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) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -78,6 +107,14 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/ip.h>
#endif
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6.h>
+#endif
+
#ifdef NS
#include <netns/ns.h>
#include <netns/ns_if.h>
@@ -103,13 +140,12 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <net/bpf.h>
#endif
-#ifdef INET6
-#include <netinet6/in6.h>
-#include <netinet6/in6_var.h>
-#endif /* INET6 */
-
-#define LOMTU (32768)
-
+#if defined(LARGE_LOMTU)
+#define LOMTU (131072 + MHLEN + MLEN)
+#else
+#define LOMTU (32768 + MHLEN + MLEN)
+#endif
+
struct ifnet loif[NLOOP];
void
@@ -181,6 +217,55 @@ looutput(ifp, m, dst, rt)
return (rt->rt_flags & RTF_BLACKHOLE ? 0 :
rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH);
}
+
+#ifndef PULLDOWN_TEST
+ /*
+ * KAME requires that the packet to be contiguous on the
+ * mbuf. We need to make that sure.
+ * this kind of code should be avoided.
+ * XXX other conditions to avoid running this part?
+ */
+ if (m && m->m_next != NULL) {
+ struct mbuf *n;
+
+ MGETHDR(n, M_DONTWAIT, MT_HEADER);
+ if (n) {
+ MCLGET(n, M_DONTWAIT);
+ if ((n->m_flags & M_EXT) == 0) {
+ m_free(n);
+ n = NULL;
+ }
+ }
+ if (!n) {
+ printf("looutput: mbuf allocation failed\n");
+ m_freem(m);
+ return ENOBUFS;
+ }
+
+ n->m_pkthdr.rcvif = m->m_pkthdr.rcvif;
+ n->m_pkthdr.len = m->m_pkthdr.len;
+ if (m->m_pkthdr.len <= MCLBYTES) {
+ m_copydata(m, 0, m->m_pkthdr.len, mtod(n, caddr_t));
+ n->m_len = m->m_pkthdr.len;
+ m_freem(m);
+ } else {
+ m_copydata(m, 0, MCLBYTES, mtod(n, caddr_t));
+ m_adj(m, MCLBYTES);
+ n->m_len = MCLBYTES;
+ n->m_next = m;
+ m->m_flags &= ~M_PKTHDR;
+ }
+ m = n;
+ }
+#if 0
+ if (m && m->m_next != NULL) {
+ printf("loop: not contiguous...\n");
+ m_freem(m);
+ return ENOBUFS;
+ }
+#endif
+#endif
+
ifp->if_opackets++;
ifp->if_obytes += m->m_pkthdr.len;
switch (dst->sa_family) {
@@ -193,7 +278,7 @@ looutput(ifp, m, dst, rt)
#endif
#ifdef INET6
case AF_INET6:
- ifq = &ipv6intrq;
+ ifq = &ip6intrq;
isr = NETISR_IPV6;
break;
#endif /* INET6 */
@@ -273,7 +358,7 @@ loioctl(ifp, cmd, data)
case SIOCSIFADDR:
ifp->if_flags |= IFF_UP;
ifa = (struct ifaddr *)data;
- if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO)
+ if (ifa != 0 /*&& ifa->ifa_addr->sa_family == AF_ISO*/)
ifa->ifa_rtrequest = lortrequest;
/*
* Everything else is done at a higher level.
@@ -293,7 +378,6 @@ loioctl(ifp, cmd, data)
case AF_INET:
break;
#endif
-
#ifdef INET6
case AF_INET6:
break;
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c
index 5aa095a7122..32d2aa9debf 100644
--- a/sys/net/if_ppp.c
+++ b/sys/net/if_ppp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ppp.c,v 1.14 1998/07/12 04:33:20 angelos Exp $ */
+/* $OpenBSD: if_ppp.c,v 1.15 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: if_ppp.c,v 1.39 1997/05/17 21:11:59 christos Exp $ */
/*
@@ -102,6 +102,12 @@
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
+#else
+#ifdef _KERNEL
+#ifdef VJC
+#error ppp device with VJC assumes INET
+#endif
+#endif
#endif
#include "bpfilter.h"
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index 54965c3f782..05d51acf141 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_tun.c,v 1.27 1999/09/29 04:30:39 deraadt Exp $ */
+/* $OpenBSD: if_tun.c,v 1.28 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: if_tun.c,v 1.24 1996/05/07 02:40:48 thorpej Exp $ */
/*
@@ -221,11 +221,13 @@ tunclose(dev, flag, mode, p)
register struct ifaddr *ifa;
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
ifa = ifa->ifa_list.tqe_next) {
+#ifdef INET
if (ifa->ifa_addr->sa_family == AF_INET) {
rtinit(ifa, (int)RTM_DELETE,
(tp->tun_flags & TUN_DSTADDR)?
RTF_HOST : 0);
}
+#endif
}
}
splx(s);
@@ -251,6 +253,7 @@ tuninit(tp)
tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR|TUN_BRDADDR);
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
ifa = ifa->ifa_list.tqe_next) {
+#ifdef INET
if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *sin;
@@ -272,6 +275,7 @@ tuninit(tp)
} else
tp->tun_flags &= ~TUN_BRDADDR;
}
+#endif
}
return 0;
@@ -314,6 +318,8 @@ tun_ioctl(ifp, cmd, data)
((struct tun_softc *)(ifp->if_softc))->tun_if.if_mtu;
break;
#endif
+ case SIOCSIFFLAGS:
+ break;
default:
error = EINVAL;
}
@@ -612,6 +618,12 @@ tunwrite(dev, uio, ioflag)
isr = NETISR_IP;
break;
#endif
+#ifdef INET6
+ case AF_INET6:
+ ifq = &ip6intrq;
+ isr = NETISR_IPV6;
+ break;
+#endif
#ifdef NS
case AF_NS:
ifq = &nsintrq;
diff --git a/sys/net/if_types.h b/sys/net/if_types.h
index 0ef92cfbf7e..01361c1f727 100644
--- a/sys/net/if_types.h
+++ b/sys/net/if_types.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_types.h,v 1.3 1997/02/24 13:34:02 niklas Exp $ */
+/* $OpenBSD: if_types.h,v 1.4 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: if_types.h,v 1.7 1995/02/27 09:10:24 glass Exp $ */
/*
@@ -97,3 +97,9 @@
#define IFT_PROPVIRTUAL 0x35 /* Proprietary Virtual/internal */
#define IFT_PROPMUX 0x36 /* Proprietary Multiplexing */
#define IFT_ENC 0x37 /* Encapsulation */
+
+/* private usage... how should we define these? */
+#define IFT_GIF 0xf0
+#define IFT_DUMMY 0xf1
+#define IFT_PVC 0xf2
+#define IFT_FAITH 0xf3
diff --git a/sys/net/net_osdep.c b/sys/net/net_osdep.c
new file mode 100644
index 00000000000..55822ed49f3
--- /dev/null
+++ b/sys/net/net_osdep.c
@@ -0,0 +1,87 @@
+/* $OpenBSD: net_osdep.c,v 1.1 1999/12/08 06:50:18 itojun 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/errno.h>
+#if !defined(__FreeBSD__) || __FreeBSD__ < 3
+#include <sys/ioctl.h>
+#endif
+#include <sys/time.h>
+#include <sys/syslog.h>
+#include <machine/cpu.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/netisr.h>
+#include <net/route.h>
+#include <net/bpf.h>
+
+#if 0
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/ip.h>
+#include <netinet/in_gif.h>
+#endif /* INET */
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/in6_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/in6_gif.h>
+#include <netinet6/in6_ifattach.h>
+#endif /* INET6 */
+#endif
+
+#if !(defined(__NetBSD__) || defined(__OpenBSD__))
+const char *
+if_name(ifp)
+ struct ifnet *ifp;
+{
+ static char nam[IFNAMSIZ + 10]; /*enough?*/
+
+#ifdef __bsdi__
+ sprintf(nam, "%s%d", ifp->if_name, ifp->if_unit);
+#else
+ snprintf(nam, sizeof(nam), "%s%d", ifp->if_name, ifp->if_unit);
+#endif
+ return nam;
+}
+#endif
diff --git a/sys/net/net_osdep.h b/sys/net/net_osdep.h
new file mode 100644
index 00000000000..99a5b7ded1c
--- /dev/null
+++ b/sys/net/net_osdep.h
@@ -0,0 +1,149 @@
+/* $OpenBSD: net_osdep.h,v 1.1 1999/12/08 06:50:18 itojun 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.
+ */
+/*
+ * glue for kernel code programming differences.
+ */
+
+/*
+ * OS dependencies:
+ *
+ * - privileged process
+ * NetBSD, FreeBSD 3
+ * struct proc *p;
+ * if (p && !suser(p->p_ucred, &p->p_acflag))
+ * privileged;
+ * OpenBSD, BSDI [34], FreeBSD 2
+ * struct socket *so;
+ * if (so->so_state & SS_PRIV)
+ * privileged;
+ * - foo_control
+ * NetBSD, FreeBSD 3
+ * needs to give struct proc * as argument
+ * OpenBSD, BSDI [34], FreeBSD 2
+ * do not need struct proc *
+ * - bpf:
+ * OpenBSD, NetBSD, BSDI [34]
+ * need caddr_t * (= if_bpf **) and struct ifnet *
+ * FreeBSD 2, FreeBSD 3
+ * need only struct ifnet * as argument
+ * - struct ifnet
+ * use queue.h? member names if name
+ * --- --- ---
+ * FreeBSD 2 no old standard if_name+unit
+ * FreeBSD 3 yes strange if_name+unit
+ * OpenBSD yes standard if_xname
+ * NetBSD yes standard if_xname
+ * BSDI [34] no old standard if_name+unit
+ * - usrreq
+ * NetBSD, OpenBSD, BSDI [34], FreeBSD 2
+ * single function with PRU_xx, arguments are mbuf
+ * FreeBSD 3
+ * separates functions, non-mbuf arguments
+ * - {set,get}sockopt
+ * NetBSD, OpenBSD, BSDI [34], FreeBSD 2
+ * manipulation based on mbuf
+ * FreeBSD 3
+ * non-mbuf manipulation using sooptcopy{in,out}()
+ * - timeout() and untimeout()
+ * NetBSD, OpenBSD, BSDI [34], FreeBSD 2
+ * timeout() is a void function
+ * FreeBSD 3
+ * timeout() is non-void, must keep returned value for untimeuot()
+ * - sysctl
+ * NetBSD, OpenBSD
+ * foo_sysctl()
+ * BSDI [34]
+ * foo_sysctl() but with different style
+ * FreeBSD 2, FreeBSD 3
+ * linker hack
+ *
+ * - if_ioctl
+ * NetBSD, FreeBSD 3, BSDI [34]
+ * 2nd argument is u_long cmd
+ * FreeBSD 2
+ * 2nd argument is int cmd
+ * - if attach routines
+ * NetBSD
+ * void xxattach(int);
+ * FreeBSD 2, FreeBSD 3
+ * void xxattach(void *);
+ * PSEUDO_SET(xxattach, if_xx);
+ *
+ * - ovbcopy()
+ * in NetBSD 1.4 or later, ovbcopy() is not supplied in the kernel.
+ * bcopy() is safe against overwrites.
+ * - splnet()
+ * NetBSD 1.4 or later requires splsoftnet().
+ * other operating systems use splnet().
+ *
+ * - dtom()
+ * NEVER USE IT!
+ *
+ * - struct ifnet for loopback interface
+ * BSDI3: struct ifnet loif;
+ * BSDI4: struct ifnet *loifp;
+ * NetBSD, OpenBSD, FreeBSD2: struct ifnet loif[NLOOP];
+ *
+ * odd thing is that many of them refers loif as ifnet *loif,
+ * not loif[NLOOP], from outside of if_loop.c.
+ */
+
+#ifndef __NET_NET_OSDEP_H_DEFINED_
+#define __NET_NET_OSDEP_H_DEFINED_
+#ifdef _KERNEL
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+#define if_name(ifp) ((ifp)->if_xname)
+#else
+struct ifnet;
+extern char *if_name __P((struct ifnet *));
+#endif
+
+#ifdef __FreeBSD__
+#define HAVE_OLD_BPF
+#endif
+
+#if defined(__FreeBSD__) && __FreeBSD__ >= 3
+#define ifa_list ifa_link
+#define if_addrlist if_addrhead
+#define if_list if_link
+#endif
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 104000000
+#define ovbcopy bcopy
+#endif
+
+#if defined(__OpenBSD__) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
+#define HAVE_NRL_INPCB
+#endif
+
+#endif /*_KERNEL*/
+#endif /*__NET_NET_OSDEP_H_DEFINED_ */
diff --git a/sys/net/ppp_defs.h b/sys/net/ppp_defs.h
index cd075e14020..e3a435e3e01 100644
--- a/sys/net/ppp_defs.h
+++ b/sys/net/ppp_defs.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ppp_defs.h,v 1.9 1999/02/11 19:52:11 mickey Exp $ */
+/* $OpenBSD: ppp_defs.h,v 1.10 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: ppp_defs.h,v 1.1 1995/07/04 06:28:26 paulus Exp $ */
/*
@@ -65,6 +65,7 @@
#define PPP_IPCP 0x8021 /* IP Control Protocol */
#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */
#define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
#define PPP_CCP 0x80fd /* Compression Control Protocol */
#define PPP_LCP 0xc021 /* Link Control Protocol */
#define PPP_PAP 0xc023 /* Password Authentication Protocol */
diff --git a/sys/net/route.c b/sys/net/route.c
index 6602c31f2fa..23fab89eea2 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: route.c,v 1.15 1999/09/13 22:33:51 niklas Exp $ */
+/* $OpenBSD: route.c,v 1.16 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos 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, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -57,6 +86,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/ioctl.h>
+#include <sys/kernel.h>
#include <net/if.h>
#include <net/route.h>
@@ -250,6 +280,7 @@ rtfree(rt)
printf("rtfree: %p not freed (neg refs)\n", rt);
return;
}
+ rt_timer_remove_all(rt);
ifa = rt->rt_ifa;
if (ifa)
IFAFREE(ifa);
@@ -496,12 +527,18 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
case RTM_ADD:
if ((ifa = ifa_ifwithroute(flags, dst, gateway)) == NULL)
senderr(ENETUNREACH);
+
+ /* The interface found in the previous statement may
+ * be overridden later by rt_setif. See the code
+ * for case RTM_ADD in rtsock.c:route_output.
+ */
makeroute:
R_Malloc(rt, struct rtentry *, sizeof(*rt));
if (rt == NULL)
senderr(ENOBUFS);
Bzero(rt, sizeof(*rt));
rt->rt_flags = RTF_UP | flags;
+ LIST_INIT(&rt->rt_timer);
if (rt_setgate(rt, dst, gateway)) {
Free(rt);
senderr(ENOBUFS);
@@ -511,6 +548,9 @@ rtrequest(req, dst, gateway, netmask, flags, ret_nrt)
rt_maskedcopy(dst, ndst, netmask);
} else
Bcopy(dst, ndst, dst->sa_len);
+if (!rt->rt_rmx.rmx_mtu && !(rt->rt_rmx.rmx_locks & RTV_MTU)) { /* XXX */
+ rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu;
+}
rn = rnh->rnh_addaddr((caddr_t)ndst, (caddr_t)netmask,
rnh, rt->rt_nodes);
if (rn == NULL) {
@@ -646,7 +686,9 @@ rtinit(ifa, cmd, flags)
dst = flags & RTF_HOST ? ifa->ifa_dstaddr : ifa->ifa_addr;
if (cmd == RTM_DELETE) {
if ((flags & RTF_HOST) == 0 && ifa->ifa_netmask) {
- m = m_get(M_WAIT, MT_SONAME);
+ m = m_get(M_DONTWAIT, MT_SONAME);
+ if (m == NULL)
+ return(ENOBUFS);
deldst = mtod(m, struct sockaddr *);
rt_maskedcopy(dst, deldst, ifa->ifa_netmask);
dst = deldst;
@@ -689,6 +731,7 @@ rtinit(ifa, cmd, flags)
IFAFREE(rt->rt_ifa);
rt->rt_ifa = ifa;
rt->rt_ifp = ifa->ifa_ifp;
+ rt->rt_rmx.rmx_mtu = ifa->ifa_ifp->if_mtu; /*XXX*/
ifa->ifa_refcnt++;
if (ifa->ifa_rtrequest)
ifa->ifa_rtrequest(RTM_ADD, rt, SA(NULL));
@@ -697,3 +740,204 @@ rtinit(ifa, cmd, flags)
}
return (error);
}
+
+/*
+ * Route timer routines. These routes allow functions to be called
+ * for various routes at any time. This is useful in supporting
+ * path MTU discovery and redirect route deletion.
+ *
+ * This is similar to some BSDI internal functions, but it provides
+ * for multiple queues for efficiency's sake...
+ */
+
+LIST_HEAD(, rttimer_queue) rttimer_queue_head;
+static int rt_init_done = 0;
+
+#define RTTIMER_CALLOUT(r) { \
+ if (r->rtt_func != NULL) { \
+ (*r->rtt_func)(r->rtt_rt, r); \
+ } else { \
+ rtrequest((int) RTM_DELETE, \
+ (struct sockaddr *)rt_key(r->rtt_rt), \
+ 0, 0, 0, 0); \
+ } \
+}
+
+/*
+ * Some subtle order problems with domain initialization mean that
+ * we cannot count on this being run from rt_init before various
+ * protocol initializations are done. Therefore, we make sure
+ * that this is run when the first queue is added...
+ */
+
+void
+rt_timer_init()
+{
+ assert(rt_init_done == 0);
+
+#if 0
+ pool_init(&rttimer_pool, sizeof(struct rttimer), 0, 0, 0, "rttmrpl",
+ 0, NULL, NULL, M_RTABLE);
+#endif
+
+ LIST_INIT(&rttimer_queue_head);
+ timeout(rt_timer_timer, NULL, hz); /* every second */
+ rt_init_done = 1;
+}
+
+struct rttimer_queue *
+rt_timer_queue_create(timeout)
+ u_int timeout;
+{
+ struct rttimer_queue *rtq;
+
+ if (rt_init_done == 0)
+ rt_timer_init();
+
+ R_Malloc(rtq, struct rttimer_queue *, sizeof *rtq);
+ if (rtq == NULL)
+ return (NULL);
+
+ rtq->rtq_timeout = timeout;
+ TAILQ_INIT(&rtq->rtq_head);
+ LIST_INSERT_HEAD(&rttimer_queue_head, rtq, rtq_link);
+
+ return (rtq);
+}
+
+void
+rt_timer_queue_change(rtq, timeout)
+ struct rttimer_queue *rtq;
+ long timeout;
+{
+
+ rtq->rtq_timeout = timeout;
+}
+
+
+void
+rt_timer_queue_destroy(rtq, destroy)
+ struct rttimer_queue *rtq;
+ int destroy;
+{
+ struct rttimer *r;
+
+ while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL) {
+ LIST_REMOVE(r, rtt_link);
+ TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
+ if (destroy)
+ RTTIMER_CALLOUT(r);
+#if 0
+ pool_put(&rttimer_pool, r);
+#else
+ free(r, M_RTABLE);
+#endif
+ }
+
+ LIST_REMOVE(rtq, rtq_link);
+
+ /*
+ * Caller is responsible for freeing the rttimer_queue structure.
+ */
+}
+
+void
+rt_timer_remove_all(rt)
+ struct rtentry *rt;
+{
+ struct rttimer *r;
+
+ while ((r = LIST_FIRST(&rt->rt_timer)) != NULL) {
+ LIST_REMOVE(r, rtt_link);
+ TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
+#if 0
+ pool_put(&rttimer_pool, r);
+#else
+ free(r, M_RTABLE);
+#endif
+ }
+}
+
+int
+rt_timer_add(rt, func, queue)
+ struct rtentry *rt;
+ void(*func) __P((struct rtentry *, struct rttimer *));
+ struct rttimer_queue *queue;
+{
+ struct rttimer *r;
+ long current_time;
+ int s;
+
+ s = splclock();
+ current_time = mono_time.tv_sec;
+ splx(s);
+
+ /*
+ * If there's already a timer with this action, destroy it before
+ * we add a new one.
+ */
+ for (r = LIST_FIRST(&rt->rt_timer); r != NULL;
+ r = LIST_NEXT(r, rtt_link)) {
+ if (r->rtt_func == func) {
+ LIST_REMOVE(r, rtt_link);
+ TAILQ_REMOVE(&r->rtt_queue->rtq_head, r, rtt_next);
+#if 0
+ pool_put(&rttimer_pool, r);
+#else
+ free(r, M_RTABLE);
+#endif
+ break; /* only one per list, so we can quit... */
+ }
+ }
+
+#if 0
+ r = pool_get(&rttimer_pool, PR_NOWAIT);
+#else
+ r = (struct rttimer *)malloc(sizeof(*r), M_RTABLE, M_NOWAIT);
+#endif
+ if (r == NULL)
+ return (ENOBUFS);
+
+ r->rtt_rt = rt;
+ r->rtt_time = current_time;
+ r->rtt_func = func;
+ r->rtt_queue = queue;
+ LIST_INSERT_HEAD(&rt->rt_timer, r, rtt_link);
+ TAILQ_INSERT_TAIL(&queue->rtq_head, r, rtt_next);
+
+ return (0);
+}
+
+/* ARGSUSED */
+void
+rt_timer_timer(arg)
+ void *arg;
+{
+ struct rttimer_queue *rtq;
+ struct rttimer *r;
+ long current_time;
+ int s;
+
+ s = splclock();
+ current_time = mono_time.tv_sec;
+ splx(s);
+
+ s = splsoftnet();
+ for (rtq = LIST_FIRST(&rttimer_queue_head); rtq != NULL;
+ rtq = LIST_NEXT(rtq, rtq_link)) {
+ while ((r = TAILQ_FIRST(&rtq->rtq_head)) != NULL &&
+ (r->rtt_time + rtq->rtq_timeout) < current_time) {
+ LIST_REMOVE(r, rtt_link);
+ TAILQ_REMOVE(&rtq->rtq_head, r, rtt_next);
+ RTTIMER_CALLOUT(r);
+#if 0
+ pool_put(&rttimer_pool, r);
+#else
+ free(r, M_RTABLE);
+#endif
+ }
+ }
+ splx(s);
+
+ timeout(rt_timer_timer, NULL, hz); /* every second */
+}
diff --git a/sys/net/route.h b/sys/net/route.h
index cd880ad239b..2165d8330f6 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: route.h,v 1.6 1999/05/16 00:34:40 ho Exp $ */
+/* $OpenBSD: route.h,v 1.7 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@@ -36,6 +36,8 @@
* @(#)route.h 8.3 (Berkeley) 4/19/94
*/
+#include <sys/queue.h>
+
/*
* Kernel resident routing tables.
*
@@ -105,6 +107,7 @@ struct rtentry {
struct rt_metrics rt_rmx; /* metrics used by rx'ing protocols */
struct rtentry *rt_gwroute; /* implied entry for gatewayed routes */
struct rtentry *rt_parent; /* If cloned, parent of this route. */
+ LIST_HEAD(, rttimer) rt_timer; /* queue of timeouts for misc funcs */
};
#define rt_use rt_rmx.rmx_pksent
@@ -233,11 +236,34 @@ struct rt_addrinfo {
struct route_cb {
int ip_count;
+ int ip6_count;
int ns_count;
int iso_count;
int any_count;
};
+/*
+ * This structure, and the prototypes for the rt_timer_{init,remove_all,
+ * add,timer} functions all used with the kind permission of BSDI.
+ * These allow functions to be called for routes at specific times.
+ */
+
+struct rttimer {
+ TAILQ_ENTRY(rttimer) rtt_next; /* entry on timer queue */
+ LIST_ENTRY(rttimer) rtt_link; /* multiple timers per rtentry */
+ struct rttimer_queue *rtt_queue;/* back pointer to queue */
+ struct rtentry *rtt_rt; /* Back pointer to the route */
+ void (*rtt_func) __P((struct rtentry *,
+ struct rttimer *));
+ time_t rtt_time; /* When this timer was registered */
+};
+
+struct rttimer_queue {
+ long rtq_timeout;
+ TAILQ_HEAD(, rttimer) rtq_head;
+ LIST_ENTRY(rttimer_queue) rtq_link;
+};
+
#ifdef _KERNEL
#define RTFREE(rt) do { \
if ((rt)->rt_refcnt <= 1) \
@@ -270,6 +296,16 @@ void rt_newaddrmsg __P((int, struct ifaddr *, int, struct rtentry *));
int rt_setgate __P((struct rtentry *, struct sockaddr *,
struct sockaddr *));
void rt_setmetrics __P((u_long, struct rt_metrics *, struct rt_metrics *));
+int rt_timer_add __P((struct rtentry *,
+ void(*)(struct rtentry *, struct rttimer *),
+ struct rttimer_queue *));
+void rt_timer_init __P((void));
+struct rttimer_queue *
+ rt_timer_queue_create __P((u_int));
+void rt_timer_queue_change __P((struct rttimer_queue *, long));
+void rt_timer_queue_destroy __P((struct rttimer_queue *, int));
+void rt_timer_remove_all __P((struct rtentry *));
+void rt_timer_timer __P((void *));
void rtable_init __P((void **));
void rtalloc __P((struct route *));
struct rtentry *
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index f842f8be969..57303703912 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: rtsock.c,v 1.7 1998/08/24 20:39:40 downsj Exp $ */
+/* $OpenBSD: rtsock.c,v 1.8 1999/12/08 06:50:18 itojun Exp $ */
/* $NetBSD: rtsock.c,v 1.18 1996/03/29 00:32:10 cgd 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) 1988, 1991, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -68,6 +97,8 @@ static struct mbuf *
static int rt_msg2 __P((int,
struct rt_addrinfo *, caddr_t, struct walkarg *));
static void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *));
+static void rt_setif __P((struct rtentry *, struct sockaddr *,
+ struct sockaddr *, struct sockaddr *));
/* Sleazy use of local variables throughout file, warning!!!! */
#define dst info.rti_info[RTAX_DST]
@@ -99,6 +130,8 @@ route_usrreq(so, req, m, nam, control)
int af = rp->rcb_proto.sp_protocol;
if (af == AF_INET)
route_cb.ip_count--;
+ else if (af == AF_INET6)
+ route_cb.ip6_count--;
else if (af == AF_NS)
route_cb.ns_count--;
else if (af == AF_ISO)
@@ -129,6 +162,8 @@ route_usrreq(so, req, m, nam, control)
}
if (af == AF_INET)
route_cb.ip_count++;
+ else if (af == AF_INET6)
+ route_cb.ip6_count++;
else if (af == AF_NS)
route_cb.ns_count++;
else if (af == AF_ISO)
@@ -159,7 +194,6 @@ route_output(m, va_alist)
struct rt_addrinfo info;
int len, error = 0;
struct ifnet *ifp = 0;
- struct ifaddr *ifa = 0;
struct socket *so;
va_list ap;
@@ -167,7 +201,7 @@ route_output(m, va_alist)
so = va_arg(ap, struct socket *);
va_end(ap);
-
+ bzero(&info, sizeof(info));
#define senderr(e) { error = e; goto flush;}
if (m == 0 || ((m->m_len < sizeof(int32_t)) &&
(m = m_pullup(m, sizeof(int32_t))) == 0))
@@ -219,6 +253,35 @@ route_output(m, va_alist)
error = rtrequest(RTM_ADD, dst, gate, netmask,
rtm->rtm_flags, &saved_nrt);
if (error == 0 && saved_nrt) {
+ /*
+ * If the route request specified an interface with
+ * IFA and/or IFP, we set the requested interface on
+ * the route with rt_setif. It would be much better
+ * to do this inside rtrequest, but that would
+ * require passing the desired interface, in some
+ * form, to rtrequest. Since rtrequest is called in
+ * so many places (roughly 40 in our source), adding
+ * a parameter is to much for us to swallow; this is
+ * something for the FreeBSD developers to tackle.
+ * Instead, we let rtrequest compute whatever
+ * interface it wants, then come in behind it and
+ * stick in the interface that we really want. This
+ * works reasonably well except when rtrequest can't
+ * figure out what interface to use (with
+ * ifa_withroute) and returns ENETUNREACH. Ideally
+ * it shouldn't matter if rtrequest can't figure out
+ * the interface if we're going to explicitly set it
+ * ourselves anyway. But practically we can't
+ * recover here because rtrequest will not do any of
+ * the work necessary to add the route if it can't
+ * find an interface. As long as there is a default
+ * route that leads to some interface, rtrequest will
+ * find an interface, so this problem should be
+ * rarely encountered.
+ * dwiggins@bbn.com
+ */
+
+ rt_setif(saved_nrt, ifpaddr, ifaaddr, gate);
rt_setmetrics(rtm->rtm_inits,
&rtm->rtm_rmx, &saved_nrt->rt_rmx);
saved_nrt->rt_refcnt--;
@@ -287,6 +350,10 @@ route_output(m, va_alist)
case RTM_CHANGE:
if (gate && rt_setgate(rt, rt_key(rt), gate))
senderr(EDQUOT);
+
+#if 1
+ rt_setif(rt, ifpaddr, ifaaddr, gate);
+#else
/* new gateway could require new ifaddr, ifp;
flags may also be different; ifp may be specified
by ll sockaddr when protocol address is ambiguous */
@@ -310,10 +377,13 @@ route_output(m, va_alist)
rt->rt_ifp = ifp;
}
}
+#endif
rt_setmetrics(rtm->rtm_inits, &rtm->rtm_rmx,
&rt->rt_rmx);
+#if 0
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, gate);
+#endif
if (genmask)
rt->rt_genmask = genmask;
/*
@@ -387,6 +457,56 @@ rt_setmetrics(which, in, out)
#undef metric
}
+/*
+ * Set route's interface given ifpaddr, ifaaddr, and gateway.
+ */
+static void
+rt_setif(rt, Ifpaddr, Ifaaddr, Gate)
+ struct rtentry *rt;
+ struct sockaddr *Ifpaddr, *Ifaaddr, *Gate;
+{
+ struct ifaddr *ifa = 0;
+ struct ifnet *ifp = 0;
+
+ /* new gateway could require new ifaddr, ifp;
+ flags may also be different; ifp may be specified
+ by ll sockaddr when protocol address is ambiguous */
+ if (Ifpaddr && (ifa = ifa_ifwithnet(Ifpaddr)) &&
+ (ifp = ifa->ifa_ifp) && (Ifaaddr || Gate))
+ ifa = ifaof_ifpforaddr(Ifaaddr ? Ifaaddr : Gate,
+ ifp);
+ else if (Ifpaddr && (ifp = if_withname(Ifpaddr)) ) {
+ ifa = Gate ? ifaof_ifpforaddr(Gate, ifp) :
+ TAILQ_FIRST(&ifp->if_addrlist);
+ }
+ else if ((Ifaaddr && (ifa = ifa_ifwithaddr(Ifaaddr))) ||
+ (Gate && (ifa = ifa_ifwithroute(rt->rt_flags,
+ rt_key(rt), Gate))))
+ ifp = ifa->ifa_ifp;
+ if (ifa) {
+ register struct ifaddr *oifa = rt->rt_ifa;
+ if (oifa != ifa) {
+ if (oifa && oifa->ifa_rtrequest)
+ oifa->ifa_rtrequest(RTM_DELETE,
+ rt, Gate);
+ IFAFREE(rt->rt_ifa);
+ rt->rt_ifa = ifa;
+ ifa->ifa_refcnt++;
+ rt->rt_ifp = ifp;
+ rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
+ } else
+ goto call_ifareq;
+ return;
+ }
+ call_ifareq:
+ /* XXX: to reset gateway to correct value, at RTM_CHANGE */
+ if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
+ rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, Gate);
+}
+
+
#define ROUNDUP(a) \
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))