summaryrefslogtreecommitdiff
path: root/sys/netinet6
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-12-11 08:04:57 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2000-12-11 08:04:57 +0000
commit86dbed8aba95dc31c186c8df3c4aac3e79a22401 (patch)
treef9c4ca816c24b6fe1cdf21c342fec085cce1addd /sys/netinet6
parent25bf51b6b2a7cf8c1a0bda4228883d0f5d273e5e (diff)
nuke #ifdef TCP6 (no longer supported).
validate ICMPv6 too big messages (pmtud) based on pcb. we accept certain amount of non-validated ones, as IPv6 mandates ICMPv6 (so even for traffic from unconnected pcb, we need pmtud). sync with kame
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/icmp6.c111
-rw-r--r--sys/netinet6/in6_proto.c86
-rw-r--r--sys/netinet6/ip6protosw.h21
3 files changed, 111 insertions, 107 deletions
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 52c8fb72b94..086f2b8da03 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: icmp6.c,v 1.25 2000/11/11 00:45:39 itojun Exp $ */
+/* $OpenBSD: icmp6.c,v 1.26 2000/12/11 08:04:56 itojun Exp $ */
/* $KAME: icmp6.c,v 1.156 2000/10/19 19:21:07 itojun Exp $ */
/*
@@ -112,12 +112,26 @@ extern int icmp6errppslim;
static int icmp6errpps_count = 0;
static struct timeval icmp6errppslim_last;
extern int icmp6_nodeinfo;
+
+/*
+ * List of callbacks to notify when Path MTU changes are made.
+ */
+struct icmp6_mtudisc_callback {
+ LIST_ENTRY(icmp6_mtudisc_callback) mc_list;
+ void (*mc_func) __P((struct in6_addr *));
+};
+
+LIST_HEAD(, icmp6_mtudisc_callback) icmp6_mtudisc_callbacks =
+ LIST_HEAD_INITIALIZER(&icmp6_mtudisc_callbacks);
+
static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
extern int pmtu_expire;
+/* XXX do these values make any sense? */
+int icmp6_mtudisc_hiwat = 1280;
+int icmp6_mtudisc_lowat = 256;
+
static void icmp6_errcount __P((struct icmp6errstat *, int, int));
-static void icmp6_mtudisc_update __P((struct in6_addr *, struct icmp6_hdr *,
- struct mbuf *));
static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int));
static const char *icmp6_redirect_diag __P((struct in6_addr *,
struct in6_addr *, struct in6_addr *));
@@ -201,6 +215,29 @@ icmp6_errcount(stat, type, code)
}
/*
+ * Register a Path MTU Discovery callback.
+ */
+void
+icmp6_mtudisc_callback_register(func)
+ void (*func) __P((struct in6_addr *));
+{
+ struct icmp6_mtudisc_callback *mc;
+
+ for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;
+ mc = LIST_NEXT(mc, mc_list)) {
+ if (mc->mc_func == func)
+ return;
+ }
+
+ mc = malloc(sizeof(*mc), M_PCB, M_NOWAIT);
+ if (mc == NULL)
+ panic("icmp6_mtudisc_callback_register");
+
+ mc->mc_func = func;
+ LIST_INSERT_HEAD(&icmp6_mtudisc_callbacks, mc, mc_list);
+}
+
+/*
* Generate an error packet of type error in response to bad IP6 packet.
*/
void
@@ -410,7 +447,7 @@ icmp6_input(mp, offp, proto)
#ifdef IPSEC
/* drop it if it does not match the default policy */
if (ipsec6_in_reject(m, NULL)) {
- ipsecstat.in_polvio++;
+ ipsec6stat.in_polvio++;
goto freeit;
}
#endif
@@ -822,7 +859,6 @@ icmp6_input(mp, offp, proto)
sizeof(struct ip6_hdr);
struct ip6ctlparam ip6cp;
struct in6_addr *finaldst = NULL;
- int icmp6type = icmp6->icmp6_type;
struct ip6_frag *fh;
struct ip6_rthdr *rth;
struct ip6_rthdr0 *rth0;
@@ -962,19 +998,19 @@ icmp6_input(mp, offp, proto)
return IPPROTO_DONE;
}
#endif
- if (icmp6type == ICMP6_PACKET_TOO_BIG) {
- if (finaldst == NULL)
- finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
- icmp6_mtudisc_update(finaldst, icmp6, m);
- }
+ if (finaldst == NULL)
+ finaldst = &((struct ip6_hdr *)(icmp6 + 1))->ip6_dst;
+ ip6cp.ip6c_m = m;
+ ip6cp.ip6c_icmp6 = icmp6;
+ ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
+ ip6cp.ip6c_off = eoff;
+ ip6cp.ip6c_finaldst = finaldst;
ctlfunc = (void (*) __P((int, struct sockaddr *, void *)))
(inet6sw[ip6_protox[nxt]].pr_ctlinput);
if (ctlfunc) {
- ip6cp.ip6c_m = m;
- ip6cp.ip6c_ip6 = (struct ip6_hdr *)(icmp6 + 1);
- ip6cp.ip6c_off = eoff;
- (*ctlfunc)(code, (struct sockaddr *)&icmp6src, &ip6cp);
+ (void) (*ctlfunc)(code, (struct sockaddr *)&icmp6src,
+ &ip6cp);
}
}
break;
@@ -996,16 +1032,38 @@ icmp6_input(mp, offp, proto)
return IPPROTO_DONE;
}
-static void
-icmp6_mtudisc_update(dst, icmp6, m)
- struct in6_addr *dst;
- struct icmp6_hdr *icmp6;/* we can assume the validity of the pointer */
- struct mbuf *m; /* currently unused but added for scoped addrs */
+void
+icmp6_mtudisc_update(ip6cp, validated)
+ struct ip6ctlparam *ip6cp;
+ int validated;
{
+ unsigned long rtcount;
+ struct icmp6_mtudisc_callback *mc;
+ struct in6_addr *dst = ip6cp->ip6c_finaldst;
+ struct icmp6_hdr *icmp6 = ip6cp->ip6c_icmp6;
+ struct mbuf *m = ip6cp->ip6c_m; /* will be necessary for scope issue */
u_int mtu = ntohl(icmp6->icmp6_mtu);
struct rtentry *rt = NULL;
struct sockaddr_in6 sin6;
+ /*
+ * allow non-validated cases if memory is plenty, to make traffic
+ * from non-connected pcb happy.
+ */
+ rtcount = rt_timer_count(icmp6_mtudisc_timeout_q);
+ if (validated) {
+ if (rtcount > icmp6_mtudisc_hiwat)
+ return;
+ else if (rtcount > icmp6_mtudisc_lowat) {
+ /*
+ * XXX nuke a victim, install the new one.
+ */
+ }
+ } else {
+ if (rtcount > icmp6_mtudisc_lowat)
+ return;
+ }
+
bzero(&sin6, sizeof(sin6));
sin6.sin6_family = PF_INET6;
sin6.sin6_len = sizeof(struct sockaddr_in6);
@@ -1030,11 +1088,20 @@ icmp6_mtudisc_update(dst, icmp6, m)
rt->rt_rmx.rmx_locks |= RTV_MTU;
} else if (mtu < rt->rt_ifp->if_mtu &&
rt->rt_rmx.rmx_mtu > mtu) {
+ icmp6stat.icp6s_pmtuchg++;
rt->rt_rmx.rmx_mtu = mtu;
}
}
if (rt)
RTFREE(rt);
+
+ /*
+ * Notify protocols that the MTU for this destination
+ * has changed.
+ */
+ for (mc = LIST_FIRST(&icmp6_mtudisc_callbacks); mc != NULL;
+ mc = LIST_NEXT(mc, mc_list))
+ (*mc->mc_func)(&sin6.sin6_addr);
}
/*
@@ -2573,6 +2640,12 @@ icmp6_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
case ICMPV6CTL_ND6_MAXNUDHINT:
return sysctl_int(oldp, oldlenp, newp, newlen,
&nd6_maxnudhint);
+ case ICMPV6CTL_MTUDISC_HIWAT:
+ return sysctl_int(oldp, oldlenp, newp, newlen,
+ &icmp6_mtudisc_hiwat);
+ case ICMPV6CTL_MTUDISC_LOWAT:
+ return sysctl_int(oldp, oldlenp, newp, newlen,
+ &icmp6_mtudisc_lowat);
default:
return ENOPROTOOPT;
}
diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c
index e373faa046c..d46491b9cf6 100644
--- a/sys/netinet6/in6_proto.c
+++ b/sys/netinet6/in6_proto.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in6_proto.c,v 1.25 2000/10/10 15:53:09 itojun Exp $ */
+/* $OpenBSD: in6_proto.c,v 1.26 2000/12/11 08:04:56 itojun Exp $ */
/* $KAME: in6_proto.c,v 1.66 2000/10/10 15:35:47 itojun Exp $ */
/*
@@ -130,14 +130,6 @@ struct ip6protosw inet6sw[] = {
0, 0, 0,
udp_sysctl,
},
-#ifdef TCP6
-{ SOCK_STREAM, &inet6domain, IPPROTO_TCP, PR_CONNREQUIRED | PR_WANTRCVD,
- tcp6_input, 0, tcp6_ctlinput, tcp6_ctloutput,
- tcp6_usrreq,
- tcp6_init, tcp6_fasttimo, tcp6_slowtimo, tcp6_drain,
- tcp6_sysctl,
-},
-#else
{ SOCK_STREAM, &inet6domain, IPPROTO_TCP, PR_CONNREQUIRED | PR_WANTRCVD,
tcp6_input, 0, tcp6_ctlinput, tcp_ctloutput,
tcp6_usrreq,
@@ -148,7 +140,6 @@ struct ip6protosw inet6sw[] = {
#endif
tcp_sysctl,
},
-#endif /*TCP6*/
{ SOCK_RAW, &inet6domain, IPPROTO_RAW, PR_ATOMIC | PR_ADDR,
rip6_input, rip6_output, rip6_ctlinput, rip6_ctloutput,
rip6_usrreq,
@@ -304,81 +295,6 @@ struct timeval icmp6errratelim = { 0, 0 }; /* no ratelimit */
int icmp6errppslim = 100; /* 100pps */
int icmp6_nodeinfo = 1; /* enable/disable NI response */
-#ifdef TCP6
-/* TCP on IP6 parameters */
-int tcp6_sendspace = 1024 * 8;
-int tcp6_recvspace = 1024 * 8;
-int tcp6_mssdflt = TCP6_MSS;
-int tcp6_rttdflt = TCP6TV_SRTTDFLT / PR_SLOWHZ;
-int tcp6_do_rfc1323 = 1;
-int tcp6_conntimeo = TCP6TV_KEEP_INIT; /* initial connection timeout */
-int tcp6_43maxseg = 0;
-int tcp6_pmtu = 0;
-
-/*
- * Parameters for keepalive option.
- * Connections for which SO_KEEPALIVE is set will be probed
- * after being idle for a time of tcp6_keepidle (in units of PR_SLOWHZ).
- * Starting at that time, the connection is probed at intervals
- * of tcp6_keepintvl (same units) until a response is received
- * or until tcp6_keepcnt probes have been made, at which time
- * the connection is dropped. Note that a tcp6_keepidle value
- * under 2 hours is nonconformant with RFC-1122, Internet Host Requirements.
- */
-int tcp6_keepidle = TCP6TV_KEEP_IDLE; /* time before probing idle */
-int tcp6_keepintvl = TCP6TV_KEEPINTVL; /* interval betwn idle probes */
-int tcp6_keepcnt = TCP6TV_KEEPCNT; /* max idle probes */
-int tcp6_maxpersistidle = TCP6TV_KEEP_IDLE; /* max idle time in persist */
-
-#ifndef INET_SERVER
-#define TCP6_LISTEN_HASH_SIZE 17
-#define TCP6_CONN_HASH_SIZE 97
-#define TCP6_SYN_HASH_SIZE 293
-#define TCP6_SYN_BUCKET_SIZE 35
-#else
-#define TCP6_LISTEN_HASH_SIZE 97
-#define TCP6_CONN_HASH_SIZE 9973
-#define TCP6_SYN_HASH_SIZE 997
-#define TCP6_SYN_BUCKET_SIZE 35
-#endif
-int tcp6_listen_hash_size = TCP6_LISTEN_HASH_SIZE;
-int tcp6_conn_hash_size = TCP6_CONN_HASH_SIZE;
-struct tcp6_hash_list tcp6_listen_hash[TCP6_LISTEN_HASH_SIZE],
- tcp6_conn_hash[TCP6_CONN_HASH_SIZE];
-
-int tcp6_syn_cache_size = TCP6_SYN_HASH_SIZE;
-int tcp6_syn_cache_limit = TCP6_SYN_HASH_SIZE*TCP6_SYN_BUCKET_SIZE;
-int tcp6_syn_bucket_limit = 3*TCP6_SYN_BUCKET_SIZE;
-struct syn_cache_head6 tcp6_syn_cache[TCP6_SYN_HASH_SIZE];
-struct syn_cache_head6 *tcp6_syn_cache_first;
-int tcp6_syn_cache_interval = 8; /* runs timer every 4 seconds */
-int tcp6_syn_cache_timeo = TCP6TV_KEEP_INIT;
-
-/*
- * Parameters for computing a desirable data segment size
- * given an upper bound (either interface MTU, or peer's MSS option)_.
- * As applications tend to use a buffer size that is a multiple
- * of kilobytes, try for something that divides evenly. However,
- * do not round down too much.
- *
- * Round segment size down to a multiple of TCP6_ROUNDSIZE if this
- * does not result in lowering by more than (size/TCP6_ROUNDFRAC).
- * For example, round 536 to 512. Older versions of the system
- * effectively used MCLBYTES (1K or 2K) as TCP6_ROUNDSIZE, with
- * a value of 1 for TCP6_ROUNDFRAC (eliminating its effect).
- * We round to a multiple of 256 for SLIP.
- */
-#ifndef TCP6_ROUNDSIZE
-#define TCP6_ROUNDSIZE 256 /* round to multiple of 256 */
-#endif
-#ifndef TCP6_ROUNDFRAC
-#define TCP6_ROUNDFRAC 10 /* round down at most N/10, or 10% */
-#endif
-
-int tcp6_roundsize = TCP6_ROUNDSIZE;
-int tcp6_roundfrac = TCP6_ROUNDFRAC;
-#endif /*TCP6*/
-
/* UDP on IP6 parameters */
int udp6_sendspace = 9216; /* really max datagram size */
int udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
diff --git a/sys/netinet6/ip6protosw.h b/sys/netinet6/ip6protosw.h
index 7797403e251..dcbae2d90ae 100644
--- a/sys/netinet6/ip6protosw.h
+++ b/sys/netinet6/ip6protosw.h
@@ -1,9 +1,10 @@
-/* $OpenBSD: ip6protosw.h,v 1.2 1999/12/10 10:04:28 angelos Exp $ */
+/* $OpenBSD: ip6protosw.h,v 1.3 2000/12/11 08:04:56 itojun Exp $ */
+/* $KAME: ip6protosw.h,v 1.14 2000/10/18 18:15:53 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:
@@ -15,7 +16,7 @@
* 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
@@ -81,15 +82,29 @@ struct socket;
struct domain;
struct proc;
struct ip6_hdr;
+struct icmp6_hdr;
+struct in6_addr;
/*
* argument type for the last arg of pr_ctlinput().
* should be consulted only with AF_INET6 family.
+ *
+ * IPv6 ICMP IPv6 [exthdrs] finalhdr paylaod
+ * ^ ^ ^ ^
+ * | | ip6c_ip6 ip6c_off
+ * | ip6c_icmp6
+ * ip6c_m
+ *
+ * ip6c_finaldst usually points to ip6c_ip6->ip6_dst. if the original
+ * (internal) packet carries a routing header, it may point the final
+ * dstination address in the routing header.
*/
struct ip6ctlparam {
struct mbuf *ip6c_m; /* start of mbuf chain */
+ struct icmp6_hdr *ip6c_icmp6; /* icmp6 header of target packet */
struct ip6_hdr *ip6c_ip6; /* ip6 header of target packet */
int ip6c_off; /* offset of the target proto header */
+ struct in6_addr *ip6c_finaldst; /* final destination address */
};
struct ip6protosw {