Index: sys/netinet/tcp_input.c =================================================================== --- sys/netinet/tcp_input.c (revision 183001) +++ sys/netinet/tcp_input.c (working copy) @@ -163,7 +163,7 @@ static void tcp_do_segment(struct mbuf *, struct tcphdr *, struct socket *, struct tcpcb *, int, int, uint8_t); static void tcp_dropwithreset(struct mbuf *, struct tcphdr *, - struct tcpcb *, int, int); + struct tcpcb *, int, int, u_int); static void tcp_pulloutofband(struct socket *, struct tcphdr *, struct mbuf *, int); static void tcp_xmit_timer(struct tcpcb *, int); @@ -885,7 +885,7 @@ dropwithreset: INP_INFO_WLOCK_ASSERT(&V_tcbinfo); - tcp_dropwithreset(m, th, tp, tlen, rstreason); + tcp_dropwithreset(m, th, tp, tlen, rstreason, 0); m = NULL; /* mbuf chain got consumed. */ dropunlock: INP_INFO_WLOCK_ASSERT(&V_tcbinfo); @@ -909,6 +909,7 @@ int headlocked = 1; int rstreason, todrop, win; u_long tiwin; + u_int t_flags = 0; struct tcpopt to; #ifdef TCPDEBUG @@ -1656,6 +1657,13 @@ s, __func__, tcpstates[tp->t_state], tlen); free(s, M_TCPLOG); } +#ifdef TCP_SIGNATURE + /* + * We need to remember this flag, + * so a RST can go out signed if needed. + */ + t_flags |= tp->t_flags & TF_SIGNATURE; +#endif tp = tcp_close(tp); V_tcpstat.tcps_rcvafterclose++; rstreason = BANDLIM_UNLIMITED; @@ -2472,7 +2480,7 @@ dropwithreset: KASSERT(headlocked, ("%s: dropwithreset: head not locked", __func__)); - tcp_dropwithreset(m, th, tp, tlen, rstreason); + tcp_dropwithreset(m, th, tp, tlen, rstreason, t_flags); if (tp != NULL) INP_WUNLOCK(tp->t_inpcb); @@ -2504,7 +2512,7 @@ */ static void tcp_dropwithreset(struct mbuf *m, struct tcphdr *th, struct tcpcb *tp, - int tlen, int rstreason) + int tlen, int rstreason, u_int t_flags) { struct ip *ip; #ifdef INET6 @@ -2543,12 +2551,12 @@ /* tcp_respond consumes the mbuf chain. */ if (th->th_flags & TH_ACK) { tcp_respond(tp, mtod(m, void *), th, m, (tcp_seq)0, - th->th_ack, TH_RST); + th->th_ack, TH_RST, t_flags); } else { if (th->th_flags & TH_SYN) tlen++; tcp_respond(tp, mtod(m, void *), th, m, th->th_seq+tlen, - (tcp_seq)0, TH_RST|TH_ACK); + (tcp_seq)0, TH_RST|TH_ACK, t_flags); } return; drop: Index: sys/netinet/tcp_subr.c =================================================================== --- sys/netinet/tcp_subr.c (revision 183001) +++ sys/netinet/tcp_subr.c (working copy) @@ -448,7 +448,7 @@ */ void tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, - tcp_seq ack, tcp_seq seq, int flags) + tcp_seq ack, tcp_seq seq, int flags, u_int t_flags) { int tlen; int win = 0; @@ -460,6 +460,11 @@ #endif /* INET6 */ int ipflags = 0; struct inpcb *inp; +#ifdef TCP_SIGNATURE + u_char opt[TCP_MAXOLEN]; + struct tcpopt to; +#endif + unsigned optlen = 0; KASSERT(tp != NULL || m != NULL, ("tcp_respond: tp and m both NULL")); @@ -482,7 +487,18 @@ if (win > (long)TCP_MAXWIN << tp->rcv_scale) win = (long)TCP_MAXWIN << tp->rcv_scale; } +#ifdef TCP_SIGNATURE + t_flags |= tp->t_flags & TF_SIGNATURE; +#endif } +#ifdef TCP_SIGNATURE + /* TCP-MD5 (RFC2385). */ + to.to_flags = 0; + if (t_flags & TF_SIGNATURE) + to.to_flags |= TOF_SIGNATURE; + /* Processing the options. */ + optlen = tcp_addoptions(&to, opt); +#endif /* TCP_SIGNATURE */ if (m == NULL) { m = m_gethdr(M_DONTWAIT, MT_DATA); if (m == NULL) @@ -534,21 +550,22 @@ nth->th_sport = th->th_sport; nth->th_dport = th->th_dport; } - xchg(nth->th_dport, nth->th_sport, n_short); + } + xchg(nth->th_dport, nth->th_sport, n_short); #undef xchg - } #ifdef INET6 if (isipv6) { ip6->ip6_flow = 0; ip6->ip6_vfc = IPV6_VERSION; ip6->ip6_nxt = IPPROTO_TCP; ip6->ip6_plen = htons((u_short)(sizeof (struct tcphdr) + - tlen)); - tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr); + tlen + optlen)); + tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr) + + optlen; } else #endif { - tlen += sizeof (struct tcpiphdr); + tlen += sizeof (struct tcpiphdr) + optlen; ip->ip_len = tlen; ip->ip_ttl = V_ip_defttl; if (V_path_mtu_discovery) @@ -576,13 +593,23 @@ nth->th_seq = htonl(seq); nth->th_ack = htonl(ack); nth->th_x2 = 0; - nth->th_off = sizeof (struct tcphdr) >> 2; + nth->th_off = (sizeof (struct tcphdr) + optlen) >> 2; nth->th_flags = flags; if (tp != NULL) nth->th_win = htons((u_short) (win >> tp->rcv_scale)); else nth->th_win = htons((u_short)win); nth->th_urp = 0; +#ifdef TCP_SIGNATURE + if (optlen <= MHLEN - tlen - max_linkhdr && + optlen && t_flags & TF_SIGNATURE) { + int sigoff = to.to_signature - opt; + tcp_signature_compute(m, 0, 0, optlen, + (u_char *)opt + sigoff, IPSEC_DIR_OUTBOUND); + + bcopy(opt, (u_char *)(nth + 1), optlen); + } +#endif #ifdef INET6 if (isipv6) { nth->th_sum = 0; Index: sys/netinet/tcp_timer.c =================================================================== --- sys/netinet/tcp_timer.c (revision 183001) +++ sys/netinet/tcp_timer.c (working copy) @@ -313,7 +313,7 @@ if (t_template) { tcp_respond(tp, t_template->tt_ipgen, &t_template->tt_t, (struct mbuf *)NULL, - tp->rcv_nxt, tp->snd_una - 1, 0); + tp->rcv_nxt, tp->snd_una - 1, 0, 0); free(t_template, M_TEMP); } callout_reset(&tp->t_timers->tt_keep, tcp_keepintvl, tcp_timer_keep, tp); Index: sys/netinet/tcp_var.h =================================================================== --- sys/netinet/tcp_var.h (revision 183001) +++ sys/netinet/tcp_var.h (working copy) @@ -293,6 +293,7 @@ u_int32_t ts_offset; /* our timestamp offset */ u_long t_starttime; int tw_time; + int t_signature; /* flag to save TF_SIGNATURE */ TAILQ_ENTRY(tcptw) tw_2msl; }; @@ -557,12 +558,11 @@ tcp_newtcpcb(struct inpcb *); int tcp_output(struct tcpcb *); void tcp_respond(struct tcpcb *, void *, - struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int); + struct tcphdr *, struct mbuf *, tcp_seq, tcp_seq, int, u_int); void tcp_tw_init(void); void tcp_tw_zone_change(void); int tcp_twcheck(struct inpcb *, struct tcpopt *, struct tcphdr *, struct mbuf *, int); -int tcp_twrespond(struct tcptw *, int); void tcp_setpersist(struct tcpcb *); #ifdef TCP_SIGNATURE int tcp_signature_compute(struct mbuf *, int, int, int, u_char *, u_int); Index: sys/netinet/ip_fw2.c =================================================================== --- sys/netinet/ip_fw2.c (revision 183001) +++ sys/netinet/ip_fw2.c (working copy) @@ -718,7 +718,7 @@ * The data in it is never read so we don't need * to correct the offsets or anything */ - tcp_respond(NULL, ip6, tcp, m, ack, seq, flags); + tcp_respond(NULL, ip6, tcp, m, ack, seq, flags, 0); } else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */ #if 0 /* Index: sys/netinet/tcp_timewait.c =================================================================== --- sys/netinet/tcp_timewait.c (revision 183001) +++ sys/netinet/tcp_timewait.c (working copy) @@ -34,6 +34,7 @@ #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ipsec.h" #include "opt_mac.h" #include "opt_tcpdebug.h" @@ -89,6 +90,10 @@ #endif #include +#ifdef IPSEC +#include +#endif /*IPSEC*/ + #include #include @@ -106,6 +111,7 @@ static void tcp_tw_2msl_reset(struct tcptw *, int); static void tcp_tw_2msl_stop(struct tcptw *); +static int tcp_twrespond(struct tcptw *, int); static int tcptw_auto_size(void) @@ -224,6 +230,10 @@ tw->t_recent = 0; tw->ts_offset = 0; } + if (tp->t_flags & TF_SIGNATURE) + tw->t_signature = 1; + else + tw->t_signature = 0; tw->snd_nxt = tp->snd_nxt; tw->rcv_nxt = tp->rcv_nxt; @@ -326,6 +336,7 @@ #else const int isipv6 = 0; #endif + u_int t_flags = 0; /* tcbinfo lock required for tcp_twclose(), tcp_tw_2msl_reset(). */ INP_INFO_WLOCK_ASSERT(&V_tcbinfo); @@ -434,13 +445,17 @@ in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) goto drop; } +#ifdef TCP_SIGNATURE + if (tw->t_signature) + t_flags |= TF_SIGNATURE; +#endif if (thflags & TH_ACK) { tcp_respond(NULL, - mtod(m, void *), th, m, 0, th->th_ack, TH_RST); + mtod(m, void *), th, m, 0, th->th_ack, TH_RST, t_flags); } else { seq = th->th_seq + (thflags & TH_SYN ? 1 : 0); tcp_respond(NULL, - mtod(m, void *), th, m, seq, 0, TH_RST|TH_ACK); + mtod(m, void *), th, m, seq, 0, TH_RST|TH_ACK, t_flags); } INP_WUNLOCK(inp); return (0); @@ -518,7 +533,7 @@ uma_zfree(tcptw_zone, tw); } -int +static int tcp_twrespond(struct tcptw *tw, int flags) { struct inpcb *inp = tw->tw_inpcb; @@ -569,6 +584,11 @@ to.to_tsval = ticks + tw->ts_offset; to.to_tsecr = tw->t_recent; } +#ifdef TCP_SIGNATURE + /* TCP-MD5 (RFC2385). */ + if (tw->t_signature) + to.to_flags |= TOF_SIGNATURE; +#endif /* TCP_SIGNATURE */ optlen = tcp_addoptions(&to, (u_char *)(th + 1)); m->m_len = hdrlen + optlen; @@ -582,6 +602,13 @@ th->th_flags = flags; th->th_win = htons(tw->last_win); +#ifdef TCP_SIGNATURE + if (tw->t_signature) { + int sigoff = to.to_signature - (u_char *)(th + 1); + tcp_signature_compute(m, 0, 0, optlen, + (u_char *)(th + 1) + sigoff, IPSEC_DIR_OUTBOUND); + } +#endif #ifdef INET6 if (isipv6) { th->th_sum = in6_cksum(m, IPPROTO_TCP, sizeof(struct ip6_hdr),