summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netinet/ip_icmp.c46
-rw-r--r--sys/netinet/ip_icmp.h1
-rw-r--r--sys/netinet/tcp_subr.c43
-rw-r--r--sys/netinet/tcp_timewait.c43
4 files changed, 74 insertions, 59 deletions
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index 4547886..c57b684 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -125,7 +125,6 @@ int icmpprintfs = 0;
static void icmp_reflect(struct mbuf *);
static void icmp_send(struct mbuf *, struct mbuf *);
-static int ip_next_mtu(int, int);
extern struct protosw inetsw[];
@@ -407,49 +406,6 @@ icmp_input(m, off)
printf("deliver to protocol %d\n", icp->icmp_ip.ip_p);
#endif
icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
-
- /*
- * MTU discovery:
- * If we got a needfrag and there is a host route to the
- * original destination, and the MTU is not locked, then
- * set the MTU in the route to the suggested new value
- * (if given) and then notify as usual. The ULPs will
- * notice that the MTU has changed and adapt accordingly.
- * If no new MTU was suggested, then we guess a new one
- * less than the current value. If the new MTU is
- * unreasonably small (defined by sysctl tcp_minmss), then
- * we don't update the MTU value.
- *
- * XXX: All this should be done in tcp_mtudisc() because
- * the way we do it now, everyone can send us bogus ICMP
- * MSGSIZE packets for any destination. By doing this far
- * higher in the chain we have a matching tcp connection.
- * Thus spoofing is much harder. However there is no easy
- * non-hackish way to pass the new MTU up to tcp_mtudisc().
- * Also see next XXX regarding IPv4 AH TCP.
- */
- if (code == PRC_MSGSIZE) {
- int mtu;
- struct in_conninfo inc;
-
- bzero(&inc, sizeof(inc));
- inc.inc_flags = 0; /* IPv4 */
- inc.inc_faddr = icmpsrc.sin_addr;
-
- mtu = ntohs(icp->icmp_nextmtu);
- if (!mtu)
- mtu = ip_next_mtu(mtu, 1);
-
- if (mtu >= max(296, (tcp_minmss +
- sizeof(struct tcpiphdr))))
- tcp_hc_updatemtu(&inc, mtu);
-
-#ifdef DEBUG_MTUDISC
- printf("MTU for %s reduced to %d\n",
- inet_ntoa(icmpsrc.sin_addr), mtu);
-#endif
- }
-
/*
* XXX if the packet contains [IPv4 AH TCP], we can't make a
* notification to TCP layer.
@@ -831,7 +787,7 @@ iptime()
* given current value MTU. If DIR is less than zero, a larger plateau
* is returned; otherwise, a smaller value is returned.
*/
-static int
+int
ip_next_mtu(mtu, dir)
int mtu;
int dir;
diff --git a/sys/netinet/ip_icmp.h b/sys/netinet/ip_icmp.h
index 9d58529..6acff63 100644
--- a/sys/netinet/ip_icmp.h
+++ b/sys/netinet/ip_icmp.h
@@ -193,6 +193,7 @@ struct icmp {
#ifdef _KERNEL
void icmp_error(struct mbuf *, int, int, n_long, struct ifnet *);
void icmp_input(struct mbuf *, int);
+int ip_next_mtu(int, int);
#endif
#endif
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 02e753a..474aa52 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -76,6 +76,7 @@
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#endif
+#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -1110,8 +1111,10 @@ tcp_ctlinput(cmd, sa, vip)
struct inpcb *inp;
struct tcpcb *tp;
struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
- tcp_seq icmp_seq;
- int s;
+ struct icmp *icp;
+ struct in_conninfo inc;
+ tcp_seq icmp_tcp_seq;
+ int mtu, s;
faddr = ((struct sockaddr_in *)sa)->sin_addr;
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
@@ -1143,6 +1146,8 @@ tcp_ctlinput(cmd, sa, vip)
return;
if (ip != NULL) {
s = splnet();
+ icp = (struct icmp *)((caddr_t)ip
+ - offsetof(struct icmp, icmp_ip));
th = (struct tcphdr *)((caddr_t)ip
+ (ip->ip_hl << 2));
INP_INFO_WLOCK(&tcbinfo);
@@ -1151,17 +1156,41 @@ tcp_ctlinput(cmd, sa, vip)
if (inp != NULL) {
INP_LOCK(inp);
if (inp->inp_socket != NULL) {
- icmp_seq = htonl(th->th_seq);
+ icmp_tcp_seq = htonl(th->th_seq);
tp = intotcpcb(inp);
- if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
- SEQ_LT(icmp_seq, tp->snd_max))
+ if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) &&
+ SEQ_LT(icmp_tcp_seq, tp->snd_max)) {
+ if (cmd == PRC_MSGSIZE) {
+ /*
+ * MTU discovery:
+ * If we got a needfrag set the MTU
+ * in the route to the suggested new
+ * value (if given) and then notify.
+ * If no new MTU was suggested, then
+ * we guess a new one less than the
+ * current value.
+ * If the new MTU is unreasonably
+ * small (defined by sysctl tcp_minmss),
+ * then we up the MTU value to minimum.
+ */
+ bzero(&inc, sizeof(inc));
+ inc.inc_flags = 0; /* IPv4 */
+ inc.inc_faddr = faddr;
+
+ mtu = ntohs(icp->icmp_nextmtu);
+ if (!mtu)
+ mtu = ip_next_mtu(mtu, 1);
+ if (mtu >= max(296, (tcp_minmss
+ + sizeof(struct tcpiphdr))))
+ tcp_hc_updatemtu(&inc, mtu);
+ }
+
inp = (*notify)(inp, inetctlerrmap[cmd]);
+ }
}
if (inp != NULL)
INP_UNLOCK(inp);
} else {
- struct in_conninfo inc;
-
inc.inc_fport = th->th_dport;
inc.inc_lport = th->th_sport;
inc.inc_faddr = faddr;
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index 02e753a..474aa52 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -76,6 +76,7 @@
#include <netinet6/ip6_var.h>
#include <netinet6/nd6.h>
#endif
+#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_seq.h>
@@ -1110,8 +1111,10 @@ tcp_ctlinput(cmd, sa, vip)
struct inpcb *inp;
struct tcpcb *tp;
struct inpcb *(*notify)(struct inpcb *, int) = tcp_notify;
- tcp_seq icmp_seq;
- int s;
+ struct icmp *icp;
+ struct in_conninfo inc;
+ tcp_seq icmp_tcp_seq;
+ int mtu, s;
faddr = ((struct sockaddr_in *)sa)->sin_addr;
if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
@@ -1143,6 +1146,8 @@ tcp_ctlinput(cmd, sa, vip)
return;
if (ip != NULL) {
s = splnet();
+ icp = (struct icmp *)((caddr_t)ip
+ - offsetof(struct icmp, icmp_ip));
th = (struct tcphdr *)((caddr_t)ip
+ (ip->ip_hl << 2));
INP_INFO_WLOCK(&tcbinfo);
@@ -1151,17 +1156,41 @@ tcp_ctlinput(cmd, sa, vip)
if (inp != NULL) {
INP_LOCK(inp);
if (inp->inp_socket != NULL) {
- icmp_seq = htonl(th->th_seq);
+ icmp_tcp_seq = htonl(th->th_seq);
tp = intotcpcb(inp);
- if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
- SEQ_LT(icmp_seq, tp->snd_max))
+ if (SEQ_GEQ(icmp_tcp_seq, tp->snd_una) &&
+ SEQ_LT(icmp_tcp_seq, tp->snd_max)) {
+ if (cmd == PRC_MSGSIZE) {
+ /*
+ * MTU discovery:
+ * If we got a needfrag set the MTU
+ * in the route to the suggested new
+ * value (if given) and then notify.
+ * If no new MTU was suggested, then
+ * we guess a new one less than the
+ * current value.
+ * If the new MTU is unreasonably
+ * small (defined by sysctl tcp_minmss),
+ * then we up the MTU value to minimum.
+ */
+ bzero(&inc, sizeof(inc));
+ inc.inc_flags = 0; /* IPv4 */
+ inc.inc_faddr = faddr;
+
+ mtu = ntohs(icp->icmp_nextmtu);
+ if (!mtu)
+ mtu = ip_next_mtu(mtu, 1);
+ if (mtu >= max(296, (tcp_minmss
+ + sizeof(struct tcpiphdr))))
+ tcp_hc_updatemtu(&inc, mtu);
+ }
+
inp = (*notify)(inp, inetctlerrmap[cmd]);
+ }
}
if (inp != NULL)
INP_UNLOCK(inp);
} else {
- struct in_conninfo inc;
-
inc.inc_fport = th->th_dport;
inc.inc_lport = th->th_sport;
inc.inc_faddr = faddr;
OpenPOWER on IntegriCloud