Index: netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.270
diff -u -p -r1.270 tcp_input.c
--- netinet/tcp_input.c 2 Aug 2007 13:06:30 -0000 1.270
+++ netinet/tcp_input.c 14 Aug 2007 11:33:34 -0000
@@ -981,6 +981,10 @@ tcp_input(struct mbuf *m, ...)
#endif
u_int8_t *optp = NULL;
int optlen = 0;
+#ifdef TCP_SIGNATURE
+ u_int8_t *soptp = NULL;
+ int soptlen = 0;
+#endif
int len, tlen, toff, hdroptlen = 0;
struct tcpcb *tp = 0;
int tiflags;
@@ -1142,6 +1146,10 @@ tcp_input(struct mbuf *m, ...)
KASSERT(TCP_HDR_ALIGNED_P(th));
optlen = off - sizeof (struct tcphdr);
optp = ((u_int8_t *)th) + sizeof(struct tcphdr);
+#ifdef TCP_SIGNATURE
+ soptp = optp;
+ soptlen = optlen;
+#endif
/*
* Do quick retrieval of timestamp options ("options
* prediction?"). If timestamp is the only option and it's
@@ -1616,13 +1624,17 @@ after_listen:
* Process options.
*/
#ifdef TCP_SIGNATURE
- if (optp || (tp->t_flags & TF_SIGNATURE))
+ if (optp || (tp->t_flags & TF_SIGNATURE)) {
+ if (!optp) {
+ optp = soptp;
+ optlen = soptlen;
+ }
#else
- if (optp)
+ if (optp) {
#endif
if (tcp_dooptions(tp, optp, optlen, th, m, toff, &opti) < 0)
goto drop;
-
+ }
if (TCP_SACK_ENABLED(tp)) {
tcp_del_sackholes(tp, th);
}
@@ -2229,7 +2241,12 @@ after_listen:
if (tiflags & TH_SYN) {
if (tp->rcv_nxt == th->th_seq) {
tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack - 1,
- TH_ACK);
+ TH_ACK,
+#ifdef TCP_SIGNATURE
+ tp->t_flags & TF_SIGNATURE);
+#else
+ 0);
+#endif
if (tcp_saveti)
m_freem(tcp_saveti);
return;
@@ -2759,13 +2776,26 @@ dropwithreset:
goto drop;
}
- if (tiflags & TH_ACK)
- (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack, TH_RST);
- else {
+ if (tiflags & TH_ACK) {
+#ifdef TCP_SIGNATURE
+ if(tcp_checksignature(soptp, soptlen))
+ (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack,
+ TH_RST, TF_SIGNATURE);
+ else
+#endif
+ (void)tcp_respond(tp, m, m, th, (tcp_seq)0, th->th_ack,
+ TH_RST, 0);
+ } else {
if (tiflags & TH_SYN)
tlen++;
- (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, (tcp_seq)0,
- TH_RST|TH_ACK);
+#ifdef TCP_SIGNATURE
+ if(tcp_checksignature(soptp, soptlen))
+ (void)tcp_respond(tp, m, m, th, th->th_seq + tlen,
+ (tcp_seq)0, TH_RST|TH_ACK, TF_SIGNATURE);
+ else
+#endif
+ (void)tcp_respond(tp, m, m, th, th->th_seq + tlen, (tcp_seq)0,
+ TH_RST|TH_ACK, 0);
}
if (tcp_saveti)
m_freem(tcp_saveti);
@@ -2806,7 +2836,7 @@ tcp_signature_apply(void *fstate, void *
}
struct secasvar *
-tcp_signature_getsav(struct mbuf *m, struct tcphdr *th)
+tcp_signature_getsav(struct mbuf *m)
{
struct secasvar *sav;
#ifdef FAST_IPSEC
@@ -2855,7 +2885,7 @@ tcp_signature_getsav(struct mbuf *m, str
sav = key_allocsa(AF_INET6, (void *)&ip6->ip6_src,
(void *)&ip6->ip6_dst, IPPROTO_TCP,
htonl(TCP_SIG_SPI), 0, 0);
-#endif
+#endif /* FAST_IPSEC */
return (sav); /* freesav must be performed by caller */
}
@@ -2928,7 +2958,34 @@ tcp_signature(struct mbuf *m, struct tcp
return (0);
}
-#endif
+
+/*
+ * Checks if signature option is present
+ */
+int
+tcp_checksignature(const u_char *cp, int cnt)
+{
+ int i = 0;
+
+ if (cp == NULL)
+ return 0;
+
+ while (i < cnt) {
+ if (cp[i] == TCPOPT_EOL)
+ return 0;
+ if (cp[i] == TCPOPT_NOP) {
+ i++;
+ continue;
+ }
+ if (cp[i] == TCPOPT_SIGNATURE)
+ return 1;
+ i += cp[i+1];
+ }
+
+return 0;
+}
+
+#endif /* TCP_SIGNATURE */
static int
tcp_dooptions(struct tcpcb *tp, const u_char *cp, int cnt,
@@ -3049,7 +3106,7 @@ tcp_dooptions(struct tcpcb *tp, const u_
case TCPOPT_SIGNATURE:
if (optlen != TCPOLEN_SIGNATURE)
continue;
- if (sigp && bcmp(sigp, cp + 2, TCP_SIGLEN))
+ if (sigp && memcmp(sigp, cp + 2, TCP_SIGLEN))
return (-1);
sigp = sigbuf;
@@ -3063,7 +3120,7 @@ tcp_dooptions(struct tcpcb *tp, const u_
#ifdef TCP_SIGNATURE
if (tp->t_flags & TF_SIGNATURE) {
- sav = tcp_signature_getsav(m, th);
+ sav = tcp_signature_getsav(m);
if (sav == NULL && tp->t_state == TCPS_LISTEN)
return (-1);
@@ -3097,7 +3154,7 @@ tcp_dooptions(struct tcpcb *tp, const u_
}
TCP_FIELDS_TO_HOST(th);
- if (bcmp(sig, sigp, TCP_SIGLEN)) {
+ if (memcmp(sig, sigp, TCP_SIGLEN)) {
tcpstat.tcps_badsig++;
if (sav == NULL)
return (-1);
@@ -3521,8 +3578,8 @@ syn_cache_lookup(const struct sockaddr *
sc = TAILQ_NEXT(sc, sc_bucketq)) {
if (sc->sc_hash != hash)
continue;
- if (!bcmp(&sc->sc_src, src, src->sa_len) &&
- !bcmp(&sc->sc_dst, dst, dst->sa_len)) {
+ if (!memcmp(&sc->sc_src, src, src->sa_len) &&
+ !memcmp(&sc->sc_dst, dst, dst->sa_len)) {
splx(s);
return (sc);
}
@@ -3849,7 +3906,8 @@ syn_cache_get(struct sockaddr *src, stru
return (so);
resetandabort:
- (void)tcp_respond(NULL, m, m, th, (tcp_seq)0, th->th_ack, TH_RST);
+ /* XXX: TCP_SIGNATURE ? */
+ (void)tcp_respond(NULL, m, m, th, (tcp_seq)0, th->th_ack, TH_RST, 0);
abort:
if (so != NULL)
(void) soabort(so);
@@ -4334,7 +4392,7 @@ syn_cache_respond(struct syn_cache *sc,
struct secasvar *sav;
u_int8_t *sigp;
- sav = tcp_signature_getsav(m, th);
+ sav = tcp_signature_getsav(m);
if (sav == NULL) {
if (m)
Index: netinet/tcp_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
retrieving revision 1.161
diff -u -p -r1.161 tcp_output.c
--- netinet/tcp_output.c 2 Aug 2007 13:12:35 -0000 1.161
+++ netinet/tcp_output.c 14 Aug 2007 11:33:34 -0000
@@ -578,6 +578,7 @@ tcp_output(struct tcpcb *tp)
struct sackhole *p;
#ifdef TCP_SIGNATURE
int sigoff = 0;
+ struct secasvar *sav;
#endif
#ifdef DIAGNOSTIC
@@ -1152,9 +1153,16 @@ send:
cp[0] = TCPOPT_SACK_PERMITTED;
cp[1] = 2;
- cp[2] = TCPOPT_NOP;
- cp[3] = TCPOPT_NOP;
- optlen += 4;
+#ifdef TCP_SIGNATURE
+ if (tp->t_flags & TF_SIGNATURE)
+ optlen += 2;
+ else
+#endif
+ {
+ cp[2] = TCPOPT_NOP;
+ cp[3] = TCPOPT_NOP;
+ optlen += 4;
+ }
}
}
}
@@ -1220,18 +1228,19 @@ send:
* Initialize TCP-MD5 option (RFC2385)
*/
bp = (u_char *)opt + optlen;
- *bp++ = TCPOPT_SIGNATURE;
- *bp++ = TCPOLEN_SIGNATURE;
+ memset(bp, 0, TCPOLEN_SIGNATURE);
+ bp[0] = TCPOPT_SIGNATURE;
+ bp[1] = TCPOLEN_SIGNATURE;
sigoff = optlen + 2;
- bzero(bp, TCP_SIGLEN);
- bp += TCP_SIGLEN;
- optlen += TCPOLEN_SIGNATURE;
+
/*
- * Terminate options list and maintain 32-bit alignment.
+ * maintain 32-bit alignment as this looks
+ * to be our last option XXX
*/
- *bp++ = TCPOPT_NOP;
- *bp++ = TCPOPT_EOL;
- optlen += 2;
+ optlen += TCPOLEN_SIGNATURE;
+ for (bp += TCPOLEN_SIGNATURE; optlen % 4; optlen++, bp++)
+ *bp = 0;
+
}
#endif /* TCP_SIGNATURE */
@@ -1430,10 +1439,9 @@ send:
#ifdef TCP_SIGNATURE
if (sigoff && (tp->t_flags & TF_SIGNATURE)) {
- struct secasvar *sav;
u_int8_t *sigp;
- sav = tcp_signature_getsav(m, th);
+ sav = tcp_signature_getsav(m);
if (sav == NULL) {
if (m)
Index: netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.218
diff -u -p -r1.218 tcp_subr.c
--- netinet/tcp_subr.c 2 Aug 2007 02:42:41 -0000 1.218
+++ netinet/tcp_subr.c 14 Aug 2007 11:33:34 -0000
@@ -595,7 +595,7 @@ tcp_template(struct tcpcb *tp)
*/
int
tcp_respond(struct tcpcb *tp, struct mbuf *template, struct mbuf *m,
- struct tcphdr *th0, tcp_seq ack, tcp_seq seq, int flags)
+ struct tcphdr *th0, tcp_seq ack, tcp_seq seq, int flags, int opts)
{
struct route *ro;
int error, tlen, win = 0;
@@ -607,6 +607,9 @@ tcp_respond(struct tcpcb *tp, struct mbu
int family; /* family on packet, not inpcb/in6pcb! */
struct tcphdr *th;
struct socket *so;
+#ifdef TCP_SIGNATURE
+ struct secasvar *sav;
+#endif
if (tp != NULL && (flags & TH_RST) == 0) {
#ifdef DIAGNOSTIC
@@ -726,12 +729,25 @@ tcp_respond(struct tcpcb *tp, struct mbu
tlen = sizeof(*th0);
else
tlen = th0->th_off << 2;
-
+#ifdef TCP_SIGNATURE
+ if (opts & TF_SIGNATURE)
+ tlen += TCPOLEN_SIGLEN;
+#endif
if (m->m_len > hlen + tlen && (m->m_flags & M_EXT) == 0 &&
mtod(m, char *) + hlen == (char *)th0) {
m->m_len = hlen + tlen;
m_freem(m->m_next);
m->m_next = NULL;
+#ifdef TCP_SIGNATURE
+ if (opts & TF_SIGNATURE) {
+ char *sigplace;
+ sigplace = mtod(m, char*);
+ sigplace += hlen + tlen - TCPOLEN_SIGLEN;
+ memset(sigplace, 0, TCPOLEN_SIGLEN);
+ sigplace[0] = TCPOPT_SIGNATURE;
+ sigplace[1] = TCPOLEN_SIGNATURE;
+ }
+#endif
} else {
struct mbuf *n;
@@ -758,8 +774,20 @@ tcp_respond(struct tcpcb *tp, struct mbu
n->m_data += max_linkhdr;
n->m_len = hlen + tlen;
m_copyback(n, 0, hlen, mtod(m, void *));
+#ifndef TCP_SIGNATURE
m_copyback(n, hlen, tlen, (void *)th0);
-
+#else
+ if (opts & TF_SIGNATURE) {
+ char sigplace[TCPOLEN_SIGLEN];
+ m_copyback(n, hlen, tlen - TCPOLEN_SIGLEN, (void *)th0);
+ memset(sigplace, 0, TCPOLEN_SIGLEN);
+ sigplace[0] = TCPOPT_SIGNATURE;
+ sigplace[1] = TCPOLEN_SIGNATURE;
+ m_copyback(n, hlen + tlen - TCPOLEN_SIGLEN, TCPOLEN_SIGLEN,
+ (void*)sigplace);
+ } else
+ m_copyback(n, hlen, tlen, (void *)th0);
+#endif
m_freem(m);
m = n;
n = NULL;
@@ -807,12 +835,33 @@ tcp_respond(struct tcpcb *tp, struct mbu
tlen += sizeof(*th);
} else
tlen += th->th_off << 2;
+#ifdef TCP_SIGNATURE
+ /* again and again */
+ if (opts & TF_SIGNATURE) {
+ tlen += TCPOLEN_SIGLEN;
+ th->th_off += TCPOLEN_SIGLEN >> 2;
+ }
+#endif
m->m_len = hlen + tlen;
m->m_pkthdr.len = hlen + tlen;
m->m_pkthdr.rcvif = (struct ifnet *) 0;
th->th_flags = flags;
th->th_urp = 0;
-
+#ifdef TCP_SIGNATURE
+ sav = tcp_signature_getsav(m);
+ if (sav) {
+ tcp_signature(m, th, (char *)th - mtod(m, char *),
+ sav, (char*)th + (th->th_off << 2) - TCPOLEN_SIGNATURE);
+ key_sa_recordxfer(sav, m);
+#ifdef FAST_IPSEC
+ KEY_FREESAV(&sav);
+#else
+ key_freesav(sav);
+#endif
+ } else
+ memset((char*)th + (th->th_off << 2) - TCPOLEN_SIGNATURE, 0,
+ TCPOLEN_SIGNATURE);
+#endif /* TCP_SIGNATURE */
switch (family) {
#ifdef INET
case AF_INET:
Index: netinet/tcp_timer.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_timer.c,v
retrieving revision 1.77
diff -u -p -r1.77 tcp_timer.c
--- netinet/tcp_timer.c 20 Jun 2007 15:29:18 -0000 1.77
+++ netinet/tcp_timer.c 14 Aug 2007 11:33:34 -0000
@@ -569,11 +569,21 @@ tcp_timer_keep(void *arg)
*/
(void)tcp_respond(tp, tp->t_template,
(struct mbuf *)NULL, NULL, tp->rcv_nxt - 1,
- tp->snd_una - 1, 0);
+ tp->snd_una - 1, 0,
+#ifdef TCP_SIGNATURE
+ tp->t_flags & TF_SIGNATURE);
+#else
+ 0);
+#endif
} else {
(void)tcp_respond(tp, tp->t_template,
(struct mbuf *)NULL, NULL, tp->rcv_nxt,
- tp->snd_una - 1, 0);
+ tp->snd_una - 1, 0,
+#ifdef TCP_SIGNATURE
+ tp->t_flags & TF_SIGNATURE);
+#else
+ 0);
+#endif
}
TCP_TIMER_ARM(tp, TCPT_KEEP, tp->t_keepintvl);
} else
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.136
diff -u -p -r1.136 tcp_usrreq.c
--- netinet/tcp_usrreq.c 2 Aug 2007 02:42:41 -0000 1.136
+++ netinet/tcp_usrreq.c 14 Aug 2007 11:33:34 -0000
@@ -722,10 +722,10 @@ tcp_ctloutput(int op, struct socket *so,
#ifdef TCP_SIGNATURE
case TCP_MD5SIG:
- if (m == NULL || m->m_len < sizeof (int))
+ if (m == NULL || m->m_len < sizeof (int)) {
error = EINVAL;
- if (error)
break;
+ }
if (*mtod(m, int *) > 0)
tp->t_flags |= TF_SIGNATURE;
else
Index: netinet/tcp_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_var.h,v
retrieving revision 1.150
diff -u -p -r1.150 tcp_var.h
--- netinet/tcp_var.h 2 Aug 2007 02:42:42 -0000 1.150
+++ netinet/tcp_var.h 14 Aug 2007 11:33:34 -0000
@@ -851,9 +851,10 @@ struct tcpcb *
tcp_drop(struct tcpcb *, int);
#ifdef TCP_SIGNATURE
int tcp_signature_apply(void *, void *, u_int);
-struct secasvar *tcp_signature_getsav(struct mbuf *, struct tcphdr *);
+struct secasvar *tcp_signature_getsav(struct mbuf *);
int tcp_signature(struct mbuf *, struct tcphdr *, int, struct secasvar *,
char *);
+int tcp_checksignature(const u_char *, int);
#endif
void tcp_drain(void);
void tcp_established(struct tcpcb *);
@@ -886,7 +887,7 @@ struct ipqent *tcpipqent_alloc(void);
void tcpipqent_free(struct ipqent *);
int tcp_respond(struct tcpcb *, struct mbuf *, struct mbuf *,
- struct tcphdr *, tcp_seq, tcp_seq, int);
+ struct tcphdr *, tcp_seq, tcp_seq, int, int);
void tcp_rmx_rtt(struct tcpcb *);
void tcp_setpersist(struct tcpcb *);
#ifdef TCP_SIGNATURE
Index: netkey/key.c
===================================================================
RCS file: /cvsroot/src/sys/netkey/key.c,v
retrieving revision 1.156
diff -u -p -r1.156 key.c
--- netkey/key.c 9 Jul 2007 21:11:14 -0000 1.156
+++ netkey/key.c 14 Aug 2007 11:33:35 -0000
@@ -8232,7 +8232,8 @@ key_sa_routechange(dst)
LIST_FOREACH(sah, &sahtree, chain) {
ro = &sah->sa_route;
- if (dst->sa_len == rtcache_getdst(ro)->sa_len &&
+ if (sah->saidx.proto != IPPROTO_TCP &&
+ dst->sa_len == rtcache_getdst(ro)->sa_len &&
memcmp(dst, rtcache_getdst(ro), dst->sa_len) == 0)
rtcache_free(ro);
}