change gdium conf to print message out both on uart and lcd
[pmon-gdium.git] / sys / netinet / tcp_subr.c
blob5cec421f24084bf45d74b83f858382728bd4fa92
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 $ */
4 /*
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
10 * are met:
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
34 * SUCH DAMAGE.
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
46 software.
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>
52 #include <sys/proc.h>
53 #include <sys/systm.h>
54 #include <sys/malloc.h>
55 #include <sys/mbuf.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>
62 #include <net/if.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>
76 #ifndef PMON
77 #include <dev/rndvar.h>
78 #endif /* PMON */
80 #ifdef INET6
81 #include <netinet6/ip6_var.h>
82 #include <netinet6/tcpipv6.h>
83 #include <sys/domain.h>
84 #endif /* INET6 */
86 #ifdef TCP_SIGNATURE
87 #include <sys/md5k.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
99 * more overhead.
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
105 #endif
106 int tcp_do_rfc1323 = TCP_DO_RFC1323;
108 #ifndef TCP_DO_SACK
109 #ifdef TCP_SACK
110 #define TCP_DO_SACK 1
111 #else
112 #define TCP_DO_SACK 0
113 #endif
114 #endif
115 int tcp_do_sack = TCP_DO_SACK; /* RFC 2018 selective ACKs */
117 #ifndef TCBHASHSIZE
118 #define TCBHASHSIZE 128
119 #endif
120 int tcbhashsize = TCBHASHSIZE;
122 #ifdef INET6
123 extern int ip6_defhlim;
124 #endif /* INET6 */
127 * Tcp initialization
129 void
130 tcp_init()
132 #ifdef TCP_COMPAT_42
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);
139 #ifdef INET6
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)) >
147 MHLEN)
148 panic("tcp_init");
149 #endif /* INET6 */
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
163 struct mbuf *
164 tcp_template(tp)
165 struct tcpcb *tp;
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);
173 if (m == NULL)
174 return (0);
176 switch (tp->pf) {
177 case 0: /*default to PF_INET*/
178 #ifdef INET
179 case AF_INET:
180 m->m_len = sizeof(struct ip);
181 break;
182 #endif /* INET */
183 #ifdef INET6
184 case AF_INET6:
185 m->m_len = sizeof(struct ip6_hdr);
186 break;
187 #endif /* INET6 */
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) {
199 m_free(m);
200 return (0);
205 switch(tp->pf) {
206 #ifdef INET
207 case AF_INET:
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) -
216 sizeof (struct ip));
217 ipovly->ih_src = inp->inp_laddr;
218 ipovly->ih_dst = inp->inp_faddr;
220 th = (struct tcphdr *)(mtod(m, caddr_t) +
221 sizeof(struct ip));
223 break;
224 #endif /* INET */
225 #ifdef INET6
226 case AF_INET6:
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));
245 break;
246 #endif /* INET6 */
249 th->th_sport = inp->inp_lport;
250 th->th_dport = inp->inp_fport;
251 th->th_seq = 0;
252 th->th_ack = 0;
253 th->th_x2 = 0;
254 th->th_off = 5;
255 th->th_flags = 0;
256 th->th_win = 0;
257 th->th_sum = 0;
258 th->th_urp = 0;
259 return (m);
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
270 * attached mbufs.
272 * In any case the ack and sequence number of the transmitted
273 * segment are as specified by the parameters.
275 #ifdef INET6
276 /* This function looks hairy, because it was so IPv4-dependent. */
277 #endif /* INET6 */
278 void
279 tcp_respond(tp, template, m, ack, seq, flags)
280 struct tcpcb *tp;
281 caddr_t template;
282 register struct mbuf *m;
283 tcp_seq ack, seq;
284 int flags;
286 register int tlen;
287 int win = 0;
288 struct route *ro = 0;
289 register struct tcphdr *th;
290 register struct tcpiphdr *ti = (struct tcpiphdr *)template;
291 #ifdef INET6
292 int is_ipv6 = 0; /* true iff IPv6 */
293 #endif /* INET6 */
295 if (tp) {
296 win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
297 #ifdef INET6
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.
308 #endif /* INET6 */
309 ro = &tp->t_inpcb->inp_route;
311 #ifdef INET6
312 else
313 is_ipv6 = (((struct ip *)ti)->ip_v == 6);
314 #endif /* INET6 */
315 if (m == 0) {
316 m = m_gethdr(M_DONTWAIT, MT_HEADER);
317 if (m == NULL)
318 return;
319 #ifdef TCP_COMPAT_42
320 tlen = 1;
321 #else
322 tlen = 0;
323 #endif
324 m->m_data += max_linkhdr;
325 #ifdef INET6
326 if (is_ipv6)
327 bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
328 sizeof(struct ip6_hdr));
329 else
330 #endif /* INET6 */
331 bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
332 sizeof(struct ip));
334 ti = mtod(m, struct tcpiphdr *);
335 flags = TH_ACK;
336 } else {
337 m_freem(m->m_next);
338 m->m_next = 0;
339 m->m_data = (caddr_t)ti;
340 tlen = 0;
341 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
342 #ifdef INET6
343 if (is_ipv6) {
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,\
347 struct in6_addr);
348 th = (void *)ti + sizeof(struct ip6_hdr);
349 } else
350 #endif /* INET6 */
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);
357 #undef xchg
359 #ifdef INET6
360 if (is_ipv6) {
361 tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
362 th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
363 } else
364 #endif /* INET6 */
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));
371 m->m_len = tlen;
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);
376 th->th_x2 = 0;
377 th->th_off = sizeof (struct tcphdr) >> 2;
378 th->th_flags = flags;
379 if (tp)
380 win >>= tp->rcv_scale;
381 if (win > TCP_MAXWIN)
382 win = TCP_MAXWIN;
383 th->th_win = htons((u_int16_t)win);
384 th->th_urp = 0;
386 #ifdef INET6
387 if (is_ipv6) {
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);
393 th->th_sum = 0;
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);
399 } else
400 #endif /* INET6 */
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.
416 struct tcpcb *
417 tcp_newtcpcb(inp)
418 struct inpcb *inp;
420 register struct tcpcb *tp;
422 tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT);
423 if (tp == NULL)
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;
429 #ifdef TCP_SACK
430 tp->sack_disable = tcp_do_sack ? 0 : 1;
431 #endif
432 tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
433 tp->t_inpcb = inp;
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;
446 #ifdef INET6
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
452 * socket...
454 if ((inp->inp_flags & INP_IPV6) == 0)
455 tp->pf = PF_INET; /* If AF_INET socket, we can't do v6 from it. */
456 #else
457 tp->pf = PF_INET;
458 #endif
460 #ifdef INET6
461 if (inp->inp_flags & INP_IPV6)
462 inp->inp_ipv6.ip6_hlim = ip6_defhlim;
463 else
464 #endif /* INET6 */
465 inp->inp_ip.ip_ttl = ip_defttl;
467 inp->inp_ppcb = (caddr_t)tp;
468 return (tp);
472 * Drop a TCP connection, reporting
473 * the specified error. If connection is synchronized,
474 * then send a RST to peer.
476 struct tcpcb *
477 tcp_drop(tp, errno)
478 register struct tcpcb *tp;
479 int errno;
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++;
487 } else
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
501 struct tcpcb *
502 tcp_close(tp)
503 register struct tcpcb *tp;
505 register struct ipqent *qe;
506 struct inpcb *inp = tp->t_inpcb;
507 struct socket *so = inp->inp_socket;
508 #ifdef TCP_SACK
509 struct sackhole *p, *q;
510 #endif
511 #ifdef RTV_RTT
512 register struct rtentry *rt;
513 #ifdef INET6
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) {
526 if (rt)
527 bound_to_specific =
528 !(IN6_IS_ADDR_UNSPECIFIED(&
529 ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr));
530 } else {
531 if (rt)
532 bound_to_specific =
533 (((struct sockaddr_in *)rt_key(rt))->
534 sin_addr.s_addr != INADDR_ANY);
536 #endif /* INET6 */
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".
550 #ifdef INET6
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) {
556 #else /* INET6 */
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) {
560 #endif /* INET6 */
561 register u_long i = 0;
563 if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
564 i = tp->t_srtt *
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.
573 rt->rt_rmx.rmx_rtt =
574 (rt->rt_rmx.rmx_rtt + i) / 2;
575 else
576 rt->rt_rmx.rmx_rtt = i;
578 if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
579 i = tp->t_rttvar *
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;
584 else
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
592 * and bad news.
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;
602 if (i < 2)
603 i = 2;
604 #ifdef INET6
605 if (tp->pf == PF_INET6)
606 i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)
607 + sizeof(struct ip6_hdr));
608 else
609 #endif /* INET6 */
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;
616 else
617 rt->rt_rmx.rmx_ssthresh = i;
620 #endif /* RTV_RTT */
622 /* free the reassembly queue, if any */
623 #ifdef INET6
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);
632 m_freem(qe->ipqe_m);
633 FREE(qe, M_IPQ);
635 } else
636 #endif /* INET6 */
637 while ((qe = tp->segq.lh_first) != NULL) {
638 LIST_REMOVE(qe, ipqe_q);
639 m_freem(qe->ipqe_m);
640 FREE(qe, M_IPQ);
642 #ifdef TCP_SACK
643 /* Free SACK holes. */
644 q = p = tp->snd_holes;
645 while (p != 0) {
646 q = p->next;
647 free(p, M_PCB);
648 p = q;
650 #endif
651 if (tp->t_template)
652 (void) m_free(tp->t_template);
653 free(tp, M_PCB);
654 inp->inp_ppcb = 0;
655 soisdisconnected(so);
656 in_pcbdetach(inp);
657 tcpstat.tcps_closed++;
658 return ((struct tcpcb *)0);
661 void
662 tcp_drain()
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).
672 void
673 tcp_notify(inp, error)
674 struct inpcb *inp;
675 int 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)) {
690 return;
691 } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
692 tp->t_rxtshift > 3 && tp->t_softerror)
693 so->so_error = error;
694 else
695 tp->t_softerror = error;
696 wakeup((caddr_t) &so->so_timeo);
697 sorwakeup(so);
698 sowwakeup(so);
701 #if defined(INET6) && !defined(TCP6)
702 void
703 tcp6_ctlinput(cmd, sa, d)
704 int cmd;
705 struct sockaddr *sa;
706 void *d;
708 (void)tcp_ctlinput(cmd, sa, NULL); /*XXX*/
710 #endif
712 void *
713 tcp_ctlinput(cmd, sa, v)
714 int cmd;
715 struct sockaddr *sa;
716 register void *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;
722 int errno;
724 if ((unsigned)cmd >= PRC_NCMDS)
725 return NULL;
726 errno = inetctlerrmap[cmd];
727 if (cmd == PRC_QUENCH)
728 notify = tcp_quench;
729 else if (PRC_IS_REDIRECT(cmd))
730 notify = in_rtchange, ip = 0;
731 else if (cmd == PRC_HOSTDEAD)
732 ip = 0;
733 else if (errno == 0)
734 return NULL;
736 #ifdef INET6
737 if (sa->sa_family == AF_INET6) {
738 if (ip) {
739 struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
741 th = (struct tcphdr *)(ipv6 + 1);
742 #if 0 /*XXX*/
743 in6_pcbnotify(&tcbtable, sa, th->th_dport,
744 &ipv6->ip6_src, th->th_sport, cmd, notify);
745 #endif
746 } else {
747 #if 0 /*XXX*/
748 in6_pcbnotify(&tcbtable, sa, 0,
749 (struct in6_addr *)&in6addr_any, 0, cmd, notify);
750 #endif
752 } else
753 #endif /* INET6 */
755 if (ip) {
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);
759 } else
760 in_pcbnotifyall(&tcbtable, sa, errno, notify);
762 return NULL;
766 * When a source quench is received, close congestion window
767 * to one segment. We will gradually open it again as we proceed.
769 void
770 tcp_quench(inp, errno)
771 struct inpcb *inp;
772 int errno;
774 struct tcpcb *tp = intotcpcb(inp);
776 if (tp)
777 tp->snd_cwnd = tp->t_maxseg;
780 #ifdef TCP_SIGNATURE
782 tcp_signature_tdb_attach()
784 return (0);
788 tcp_signature_tdb_init(tdbp, xsp, ii)
789 struct tdb *tdbp;
790 struct xformsw *xsp;
791 struct ipsecinit *ii;
793 char *c;
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))
799 return (EINVAL);
801 c = (char *)ii->ii_authkey;
803 while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {
804 if (isdigit(*c)) {
805 if (*(c + 1) == ' ')
806 return (EINVAL);
807 } else {
808 if (!isalpha(*c))
809 return (EINVAL);
812 c++;
815 if (!isdigit(*c) && !isalpha(*c))
816 return (EINVAL);
818 tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
819 if (tdbp->tdb_amxkey == NULL)
820 return (ENOMEM);
821 bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
822 tdbp->tdb_amxkeylen = ii->ii_authkeylen;
824 return (0);
828 tcp_signature_tdb_zeroize(tdbp)
829 struct tdb *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;
837 return (0);
841 tcp_signature_tdb_input(m, tdbp, skip, protoff)
842 struct mbuf *m;
843 struct tdb *tdbp;
844 int skip, protoff;
846 return (0);
850 tcp_signature_tdb_output(m, tdbp, mp, skip, protoff)
851 struct mbuf *m;
852 struct tdb *tdbp;
853 struct mbuf **mp;
854 int skip, protoff;
856 return (EINVAL);
860 tcp_signature_apply(fstate, data, len)
861 caddr_t fstate;
862 caddr_t data;
863 unsigned int len;
865 MD5Update((MD5_CTX *)fstate, (char *)data, len);
866 return 0;
868 #endif /* TCP_SIGNATURE */