summaryrefslogtreecommitdiff
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/icmp6.h15
-rw-r--r--sys/netinet/tcp_input.c4
-rw-r--r--sys/netinet/tcp_subr.c107
-rw-r--r--sys/netinet/tcp_usrreq.c5
-rw-r--r--sys/netinet/tcp_var.h6
-rw-r--r--sys/netinet/udp_usrreq.c141
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