]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/net/tcpip/v2_0/src/sys/netinet/tcp_subr.c
Initial revision
[karo-tx-redboot.git] / packages / net / tcpip / v2_0 / src / sys / netinet / tcp_subr.c
1 //==========================================================================
2 //
3 //      sys/netinet/tcp_subr.c
4 //
5 //     
6 //
7 //==========================================================================
8 //####BSDCOPYRIGHTBEGIN####
9 //
10 // -------------------------------------------
11 //
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.
14 //
15 // -------------------------------------------
16 //
17 //####BSDCOPYRIGHTEND####
18 //==========================================================================
19 //#####DESCRIPTIONBEGIN####
20 //
21 // Author(s):    gthomas
22 // Contributors: gthomas
23 // Date:         2000-01-10
24 // Purpose:      
25 // Description:  
26 //              
27 //
28 //####DESCRIPTIONEND####
29 //
30 //==========================================================================
31
32
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 $   */
35
36 /*
37  * Copyright (c) 1982, 1986, 1988, 1990, 1993
38  *      The Regents of the University of California.  All rights reserved.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
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.
55  *
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
66  * SUCH DAMAGE.
67  *
68  *      @(#)tcp_subr.c  8.1 (Berkeley) 6/10/93
69  */
70
71 /*
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
78 software.
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>.
81 */
82
83 #include <sys/param.h>
84 #ifndef __ECOS
85 #include <sys/proc.h>
86 #include <sys/systm.h>
87 #endif
88 #include <sys/malloc.h>
89 #include <sys/mbuf.h>
90 #include <sys/socket.h>
91 #include <sys/socketvar.h>
92 #include <sys/protosw.h>
93 #include <sys/errno.h>
94 #ifdef __ECOS
95 #undef errno
96 #endif
97
98 #include <net/route.h>
99 #include <net/if.h>
100
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>
113 #ifndef __ECOS
114 #include <dev/rndvar.h>
115 #endif
116
117 #ifdef INET6
118 #include <netinet6/ip6_var.h>
119 #include <netinet6/tcpipv6.h>
120 #include <sys/domain.h>
121 #endif /* INET6 */
122
123 #ifdef TCP_SIGNATURE
124 #include <sys/md5k.h>
125 #endif /* TCP_SIGNATURE */
126
127 /* patchable/settable parameters for tcp */
128 int     tcp_mssdflt = TCP_MSS;
129 int     tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
130
131 /*
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
136  * more overhead.
137  * XXX And it should be a settable per route characteristic (with this just
138  * used as the default).
139  */
140 #ifndef TCP_DO_RFC1323
141 #define TCP_DO_RFC1323  1
142 #endif
143 int    tcp_do_rfc1323 = TCP_DO_RFC1323;
144
145 #ifndef TCP_DO_SACK
146 #ifdef TCP_SACK
147 #define TCP_DO_SACK     0       /* XXX - make this 1 when SACK is fixed */
148 #else
149 #define TCP_DO_SACK     0
150 #endif
151 #endif
152 int    tcp_do_sack = TCP_DO_SACK;               /* RFC 2018 selective ACKs */
153
154 #ifndef TCBHASHSIZE
155 #define TCBHASHSIZE     128
156 #endif
157 int     tcbhashsize = TCBHASHSIZE;
158
159 #ifdef INET6
160 extern int ip6_defhlim;
161 #endif /* INET6 */
162
163 /*
164  * Tcp initialization
165  */
166 void
167 tcp_init()
168 {
169 #ifdef TCP_COMPAT_42
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);
175
176 #ifdef INET6
177         /*
178          * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
179          * do max length checks/computations only on the former.
180          */
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)) >
184             MHLEN)
185                 panic("tcp_init");
186 #endif /* INET6 */
187 }
188
189 /*
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.
194  *
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
199  */
200 struct mbuf *
201 tcp_template(tp)
202         struct tcpcb *tp;
203 {
204         register struct inpcb *inp = tp->t_inpcb;
205         register struct mbuf *m;
206         register struct tcphdr *th = (struct tcphdr *)0;
207
208         if ((m = tp->t_template) == 0) {
209                 m = m_get(M_DONTWAIT, MT_HEADER);
210                 if (m == NULL)
211                         return (0);
212
213                 switch (tp->pf) {
214                 case 0: /*default to PF_INET*/
215 #ifdef INET
216                 case AF_INET:
217                         m->m_len = sizeof(struct ip);
218                         break;
219 #endif /* INET */
220 #ifdef INET6
221                 case AF_INET6:
222                         m->m_len = sizeof(struct ip6_hdr);
223                         break;
224 #endif /* INET6 */
225                 }
226                 m->m_len += sizeof (struct tcphdr);
227
228                 /*
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.
232                  */ 
233                 if (m->m_len + MAX_TCPOPTLEN + max_linkhdr >= MHLEN) {
234                         MCLGET(m, M_DONTWAIT);
235                         if ((m->m_flags & M_EXT) == 0) {
236                                 m_free(m);
237                                 return (0);
238                         }
239                 }
240         }
241
242         switch(tp->pf) {
243 #ifdef INET
244         case AF_INET:
245                 {
246                         struct ipovly *ipovly;
247
248                         ipovly = mtod(m, struct ipovly *);
249
250                         bzero(ipovly->ih_x1, sizeof ipovly->ih_x1);
251                         ipovly->ih_pr = IPPROTO_TCP;
252                         ipovly->ih_len = htons(sizeof (struct tcpiphdr) -
253                                 sizeof (struct ip));
254                         ipovly->ih_src = inp->inp_laddr;
255                         ipovly->ih_dst = inp->inp_faddr;
256
257                         th = (struct tcphdr *)(mtod(m, caddr_t) +
258                                 sizeof(struct ip));
259                 }
260                 break;
261 #endif /* INET */
262 #ifdef INET6
263         case AF_INET6:
264                 {
265                         struct ip6_hdr *ipv6;
266
267                         ipv6 = mtod(m, struct ip6_hdr *);
268
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));  
273                                                   
274
275                         ipv6->ip6_nxt = IPPROTO_TCP;
276                         ipv6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/
277                         ipv6->ip6_hlim = in6_selecthlim(inp, NULL);     /*XXX*/
278
279                         th = (struct tcphdr *)(mtod(m, caddr_t) +
280                                 sizeof(struct ip6_hdr));
281                 }
282                 break;
283 #endif /* INET6 */
284         }
285
286         th->th_sport = inp->inp_lport;
287         th->th_dport = inp->inp_fport;
288         th->th_seq = 0;
289         th->th_ack = 0;
290         th->th_x2  = 0;
291         th->th_off = 5;
292         th->th_flags = 0;
293         th->th_win = 0;
294         th->th_sum = 0;
295         th->th_urp = 0;
296         return (m);
297 }
298
299 /*
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
307  * attached mbufs.
308  *
309  * In any case the ack and sequence number of the transmitted
310  * segment are as specified by the parameters.
311  */
312 #ifdef INET6
313 /* This function looks hairy, because it was so IPv4-dependent. */
314 #endif /* INET6 */
315 void
316 tcp_respond(tp, template, m, ack, seq, flags)
317         struct tcpcb *tp;
318         caddr_t template;
319         register struct mbuf *m;
320         tcp_seq ack, seq;
321         int flags;
322 {
323         register int tlen;
324         int win = 0;
325         struct route *ro = 0;
326         register struct tcphdr *th;
327         register struct tcpiphdr *ti = (struct tcpiphdr *)template;
328 #ifdef INET6
329         int is_ipv6 = 0;   /* true iff IPv6 */
330 #endif /* INET6 */
331
332         if (tp) {
333                 win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
334 #ifdef INET6
335                 /*
336                  * If this is called with an unconnected
337                  * socket/tp/pcb (tp->pf is 0), we lose.
338                  */
339                 is_ipv6 = (tp->pf == PF_INET6);
340
341                 /*
342                  * The route/route6 distinction is meaningless
343                  * unless you're allocating space or passing parameters.
344                  */
345 #endif /* INET6 */
346                 ro = &tp->t_inpcb->inp_route;
347         }
348 #ifdef INET6
349         else
350                 is_ipv6 = (((struct ip *)ti)->ip_v == 6);
351 #endif /* INET6 */
352         if (m == 0) {
353                 m = m_gethdr(M_DONTWAIT, MT_HEADER);
354                 if (m == NULL)
355                         return;
356 #ifdef TCP_COMPAT_42
357                 tlen = 1;
358 #else
359                 tlen = 0;
360 #endif
361                 m->m_data += max_linkhdr;
362 #ifdef INET6
363                 if (is_ipv6)
364                         bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
365                             sizeof(struct ip6_hdr));
366                 else
367 #endif /* INET6 */
368                         bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
369                             sizeof(struct ip));
370
371                 ti = mtod(m, struct tcpiphdr *);
372                 flags = TH_ACK;
373         } else {
374                 m_freem(m->m_next);
375                 m->m_next = 0;
376                 m->m_data = (caddr_t)ti;
377                 tlen = 0;
378 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
379 #ifdef INET6
380                 if (is_ipv6) {
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,\
384                             struct in6_addr);
385                         th = (void *)ti + sizeof(struct ip6_hdr);
386                 } else
387 #endif /* INET6 */
388                 {
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));
392                 }
393                 xchg(th->th_dport, th->th_sport, u_int16_t);
394 #undef xchg
395         }
396 #ifdef INET6
397         if (is_ipv6) {
398                 tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr); 
399                 th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
400         } else
401 #endif /* INET6 */
402         {
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));
406         }
407
408         m->m_len = tlen;
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);
413         th->th_x2 = 0;
414         th->th_off = sizeof (struct tcphdr) >> 2;
415         th->th_flags = flags;
416         if (tp)
417                 th->th_win = htons((u_int16_t) (win >> tp->rcv_scale));
418         else
419                 th->th_win = htons((u_int16_t)win);
420         th->th_urp = 0;
421
422 #ifdef INET6
423         if (is_ipv6) {
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);
429                 th->th_sum = 0;
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);
435         } else
436 #endif /* INET6 */
437         {
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);
444         }
445 }
446
447 /*
448  * Create a new TCP control block, making an
449  * empty reassembly queue and hooking it to the argument
450  * protocol control block.
451  */
452 struct tcpcb *
453 tcp_newtcpcb(inp)
454         struct inpcb *inp;
455 {
456         register struct tcpcb *tp;
457
458         tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT);
459         if (tp == NULL)
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;
464
465 #ifdef TCP_SACK
466         tp->sack_disable = tcp_do_sack ? 0 : 1;
467 #endif
468         tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
469         tp->t_inpcb = inp;
470         /*
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.
474          */
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;
482 #ifdef INET6
483         /*
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
488          * socket...
489          */
490         if ((inp->inp_flags & INP_IPV6) == 0)
491                 tp->pf = PF_INET;  /* If AF_INET socket, we can't do v6 from it. */
492 #else
493         tp->pf = PF_INET;
494 #endif
495
496 #ifdef INET6
497         if (inp->inp_flags & INP_IPV6) 
498                 inp->inp_ipv6.ip6_hlim = ip6_defhlim;
499         else
500 #endif /* INET6 */
501                 inp->inp_ip.ip_ttl = ip_defttl;
502
503         inp->inp_ppcb = (caddr_t)tp;
504         return (tp);
505 }
506
507 /*
508  * Drop a TCP connection, reporting
509  * the specified error.  If connection is synchronized,
510  * then send a RST to peer.
511  */
512 struct tcpcb *
513 tcp_drop(tp, errno)
514         register struct tcpcb *tp;
515         int errno;
516 {
517         struct socket *so = tp->t_inpcb->inp_socket;
518
519         if (TCPS_HAVERCVDSYN(tp->t_state)) {
520                 tp->t_state = TCPS_CLOSED;
521                 (void) tcp_output(tp);
522                 tcpstat.tcps_drops++;
523         } else
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));
529 }
530
531 /*
532  * Close a TCP control block:
533  *      discard all space held by the tcp
534  *      discard internet protocol block
535  *      wake up any sleepers
536  */
537 struct tcpcb *
538 tcp_close(tp)
539         register struct tcpcb *tp;
540 {
541         register struct ipqent *qe;
542         struct inpcb *inp = tp->t_inpcb;
543         struct socket *so = inp->inp_socket;
544 #ifdef TCP_SACK
545         struct sackhole *p, *q;
546 #endif
547 #ifdef RTV_RTT
548         register struct rtentry *rt;
549 #ifdef INET6
550         register int bound_to_specific = 0;  /* I.e. non-default */
551
552         /*
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.
557          *
558          * Perhaps should be doing this only for a RTF_HOST route.
559          */
560         rt = inp->inp_route.ro_rt;  /* Same for route or route6. */
561         if (tp->pf == PF_INET6) {
562                 if (rt)
563                         bound_to_specific =
564                             !(IN6_IS_ADDR_UNSPECIFIED(&
565                             ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr));
566         } else {
567                 if (rt)
568                         bound_to_specific =
569                             (((struct sockaddr_in *)rt_key(rt))->
570                             sin_addr.s_addr != INADDR_ANY);
571         }
572 #endif /* INET6 */
573
574         /*
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.
582          *
583          * Don't update the default route's characteristics and don't
584          * update anything that the user "locked".
585          */
586 #ifdef INET6
587         /*
588          * Note that rt and bound_to_specific are set above.
589          */
590         if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
591             rt && bound_to_specific) {
592 #else /* INET6 */
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) {
596 #endif /* INET6 */
597                 register u_long i = 0;
598
599                 if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
600                         i = tp->t_srtt *
601                             (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
602                         if (rt->rt_rmx.rmx_rtt && i)
603                                 /*
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.
608                                  */
609                                 rt->rt_rmx.rmx_rtt =
610                                     (rt->rt_rmx.rmx_rtt + i) / 2;
611                         else
612                                 rt->rt_rmx.rmx_rtt = i;
613                 }
614                 if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
615                         i = tp->t_rttvar *
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;
620                         else
621                                 rt->rt_rmx.rmx_rttvar = i;
622                 }
623                 /*
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
628                  * and bad news.
629                  */
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)) {
633                         /*
634                          * convert the limit from user data bytes to
635                          * packets then to packet data bytes.
636                          */
637                         i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
638                         if (i < 2)
639                                 i = 2;
640 #ifdef INET6
641                         if (tp->pf == PF_INET6)
642                                 i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)
643                                     + sizeof(struct ip6_hdr));
644                         else
645 #endif /* INET6 */
646                                 i *= (u_long)(tp->t_maxseg +
647                                     sizeof (struct tcpiphdr));
648
649                         if (rt->rt_rmx.rmx_ssthresh)
650                                 rt->rt_rmx.rmx_ssthresh =
651                                     (rt->rt_rmx.rmx_ssthresh + i) / 2;
652                         else
653                                 rt->rt_rmx.rmx_ssthresh = i;
654                 }
655         }
656 #endif /* RTV_RTT */
657
658         /* free the reassembly queue, if any */
659 #ifdef INET6
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.
664          */
665         if (tp->pf == AF_INET6) {
666                 while ((qe = tp->segq.lh_first) != NULL) {
667                         LIST_REMOVE(qe, ipqe_q);
668                         m_freem(qe->ipqe_m);
669                         FREE(qe, M_IPQ);
670                 }
671         } else
672 #endif /* INET6 */
673                 while ((qe = tp->segq.lh_first) != NULL) {
674                         LIST_REMOVE(qe, ipqe_q);
675                         m_freem(qe->ipqe_m);
676                         FREE(qe, M_IPQ);
677                 }
678 #ifdef TCP_SACK
679         /* Free SACK holes. */
680         q = p = tp->snd_holes;
681         while (p != 0) {
682                 q = p->next;
683                 free(p, M_PCB);
684                 p = q;
685         }
686 #endif
687         if (tp->t_template)
688                 (void) m_free(tp->t_template);
689         free(tp, M_PCB);
690         inp->inp_ppcb = 0;
691         soisdisconnected(so);
692         in_pcbdetach(inp);
693         tcpstat.tcps_closed++;
694         return ((struct tcpcb *)0);
695 }
696
697 void
698 tcp_drain()
699 {
700
701 }
702
703 /*
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).
707  */
708 void
709 tcp_notify(inp, error)
710         struct inpcb *inp;
711         int error;
712 {
713         register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
714         register struct socket *so = inp->inp_socket;
715
716         /*
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.
722          */
723         if (tp->t_state == TCPS_ESTABLISHED &&
724              (error == EHOSTUNREACH || error == ENETUNREACH ||
725               error == EHOSTDOWN)) {
726                 return;
727         } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
728             tp->t_rxtshift > 3 && tp->t_softerror)
729                 so->so_error = error;
730         else 
731                 tp->t_softerror = error;
732         wakeup((caddr_t) &so->so_timeo);
733         sorwakeup(so);
734         sowwakeup(so);
735 }
736
737 #if defined(INET6) && !defined(TCP6)
738 void
739 tcp6_ctlinput(cmd, sa, d)
740         int cmd;
741         struct sockaddr *sa;
742         void *d;
743 {
744         (void)tcp_ctlinput(cmd, sa, NULL);      /*XXX*/
745 }
746 #endif
747
748 void *
749 tcp_ctlinput(cmd, sa, v)
750         int cmd;
751         struct sockaddr *sa;
752         register void *v;
753 {
754         register struct ip *ip = v;
755         register struct tcphdr *th;
756         extern int inetctlerrmap[];
757         void (*notify) __P((struct inpcb *, int)) = tcp_notify;
758         int errno;
759
760         if ((unsigned)cmd >= PRC_NCMDS)
761                 return NULL;
762         errno = inetctlerrmap[cmd];
763         if (cmd == PRC_QUENCH)
764                 notify = tcp_quench;
765         else if (PRC_IS_REDIRECT(cmd))
766                 notify = in_rtchange, ip = 0;
767         else if (cmd == PRC_HOSTDEAD)
768                 ip = 0;
769         else if (errno == 0)
770                 return NULL;
771
772 #ifdef INET6
773         if (sa->sa_family == AF_INET6) {
774                 if (ip) {
775                         struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
776
777                         th = (struct tcphdr *)(ipv6 + 1);
778 #if 0 /*XXX*/
779                         in6_pcbnotify(&tcbtable, sa, th->th_dport,
780                             &ipv6->ip6_src, th->th_sport, cmd, notify);
781 #endif
782                 } else {
783 #if 0 /*XXX*/
784                         in6_pcbnotify(&tcbtable, sa, 0,
785                             (struct in6_addr *)&in6addr_any, 0, cmd, notify);
786 #endif
787                 }
788         } else
789 #endif /* INET6 */
790         {
791                 if (ip) {
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);
795                 } else
796                         in_pcbnotifyall(&tcbtable, sa, errno, notify);
797         }
798         return NULL;
799 }
800
801 /*
802  * When a source quench is received, close congestion window
803  * to one segment.  We will gradually open it again as we proceed.
804  */
805 void
806 tcp_quench(inp, errno)
807         struct inpcb *inp;
808         int errno;
809 {
810         struct tcpcb *tp = intotcpcb(inp);
811
812         if (tp)
813                 tp->snd_cwnd = tp->t_maxseg;
814 }
815
816 #ifdef TCP_SIGNATURE
817 int
818 tcp_signature_tdb_attach()
819 {
820         return (0);
821 }
822
823 int
824 tcp_signature_tdb_init(tdbp, xsp, ii)
825         struct tdb *tdbp;
826         struct xformsw *xsp;
827         struct ipsecinit *ii;
828 {
829         char *c;
830 #define isdigit(c)        (((c) >= '0') && ((c) <= '9'))
831 #define isalpha(c)      ( (((c) >= 'A') && ((c) <= 'Z')) || \
832                           (((c) >= 'a') && ((c) <= 'z')) )
833
834         if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))
835                 return (EINVAL);
836
837         c = (char *)ii->ii_authkey;
838
839         while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {
840                 if (isdigit(*c)) {
841                         if (*(c + 1) == ' ')
842                                 return (EINVAL);
843                 } else {
844                         if (!isalpha(*c))
845                                 return (EINVAL);
846                 }
847
848                 c++;
849         }
850
851         if (!isdigit(*c) && !isalpha(*c))
852                 return (EINVAL);
853
854         tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
855         if (tdbp->tdb_amxkey == NULL)
856                 return (ENOMEM);
857         bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
858         tdbp->tdb_amxkeylen = ii->ii_authkeylen;
859
860         return (0);
861 }
862
863 int
864 tcp_signature_tdb_zeroize(tdbp)
865         struct tdb *tdbp;
866 {
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;
871         }
872
873         return (0);
874 }
875
876 struct mbuf *
877 tcp_signature_tdb_input(m, tdbp)
878         struct mbuf *m;
879         struct tdb *tdbp;
880 {
881         return (0);
882 }
883
884 int
885 tcp_signature_tdb_output(m, tdbp, mp)
886         struct mbuf *m;
887         struct tdb *tdbp;
888         struct mbuf **mp;
889 {
890         return (EINVAL);
891 }
892
893 int
894 tcp_signature_apply(fstate, data, len)
895         caddr_t fstate;
896         caddr_t data;
897         unsigned int len;
898 {
899         MD5Update((MD5_CTX *)fstate, (char *)data, len);
900         return 0;
901 }
902 #endif /* TCP_SIGNATURE */