2 * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/param.h>
31 #include <sys/socket.h>
32 #include <net/route.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/in.h>
35 #include <netinet/ip.h>
36 #include <netinet/tcp.h>
47 #include "throughput.h"
54 #include "slcompress.h"
58 #include "descriptor.h"
70 * We are in a liberal position about MSS
71 * (RFC 879, section 7).
73 #define MAXMSS(mtu) ((mtu) - sizeof(struct ip) - sizeof(struct tcphdr) - 12)
77 * The following macro is used to update an
78 * internet checksum. "acc" is a 32-bit
79 * accumulation of all the changes to the
80 * checksum (adding in old 16-bit words and
81 * subtracting out new words), and "cksum"
82 * is the checksum value to be updated.
84 #define ADJUST_CHECKSUM(acc, cksum) { \
88 acc = (acc >> 16) + (acc & 0xffff); \
90 cksum = (u_short) ~acc; \
92 acc = (acc >> 16) + (acc & 0xffff); \
94 cksum = (u_short) acc; \
99 MSSFixup(struct tcphdr
*tc
, size_t pktlen
, u_int16_t maxmss
)
101 size_t hlen
, olen
, optlen
;
106 hlen
= tc
->th_off
<< 2;
108 /* Invalid header length or header without options. */
109 if (hlen
<= sizeof(struct tcphdr
) || hlen
> pktlen
)
112 /* MSS option only allowed within SYN packets. */
113 if (!(tc
->th_flags
& TH_SYN
))
116 for (olen
= hlen
- sizeof(struct tcphdr
), opt
= (u_char
*)(tc
+ 1);
117 olen
> 0; olen
-= optlen
, opt
+= optlen
) {
118 if (*opt
== TCPOPT_EOL
)
120 else if (*opt
== TCPOPT_NOP
)
124 if (optlen
<= 0 || optlen
> olen
)
126 if (*opt
== TCPOPT_MAXSEG
) {
127 if (optlen
!= TCPOLEN_MAXSEG
)
129 mss
= (u_int16_t
*)(opt
+ 2);
130 if (ntohs(*mss
) > maxmss
) {
131 log_Printf(LogDEBUG
, "MSS: %u -> %u\n",
132 ntohs(*mss
), maxmss
);
134 *mss
= htons(maxmss
);
136 ADJUST_CHECKSUM(accumulate
, tc
->th_sum
);
144 tcpmss_Check(struct bundle
*bundle
, struct mbuf
*bp
)
149 if (!Enabled(bundle
, OPT_TCPMSSFIXUP
))
154 pip
= (struct ip
*)MBUF_CTOP(bp
);
155 hlen
= pip
->ip_hl
<< 2;
158 * Check for MSS option only for TCP packets with zero fragment offsets
159 * and correct total and header lengths.
161 if (pip
->ip_p
== IPPROTO_TCP
&& (ntohs(pip
->ip_off
) & IP_OFFMASK
) == 0 &&
162 ntohs(pip
->ip_len
) == plen
&& hlen
<= plen
&&
163 plen
>= sizeof(struct tcphdr
) + hlen
)
164 MSSFixup((struct tcphdr
*)(MBUF_CTOP(bp
) + hlen
), plen
- hlen
,
165 MAXMSS(bundle
->iface
->mtu
));
171 tcpmss_LayerPush(struct bundle
*bundle
, struct link
*l __unused
,
172 struct mbuf
*bp
, int pri __unused
, u_short
*proto __unused
)
174 return tcpmss_Check(bundle
, bp
);
178 tcpmss_LayerPull(struct bundle
*bundle
, struct link
*l __unused
,
179 struct mbuf
*bp
, u_short
*proto __unused
)
181 return tcpmss_Check(bundle
, bp
);
184 struct layer tcpmsslayer
=
185 { LAYER_PROTO
, "tcpmss", tcpmss_LayerPush
, tcpmss_LayerPull
};