Fix a problem pointed out by Charles Hannum; DF wasn't being set in
SYN,ACK packets during Path MTU Discovery. Fix tcp_respond() to do the appropriate route lookup and set DF as appropriate. Also, fixup similar code in tcp_output() to relookup the route if it is down.
This commit is contained in:
parent
e612d0da5f
commit
a43786143f
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: tcp_output.c,v 1.46 1998/12/16 00:33:14 thorpej Exp $ */
|
||||
/* $NetBSD: tcp_output.c,v 1.47 1999/01/20 03:39:54 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -170,8 +170,11 @@ int
|
||||
tcp_output(tp)
|
||||
register struct tcpcb *tp;
|
||||
{
|
||||
register struct socket *so = tp->t_inpcb->inp_socket;
|
||||
register long len, win;
|
||||
struct socket *so = tp->t_inpcb->inp_socket;
|
||||
struct route *ro = &tp->t_inpcb->inp_route;
|
||||
struct rtentry *rt;
|
||||
struct sockaddr_in *dst;
|
||||
long len, win;
|
||||
int off, flags, error;
|
||||
register struct mbuf *m;
|
||||
register struct tcpiphdr *ti;
|
||||
@ -662,25 +665,46 @@ send:
|
||||
* the template, but need a way to checksum without them.
|
||||
*/
|
||||
m->m_pkthdr.len = hdrlen + len;
|
||||
{
|
||||
struct rtentry *rt;
|
||||
|
||||
((struct ip *)ti)->ip_len = m->m_pkthdr.len;
|
||||
((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */
|
||||
((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */
|
||||
|
||||
if (ip_mtudisc && (rt = in_pcbrtentry(tp->t_inpcb)) != 0 &&
|
||||
(rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
|
||||
/*
|
||||
* If we're doing Path MTU discovery, we need to set DF unless
|
||||
* the route's MTU is locked. If we lack a route, we need to
|
||||
* look it up now.
|
||||
*
|
||||
* ip_output() could do this for us, but it's convenient to just
|
||||
* do it here unconditionally.
|
||||
*/
|
||||
if ((rt = ro->ro_rt) == NULL || (rt->rt_flags & RTF_UP) == 0) {
|
||||
if (ro->ro_rt != NULL) {
|
||||
RTFREE(ro->ro_rt);
|
||||
ro->ro_rt = NULL;
|
||||
}
|
||||
dst = satosin(&ro->ro_dst);
|
||||
dst->sin_family = AF_INET;
|
||||
dst->sin_len = sizeof(*dst);
|
||||
dst->sin_addr = tp->t_inpcb->inp_faddr;
|
||||
rtalloc(ro);
|
||||
if ((rt = ro->ro_rt) == NULL) {
|
||||
m_freem(m);
|
||||
ipstat.ips_noroute++;
|
||||
error = EHOSTUNREACH;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (ip_mtudisc != 0 && (rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
|
||||
((struct ip *)ti)->ip_off |= IP_DF;
|
||||
|
||||
#if BSD >= 43
|
||||
error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
|
||||
error = ip_output(m, tp->t_inpcb->inp_options, ro,
|
||||
so->so_options & SO_DONTROUTE, 0);
|
||||
#else
|
||||
error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
|
||||
error = ip_output(m, (struct mbuf *)0, ro,
|
||||
so->so_options & SO_DONTROUTE);
|
||||
#endif
|
||||
}
|
||||
if (error) {
|
||||
out:
|
||||
if (error == ENOBUFS) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: tcp_subr.c,v 1.63 1998/12/18 21:38:03 thorpej Exp $ */
|
||||
/* $NetBSD: tcp_subr.c,v 1.64 1999/01/20 03:39:54 thorpej Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
|
||||
@ -212,14 +212,22 @@ tcp_respond(tp, ti, m, ack, seq, flags)
|
||||
tcp_seq ack, seq;
|
||||
int flags;
|
||||
{
|
||||
register int tlen;
|
||||
int win = 0;
|
||||
struct route *ro = 0;
|
||||
struct route iproute, *ro;
|
||||
struct rtentry *rt;
|
||||
struct sockaddr_in *dst;
|
||||
int error, tlen, win = 0;
|
||||
|
||||
if (tp) {
|
||||
if (tp != NULL) {
|
||||
if ((flags & TH_RST) == 0)
|
||||
win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
|
||||
ro = &tp->t_inpcb->inp_route;
|
||||
#ifdef DIAGNOSTIC
|
||||
if (!in_hosteq(ti->ti_dst, tp->t_inpcb->inp_faddr))
|
||||
panic("tcp_respond: ti_dst != inp_faddr");
|
||||
#endif
|
||||
} else {
|
||||
ro = &iproute;
|
||||
bzero(ro, sizeof(*ro));
|
||||
}
|
||||
if (m == 0) {
|
||||
m = m_gethdr(M_DONTWAIT, MT_HEADER);
|
||||
@ -270,7 +278,42 @@ tcp_respond(tp, ti, m, ack, seq, flags)
|
||||
ti->ti_sum = in_cksum(m, tlen);
|
||||
((struct ip *)ti)->ip_len = tlen;
|
||||
((struct ip *)ti)->ip_ttl = ip_defttl;
|
||||
return ip_output(m, NULL, ro, 0, NULL);
|
||||
|
||||
/*
|
||||
* If we're doing Path MTU discovery, we need to set DF unless
|
||||
* the route's MTU is locked. If we lack a route, we need to
|
||||
* look it up now.
|
||||
*
|
||||
* ip_output() could do this for us, but it's convenient to just
|
||||
* do it here unconditionally.
|
||||
*/
|
||||
if ((rt = ro->ro_rt) == NULL || (rt->rt_flags & RTF_UP) == 0) {
|
||||
if (ro->ro_rt != NULL) {
|
||||
RTFREE(ro->ro_rt);
|
||||
ro->ro_rt = NULL;
|
||||
}
|
||||
dst = satosin(&ro->ro_dst);
|
||||
dst->sin_family = AF_INET;
|
||||
dst->sin_len = sizeof(*dst);
|
||||
dst->sin_addr = ti->ti_dst;
|
||||
rtalloc(ro);
|
||||
if ((rt = ro->ro_rt) == NULL) {
|
||||
m_freem(m);
|
||||
ipstat.ips_noroute++;
|
||||
return (EHOSTUNREACH);
|
||||
}
|
||||
}
|
||||
if (ip_mtudisc != 0 && (rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
|
||||
((struct ip *)ti)->ip_off |= IP_DF;
|
||||
|
||||
error = ip_output(m, NULL, ro, 0, NULL);
|
||||
|
||||
if (ro == &iproute) {
|
||||
RTFREE(ro->ro_rt);
|
||||
ro->ro_rt = NULL;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user