1 //==========================================================================
3 // sys/netinet/tcp_subr.c
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
10 // -------------------------------------------
12 // Portions of this software may have been derived from OpenBSD or other sources,
13 // and are covered by the appropriate copyright disclaimers included herein.
15 // -------------------------------------------
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
22 // Contributors: gthomas
28 //####DESCRIPTIONEND####
30 //==========================================================================
33 /* $OpenBSD: tcp_subr.c,v 1.21 1999/12/08 06:50:20 itojun Exp $ */
34 /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
37 * Copyright (c) 1982, 1986, 1988, 1990, 1993
38 * The Regents of the University of California. All rights reserved.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. All advertising materials mentioning features or use of this software
49 * must display the following acknowledgement:
50 * This product includes software developed by the University of
51 * California, Berkeley and its contributors.
52 * 4. Neither the name of the University nor the names of its contributors
53 * may be used to endorse or promote products derived from this software
54 * without specific prior written permission.
56 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
72 %%% portions-copyright-nrl-95
73 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
74 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
75 Reserved. All rights under this copyright have been assigned to the US
76 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
77 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
79 You should have received a copy of the license with this software. If you
80 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
83 #include <sys/param.h>
86 #include <sys/systm.h>
88 #include <sys/malloc.h>
90 #include <sys/socket.h>
91 #include <sys/socketvar.h>
92 #include <sys/protosw.h>
93 #include <sys/errno.h>
98 #include <net/route.h>
101 #include <netinet/in.h>
102 #include <netinet/in_systm.h>
103 #include <netinet/ip.h>
104 #include <netinet/in_pcb.h>
105 #include <netinet/ip_var.h>
106 #include <netinet/ip_icmp.h>
107 #include <netinet/tcp.h>
108 #include <netinet/tcp_fsm.h>
109 #include <netinet/tcp_seq.h>
110 #include <netinet/tcp_timer.h>
111 #include <netinet/tcp_var.h>
112 #include <netinet/tcpip.h>
114 #include <dev/rndvar.h>
118 #include <netinet6/ip6_var.h>
119 #include <netinet6/tcpipv6.h>
120 #include <sys/domain.h>
124 #include <sys/md5k.h>
125 #endif /* TCP_SIGNATURE */
127 /* patchable/settable parameters for tcp */
128 int tcp_mssdflt = TCP_MSS;
129 int tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
132 * Configure kernel with options "TCP_DO_RFC1323=0" to disable RFC1323 stuff.
133 * This is a good idea over slow SLIP/PPP links, because the timestamp
134 * pretty well destroys the VJ compression (any packet with a timestamp
135 * different from the previous one can't be compressed), as well as adding
137 * XXX And it should be a settable per route characteristic (with this just
138 * used as the default).
140 #ifndef TCP_DO_RFC1323
141 #define TCP_DO_RFC1323 1
143 int tcp_do_rfc1323 = TCP_DO_RFC1323;
147 #define TCP_DO_SACK 0 /* XXX - make this 1 when SACK is fixed */
149 #define TCP_DO_SACK 0
152 int tcp_do_sack = TCP_DO_SACK; /* RFC 2018 selective ACKs */
155 #define TCBHASHSIZE 128
157 int tcbhashsize = TCBHASHSIZE;
160 extern int ip6_defhlim;
170 tcp_iss = 1; /* wrong */
171 #else /* TCP_COMPAT_42 */
172 tcp_iss = arc4random() + 1;
173 #endif /* !TCP_COMPAT_42 */
174 in_pcbinit(&tcbtable, tcbhashsize);
178 * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
179 * do max length checks/computations only on the former.
181 if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)))
182 max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
183 if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) >
190 * Create template to be used to send tcp packets on a connection.
191 * Call after host entry created, allocates an mbuf and fills
192 * in a skeletal tcp/ip header, minimizing the amount of work
193 * necessary when the connection is used.
195 * To support IPv6 in addition to IPv4 and considering that the sizes of
196 * the IPv4 and IPv6 headers are not the same, we now use a separate pointer
197 * for the TCP header. Also, we made the former tcpiphdr header pointer
198 * into just an IP overlay pointer, with casting as appropriate for v6. rja
204 register struct inpcb *inp = tp->t_inpcb;
205 register struct mbuf *m;
206 register struct tcphdr *th = (struct tcphdr *)0;
208 if ((m = tp->t_template) == 0) {
209 m = m_get(M_DONTWAIT, MT_HEADER);
214 case 0: /*default to PF_INET*/
217 m->m_len = sizeof(struct ip);
222 m->m_len = sizeof(struct ip6_hdr);
226 m->m_len += sizeof (struct tcphdr);
229 * The link header, network header, TCP header, and TCP options
230 * all must fit in this mbuf. For now, assume the worst case of
231 * TCP options size. Eventually, compute this from tp flags.
233 if (m->m_len + MAX_TCPOPTLEN + max_linkhdr >= MHLEN) {
234 MCLGET(m, M_DONTWAIT);
235 if ((m->m_flags & M_EXT) == 0) {
246 struct ipovly *ipovly;
248 ipovly = mtod(m, struct ipovly *);
250 bzero(ipovly->ih_x1, sizeof ipovly->ih_x1);
251 ipovly->ih_pr = IPPROTO_TCP;
252 ipovly->ih_len = htons(sizeof (struct tcpiphdr) -
254 ipovly->ih_src = inp->inp_laddr;
255 ipovly->ih_dst = inp->inp_faddr;
257 th = (struct tcphdr *)(mtod(m, caddr_t) +
265 struct ip6_hdr *ipv6;
267 ipv6 = mtod(m, struct ip6_hdr *);
269 ipv6->ip6_src = inp->inp_laddr6;
270 ipv6->ip6_dst = inp->inp_faddr6;
271 ipv6->ip6_flow = htonl(0x60000000) |
272 (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff));
275 ipv6->ip6_nxt = IPPROTO_TCP;
276 ipv6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/
277 ipv6->ip6_hlim = in6_selecthlim(inp, NULL); /*XXX*/
279 th = (struct tcphdr *)(mtod(m, caddr_t) +
280 sizeof(struct ip6_hdr));
286 th->th_sport = inp->inp_lport;
287 th->th_dport = inp->inp_fport;
300 * Send a single message to the TCP at address specified by
301 * the given TCP/IP header. If m == 0, then we make a copy
302 * of the tcpiphdr at ti and send directly to the addressed host.
303 * This is used to force keep alive messages out using the TCP
304 * template for a connection tp->t_template. If flags are given
305 * then we send a message back to the TCP which originated the
306 * segment ti, and discard the mbuf containing it and any other
309 * In any case the ack and sequence number of the transmitted
310 * segment are as specified by the parameters.
313 /* This function looks hairy, because it was so IPv4-dependent. */
316 tcp_respond(tp, template, m, ack, seq, flags)
319 register struct mbuf *m;
325 struct route *ro = 0;
326 register struct tcphdr *th;
327 register struct tcpiphdr *ti = (struct tcpiphdr *)template;
329 int is_ipv6 = 0; /* true iff IPv6 */
333 win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
336 * If this is called with an unconnected
337 * socket/tp/pcb (tp->pf is 0), we lose.
339 is_ipv6 = (tp->pf == PF_INET6);
342 * The route/route6 distinction is meaningless
343 * unless you're allocating space or passing parameters.
346 ro = &tp->t_inpcb->inp_route;
350 is_ipv6 = (((struct ip *)ti)->ip_v == 6);
353 m = m_gethdr(M_DONTWAIT, MT_HEADER);
361 m->m_data += max_linkhdr;
364 bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
365 sizeof(struct ip6_hdr));
368 bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
371 ti = mtod(m, struct tcpiphdr *);
376 m->m_data = (caddr_t)ti;
378 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
381 m->m_len = sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
382 xchg(((struct ip6_hdr *)ti)->ip6_dst,\
383 ((struct ip6_hdr *)ti)->ip6_src,\
385 th = (void *)ti + sizeof(struct ip6_hdr);
389 m->m_len = sizeof (struct tcpiphdr);
390 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
391 th = (void *)((caddr_t)ti + sizeof(struct ip));
393 xchg(th->th_dport, th->th_sport, u_int16_t);
398 tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
399 th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
403 ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + tlen));
404 tlen += sizeof (struct tcpiphdr);
405 th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip));
409 m->m_pkthdr.len = tlen;
410 m->m_pkthdr.rcvif = (struct ifnet *) 0;
411 th->th_seq = htonl(seq);
412 th->th_ack = htonl(ack);
414 th->th_off = sizeof (struct tcphdr) >> 2;
415 th->th_flags = flags;
417 th->th_win = htons((u_int16_t) (win >> tp->rcv_scale));
419 th->th_win = htons((u_int16_t)win);
424 ((struct ip6_hdr *)ti)->ip6_flow = htonl(0x60000000);
425 ((struct ip6_hdr *)ti)->ip6_nxt = IPPROTO_TCP;
426 ((struct ip6_hdr *)ti)->ip6_hlim =
427 in6_selecthlim(tp ? tp->t_inpcb : NULL, NULL); /*XXX*/
428 ((struct ip6_hdr *)ti)->ip6_plen = tlen - sizeof(struct ip6_hdr);
430 th->th_sum = in6_cksum(m, IPPROTO_TCP,
431 sizeof(struct ip6_hdr), ((struct ip6_hdr *)ti)->ip6_plen);
432 HTONS(((struct ip6_hdr *)ti)->ip6_plen);
433 ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL,
434 (struct route_in6 *)ro, 0, NULL, NULL);
438 bzero(ti->ti_x1, sizeof ti->ti_x1);
439 ti->ti_len = htons((u_short)tlen - sizeof(struct ip));
440 th->th_sum = in_cksum(m, tlen);
441 ((struct ip *)ti)->ip_len = tlen;
442 ((struct ip *)ti)->ip_ttl = ip_defttl;
443 ip_output(m, NULL, ro, 0, NULL, tp ? tp->t_inpcb : NULL);
448 * Create a new TCP control block, making an
449 * empty reassembly queue and hooking it to the argument
450 * protocol control block.
456 register struct tcpcb *tp;
458 tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT);
460 return ((struct tcpcb *)0);
461 bzero((char *) tp, sizeof(struct tcpcb));
462 LIST_INIT(&tp->segq);
463 tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
466 tp->sack_disable = tcp_do_sack ? 0 : 1;
468 tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
471 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
472 * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
473 * reasonable initial retransmit time.
475 tp->t_srtt = TCPTV_SRTTBASE;
476 tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << (TCP_RTTVAR_SHIFT + 2 - 1);
477 tp->t_rttmin = TCPTV_MIN;
478 TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
479 TCPTV_MIN, TCPTV_REXMTMAX);
480 tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
481 tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
484 * If we want to use tp->pf for a quick-n-easy way to determine
485 * the outbound dgram type, we cannot make this decision
486 * until a connection is established! Bzero() sets pf to zero, and
487 * that's the way we want it, unless, of course, it's an AF_INET
490 if ((inp->inp_flags & INP_IPV6) == 0)
491 tp->pf = PF_INET; /* If AF_INET socket, we can't do v6 from it. */
497 if (inp->inp_flags & INP_IPV6)
498 inp->inp_ipv6.ip6_hlim = ip6_defhlim;
501 inp->inp_ip.ip_ttl = ip_defttl;
503 inp->inp_ppcb = (caddr_t)tp;
508 * Drop a TCP connection, reporting
509 * the specified error. If connection is synchronized,
510 * then send a RST to peer.
514 register struct tcpcb *tp;
517 struct socket *so = tp->t_inpcb->inp_socket;
519 if (TCPS_HAVERCVDSYN(tp->t_state)) {
520 tp->t_state = TCPS_CLOSED;
521 (void) tcp_output(tp);
522 tcpstat.tcps_drops++;
524 tcpstat.tcps_conndrops++;
525 if (errno == ETIMEDOUT && tp->t_softerror)
526 errno = tp->t_softerror;
527 so->so_error = errno;
528 return (tcp_close(tp));
532 * Close a TCP control block:
533 * discard all space held by the tcp
534 * discard internet protocol block
535 * wake up any sleepers
539 register struct tcpcb *tp;
541 register struct ipqent *qe;
542 struct inpcb *inp = tp->t_inpcb;
543 struct socket *so = inp->inp_socket;
545 struct sackhole *p, *q;
548 register struct rtentry *rt;
550 register int bound_to_specific = 0; /* I.e. non-default */
553 * This code checks the nature of the route for this connection.
554 * Normally this is done by two simple checks in the next
555 * INET/INET6 ifdef block, but because of two possible lower layers,
556 * that check is done here.
558 * Perhaps should be doing this only for a RTF_HOST route.
560 rt = inp->inp_route.ro_rt; /* Same for route or route6. */
561 if (tp->pf == PF_INET6) {
564 !(IN6_IS_ADDR_UNSPECIFIED(&
565 ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr));
569 (((struct sockaddr_in *)rt_key(rt))->
570 sin_addr.s_addr != INADDR_ANY);
575 * If we sent enough data to get some meaningful characteristics,
576 * save them in the routing entry. 'Enough' is arbitrarily
577 * defined as the sendpipesize (default 4K) * 16. This would
578 * give us 16 rtt samples assuming we only get one sample per
579 * window (the usual case on a long haul net). 16 samples is
580 * enough for the srtt filter to converge to within 5% of the correct
581 * value; fewer samples and we could save a very bogus rtt.
583 * Don't update the default route's characteristics and don't
584 * update anything that the user "locked".
588 * Note that rt and bound_to_specific are set above.
590 if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
591 rt && bound_to_specific) {
593 if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
594 (rt = inp->inp_route.ro_rt) &&
595 satosin(rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
597 register u_long i = 0;
599 if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
601 (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
602 if (rt->rt_rmx.rmx_rtt && i)
604 * filter this update to half the old & half
605 * the new values, converting scale.
606 * See route.h and tcp_var.h for a
607 * description of the scaling constants.
610 (rt->rt_rmx.rmx_rtt + i) / 2;
612 rt->rt_rmx.rmx_rtt = i;
614 if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
616 (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
617 if (rt->rt_rmx.rmx_rttvar && i)
618 rt->rt_rmx.rmx_rttvar =
619 (rt->rt_rmx.rmx_rttvar + i) / 2;
621 rt->rt_rmx.rmx_rttvar = i;
624 * update the pipelimit (ssthresh) if it has been updated
625 * already or if a pipesize was specified & the threshhold
626 * got below half the pipesize. I.e., wait for bad news
627 * before we start updating, then update on both good
630 if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
631 (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh) ||
632 i < (rt->rt_rmx.rmx_sendpipe / 2)) {
634 * convert the limit from user data bytes to
635 * packets then to packet data bytes.
637 i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
641 if (tp->pf == PF_INET6)
642 i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)
643 + sizeof(struct ip6_hdr));
646 i *= (u_long)(tp->t_maxseg +
647 sizeof (struct tcpiphdr));
649 if (rt->rt_rmx.rmx_ssthresh)
650 rt->rt_rmx.rmx_ssthresh =
651 (rt->rt_rmx.rmx_ssthresh + i) / 2;
653 rt->rt_rmx.rmx_ssthresh = i;
658 /* free the reassembly queue, if any */
660 /* Reassembling TCP segments in v6 might be sufficiently different
661 * to merit two codepaths to free the reasssembly queue.
662 * If an undecided TCP socket, then the IPv4 codepath will be used
663 * because it won't matter much anyway.
665 if (tp->pf == AF_INET6) {
666 while ((qe = tp->segq.lh_first) != NULL) {
667 LIST_REMOVE(qe, ipqe_q);
673 while ((qe = tp->segq.lh_first) != NULL) {
674 LIST_REMOVE(qe, ipqe_q);
679 /* Free SACK holes. */
680 q = p = tp->snd_holes;
688 (void) m_free(tp->t_template);
691 soisdisconnected(so);
693 tcpstat.tcps_closed++;
694 return ((struct tcpcb *)0);
704 * Notify a tcp user of an asynchronous error;
705 * store error as soft error, but wake up user
706 * (for now, won't do anything until can select for soft error).
709 tcp_notify(inp, error)
713 register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
714 register struct socket *so = inp->inp_socket;
717 * Ignore some errors if we are hooked up.
718 * If connection hasn't completed, has retransmitted several times,
719 * and receives a second error, give up now. This is better
720 * than waiting a long time to establish a connection that
721 * can never complete.
723 if (tp->t_state == TCPS_ESTABLISHED &&
724 (error == EHOSTUNREACH || error == ENETUNREACH ||
725 error == EHOSTDOWN)) {
727 } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
728 tp->t_rxtshift > 3 && tp->t_softerror)
729 so->so_error = error;
731 tp->t_softerror = error;
732 wakeup((caddr_t) &so->so_timeo);
737 #if defined(INET6) && !defined(TCP6)
739 tcp6_ctlinput(cmd, sa, d)
744 (void)tcp_ctlinput(cmd, sa, NULL); /*XXX*/
749 tcp_ctlinput(cmd, sa, v)
754 register struct ip *ip = v;
755 register struct tcphdr *th;
756 extern int inetctlerrmap[];
757 void (*notify) __P((struct inpcb *, int)) = tcp_notify;
760 if ((unsigned)cmd >= PRC_NCMDS)
762 errno = inetctlerrmap[cmd];
763 if (cmd == PRC_QUENCH)
765 else if (PRC_IS_REDIRECT(cmd))
766 notify = in_rtchange, ip = 0;
767 else if (cmd == PRC_HOSTDEAD)
773 if (sa->sa_family == AF_INET6) {
775 struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
777 th = (struct tcphdr *)(ipv6 + 1);
779 in6_pcbnotify(&tcbtable, sa, th->th_dport,
780 &ipv6->ip6_src, th->th_sport, cmd, notify);
784 in6_pcbnotify(&tcbtable, sa, 0,
785 (struct in6_addr *)&in6addr_any, 0, cmd, notify);
792 th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
793 in_pcbnotify(&tcbtable, sa, th->th_dport, ip->ip_src,
794 th->th_sport, errno, notify);
796 in_pcbnotifyall(&tcbtable, sa, errno, notify);
802 * When a source quench is received, close congestion window
803 * to one segment. We will gradually open it again as we proceed.
806 tcp_quench(inp, errno)
810 struct tcpcb *tp = intotcpcb(inp);
813 tp->snd_cwnd = tp->t_maxseg;
818 tcp_signature_tdb_attach()
824 tcp_signature_tdb_init(tdbp, xsp, ii)
827 struct ipsecinit *ii;
830 #define isdigit(c) (((c) >= '0') && ((c) <= '9'))
831 #define isalpha(c) ( (((c) >= 'A') && ((c) <= 'Z')) || \
832 (((c) >= 'a') && ((c) <= 'z')) )
834 if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))
837 c = (char *)ii->ii_authkey;
839 while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {
851 if (!isdigit(*c) && !isalpha(*c))
854 tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
855 if (tdbp->tdb_amxkey == NULL)
857 bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
858 tdbp->tdb_amxkeylen = ii->ii_authkeylen;
864 tcp_signature_tdb_zeroize(tdbp)
867 if (tdbp->tdb_amxkey) {
868 bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
869 free(tdbp->tdb_amxkey, M_XDATA);
870 tdbp->tdb_amxkey = NULL;
877 tcp_signature_tdb_input(m, tdbp)
885 tcp_signature_tdb_output(m, tdbp, mp)
894 tcp_signature_apply(fstate, data, len)
899 MD5Update((MD5_CTX *)fstate, (char *)data, len);
902 #endif /* TCP_SIGNATURE */