]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/netinet/tcp_timewait.c
This commit was generated by cvs2svn to compensate for changes in r53809,
[FreeBSD/FreeBSD.git] / sys / netinet / tcp_timewait.c
1 /*
2  * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      @(#)tcp_subr.c  8.2 (Berkeley) 5/24/95
34  * $FreeBSD$
35  */
36
37 #include "opt_compat.h"
38 #include "opt_inet.h"
39 #include "opt_tcpdebug.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/callout.h>
44 #include <sys/kernel.h>
45 #include <sys/sysctl.h>
46 #include <sys/malloc.h>
47 #include <sys/mbuf.h>
48 #include <sys/proc.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/protosw.h>
52
53 #include <vm/vm_zone.h>
54
55 #include <net/route.h>
56 #include <net/if.h>
57
58 #define _IP_VHL
59 #include <netinet/in.h>
60 #include <netinet/in_systm.h>
61 #include <netinet/ip.h>
62 #include <netinet/in_pcb.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/tcp_fsm.h>
67 #include <netinet/tcp_seq.h>
68 #include <netinet/tcp_timer.h>
69 #include <netinet/tcp_var.h>
70 #include <netinet/tcpip.h>
71 #ifdef TCPDEBUG
72 #include <netinet/tcp_debug.h>
73 #endif
74
75 int     tcp_mssdflt = TCP_MSS;
76 SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, CTLFLAG_RW, 
77     &tcp_mssdflt , 0, "Default TCP Maximum Segment Size");
78
79 #ifdef INET6
80 int     tcp_v6mssdflt = TCP6_MSS;
81 SYSCTL_INT(_net_inet_tcp, TCPCTL_V6MSSDFLT, v6mssdflt,
82         CTLFLAG_RW, &tcp_v6mssdflt , 0, "");
83 #endif
84
85 #if 0
86 static int      tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
87 SYSCTL_INT(_net_inet_tcp, TCPCTL_RTTDFLT, rttdflt, CTLFLAG_RW, 
88     &tcp_rttdflt , 0, "Default maximum TCP Round Trip Time");
89 #endif
90
91 static int      tcp_do_rfc1323 = 1;
92 SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW, 
93     &tcp_do_rfc1323 , 0, "Enable rfc1323 (high performance TCP) extensions");
94
95 static int      tcp_do_rfc1644 = 0;
96 SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644, CTLFLAG_RW, 
97     &tcp_do_rfc1644 , 0, "Enable rfc1644 (TTCP) extensions");
98
99 static int      tcp_tcbhashsize = 0;
100 SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcbhashsize, CTLFLAG_RD,
101      &tcp_tcbhashsize, 0, "Size of TCP control-block hashtable");
102
103 SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD, 
104     &tcbinfo.ipi_count, 0, "Number of active PCBs");
105
106 static void     tcp_cleartaocache __P((void));
107 static void     tcp_notify __P((struct inpcb *, int));
108
109 /*
110  * Target size of TCP PCB hash tables. Must be a power of two.
111  *
112  * Note that this can be overridden by the kernel environment
113  * variable net.inet.tcp.tcbhashsize
114  */
115 #ifndef TCBHASHSIZE
116 #define TCBHASHSIZE     512
117 #endif
118
119 /*
120  * This is the actual shape of what we allocate using the zone
121  * allocator.  Doing it this way allows us to protect both structures
122  * using the same generation count, and also eliminates the overhead
123  * of allocating tcpcbs separately.  By hiding the structure here,
124  * we avoid changing most of the rest of the code (although it needs
125  * to be changed, eventually, for greater efficiency).
126  */
127 #define ALIGNMENT       32
128 #define ALIGNM1         (ALIGNMENT - 1)
129 struct  inp_tp {
130         union {
131                 struct  inpcb inp;
132                 char    align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
133         } inp_tp_u;
134         struct  tcpcb tcb;
135         struct  callout inp_tp_rexmt, inp_tp_persist, inp_tp_keep, inp_tp_2msl;
136         struct  callout inp_tp_delack;
137 };
138 #undef ALIGNMENT
139 #undef ALIGNM1
140
141 /*
142  * Tcp initialization
143  */
144 void
145 tcp_init()
146 {
147         int hashsize;
148         
149         tcp_iss = random();     /* wrong, but better than a constant */
150         tcp_ccgen = 1;
151         tcp_cleartaocache();
152
153         tcp_delacktime = TCPTV_DELACK;
154         tcp_keepinit = TCPTV_KEEP_INIT;
155         tcp_keepidle = TCPTV_KEEP_IDLE;
156         tcp_keepintvl = TCPTV_KEEPINTVL;
157         tcp_maxpersistidle = TCPTV_KEEP_IDLE;
158         tcp_msl = TCPTV_MSL;
159
160         LIST_INIT(&tcb);
161         tcbinfo.listhead = &tcb;
162         TUNABLE_INT_FETCH("net.inet.tcp.tcbhashsize", TCBHASHSIZE, hashsize);
163         if (!powerof2(hashsize)) {
164                 printf("WARNING: TCB hash size not a power of 2\n");
165                 hashsize = 512; /* safe default */
166         }
167         tcp_tcbhashsize = hashsize;
168         tcbinfo.hashbase = hashinit(hashsize, M_PCB, &tcbinfo.hashmask);
169         tcbinfo.porthashbase = hashinit(hashsize, M_PCB,
170                                         &tcbinfo.porthashmask);
171         tcbinfo.ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets,
172                                  ZONE_INTERRUPT, 0);
173
174         if (max_protohdr < sizeof(struct tcpiphdr))
175                 max_protohdr = sizeof(struct tcpiphdr);
176         if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
177                 panic("tcp_init");
178 }
179
180 /*
181  * Create template to be used to send tcp packets on a connection.
182  * Call after host entry created, allocates an mbuf and fills
183  * in a skeletal tcp/ip header, minimizing the amount of work
184  * necessary when the connection is used.
185  */
186 struct tcpiphdr *
187 tcp_template(tp)
188         struct tcpcb *tp;
189 {
190         register struct inpcb *inp = tp->t_inpcb;
191         register struct mbuf *m;
192         register struct tcpiphdr *n;
193
194         if ((n = tp->t_template) == 0) {
195                 m = m_get(M_DONTWAIT, MT_HEADER);
196                 if (m == NULL)
197                         return (0);
198                 m->m_len = sizeof (struct tcpiphdr);
199                 n = mtod(m, struct tcpiphdr *);
200         }
201         bzero(n->ti_x1, sizeof(n->ti_x1));
202         n->ti_pr = IPPROTO_TCP;
203         n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
204         n->ti_src = inp->inp_laddr;
205         n->ti_dst = inp->inp_faddr;
206         n->ti_sport = inp->inp_lport;
207         n->ti_dport = inp->inp_fport;
208         n->ti_seq = 0;
209         n->ti_ack = 0;
210         n->ti_x2 = 0;
211         n->ti_off = 5;
212         n->ti_flags = 0;
213         n->ti_win = 0;
214         n->ti_sum = 0;
215         n->ti_urp = 0;
216         return (n);
217 }
218
219 /*
220  * Send a single message to the TCP at address specified by
221  * the given TCP/IP header.  If m == 0, then we make a copy
222  * of the tcpiphdr at ti and send directly to the addressed host.
223  * This is used to force keep alive messages out using the TCP
224  * template for a connection tp->t_template.  If flags are given
225  * then we send a message back to the TCP which originated the
226  * segment ti, and discard the mbuf containing it and any other
227  * attached mbufs.
228  *
229  * In any case the ack and sequence number of the transmitted
230  * segment are as specified by the parameters.
231  *
232  * NOTE: If m != NULL, then ti must point to *inside* the mbuf.
233  */
234 void
235 tcp_respond(tp, ti, m, ack, seq, flags)
236         struct tcpcb *tp;
237         register struct tcpiphdr *ti;
238         register struct mbuf *m;
239         tcp_seq ack, seq;
240         int flags;
241 {
242         register int tlen;
243         int win = 0;
244         struct route *ro = 0;
245         struct route sro;
246
247         if (tp) {
248                 if (!(flags & TH_RST))
249                         win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
250                 ro = &tp->t_inpcb->inp_route;
251         } else {
252                 ro = &sro;
253                 bzero(ro, sizeof *ro);
254         }
255         if (m == 0) {
256                 m = m_gethdr(M_DONTWAIT, MT_HEADER);
257                 if (m == NULL)
258                         return;
259 #ifdef TCP_COMPAT_42
260                 tlen = 1;
261 #else
262                 tlen = 0;
263 #endif
264                 m->m_data += max_linkhdr;
265                 *mtod(m, struct tcpiphdr *) = *ti;
266                 ti = mtod(m, struct tcpiphdr *);
267                 flags = TH_ACK;
268         } else {
269                 m_freem(m->m_next);
270                 m->m_next = 0;
271                 m->m_data = (caddr_t)ti;
272                 m->m_len = sizeof (struct tcpiphdr);
273                 tlen = 0;
274 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
275                 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, n_long);
276                 xchg(ti->ti_dport, ti->ti_sport, n_short);
277 #undef xchg
278         }
279         ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
280         tlen += sizeof (struct tcpiphdr);
281         m->m_len = tlen;
282         m->m_pkthdr.len = tlen;
283         m->m_pkthdr.rcvif = (struct ifnet *) 0;
284         bzero(ti->ti_x1, sizeof(ti->ti_x1));
285         ti->ti_seq = htonl(seq);
286         ti->ti_ack = htonl(ack);
287         ti->ti_x2 = 0;
288         ti->ti_off = sizeof (struct tcphdr) >> 2;
289         ti->ti_flags = flags;
290         if (tp)
291                 ti->ti_win = htons((u_short) (win >> tp->rcv_scale));
292         else
293                 ti->ti_win = htons((u_short)win);
294         ti->ti_urp = 0;
295         ti->ti_sum = 0;
296         ti->ti_sum = in_cksum(m, tlen);
297         ((struct ip *)ti)->ip_len = tlen;
298         ((struct ip *)ti)->ip_ttl = ip_defttl;
299 #ifdef TCPDEBUG
300         if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
301                 tcp_trace(TA_OUTPUT, 0, tp, ti, 0);
302 #endif
303         (void) ip_output(m, NULL, ro, 0, NULL);
304         if (ro == &sro && ro->ro_rt) {
305                 RTFREE(ro->ro_rt);
306         }
307 }
308
309 /*
310  * Create a new TCP control block, making an
311  * empty reassembly queue and hooking it to the argument
312  * protocol control block.  The `inp' parameter must have
313  * come from the zone allocator set up in tcp_init().
314  */
315 struct tcpcb *
316 tcp_newtcpcb(inp)
317         struct inpcb *inp;
318 {
319         struct inp_tp *it;
320         register struct tcpcb *tp;
321
322         it = (struct inp_tp *)inp;
323         tp = &it->tcb;
324         bzero((char *) tp, sizeof(struct tcpcb));
325         tp->t_segq = NULL;
326         tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
327
328         /* Set up our timeouts. */
329         callout_init(tp->tt_rexmt = &it->inp_tp_rexmt);
330         callout_init(tp->tt_persist = &it->inp_tp_persist);
331         callout_init(tp->tt_keep = &it->inp_tp_keep);
332         callout_init(tp->tt_2msl = &it->inp_tp_2msl);
333         callout_init(tp->tt_delack = &it->inp_tp_delack);
334
335         if (tcp_do_rfc1323)
336                 tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
337         if (tcp_do_rfc1644)
338                 tp->t_flags |= TF_REQ_CC;
339         tp->t_inpcb = inp;      /* XXX */
340         /*
341          * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
342          * rtt estimate.  Set rttvar so that srtt + 4 * rttvar gives
343          * reasonable initial retransmit time.
344          */
345         tp->t_srtt = TCPTV_SRTTBASE;
346         tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
347         tp->t_rttmin = TCPTV_MIN;
348         tp->t_rxtcur = TCPTV_RTOBASE;
349         tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
350         tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
351         tp->t_rcvtime = ticks;
352         inp->inp_ip_ttl = ip_defttl;
353         inp->inp_ppcb = (caddr_t)tp;
354         return (tp);            /* XXX */
355 }
356
357 /*
358  * Drop a TCP connection, reporting
359  * the specified error.  If connection is synchronized,
360  * then send a RST to peer.
361  */
362 struct tcpcb *
363 tcp_drop(tp, errno)
364         register struct tcpcb *tp;
365         int errno;
366 {
367         struct socket *so = tp->t_inpcb->inp_socket;
368
369         if (TCPS_HAVERCVDSYN(tp->t_state)) {
370                 tp->t_state = TCPS_CLOSED;
371                 (void) tcp_output(tp);
372                 tcpstat.tcps_drops++;
373         } else
374                 tcpstat.tcps_conndrops++;
375         if (errno == ETIMEDOUT && tp->t_softerror)
376                 errno = tp->t_softerror;
377         so->so_error = errno;
378         return (tcp_close(tp));
379 }
380
381 /*
382  * Close a TCP control block:
383  *      discard all space held by the tcp
384  *      discard internet protocol block
385  *      wake up any sleepers
386  */
387 struct tcpcb *
388 tcp_close(tp)
389         register struct tcpcb *tp;
390 {
391         register struct mbuf *q;
392         register struct mbuf *nq;
393         struct inpcb *inp = tp->t_inpcb;
394         struct socket *so = inp->inp_socket;
395         register struct rtentry *rt;
396         int dosavessthresh;
397
398         /*
399          * Make sure that all of our timers are stopped before we
400          * delete the PCB.
401          */
402         callout_stop(tp->tt_rexmt);
403         callout_stop(tp->tt_persist);
404         callout_stop(tp->tt_keep);
405         callout_stop(tp->tt_2msl);
406         callout_stop(tp->tt_delack);
407
408         /*
409          * If we got enough samples through the srtt filter,
410          * save the rtt and rttvar in the routing entry.
411          * 'Enough' is arbitrarily defined as the 16 samples.
412          * 16 samples is enough for the srtt filter to converge
413          * to within 5% of the correct value; fewer samples and
414          * we could save a very bogus rtt.
415          *
416          * Don't update the default route's characteristics and don't
417          * update anything that the user "locked".
418          */
419         if (tp->t_rttupdated >= 16 &&
420             (rt = inp->inp_route.ro_rt) &&
421             ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
422                 register u_long i = 0;
423
424                 if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
425                         i = tp->t_srtt *
426                             (RTM_RTTUNIT / (hz * TCP_RTT_SCALE));
427                         if (rt->rt_rmx.rmx_rtt && i)
428                                 /*
429                                  * filter this update to half the old & half
430                                  * the new values, converting scale.
431                                  * See route.h and tcp_var.h for a
432                                  * description of the scaling constants.
433                                  */
434                                 rt->rt_rmx.rmx_rtt =
435                                     (rt->rt_rmx.rmx_rtt + i) / 2;
436                         else
437                                 rt->rt_rmx.rmx_rtt = i;
438                         tcpstat.tcps_cachedrtt++;
439                 }
440                 if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
441                         i = tp->t_rttvar *
442                             (RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE));
443                         if (rt->rt_rmx.rmx_rttvar && i)
444                                 rt->rt_rmx.rmx_rttvar =
445                                     (rt->rt_rmx.rmx_rttvar + i) / 2;
446                         else
447                                 rt->rt_rmx.rmx_rttvar = i;
448                         tcpstat.tcps_cachedrttvar++;
449                 }
450                 /*
451                  * The old comment here said:
452                  * update the pipelimit (ssthresh) if it has been updated
453                  * already or if a pipesize was specified & the threshhold
454                  * got below half the pipesize.  I.e., wait for bad news
455                  * before we start updating, then update on both good
456                  * and bad news.
457                  *
458                  * But we want to save the ssthresh even if no pipesize is
459                  * specified explicitly in the route, because such
460                  * connections still have an implicit pipesize specified
461                  * by the global tcp_sendspace.  In the absence of a reliable
462                  * way to calculate the pipesize, it will have to do.
463                  */
464                 i = tp->snd_ssthresh;
465                 if (rt->rt_rmx.rmx_sendpipe != 0)
466                         dosavessthresh = (i < rt->rt_rmx.rmx_sendpipe / 2);
467                 else
468                         dosavessthresh = (i < so->so_snd.sb_hiwat / 2);
469                 if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
470                      i != 0 && rt->rt_rmx.rmx_ssthresh != 0)
471                     || dosavessthresh) {
472                         /*
473                          * convert the limit from user data bytes to
474                          * packets then to packet data bytes.
475                          */
476                         i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
477                         if (i < 2)
478                                 i = 2;
479                         i *= (u_long)(tp->t_maxseg + sizeof (struct tcpiphdr));
480                         if (rt->rt_rmx.rmx_ssthresh)
481                                 rt->rt_rmx.rmx_ssthresh =
482                                     (rt->rt_rmx.rmx_ssthresh + i) / 2;
483                         else
484                                 rt->rt_rmx.rmx_ssthresh = i;
485                         tcpstat.tcps_cachedssthresh++;
486                 }
487         }
488         /* free the reassembly queue, if any */
489         for (q = tp->t_segq; q; q = nq) {
490                 nq = q->m_nextpkt;
491                 tp->t_segq = nq;
492                 m_freem(q);
493         }
494         if (tp->t_template)
495                 (void) m_free(dtom(tp->t_template));
496         inp->inp_ppcb = NULL;
497         soisdisconnected(so);
498         in_pcbdetach(inp);
499         tcpstat.tcps_closed++;
500         return ((struct tcpcb *)0);
501 }
502
503 void
504 tcp_drain()
505 {
506
507 }
508
509 /*
510  * Notify a tcp user of an asynchronous error;
511  * store error as soft error, but wake up user
512  * (for now, won't do anything until can select for soft error).
513  */
514 static void
515 tcp_notify(inp, error)
516         struct inpcb *inp;
517         int error;
518 {
519         register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
520         register struct socket *so = inp->inp_socket;
521
522         /*
523          * Ignore some errors if we are hooked up.
524          * If connection hasn't completed, has retransmitted several times,
525          * and receives a second error, give up now.  This is better
526          * than waiting a long time to establish a connection that
527          * can never complete.
528          */
529         if (tp->t_state == TCPS_ESTABLISHED &&
530              (error == EHOSTUNREACH || error == ENETUNREACH ||
531               error == EHOSTDOWN)) {
532                 return;
533         } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
534             tp->t_softerror)
535                 so->so_error = error;
536         else
537                 tp->t_softerror = error;
538         wakeup((caddr_t) &so->so_timeo);
539         sorwakeup(so);
540         sowwakeup(so);
541 }
542
543 static int
544 tcp_pcblist SYSCTL_HANDLER_ARGS
545 {
546         int error, i, n, s;
547         struct inpcb *inp, **inp_list;
548         inp_gen_t gencnt;
549         struct xinpgen xig;
550
551         /*
552          * The process of preparing the TCB list is too time-consuming and
553          * resource-intensive to repeat twice on every request.
554          */
555         if (req->oldptr == 0) {
556                 n = tcbinfo.ipi_count;
557                 req->oldidx = 2 * (sizeof xig)
558                         + (n + n/8) * sizeof(struct xtcpcb);
559                 return 0;
560         }
561
562         if (req->newptr != 0)
563                 return EPERM;
564
565         /*
566          * OK, now we're committed to doing something.
567          */
568         s = splnet();
569         gencnt = tcbinfo.ipi_gencnt;
570         n = tcbinfo.ipi_count;
571         splx(s);
572
573         xig.xig_len = sizeof xig;
574         xig.xig_count = n;
575         xig.xig_gen = gencnt;
576         xig.xig_sogen = so_gencnt;
577         error = SYSCTL_OUT(req, &xig, sizeof xig);
578         if (error)
579                 return error;
580
581         inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
582         if (inp_list == 0)
583                 return ENOMEM;
584         
585         s = splnet();
586         for (inp = tcbinfo.listhead->lh_first, i = 0; inp && i < n;
587              inp = inp->inp_list.le_next) {
588                 if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp))
589                         inp_list[i++] = inp;
590         }
591         splx(s);
592         n = i;
593
594         error = 0;
595         for (i = 0; i < n; i++) {
596                 inp = inp_list[i];
597                 if (inp->inp_gencnt <= gencnt) {
598                         struct xtcpcb xt;
599                         caddr_t inp_ppcb;
600                         xt.xt_len = sizeof xt;
601                         /* XXX should avoid extra copy */
602                         bcopy(inp, &xt.xt_inp, sizeof *inp);
603                         inp_ppcb = inp->inp_ppcb;
604                         if (inp_ppcb != NULL)
605                                 bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
606                         else
607                                 bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
608                         if (inp->inp_socket)
609                                 sotoxsocket(inp->inp_socket, &xt.xt_socket);
610                         error = SYSCTL_OUT(req, &xt, sizeof xt);
611                 }
612         }
613         if (!error) {
614                 /*
615                  * Give the user an updated idea of our state.
616                  * If the generation differs from what we told
617                  * her before, she knows that something happened
618                  * while we were processing this request, and it
619                  * might be necessary to retry.
620                  */
621                 s = splnet();
622                 xig.xig_gen = tcbinfo.ipi_gencnt;
623                 xig.xig_sogen = so_gencnt;
624                 xig.xig_count = tcbinfo.ipi_count;
625                 splx(s);
626                 error = SYSCTL_OUT(req, &xig, sizeof xig);
627         }
628         free(inp_list, M_TEMP);
629         return error;
630 }
631
632 SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
633             tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
634
635 static int
636 tcp_getcred SYSCTL_HANDLER_ARGS
637 {
638         struct sockaddr_in addrs[2];
639         struct inpcb *inp;
640         int error, s;
641
642         error = suser(req->p);
643         if (error)
644                 return (error);
645         error = SYSCTL_IN(req, addrs, sizeof(addrs));
646         if (error)
647                 return (error);
648         s = splnet();
649         inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
650             addrs[0].sin_addr, addrs[0].sin_port, 0);
651         if (inp == NULL || inp->inp_socket == NULL) {
652                 error = ENOENT;
653                 goto out;
654         }
655         error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
656 out:
657         splx(s);
658         return (error);
659 }
660
661 SYSCTL_PROC(_net_inet_tcp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
662     0, 0, tcp_getcred, "S,ucred", "Get the ucred of a TCP connection");
663
664 void
665 tcp_ctlinput(cmd, sa, vip)
666         int cmd;
667         struct sockaddr *sa;
668         void *vip;
669 {
670         register struct ip *ip = vip;
671         register struct tcphdr *th;
672         void (*notify) __P((struct inpcb *, int)) = tcp_notify;
673
674         if (cmd == PRC_QUENCH)
675                 notify = tcp_quench;
676         else if (cmd == PRC_MSGSIZE)
677                 notify = tcp_mtudisc;
678         else if (!PRC_IS_REDIRECT(cmd) &&
679                  ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0))
680                 return;
681         if (ip) {
682                 th = (struct tcphdr *)((caddr_t)ip 
683                                        + (IP_VHL_HL(ip->ip_vhl) << 2));
684                 in_pcbnotify(&tcb, sa, th->th_dport, ip->ip_src, th->th_sport,
685                         cmd, notify);
686         } else
687                 in_pcbnotify(&tcb, sa, 0, zeroin_addr, 0, cmd, notify);
688 }
689
690 /*
691  * When a source quench is received, close congestion window
692  * to one segment.  We will gradually open it again as we proceed.
693  */
694 void
695 tcp_quench(inp, errno)
696         struct inpcb *inp;
697         int errno;
698 {
699         struct tcpcb *tp = intotcpcb(inp);
700
701         if (tp)
702                 tp->snd_cwnd = tp->t_maxseg;
703 }
704
705 /*
706  * When `need fragmentation' ICMP is received, update our idea of the MSS
707  * based on the new value in the route.  Also nudge TCP to send something,
708  * since we know the packet we just sent was dropped.
709  * This duplicates some code in the tcp_mss() function in tcp_input.c.
710  */
711 void
712 tcp_mtudisc(inp, errno)
713         struct inpcb *inp;
714         int errno;
715 {
716         struct tcpcb *tp = intotcpcb(inp);
717         struct rtentry *rt;
718         struct rmxp_tao *taop;
719         struct socket *so = inp->inp_socket;
720         int offered;
721         int mss;
722
723         if (tp) {
724                 rt = tcp_rtlookup(inp);
725                 if (!rt || !rt->rt_rmx.rmx_mtu) {
726                         tp->t_maxopd = tp->t_maxseg = tcp_mssdflt;
727                         return;
728                 }
729                 taop = rmx_taop(rt->rt_rmx);
730                 offered = taop->tao_mssopt;
731                 mss = rt->rt_rmx.rmx_mtu - sizeof(struct tcpiphdr);
732                 if (offered)
733                         mss = min(mss, offered);
734                 /*
735                  * XXX - The above conditional probably violates the TCP
736                  * spec.  The problem is that, since we don't know the
737                  * other end's MSS, we are supposed to use a conservative
738                  * default.  But, if we do that, then MTU discovery will
739                  * never actually take place, because the conservative
740                  * default is much less than the MTUs typically seen
741                  * on the Internet today.  For the moment, we'll sweep
742                  * this under the carpet.
743                  *
744                  * The conservative default might not actually be a problem
745                  * if the only case this occurs is when sending an initial
746                  * SYN with options and data to a host we've never talked
747                  * to before.  Then, they will reply with an MSS value which
748                  * will get recorded and the new parameters should get
749                  * recomputed.  For Further Study.
750                  */
751                 if (tp->t_maxopd <= mss)
752                         return;
753                 tp->t_maxopd = mss;
754
755                 if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
756                     (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
757                         mss -= TCPOLEN_TSTAMP_APPA;
758                 if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
759                     (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)
760                         mss -= TCPOLEN_CC_APPA;
761 #if     (MCLBYTES & (MCLBYTES - 1)) == 0
762                 if (mss > MCLBYTES)
763                         mss &= ~(MCLBYTES-1);
764 #else
765                 if (mss > MCLBYTES)
766                         mss = mss / MCLBYTES * MCLBYTES;
767 #endif
768                 if (so->so_snd.sb_hiwat < mss)
769                         mss = so->so_snd.sb_hiwat;
770
771                 tp->t_maxseg = mss;
772
773                 tcpstat.tcps_mturesent++;
774                 tp->t_rtttime = 0;
775                 tp->snd_nxt = tp->snd_una;
776                 tcp_output(tp);
777         }
778 }
779
780 /*
781  * Look-up the routing entry to the peer of this inpcb.  If no route
782  * is found and it cannot be allocated the return NULL.  This routine
783  * is called by TCP routines that access the rmx structure and by tcp_mss
784  * to get the interface MTU.
785  */
786 struct rtentry *
787 tcp_rtlookup(inp)
788         struct inpcb *inp;
789 {
790         struct route *ro;
791         struct rtentry *rt;
792
793         ro = &inp->inp_route;
794         rt = ro->ro_rt;
795         if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
796                 /* No route yet, so try to acquire one */
797                 if (inp->inp_faddr.s_addr != INADDR_ANY) {
798                         ro->ro_dst.sa_family = AF_INET;
799                         ro->ro_dst.sa_len = sizeof(ro->ro_dst);
800                         ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
801                                 inp->inp_faddr;
802                         rtalloc(ro);
803                         rt = ro->ro_rt;
804                 }
805         }
806         return rt;
807 }
808
809 /*
810  * Return a pointer to the cached information about the remote host.
811  * The cached information is stored in the protocol specific part of
812  * the route metrics.
813  */
814 struct rmxp_tao *
815 tcp_gettaocache(inp)
816         struct inpcb *inp;
817 {
818         struct rtentry *rt = tcp_rtlookup(inp);
819
820         /* Make sure this is a host route and is up. */
821         if (rt == NULL ||
822             (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
823                 return NULL;
824
825         return rmx_taop(rt->rt_rmx);
826 }
827
828 /*
829  * Clear all the TAO cache entries, called from tcp_init.
830  *
831  * XXX
832  * This routine is just an empty one, because we assume that the routing
833  * routing tables are initialized at the same time when TCP, so there is
834  * nothing in the cache left over.
835  */
836 static void
837 tcp_cleartaocache()
838 {
839 }