Bug #1820 » 0002-Implement-IPv6-support-for-TCP-MD5-Signature-Option-.patch
| sys/netinet/tcp_output.c | ||
|---|---|---|
|
tcp_sack_fill_report(tp, opt, &optlen);
|
||
|
#ifdef TCP_SIGNATURE
|
||
|
if (!isipv6)
|
||
|
if (tp->t_flags & TF_SIGNATURE) {
|
||
|
int i;
|
||
|
u_char *bp;
|
||
|
/*
|
||
|
* Initialize TCP-MD5 option (RFC2385)
|
||
|
*/
|
||
|
bp = (u_char *)opt + optlen;
|
||
|
*bp++ = TCPOPT_SIGNATURE;
|
||
|
*bp++ = TCPOLEN_SIGNATURE;
|
||
|
sigoff = optlen + 2;
|
||
|
for (i = 0; i < TCP_SIGLEN; i++)
|
||
|
*bp++ = 0;
|
||
|
optlen += TCPOLEN_SIGNATURE;
|
||
|
/*
|
||
|
* Terminate options list and maintain 32-bit alignment.
|
||
|
*/
|
||
|
*bp++ = TCPOPT_NOP;
|
||
|
*bp++ = TCPOPT_EOL;
|
||
|
optlen += 2;
|
||
|
}
|
||
|
if (tp->t_flags & TF_SIGNATURE) {
|
||
|
int i;
|
||
|
u_char *bp;
|
||
|
/*
|
||
|
* Initialize TCP-MD5 option (RFC2385)
|
||
|
*/
|
||
|
bp = (u_char *)opt + optlen;
|
||
|
*bp++ = TCPOPT_SIGNATURE;
|
||
|
*bp++ = TCPOLEN_SIGNATURE;
|
||
|
sigoff = optlen + 2;
|
||
|
for (i = 0; i < TCP_SIGLEN; i++)
|
||
|
*bp++ = 0;
|
||
|
optlen += TCPOLEN_SIGNATURE;
|
||
|
/*
|
||
|
* Terminate options list and maintain 32-bit alignment.
|
||
|
*/
|
||
|
*bp++ = TCPOPT_NOP;
|
||
|
*bp++ = TCPOPT_EOL;
|
||
|
optlen += 2;
|
||
|
}
|
||
|
#endif /* TCP_SIGNATURE */
|
||
|
KASSERT(optlen <= TCP_MAXOLEN, ("too many TCP options"));
|
||
|
hdrlen += optlen;
|
||
| ... | ... | |
|
}
|
||
|
#ifdef TCP_SIGNATURE
|
||
|
if (!isipv6)
|
||
|
if (tp->t_flags & TF_SIGNATURE)
|
||
|
tcpsignature_compute(m, sizeof(struct ip), len, optlen,
|
||
|
(u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
|
||
|
if (tp->t_flags & TF_SIGNATURE)
|
||
|
tcpsignature_compute(m, len, optlen,
|
||
|
(u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND);
|
||
|
#endif /* TCP_SIGNATURE */
|
||
|
/*
|
||
| sys/netinet/tcp_subr.c | ||
|---|---|---|
|
#ifdef TCP_SIGNATURE
|
||
|
/*
|
||
|
* Compute TCP-MD5 hash of a TCPv4 segment. (RFC2385)
|
||
|
* Compute TCP-MD5 hash of a TCP segment. (RFC2385)
|
||
|
*
|
||
|
* We do this over ip, tcphdr, segment data, and the key in the SADB.
|
||
|
* When called from tcp_input(), we can be sure that th_sum has been
|
||
|
* zeroed out and verified already.
|
||
|
*
|
||
|
* This function is for IPv4 use only. Calling this function with an
|
||
|
* IPv6 packet in the mbuf chain will yield undefined results.
|
||
|
*
|
||
|
* Return 0 if successful, otherwise return -1.
|
||
|
*
|
||
|
* XXX The key is retrieved from the system's PF_KEY SADB, by keying a
|
||
| ... | ... | |
|
int
|
||
|
tcpsignature_compute(
|
||
|
struct mbuf *m, /* mbuf chain */
|
||
|
int off0, /* offset to TCP header */
|
||
|
int len, /* length of TCP data */
|
||
|
int optlen, /* length of TCP options */
|
||
|
u_char *buf, /* storage for MD5 digest */
|
||
| ... | ... | |
|
struct ipovly *ipovly;
|
||
|
struct secasvar *sav;
|
||
|
struct tcphdr *th;
|
||
|
#ifdef INET6
|
||
|
struct ip6_hdr *ip6;
|
||
|
struct in6_addr in6;
|
||
|
uint32_t plen;
|
||
|
uint16_t nhdr;
|
||
|
#endif /* INET6 */
|
||
|
u_short savecsum;
|
||
|
KASSERT(m != NULL, ("passed NULL mbuf. Game over."));
|
||
| ... | ... | |
|
* Extract the destination from the IP header in the mbuf.
|
||
|
*/
|
||
|
ip = mtod(m, struct ip *);
|
||
|
#ifdef INET6
|
||
|
ip6 = NULL; /* Make the compiler happy. */
|
||
|
#endif /* INET6 */
|
||
|
/*
|
||
|
* Look up an SADB entry which matches the address found in
|
||
|
* the segment.
|
||
|
*/
|
||
|
sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
|
||
|
IPPROTO_TCP, htonl(TCP_SIG_SPI));
|
||
|
switch (IP_VHL_V(ip->ip_vhl)) {
|
||
|
case IPVERSION:
|
||
|
sav = key_allocsa(AF_INET, (caddr_t)&ip->ip_src, (caddr_t)&ip->ip_dst,
|
||
|
IPPROTO_TCP, htonl(TCP_SIG_SPI));
|
||
|
break;
|
||
|
#ifdef INET6
|
||
|
case (IPV6_VERSION >> 4):
|
||
|
ip6 = mtod(m, struct ip6_hdr *);
|
||
|
sav = key_allocsa(AF_INET6, (caddr_t)&ip6->ip6_src, (caddr_t)&ip6->ip6_dst,
|
||
|
IPPROTO_TCP, htonl(TCP_SIG_SPI));
|
||
|
break;
|
||
|
#endif /* INET6 */
|
||
|
default:
|
||
|
return (EINVAL);
|
||
|
/* NOTREACHED */
|
||
|
break;
|
||
|
}
|
||
|
if (sav == NULL) {
|
||
|
kprintf("%s: SADB lookup failed\n", __func__);
|
||
|
return (EINVAL);
|
||
|
}
|
||
|
MD5Init(&ctx);
|
||
|
ipovly = (struct ipovly *)ip;
|
||
|
th = (struct tcphdr *)((u_char *)ip + off0);
|
||
|
doff = off0 + sizeof(struct tcphdr) + optlen;
|
||
|
/*
|
||
|
* Step 1: Update MD5 hash with IP pseudo-header.
|
||
|
*
|
||
| ... | ... | |
|
* XXX One cannot depend on ipovly->ih_len here. When called from
|
||
|
* tcp_output(), the underlying ip_len member has not yet been set.
|
||
|
*/
|
||
|
ippseudo.ippseudo_src = ipovly->ih_src;
|
||
|
ippseudo.ippseudo_dst = ipovly->ih_dst;
|
||
|
ippseudo.ippseudo_pad = 0;
|
||
|
ippseudo.ippseudo_p = IPPROTO_TCP;
|
||
|
ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + optlen);
|
||
|
MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
|
||
|
switch (IP_VHL_V(ip->ip_vhl)) {
|
||
|
case IPVERSION:
|
||
|
ipovly = (struct ipovly *)ip;
|
||
|
ippseudo.ippseudo_src = ipovly->ih_src;
|
||
|
ippseudo.ippseudo_dst = ipovly->ih_dst;
|
||
|
ippseudo.ippseudo_pad = 0;
|
||
|
ippseudo.ippseudo_p = IPPROTO_TCP;
|
||
|
ippseudo.ippseudo_len = htons(len + sizeof(struct tcphdr) + optlen);
|
||
|
MD5Update(&ctx, (char *)&ippseudo, sizeof(struct ippseudo));
|
||
|
th = (struct tcphdr *)((u_char *)ip + sizeof(struct ip));
|
||
|
doff = sizeof(struct ip) + sizeof(struct tcphdr) + optlen;
|
||
|
break;
|
||
|
#ifdef INET6
|
||
|
/*
|
||
|
* RFC 2385, 2.0 Proposal
|
||
|
* For IPv6, the pseudo-header is as described in RFC 2460, namely the
|
||
|
* 128-bit source IPv6 address, 128-bit destination IPv6 address, zero-
|
||
|
* extended next header value (to form 32 bits), and 32-bit segment
|
||
|
* length.
|
||
|
* Note: Upper-Layer Packet Length comes before Next Header.
|
||
|
*/
|
||
|
case (IPV6_VERSION >> 4):
|
||
|
in6 = ip6->ip6_src;
|
||
|
in6_clearscope(&in6);
|
||
|
MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
|
||
|
in6 = ip6->ip6_dst;
|
||
|
in6_clearscope(&in6);
|
||
|
MD5Update(&ctx, (char *)&in6, sizeof(struct in6_addr));
|
||
|
plen = htonl(len + sizeof(struct tcphdr) + optlen);
|
||
|
MD5Update(&ctx, (char *)&plen, sizeof(uint32_t));
|
||
|
nhdr = 0;
|
||
|
MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
|
||
|
MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
|
||
|
MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
|
||
|
nhdr = IPPROTO_TCP;
|
||
|
MD5Update(&ctx, (char *)&nhdr, sizeof(uint8_t));
|
||
|
th = (struct tcphdr *)((u_char *)ip6 + sizeof(struct ip6_hdr));
|
||
|
doff = sizeof(struct ip6_hdr) + sizeof(struct tcphdr) + optlen;
|
||
|
break;
|
||
|
#endif /* INET6 */
|
||
|
default:
|
||
|
return (EINVAL);
|
||
|
/* NOTREACHED */
|
||
|
break;
|
||
|
}
|
||
|
/*
|
||
|
* Step 2: Update MD5 hash with TCP header, excluding options.
|
||
|
* The TCP checksum must be set to zero.
|
||
| sys/netinet/tcp_syncache.c | ||
|---|---|---|
|
*bp++ = TCPOLEN_SIGNATURE;
|
||
|
for (i = 0; i < TCP_SIGLEN; i++)
|
||
|
*bp++ = 0;
|
||
|
tcpsignature_compute(m, sizeof(struct ip), 0, optlen,
|
||
|
tcpsignature_compute(m, 0, optlen,
|
||
|
optp + 2, IPSEC_DIR_OUTBOUND);
|
||
|
*bp++ = TCPOPT_NOP;
|
||
|
*bp++ = TCPOPT_EOL;
|
||
| sys/netinet/tcp_var.h | ||
|---|---|---|
|
#ifdef TCP_SIGNATURE
|
||
|
int tcpsignature_apply(void *fstate, void *data, unsigned int len);
|
||
|
int tcpsignature_compute(struct mbuf *m, int off0, int len, int tcpoptlen,
|
||
|
int tcpsignature_compute(struct mbuf *m, int len, int tcpoptlen,
|
||
|
u_char *buf, u_int direction);
|
||
|
#endif /* TCP_SIGNATURE */
|
||
- « Previous
- 1
- 2
- Next »