diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/icmp6.h | 15 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 107 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 5 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 6 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 141 |
6 files changed, 210 insertions, 68 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h index 95e38d4801c..749cc8a7567 100644 --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -1,5 +1,5 @@ -/* $OpenBSD: icmp6.h,v 1.11 2000/10/10 15:53:07 itojun Exp $ */ -/* $KAME: icmp6.h,v 1.23 2000/10/10 15:35:45 itojun Exp $ */ +/* $OpenBSD: icmp6.h,v 1.12 2000/12/11 08:04:55 itojun Exp $ */ +/* $KAME: icmp6.h,v 1.24 2000/10/18 19:24:24 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -536,6 +536,7 @@ struct icmp6stat { #define icp6s_oparamprob_option icp6s_outerrhist.icp6errs_paramprob_option #define icp6s_oredirect icp6s_outerrhist.icp6errs_redirect #define icp6s_ounknown icp6s_outerrhist.icp6errs_unknown + u_quad_t icp6s_pmtuchg; /* path MTU changes */ }; /* @@ -556,7 +557,9 @@ struct icmp6stat { #define ICMPV6CTL_NODEINFO 13 #define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */ #define ICMPV6CTL_ND6_MAXNUDHINT 15 -#define ICMPV6CTL_MAXID 16 +#define ICMPV6CTL_MTUDISC_HIWAT 16 +#define ICMPV6CTL_MTUDISC_LOWAT 17 +#define ICMPV6CTL_MAXID 18 #define ICMPV6CTL_NAMES { \ { 0, 0 }, \ @@ -575,6 +578,8 @@ struct icmp6stat { { "nodeinfo", CTLTYPE_INT }, \ { "errppslimit", CTLTYPE_INT }, \ { "nd6_maxnudhint", CTLTYPE_INT }, \ + { "mtudisc_hiwat", CTLTYPE_INT }, \ + { "mtudisc_lowat", CTLTYPE_INT }, \ } #define RTF_PROBEMTU RTF_PROTO1 @@ -596,6 +601,10 @@ void icmp6_redirect_input __P((struct mbuf *, int)); void icmp6_redirect_output __P((struct mbuf *, struct rtentry *)); int icmp6_sysctl __P((int *, u_int, void *, size_t *, void *, size_t)); +struct ip6ctlparam; +void icmp6_mtudisc_update __P((struct ip6ctlparam *, int)); +void icmp6_mtudisc_callback_register __P((void (*)(struct in6_addr *))); + /* XXX: is this the right place for these macros? */ #define icmp6_ifstat_inc(ifp, tag) \ do { \ diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index f45766afc53..8fc588e947f 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.79 2000/10/14 01:04:10 itojun Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.80 2000/12/11 08:04:55 itojun Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -319,7 +319,7 @@ done: splx(s); } -#if defined(INET6) && !defined(TCP6) +#ifdef INET6 int tcp6_input(mp, offp, proto) struct mbuf **mp; diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 39043f8e7cc..e57ac20961c 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.35 2000/10/13 17:58:36 itojun Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.36 2000/12/11 08:04:55 itojun Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -152,6 +152,8 @@ tcp_init() if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) > MHLEN) panic("tcp_init"); + + icmp6_mtudisc_callback_register(tcp6_mtudisc_callback); #endif /* INET6 */ } @@ -715,30 +717,39 @@ tcp_notify(inp, error) sowwakeup(so); } -#if defined(INET6) && !defined(TCP6) +#ifdef INET6 void tcp6_ctlinput(cmd, sa, d) int cmd; struct sockaddr *sa; void *d; { - register struct tcphdr *thp; + struct tcphdr *thp; struct tcphdr th; void (*notify) __P((struct inpcb *, int)) = tcp_notify; + int nmatch; struct sockaddr_in6 sa6; - struct mbuf *m; struct ip6_hdr *ip6; + struct mbuf *m; int off; - + struct in6_addr finaldst; + struct in6_addr s; + if (sa->sa_family != AF_INET6 || sa->sa_len != sizeof(struct sockaddr_in6)) return; - if (cmd == PRC_QUENCH) + if ((unsigned)cmd >= PRC_NCMDS) + return; + else if (cmd == PRC_QUENCH) { + /* XXX there's no PRC_QUENCH in IPv6 */ notify = tcp_quench; + } else if (PRC_IS_REDIRECT(cmd)) + notify = in_rtchange, d = NULL; else if (cmd == PRC_MSGSIZE) - notify = tcp_mtudisc; - else if (!PRC_IS_REDIRECT(cmd) && - ((unsigned)cmd > PRC_NCMDS || inet6ctlerrmap[cmd] == 0)) + ; /* special code is present, see below */ + else if (cmd == PRC_HOSTDEAD) + d = NULL; + else if (inet6ctlerrmap[cmd] == 0) return; /* if the parameter is from icmp6, decode it. */ @@ -747,6 +758,16 @@ tcp6_ctlinput(cmd, sa, d) m = ip6cp->ip6c_m; ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; + + /* translate addresses into internal form */ + bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst)); + if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) { + finaldst.s6_addr16[1] = + htons(m->m_pkthdr.rcvif->if_index); + } + bcopy(&ip6->ip6_src, &s, sizeof(s)); + if (IN6_IS_ADDR_LINKLOCAL(&s)) + s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); } else { m = NULL; ip6 = NULL; @@ -756,21 +777,12 @@ tcp6_ctlinput(cmd, sa, d) 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); + if (ip6) { /* - * XXX: We assume that when IPV6 is non NULL, + * XXX: We assume that when ip6 is non NULL, * M and OFF are valid. */ - struct ip6_hdr ip6_tmp; - - /* translate addresses into internal form */ - ip6_tmp = *ip6; - if (IN6_IS_ADDR_LINKLOCAL(&ip6_tmp.ip6_src)) - ip6_tmp.ip6_src.s6_addr16[1] = - htons(m->m_pkthdr.rcvif->if_index); - if (IN6_IS_ADDR_LINKLOCAL(&ip6_tmp.ip6_dst)) - ip6_tmp.ip6_dst.s6_addr16[1] = - htons(m->m_pkthdr.rcvif->if_index); /* check if we can safely examine src and dst ports */ if (m->m_pkthdr.len < off + sizeof(th)) @@ -785,12 +797,36 @@ tcp6_ctlinput(cmd, sa, d) thp = &th; } else thp = (struct tcphdr *)(mtod(m, caddr_t) + off); - (void)in6_pcbnotify(&tcbtable, (struct sockaddr *)&sa6, - thp->th_dport, &ip6_tmp.ip6_src, - thp->th_sport, cmd, notify); + + if (cmd == PRC_MSGSIZE) { + int valid = 0; + + /* + * Check to see if we have a valid TCP connection + * corresponding to the address in the ICMPv6 message + * payload. + */ + if (in_pcblookup(&tcbtable, &finaldst, + thp->th_dport, &s, thp->th_sport, + INPLOOKUP_WILDCARD)) + valid++; + + /* + * Now that we've validated that we are actually + * communicating with the host indicated in the ICMPv6 + * message, recalculate the new MTU, and create the + * corresponding routing entry. + */ + icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); + + return; + } + + nmatch = in6_pcbnotify(&tcbtable, (struct sockaddr *)&sa6, + thp->th_dport, &s, thp->th_sport, cmd, notify); } else { - (void)in6_pcbnotify(&tcbtable, (struct sockaddr *)&sa6, 0, - &zeroin6_addr, 0, cmd, notify); + (void) in6_pcbnotify(&tcbtable, (struct sockaddr *)&sa6, 0, + &zeroin6_addr, 0, cmd, notify); } } #endif @@ -845,7 +881,7 @@ tcp_ctlinput(cmd, sa, v) if (ip) { th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2)); in_pcbnotify(&tcbtable, sa, th->th_dport, ip->ip_src, - th->th_sport, errno, notify); + th->th_sport, errno, notify); } else in_pcbnotifyall(&tcbtable, sa, errno, notify); @@ -925,6 +961,25 @@ tcp_mtudisc_increase(inp, errno) } } +#ifdef INET6 +/* + * Path MTU Discovery handlers. + */ +void +tcp6_mtudisc_callback(faddr) + struct in6_addr *faddr; +{ + struct sockaddr_in6 sin6; + + bzero(&sin6, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_addr = *faddr; + (void) in6_pcbnotify(&tcbtable, (struct sockaddr *)&sin6, 0, + &zeroin6_addr, 0, EMSGSIZE, tcp_mtudisc); +} +#endif /* INET6 */ + #ifdef TCP_SIGNATURE int tcp_signature_tdb_attach() diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index dbcc84d3f25..38a4fc02830 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.48 2000/10/14 01:04:11 itojun Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.49 2000/12/11 08:04:56 itojun Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -95,7 +95,7 @@ extern struct baddynamicports baddynamicports; int tcp_ident __P((void *, size_t *, void *, size_t)); -#if defined(INET6) && !defined(TCP6) +#ifdef INET6 int tcp6_usrreq(so, req, m, nam, control, p) struct socket *so; @@ -103,6 +103,7 @@ tcp6_usrreq(so, req, m, nam, control, p) struct mbuf *m, *nam, *control; struct proc *p; { + return tcp_usrreq(so, req, m, nam, control); } #endif diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index c8416d8cc02..fa07feff32b 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.33 2000/10/14 01:04:11 itojun Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.34 2000/12/11 08:04:56 itojun Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -349,6 +349,10 @@ int tcp_mss __P((struct tcpcb *, int)); void tcp_mss_update __P((struct tcpcb *)); void tcp_mtudisc __P((struct inpcb *, int)); void tcp_mtudisc_increase __P((struct inpcb *, int)); +#ifdef INET6 +void tcp6_mtudisc __P((struct inpcb *, int)); +void tcp6_mtudisc_callback __P((struct in6_addr *)); +#endif struct tcpcb * tcp_newtcpcb __P((struct inpcb *)); void tcp_notify __P((struct inpcb *, int)); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index d3ecb7d686f..6d8bc00de36 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: udp_usrreq.c,v 1.51 2000/10/13 17:58:37 itojun Exp $ */ +/* $OpenBSD: udp_usrreq.c,v 1.52 2000/12/11 08:04:56 itojun Exp $ */ /* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */ /* @@ -122,7 +122,7 @@ udp_init() in_pcbinit(&udbtable, udbhashsize); } -#if defined(INET6) && !defined(TCP6) +#ifdef INET6 int udp6_input(mp, offp, proto) struct mbuf **mp; @@ -650,39 +650,127 @@ udp_notify(inp, errno) sowwakeup(inp->inp_socket); } -#if defined(INET6) && !defined(TCP6) +#ifdef INET6 void udp6_ctlinput(cmd, sa, d) int cmd; struct sockaddr *sa; void *d; { + struct udphdr *uhp; + struct udphdr uh; struct sockaddr_in6 sa6; struct ip6_hdr *ip6; struct mbuf *m; int off; + struct in6_addr s; + struct in6_addr finaldst; + void (*notify) __P((struct inpcb *, int)) = udp_notify; - if (sa == NULL) + if (!sa) return; - if (sa->sa_family != AF_INET6) + if (sa->sa_family != AF_INET6 || + sa->sa_len != sizeof(struct sockaddr_in6)) return; - /* decode parameter from icmp6. */ + if ((unsigned)cmd >= PRC_NCMDS) + return; + if (PRC_IS_REDIRECT(cmd)) + notify = in_rtchange, d = NULL; + else if (cmd == PRC_HOSTDEAD) + d = NULL; + else if (cmd == PRC_MSGSIZE) + ; /* special code is present, see below */ + else if (inet6ctlerrmap[cmd] == 0) + return; + + /* if the parameter is from icmp6, decode it. */ if (d != NULL) { struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d; - ip6 = ip6cp->ip6c_ip6; m = ip6cp->ip6c_m; + ip6 = ip6cp->ip6c_ip6; off = ip6cp->ip6c_off; - } else - return; + + /* translate addresses into internal form */ + bcopy(ip6cp->ip6c_finaldst, &finaldst, sizeof(finaldst)); + if (IN6_IS_ADDR_LINKLOCAL(&finaldst)) { + finaldst.s6_addr16[1] = + htons(m->m_pkthdr.rcvif->if_index); + } + bcopy(&ip6->ip6_src, &s, sizeof(s)); + if (IN6_IS_ADDR_LINKLOCAL(&s)) + s.s6_addr16[1] = htons(m->m_pkthdr.rcvif->if_index); + } else { + m = NULL; + ip6 = NULL; + } /* 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); + if (ip6) { + /* + * XXX: We assume that when IPV6 is non NULL, + * M and OFF are valid. + */ + + /* check if we can safely examine src and dst ports */ + if (m->m_pkthdr.len < off + sizeof(uh)) + return; + + if (m->m_len < off + sizeof(uh)) { + /* + * this should be rare case, + * so we compromise on this copy... + */ + m_copydata(m, off, sizeof(uh), (caddr_t)&uh); + uhp = &uh; + } else + uhp = (struct udphdr *)(mtod(m, caddr_t) + off); + + if (cmd == PRC_MSGSIZE) { + int valid = 0; + /* + * Check to see if we have a valid UDP socket + * corresponding to the address in the ICMPv6 message + * payload. + */ + if (in_pcblookup(&udbtable, &finaldst, uhp->uh_dport, + &s, uhp->uh_sport, INPLOOKUP_IPV6)) + valid++; +#if 0 + /* + * As the use of sendto(2) is fairly popular, + * we may want to allow non-connected pcb too. + * But it could be too weak against attacks... + * We should at least check if the local address (= s) + * is really ours. + */ + else if (in_pcblookup(&udbtable, &finaldst, + uhp->uh_dport, &s, uhp->uh_sport, + INPLOOKUP_WILDCARD | INPLOOKUP_IPV6)) + valid++; +#endif + + /* + * Now that we've validated that we are actually + * communicating with the host indicated in the ICMPv6 + * message, recalculate the new MTU, and create the + * corresponding routing entry. + */ + icmp6_mtudisc_update((struct ip6ctlparam *)d, valid); + + return; + } + + (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, + uhp->uh_dport, &s, uhp->uh_sport, cmd, notify); + } else { + (void) in6_pcbnotify(&udbtable, (struct sockaddr *)&sa6, 0, + &zeroin6_addr, 0, cmd, notify); + } } #endif @@ -698,6 +786,12 @@ udp_ctlinput(cmd, sa, v) void (*notify) __P((struct inpcb *, int)) = udp_notify; int errno; + if (!sa) + return NULL; + if (sa->sa_family != AF_INET || + sa->sa_len != sizeof(struct sockaddr_in)) + return NULL; + if ((unsigned)cmd >= PRC_NCMDS) return NULL; errno = inetctlerrmap[cmd]; @@ -707,28 +801,6 @@ 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 ip6_hdr *ip6 = (struct ip6_hdr *)ip; - - /* XXX we assume that the mbuf is sane enough */ - - uhp = (struct udphdr *)((caddr_t)ip6 + sizeof(*ip6)); -#if 0 /*XXX*/ - in6_pcbnotify(&udbtable, sa, uhp->uh_dport, - &(ip6->ip6_src), uhp->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) { uhp = (struct udphdr *)((caddr_t)ip + (ip->ip_hl << 2)); in_pcbnotify(&udbtable, sa, uhp->uh_dport, ip->ip_src, @@ -1014,7 +1086,7 @@ 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) +#ifdef INET6 /*ARGSUSED*/ int udp6_usrreq(so, req, m, addr, control, p) @@ -1023,6 +1095,7 @@ udp6_usrreq(so, req, m, addr, control, p) struct mbuf *m, *addr, *control; struct proc *p; { + return udp_usrreq(so, req, m, addr, control); } #endif |