1706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
2706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Copyright (c) 2000 Ruslan Ermilov and Brian Somers <brian@Awfulhak.org>
3706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * All rights reserved.
4706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
5706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * Redistribution and use in source and binary forms, with or without
6706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * modification, are permitted provided that the following conditions
7706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * are met:
8706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 1. Redistributions of source code must retain the above copyright
9706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer.
10706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * 2. Redistributions in binary form must reproduce the above copyright
11706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    notice, this list of conditions and the following disclaimer in the
12706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *    documentation and/or other materials provided with the distribution.
13706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
14706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * SUCH DAMAGE.
25706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh *
26706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * $FreeBSD: src/usr.sbin/ppp/tcpmss.c,v 1.8.26.1 2010/12/21 17:10:29 kensmith Exp $
27706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
28706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
29706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/param.h>
30706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
31706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/socket.h>
32706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <net/route.h>
33706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in_systm.h>
34706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/in.h>
35706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/ip.h>
36706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <netinet/tcp.h>
37706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <sys/un.h>
38706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
39706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include <termios.h>
40706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
41706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "layer.h"
42706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "defs.h"
43706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "log.h"
44706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "timer.h"
45706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "fsm.h"
46706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mbuf.h"
47706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "throughput.h"
48706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lqr.h"
49706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "hdlc.h"
50706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "lcp.h"
51706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ccp.h"
52706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "link.h"
53706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iplist.h"
54706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "slcompress.h"
55706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncpaddr.h"
56706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipcp.h"
57706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "filter.h"
58706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "descriptor.h"
59706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "mp.h"
60706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "iface.h"
61706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#ifndef NORADIUS
62706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "radius.h"
63706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#endif
64706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ipv6cp.h"
65706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "ncp.h"
66706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#include "bundle.h"
67706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
68706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
69706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
70706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * We are in a liberal position about MSS
71706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * (RFC 879, section 7).
72706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
73706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define MAXMSS(mtu) ((mtu) - sizeof(struct ip) - sizeof(struct tcphdr) - 12)
74706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
75706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
76706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh/*-
77706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * The following macro is used to update an
78706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * internet checksum.  "acc" is a 32-bit
79706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * accumulation of all the changes to the
80706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * checksum (adding in old 16-bit words and
81706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * subtracting out new words), and "cksum"
82706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh * is the checksum value to be updated.
83706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh */
84706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh#define ADJUST_CHECKSUM(acc, cksum) { \
85706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  acc += cksum; \
86706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (acc < 0) { \
87706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    acc = -acc; \
88706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    acc = (acc >> 16) + (acc & 0xffff); \
89706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    acc += acc >> 16; \
90706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cksum = (u_short) ~acc; \
91706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } else { \
92706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    acc = (acc >> 16) + (acc & 0xffff); \
93706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    acc += acc >> 16; \
94706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    cksum = (u_short) acc; \
95706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  } \
96706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
97706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
98706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic void
99706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi YehMSSFixup(struct tcphdr *tc, size_t pktlen, u_int16_t maxmss)
100706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
101706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  size_t hlen, olen, optlen;
102706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_char *opt;
103706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  u_int16_t *mss;
104706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  int accumulate;
105706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
106706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hlen = tc->th_off << 2;
107706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
108706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* Invalid header length or header without options. */
109706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (hlen <= sizeof(struct tcphdr) || hlen > pktlen)
110706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
111706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
112706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /* MSS option only allowed within SYN packets. */
113706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!(tc->th_flags & TH_SYN))
114706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return;
115706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
116706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  for (olen = hlen - sizeof(struct tcphdr), opt = (u_char *)(tc + 1);
117706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh       olen > 0; olen -= optlen, opt += optlen) {
118706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    if (*opt == TCPOPT_EOL)
119706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      break;
120706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else if (*opt == TCPOPT_NOP)
121706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      optlen = 1;
122706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    else {
123706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      optlen = *(opt + 1);
124706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (optlen <= 0 || optlen > olen)
125706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        break;
126706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      if (*opt == TCPOPT_MAXSEG) {
127706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (optlen != TCPOLEN_MAXSEG)
128706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          continue;
129706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        mss = (u_int16_t *)(opt + 2);
130706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        if (ntohs(*mss) > maxmss) {
131706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          log_Printf(LogDEBUG, "MSS: %u -> %u\n",
132706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh               ntohs(*mss), maxmss);
133706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          accumulate = *mss;
134706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          *mss = htons(maxmss);
135706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          accumulate -= *mss;
136706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh          ADJUST_CHECKSUM(accumulate, tc->th_sum);
137706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh        }
138706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      }
139706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    }
140706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  }
141706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
142706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
143706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct mbuf *
144706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehtcpmss_Check(struct bundle *bundle, struct mbuf *bp)
145706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
146706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  struct ip *pip;
147706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  size_t hlen, plen;
148706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
149706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (!Enabled(bundle, OPT_TCPMSSFIXUP))
150706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    return bp;
151706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
152706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  bp = m_pullup(bp);
153706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  plen = m_length(bp);
154706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  pip = (struct ip *)MBUF_CTOP(bp);
155706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  hlen = pip->ip_hl << 2;
156706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
157706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  /*
158706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * Check for MSS option only for TCP packets with zero fragment offsets
159706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   * and correct total and header lengths.
160706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh   */
161706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  if (pip->ip_p == IPPROTO_TCP && (ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
162706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      ntohs(pip->ip_len) == plen && hlen <= plen &&
163706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh      plen >= sizeof(struct tcphdr) + hlen)
164706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh    MSSFixup((struct tcphdr *)(MBUF_CTOP(bp) + hlen), plen - hlen,
165706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh             MAXMSS(bundle->iface->mtu));
166706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
167706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  return bp;
168706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
169706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
170706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct mbuf *
171706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehtcpmss_LayerPush(struct bundle *bundle, struct link *l __unused,
172706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		 struct mbuf *bp, int pri __unused, u_short *proto __unused)
173706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
174706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	return tcpmss_Check(bundle, bp);
175706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
176706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
177706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstatic struct mbuf *
178706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehtcpmss_LayerPull(struct bundle *bundle, struct link *l __unused,
179706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh		 struct mbuf *bp, u_short *proto __unused)
180706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh{
181706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh	return tcpmss_Check(bundle, bp);
182706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh}
183706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh
184706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yehstruct layer tcpmsslayer =
185706e567fc5ff6b79738a5f470e5aa7b2cae76459Chia-chi Yeh  { LAYER_PROTO, "tcpmss", tcpmss_LayerPush, tcpmss_LayerPull };
186