1 /* $OpenBSD: tcp_subr.c,v 1.25 2000/03/21 04:53:13 angelos Exp $ */
2 /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
5 * Copyright (c) 1982, 1986, 1988, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)tcp_subr.c 8.1 (Berkeley) 6/10/93
40 %%% portions-copyright-nrl-95
41 Portions of this software are Copyright 1995-1998 by Randall Atkinson,
42 Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
43 Reserved. All rights under this copyright have been assigned to the US
44 Naval Research Laboratory (NRL). The NRL Copyright Notice and License
45 Agreement Version 1.1 (January 17, 1995) applies to these portions of the
47 You should have received a copy of the license with this software. If you
48 didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
51 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/malloc.h>
56 #include <sys/socket.h>
57 #include <sys/socketvar.h>
58 #include <sys/protosw.h>
59 #include <sys/errno.h>
61 #include <net/route.h>
64 #include <netinet/in.h>
65 #include <netinet/in_systm.h>
66 #include <netinet/ip.h>
67 #include <netinet/in_pcb.h>
68 #include <netinet/ip_var.h>
69 #include <netinet/ip_icmp.h>
70 #include <netinet/tcp.h>
71 #include <netinet/tcp_fsm.h>
72 #include <netinet/tcp_seq.h>
73 #include <netinet/tcp_timer.h>
74 #include <netinet/tcp_var.h>
75 #include <netinet/tcpip.h>
77 #include <dev/rndvar.h>
81 #include <netinet6/ip6_var.h>
82 #include <netinet6/tcpipv6.h>
83 #include <sys/domain.h>
88 #endif /* TCP_SIGNATURE */
90 /* patchable/settable parameters for tcp */
91 int tcp_mssdflt
= TCP_MSS
;
92 int tcp_rttdflt
= TCPTV_SRTTDFLT
/ PR_SLOWHZ
;
95 * Configure kernel with options "TCP_DO_RFC1323=0" to disable RFC1323 stuff.
96 * This is a good idea over slow SLIP/PPP links, because the timestamp
97 * pretty well destroys the VJ compression (any packet with a timestamp
98 * different from the previous one can't be compressed), as well as adding
100 * XXX And it should be a settable per route characteristic (with this just
101 * used as the default).
103 #ifndef TCP_DO_RFC1323
104 #define TCP_DO_RFC1323 1
106 int tcp_do_rfc1323
= TCP_DO_RFC1323
;
110 #define TCP_DO_SACK 1
112 #define TCP_DO_SACK 0
115 int tcp_do_sack
= TCP_DO_SACK
; /* RFC 2018 selective ACKs */
118 #define TCBHASHSIZE 128
120 int tcbhashsize
= TCBHASHSIZE
;
123 extern int ip6_defhlim
;
133 tcp_iss
= 1; /* wrong */
134 #else /* TCP_COMPAT_42 */
135 tcp_iss
= arc4random() + 1;
136 #endif /* !TCP_COMPAT_42 */
137 in_pcbinit(&tcbtable
, tcbhashsize
);
141 * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
142 * do max length checks/computations only on the former.
144 if (max_protohdr
< (sizeof(struct ip6_hdr
) + sizeof(struct tcphdr
)))
145 max_protohdr
= (sizeof(struct ip6_hdr
) + sizeof(struct tcphdr
));
146 if ((max_linkhdr
+ sizeof(struct ip6_hdr
) + sizeof(struct tcphdr
)) >
153 * Create template to be used to send tcp packets on a connection.
154 * Call after host entry created, allocates an mbuf and fills
155 * in a skeletal tcp/ip header, minimizing the amount of work
156 * necessary when the connection is used.
158 * To support IPv6 in addition to IPv4 and considering that the sizes of
159 * the IPv4 and IPv6 headers are not the same, we now use a separate pointer
160 * for the TCP header. Also, we made the former tcpiphdr header pointer
161 * into just an IP overlay pointer, with casting as appropriate for v6. rja
167 register struct inpcb
*inp
= tp
->t_inpcb
;
168 register struct mbuf
*m
;
169 register struct tcphdr
*th
;
171 if ((m
= tp
->t_template
) == 0) {
172 m
= m_get(M_DONTWAIT
, MT_HEADER
);
177 case 0: /*default to PF_INET*/
180 m
->m_len
= sizeof(struct ip
);
185 m
->m_len
= sizeof(struct ip6_hdr
);
189 m
->m_len
+= sizeof (struct tcphdr
);
192 * The link header, network header, TCP header, and TCP options
193 * all must fit in this mbuf. For now, assume the worst case of
194 * TCP options size. Eventually, compute this from tp flags.
196 if (m
->m_len
+ MAX_TCPOPTLEN
+ max_linkhdr
>= MHLEN
) {
197 MCLGET(m
, M_DONTWAIT
);
198 if ((m
->m_flags
& M_EXT
) == 0) {
209 struct ipovly
*ipovly
;
211 ipovly
= mtod(m
, struct ipovly
*);
213 bzero(ipovly
->ih_x1
, sizeof ipovly
->ih_x1
);
214 ipovly
->ih_pr
= IPPROTO_TCP
;
215 ipovly
->ih_len
= htons(sizeof (struct tcpiphdr
) -
217 ipovly
->ih_src
= inp
->inp_laddr
;
218 ipovly
->ih_dst
= inp
->inp_faddr
;
220 th
= (struct tcphdr
*)(mtod(m
, caddr_t
) +
228 struct ip6_hdr
*ipv6
;
230 ipv6
= mtod(m
, struct ip6_hdr
*);
232 ipv6
->ip6_src
= inp
->inp_laddr6
;
233 ipv6
->ip6_dst
= inp
->inp_faddr6
;
234 ipv6
->ip6_flow
= htonl(0x60000000) |
235 (inp
->inp_ipv6
.ip6_flow
& htonl(0x0fffffff));
238 ipv6
->ip6_nxt
= IPPROTO_TCP
;
239 ipv6
->ip6_plen
= htons(sizeof(struct tcphdr
)); /*XXX*/
240 ipv6
->ip6_hlim
= in6_selecthlim(inp
, NULL
); /*XXX*/
242 th
= (struct tcphdr
*)(mtod(m
, caddr_t
) +
243 sizeof(struct ip6_hdr
));
249 th
->th_sport
= inp
->inp_lport
;
250 th
->th_dport
= inp
->inp_fport
;
263 * Send a single message to the TCP at address specified by
264 * the given TCP/IP header. If m == 0, then we make a copy
265 * of the tcpiphdr at ti and send directly to the addressed host.
266 * This is used to force keep alive messages out using the TCP
267 * template for a connection tp->t_template. If flags are given
268 * then we send a message back to the TCP which originated the
269 * segment ti, and discard the mbuf containing it and any other
272 * In any case the ack and sequence number of the transmitted
273 * segment are as specified by the parameters.
276 /* This function looks hairy, because it was so IPv4-dependent. */
279 tcp_respond(tp
, template, m
, ack
, seq
, flags
)
282 register struct mbuf
*m
;
288 struct route
*ro
= 0;
289 register struct tcphdr
*th
;
290 register struct tcpiphdr
*ti
= (struct tcpiphdr
*)template;
292 int is_ipv6
= 0; /* true iff IPv6 */
296 win
= sbspace(&tp
->t_inpcb
->inp_socket
->so_rcv
);
299 * If this is called with an unconnected
300 * socket/tp/pcb (tp->pf is 0), we lose.
302 is_ipv6
= (tp
->pf
== PF_INET6
);
305 * The route/route6 distinction is meaningless
306 * unless you're allocating space or passing parameters.
309 ro
= &tp
->t_inpcb
->inp_route
;
313 is_ipv6
= (((struct ip
*)ti
)->ip_v
== 6);
316 m
= m_gethdr(M_DONTWAIT
, MT_HEADER
);
324 m
->m_data
+= max_linkhdr
;
327 bcopy(ti
, mtod(m
, caddr_t
), sizeof(struct tcphdr
) +
328 sizeof(struct ip6_hdr
));
331 bcopy(ti
, mtod(m
, caddr_t
), sizeof(struct tcphdr
) +
334 ti
= mtod(m
, struct tcpiphdr
*);
339 m
->m_data
= (caddr_t
)ti
;
341 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
344 m
->m_len
= sizeof(struct tcphdr
) + sizeof(struct ip6_hdr
);
345 xchg(((struct ip6_hdr
*)ti
)->ip6_dst
,\
346 ((struct ip6_hdr
*)ti
)->ip6_src
,\
348 th
= (void *)ti
+ sizeof(struct ip6_hdr
);
352 m
->m_len
= sizeof (struct tcpiphdr
);
353 xchg(ti
->ti_dst
.s_addr
, ti
->ti_src
.s_addr
, u_int32_t
);
354 th
= (void *)ti
+ sizeof(struct ip
);
356 xchg(th
->th_dport
, th
->th_sport
, u_int16_t
);
361 tlen
+= sizeof(struct tcphdr
) + sizeof(struct ip6_hdr
);
362 th
= (struct tcphdr
*)((caddr_t
)ti
+ sizeof(struct ip6_hdr
));
366 ti
->ti_len
= htons((u_int16_t
)(sizeof (struct tcphdr
) + tlen
));
367 tlen
+= sizeof (struct tcpiphdr
);
368 th
= (struct tcphdr
*)((caddr_t
)ti
+ sizeof(struct ip
));
372 m
->m_pkthdr
.len
= tlen
;
373 m
->m_pkthdr
.rcvif
= (struct ifnet
*) 0;
374 th
->th_seq
= htonl(seq
);
375 th
->th_ack
= htonl(ack
);
377 th
->th_off
= sizeof (struct tcphdr
) >> 2;
378 th
->th_flags
= flags
;
380 win
>>= tp
->rcv_scale
;
381 if (win
> TCP_MAXWIN
)
383 th
->th_win
= htons((u_int16_t
)win
);
388 ((struct ip6_hdr
*)ti
)->ip6_flow
= htonl(0x60000000);
389 ((struct ip6_hdr
*)ti
)->ip6_nxt
= IPPROTO_TCP
;
390 ((struct ip6_hdr
*)ti
)->ip6_hlim
=
391 in6_selecthlim(tp
? tp
->t_inpcb
: NULL
, NULL
); /*XXX*/
392 ((struct ip6_hdr
*)ti
)->ip6_plen
= tlen
- sizeof(struct ip6_hdr
);
394 th
->th_sum
= in6_cksum(m
, IPPROTO_TCP
,
395 sizeof(struct ip6_hdr
), ((struct ip6_hdr
*)ti
)->ip6_plen
);
396 HTONS(((struct ip6_hdr
*)ti
)->ip6_plen
);
397 ip6_output(m
, tp
? tp
->t_inpcb
->inp_outputopts6
: NULL
,
398 (struct route_in6
*)ro
, 0, NULL
, NULL
);
402 bzero(ti
->ti_x1
, sizeof ti
->ti_x1
);
403 ti
->ti_len
= htons((u_short
)tlen
- sizeof(struct ip
));
404 th
->th_sum
= in_cksum(m
, tlen
);
405 ((struct ip
*)ti
)->ip_len
= tlen
;
406 ((struct ip
*)ti
)->ip_ttl
= ip_defttl
;
407 ip_output(m
, NULL
, ro
, 0, NULL
, tp
? tp
->t_inpcb
: NULL
);
412 * Create a new TCP control block, making an
413 * empty reassembly queue and hooking it to the argument
414 * protocol control block.
420 register struct tcpcb
*tp
;
422 tp
= malloc(sizeof(*tp
), M_PCB
, M_NOWAIT
);
424 return ((struct tcpcb
*)0);
425 bzero((char *) tp
, sizeof(struct tcpcb
));
426 LIST_INIT(&tp
->segq
);
427 tp
->t_maxseg
= tp
->t_maxopd
= tcp_mssdflt
;
430 tp
->sack_disable
= tcp_do_sack
? 0 : 1;
432 tp
->t_flags
= tcp_do_rfc1323
? (TF_REQ_SCALE
|TF_REQ_TSTMP
) : 0;
435 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
436 * rtt estimate. Set rttvar so that srtt + 2 * rttvar gives
437 * reasonable initial retransmit time.
439 tp
->t_srtt
= TCPTV_SRTTBASE
;
440 tp
->t_rttvar
= tcp_rttdflt
* PR_SLOWHZ
<< (TCP_RTTVAR_SHIFT
+ 2 - 1);
441 tp
->t_rttmin
= TCPTV_MIN
;
442 TCPT_RANGESET(tp
->t_rxtcur
, TCP_REXMTVAL(tp
),
443 TCPTV_MIN
, TCPTV_REXMTMAX
);
444 tp
->snd_cwnd
= TCP_MAXWIN
<< TCP_MAX_WINSHIFT
;
445 tp
->snd_ssthresh
= TCP_MAXWIN
<< TCP_MAX_WINSHIFT
;
448 * If we want to use tp->pf for a quick-n-easy way to determine
449 * the outbound dgram type, we cannot make this decision
450 * until a connection is established! Bzero() sets pf to zero, and
451 * that's the way we want it, unless, of course, it's an AF_INET
454 if ((inp
->inp_flags
& INP_IPV6
) == 0)
455 tp
->pf
= PF_INET
; /* If AF_INET socket, we can't do v6 from it. */
461 if (inp
->inp_flags
& INP_IPV6
)
462 inp
->inp_ipv6
.ip6_hlim
= ip6_defhlim
;
465 inp
->inp_ip
.ip_ttl
= ip_defttl
;
467 inp
->inp_ppcb
= (caddr_t
)tp
;
472 * Drop a TCP connection, reporting
473 * the specified error. If connection is synchronized,
474 * then send a RST to peer.
478 register struct tcpcb
*tp
;
481 struct socket
*so
= tp
->t_inpcb
->inp_socket
;
483 if (TCPS_HAVERCVDSYN(tp
->t_state
)) {
484 tp
->t_state
= TCPS_CLOSED
;
485 (void) tcp_output(tp
);
486 tcpstat
.tcps_drops
++;
488 tcpstat
.tcps_conndrops
++;
489 if (errno
== ETIMEDOUT
&& tp
->t_softerror
)
490 errno
= tp
->t_softerror
;
491 so
->so_error
= errno
;
492 return (tcp_close(tp
));
496 * Close a TCP control block:
497 * discard all space held by the tcp
498 * discard internet protocol block
499 * wake up any sleepers
503 register struct tcpcb
*tp
;
505 register struct ipqent
*qe
;
506 struct inpcb
*inp
= tp
->t_inpcb
;
507 struct socket
*so
= inp
->inp_socket
;
509 struct sackhole
*p
, *q
;
512 register struct rtentry
*rt
;
514 register int bound_to_specific
= 0; /* I.e. non-default */
517 * This code checks the nature of the route for this connection.
518 * Normally this is done by two simple checks in the next
519 * INET/INET6 ifdef block, but because of two possible lower layers,
520 * that check is done here.
522 * Perhaps should be doing this only for a RTF_HOST route.
524 rt
= inp
->inp_route
.ro_rt
; /* Same for route or route6. */
525 if (tp
->pf
== PF_INET6
) {
528 !(IN6_IS_ADDR_UNSPECIFIED(&
529 ((struct sockaddr_in6
*)rt_key(rt
))->sin6_addr
));
533 (((struct sockaddr_in
*)rt_key(rt
))->
534 sin_addr
.s_addr
!= INADDR_ANY
);
539 * If we sent enough data to get some meaningful characteristics,
540 * save them in the routing entry. 'Enough' is arbitrarily
541 * defined as the sendpipesize (default 4K) * 16. This would
542 * give us 16 rtt samples assuming we only get one sample per
543 * window (the usual case on a long haul net). 16 samples is
544 * enough for the srtt filter to converge to within 5% of the correct
545 * value; fewer samples and we could save a very bogus rtt.
547 * Don't update the default route's characteristics and don't
548 * update anything that the user "locked".
552 * Note that rt and bound_to_specific are set above.
554 if (SEQ_LT(tp
->iss
+ so
->so_snd
.sb_hiwat
* 16, tp
->snd_max
) &&
555 rt
&& bound_to_specific
) {
557 if (SEQ_LT(tp
->iss
+ so
->so_snd
.sb_hiwat
* 16, tp
->snd_max
) &&
558 (rt
= inp
->inp_route
.ro_rt
) &&
559 satosin(rt_key(rt
))->sin_addr
.s_addr
!= INADDR_ANY
) {
561 register u_long i
= 0;
563 if ((rt
->rt_rmx
.rmx_locks
& RTV_RTT
) == 0) {
565 (RTM_RTTUNIT
/ (PR_SLOWHZ
* TCP_RTT_SCALE
));
566 if (rt
->rt_rmx
.rmx_rtt
&& i
)
568 * filter this update to half the old & half
569 * the new values, converting scale.
570 * See route.h and tcp_var.h for a
571 * description of the scaling constants.
574 (rt
->rt_rmx
.rmx_rtt
+ i
) / 2;
576 rt
->rt_rmx
.rmx_rtt
= i
;
578 if ((rt
->rt_rmx
.rmx_locks
& RTV_RTTVAR
) == 0) {
580 (RTM_RTTUNIT
/ (PR_SLOWHZ
* TCP_RTTVAR_SCALE
));
581 if (rt
->rt_rmx
.rmx_rttvar
&& i
)
582 rt
->rt_rmx
.rmx_rttvar
=
583 (rt
->rt_rmx
.rmx_rttvar
+ i
) / 2;
585 rt
->rt_rmx
.rmx_rttvar
= i
;
588 * update the pipelimit (ssthresh) if it has been updated
589 * already or if a pipesize was specified & the threshhold
590 * got below half the pipesize. I.e., wait for bad news
591 * before we start updating, then update on both good
594 if (((rt
->rt_rmx
.rmx_locks
& RTV_SSTHRESH
) == 0 &&
595 (i
= tp
->snd_ssthresh
) && rt
->rt_rmx
.rmx_ssthresh
) ||
596 i
< (rt
->rt_rmx
.rmx_sendpipe
/ 2)) {
598 * convert the limit from user data bytes to
599 * packets then to packet data bytes.
601 i
= (i
+ tp
->t_maxseg
/ 2) / tp
->t_maxseg
;
605 if (tp
->pf
== PF_INET6
)
606 i
*= (u_long
)(tp
->t_maxseg
+ sizeof (struct tcphdr
)
607 + sizeof(struct ip6_hdr
));
610 i
*= (u_long
)(tp
->t_maxseg
+
611 sizeof (struct tcpiphdr
));
613 if (rt
->rt_rmx
.rmx_ssthresh
)
614 rt
->rt_rmx
.rmx_ssthresh
=
615 (rt
->rt_rmx
.rmx_ssthresh
+ i
) / 2;
617 rt
->rt_rmx
.rmx_ssthresh
= i
;
622 /* free the reassembly queue, if any */
624 /* Reassembling TCP segments in v6 might be sufficiently different
625 * to merit two codepaths to free the reasssembly queue.
626 * If an undecided TCP socket, then the IPv4 codepath will be used
627 * because it won't matter much anyway.
629 if (tp
->pf
== AF_INET6
) {
630 while ((qe
= tp
->segq
.lh_first
) != NULL
) {
631 LIST_REMOVE(qe
, ipqe_q
);
637 while ((qe
= tp
->segq
.lh_first
) != NULL
) {
638 LIST_REMOVE(qe
, ipqe_q
);
643 /* Free SACK holes. */
644 q
= p
= tp
->snd_holes
;
652 (void) m_free(tp
->t_template
);
655 soisdisconnected(so
);
657 tcpstat
.tcps_closed
++;
658 return ((struct tcpcb
*)0);
668 * Notify a tcp user of an asynchronous error;
669 * store error as soft error, but wake up user
670 * (for now, won't do anything until can select for soft error).
673 tcp_notify(inp
, error
)
677 register struct tcpcb
*tp
= (struct tcpcb
*)inp
->inp_ppcb
;
678 register struct socket
*so
= inp
->inp_socket
;
681 * Ignore some errors if we are hooked up.
682 * If connection hasn't completed, has retransmitted several times,
683 * and receives a second error, give up now. This is better
684 * than waiting a long time to establish a connection that
685 * can never complete.
687 if (tp
->t_state
== TCPS_ESTABLISHED
&&
688 (error
== EHOSTUNREACH
|| error
== ENETUNREACH
||
689 error
== EHOSTDOWN
)) {
691 } else if (TCPS_HAVEESTABLISHED(tp
->t_state
) == 0 &&
692 tp
->t_rxtshift
> 3 && tp
->t_softerror
)
693 so
->so_error
= error
;
695 tp
->t_softerror
= error
;
696 wakeup((caddr_t
) &so
->so_timeo
);
701 #if defined(INET6) && !defined(TCP6)
703 tcp6_ctlinput(cmd
, sa
, d
)
708 (void)tcp_ctlinput(cmd
, sa
, NULL
); /*XXX*/
713 tcp_ctlinput(cmd
, sa
, v
)
718 register struct ip
*ip
= v
;
719 register struct tcphdr
*th
;
720 extern int inetctlerrmap
[];
721 void (*notify
) __P((struct inpcb
*, int)) = tcp_notify
;
724 if ((unsigned)cmd
>= PRC_NCMDS
)
726 errno
= inetctlerrmap
[cmd
];
727 if (cmd
== PRC_QUENCH
)
729 else if (PRC_IS_REDIRECT(cmd
))
730 notify
= in_rtchange
, ip
= 0;
731 else if (cmd
== PRC_HOSTDEAD
)
737 if (sa
->sa_family
== AF_INET6
) {
739 struct ip6_hdr
*ipv6
= (struct ip6_hdr
*)ip
;
741 th
= (struct tcphdr
*)(ipv6
+ 1);
743 in6_pcbnotify(&tcbtable
, sa
, th
->th_dport
,
744 &ipv6
->ip6_src
, th
->th_sport
, cmd
, notify
);
748 in6_pcbnotify(&tcbtable
, sa
, 0,
749 (struct in6_addr
*)&in6addr_any
, 0, cmd
, notify
);
756 th
= (struct tcphdr
*)((caddr_t
)ip
+ (ip
->ip_hl
<< 2));
757 in_pcbnotify(&tcbtable
, sa
, th
->th_dport
, ip
->ip_src
,
758 th
->th_sport
, errno
, notify
);
760 in_pcbnotifyall(&tcbtable
, sa
, errno
, notify
);
766 * When a source quench is received, close congestion window
767 * to one segment. We will gradually open it again as we proceed.
770 tcp_quench(inp
, errno
)
774 struct tcpcb
*tp
= intotcpcb(inp
);
777 tp
->snd_cwnd
= tp
->t_maxseg
;
782 tcp_signature_tdb_attach()
788 tcp_signature_tdb_init(tdbp
, xsp
, ii
)
791 struct ipsecinit
*ii
;
794 #define isdigit(c) (((c) >= '0') && ((c) <= '9'))
795 #define isalpha(c) ( (((c) >= 'A') && ((c) <= 'Z')) || \
796 (((c) >= 'a') && ((c) <= 'z')) )
798 if ((ii
->ii_authkeylen
< 1) || (ii
->ii_authkeylen
> 80))
801 c
= (char *)ii
->ii_authkey
;
803 while (c
< (char *)ii
->ii_authkey
+ ii
->ii_authkeylen
- 1) {
815 if (!isdigit(*c
) && !isalpha(*c
))
818 tdbp
->tdb_amxkey
= malloc(ii
->ii_authkeylen
, M_XDATA
, M_DONTWAIT
);
819 if (tdbp
->tdb_amxkey
== NULL
)
821 bcopy(ii
->ii_authkey
, tdbp
->tdb_amxkey
, ii
->ii_authkeylen
);
822 tdbp
->tdb_amxkeylen
= ii
->ii_authkeylen
;
828 tcp_signature_tdb_zeroize(tdbp
)
831 if (tdbp
->tdb_amxkey
) {
832 bzero(tdbp
->tdb_amxkey
, tdbp
->tdb_amxkeylen
);
833 free(tdbp
->tdb_amxkey
, M_XDATA
);
834 tdbp
->tdb_amxkey
= NULL
;
841 tcp_signature_tdb_input(m
, tdbp
, skip
, protoff
)
850 tcp_signature_tdb_output(m
, tdbp
, mp
, skip
, protoff
)
860 tcp_signature_apply(fstate
, data
, len
)
865 MD5Update((MD5_CTX
*)fstate
, (char *)data
, len
);
868 #endif /* TCP_SIGNATURE */