Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/ppp/tcpmss.c
Show All 29 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/socket.h> | #include <sys/socket.h> | ||||
#include <net/route.h> | #include <net/route.h> | ||||
#include <netinet/in_systm.h> | #include <netinet/in_systm.h> | ||||
#include <netinet/in.h> | #include <netinet/in.h> | ||||
#include <netinet/ip.h> | #include <netinet/ip.h> | ||||
#ifndef NOINET6 | |||||
#include <netinet/ip6.h> | |||||
#endif | |||||
#include <netinet/tcp.h> | #include <netinet/tcp.h> | ||||
#include <sys/un.h> | #include <sys/un.h> | ||||
#include <termios.h> | #include <termios.h> | ||||
#include "layer.h" | #include "layer.h" | ||||
#include "defs.h" | #include "defs.h" | ||||
#include "log.h" | #include "log.h" | ||||
Show All 18 Lines | |||||
#include "radius.h" | #include "radius.h" | ||||
#endif | #endif | ||||
#include "ipv6cp.h" | #include "ipv6cp.h" | ||||
#include "ncp.h" | #include "ncp.h" | ||||
#include "bundle.h" | #include "bundle.h" | ||||
/*- | /*- | ||||
* We are in a liberal position about MSS | * Compute the MSS as described in RFC 6691. | ||||
* (RFC 879, section 7). | |||||
*/ | */ | ||||
#define MAXMSS(mtu) ((mtu) - sizeof(struct ip) - sizeof(struct tcphdr) - 12) | #define MAXMSS4(mtu) ((mtu) - sizeof(struct ip) - sizeof(struct tcphdr)) | ||||
#ifndef NOINET6 | |||||
#define MAXMSS6(mtu) ((mtu) - sizeof(struct ip6_hdr) - sizeof(struct tcphdr)) | |||||
#endif | |||||
/*- | /*- | ||||
* The following macro is used to update an | * The following macro is used to update an | ||||
* internet checksum. "acc" is a 32-bit | * internet checksum. "acc" is a 32-bit | ||||
* accumulation of all the changes to the | * accumulation of all the changes to the | ||||
* checksum (adding in old 16-bit words and | * checksum (adding in old 16-bit words and | ||||
* subtracting out new words), and "cksum" | * subtracting out new words), and "cksum" | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | for (olen = hlen - sizeof(struct tcphdr), opt = (u_char *)(tc + 1); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static struct mbuf * | static struct mbuf * | ||||
tcpmss_Check(struct bundle *bundle, struct mbuf *bp) | tcpmss_Check(struct bundle *bundle, struct mbuf *bp) | ||||
{ | { | ||||
struct ip *pip; | struct ip *pip; | ||||
#ifndef NOINET6 | |||||
struct ip6_hdr *pip6; | |||||
struct ip6_frag *pfrag; | |||||
#endif | |||||
size_t hlen, plen; | size_t hlen, plen; | ||||
if (!Enabled(bundle, OPT_TCPMSSFIXUP)) | if (!Enabled(bundle, OPT_TCPMSSFIXUP)) | ||||
return bp; | return bp; | ||||
bp = m_pullup(bp); | bp = m_pullup(bp); | ||||
plen = m_length(bp); | plen = m_length(bp); | ||||
if (plen < sizeof(struct ip)) | |||||
thj: This should move into to switch statement below to be consistent with the v6 path | |||||
Done Inline ActionsThe reason I added the check here is that from the next line on I assume that pip points to an IP header and in the line after that I look at the first component of it. Don't I need to make sure I have at least enough data to look at the ip_v field? I think only checking in the switch statement is too late, since I have already accessed a component. Or am I wrong? tuexen: The reason I added the check here is that from the next line on I assume that pip points to an… | |||||
return bp; | |||||
pip = (struct ip *)MBUF_CTOP(bp); | pip = (struct ip *)MBUF_CTOP(bp); | ||||
hlen = pip->ip_hl << 2; | |||||
switch (pip->ip_v) { | |||||
case IPVERSION: | |||||
/* | /* | ||||
* Check for MSS option only for TCP packets with zero fragment offsets | * Check for MSS option only for TCP packets with zero fragment offsets | ||||
* and correct total and header lengths. | * and correct total and header lengths. | ||||
*/ | */ | ||||
hlen = pip->ip_hl << 2; | |||||
if (pip->ip_p == IPPROTO_TCP && (ntohs(pip->ip_off) & IP_OFFMASK) == 0 && | if (pip->ip_p == IPPROTO_TCP && (ntohs(pip->ip_off) & IP_OFFMASK) == 0 && | ||||
ntohs(pip->ip_len) == plen && hlen <= plen && | ntohs(pip->ip_len) == plen && hlen <= plen && | ||||
plen >= sizeof(struct tcphdr) + hlen) | plen >= sizeof(struct tcphdr) + hlen) | ||||
MSSFixup((struct tcphdr *)(MBUF_CTOP(bp) + hlen), plen - hlen, | MSSFixup((struct tcphdr *)(MBUF_CTOP(bp) + hlen), plen - hlen, | ||||
MAXMSS(bundle->iface->mtu)); | MAXMSS4(bundle->iface->mtu)); | ||||
break; | |||||
#ifndef NOINET6 | |||||
case IPV6_VERSION >> 4: | |||||
/* | |||||
* Check for MSS option only for TCP packets with no extension headers | |||||
* or a single extension header which is a fragmentation header with | |||||
* offset 0. Furthermore require that the length field is correct. | |||||
*/ | |||||
if (plen < sizeof(struct ip6_hdr)) | |||||
break; | |||||
pip6 = (struct ip6_hdr *)MBUF_CTOP(bp); | |||||
if (ntohs(pip6->ip6_plen) + sizeof(struct ip6_hdr) != plen) | |||||
break; | |||||
hlen = 0; | |||||
switch (pip6->ip6_nxt) { | |||||
case IPPROTO_TCP: | |||||
hlen = sizeof(struct ip6_hdr); | |||||
break; | |||||
case IPPROTO_FRAGMENT: | |||||
if (plen >= sizeof(struct ip6_frag) + sizeof(struct ip6_hdr)) { | |||||
pfrag = (struct ip6_frag *)(MBUF_CTOP(bp) + sizeof(struct ip6_hdr)); | |||||
if (pfrag->ip6f_nxt == IPPROTO_TCP && | |||||
ntohs(pfrag->ip6f_offlg & IP6F_OFF_MASK) == 0) | |||||
hlen = sizeof(struct ip6_hdr)+ sizeof(struct ip6_frag); | |||||
} | |||||
break; | |||||
} | |||||
if (hlen > 0 && plen >= sizeof(struct tcphdr) + hlen) | |||||
MSSFixup((struct tcphdr *)(MBUF_CTOP(bp) + hlen), plen - hlen, | |||||
MAXMSS6(bundle->iface->mtu)); | |||||
break; | |||||
#endif | |||||
default: | |||||
log_Printf(LogDEBUG, "tcpmss_Check: Unknown IP family %u\n", pip->ip_v); | |||||
break; | |||||
} | |||||
return bp; | return bp; | ||||
} | } | ||||
static struct mbuf * | static struct mbuf * | ||||
tcpmss_LayerPush(struct bundle *bundle, struct link *l __unused, | tcpmss_LayerPush(struct bundle *bundle, struct link *l __unused, | ||||
struct mbuf *bp, int pri __unused, u_short *proto __unused) | struct mbuf *bp, int pri __unused, u_short *proto __unused) | ||||
{ | { | ||||
return tcpmss_Check(bundle, bp); | return tcpmss_Check(bundle, bp); | ||||
Show All 11 Lines |
This should move into to switch statement below to be consistent with the v6 path