diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-12-11 08:04:57 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-12-11 08:04:57 +0000 |
commit | 86dbed8aba95dc31c186c8df3c4aac3e79a22401 (patch) | |
tree | f9c4ca816c24b6fe1cdf21c342fec085cce1addd /sys/netinet6 | |
parent | 25bf51b6b2a7cf8c1a0bda4228883d0f5d273e5e (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.c | 111 | ||||
-rw-r--r-- | sys/netinet6/in6_proto.c | 86 | ||||
-rw-r--r-- | sys/netinet6/ip6protosw.h | 21 |
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 { |