summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-08 06:50:25 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-08 06:50:25 +0000
commitd9c080e0265d3557ac6fe2d2723cf4823eaa909f (patch)
tree422a747ed77f091d33ae234312450cc5cb2aa789 /sys/netinet
parentbfa115c3a1f89cedeb913741469312347a52f8ee (diff)
bring in KAME IPv6 code, dated 19991208.
replaces NRL IPv6 layer. reuses NRL pcb layer. no IPsec-on-v6 support. see sys/netinet6/{TODO,IMPLEMENTATION} for more details. GENERIC configuration should work fine as before. GENERIC.v6 works fine as well, but you'll need KAME userland tools to play with IPv6 (will be bringed into soon).
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/fil.c11
-rw-r--r--sys/netinet/icmp6.h37
-rw-r--r--sys/netinet/if_atm.c4
-rw-r--r--sys/netinet/if_ether.h19
-rw-r--r--sys/netinet/igmp.c39
-rw-r--r--sys/netinet/in.c259
-rw-r--r--sys/netinet/in.h35
-rw-r--r--sys/netinet/in4_cksum.c217
-rw-r--r--sys/netinet/in_gif.c357
-rw-r--r--sys/netinet/in_gif.h42
-rw-r--r--sys/netinet/in_pcb.c146
-rw-r--r--sys/netinet/in_pcb.h86
-rw-r--r--sys/netinet/in_proto.c73
-rw-r--r--sys/netinet/in_var.h7
-rw-r--r--sys/netinet/ip.h7
-rw-r--r--sys/netinet/ip6.h3
-rw-r--r--sys/netinet/ip_auth.c9
-rw-r--r--sys/netinet/ip_ecn.c148
-rw-r--r--sys/netinet/ip_ecn.h55
-rw-r--r--sys/netinet/ip_fil.c9
-rw-r--r--sys/netinet/ip_frag.c9
-rw-r--r--sys/netinet/ip_icmp.c37
-rw-r--r--sys/netinet/ip_input.c61
-rw-r--r--sys/netinet/ip_mroute.h6
-rw-r--r--sys/netinet/ip_output.c56
-rw-r--r--sys/netinet/ip_var.h3
-rw-r--r--sys/netinet/tcp_debug.c8
-rw-r--r--sys/netinet/tcp_input.c173
-rw-r--r--sys/netinet/tcp_output.c89
-rw-r--r--sys/netinet/tcp_subr.c109
-rw-r--r--sys/netinet/tcp_usrreq.c84
-rw-r--r--sys/netinet/tcp_var.h14
-rw-r--r--sys/netinet/udp_usrreq.c326
-rw-r--r--sys/netinet/udp_var.h8
34 files changed, 2273 insertions, 273 deletions
diff --git a/sys/netinet/fil.c b/sys/netinet/fil.c
index adc8a0f0cd8..84bfd975173 100644
--- a/sys/netinet/fil.c
+++ b/sys/netinet/fil.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $ */
+/* $OpenBSD: fil.c,v 1.16 1999/12/08 06:50:18 itojun Exp $ */
/*
* Copyright (C) 1993-1998 by Darren Reed.
*
@@ -8,7 +8,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-1996 Darren Reed";
-static const char rcsid[] = "@(#)$Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $";
+static const char rcsid[] = "@(#)$Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Exp $";
#endif
#include <sys/errno.h>
@@ -45,6 +45,11 @@ static const char rcsid[] = "@(#)$Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp
# include <net/af.h>
#endif
#include <net/route.h>
+#ifdef _KERNEL
+#ifndef INET
+#error ipfilter assumes options INET
+#endif
+#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
@@ -1137,7 +1142,7 @@ nodata:
* SUCH DAMAGE.
*
* @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94
- * $Id: fil.c,v 1.15 1999/02/19 20:52:22 kjell Exp $
+ * $Id: fil.c,v 1.16 1999/12/08 06:50:18 itojun Exp $
*/
/*
* Copy data from an mbuf chain starting "off" bytes from the beginning,
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
new file mode 100644
index 00000000000..7bfb3b2c160
--- /dev/null
+++ b/sys/netinet/icmp6.h
@@ -0,0 +1,37 @@
+/* $OpenBSD: icmp6.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.
+ */
+
+#ifndef _NETINET_ICMP6_H_
+#define _NETINET_ICMP6_H_
+
+#include <netinet6/icmp6.h>
+
+#endif /* !_NETINET_ICMP6_H_ */
diff --git a/sys/netinet/if_atm.c b/sys/netinet/if_atm.c
index 2250042ee94..a8022fabcf0 100644
--- a/sys/netinet/if_atm.c
+++ b/sys/netinet/if_atm.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_atm.c,v 1.6 1997/09/28 23:09:55 deraadt Exp $ */
+/* $OpenBSD: if_atm.c,v 1.7 1999/12/08 06:50:18 itojun Exp $ */
/*
*
@@ -36,7 +36,7 @@
* IP <=> ATM address resolution.
*/
-#ifdef INET
+#if defined(INET) || defined(INET6)
#include <sys/param.h>
#include <sys/systm.h>
diff --git a/sys/netinet/if_ether.h b/sys/netinet/if_ether.h
index 25045da1c93..7364cdf83c1 100644
--- a/sys/netinet/if_ether.h
+++ b/sys/netinet/if_ether.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ether.h,v 1.9 1999/08/08 00:43:00 niklas Exp $ */
+/* $OpenBSD: if_ether.h,v 1.10 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: if_ether.h,v 1.22 1996/05/11 13:00:00 mycroft Exp $ */
/*
@@ -91,6 +91,23 @@ struct ether_header {
(enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \
(enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \
}
+
+/*
+ * Macro to map an IPv6 multicast address to an Ethernet multicast address.
+ * The high-order 16 bits of the Ethernet address are statically assigned,
+ * and the low-order 32 bits are taken from the low end of the IPv6 address.
+ */
+#define ETHER_MAP_IPV6_MULTICAST(ip6addr, enaddr) \
+ /* struct in6_addr *ip6addr; */ \
+ /* u_int8_t enaddr[ETHER_ADDR_LEN]; */ \
+{ \
+ (enaddr)[0] = 0x33; \
+ (enaddr)[1] = 0x33; \
+ (enaddr)[2] = ((u_int8_t *)ip6addr)[12]; \
+ (enaddr)[3] = ((u_int8_t *)ip6addr)[13]; \
+ (enaddr)[4] = ((u_int8_t *)ip6addr)[14]; \
+ (enaddr)[5] = ((u_int8_t *)ip6addr)[15]; \
+}
#endif
/*
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index 61c70584d87..25bc976f535 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: igmp.c,v 1.5 1999/08/08 00:43:00 niklas Exp $ */
+/* $OpenBSD: igmp.c,v 1.6 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: igmp.c,v 1.15 1996/02/13 23:41:25 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.
+ */
+
+/*
* Internet Group Management Protocol (IGMP) routines.
*
* Written by Steve Deering, Stanford, May 1988.
@@ -122,6 +151,7 @@ igmp_input(m, va_alist)
va_dcl
#endif
{
+ int proto;
register int iphlen;
register struct ifnet *ifp = m->m_pkthdr.rcvif;
register struct ip *ip = mtod(m, struct ip *);
@@ -137,6 +167,7 @@ igmp_input(m, va_alist)
va_start(ap, m);
iphlen = va_arg(ap, int);
+ proto = va_arg(ap, int);
va_end(ap);
++igmpstat.igps_rcv_total;
@@ -384,7 +415,8 @@ igmp_input(m, va_alist)
* Pass all valid IGMP packets up to any process(es) listening
* on a raw IGMP socket.
*/
- rip_input(m);
+ rip_input(m, iphlen, proto);
+ return;
}
void
@@ -539,6 +571,9 @@ igmp_sendpkt(inm, type)
imo.imo_multicast_loop = 0;
#endif /* MROUTING */
+#if 0 /*KAME IPSEC*/
+ m->m_pkthdr.rcvif = NULL;
+#endif /*IPSEC*/
ip_output(m, (struct mbuf *)0, (struct route *)0, IP_MULTICASTOPTS,
&imo, NULL);
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 799cd45d3c4..5f7414e6c30 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.c,v 1.13 1999/04/20 20:06:11 niklas Exp $ */
+/* $OpenBSD: in.c,v 1.14 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in.c,v 1.26 1996/02/13 23:41:39 christos Exp $ */
/*
@@ -45,7 +45,12 @@
#include <sys/systm.h>
#include <net/if.h>
+#include <net/if_types.h>
#include <net/route.h>
+#include "gif.h"
+#if NGIF > 0
+#include <net/if_gif.h>
+#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
@@ -61,6 +66,11 @@
#ifdef INET
+static int in_mask2len __P((struct in_addr *));
+static void in_len2mask __P((struct in_addr *, int));
+static int in_lifaddr_ioctl __P((struct socket *, u_long, caddr_t,
+ struct ifnet *));
+
#ifndef SUBNETSARELOCAL
#define SUBNETSARELOCAL 0
#endif
@@ -128,6 +138,44 @@ in_socktrim(ap)
}
}
+static int
+in_mask2len(mask)
+ struct in_addr *mask;
+{
+ int x, y;
+ u_char *p;
+
+ p = (u_char *)mask;
+ for (x = 0; x < sizeof(*mask); x++) {
+ if (p[x] != 0xff)
+ break;
+ }
+ y = 0;
+ if (x < sizeof(*mask)) {
+ for (y = 0; y < 8; y++) {
+ if ((p[x] & (0x80 >> y)) == 0)
+ break;
+ }
+ }
+ return x * 8 + y;
+}
+
+static void
+in_len2mask(mask, len)
+ struct in_addr *mask;
+ int len;
+{
+ int i;
+ u_char *p;
+
+ p = (u_char *)mask;
+ bzero(mask, sizeof(*mask));
+ for (i = 0; i < len / 8; i++)
+ p[i] = 0xff;
+ if (len % 8)
+ p[i] = (0xff00 >> (len % 8)) & 0xff;
+}
+
int in_interfaces; /* number of external internet interfaces */
/*
@@ -148,6 +196,31 @@ in_control(so, cmd, data, ifp)
struct sockaddr_in oldaddr;
int error, hostIsNew, maskIsNew;
+#if NGIF > 0
+ if (ifp && ifp->if_type == IFT_GIF) {
+ switch (cmd) {
+ case SIOCSIFPHYADDR:
+ if ((so->so_state & SS_PRIV) == 0)
+ return(EPERM);
+ case SIOCGIFPSRCADDR:
+ case SIOCGIFPDSTADDR:
+ return gif_ioctl(ifp, cmd, data);
+ }
+ }
+#endif
+
+ switch (cmd) {
+ case SIOCALIFADDR:
+ case SIOCDLIFADDR:
+ if ((so->so_state & SS_PRIV) == 0)
+ return(EPERM);
+ /*fall through*/
+ case SIOCGLIFADDR:
+ if (!ifp)
+ return EINVAL;
+ return in_lifaddr_ioctl(so, cmd, data, ifp);
+ }
+
/*
* Find address for this interface, if it exists.
*/
@@ -335,6 +408,190 @@ in_control(so, cmd, data, ifp)
}
/*
+ * SIOC[GAD]LIFADDR.
+ * SIOCGLIFADDR: get first address. (???)
+ * SIOCGLIFADDR with IFLR_PREFIX:
+ * get first address that matches the specified prefix.
+ * SIOCALIFADDR: add the specified address.
+ * SIOCALIFADDR with IFLR_PREFIX:
+ * EINVAL since we can't deduce hostid part of the address.
+ * SIOCDLIFADDR: delete the specified address.
+ * SIOCDLIFADDR with IFLR_PREFIX:
+ * delete the first address that matches the specified prefix.
+ * return values:
+ * EINVAL on invalid parameters
+ * EADDRNOTAVAIL on prefix match failed/specified address not found
+ * other values may be returned from in_ioctl()
+ */
+static int
+in_lifaddr_ioctl(so, cmd, data, ifp)
+ struct socket *so;
+ u_long cmd;
+ caddr_t data;
+ struct ifnet *ifp;
+{
+ struct if_laddrreq *iflr = (struct if_laddrreq *)data;
+ struct ifaddr *ifa;
+ struct sockaddr *sa;
+
+ /* sanity checks */
+ if (!data || !ifp) {
+ panic("invalid argument to in_lifaddr_ioctl");
+ /*NOTRECHED*/
+ }
+
+ switch (cmd) {
+ case SIOCGLIFADDR:
+ /* address must be specified on GET with IFLR_PREFIX */
+ if ((iflr->flags & IFLR_PREFIX) == 0)
+ break;
+ /*FALLTHROUGH*/
+ case SIOCALIFADDR:
+ case SIOCDLIFADDR:
+ /* address must be specified on ADD and DELETE */
+ sa = (struct sockaddr *)&iflr->addr;
+ if (sa->sa_family != AF_INET)
+ return EINVAL;
+ if (sa->sa_len != sizeof(struct sockaddr_in))
+ return EINVAL;
+ /* XXX need improvement */
+ sa = (struct sockaddr *)&iflr->dstaddr;
+ if (sa->sa_family
+ && sa->sa_family != AF_INET)
+ return EINVAL;
+ if (sa->sa_len && sa->sa_len != sizeof(struct sockaddr_in))
+ return EINVAL;
+ break;
+ default: /*shouldn't happen*/
+#if 0
+ panic("invalid cmd to in_lifaddr_ioctl");
+ /*NOTREACHED*/
+#else
+ return EOPNOTSUPP;
+#endif
+ }
+ if (sizeof(struct in_addr) * 8 < iflr->prefixlen)
+ return EINVAL;
+
+ switch (cmd) {
+ case SIOCALIFADDR:
+ {
+ struct in_aliasreq ifra;
+
+ if (iflr->flags & IFLR_PREFIX)
+ return EINVAL;
+
+ /* copy args to in_aliasreq, perform ioctl(SIOCAIFADDR_IN6). */
+ bzero(&ifra, sizeof(ifra));
+ bcopy(iflr->iflr_name, ifra.ifra_name,
+ sizeof(ifra.ifra_name));
+
+ bcopy(&iflr->addr, &ifra.ifra_addr,
+ ((struct sockaddr *)&iflr->addr)->sa_len);
+
+ if (((struct sockaddr *)&iflr->dstaddr)->sa_family) { /*XXX*/
+ bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
+ ((struct sockaddr *)&iflr->dstaddr)->sa_len);
+ }
+
+ ifra.ifra_mask.sin_family = AF_INET;
+ ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
+ in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
+
+ return in_control(so, SIOCAIFADDR, (caddr_t)&ifra, ifp);
+ }
+ case SIOCGLIFADDR:
+ case SIOCDLIFADDR:
+ {
+ struct in_ifaddr *ia;
+ struct in_addr mask, candidate, match;
+ struct sockaddr_in *sin;
+ int cmp;
+
+ bzero(&mask, sizeof(mask));
+ if (iflr->flags & IFLR_PREFIX) {
+ /* lookup a prefix rather than address. */
+ in_len2mask(&mask, iflr->prefixlen);
+
+ sin = (struct sockaddr_in *)&iflr->addr;
+ match.s_addr = sin->sin_addr.s_addr;
+ match.s_addr &= mask.s_addr;
+
+ /* if you set extra bits, that's wrong */
+ if (match.s_addr != sin->sin_addr.s_addr)
+ return EINVAL;
+
+ cmp = 1;
+ } else {
+ if (cmd == SIOCGLIFADDR) {
+ /* on getting an address, take the 1st match */
+ cmp = 0; /*XXX*/
+ } else {
+ /* on deleting an address, do exact match */
+ in_len2mask(&mask, 32);
+ sin = (struct sockaddr_in *)&iflr->addr;
+ match.s_addr = sin->sin_addr.s_addr;
+
+ cmp = 1;
+ }
+ }
+
+ for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) {
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (!cmp)
+ break;
+ candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
+ candidate.s_addr &= mask.s_addr;
+ if (candidate.s_addr == match.s_addr)
+ break;
+ }
+ if (!ifa)
+ return EADDRNOTAVAIL;
+ ia = (struct in_ifaddr *)ifa;
+
+ if (cmd == SIOCGLIFADDR) {
+ /* fill in the if_laddrreq structure */
+ bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
+
+ if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
+ bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
+ ia->ia_dstaddr.sin_len);
+ } else
+ bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
+
+ iflr->prefixlen =
+ in_mask2len(&ia->ia_sockmask.sin_addr);
+
+ iflr->flags = 0; /*XXX*/
+
+ return 0;
+ } else {
+ struct in_aliasreq ifra;
+
+ /* fill in_aliasreq and do ioctl(SIOCDIFADDR_IN6) */
+ bzero(&ifra, sizeof(ifra));
+ bcopy(iflr->iflr_name, ifra.ifra_name,
+ sizeof(ifra.ifra_name));
+
+ bcopy(&ia->ia_addr, &ifra.ifra_addr,
+ ia->ia_addr.sin_len);
+ if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
+ bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
+ ia->ia_dstaddr.sin_len);
+ }
+ bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
+ ia->ia_sockmask.sin_len);
+
+ return in_control(so, SIOCDIFADDR, (caddr_t)&ifra, ifp);
+ }
+ }
+ }
+
+ return EOPNOTSUPP; /*just for safety*/
+}
+
+/*
* Delete any existing route for an interface.
*/
void
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index faf5eb1ab0e..84a9cc056d7 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.25 1999/10/28 03:29:49 angelos Exp $ */
+/* $OpenBSD: in.h,v 1.26 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -63,6 +63,7 @@
#define IPPROTO_IPV6 41 /* IPv6 in IPv6 */
#define IPPROTO_ROUTING 43 /* Routing header. */
#define IPPROTO_FRAGMENT 44 /* Fragmentation/reassembly header. */
+#define IPPROTO_RSVP 46 /* resource reservation */
#define IPPROTO_ESP 50 /* Encap. Security Payload */
#define IPPROTO_AH 51 /* Authentication header */
#define IPPROTO_ICMPV6 58 /* ICMP for IPv6 */
@@ -71,6 +72,8 @@
#define IPPROTO_EON 80 /* ISO cnlp */
#define IPPROTO_ETHERIP 97 /* Ethernet in IPv4 */
#define IPPROTO_ENCAP 98 /* encapsulation header */
+#define IPPROTO_PIM 103 /* Protocol indep. multicast */
+#define IPPROTO_IPCOMP 108 /* IP Payload Comp. Protocol */
#define IPPROTO_RAW 255 /* raw IP packet */
#define IPPROTO_MAX 256
@@ -133,6 +136,7 @@ struct in_addr {
in_addr_t s_addr;
};
+#if 0 /*NRL IPv6*/
/*
* IP Version 6 Internet address
*/
@@ -151,6 +155,10 @@ struct in6_addr {
#define s6_addr16 s6_u.s6u_addr16
#define s6_addr32 s6_u.s6u_addr32
};
+#endif
+
+/* last return value of *_input(), meaning "all job for this pkt is done". */
+#define IPPROTO_DONE 257
/*
* Definitions of bits in internet address integers.
@@ -216,6 +224,7 @@ struct in6_addr {
#define IN_LOOPBACKNET 127 /* official! */
+#if 0 /*NRL IPv6*/
/*
* Tests for IPv6 address types
*/
@@ -294,6 +303,7 @@ extern const struct in6_addr in6addr_any;
extern const struct in6_addr in6addr_loopback;
#define IN6ADDR_LOOPBACK_INIT {{{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 }}}
+#endif
/*
* IP Version 4 socket address.
@@ -306,6 +316,7 @@ struct sockaddr_in {
int8_t sin_zero[8];
};
+#if 0 /*NRL IPv6*/
/*
* IP Version 6 socket address.
*/
@@ -318,6 +329,9 @@ struct sockaddr_in6 {
struct in6_addr sin6_addr;
u_int32_t sin6_scope_id;
};
+#endif
+
+#define INET_ADDRSTRLEN 16
/*
* Structure used to describe IP options.
@@ -360,6 +374,7 @@ struct ip_opts {
#define IP_ESP_TRANS_LEVEL 21 /* u_char; transport encryption */
#define IP_ESP_NETWORK_LEVEL 22 /* u_char; full-packet encryption */
+#if 0 /* NRL IPv6 */
#define IPV6_MULTICAST_IF 23 /* u_int; set/get multicast interface */
#define IPV6_MULTICAST_HOPS 24 /* int; set/get multicast hop limit */
#define IPV6_MULTICAST_LOOP 25 /* u_int; set/get multicast loopback */
@@ -379,9 +394,14 @@ struct ip_opts {
#define IPV6_CHECKSUM 37 /* int; offset to place send checksum */
#define ICMPV6_FILTER 38 /* struct icmpv6_filter; get/set filter */
#define ICMP6_FILTER ICMP6_FILTER
+#endif
#define IPSEC_OUTSA 39 /* set the outbound SA for a socket */
+#if 0 /*KAME IPSEC*/
+#define IP_IPSEC_POLICY ?? /* struct; get/set security policy */
+#endif
+
/*
* Security levels - IPsec, not IPSO
*/
@@ -398,6 +418,7 @@ struct ip_opts {
#define IPSEC_ESP_TRANS_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT
#define IPSEC_ESP_NETWORK_LEVEL_DEFAULT IPSEC_LEVEL_DEFAULT
+#if 0 /* NRL IPv6 */
/*
* IPv6 Routing header types
*/
@@ -405,6 +426,7 @@ struct ip_opts {
#define IPV6_RTHDR_LOOSE 0 /* this hop need not be a neighbor */
#define IPV6_RTHDR_STRICT 1 /* this hop must be a neighbor */
+#endif
/*
* Defaults and limits for options
@@ -421,6 +443,7 @@ struct ip_mreq {
struct in_addr imr_interface; /* local IP address of interface */
};
+#if 0 /* NRL IPv6 */
/*
* Argument structure for IPV6_ADD_MEMBERSHIP and IPV6_DROP_MEMBERSHIP.
*/
@@ -436,6 +459,7 @@ struct in6_pktinfo {
struct in6_addr ipi6_addr;
unsigned int ipi6_ifindex;
};
+#endif
/*
* Argument for IP_PORTRANGE:
@@ -449,7 +473,9 @@ struct in6_pktinfo {
* Buffer lengths for strings containing printable IP addresses
*/
#define INET_ADDRSTRLEN 16
+#if 0 /* NRL IPv6 */
#define INET6_ADDRSTRLEN 46
+#endif
/*
* Definitions for inet sysctl operations.
@@ -577,7 +603,8 @@ struct in6_pktinfo {
#define IPCTL_IPPORT_HILASTAUTO 10
#define IPCTL_IPPORT_MAXQUEUE 11
#define IPCTL_ENCDEBUG 12
-#define IPCTL_MAXID 13
+#define IPCTL_GIF_TTL 13 /* default TTL for gif encap packet */
+#define IPCTL_MAXID 14
#define IPCTL_NAMES { \
{ 0, 0 }, \
@@ -593,8 +620,12 @@ struct in6_pktinfo {
{ "porthilast", CTLTYPE_INT }, \
{ "maxqueue", CTLTYPE_INT }, \
{ "encdebug", CTLTYPE_INT }, \
+ { "gifttl", CTLTYPE_INT }, \
}
+/* INET6 stuff */
+#include <netinet6/in6.h>
+
#ifndef _KERNEL
#include <sys/cdefs.h>
diff --git a/sys/netinet/in4_cksum.c b/sys/netinet/in4_cksum.c
new file mode 100644
index 00000000000..171d5467420
--- /dev/null
+++ b/sys/netinet/in4_cksum.c
@@ -0,0 +1,217 @@
+/* $OpenBSD: in4_cksum.c,v 1.1 1999/12/08 06:50:19 itojun Exp $ */
+
+/* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */
+
+/*
+ * Copyright (C) 1999 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, 1992, 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.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+/*
+ * Checksum routine for Internet Protocol family headers (Portable Version).
+ * This is only for IPv4 pseudo header checksum.
+ * No need to clear non-pseudo-header fields in IPv4 header.
+ * len is for actual payload size, and does not include IPv4 header and
+ * skipped header chain (off + len should be equal to the whole packet).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+
+int
+in4_cksum(m, nxt, off, len)
+ register struct mbuf *m;
+ u_int8_t nxt;
+ register int off, len;
+{
+ register u_int16_t *w;
+ register int sum = 0;
+ register int mlen = 0;
+ int byte_swapped = 0;
+ struct ipovly ipov;
+
+ union {
+ u_int8_t c[2];
+ u_int16_t s;
+ } s_util;
+ union {
+ u_int16_t s[2];
+ u_int32_t l;
+ } l_util;
+
+ /* pseudo header */
+ if (off < sizeof(struct ipovly))
+ panic("offset too short");
+ bzero(&ipov, sizeof(ipov));
+ ipov.ih_len = htons(len);
+ ipov.ih_pr = nxt;
+ ipov.ih_src = mtod(m, struct ip *)->ip_src;
+ ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
+ w = (u_int16_t *)&ipov;
+ /* assumes sizeof(ipov) == 20 */
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
+ sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
+
+ /* skip unnecessary part */
+ while (m && off > 0) {
+ if (m->m_len > off)
+ break;
+ off -= m->m_len;
+ m = m->m_next;
+ }
+
+ for (;m && len; m = m->m_next) {
+ if (m->m_len == 0)
+ continue;
+ w = (u_int16_t *)(mtod(m, caddr_t) + off);
+ if (mlen == -1) {
+ /*
+ * The first byte of this mbuf is the continuation
+ * of a word spanning between this mbuf and the
+ * last mbuf.
+ *
+ * s_util.c[0] is already saved when scanning previous
+ * mbuf.
+ */
+ s_util.c[1] = *(u_int8_t *)w;
+ sum += s_util.s;
+ w = (u_int16_t *)((u_int8_t *)w + 1);
+ mlen = m->m_len - off - 1;
+ len--;
+ } else
+ mlen = m->m_len - off;
+ off = 0;
+ if (len < mlen)
+ mlen = len;
+ len -= mlen;
+ /*
+ * Force to even boundary.
+ */
+ if ((1 & (long) w) && (mlen > 0)) {
+ REDUCE;
+ sum <<= 8;
+ s_util.c[0] = *(u_int8_t *)w;
+ w = (u_int16_t *)((int8_t *)w + 1);
+ mlen--;
+ byte_swapped = 1;
+ }
+ /*
+ * Unroll the loop to make overhead from
+ * branches &c small.
+ */
+ while ((mlen -= 32) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
+ sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
+ sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
+ w += 16;
+ }
+ mlen += 32;
+ while ((mlen -= 8) >= 0) {
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
+ w += 4;
+ }
+ mlen += 8;
+ if (mlen == 0 && byte_swapped == 0)
+ continue;
+ REDUCE;
+ while ((mlen -= 2) >= 0) {
+ sum += *w++;
+ }
+ if (byte_swapped) {
+ REDUCE;
+ sum <<= 8;
+ byte_swapped = 0;
+ if (mlen == -1) {
+ s_util.c[1] = *(u_int8_t *)w;
+ sum += s_util.s;
+ mlen = 0;
+ } else
+ mlen = -1;
+ } else if (mlen == -1)
+ s_util.c[0] = *(u_int8_t *)w;
+ }
+ if (len)
+ printf("cksum4: out of data\n");
+ if (mlen == -1) {
+ /* The last mbuf has odd # of bytes. Follow the
+ standard (the odd byte may be shifted left by 8 bits
+ or not as determined by endian-ness of the machine) */
+ s_util.c[1] = 0;
+ sum += s_util.s;
+ }
+ REDUCE;
+ return (~sum & 0xffff);
+}
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
new file mode 100644
index 00000000000..5abb3007660
--- /dev/null
+++ b/sys/netinet/in_gif.c
@@ -0,0 +1,357 @@
+/* $OpenBSD: in_gif.c,v 1.1 1999/12/08 06:50:19 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.
+ */
+
+/*
+ * in_gif.c
+ */
+
+#ifdef __FreeBSD__
+#include "opt_mrouting.h"
+#endif
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
+#include "opt_inet.h"
+#ifdef __NetBSD__ /*XXX*/
+#include "opt_ipsec.h"
+#endif
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+#ifdef __FreeBSD__
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#endif
+#if !defined(__FreeBSD__) || __FreeBSD__ < 3
+#include <sys/ioctl.h>
+#endif
+#include <sys/protosw.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_gif.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/in_gif.h>
+#include <netinet/ip_ecn.h>
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif
+
+#ifdef MROUTING
+#include <netinet/ip_mroute.h>
+#endif /* MROUTING */
+
+#include <net/if_gif.h>
+
+#include "gif.h"
+
+#include <machine/stdarg.h>
+
+#include <net/net_osdep.h>
+
+#if NGIF > 0
+int ip_gif_ttl = GIF_TTL;
+#else
+int ip_gif_ttl = 0;
+#endif
+#ifdef __FreeBSD__
+SYSCTL_INT(_net_inet_ip, IPCTL_GIF_TTL, gifttl, CTLFLAG_RW,
+ &ip_gif_ttl, 0, "");
+#endif
+
+int
+in_gif_output(ifp, family, m, rt)
+ struct ifnet *ifp;
+ int family;
+ struct mbuf *m;
+ struct rtentry *rt;
+{
+ register struct gif_softc *sc = (struct gif_softc*)ifp;
+ struct sockaddr_in *dst = (struct sockaddr_in *)&sc->gif_ro.ro_dst;
+ struct sockaddr_in *sin_src = (struct sockaddr_in *)sc->gif_psrc;
+ struct sockaddr_in *sin_dst = (struct sockaddr_in *)sc->gif_pdst;
+ struct ip iphdr; /* capsule IP header, host byte ordered */
+ int proto, error;
+ u_int8_t tos;
+
+ if (sin_src == NULL || sin_dst == NULL ||
+ sin_src->sin_family != AF_INET ||
+ sin_dst->sin_family != AF_INET) {
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ switch (family) {
+#ifdef INET
+ case AF_INET:
+ {
+ struct ip *ip;
+
+ proto = IPPROTO_IPV4;
+ if (m->m_len < sizeof(*ip)) {
+ m = m_pullup(m, sizeof(*ip));
+ if (!m)
+ return ENOBUFS;
+ }
+ ip = mtod(m, struct ip *);
+ tos = ip->ip_tos;
+ break;
+ }
+#endif /*INET*/
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct ip6_hdr *ip6;
+ proto = IPPROTO_IPV6;
+ if (m->m_len < sizeof(*ip6)) {
+ m = m_pullup(m, sizeof(*ip6));
+ if (!m)
+ return ENOBUFS;
+ }
+ ip6 = mtod(m, struct ip6_hdr *);
+ tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+ break;
+ }
+#endif /*INET6*/
+ default:
+#ifdef DIAGNOSTIC
+ printf("in_gif_output: warning: unknown family %d passed\n",
+ family);
+#endif
+ m_freem(m);
+ return EAFNOSUPPORT;
+ }
+
+ bzero(&iphdr, sizeof(iphdr));
+ iphdr.ip_src = sin_src->sin_addr;
+ if (ifp->if_flags & IFF_LINK0) {
+ /* multi-destination mode */
+ if (sin_dst->sin_addr.s_addr != INADDR_ANY)
+ iphdr.ip_dst = sin_dst->sin_addr;
+ else if (rt) {
+ if (family != AF_INET) {
+ m_freem(m);
+ return EINVAL; /*XXX*/
+ }
+ iphdr.ip_dst = ((struct sockaddr_in *)
+ (rt->rt_gateway))->sin_addr;
+ } else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ } else {
+ /* bidirectional configured tunnel mode */
+ if (sin_dst->sin_addr.s_addr != INADDR_ANY)
+ iphdr.ip_dst = sin_dst->sin_addr;
+ else {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+ }
+ iphdr.ip_p = proto;
+ /* version will be set in ip_output() */
+ iphdr.ip_ttl = ip_gif_ttl;
+ iphdr.ip_len = m->m_pkthdr.len + sizeof(struct ip);
+ if (ifp->if_flags & IFF_LINK1)
+ ip_ecn_ingress(ECN_ALLOWED, &iphdr.ip_tos, &tos);
+
+ /* prepend new IP header */
+ M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
+ if (m && m->m_len < sizeof(struct ip))
+ m = m_pullup(m, sizeof(struct ip));
+ if (m == NULL) {
+ printf("ENOBUFS in in_gif_output %d\n", __LINE__);
+ return ENOBUFS;
+ }
+
+ *(mtod(m, struct ip *)) = iphdr;
+
+ if (dst->sin_family != sin_dst->sin_family ||
+ dst->sin_addr.s_addr != sin_dst->sin_addr.s_addr) {
+ /* cache route doesn't match */
+ dst->sin_family = sin_dst->sin_family;
+ dst->sin_len = sizeof(struct sockaddr_in);
+ dst->sin_addr = sin_dst->sin_addr;
+ if (sc->gif_ro.ro_rt) {
+ RTFREE(sc->gif_ro.ro_rt);
+ sc->gif_ro.ro_rt = NULL;
+ }
+#if 0
+ sc->gif_if.if_mtu = GIF_MTU;
+#endif
+ }
+
+ if (sc->gif_ro.ro_rt == NULL) {
+ rtalloc(&sc->gif_ro);
+ if (sc->gif_ro.ro_rt == NULL) {
+ m_freem(m);
+ return ENETUNREACH;
+ }
+#if 0
+ ifp->if_mtu = sc->gif_ro.ro_rt->rt_ifp->if_mtu
+ - sizeof(struct ip);
+#endif
+ }
+
+#ifdef IPSEC
+#ifndef __OpenBSD__ /*KAME IPSEC*/
+ m->m_pkthdr.rcvif = NULL;
+#endif
+#endif /*IPSEC*/
+#ifndef __OpenBSD__
+ error = ip_output(m, NULL, &sc->gif_ro, 0, NULL);
+#else
+ error = ip_output(m, NULL, &sc->gif_ro, 0, NULL, NULL);
+#endif
+ return(error);
+}
+
+void
+#if __STDC__
+in_gif_input(struct mbuf *m, ...)
+#else
+in_gif_input(m, va_alist)
+ struct mbuf *m;
+ va_dcl
+#endif
+{
+ int off, proto;
+ struct gif_softc *sc;
+ struct ifnet *gifp = NULL;
+ struct ip *ip;
+ int i, af;
+ va_list ap;
+ u_int8_t otos;
+
+ va_start(ap, m);
+ off = va_arg(ap, int);
+ proto = va_arg(ap, int);
+ va_end(ap);
+
+ ip = mtod(m, struct ip *);
+
+ /* this code will be soon improved. */
+#define satosin(sa) ((struct sockaddr_in *)(sa))
+ for (i = 0, sc = gif; i < ngif; i++, sc++) {
+ if (sc->gif_psrc == NULL
+ || sc->gif_pdst == NULL
+ || sc->gif_psrc->sa_family != AF_INET
+ || sc->gif_pdst->sa_family != AF_INET) {
+ continue;
+ }
+
+ if ((sc->gif_if.if_flags & IFF_UP) == 0)
+ continue;
+
+ if ((sc->gif_if.if_flags & IFF_LINK0)
+ && satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
+ && satosin(sc->gif_pdst)->sin_addr.s_addr == INADDR_ANY) {
+ gifp = &sc->gif_if;
+ continue;
+ }
+
+ if (satosin(sc->gif_psrc)->sin_addr.s_addr == ip->ip_dst.s_addr
+ && satosin(sc->gif_pdst)->sin_addr.s_addr == ip->ip_src.s_addr)
+ {
+ gifp = &sc->gif_if;
+ break;
+ }
+ }
+
+ if (gifp == NULL) {
+#ifdef MROUTING
+ /* for backward compatibility */
+ if (proto == IPPROTO_IPV4) {
+ ipip_input(m, off, proto);
+ return;
+ }
+#endif /*MROUTING*/
+ m_freem(m);
+ ipstat.ips_nogif++;
+ return;
+ }
+
+ otos = ip->ip_tos;
+ m_adj(m, off);
+
+ switch (proto) {
+#ifdef INET
+ case IPPROTO_IPV4:
+ {
+ struct ip *ip;
+ af = AF_INET;
+ if (m->m_len < sizeof(*ip)) {
+ m = m_pullup(m, sizeof(*ip));
+ if (!m)
+ return;
+ }
+ ip = mtod(m, struct ip *);
+ if (gifp->if_flags & IFF_LINK1)
+ ip_ecn_egress(ECN_ALLOWED, &otos, &ip->ip_tos);
+ break;
+ }
+#endif
+#ifdef INET6
+ case IPPROTO_IPV6:
+ {
+ struct ip6_hdr *ip6;
+ u_int8_t itos;
+ af = AF_INET6;
+ if (m->m_len < sizeof(*ip6)) {
+ m = m_pullup(m, sizeof(*ip6));
+ if (!m)
+ return;
+ }
+ ip6 = mtod(m, struct ip6_hdr *);
+ itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+ if (gifp->if_flags & IFF_LINK1)
+ ip_ecn_egress(ECN_ALLOWED, &otos, &itos);
+ ip6->ip6_flow &= ~htonl(0xff << 20);
+ ip6->ip6_flow |= htonl((u_int32_t)itos << 20);
+ break;
+ }
+#endif /* INET6 */
+ default:
+ ipstat.ips_nogif++;
+ m_freem(m);
+ return;
+ }
+ gif_input(m, af, gifp);
+ return;
+}
diff --git a/sys/netinet/in_gif.h b/sys/netinet/in_gif.h
new file mode 100644
index 00000000000..a80e6fff158
--- /dev/null
+++ b/sys/netinet/in_gif.h
@@ -0,0 +1,42 @@
+/* $OpenBSD: in_gif.h,v 1.1 1999/12/08 06:50:19 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.
+ */
+
+#ifndef _NETINET_IN_GIF_H_
+#define _NETINET_IN_GIF_H_
+
+#define GIF_TTL 30
+
+extern int ip_gif_ttl;
+
+void in_gif_input __P((struct mbuf *, ...));
+int in_gif_output __P((struct ifnet *, int, struct mbuf *, struct rtentry *));
+
+#endif /*_NETINET_IN_GIF_H_*/
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 91b157519d6..71458addf74 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.c,v 1.34 1999/05/16 21:48:29 niklas Exp $ */
+/* $OpenBSD: in_pcb.c,v 1.35 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@@ -73,7 +73,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <dev/rndvar.h>
#ifdef INET6
-#include <netinet6/ipv6_var.h>
+#include <netinet6/ip6_var.h>
#endif /* INET6 */
#ifdef IPSEC
@@ -82,6 +82,12 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
extern int check_ipsec_policy __P((struct inpcb *, u_int32_t));
#endif
+#if 0 /*KAME IPSEC*/
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#include <netkey/key_debug.h>
+#endif /* IPSEC */
+
struct in_addr zeroin_addr;
extern int ipsec_auth_default_level;
@@ -165,6 +171,7 @@ in_pcballoc(so, v)
&inp->inp_laddr, inp->inp_lport), inp, inp_hash);
splx(s);
so->so_pcb = inp;
+ inp->inp_hops = -1;
#ifdef INET6
/*
@@ -355,10 +362,8 @@ in_pcbconnect(v, nam)
struct mbuf *nam;
{
register struct inpcb *inp = v;
- struct in_ifaddr *ia;
struct sockaddr_in *ifaddr = NULL;
register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
- struct sockaddr_in *sin2;
#ifdef INET6
if (sotopf(inp->inp_socket) == PF_INET6)
@@ -386,7 +391,10 @@ in_pcbconnect(v, nam)
sin->sin_addr = in_ifaddr.tqh_first->ia_broadaddr.sin_addr;
}
if (inp->inp_laddr.s_addr == INADDR_ANY) {
+#if 0
register struct route *ro;
+ struct sockaddr_in *sin2;
+ struct in_ifaddr *ia;
ia = (struct in_ifaddr *)0;
/*
@@ -446,10 +454,11 @@ in_pcbconnect(v, nam)
if (IN_MULTICAST(sin->sin_addr.s_addr) &&
#ifdef INET6
inp->inp_moptions != NULL &&
- !(inp->inp_flags & INP_IPV6_MCAST)) {
+ !(inp->inp_flags & INP_IPV6_MCAST))
#else
- inp->inp_moptions != NULL) {
+ inp->inp_moptions != NULL)
#endif
+ {
struct ip_moptions *imo;
struct ifnet *ifp;
@@ -465,6 +474,16 @@ in_pcbconnect(v, nam)
}
}
ifaddr = satosin(&ia->ia_addr);
+#else
+ int error;
+ ifaddr = in_selectsrc(sin, &inp->inp_route,
+ inp->inp_socket->so_options, inp->inp_moptions, &error);
+ if (ifaddr == NULL) {
+ if (error == 0)
+ error = EADDRNOTAVAIL;
+ return error;
+ }
+#endif
}
if (in_pcbhashlookup(inp->inp_table, sin->sin_addr, sin->sin_port,
inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
@@ -515,6 +534,14 @@ in_pcbdetach(v)
struct socket *so = inp->inp_socket;
int s;
+#if 0 /*KAME IPSEC*/
+ if (so->so_pcb) {
+ KEYDEBUG(KEYDEBUG_KEY_STAMP,
+ printf("DP call free SO=%p from in_pcbdetach\n", so));
+ key_freeso(so);
+ }
+ ipsec4_delete_pcbpolicy(inp);
+#endif /*IPSEC*/
so->so_pcb = 0;
sofree(so);
if (inp->inp_options)
@@ -522,10 +549,10 @@ in_pcbdetach(v)
if (inp->inp_route.ro_rt)
rtfree(inp->inp_route.ro_rt);
#ifdef INET6
- if (inp->inp_flags & INP_IPV6_MCAST)
- ipv6_freemoptions(inp->inp_moptions6);
+ if (inp->inp_flags & INP_IPV6)
+ ip6_freemoptions(inp->inp_moptions6);
else
-#endif /* INET6 */
+#endif
ip_freemoptions(inp->inp_moptions);
#ifdef IPSEC
/* XXX IPsec cleanup here */
@@ -778,8 +805,9 @@ in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags)
if (!IN6_IS_ADDR_UNSPECIFIED(faddr6))
wildcard++;
}
- } else {
+ } else
#endif /* INET6 */
+ {
if (inp->inp_faddr.s_addr != INADDR_ANY) {
if (faddr.s_addr == INADDR_ANY)
wildcard++;
@@ -799,9 +827,7 @@ in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags)
if (laddr.s_addr != INADDR_ANY)
wildcard++;
}
-#ifdef INET6
}
-#endif /* INET6 */
if ((!wildcard || (flags & INPLOOKUP_WILDCARD)) &&
wildcard < matchwild) {
match = inp;
@@ -812,6 +838,100 @@ in_pcblookup(table, faddrp, fport_arg, laddrp, lport_arg, flags)
return (match);
}
+struct sockaddr_in *
+in_selectsrc(sin, ro, soopts, mopts, errorp)
+ struct sockaddr_in *sin;
+ struct route *ro;
+ int soopts;
+ struct ip_moptions *mopts;
+ int *errorp;
+{
+ struct sockaddr_in *sin2;
+ struct in_ifaddr *ia;
+
+ ia = (struct in_ifaddr *)0;
+ /*
+ * If route is known or can be allocated now,
+ * our src addr is taken from the i/f, else punt.
+ */
+ if (ro->ro_rt &&
+ (satosin(&ro->ro_dst)->sin_addr.s_addr !=
+ sin->sin_addr.s_addr ||
+ soopts & SO_DONTROUTE)) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = (struct rtentry *)0;
+ }
+ if ((soopts & SO_DONTROUTE) == 0 && /*XXX*/
+ (ro->ro_rt == (struct rtentry *)0 ||
+ ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
+ /* No route yet, so try to acquire one */
+ ro->ro_dst.sa_family = AF_INET;
+ ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
+ satosin(&ro->ro_dst)->sin_addr = sin->sin_addr;
+ rtalloc(ro);
+
+ /*
+ * It is important to bzero out the rest of the
+ * struct sockaddr_in when mixing v6 & v4!
+ */
+ sin2 = (struct sockaddr_in *)&ro->ro_dst;
+ bzero(sin2->sin_zero, sizeof(sin2->sin_zero));
+ }
+ /*
+ * If we found a route, use the address
+ * corresponding to the outgoing interface
+ * unless it is the loopback (in case a route
+ * to our address on another net goes to loopback).
+ */
+ if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
+ ia = ifatoia(ro->ro_rt->rt_ifa);
+ if (ia == 0) {
+ u_int16_t fport = sin->sin_port;
+
+ sin->sin_port = 0;
+ ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
+ if (ia == 0)
+ ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
+ sin->sin_port = fport;
+ if (ia == 0)
+ ia = in_ifaddr.tqh_first;
+ if (ia == 0) {
+ *errorp = EADDRNOTAVAIL;
+ return NULL;
+ }
+ }
+ /*
+ * If the destination address is multicast and an outgoing
+ * interface has been set as a multicast option, use the
+ * address of that interface as our source address.
+ */
+ if (IN_MULTICAST(sin->sin_addr.s_addr) &&
+#if 0 /*def INET6*/
+ mopts != NULL &&
+ !(inp->inp_flags & INP_IPV6_MCAST))
+#else
+ mopts != NULL)
+#endif
+ {
+ struct ip_moptions *imo;
+ struct ifnet *ifp;
+
+ imo = mopts;
+ if (imo->imo_multicast_ifp != NULL) {
+ ifp = imo->imo_multicast_ifp;
+ for (ia = in_ifaddr.tqh_first; ia != 0;
+ ia = ia->ia_list.tqe_next)
+ if (ia->ia_ifp == ifp)
+ break;
+ if (ia == 0) {
+ *errorp = EADDRNOTAVAIL;
+ return NULL;
+ }
+ }
+ }
+ return satosin(&ia->ia_addr);
+}
+
void
in_pcbrehash(inp)
struct inpcb *inp;
@@ -919,3 +1039,5 @@ in6_pcbhashlookup(table, faddr, fport_arg, laddr, lport_arg)
return (inp);
}
#endif /* INET6 */
+
+
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index cb753c3ae82..819fc5a594f 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -1,7 +1,36 @@
-/* $OpenBSD: in_pcb.h,v 1.17 1999/03/27 21:04:19 provos Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.18 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 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) 1982, 1986, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -37,9 +66,12 @@
*/
#include <sys/queue.h>
-#include <netinet6/ipv6.h>
-#include <netinet6/ipv6_var.h>
-#include <netinet6/icmpv6.h>
+#if 0 /*KAME IPSEC*/
+#include <netinet6/ipsec.h>
+#endif
+#include <netinet6/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/icmp6.h>
#include <netinet/ip_ipsp.h>
union inpaddru {
@@ -73,21 +105,23 @@ struct inpcb {
caddr_t inp_ppcb; /* pointer to per-protocol pcb */
union { /* Route (notice increased size). */
struct route ru_route;
- struct route6 ru_route6;
+ struct route_in6 ru_route6;
} inp_ru;
#define inp_route inp_ru.ru_route
#define inp_route6 inp_ru.ru_route6
int inp_flags; /* generic IP/datagram flags */
union { /* Header prototype. */
struct ip hu_ip;
- struct ipv6 hu_ipv6;
+ struct ip6_hdr hu_ipv6;
} inp_hu;
#define inp_ip inp_hu.hu_ip
#define inp_ipv6 inp_hu.hu_ipv6
struct mbuf *inp_options; /* IP options */
+ struct ip6_pktopts *inp_outputopts6; /* IP6 options for outgoing packets */
+ int inp_hops;
union {
struct ip_moptions *mou_mo; /* IPv4 multicast options */
- struct ipv6_moptions *mou_mo6; /* IPv6 multicast options */
+ struct ip6_moptions *mou_mo6; /* IPv6 multicast options */
} inp_mou;
#define inp_moptions inp_mou.mou_mo
#define inp_moptions6 inp_mou.mou_mo6
@@ -104,7 +138,12 @@ struct inpcb {
struct tdb *inp_tdb; /* If tdb_dst matches our dst, use */
int inp_fflowinfo; /* Foreign flowlabel & priority */
int inp_csumoffset;
- struct icmpv6_filter inp_filter;
+ struct icmp6_filter *inp_icmp6filt;
+#if 0 /*KAME IPSEC*/
+ struct secpolicy *inp_sp; /* security policy. It may not be
+ * used according to policy selection.
+ */
+#endif
};
struct inpcbtable {
@@ -144,6 +183,24 @@ struct inpcbtable {
* the mapped form of v6 addresses) */
#define INP_IPV6_MCAST 0x800 /* Set if inp_moptions points to ipv6 ones */
+#if 1 /*KAME*/
+/* flags in in6p_flags */
+#define IN6P_RECVOPTS 0x01 /* receive incoming IP6 options */
+#define IN6P_RECVRETOPTS 0x02 /* receive IP6 options for reply */
+#define IN6P_RECVDSTADDR 0x04 /* receive IP6 dst address */
+#define IN6P_HIGHPORT 0x10 /* user wants "high" port binding */
+#define IN6P_LOWPORT 0x20 /* user wants "low" port binding */
+#define IN6P_ANONPORT 0x40 /* port chosen for user */
+#define IN6P_FAITH 0x80 /* accept FAITH'ed connections */
+#define IN6P_PKTINFO 0x010000
+#define IN6P_HOPLIMIT 0x020000
+#define IN6P_NEXTHOP 0x040000
+#define IN6P_HOPOPTS 0x080000
+#define IN6P_DSTOPTS 0x100000
+#define IN6P_RTHDR 0x200000
+#define IN6P_CONTROLOPTS (0x3f0000 | IN6P_RECVOPTS | IN6P_RECVRETOPTS | IN6P_RECVDSTADDR)
+#endif
+
#define INPLOOKUP_WILDCARD 1
#define INPLOOKUP_SETLOCAL 2
#define INPLOOKUP_IPV6 4
@@ -201,4 +258,17 @@ void in_rtchange __P((struct inpcb *, int));
void in_setpeeraddr __P((struct inpcb *, struct mbuf *));
void in_setsockaddr __P((struct inpcb *, struct mbuf *));
int in_baddynamic __P((u_int16_t, u_int16_t));
+extern struct sockaddr_in *in_selectsrc __P((struct sockaddr_in *,
+ struct route *, int, struct ip_moptions *, int *));
+
+/* INET6 stuff */
+int in6_pcbnotify __P((struct inpcbtable *, struct sockaddr *,
+ u_int, struct in6_addr *, u_int, int,
+ void (*)(struct inpcb *, int)));
+struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *,
+ struct ip6_pktopts *,
+ struct ip6_moptions *,
+ struct route_in6 *,
+ struct in6_addr *, int *));
+int in6_selecthlim __P((struct inpcb *, struct ifnet *));
#endif
diff --git a/sys/netinet/in_proto.c b/sys/netinet/in_proto.c
index ed387d1efb3..179361ddbd0 100644
--- a/sys/netinet/in_proto.c
+++ b/sys/netinet/in_proto.c
@@ -1,7 +1,36 @@
-/* $OpenBSD: in_proto.c,v 1.15 1999/10/28 03:21:51 angelos Exp $ */
+/* $OpenBSD: in_proto.c,v 1.16 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in_proto.c,v 1.14 1996/02/18 18:58:32 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) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -64,6 +93,14 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
#include <netinet/in_pcb.h>
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet/ip6.h>
+#endif
+
#include <netinet/igmp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
@@ -78,6 +115,19 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
* TCP/IP protocol family: IP, ICMP, UDP, TCP.
*/
+#if 0 /*KAME IPSEC*/
+#include <netinet6/ah.h>
+#ifdef IPSEC_ESP
+#include <netinet6/esp.h>
+#endif
+#include <netinet6/ipcomp.h>
+#endif /* IPSEC */
+
+#include "gif.h"
+#if NGIF > 0
+#include <netinet/in_gif.h>
+#endif
+
#ifdef NSIP
#include <netns/ns_var.h>
#include <netns/idp_var.h>
@@ -107,7 +157,7 @@ void iplinit __P((void));
#endif
#ifdef INET6
-#include <netinet6/ipv6_var.h>
+#include <netinet6/ip6_var.h>
#endif /* INET6 */
#ifdef IPSEC
@@ -146,6 +196,20 @@ struct protosw inetsw[] = {
rip_usrreq,
0, 0, 0, 0, icmp_sysctl
},
+#if NGIF > 0
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV4, PR_ATOMIC|PR_ADDR,
+ in_gif_input, 0, 0, 0,
+ 0,
+ 0, 0, 0, 0,
+},
+#ifdef INET6
+{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
+ in_gif_input, 0, 0, 0,
+ 0,
+ 0, 0, 0, 0,
+},
+#endif /* INET6 */
+#else /* NGIF */
#if defined(IPSEC) || defined(MROUTING)
{ SOCK_RAW, &inetdomain, IPPROTO_IPIP, PR_ATOMIC|PR_ADDR,
ip4_input, rip_output, 0, rip_ctloutput,
@@ -153,6 +217,7 @@ struct protosw inetsw[] = {
0, 0, 0, 0, ip4_sysctl
},
#endif /* MROUTING || IPSEC */
+#endif /*NGIF*/
{ SOCK_RAW, &inetdomain, IPPROTO_IGMP, PR_ATOMIC|PR_ADDR,
igmp_input, rip_output, 0, rip_ctloutput,
rip_usrreq,
@@ -204,10 +269,10 @@ struct protosw inetsw[] = {
0, 0, 0, 0, etherip_sysctl
},
#endif
-#ifdef INET6
+#if 0 /*NRL IPv6*/
/* IPv6 in IPv4 tunneled packets... */
{ SOCK_RAW, &inetdomain, IPPROTO_IPV6, PR_ATOMIC|PR_ADDR,
- ipv6_input, rip_output, ipv6_trans_ctlinput, rip_ctloutput,
+ ip6_input, rip_output, ipv6_trans_ctlinput, rip_ctloutput,
rip_usrreq,
0, 0, 0, 0
},
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h
index 7dafa91702d..c96bf076f15 100644
--- a/sys/netinet/in_var.h
+++ b/sys/netinet/in_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_var.h,v 1.2 1996/03/03 22:30:34 niklas Exp $ */
+/* $OpenBSD: in_var.h,v 1.3 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: in_var.h,v 1.16 1996/02/13 23:42:15 christos Exp $ */
/*
@@ -80,6 +80,7 @@ struct in_aliasreq {
TAILQ_HEAD(in_ifaddrhead, in_ifaddr);
extern struct in_ifaddrhead in_ifaddr;
extern struct ifqueue ipintrq; /* ip packet input queue */
+extern int inetctlerrmap[];
void in_socktrim __P((struct sockaddr_in *));
@@ -213,3 +214,7 @@ void in_delmulti __P((struct in_multi *));
void in_ifscrub __P((struct ifnet *, struct in_ifaddr *));
int in_control __P((struct socket *, u_long, caddr_t, struct ifnet *));
#endif
+
+
+/* INET6 stuff */
+#include <netinet6/in6_var.h>
diff --git a/sys/netinet/ip.h b/sys/netinet/ip.h
index 524938bb9c7..a3fd5ea3549 100644
--- a/sys/netinet/ip.h
+++ b/sys/netinet/ip.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip.h,v 1.5 1999/07/06 20:17:52 cmetz Exp $ */
+/* $OpenBSD: ip.h,v 1.6 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: ip.h,v 1.9 1995/05/15 01:22:44 cgd Exp $ */
/*
@@ -77,6 +77,11 @@ struct ip {
#define IPTOS_THROUGHPUT 0x08
#define IPTOS_RELIABILITY 0x04
/* IPTOS_LOWCOST 0x02 XXX */
+#if 1
+/* ECN bits proposed by Sally Floyd */
+#define IPTOS_CE 0x01 /* congestion experienced */
+#define IPTOS_ECT 0x02 /* ECN-capable transport */
+#endif
/*
* Definitions for IP precedence (also in ip_tos) (hopefully unused)
diff --git a/sys/netinet/ip6.h b/sys/netinet/ip6.h
new file mode 100644
index 00000000000..33b19eba749
--- /dev/null
+++ b/sys/netinet/ip6.h
@@ -0,0 +1,3 @@
+/* $OpenBSD: ip6.h,v 1.1 1999/12/08 06:50:19 itojun Exp $ */
+
+#include <netinet6/ip6.h>
diff --git a/sys/netinet/ip_auth.c b/sys/netinet/ip_auth.c
index 4d7e5cce18c..ea64528f34e 100644
--- a/sys/netinet/ip_auth.c
+++ b/sys/netinet/ip_auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_auth.c,v 1.6 1999/11/22 04:35:11 deraadt Exp $ */
+/* $OpenBSD: ip_auth.c,v 1.7 1999/12/08 06:50:19 itojun Exp $ */
/*
* Copyright (C) 1998 by Darren Reed & Guido van Rooij.
*
@@ -7,7 +7,7 @@
* to the original author and the contributors.
*/
#if !defined(lint)
-static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.6 1999/11/22 04:35:11 deraadt Exp $";
+static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.7 1999/12/08 06:50:19 itojun Exp $";
#endif
#include <sys/errno.h>
@@ -53,6 +53,11 @@ static const char rcsid[] = "@(#)$Id: ip_auth.c,v 1.6 1999/11/22 04:35:11 deraad
#include <net/af.h>
#endif
#include <net/route.h>
+#ifdef _KERNEL
+#ifndef INET
+#error ipfilter assumes options INET
+#endif
+#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
diff --git a/sys/netinet/ip_ecn.c b/sys/netinet/ip_ecn.c
new file mode 100644
index 00000000000..ad8770fcfd7
--- /dev/null
+++ b/sys/netinet/ip_ecn.c
@@ -0,0 +1,148 @@
+/* $OpenBSD: ip_ecn.c,v 1.1 1999/12/08 06:50:19 itojun Exp $ */
+
+/*
+ * Copyright (C) 1999 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.
+ *
+ * KAME Id: ip_ecn.c,v 1.2 1999/07/30 12:17:15 itojun Exp
+ */
+/*
+ * ECN consideration on tunnel ingress/egress operation.
+ * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
+ */
+
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
+#include "opt_inet.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/errno.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet/ip6.h>
+#endif
+
+#include <netinet/ip_ecn.h>
+
+/*
+ * modify outer ECN (TOS) field on ingress operation (tunnel encapsulation).
+ * call it after you've done the default initialization/copy for the outer.
+ */
+void
+ip_ecn_ingress(mode, outer, inner)
+ int mode;
+ u_int8_t *outer;
+ u_int8_t *inner;
+{
+ if (!outer || !inner)
+ panic("NULL pointer passed to ip_ecn_ingress");
+
+ switch (mode) {
+ case ECN_ALLOWED: /* ECN allowed */
+ *outer &= ~IPTOS_CE;
+ break;
+ case ECN_FORBIDDEN: /* ECN forbidden */
+ *outer &= ~(IPTOS_ECT | IPTOS_CE);
+ break;
+ case ECN_NOCARE: /* no consideration to ECN */
+ break;
+ }
+}
+
+/*
+ * modify inner ECN (TOS) field on egress operation (tunnel decapsulation).
+ * call it after you've done the default initialization/copy for the inner.
+ */
+void
+ip_ecn_egress(mode, outer, inner)
+ int mode;
+ u_int8_t *outer;
+ u_int8_t *inner;
+{
+ if (!outer || !inner)
+ panic("NULL pointer passed to ip_ecn_egress");
+
+ switch (mode) {
+ case ECN_ALLOWED:
+ if (*outer & IPTOS_CE)
+ *inner |= IPTOS_CE;
+ break;
+ case ECN_FORBIDDEN: /* ECN forbidden */
+ case ECN_NOCARE: /* no consideration to ECN */
+ break;
+ }
+}
+
+#ifdef INET6
+void
+ip6_ecn_ingress(mode, outer, inner)
+ int mode;
+ u_int32_t *outer;
+ u_int32_t *inner;
+{
+ u_int8_t outer8, inner8;
+
+ if (!outer || !inner)
+ panic("NULL pointer passed to ip6_ecn_ingress");
+
+ outer8 = (ntohl(*outer) >> 20) & 0xff;
+ inner8 = (ntohl(*inner) >> 20) & 0xff;
+ ip_ecn_ingress(mode, &outer8, &inner8);
+ *outer &= ~htonl(0xff << 20);
+ *outer |= htonl((u_int32_t)outer8 << 20);
+}
+
+void
+ip6_ecn_egress(mode, outer, inner)
+ int mode;
+ u_int32_t *outer;
+ u_int32_t *inner;
+{
+ u_int8_t outer8, inner8;
+
+ if (!outer || !inner)
+ panic("NULL pointer passed to ip6_ecn_egress");
+
+ outer8 = (ntohl(*outer) >> 20) & 0xff;
+ inner8 = (ntohl(*inner) >> 20) & 0xff;
+ ip_ecn_egress(mode, &outer8, &inner8);
+ *inner &= ~htonl(0xff << 20);
+ *inner |= htonl((u_int32_t)inner8 << 20);
+}
+#endif
diff --git a/sys/netinet/ip_ecn.h b/sys/netinet/ip_ecn.h
new file mode 100644
index 00000000000..e82daec9822
--- /dev/null
+++ b/sys/netinet/ip_ecn.h
@@ -0,0 +1,55 @@
+/* $OpenBSD: ip_ecn.h,v 1.1 1999/12/08 06:50:19 itojun Exp $ */
+
+/*
+ * Copyright (C) 1999 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.
+ *
+ * KAME Id: ip_ecn.h,v 1.2 1999/08/19 12:57:44 itojun Exp
+ */
+/*
+ * ECN consideration on tunnel ingress/egress operation.
+ * http://www.aciri.org/floyd/papers/draft-ipsec-ecn-00.txt
+ */
+
+#if (defined(__FreeBSD__) && __FreeBSD__ >= 3) || defined(__NetBSD__)
+#if defined(_KERNEL) && !defined(_LKM)
+#include "opt_inet.h"
+#endif
+#endif
+
+#define ECN_ALLOWED 1 /* ECN allowed */
+#define ECN_FORBIDDEN 0 /* ECN forbidden */
+#define ECN_NOCARE (-1) /* no consideration to ECN */
+
+#if defined(KERNEL) || defined(_KERNEL)
+extern void ip_ecn_ingress __P((int, u_int8_t *, u_int8_t *));
+extern void ip_ecn_egress __P((int, u_int8_t *, u_int8_t *));
+#ifdef INET6
+extern void ip6_ecn_ingress __P((int, u_int32_t *, u_int32_t *));
+extern void ip6_ecn_egress __P((int, u_int32_t *, u_int32_t *));
+#endif
+#endif
diff --git a/sys/netinet/ip_fil.c b/sys/netinet/ip_fil.c
index ad7890d73b9..b0d51cf2f43 100644
--- a/sys/netinet/ip_fil.c
+++ b/sys/netinet/ip_fil.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $ */
+/* $OpenBSD: ip_fil.c,v 1.25 1999/12/08 06:50:19 itojun Exp $ */
/*
* Copyright (C) 1993-1998 by Darren Reed.
*
@@ -8,7 +8,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraadt Exp $";
+static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.25 1999/12/08 06:50:19 itojun Exp $";
#endif
#ifndef SOLARIS
@@ -73,6 +73,11 @@ static const char rcsid[] = "@(#)$Id: ip_fil.c,v 1.24 1999/06/07 22:00:32 deraad
# endif
#endif
#include <net/route.h>
+#ifdef _KERNEL
+#ifndef INET
+#error ipfilter assumes options INET
+#endif
+#endif
#include <netinet/in.h>
#if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
#include <netinet/in_var.h>
diff --git a/sys/netinet/ip_frag.c b/sys/netinet/ip_frag.c
index d3b059cbb5c..d7f1a39f030 100644
--- a/sys/netinet/ip_frag.c
+++ b/sys/netinet/ip_frag.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $ */
+/* $OpenBSD: ip_frag.c,v 1.12 1999/12/08 06:50:19 itojun Exp $ */
/*
* Copyright (C) 1993-1998 by Darren Reed.
*
@@ -8,7 +8,7 @@
*/
#if !defined(lint)
static const char sccsid[] = "@(#)ip_frag.c 1.11 3/24/96 (C) 1993-1995 Darren Reed";
-static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraadt Exp $";
+static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.12 1999/12/08 06:50:19 itojun Exp $";
#endif
#include <sys/errno.h>
@@ -51,6 +51,11 @@ static const char rcsid[] = "@(#)$Id: ip_frag.c,v 1.11 1999/02/05 05:58:51 deraa
#include <net/af.h>
#endif
#include <net/route.h>
+#ifdef _KERNEL
+#ifndef INET
+#error ipfilter assumes options INET
+#endif
+#endif
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index bdd165d9fbe..5c7d16adb92 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_icmp.c,v 1.18 1999/09/26 23:59:15 deraadt Exp $ */
+/* $OpenBSD: ip_icmp.c,v 1.19 1999/12/08 06:50:19 itojun Exp $ */
/* $NetBSD: ip_icmp.c,v 1.19 1996/02/13 23:42:22 christos Exp $ */
/*
@@ -72,6 +72,12 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/ip_var.h>
#include <netinet/icmp_var.h>
+#if 0 /*KAME IPSEC*/
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#include <netkey/key_debug.h>
+#endif
+
#include <machine/stdarg.h>
/*
@@ -86,6 +92,12 @@ int icmpbmcastecho = 0;
int icmpprintfs = 0;
#endif
+#if 0
+static int ip_next_mtu __P((int, int));
+#else
+/*static*/ int ip_next_mtu __P((int, int));
+#endif
+
extern struct protosw inetsw[];
/*
@@ -211,6 +223,7 @@ icmp_input(m, va_alist)
va_dcl
#endif
{
+ int proto;
register struct icmp *icp;
register struct ip *ip = mtod(m, struct ip *);
int icmplen = ip->ip_len;
@@ -224,6 +237,7 @@ icmp_input(m, va_alist)
va_start(ap, m);
hlen = va_arg(ap, int);
+ proto = va_arg(ap, int);
va_end(ap);
/*
@@ -267,6 +281,13 @@ icmp_input(m, va_alist)
printf("icmp_input, type %d code %d\n", icp->icmp_type,
icp->icmp_code);
#endif
+#if 0 /*KAME IPSEC*/
+ /* drop it if it does not match the policy */
+ if (ipsec4_in_reject(m, NULL)) {
+ ipsecstat.in_polvio++;
+ goto freeit;
+ }
+#endif
if (icp->icmp_type > ICMP_MAXTYPE)
goto raw;
icmpstat.icps_inhist[icp->icmp_type]++;
@@ -284,7 +305,7 @@ icmp_input(m, va_alist)
break;
case ICMP_UNREACH_NEEDFRAG:
-#ifdef INET6
+#if 0 /*NRL INET6*/
if (icp->icmp_nextmtu) {
extern int ipv6_trans_mtu
__P((struct mbuf **, int, int));
@@ -385,6 +406,10 @@ icmp_input(m, va_alist)
printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
#endif
icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
+ /*
+ * XXX if the packet contains [IPv4 AH TCP], we can't make a
+ * notification to TCP layer.
+ */
ctlfunc = inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput;
if (ctlfunc)
(*ctlfunc)(code, sintosa(&icmpsrc), &icp->icmp_ip);
@@ -484,6 +509,9 @@ reflect:
(struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
sintosa(&icmpgw), (struct rtentry **)0);
pfctlinput(PRC_REDIRECT_HOST, sintosa(&icmpsrc));
+#if 0 /*KAME IPSEC*/
+ key_sa_routechange((struct sockaddr *)&icmpsrc);
+#endif
break;
/*
@@ -501,7 +529,7 @@ reflect:
}
raw:
- rip_input(m, 0);
+ rip_input(m, hlen, proto);
return;
freeit:
@@ -661,6 +689,9 @@ icmp_send(m, opts)
buf, inet_ntoa(ip->ip_src));
}
#endif
+#if 0 /*KAME IPSEC*/
+ m->m_pkthdr.rcvif = NULL;
+#endif /*IPSEC*/
(void) ip_output(m, opts, NULL, 0, NULL, NULL);
}
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 456572c9b34..a97d8cbd491 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.43 1999/11/29 16:22:29 ho Exp $ */
+/* $OpenBSD: ip_input.c,v 1.44 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -722,6 +722,8 @@ insert:
* Make header visible.
*/
ip->ip_len = next;
+ ip->ip_ttl = 0; /* xxx */
+ ip->ip_sum = 0;
ip->ip_src = fp->ipq_src;
ip->ip_dst = fp->ipq_dst;
LIST_REMOVE(fp, ipq_q);
@@ -1073,7 +1075,7 @@ save_rte(option, dst)
#ifdef DIAGNOSTIC
if (ipprintfs)
printf("save_rte: olen %d\n", olen);
-#endif
+#endif /* 0 */
if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
return;
bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, olen);
@@ -1254,6 +1256,9 @@ ip_forward(m, srcrt)
struct mbuf *mcopy;
n_long dest;
struct ifnet *destifp;
+#if 0 /*KAME IPSEC*/
+ struct ifnet dummyifp;
+#endif
dest = 0;
#ifdef DIAGNOSTIC
@@ -1330,6 +1335,9 @@ ip_forward(m, srcrt)
}
}
+#if 0 /*KAME IPSEC*/
+ m->m_pkthdr.rcvif = NULL;
+#endif /*IPSEC*/
error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
0, NULL, NULL);
@@ -1367,8 +1375,57 @@ ip_forward(m, srcrt)
case EMSGSIZE:
type = ICMP_UNREACH;
code = ICMP_UNREACH_NEEDFRAG;
+#if 1 /*KAME IPSEC*/
if (ipforward_rt.ro_rt)
destifp = ipforward_rt.ro_rt->rt_ifp;
+#else
+ /*
+ * If the packet is routed over IPsec tunnel, tell the
+ * originator the tunnel MTU.
+ * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
+ * XXX quickhack!!!
+ */
+ if (ipforward_rt.ro_rt) {
+ struct secpolicy *sp;
+ int ipsecerror;
+ int ipsechdr;
+ struct route *ro;
+
+ sp = ipsec4_getpolicybyaddr(mcopy,
+ IP_FORWARDING,
+ &ipsecerror);
+
+ if (sp == NULL)
+ destifp = ipforward_rt.ro_rt->rt_ifp;
+ else {
+ /* count IPsec header size */
+ ipsechdr = ipsec4_hdrsiz(mcopy, NULL);
+
+ /*
+ * find the correct route for outer IPv4
+ * header, compute tunnel MTU.
+ *
+ * XXX BUG ALERT
+ * The "dummyifp" code relies upon the fact
+ * that icmp_error() touches only ifp->if_mtu.
+ */
+ /*XXX*/
+ destifp = NULL;
+ if (sp->req != NULL
+ && sp->req->sa != NULL) {
+ ro = &sp->req->sa->saidx->sa_route;
+ if (ro->ro_rt && ro->ro_rt->rt_ifp) {
+ dummyifp.if_mtu =
+ ro->ro_rt->rt_ifp->if_mtu;
+ dummyifp.if_mtu -= ipsechdr;
+ destifp = &dummyifp;
+ }
+ }
+
+ key_freesp(sp);
+ }
+ }
+#endif /*IPSEC*/
ipstat.ips_cantfrag++;
break;
diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h
index 975e834e858..feb51fc1a00 100644
--- a/sys/netinet/ip_mroute.h
+++ b/sys/netinet/ip_mroute.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_mroute.h,v 1.4 1999/08/08 00:43:00 niklas Exp $ */
+/* $OpenBSD: ip_mroute.h,v 1.5 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: ip_mroute.h,v 1.10 1996/02/13 23:42:55 christos Exp $ */
/*
@@ -222,8 +222,12 @@ int legal_vif_num __P((int));
int ip_rsvp_vif_init __P((struct socket *, struct mbuf *));
int ip_rsvp_vif_done __P((struct socket *, struct mbuf *));
void ip_rsvp_force_done __P((struct socket *));
+#if 0
void rsvp_input __P((struct mbuf *, struct ifnet *));
#else
+void rsvp_input __P((struct mbuf *, int, int));
+#endif
+#else
int ip_mforward __P((struct mbuf *, struct ifnet *));
#endif
void ipip_input __P((struct mbuf *, ...));
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 186433bef12..ec98e1a0dba 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.54 1999/12/06 07:14:36 angelos Exp $ */
+/* $OpenBSD: ip_output.c,v 1.55 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -47,6 +47,9 @@
#include <sys/kernel.h>
#include <sys/proc.h>
+#include <vm/vm.h>
+#include <sys/proc.h>
+
#include <net/if.h>
#include <net/route.h>
@@ -84,6 +87,12 @@ extern u_int8_t get_sa_require __P((struct inpcb *));
#endif
+#if 0 /*KAME IPSEC*/
+#include <netinet6/ipsec.h>
+#include <netkey/key.h>
+#include <netkey/key_debug.h>
+#endif /*IPSEC*/
+
static struct mbuf *ip_insertoptions __P((struct mbuf *, struct mbuf *, int *));
static void ip_mloopback
__P((struct ifnet *, struct mbuf *, struct sockaddr_in *));
@@ -153,6 +162,10 @@ ip_output(m0, va_alist)
+#if 0 /*KAME IPSEC*/
+ m->m_pkthdr.rcvif = NULL;
+#endif /*IPSEC*/
+
#ifdef DIAGNOSTIC
if ((m->m_flags & M_PKTHDR) == 0)
panic("ip_output no HDR");
@@ -699,10 +712,21 @@ no_encap:
error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
goto done;
}
+
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
*/
+#if 0
+ /*
+ * If IPsec packet is too big for the interface, try fragment it.
+ * XXX This really is a quickhack. May be inappropriate.
+ * XXX fails if somebody is sending AH'ed packet, with:
+ * sizeof(packet without AH) < mtu < sizeof(packet with AH)
+ */
+ if (sab && ip->ip_p != IPPROTO_AH && (flags & IP_FORWARDING) == 0)
+ ip->ip_off &= ~IP_DF;
+#endif /*IPSEC*/
if (ip->ip_off & IP_DF) {
error = EMSGSIZE;
ipstat.ips_cantfrag++;
@@ -1066,6 +1090,30 @@ ip_ctloutput(op, so, level, optname, mp)
#endif
break;
+#if 0 /*KAME IPSEC*/
+ case IP_IPSEC_POLICY:
+ {
+ caddr_t req = NULL;
+ int len = 0;
+ int priv = 0;
+#ifdef __NetBSD__
+ if (p == 0 || suser(p->p_ucred, &p->p_acflag))
+ priv = 0;
+ else
+ priv = 1;
+#else
+ priv = (in6p->in6p_socket->so_state & SS_PRIV);
+#endif
+ if (m != 0) {
+ req = mtod(m, caddr_t);
+ len = m->m_len;
+ }
+ error = ipsec_set_policy(&inp->inp_sp,
+ optname, req, len, priv);
+ break;
+ }
+#endif /*IPSEC*/
+
default:
error = ENOPROTOOPT;
break;
@@ -1121,6 +1169,12 @@ ip_ctloutput(op, so, level, optname, mp)
*mtod(m, int *) = optval;
break;
+#if 0 /*KAME IPSEC*/
+ case IP_IPSEC_POLICY:
+ error = ipsec_get_policy(inp->inp_sp, mp);
+ break;
+#endif /*IPSEC*/
+
case IP_MULTICAST_IF:
case IP_MULTICAST_TTL:
case IP_MULTICAST_LOOP:
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index ccf7e9d2b92..fb12553a38a 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.11 1999/02/17 23:51:12 deraadt Exp $ */
+/* $OpenBSD: ip_var.h,v 1.12 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -145,6 +145,7 @@ struct ipstat {
u_long ips_badfrags; /* malformed fragments (bad length) */
u_long ips_rcvmemdrop; /* frags dropped for lack of memory */
u_long ips_toolong; /* ip length > max ip packet size */
+ u_long ips_nogif; /* no match gif found */
};
#ifdef _KERNEL
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c
index 9adb1879804..13e1c89eb52 100644
--- a/sys/netinet/tcp_debug.c
+++ b/sys/netinet/tcp_debug.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_debug.c,v 1.5 1999/07/02 20:39:07 cmetz Exp $ */
+/* $OpenBSD: tcp_debug.c,v 1.6 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */
/*
@@ -81,8 +81,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/tcp_debug.h>
#ifdef INET6
-#include <netinet6/ipv6.h>
-#include <netinet6/in6.h>
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/ip6.h>
#endif /* INET6 */
#ifdef TCPDEBUG
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index e2a6b6136d3..f080fb3c386 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.51 1999/11/15 05:50:59 hugh Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.52 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -82,18 +82,32 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#endif /* IPSEC */
#ifdef INET6
+#ifndef INET
+#include <netinet/in.h>
+#endif
#include <sys/domain.h>
#include <netinet6/in6_var.h>
-#include <netinet6/ipv6.h>
-#include <netinet6/ipv6_var.h>
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
#include <netinet6/tcpipv6.h>
+#include <netinet/icmp6.h>
+#include <netinet6/nd6.h>
+
+#ifndef CREATE_IPV6_MAPPED
+#define CREATE_IPV6_MAPPED(a6, a4) \
+do { \
+ bzero(&(a6), sizeof(a6)); \
+ (a6).s6_addr[10] = (a6).s6_addr[11] = 0xff; \
+ *(u_int32_t *)&(a6).s6_addr[12] = (a4); \
+} while (0)
+#endif
struct tcpiphdr tcp_saveti;
struct tcpipv6hdr tcp_saveti6;
/* for the packet header length in the mbuf */
#define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len)
-#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ipv6))
+#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr))
#define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip))
#endif /* INET6 */
@@ -111,6 +125,22 @@ extern u_long sb_max;
#define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0)
/*
+ * Neighbor Discovery, Neighbor Unreachability Detection Upper layer hint.
+ */
+#ifdef INET6
+#define ND6_HINT(tp) \
+do { \
+ if (tp && tp->t_inpcb && (tp->t_inpcb->inp_flags & INP_IPV6) \
+ && !(tp->t_inpcb->inp_flags & INP_IPV6_MAPPED) \
+ && tp->t_inpcb->inp_route6.ro_rt) { \
+ nd6_nud_hint(tp->t_inpcb->inp_route6.ro_rt, NULL); \
+ } \
+} while (0)
+#else
+#define ND6_HINT(tp)
+#endif
+
+/*
* Insert segment ti into reassembly queue of tcp with
* control block tp. Return TH_FIN if reassembly now includes
* a segment with FIN. The macro form does the common case inline
@@ -237,6 +267,7 @@ present:
nq = q->ipqe_q.le_next;
LIST_REMOVE(q, ipqe_q);
+ ND6_HINT(tp);
if (so->so_state & SS_CANTRCVMORE)
m_freem(q->ipqe_m);
else
@@ -295,6 +326,44 @@ done:
splx(s);
}
+#if defined(INET6) && !defined(TCP6)
+int
+tcp6_input(mp, offp, proto)
+ struct mbuf **mp;
+ int *offp, proto;
+{
+ struct mbuf *m = *mp;
+
+#if defined(NFAITH) && 0 < NFAITH
+ if (m->m_pkthdr.rcvif) {
+ if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
+ /* XXX send icmp6 host/port unreach? */
+ m_freem(m);
+ return IPPROTO_DONE;
+ }
+ }
+#endif
+
+ /*
+ * draft-itojun-ipv6-tcp-to-anycast
+ * better place to put this in?
+ */
+ if (m->m_flags & M_ANYCAST6) {
+ if (m->m_len >= sizeof(struct ip6_hdr)) {
+ struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
+ icmp6_error(m, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_ADDR,
+ (caddr_t)&ip6->ip6_dst - (caddr_t)ip6);
+ } else
+ m_freem(m);
+ return IPPROTO_DONE;
+ }
+
+ tcp_input(m, *offp, proto);
+ return IPPROTO_DONE;
+}
+#endif
+
/*
* TCP input routine, follows pages 65-76 of the
* protocol specification dated September, 1981 very closely.
@@ -316,6 +385,7 @@ tcp_input(m, va_alist)
register int tiflags;
struct socket *so = NULL;
int todrop, acked, ourfinisacked, needoutput = 0;
+ int hdroptlen = 0;
short ostate = 0;
struct in_addr laddr;
int dropsocket = 0;
@@ -332,7 +402,7 @@ tcp_input(m, va_alist)
#ifdef INET6
struct in6_addr laddr6;
unsigned short is_ipv6; /* Type of incoming datagram. */
- struct ipv6 *ipv6 = NULL;
+ struct ip6_hdr *ipv6 = NULL;
#endif /* INET6 */
va_start(ap, m);
@@ -369,8 +439,15 @@ tcp_input(m, va_alist)
#else /* INET6 */
if (!is_ipv6)
#endif /* INET6 */
- if (iphlen > sizeof (struct ip))
+ if (iphlen > sizeof (struct ip)) {
+#if 0 /*XXX*/
ip_stripoptions(m, (struct mbuf *)0);
+#else
+ printf("extension headers are not allowed\n");
+ m_freem(m);
+ return;
+#endif
+ }
if (m->m_len < iphlen + sizeof(struct tcphdr)) {
if ((m = m_pullup2(m, iphlen + sizeof(struct tcphdr))) == 0) {
tcpstat.tcps_rcvshort++;
@@ -391,22 +468,28 @@ tcp_input(m, va_alist)
if (is_ipv6) {
#ifdef DIAGNOSTIC
- if (iphlen < sizeof(struct ipv6)) {
+ if (iphlen < sizeof(struct ip6_hdr)) {
m_freem(m);
return;
}
#endif /* DIAGNOSTIC */
/* strip off any options */
- if (iphlen > sizeof(struct ipv6)) {
+ if (iphlen > sizeof(struct ip6_hdr)) {
+#if 0 /*XXX*/
ipv6_stripoptions(m, iphlen);
- iphlen = sizeof(struct ipv6);
+#else
+ printf("extension headers are not allowed\n");
+ m_freem(m);
+ return;
+#endif
+ iphlen = sizeof(struct ip6_hdr);
}
ti = NULL;
- ipv6 = mtod(m, struct ipv6 *);
+ ipv6 = mtod(m, struct ip6_hdr *);
- if (in6_cksum(m, IPPROTO_TCP, tlen, sizeof(struct ipv6))) {
+ if (in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr), tlen)) {
tcpstat.tcps_rcvbadsum++;
goto drop;
} /* endif in6_cksum */
@@ -453,7 +536,7 @@ tcp_input(m, va_alist)
}
#ifdef INET6
if (is_ipv6)
- ipv6 = mtod(m, struct ipv6 *);
+ ipv6 = mtod(m, struct ip6_hdr *);
else
#endif /* INET6 */
ti = mtod(m, struct tcpiphdr *);
@@ -495,8 +578,8 @@ tcp_input(m, va_alist)
findpcb:
#ifdef INET6
if (is_ipv6) {
- inp = in6_pcbhashlookup(&tcbtable, &ipv6->ipv6_src, th->th_sport,
- &ipv6->ipv6_dst, th->th_dport);
+ inp = in6_pcbhashlookup(&tcbtable, &ipv6->ip6_src, th->th_sport,
+ &ipv6->ip6_dst, th->th_dport);
} else
#endif /* INET6 */
inp = in_pcbhashlookup(&tcbtable, ti->ti_src, ti->ti_sport,
@@ -505,8 +588,8 @@ findpcb:
++tcpstat.tcps_pcbhashmiss;
#ifdef INET6
if (is_ipv6)
- inp = in_pcblookup(&tcbtable, &ipv6->ipv6_src,
- th->th_sport, &ipv6->ipv6_dst, th->th_dport,
+ inp = in_pcblookup(&tcbtable, &ipv6->ip6_src,
+ th->th_sport, &ipv6->ip6_dst, th->th_dport,
INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
else
#endif /* INET6 */
@@ -601,10 +684,10 @@ findpcb:
| INP_IPV6_MAPPED));
if ((inp->inp_flags & INP_IPV6) &&
!(inp->inp_flags & INP_IPV6_MAPPED)) {
- inp->inp_ipv6.ipv6_hoplimit =
- oldinpcb->inp_ipv6.ipv6_hoplimit;
- inp->inp_ipv6.ipv6_versfl =
- oldinpcb->inp_ipv6.ipv6_versfl;
+ inp->inp_ipv6.ip6_hlim =
+ oldinpcb->inp_ipv6.ip6_hlim;
+ inp->inp_ipv6.ip6_flow =
+ oldinpcb->inp_ipv6.ip6_flow;
}
}
#else /* INET6 */
@@ -613,11 +696,11 @@ findpcb:
inp->inp_lport = th->th_dport;
#ifdef INET6
if (is_ipv6) {
- inp->inp_laddr6 = ipv6->ipv6_dst;
+ inp->inp_laddr6 = ipv6->ip6_dst;
inp->inp_fflowinfo = htonl(0x0fffffff) &
- ipv6->ipv6_versfl;
+ ipv6->ip6_flow;
- /*inp->inp_options = ipv6_srcroute();*/ /* soon. */
+ /*inp->inp_options = ip6_srcroute();*/ /* soon. */
/* still need to tweak outbound options
processing to include this mbuf in
the right place and put the correct
@@ -656,7 +739,7 @@ findpcb:
#ifdef notyet
#ifdef INET6
if (is_ipv6)
- ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);
+ icmp6_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);
else
#endif /* INET6 */
icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);
@@ -744,6 +827,7 @@ findpcb:
acked = th->th_ack - tp->snd_una;
tcpstat.tcps_rcvackpack++;
tcpstat.tcps_rcvackbyte += acked;
+ ND6_HINT(tp);
sbdrop(&so->so_snd, acked);
tp->snd_una = th->th_ack;
#if defined(TCP_SACK) || defined(TCP_NEWRENO)
@@ -797,12 +881,12 @@ findpcb:
tp->rcv_nxt += tlen;
tcpstat.tcps_rcvpack++;
tcpstat.tcps_rcvbyte += tlen;
+ ND6_HINT(tp);
/*
* Drop TCP, IP headers and TCP options then add data
* to socket buffer.
*/
- m->m_data += iphlen + off;
- m->m_len -= iphlen + off;
+ m_adj(m, iphlen + off);
sbappend(&so->so_rcv, m);
sorwakeup(so);
if (th->th_flags & TH_PUSH)
@@ -814,10 +898,9 @@ findpcb:
}
/*
- * Drop TCP, IP headers and TCP options.
+ * Compute mbuf offset to TCP data segment.
*/
- m->m_data += iphlen + off;
- m->m_len -= iphlen + off;
+ hdroptlen = iphlen + off;
/*
* Calculate amount of space in receive window,
@@ -865,7 +948,7 @@ findpcb:
if (th->th_dport == th->th_sport) {
#ifdef INET6
if (is_ipv6) {
- if (IN6_ARE_ADDR_EQUAL(&ipv6->ipv6_src, &ipv6->ipv6_dst))
+ if (IN6_ARE_ADDR_EQUAL(&ipv6->ip6_src, &ipv6->ip6_dst))
goto drop;
} else {
#endif /* INET6 */
@@ -886,7 +969,7 @@ findpcb:
#ifdef INET6
if (is_ipv6) {
/* XXX What about IPv6 Anycasting ?? :-( rja */
- if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst))
+ if (IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst))
goto drop;
} else
#endif /* INET6 */
@@ -912,13 +995,13 @@ findpcb:
sin6 = mtod(am, struct sockaddr_in6 *);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_addr = ipv6->ipv6_src;
+ sin6->sin6_addr = ipv6->ip6_src;
sin6->sin6_port = th->th_sport;
sin6->sin6_flowinfo = htonl(0x0fffffff) &
- inp->inp_ipv6.ipv6_versfl;
+ inp->inp_ipv6.ip6_flow;
laddr6 = inp->inp_laddr6;
if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
- inp->inp_laddr6 = ipv6->ipv6_dst;
+ inp->inp_laddr6 = ipv6->ip6_dst;
/* This is a good optimization. */
if (in6_pcbconnect(inp, am)) {
inp->inp_laddr6 = laddr6;
@@ -982,6 +1065,7 @@ findpcb:
goto drop;
}
(void) m_free(am);
+ tp->pf = PF_INET;
#ifdef INET6
} /* if (inp->inp_flags & INP_IPV6) */
} /* if (is_ipv6) */
@@ -1210,7 +1294,7 @@ trimthenstep6:
tcpstat.tcps_rcvpartduppack++;
tcpstat.tcps_rcvpartdupbyte += todrop;
}
- m_adj(m, todrop);
+ hdroptlen += todrop; /* drop from head afterwards */
th->th_seq += todrop;
tlen -= todrop;
if (th->th_urp > todrop)
@@ -1295,7 +1379,11 @@ trimthenstep6:
* Close the tcb.
*/
if (tiflags & TH_RST) {
+#ifndef INET6
if (ti->ti_seq != tp->last_ack_sent)
+#else
+ if (th->th_seq != tp->last_ack_sent)
+#endif
goto drop;
switch (tp->t_state) {
@@ -1662,6 +1750,7 @@ trimthenstep6:
#endif
tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale);
}
+ ND6_HINT(tp);
if (acked > so->so_snd.sb_cc) {
tp->snd_wnd -= so->so_snd.sb_cc;
sbdrop(&so->so_snd, (int)so->so_snd.sb_cc);
@@ -1814,7 +1903,7 @@ step6:
&& (so->so_options & SO_OOBINLINE) == 0
#endif
)
- tcp_pulloutofband(so, th->th_urp, m); /* XXX? */
+ tcp_pulloutofband(so, th->th_urp, m, hdroptlen);
} else
/*
* If no out of band data is expected,
@@ -1845,9 +1934,12 @@ dodata: /* XXX */
tiflags = th->th_flags & TH_FIN;
tcpstat.tcps_rcvpack++;
tcpstat.tcps_rcvbyte += tlen;
+ ND6_HINT(tp);
+ m_adj(m, hdroptlen);
sbappend(&so->so_rcv, m);
sorwakeup(so);
} else {
+ m_adj(m, hdroptlen);
tiflags = tcp_reass(tp, th, m, &tlen);
tp->t_flags |= TF_ACKNOW;
}
@@ -1973,7 +2065,7 @@ dropwithreset:
if (is_ipv6) {
/* For following calls to tcp_respond */
ti = mtod(m, struct tcpiphdr *);
- if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst))
+ if (IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst))
goto drop;
} else {
#endif /* INET6 */
@@ -2515,12 +2607,13 @@ tcp_sack_partialack(tp, th)
* sequencing purposes.
*/
void
-tcp_pulloutofband(so, urgent, m)
+tcp_pulloutofband(so, urgent, m, off)
struct socket *so;
u_int urgent;
register struct mbuf *m;
+ int off;
{
- int cnt = urgent - 1;
+ int cnt = off + urgent - 1;
while (cnt >= 0) {
if (m->m_len > cnt) {
@@ -2665,7 +2758,7 @@ tcp_mss(tp, offer)
* Get a new IPv6 route if an IPv6 destination, otherwise, get
* and IPv4 route (including those pesky IPv4-mapped addresses).
*/
- bzero(ro,sizeof(struct route6));
+ bzero(ro,sizeof(struct route_in6));
if (sotopf(so) == AF_INET6) {
if (IN6_IS_ADDR_V4MAPPED(&inp->inp_faddr6)) {
/* Get an IPv4 route. */
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 23bc4f94b9f..8e73f4978f0 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.24 1999/12/02 16:31:17 deraadt Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.25 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -440,17 +440,13 @@ send:
* NOTE: we assume that the IP/TCP header plus TCP options
* always fit in a single mbuf, leaving room for a maximum
* link header, i.e.
- * max_linkhdr + sizeof(network header) + sizeof(struct tcphdr) +
- * optlen <= MHLEN
+ * max_linkhdr + sizeof(network header) + sizeof(struct tcphdr +
+ * optlen <= MHLEN
*/
optlen = 0;
-#if defined(INET) && defined(INET6)
switch (tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0: /* If tp->pf is 0, then assume IPv4 unless not avail */
+ case 0: /*default to PF_INET*/
#ifdef INET
case PF_INET:
hdrlen = sizeof(struct ip) + sizeof(struct tcphdr);
@@ -458,7 +454,7 @@ send:
#endif /* INET */
#ifdef INET6
case PF_INET6:
- hdrlen = sizeof(struct ipv6) + sizeof(struct tcphdr);
+ hdrlen = sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
break;
#endif /* INET6 */
default:
@@ -626,13 +622,20 @@ send:
m->m_data -= hdrlen;
#else
MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m != NULL) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ m = NULL;
+ }
+ }
if (m == NULL) {
error = ENOBUFS;
goto out;
}
m->m_data += max_linkhdr;
m->m_len = hdrlen;
- if (len <= MHLEN - hdrlen - max_linkhdr) {
+ if (len <= MCLBYTES - hdrlen - max_linkhdr) {
m_copydata(so->so_snd.sb_mb, off, (int) len,
mtod(m, caddr_t) + hdrlen);
m->m_len += len;
@@ -664,6 +667,13 @@ send:
tcpstat.tcps_sndwinup++;
MGETHDR(m, M_DONTWAIT, MT_HEADER);
+ if (m != NULL) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_freem(m);
+ m = NULL;
+ }
+ }
if (m == NULL) {
error = ENOBUFS;
goto out;
@@ -763,12 +773,8 @@ send:
tp->snd_up = tp->snd_una; /* drag it along */
/* Put TCP length in pseudo-header */
-#if defined(INET) && defined(INET6)
switch (tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
if (len + optlen)
@@ -790,12 +796,8 @@ send:
memset(&sa, 0, sizeof(union sockaddr_union));
-#if defined(INET) && defined(INET6)
- switch(tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ switch (tp->pf) {
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
sa.sa.sa_len = sizeof(struct sockaddr_in);
@@ -807,7 +809,7 @@ send:
case AF_INET6:
sa.sa.sa_len = sizeof(struct sockaddr_in6);
sa.sa.sa_family = AF_INET6;
- sa.sin6.sin6_addr = mtod(m, struct ipv6 *)->ipv6_dst;
+ sa.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_dst;
break;
#endif /* INET6 */
}
@@ -820,12 +822,8 @@ send:
MD5Init(&ctx);
-#if defined(INET) && defined(INET6)
- switch(tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ switch (tp->pf) {
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
{
@@ -875,12 +873,8 @@ send:
* Put TCP length in extended header, and then
* checksum extended header and data.
*/
-#if defined(INET) && defined(INET6)
switch (tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
th->th_sum = in_cksum(m, (int)(hdrlen + len));
@@ -888,8 +882,9 @@ send:
#endif /* INET */
#ifdef INET6
case AF_INET6:
- th->th_sum = in6_cksum(m, IPPROTO_TCP, hdrlen + len,
- sizeof(struct ipv6));
+ m->m_pkthdr.len = hdrlen + len;
+ th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr),
+ hdrlen - sizeof(struct ip6_hdr) + len);
break;
#endif /* INET6 */
}
@@ -981,12 +976,8 @@ send:
*/
m->m_pkthdr.len = hdrlen + len;
-#if defined(INET) && defined(INET6)
switch (tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
{
@@ -997,7 +988,6 @@ send:
ip->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl;
ip->ip_tos = tp->t_inpcb->inp_ip.ip_tos;
}
-
error = ip_output(m, tp->t_inpcb->inp_options,
&tp->t_inpcb->inp_route, so->so_options & SO_DONTROUTE,
0, tp->t_inpcb);
@@ -1006,16 +996,17 @@ send:
#ifdef INET6
case AF_INET6:
{
- struct ipv6 *ipv6;
+ struct ip6_hdr *ipv6;
- ipv6->ipv6_length = m->m_pkthdr.len -
- sizeof(struct ipv6);
- ipv6->ipv6_nexthdr = IPPROTO_TCP;
+ ipv6 = mtod(m, struct ip6_hdr *);
+ ipv6->ip6_plen = m->m_pkthdr.len -
+ sizeof(struct ip6_hdr);
+ ipv6->ip6_nxt = IPPROTO_TCP;
+ ipv6->ip6_hlim = in6_selecthlim(tp->t_inpcb, NULL);
}
-
- error = ipv6_output(m, &tp->t_inpcb->inp_route6,
- (so->so_options & SO_DONTROUTE), NULL, NULL,
- tp->t_inpcb->inp_socket);
+ error = ip6_output(m, tp->t_inpcb->inp_outputopts6,
+ &tp->t_inpcb->inp_route6,
+ (so->so_options & SO_DONTROUTE), NULL, NULL);
break;
#endif /* INET6 */
#ifdef TUBA
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index b8aa47c4e05..a63bcc2c3af 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.20 1999/10/29 02:10:02 angelos Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.21 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -76,7 +76,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <dev/rndvar.h>
#ifdef INET6
-#include <netinet6/ipv6_var.h>
+#include <netinet6/ip6_var.h>
#include <netinet6/tcpipv6.h>
#include <sys/domain.h>
#endif /* INET6 */
@@ -118,7 +118,7 @@ int tcp_do_sack = TCP_DO_SACK; /* RFC 2018 selective ACKs */
int tcbhashsize = TCBHASHSIZE;
#ifdef INET6
-extern int ipv6_defhoplmt;
+extern int ip6_defhlim;
#endif /* INET6 */
/*
@@ -136,12 +136,12 @@ tcp_init()
#ifdef INET6
/*
- * Since sizeof(struct ipv6) > sizeof(struct ip), we
+ * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
* do max length checks/computations only on the former.
*/
- if (max_protohdr < (sizeof(struct ipv6) + sizeof(struct tcphdr)))
- max_protohdr = (sizeof(struct ipv6) + sizeof(struct tcphdr));
- if ((max_linkhdr + sizeof(struct ipv6) + sizeof(struct tcphdr)) >
+ if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)))
+ max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
+ if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) >
MHLEN)
panic("tcp_init");
#endif /* INET6 */
@@ -171,12 +171,8 @@ tcp_template(tp)
if (m == NULL)
return (0);
-#if defined(INET) && defined(INET6)
switch (tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
+ case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
m->m_len = sizeof(struct ip);
@@ -184,7 +180,7 @@ tcp_template(tp)
#endif /* INET */
#ifdef INET6
case AF_INET6:
- m->m_len = sizeof(struct ipv6);
+ m->m_len = sizeof(struct ip6_hdr);
break;
#endif /* INET6 */
}
@@ -204,12 +200,7 @@ tcp_template(tp)
}
}
-#if defined(INET) && defined(INET6)
switch(tp->pf) {
-#else /* defined(INET) && defined(INET6) */
- switch(0) {
-#endif /* defined(INET) && defined(INET6) */
- case 0:
#ifdef INET
case AF_INET:
{
@@ -232,22 +223,22 @@ tcp_template(tp)
#ifdef INET6
case AF_INET6:
{
- struct ipv6 *ipv6;
+ struct ip6_hdr *ipv6;
- ipv6 = mtod(m, struct ipv6 *);
+ ipv6 = mtod(m, struct ip6_hdr *);
- ipv6->ipv6_src = inp->inp_laddr6;
- ipv6->ipv6_dst = inp->inp_faddr6;
- ipv6->ipv6_versfl = htonl(0x60000000) |
- (inp->inp_ipv6.ipv6_versfl &
- htonl(0x0fffffff));
+ ipv6->ip6_src = inp->inp_laddr6;
+ ipv6->ip6_dst = inp->inp_faddr6;
+ ipv6->ip6_flow = htonl(0x60000000) |
+ (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff));
+
- ipv6->ipv6_nexthdr = IPPROTO_TCP;
- ipv6->ipv6_length = htons(sizeof(struct tcphdr));
- ipv6->ipv6_hoplimit = inp->inp_ipv6.ipv6_hoplimit;
+ ipv6->ip6_nxt = IPPROTO_TCP;
+ ipv6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/
+ ipv6->ip6_hlim = in6_selecthlim(inp, NULL); /*XXX*/
th = (struct tcphdr *)(mtod(m, caddr_t) +
- sizeof(struct ipv6));
+ sizeof(struct ip6_hdr));
}
break;
#endif /* INET6 */
@@ -332,7 +323,7 @@ tcp_respond(tp, template, m, ack, seq, flags)
#ifdef INET6
if (is_ipv6)
bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
- sizeof(struct ipv6));
+ sizeof(struct ip6_hdr));
else
#endif /* INET6 */
bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
@@ -348,11 +339,11 @@ tcp_respond(tp, template, m, ack, seq, flags)
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
#ifdef INET6
if (is_ipv6) {
- m->m_len = sizeof(struct tcphdr) + sizeof(struct ipv6);
- xchg(((struct ipv6 *)ti)->ipv6_dst,\
- ((struct ipv6 *)ti)->ipv6_src,\
+ m->m_len = sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
+ xchg(((struct ip6_hdr *)ti)->ip6_dst,\
+ ((struct ip6_hdr *)ti)->ip6_src,\
struct in6_addr);
- th = (void *)ti + sizeof(struct ipv6);
+ th = (void *)ti + sizeof(struct ip6_hdr);
} else
#endif /* INET6 */
{
@@ -365,8 +356,8 @@ tcp_respond(tp, template, m, ack, seq, flags)
}
#ifdef INET6
if (is_ipv6) {
- tlen += sizeof(struct tcphdr) + sizeof(struct ipv6);
- th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ipv6));
+ tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
+ th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
} else
#endif /* INET6 */
{
@@ -391,15 +382,17 @@ tcp_respond(tp, template, m, ack, seq, flags)
#ifdef INET6
if (is_ipv6) {
- ((struct ipv6 *)ti)->ipv6_versfl = htonl(0x60000000);
- ((struct ipv6 *)ti)->ipv6_nexthdr = IPPROTO_TCP;
- ((struct ipv6 *)ti)->ipv6_hoplimit = MAXHOPLIMIT;
- ((struct ipv6 *)ti)->ipv6_length = tlen - sizeof(struct ipv6);
+ ((struct ip6_hdr *)ti)->ip6_flow = htonl(0x60000000);
+ ((struct ip6_hdr *)ti)->ip6_nxt = IPPROTO_TCP;
+ ((struct ip6_hdr *)ti)->ip6_hlim =
+ in6_selecthlim(tp ? tp->t_inpcb : NULL, NULL); /*XXX*/
+ ((struct ip6_hdr *)ti)->ip6_plen = tlen - sizeof(struct ip6_hdr);
th->th_sum = 0;
th->th_sum = in6_cksum(m, IPPROTO_TCP,
- ((struct ipv6 *)ti)->ipv6_length, sizeof(struct ipv6));
- HTONS(((struct ipv6 *)ti)->ipv6_length);
- ipv6_output(m, (struct route6 *)ro, 0, NULL, NULL, NULL);
+ sizeof(struct ip6_hdr), ((struct ip6_hdr *)ti)->ip6_plen);
+ HTONS(((struct ip6_hdr *)ti)->ip6_plen);
+ ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL,
+ (struct route_in6 *)ro, 0, NULL, NULL);
} else
#endif /* INET6 */
{
@@ -457,9 +450,13 @@ tcp_newtcpcb(inp)
*/
if ((inp->inp_flags & INP_IPV6) == 0)
tp->pf = PF_INET; /* If AF_INET socket, we can't do v6 from it. */
+#else
+ tp->pf = PF_INET;
+#endif
+#ifdef INET6
if (inp->inp_flags & INP_IPV6)
- inp->inp_ipv6.ipv6_hoplimit = ipv6_defhoplmt;
+ inp->inp_ipv6.ip6_hlim = ip6_defhlim;
else
#endif /* INET6 */
inp->inp_ip.ip_ttl = ip_defttl;
@@ -604,7 +601,7 @@ tcp_close(tp)
#ifdef INET6
if (tp->pf == PF_INET6)
i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)
- + sizeof(struct ipv6));
+ + sizeof(struct ip6_hdr));
else
#endif /* INET6 */
i *= (u_long)(tp->t_maxseg +
@@ -698,6 +695,17 @@ tcp_notify(inp, error)
sowwakeup(so);
}
+#if defined(INET6) && !defined(TCP6)
+void
+tcp6_ctlinput(cmd, sa, d)
+ int cmd;
+ struct sockaddr *sa;
+ void *d;
+{
+ (void)tcp_ctlinput(cmd, sa, NULL); /*XXX*/
+}
+#endif
+
void *
tcp_ctlinput(cmd, sa, v)
int cmd;
@@ -725,14 +733,19 @@ tcp_ctlinput(cmd, sa, v)
#ifdef INET6
if (sa->sa_family == AF_INET6) {
if (ip) {
- struct ipv6 *ipv6 = (struct ipv6 *)ip;
+ struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
th = (struct tcphdr *)(ipv6 + 1);
+#if 0 /*XXX*/
in6_pcbnotify(&tcbtable, sa, th->th_dport,
- &ipv6->ipv6_src, th->th_sport, cmd, notify);
- } else
+ &ipv6->ip6_src, th->th_sport, cmd, notify);
+#endif
+ } else {
+#if 0 /*XXX*/
in6_pcbnotify(&tcbtable, sa, 0,
(struct in6_addr *)&in6addr_any, 0, cmd, notify);
+#endif
+ }
} else
#endif /* INET6 */
{
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 4868d9728f4..d1995fad249 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_usrreq.c,v 1.36 1999/09/01 21:38:21 provos Exp $ */
+/* $OpenBSD: tcp_usrreq.c,v 1.37 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */
/*
@@ -100,6 +100,18 @@ extern struct baddynamicports baddynamicports;
int tcp_ident __P((void *, size_t *, void *, size_t));
+#if defined(INET6) && !defined(TCP6)
+int
+tcp6_usrreq(so, req, m, nam, control, p)
+ struct socket *so;
+ int req;
+ struct mbuf *m, *nam, *control;
+ struct proc *p;
+{
+ return tcp_usrreq(so, req, m, nam, control);
+}
+#endif
+
/*
* Process a TCP user request for TCP tb. If this is a send request
* then m is the mbuf chain of send data. If this is a timer expiration
@@ -196,7 +208,12 @@ tcp_usrreq(so, req, m, nam, control)
* Give the socket an address.
*/
case PRU_BIND:
- error = in_pcbbind(inp, nam);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ error = in6_pcbbind(inp, nam);
+ else
+#endif
+ error = in_pcbbind(inp, nam);
if (error)
break;
#ifdef INET6
@@ -219,8 +236,14 @@ tcp_usrreq(so, req, m, nam, control)
* Prepare to accept connections.
*/
case PRU_LISTEN:
- if (inp->inp_lport == 0)
- error = in_pcbbind(inp, NULL);
+ if (inp->inp_lport == 0) {
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ error = in6_pcbbind(inp, NULL);
+ else
+#endif
+ error = in_pcbbind(inp, NULL);
+ }
/* If the in_pcbbind() above is called, the tp->pf
should still be whatever it was before. */
if (error == 0)
@@ -251,8 +274,16 @@ tcp_usrreq(so, req, m, nam, control)
error = EINVAL;
break;
}
+
+ if (inp->inp_lport == 0) {
+ error = in6_pcbbind(inp, NULL);
+ if (error)
+ break;
+ }
+ error = in6_pcbconnect(inp, nam);
} else if (sin->sin_family == AF_INET)
#endif /* INET6 */
+ {
if ((sin->sin_addr.s_addr == INADDR_ANY) ||
IN_MULTICAST(sin->sin_addr.s_addr) ||
in_broadcast(sin->sin_addr, NULL)) {
@@ -260,18 +291,20 @@ tcp_usrreq(so, req, m, nam, control)
break;
}
- /* Trying to connect to some broadcast address */
- if (in_broadcast(sin->sin_addr, NULL)) {
- error = EINVAL;
- break;
- }
-
- if (inp->inp_lport == 0) {
- error = in_pcbbind(inp, NULL);
- if (error)
+ /* Trying to connect to some broadcast address */
+ if (in_broadcast(sin->sin_addr, NULL)) {
+ error = EINVAL;
break;
+ }
+
+ if (inp->inp_lport == 0) {
+ error = in_pcbbind(inp, NULL);
+ if (error)
+ break;
+ }
+ error = in_pcbconnect(inp, nam);
}
- error = in_pcbconnect(inp, nam);
+
if (error)
break;
@@ -358,7 +391,12 @@ tcp_usrreq(so, req, m, nam, control)
* of the peer, storing through addr.
*/
case PRU_ACCEPT:
- in_setpeeraddr(inp, nam);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ in6_setpeeraddr(inp, nam);
+ else
+#endif
+ in_setpeeraddr(inp, nam);
break;
/*
@@ -446,11 +484,21 @@ tcp_usrreq(so, req, m, nam, control)
break;
case PRU_SOCKADDR:
- in_setsockaddr(inp, nam);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ in6_setsockaddr(inp, nam);
+ else
+#endif
+ in_setsockaddr(inp, nam);
break;
case PRU_PEERADDR:
- in_setpeeraddr(inp, nam);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ in6_setpeeraddr(inp, nam);
+ else
+#endif
+ in_setpeeraddr(inp, nam);
break;
/*
@@ -504,7 +552,7 @@ tcp_ctloutput(op, so, level, optname, mp)
* AF_INET6 sockets which get SET/GET options for IPv4.
*/
if (tp->pf == PF_INET6)
- error = ipv6_ctloutput(op, so, level, optname, mp);
+ error = ip6_ctloutput(op, so, level, optname, mp);
else
#endif /* INET6 */
error = ip_ctloutput(op, so, level, optname, mp);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 25039955a3c..c22b3b8c61d 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.24 1999/08/06 18:17:38 deraadt Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.25 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -324,6 +324,9 @@ int tcp_attach __P((struct socket *));
void tcp_canceltimers __P((struct tcpcb *));
struct tcpcb *
tcp_close __P((struct tcpcb *));
+#if defined(INET6) && !defined(TCP6)
+void tcp6_ctlinput __P((int, struct sockaddr *, void *));
+#endif
void *tcp_ctlinput __P((int, struct sockaddr *, void *));
int tcp_ctloutput __P((int, struct socket *, int, int, struct mbuf **));
struct tcpcb *
@@ -335,13 +338,16 @@ void tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *,
void tcp_drain __P((void));
void tcp_fasttimo __P((void));
void tcp_init __P((void));
+#if defined(INET6) && !defined(TCP6)
+int tcp6_input __P((struct mbuf **, int *, int));
+#endif
void tcp_input __P((struct mbuf *, ...));
int tcp_mss __P((struct tcpcb *, u_int));
struct tcpcb *
tcp_newtcpcb __P((struct inpcb *));
void tcp_notify __P((struct inpcb *, int));
int tcp_output __P((struct tcpcb *));
-void tcp_pulloutofband __P((struct socket *, u_int, struct mbuf *));
+void tcp_pulloutofband __P((struct socket *, u_int, struct mbuf *, int));
void tcp_quench __P((struct inpcb *, int));
int tcp_reass __P((struct tcpcb *, struct tcphdr *, struct mbuf *, int *));
void tcp_respond __P((struct tcpcb *, caddr_t, struct mbuf *, tcp_seq,
@@ -356,6 +362,10 @@ void tcp_trace __P((int, int, struct tcpcb *, caddr_t, int, int));
struct tcpcb *
tcp_usrclosed __P((struct tcpcb *));
int tcp_sysctl __P((int *, u_int, void *, size_t *, void *, size_t));
+#if defined(INET6) && !defined(TCP6)
+int tcp6_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *));
+#endif
int tcp_usrreq __P((struct socket *,
int, struct mbuf *, struct mbuf *, struct mbuf *));
void tcp_xmit_timer __P((struct tcpcb *, int));
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 644cecc7f98..ff65e76a6e2 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.28 1999/11/04 11:24:24 ho Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.29 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -84,13 +84,25 @@ extern int check_ipsec_policy __P((struct inpcb *, u_int32_t));
#include <machine/stdarg.h>
#ifdef INET6
-#include <netinet6/in6.h>
-#include <netinet6/ipv6.h>
+#ifndef INET
+#include <netinet/in.h>
+#endif
+#include <netinet6/ip6.h>
#include <netinet6/in6_var.h>
-#include <netinet6/ipv6_var.h>
-#include <netinet6/ipv6_icmp.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/icmp6.h>
+#include <netinet6/ip6protosw.h>
+
+#ifndef CREATE_IPV6_MAPPED
+#define CREATE_IPV6_MAPPED(a6, a4) \
+do { \
+ bzero(&(a6), sizeof(a6)); \
+ (a6).s6_addr[10] = (a6).s6_addr[11] = 0xff; \
+ *(u_int32_t *)&(a6).s6_addr[12] = (a4); \
+} while (0)
+#endif
-extern int ipv6_defhoplmt;
+extern int ip6_defhlim;
#endif /* INET6 */
@@ -120,6 +132,29 @@ udp_init()
in_pcbinit(&udbtable, udbhashsize);
}
+#if defined(INET6) && !defined(TCP6)
+int
+udp6_input(mp, offp, proto)
+ struct mbuf **mp;
+ int *offp, proto;
+{
+ struct mbuf *m = *mp;
+
+#if defined(NFAITH) && 0 < NFAITH
+ if (m->m_pkthdr.rcvif) {
+ if (m->m_pkthdr.rcvif->if_type == IFT_FAITH) {
+ /* XXX send icmp6 host/port unreach? */
+ m_freem(m);
+ return IPPROTO_DONE;
+ }
+ }
+#endif
+
+ udp_input(m, *offp, proto);
+ return IPPROTO_DONE;
+}
+#endif
+
void
#if __STDC__
udp_input(struct mbuf *m, ...)
@@ -146,7 +181,7 @@ udp_input(m, va_alist)
#endif /* INET6 */
} srcsa, dstsa;
#ifdef INET6
- struct ipv6 *ipv6;
+ struct ip6_hdr *ipv6;
struct sockaddr_in6 src_v4mapped;
#endif /* INET6 */
#ifdef IPSEC
@@ -182,7 +217,7 @@ udp_input(m, va_alist)
#ifdef INET6
case 6:
ip = NULL;
- ipv6 = mtod(m, struct ipv6 *);
+ ipv6 = mtod(m, struct ip6_hdr *);
srcsa.sa.sa_family = AF_INET6;
break;
#endif /* INET6 */
@@ -220,7 +255,7 @@ udp_input(m, va_alist)
}
#ifdef INET6
if (ipv6)
- ipv6 = mtod(m, struct ipv6 *);
+ ipv6 = mtod(m, struct ip6_hdr *);
else
#endif /* INET6 */
ip = mtod(m, struct ip *);
@@ -258,7 +293,7 @@ udp_input(m, va_alist)
/*
* In IPv6, the UDP checksum is ALWAYS used.
*/
- if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, len, iphlen))) {
+ if ((uh->uh_sum = in6_cksum(m, IPPROTO_UDP, iphlen, len))) {
udpstat.udps_badsum++;
goto bad;
}
@@ -304,20 +339,30 @@ udp_input(m, va_alist)
srcsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
srcsa.sin6.sin6_family = AF_INET6;
srcsa.sin6.sin6_port = uh->uh_sport;
- srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ipv6_versfl;
- srcsa.sin6.sin6_addr = ipv6->ipv6_src;
+ srcsa.sin6.sin6_flowinfo = htonl(0x0fffffff) & ipv6->ip6_flow;
+ srcsa.sin6.sin6_addr = ipv6->ip6_src;
+ if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr))
+ srcsa.sin6.sin6_addr.s6_addr16[1] = 0;
+ if (m->m_pkthdr.rcvif) {
+ if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6.sin6_addr)) {
+ srcsa.sin6.sin6_scope_id =
+ m->m_pkthdr.rcvif->if_index;
+ } else
+ srcsa.sin6.sin6_scope_id = 0;
+ } else
+ srcsa.sin6.sin6_scope_id = 0;
bzero(&dstsa, sizeof(struct sockaddr_in6));
dstsa.sin6.sin6_len = sizeof(struct sockaddr_in6);
dstsa.sin6.sin6_family = AF_INET6;
dstsa.sin6.sin6_port = uh->uh_dport;
- dstsa.sin6.sin6_addr = ipv6->ipv6_dst;
+ dstsa.sin6.sin6_addr = ipv6->ip6_dst;
break;
#endif /* INET6 */
}
#ifdef INET6
- if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst)) ||
+ if ((ipv6 && IN6_IS_ADDR_MULTICAST(&ipv6->ip6_dst)) ||
(ip && IN_MULTICAST(ip->ip_dst.s_addr)) ||
(ip && in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif))) {
#else /* INET6 */
@@ -361,7 +406,7 @@ udp_input(m, va_alist)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
if (!IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6,
- &ipv6->ipv6_dst))
+ &ipv6->ip6_dst))
continue;
} else
#endif /* INET6 */
@@ -374,7 +419,7 @@ udp_input(m, va_alist)
if (ipv6) {
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
if (!IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6,
- &ipv6->ipv6_src) ||
+ &ipv6->ip6_src) ||
inp->inp_fport != uh->uh_sport)
continue;
} else
@@ -391,8 +436,12 @@ udp_input(m, va_alist)
if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
#ifdef INET6
+#if 0 /*XXX*/
if (ipv6)
opts = ipv6_headertocontrol(m, iphlen, ((struct inpcb *)last->so_pcb)->inp_flags);
+#else
+ opts = NULL;
+#endif
#endif /* INET6 */
if (sbappendaddr(&last->so_rcv,
#ifdef INET6
@@ -436,9 +485,13 @@ udp_input(m, va_alist)
}
#ifdef INET6
+#if 0 /*XXX*/
if (ipv6)
opts = ipv6_headertocontrol(m, iphlen,
((struct inpcb *)last->so_pcb)->inp_flags);
+#else
+ opts = NULL;
+#endif
#endif /* INET6 */
if (sbappendaddr(&last->so_rcv,
#ifdef INET6
@@ -462,8 +515,8 @@ udp_input(m, va_alist)
*/
#ifdef INET6
if (ipv6)
- inp = in6_pcbhashlookup(&udbtable, &ipv6->ipv6_src, uh->uh_sport,
- &ipv6->ipv6_dst, uh->uh_dport);
+ inp = in6_pcbhashlookup(&udbtable, &ipv6->ip6_src, uh->uh_sport,
+ &ipv6->ip6_dst, uh->uh_dport);
else
#endif /* INET6 */
inp = in_pcbhashlookup(&udbtable, ip->ip_src, uh->uh_sport,
@@ -473,8 +526,8 @@ udp_input(m, va_alist)
#ifdef INET6
if (ipv6) {
inp = in_pcblookup(&udbtable,
- (struct in_addr *)&(ipv6->ipv6_src),
- uh->uh_sport, (struct in_addr *)&(ipv6->ipv6_dst),
+ (struct in_addr *)&(ipv6->ip6_src),
+ uh->uh_sport, (struct in_addr *)&(ipv6->ip6_dst),
uh->uh_dport, INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
} else
#endif /* INET6 */
@@ -486,16 +539,21 @@ udp_input(m, va_alist)
udpstat.udps_noportbcast++;
goto bad;
}
- *ip = save_ip;
- HTONS(ip->ip_id);
- uh->uh_sum = savesum;
#ifdef INET6
- if (ipv6)
- ipv6_icmp_error(m, ICMPV6_UNREACH,
- ICMPV6_UNREACH_PORT,0);
- else
+ if (ipv6) {
+ icmp6_error(m, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_NOPORT,0);
+ } else
#endif /* INET6 */
- icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
+ {
+ *ip = save_ip;
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_id);
+ HTONS(ip->ip_off);
+ uh->uh_sum = savesum;
+ icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT,
+ 0, 0);
+ }
return;
}
}
@@ -528,9 +586,13 @@ udp_input(m, va_alist)
#ifdef INET6
if (ipv6) {
+#if 0 /*XXX*/
if (inp->inp_flags & INP_IPV6)
opts = ipv6_headertocontrol(m, iphlen,
inp->inp_flags);
+#else
+ opts = NULL;
+#endif
} else
if (ip)
#endif /* INET6 */
@@ -622,6 +684,42 @@ udp_notify(inp, errno)
sowwakeup(inp->inp_socket);
}
+#if defined(INET6) && !defined(TCP6)
+void
+udp6_ctlinput(cmd, sa, d)
+ int cmd;
+ struct sockaddr *sa;
+ void *d;
+{
+ struct sockaddr_in6 sa6;
+ struct ip6_hdr *ip6;
+ struct mbuf *m;
+ int off;
+
+ if (sa == NULL)
+ return;
+ if (sa->sa_family != AF_INET6)
+ return;
+
+ /* decode parameter from icmp6. */
+ if (d != NULL) {
+ struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
+ ip6 = ip6cp->ip6c_ip6;
+ m = ip6cp->ip6c_m;
+ off = ip6cp->ip6c_off;
+ } else
+ return;
+
+ /* translate addresses into internal form */
+ sa6 = *(struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr) && m && m->m_pkthdr.rcvif)
+ sa6.sin6_addr.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index);
+ sa = (struct sockaddr *)&sa6;
+
+ (void)udp_ctlinput(cmd, sa, (void *)ip6);
+}
+#endif
+
void *
udp_ctlinput(cmd, sa, v)
int cmd;
@@ -643,17 +741,24 @@ udp_ctlinput(cmd, sa, v)
ip = 0;
else if (errno == 0)
return NULL;
+ if (sa == NULL)
+ return NULL;
#ifdef INET6
if (sa->sa_family == AF_INET6) {
if (ip) {
- struct ipv6 *ipv6 = (struct ipv6 *)ip;
+ struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
- uh = (struct udphdr *)((caddr_t)ipv6 + sizeof(struct ipv6));
+ uh = (struct udphdr *)((caddr_t)ipv6 + sizeof(struct ip6_hdr));
+#if 0 /*XXX*/
in6_pcbnotify(&udbtable, sa, uh->uh_dport,
- &(ipv6->ipv6_src), uh->uh_sport, cmd, udp_notify);
- } else
+ &(ipv6->ip6_src), uh->uh_sport, cmd, udp_notify);
+#endif
+ } else {
+#if 0 /*XXX*/
in6_pcbnotify(&udbtable, sa, 0,
(struct in6_addr *)&in6addr_any, 0, cmd, udp_notify);
+#endif
+ }
} else
#endif /* INET6 */
if (ip) {
@@ -685,6 +790,7 @@ udp_output(m, va_alist)
register struct in6_addr laddr6;
int v6packet = 0;
struct ifnet *forceif = NULL;
+ struct sockaddr_in6 *sin6 = NULL;
#endif /* INET6 */
int pcbflags = 0;
@@ -700,6 +806,10 @@ udp_output(m, va_alist)
#endif /* INET6 */
if (addr) {
+#ifdef INET6
+ sin6 = mtod(addr, struct sockaddr_in6 *);
+#endif
+
/*
* Save current PCB flags because they may change during
* temporary connection, particularly the INP_IPV6_UNDEC
@@ -710,16 +820,17 @@ udp_output(m, va_alist)
#ifdef INET6
if (inp->inp_flags & INP_IPV6)
laddr6 = inp->inp_laddr6;
- else
+ else
#endif /* INET6 */
laddr = inp->inp_laddr;
#ifdef INET6
if (((inp->inp_flags & INP_IPV6) &&
!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6)) ||
- (inp->inp_faddr.s_addr != INADDR_ANY)) {
+ (inp->inp_faddr.s_addr != INADDR_ANY))
#else /* INET6 */
- if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ if (inp->inp_faddr.s_addr != INADDR_ANY)
#endif /* INET6 */
+ {
error = EISCONN;
goto release;
}
@@ -760,7 +871,7 @@ udp_output(m, va_alist)
m_freem(control);
M_PREPEND(m, v6packet ? (sizeof(struct udphdr) +
- sizeof(struct ipv6)) : sizeof(struct udpiphdr), M_DONTWAIT);
+ sizeof(struct ip6_hdr)) : sizeof(struct udpiphdr), M_DONTWAIT);
#else /* INET6 */
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
#endif /* INET6 */
@@ -784,41 +895,101 @@ udp_output(m, va_alist)
*/
#ifdef INET6
if (v6packet) {
- struct ipv6 *ipv6 = mtod(m, struct ipv6 *);
+ struct ip6_hdr *ipv6 = mtod(m, struct ip6_hdr *);
struct udphdr *uh = (struct udphdr *)(mtod(m, caddr_t) +
- sizeof(struct ipv6));
- int payload = sizeof(struct ipv6);
-
- ipv6->ipv6_versfl = htonl(0x60000000) |
- (inp->inp_ipv6.ipv6_versfl & htonl(0x0fffffff));
+ sizeof(struct ip6_hdr));
+ int payload = sizeof(struct ip6_hdr);
+ struct in6_addr *faddr;
+ struct in6_addr *laddr;
+ struct ifnet *oifp = NULL;
+
+ ipv6->ip6_flow = htonl(0x60000000) |
+ (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff));
- ipv6->ipv6_hoplimit = inp->inp_ipv6.ipv6_hoplimit;
- ipv6->ipv6_nexthdr = IPPROTO_UDP;
- ipv6->ipv6_src = inp->inp_laddr6;
- ipv6->ipv6_dst = inp->inp_faddr6;
- ipv6->ipv6_length = (u_short)len + sizeof(struct udphdr);
+ ipv6->ip6_nxt = IPPROTO_UDP;
+ ipv6->ip6_dst = inp->inp_faddr6;
+ /*
+ * If the scope of the destination is link-local,
+ * embed the interface
+ * index in the address.
+ *
+ * XXX advanced-api value overrides sin6_scope_id
+ */
+ faddr = &ipv6->ip6_dst;
+ if (IN6_IS_ADDR_LINKLOCAL(faddr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(faddr)) {
+ struct ip6_pktopts *optp = inp->inp_outputopts6;
+ struct in6_pktinfo *pi = NULL;
+ struct ip6_moptions *mopt = NULL;
+
+ /*
+ * XXX Boundary check is assumed to be already done in
+ * ip6_setpktoptions().
+ */
+ if (optp && (pi = optp->ip6po_pktinfo) &&
+ pi->ipi6_ifindex) {
+ faddr->s6_addr16[1] = htons(pi->ipi6_ifindex);
+ oifp = ifindex2ifnet[pi->ipi6_ifindex];
+ }
+ else if (IN6_IS_ADDR_MULTICAST(faddr) &&
+ (mopt = inp->inp_moptions6) &&
+ mopt->im6o_multicast_ifp) {
+ oifp = mopt->im6o_multicast_ifp;
+ faddr->s6_addr16[1] = oifp->if_index;
+ } else if (sin6 && sin6->sin6_scope_id) {
+ /* boundary check */
+ if (sin6->sin6_scope_id < 0
+ || if_index < sin6->sin6_scope_id) {
+ error = ENXIO; /* XXX EINVAL? */
+ goto release;
+ }
+ /* XXX */
+ faddr->s6_addr16[1] =
+ htons(sin6->sin6_scope_id & 0xffff);
+ }
+ }
+ ipv6->ip6_hlim = in6_selecthlim(inp, oifp);
+ if (sin6) { /*XXX*/
+ laddr = in6_selectsrc(sin6, inp->inp_outputopts6,
+ inp->inp_moptions6,
+ &inp->inp_route6,
+ &inp->inp_laddr6, &error);
+ if (laddr == NULL) {
+ if (error == 0)
+ error = EADDRNOTAVAIL;
+ goto release;
+ }
+ } else
+ laddr = &inp->inp_laddr6;
+
+ ipv6->ip6_src = *laddr;
+
+ ipv6->ip6_plen = (u_short)len + sizeof(struct udphdr);
uh->uh_sport = inp->inp_lport;
uh->uh_dport = inp->inp_fport;
- uh->uh_ulen = htons(ipv6->ipv6_length);
+ uh->uh_ulen = htons(ipv6->ip6_plen);
uh->uh_sum = 0;
- if (control)
+ if (control) {
+#if 0 /*XXX*/
if ((error = ipv6_controltoheader(&m, control,
&forceif, &payload)))
goto release;
+#endif
+ }
/*
* Always calculate udp checksum for IPv6 datagrams
*/
- if (!(uh->uh_sum = in6_cksum(m, IPPROTO_UDP, len +
- sizeof(struct udphdr), payload)))
+ if (!(uh->uh_sum = in6_cksum(m, IPPROTO_UDP,
+ payload, len + sizeof(struct udphdr))))
uh->uh_sum = 0xffff;
- error = ipv6_output(m, &inp->inp_route6,
+ error = ip6_output(m, NULL, &inp->inp_route6,
inp->inp_socket->so_options & SO_DONTROUTE,
(inp->inp_flags & INP_IPV6_MCAST)?inp->inp_moptions6:NULL,
- forceif, inp->inp_socket);
+ &forceif);
} else
#endif /* INET6 */
{
@@ -901,6 +1072,19 @@ u_int udp_sendspace = 9216; /* really max datagram size */
u_int udp_recvspace = 40 * (1024 + sizeof(struct sockaddr_in));
/* 40 1K datagrams */
+#if defined(INET6) && !defined(TCP6)
+/*ARGSUSED*/
+int
+udp6_usrreq(so, req, m, addr, control, p)
+ struct socket *so;
+ int req;
+ struct mbuf *m, *addr, *control;
+ struct proc *p;
+{
+ return udp_usrreq(so, req, m, addr, control);
+}
+#endif
+
/*ARGSUSED*/
int
udp_usrreq(so, req, m, addr, control)
@@ -947,8 +1131,8 @@ udp_usrreq(so, req, m, addr, control)
break;
#ifdef INET6
if (((struct inpcb *)so->so_pcb)->inp_flags & INP_IPV6)
- ((struct inpcb *) so->so_pcb)->inp_ipv6.ipv6_hoplimit =
- ipv6_defhoplmt;
+ ((struct inpcb *) so->so_pcb)->inp_ipv6.ip6_hlim =
+ ip6_defhlim;
else
#endif /* INET6 */
((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl;
@@ -960,7 +1144,12 @@ udp_usrreq(so, req, m, addr, control)
case PRU_BIND:
s = splsoftnet();
- error = in_pcbbind(inp, addr);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ error = in6_pcbbind(inp, addr);
+ else
+#endif
+ error = in_pcbbind(inp, addr);
splx(s);
break;
@@ -975,16 +1164,21 @@ udp_usrreq(so, req, m, addr, control)
error = EISCONN;
break;
}
+ s = splsoftnet();
+ error = in6_pcbconnect(inp, addr);
+ splx(s);
} else
#endif /* INET6 */
+ {
if (inp->inp_faddr.s_addr != INADDR_ANY) {
error = EISCONN;
break;
}
+ s = splsoftnet();
+ error = in_pcbconnect(inp, addr);
+ splx(s);
+ }
- s = splsoftnet();
- error = in_pcbconnect(inp, addr);
- splx(s);
if (error == 0)
soisconnected(so);
break;
@@ -1042,11 +1236,21 @@ udp_usrreq(so, req, m, addr, control)
break;
case PRU_SOCKADDR:
- in_setsockaddr(inp, addr);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ in6_setsockaddr(inp, addr);
+ else
+#endif /* INET6 */
+ in_setsockaddr(inp, addr);
break;
case PRU_PEERADDR:
- in_setpeeraddr(inp, addr);
+#ifdef INET6
+ if (inp->inp_flags & INP_IPV6)
+ in6_setpeeraddr(inp, addr);
+ else
+#endif /* INET6 */
+ in_setpeeraddr(inp, addr);
break;
case PRU_SENSE:
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index afc23036d32..e1e409e3985 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_var.h,v 1.8 1999/03/27 21:04:21 provos Exp $ */
+/* $OpenBSD: udp_var.h,v 1.9 1999/12/08 06:50:20 itojun Exp $ */
/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */
/*
@@ -90,6 +90,12 @@ struct udpstat {
struct inpcbtable udbtable;
struct udpstat udpstat;
+#if defined(INET6) && !defined(TCP6)
+void udp6_ctlinput __P((int, struct sockaddr *, void *));
+int udp6_input __P((struct mbuf **, int *, int));
+int udp6_usrreq __P((struct socket *,
+ int, struct mbuf *, struct mbuf *, struct mbuf *, struct proc *));
+#endif
void *udp_ctlinput __P((int, struct sockaddr *, void *));
void udp_init __P((void));
void udp_input __P((struct mbuf *, ...));