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 »