OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [net/] [bsd_tcpip/] [current/] [src/] [sys/] [netinet/] [tcp_subr.c] - Blame information for rev 838

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      src/sys/netinet/tcp_subr.c
4
//
5
//==========================================================================
6
// ####BSDCOPYRIGHTBEGIN####                                    
7
// -------------------------------------------                  
8
// This file is part of eCos, the Embedded Configurable Operating System.
9
//
10
// Portions of this software may have been derived from FreeBSD 
11
// or other sources, and if so are covered by the appropriate copyright
12
// and license included herein.                                 
13
//
14
// Portions created by the Free Software Foundation are         
15
// Copyright (C) 2002 Free Software Foundation, Inc.            
16
// -------------------------------------------                  
17
// ####BSDCOPYRIGHTEND####                                      
18
//==========================================================================
19
 
20
/*
21
 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
22
 *      The Regents of the University of California.  All rights reserved.
23
 *
24
 * Redistribution and use in source and binary forms, with or without
25
 * modification, are permitted provided that the following conditions
26
 * are met:
27
 * 1. Redistributions of source code must retain the above copyright
28
 *    notice, this list of conditions and the following disclaimer.
29
 * 2. Redistributions in binary form must reproduce the above copyright
30
 *    notice, this list of conditions and the following disclaimer in the
31
 *    documentation and/or other materials provided with the distribution.
32
 * 3. All advertising materials mentioning features or use of this software
33
 *    must display the following acknowledgement:
34
 *      This product includes software developed by the University of
35
 *      California, Berkeley and its contributors.
36
 * 4. Neither the name of the University nor the names of its contributors
37
 *    may be used to endorse or promote products derived from this software
38
 *    without specific prior written permission.
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 *
52
 *      @(#)tcp_subr.c  8.2 (Berkeley) 5/24/95
53
 * $FreeBSD: src/sys/netinet/tcp_subr.c,v 1.73.2.22 2001/08/22 00:59:12 silby Exp $
54
 */
55
 
56
#include <sys/param.h>
57
#include <sys/malloc.h>
58
#include <sys/sysctl.h>
59
#include <sys/mbuf.h>
60
#ifdef INET6
61
#include <sys/domain.h>
62
#endif
63
#include <sys/socket.h>
64
#include <sys/socketvar.h>
65
#include <sys/protosw.h>
66
 
67
#include <net/route.h>
68
#include <net/if.h>
69
 
70
#define _IP_VHL
71
#include <netinet/in.h>
72
#include <netinet/in_systm.h>
73
#include <netinet/ip.h>
74
#ifdef INET6
75
#include <netinet/ip6.h>
76
#endif
77
#include <netinet/in_pcb.h>
78
#ifdef INET6
79
#include <netinet6/in6_pcb.h>
80
#endif
81
#include <netinet/in_var.h>
82
#include <netinet/ip_var.h>
83
#ifdef INET6
84
#include <netinet6/ip6_var.h>
85
#endif
86
#include <netinet/tcp.h>
87
#include <netinet/tcp_fsm.h>
88
#include <netinet/tcp_seq.h>
89
#include <netinet/tcp_timer.h>
90
#include <netinet/tcp_var.h>
91
#ifdef INET6
92
#include <netinet6/tcp6_var.h>
93
#include <netinet6/ip6protosw.h>
94
#endif
95
#include <netinet/tcpip.h>
96
#ifdef TCPDEBUG
97
#include <netinet/tcp_debug.h>
98
#endif
99
 
100
#ifdef IPSEC
101
#include <netinet6/ipsec.h>
102
#endif /*IPSEC*/
103
 
104
#include <sys/md5.h>
105
 
106
int     tcp_mssdflt = TCP_MSS;
107
SYSCTL_INT(_net_inet_tcp, TCPCTL_MSSDFLT, mssdflt, CTLFLAG_RW,
108
    &tcp_mssdflt , 0, "Default TCP Maximum Segment Size");
109
 
110
#ifdef INET6
111
int     tcp_v6mssdflt = TCP6_MSS;
112
SYSCTL_INT(_net_inet_tcp, TCPCTL_V6MSSDFLT, v6mssdflt,
113
        CTLFLAG_RW, &tcp_v6mssdflt , 0,
114
        "Default TCP Maximum Segment Size for IPv6");
115
#endif
116
 
117
#if 0
118
static int      tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
119
SYSCTL_INT(_net_inet_tcp, TCPCTL_RTTDFLT, rttdflt, CTLFLAG_RW,
120
    &tcp_rttdflt , 0, "Default maximum TCP Round Trip Time");
121
#endif
122
 
123
static int      tcp_do_rfc1323 = 1;
124
SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1323, rfc1323, CTLFLAG_RW,
125
    &tcp_do_rfc1323 , 0, "Enable rfc1323 (high performance TCP) extensions");
126
 
127
static int      tcp_do_rfc1644 = 0;
128
SYSCTL_INT(_net_inet_tcp, TCPCTL_DO_RFC1644, rfc1644, CTLFLAG_RW,
129
    &tcp_do_rfc1644 , 0, "Enable rfc1644 (TTCP) extensions");
130
 
131
static int      tcp_tcbhashsize = 0;
132
SYSCTL_INT(_net_inet_tcp, OID_AUTO, tcbhashsize, CTLFLAG_RD,
133
     &tcp_tcbhashsize, 0, "Size of TCP control-block hashtable");
134
 
135
static int      do_tcpdrain = 1;
136
SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_tcpdrain, CTLFLAG_RW, &do_tcpdrain, 0,
137
     "Enable tcp_drain routine for extra help when low on mbufs");
138
 
139
SYSCTL_INT(_net_inet_tcp, OID_AUTO, pcbcount, CTLFLAG_RD,
140
    &tcbinfo.ipi_count, 0, "Number of active PCBs");
141
 
142
static int      icmp_may_rst = 1;
143
SYSCTL_INT(_net_inet_tcp, OID_AUTO, icmp_may_rst, CTLFLAG_RW, &icmp_may_rst, 0,
144
    "Certain ICMP unreachable messages may abort connections in SYN_SENT");
145
 
146
static int      tcp_strict_rfc1948 = 0;
147
SYSCTL_INT(_net_inet_tcp, OID_AUTO, strict_rfc1948, CTLFLAG_RW,
148
    &tcp_strict_rfc1948, 0, "Determines if RFC1948 is followed exactly");
149
 
150
static int      tcp_isn_reseed_interval = 0;
151
SYSCTL_INT(_net_inet_tcp, OID_AUTO, isn_reseed_interval, CTLFLAG_RW,
152
    &tcp_isn_reseed_interval, 0, "Seconds between reseeding of ISN secret");
153
 
154
static void     tcp_cleartaocache __P((void));
155
static void     tcp_notify __P((struct inpcb *, int));
156
 
157
/*
158
 * Target size of TCP PCB hash tables. Must be a power of two.
159
 *
160
 * Note that this can be overridden by the kernel environment
161
 * variable net.inet.tcp.tcbhashsize
162
 */
163
#ifndef TCBHASHSIZE
164
#define TCBHASHSIZE     512
165
#endif
166
 
167
/*
168
 * This is the actual shape of what we allocate using the zone
169
 * allocator.  Doing it this way allows us to protect both structures
170
 * using the same generation count, and also eliminates the overhead
171
 * of allocating tcpcbs separately.  By hiding the structure here,
172
 * we avoid changing most of the rest of the code (although it needs
173
 * to be changed, eventually, for greater efficiency).
174
 */
175
#define ALIGNMENT       32
176
#define ALIGNM1         (ALIGNMENT - 1)
177
struct  inp_tp {
178
        union {
179
                struct  inpcb inp;
180
                char    align[(sizeof(struct inpcb) + ALIGNM1) & ~ALIGNM1];
181
        } inp_tp_u;
182
        struct  tcpcb tcb;
183
        struct  callout inp_tp_rexmt, inp_tp_persist, inp_tp_keep, inp_tp_2msl;
184
        struct  callout inp_tp_delack;
185
};
186
#undef ALIGNMENT
187
#undef ALIGNM1
188
 
189
/*
190
 * Tcp initialization
191
 */
192
void
193
tcp_init()
194
{
195
        int hashsize = TCBHASHSIZE;
196
 
197
        tcp_ccgen = 1;
198
        tcp_cleartaocache();
199
 
200
        tcp_delacktime = TCPTV_DELACK;
201
        tcp_keepinit = TCPTV_KEEP_INIT;
202
        tcp_keepidle = TCPTV_KEEP_IDLE;
203
        tcp_keepintvl = TCPTV_KEEPINTVL;
204
        tcp_maxpersistidle = TCPTV_KEEP_IDLE;
205
        tcp_msl = TCPTV_MSL;
206
        tcp_rexmit_min = TCPTV_MIN;
207
 
208
        LIST_INIT(&tcb);
209
        tcbinfo.listhead = &tcb;
210
        tcp_tcbhashsize = hashsize;
211
        tcbinfo.hashbase = hashinit(hashsize, M_PCB, &tcbinfo.hashmask);
212
        tcbinfo.porthashbase = hashinit(hashsize, M_PCB,
213
                                        &tcbinfo.porthashmask);
214
        tcbinfo.ipi_zone = zinit("tcpcb", sizeof(struct inp_tp), maxsockets,
215
                                 ZONE_INTERRUPT, 0);
216
#ifdef CYGNUM_NET_TCP_REASS_DIVISOR
217
        tcp_reass_maxseg = nmbclusters / CYGNUM_NET_TCP_REASS_DIVISOR;
218
#endif
219
 
220
#ifdef INET6
221
#define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
222
#else /* INET6 */
223
#define TCP_MINPROTOHDR (sizeof(struct tcpiphdr))
224
#endif /* INET6 */
225
        if (max_protohdr < TCP_MINPROTOHDR)
226
                max_protohdr = TCP_MINPROTOHDR;
227
        if (max_linkhdr + TCP_MINPROTOHDR > MHLEN)
228
                panic("tcp_init");
229
#undef TCP_MINPROTOHDR
230
}
231
 
232
/*
233
 * Fill in the IP and TCP headers for an outgoing packet, given the tcpcb.
234
 * tcp_template used to store this data in mbufs, but we now recopy it out
235
 * of the tcpcb each time to conserve mbufs.
236
 */
237
void
238
tcp_fillheaders(tp, ip_ptr, tcp_ptr)
239
        struct tcpcb *tp;
240
        void *ip_ptr;
241
        void *tcp_ptr;
242
{
243
        struct inpcb *inp = tp->t_inpcb;
244
        struct tcphdr *tcp_hdr = (struct tcphdr *)tcp_ptr;
245
 
246
#ifdef INET6
247
        if ((inp->inp_vflag & INP_IPV6) != 0) {
248
                struct ip6_hdr *ip6;
249
 
250
                ip6 = (struct ip6_hdr *)ip_ptr;
251
                ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
252
                        (inp->in6p_flowinfo & IPV6_FLOWINFO_MASK);
253
                ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
254
                        (IPV6_VERSION & IPV6_VERSION_MASK);
255
                ip6->ip6_nxt = IPPROTO_TCP;
256
                ip6->ip6_plen = sizeof(struct tcphdr);
257
                ip6->ip6_src = inp->in6p_laddr;
258
                ip6->ip6_dst = inp->in6p_faddr;
259
                tcp_hdr->th_sum = 0;
260
        } else
261
#endif
262
        {
263
        struct ip *ip = (struct ip *) ip_ptr;
264
 
265
        ip->ip_vhl = IP_VHL_BORING;
266
        ip->ip_tos = 0;
267
        ip->ip_len = 0;
268
        ip->ip_id = 0;
269
        ip->ip_off = 0;
270
        ip->ip_ttl = 0;
271
        ip->ip_sum = 0;
272
        ip->ip_p = IPPROTO_TCP;
273
        ip->ip_src = inp->inp_laddr;
274
        ip->ip_dst = inp->inp_faddr;
275
        tcp_hdr->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
276
                htons(sizeof(struct tcphdr) + IPPROTO_TCP));
277
        }
278
 
279
        tcp_hdr->th_sport = inp->inp_lport;
280
        tcp_hdr->th_dport = inp->inp_fport;
281
        tcp_hdr->th_seq = 0;
282
        tcp_hdr->th_ack = 0;
283
        tcp_hdr->th_x2 = 0;
284
        tcp_hdr->th_off = 5;
285
        tcp_hdr->th_flags = 0;
286
        tcp_hdr->th_win = 0;
287
        tcp_hdr->th_urp = 0;
288
}
289
 
290
/*
291
 * Create template to be used to send tcp packets on a connection.
292
 * Allocates an mbuf and fills in a skeletal tcp/ip header.  The only
293
 * use for this function is in keepalives, which use tcp_respond.
294
 */
295
struct tcptemp *
296
tcp_maketemplate(tp)
297
        struct tcpcb *tp;
298
{
299
        struct mbuf *m;
300
        struct tcptemp *n;
301
 
302
        m = m_get(M_DONTWAIT, MT_HEADER);
303
        if (m == NULL)
304
                return (0);
305
        m->m_len = sizeof(struct tcptemp);
306
        n = mtod(m, struct tcptemp *);
307
 
308
        tcp_fillheaders(tp, (void *)&n->tt_ipgen, (void *)&n->tt_t);
309
        return (n);
310
}
311
 
312
/*
313
 * Send a single message to the TCP at address specified by
314
 * the given TCP/IP header.  If m == 0, then we make a copy
315
 * of the tcpiphdr at ti and send directly to the addressed host.
316
 * This is used to force keep alive messages out using the TCP
317
 * template for a connection.  If flags are given then we send
318
 * a message back to the TCP which originated the * segment ti,
319
 * and discard the mbuf containing it and any other attached mbufs.
320
 *
321
 * In any case the ack and sequence number of the transmitted
322
 * segment are as specified by the parameters.
323
 *
324
 * NOTE: If m != NULL, then ti must point to *inside* the mbuf.
325
 */
326
void
327
tcp_respond(tp, ipgen, th, m, ack, seq, flags)
328
        struct tcpcb *tp;
329
        void *ipgen;
330
        register struct tcphdr *th;
331
        register struct mbuf *m;
332
        tcp_seq ack, seq;
333
        int flags;
334
{
335
        register int tlen;
336
        int win = 0;
337
        struct route *ro = 0;
338
        struct route sro;
339
        struct ip *ip;
340
        struct tcphdr *nth;
341
#ifdef INET6
342
#ifdef NEW_STRUCT_ROUTE
343
        struct route *ro6 = 0;
344
        struct route sro6;
345
#else
346
        struct route_in6 *ro6 = 0;
347
        struct route_in6 sro6;
348
#endif
349
        struct ip6_hdr *ip6;
350
        int isipv6;
351
#endif /* INET6 */
352
        int ipflags = 0;
353
 
354
#ifdef INET6
355
        isipv6 = IP_VHL_V(((struct ip *)ipgen)->ip_vhl) == 6;
356
        ip6 = ipgen;
357
#endif /* INET6 */
358
        ip = ipgen;
359
 
360
        if (tp) {
361
                if (!(flags & TH_RST)) {
362
                        win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
363
                        if (win > (long)TCP_MAXWIN << tp->rcv_scale)
364
                                win = (long)TCP_MAXWIN << tp->rcv_scale;
365
                }
366
#ifdef INET6
367
                if (isipv6)
368
                        ro6 = &tp->t_inpcb->in6p_route;
369
                else
370
#endif /* INET6 */
371
                ro = &tp->t_inpcb->inp_route;
372
        } else {
373
#ifdef INET6
374
                if (isipv6) {
375
                        ro6 = &sro6;
376
                        bzero(ro6, sizeof *ro6);
377
                } else
378
#endif /* INET6 */
379
              {
380
                ro = &sro;
381
                bzero(ro, sizeof *ro);
382
              }
383
        }
384
        if (m == 0) {
385
                m = m_gethdr(M_DONTWAIT, MT_HEADER);
386
                if (m == NULL)
387
                        return;
388
                tlen = 0;
389
                m->m_data += max_linkhdr;
390
#ifdef INET6
391
                if (isipv6) {
392
                        bcopy((caddr_t)ip6, mtod(m, caddr_t),
393
                              sizeof(struct ip6_hdr));
394
                        ip6 = mtod(m, struct ip6_hdr *);
395
                        nth = (struct tcphdr *)(ip6 + 1);
396
                } else
397
#endif /* INET6 */
398
              {
399
                bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
400
                ip = mtod(m, struct ip *);
401
                nth = (struct tcphdr *)(ip + 1);
402
              }
403
                bcopy((caddr_t)th, (caddr_t)nth, sizeof(struct tcphdr));
404
                flags = TH_ACK;
405
        } else {
406
                m_freem(m->m_next);
407
                m->m_next = 0;
408
                m->m_data = (caddr_t)ipgen;
409
                /* m_len is set later */
410
                tlen = 0;
411
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
412
#ifdef INET6
413
                if (isipv6) {
414
                        xchg(ip6->ip6_dst, ip6->ip6_src, struct in6_addr);
415
                        nth = (struct tcphdr *)(ip6 + 1);
416
                } else
417
#endif /* INET6 */
418
              {
419
                xchg(ip->ip_dst.s_addr, ip->ip_src.s_addr, n_long);
420
                nth = (struct tcphdr *)(ip + 1);
421
              }
422
                if (th != nth) {
423
                        /*
424
                         * this is usually a case when an extension header
425
                         * exists between the IPv6 header and the
426
                         * TCP header.
427
                         */
428
                        nth->th_sport = th->th_sport;
429
                        nth->th_dport = th->th_dport;
430
                }
431
                xchg(nth->th_dport, nth->th_sport, n_short);
432
#undef xchg
433
        }
434
#ifdef INET6
435
        if (isipv6) {
436
                ip6->ip6_plen = htons((u_short)(sizeof (struct tcphdr) +
437
                                                tlen));
438
                tlen += sizeof (struct ip6_hdr) + sizeof (struct tcphdr);
439
        } else
440
#endif
441
      {
442
        tlen += sizeof (struct tcpiphdr);
443
        ip->ip_len = tlen;
444
        ip->ip_ttl = ip_defttl;
445
      }
446
        m->m_len = tlen;
447
        m->m_pkthdr.len = tlen;
448
        m->m_pkthdr.rcvif = (struct ifnet *) 0;
449
        nth->th_seq = htonl(seq);
450
        nth->th_ack = htonl(ack);
451
        nth->th_x2 = 0;
452
        nth->th_off = sizeof (struct tcphdr) >> 2;
453
        nth->th_flags = flags;
454
        if (tp)
455
                nth->th_win = htons((u_short) (win >> tp->rcv_scale));
456
        else
457
                nth->th_win = htons((u_short)win);
458
        nth->th_urp = 0;
459
#ifdef INET6
460
        if (isipv6) {
461
                nth->th_sum = 0;
462
                nth->th_sum = in6_cksum(m, IPPROTO_TCP,
463
                                        sizeof(struct ip6_hdr),
464
                                        tlen - sizeof(struct ip6_hdr));
465
                ip6->ip6_hlim = in6_selecthlim(tp ? tp->t_inpcb : NULL,
466
                                               ro6 && ro6->ro_rt ?
467
                                               ro6->ro_rt->rt_ifp :
468
                                               NULL);
469
        } else
470
#endif /* INET6 */
471
      {
472
        nth->th_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
473
            htons((u_short)(tlen - sizeof(struct ip) + ip->ip_p)));
474
        m->m_pkthdr.csum_flags = CSUM_TCP;
475
        m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
476
      }
477
#ifdef TCPDEBUG
478
        if (tp == NULL || (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
479
                tcp_trace(TA_OUTPUT, 0, tp, mtod(m, void *), th, 0);
480
#endif
481
#ifdef IPSEC
482
        if (ipsec_setsocket(m, tp ? tp->t_inpcb->inp_socket : NULL) != 0) {
483
                m_freem(m);
484
                return;
485
        }
486
#endif
487
#ifdef INET6
488
        if (isipv6) {
489
                (void)ip6_output(m, NULL, ro6, ipflags, NULL, NULL);
490
                if (ro6 == &sro6 && ro6->ro_rt) {
491
                        RTFREE(ro6->ro_rt);
492
                        ro6->ro_rt = NULL;
493
                }
494
        } else
495
#endif /* INET6 */
496
      {
497
        (void) ip_output(m, NULL, ro, ipflags, NULL);
498
        if (ro == &sro && ro->ro_rt) {
499
                RTFREE(ro->ro_rt);
500
                ro->ro_rt = NULL;
501
        }
502
      }
503
}
504
 
505
/*
506
 * Create a new TCP control block, making an
507
 * empty reassembly queue and hooking it to the argument
508
 * protocol control block.  The `inp' parameter must have
509
 * come from the zone allocator set up in tcp_init().
510
 */
511
struct tcpcb *
512
tcp_newtcpcb(inp)
513
        struct inpcb *inp;
514
{
515
        struct inp_tp *it;
516
        register struct tcpcb *tp;
517
#ifdef INET6
518
        int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
519
#endif /* INET6 */
520
 
521
        it = (struct inp_tp *)inp;
522
        tp = &it->tcb;
523
        bzero((char *) tp, sizeof(struct tcpcb));
524
        LIST_INIT(&tp->t_segq);
525
        tp->t_maxseg = tp->t_maxopd =
526
#ifdef INET6
527
                isipv6 ? tcp_v6mssdflt :
528
#endif /* INET6 */
529
                tcp_mssdflt;
530
 
531
        /* Set up our timeouts. */
532
        callout_init(tp->tt_rexmt = &it->inp_tp_rexmt);
533
        callout_init(tp->tt_persist = &it->inp_tp_persist);
534
        callout_init(tp->tt_keep = &it->inp_tp_keep);
535
        callout_init(tp->tt_2msl = &it->inp_tp_2msl);
536
        callout_init(tp->tt_delack = &it->inp_tp_delack);
537
 
538
        if (tcp_do_rfc1323)
539
                tp->t_flags = (TF_REQ_SCALE|TF_REQ_TSTMP);
540
        if (tcp_do_rfc1644)
541
                tp->t_flags |= TF_REQ_CC;
542
        tp->t_inpcb = inp;      /* XXX */
543
        /*
544
         * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
545
         * rtt estimate.  Set rttvar so that srtt + 4 * rttvar gives
546
         * reasonable initial retransmit time.
547
         */
548
        tp->t_srtt = TCPTV_SRTTBASE;
549
        tp->t_rttvar = ((TCPTV_RTOBASE - TCPTV_SRTTBASE) << TCP_RTTVAR_SHIFT) / 4;
550
        tp->t_rttmin = tcp_rexmit_min;
551
        tp->t_rxtcur = TCPTV_RTOBASE;
552
        tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
553
        tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
554
        tp->t_rcvtime = ticks;
555
        /*
556
         * IPv4 TTL initialization is necessary for an IPv6 socket as well,
557
         * because the socket may be bound to an IPv6 wildcard address,
558
         * which may match an IPv4-mapped IPv6 address.
559
         */
560
        inp->inp_ip_ttl = ip_defttl;
561
        inp->inp_ppcb = (caddr_t)tp;
562
        return (tp);            /* XXX */
563
}
564
 
565
/*
566
 * Drop a TCP connection, reporting
567
 * the specified error.  If connection is synchronized,
568
 * then send a RST to peer.
569
 */
570
struct tcpcb *
571
tcp_drop(tp, _errno)
572
        register struct tcpcb *tp;
573
        int _errno;
574
{
575
        struct socket *so = tp->t_inpcb->inp_socket;
576
 
577
        if (TCPS_HAVERCVDSYN(tp->t_state)) {
578
                tp->t_state = TCPS_CLOSED;
579
                (void) tcp_output(tp);
580
                tcpstat.tcps_drops++;
581
        } else
582
                tcpstat.tcps_conndrops++;
583
        if (_errno == ETIMEDOUT && tp->t_softerror)
584
                _errno = tp->t_softerror;
585
        so->so_error = _errno;
586
        return (tcp_close(tp));
587
}
588
 
589
/*
590
 * Close a TCP control block:
591
 *      discard all space held by the tcp
592
 *      discard internet protocol block
593
 *      wake up any sleepers
594
 */
595
struct tcpcb *
596
tcp_close(tp)
597
        register struct tcpcb *tp;
598
{
599
        register struct tseg_qent *q;
600
        struct inpcb *inp = tp->t_inpcb;
601
        struct socket *so = inp->inp_socket;
602
#ifdef INET6
603
        int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
604
#endif /* INET6 */
605
        register struct rtentry *rt;
606
        int dosavessthresh;
607
 
608
        /*
609
         * Make sure that all of our timers are stopped before we
610
         * delete the PCB.
611
         */
612
        callout_stop(tp->tt_rexmt);
613
        callout_stop(tp->tt_persist);
614
        callout_stop(tp->tt_keep);
615
        callout_stop(tp->tt_2msl);
616
        callout_stop(tp->tt_delack);
617
 
618
        /*
619
         * If we got enough samples through the srtt filter,
620
         * save the rtt and rttvar in the routing entry.
621
         * 'Enough' is arbitrarily defined as the 16 samples.
622
         * 16 samples is enough for the srtt filter to converge
623
         * to within 5% of the correct value; fewer samples and
624
         * we could save a very bogus rtt.
625
         *
626
         * Don't update the default route's characteristics and don't
627
         * update anything that the user "locked".
628
         */
629
        if (tp->t_rttupdated >= 16) {
630
                register u_long i = 0;
631
#ifdef INET6
632
                if (isipv6) {
633
                        struct sockaddr_in6 *sin6;
634
 
635
                        if ((rt = inp->in6p_route.ro_rt) == NULL)
636
                                goto no_valid_rt;
637
                        sin6 = (struct sockaddr_in6 *)rt_key(rt);
638
                        if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
639
                                goto no_valid_rt;
640
                }
641
                else
642
#endif /* INET6 */              
643
                if ((rt = inp->inp_route.ro_rt) == NULL ||
644
                    ((struct sockaddr_in *)rt_key(rt))->sin_addr.s_addr
645
                    == INADDR_ANY)
646
                        goto no_valid_rt;
647
 
648
                if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
649
                        i = tp->t_srtt *
650
                            (RTM_RTTUNIT / (hz * TCP_RTT_SCALE));
651
                        if (rt->rt_rmx.rmx_rtt && i)
652
                                /*
653
                                 * filter this update to half the old & half
654
                                 * the new values, converting scale.
655
                                 * See route.h and tcp_var.h for a
656
                                 * description of the scaling constants.
657
                                 */
658
                                rt->rt_rmx.rmx_rtt =
659
                                    (rt->rt_rmx.rmx_rtt + i) / 2;
660
                        else
661
                                rt->rt_rmx.rmx_rtt = i;
662
                        tcpstat.tcps_cachedrtt++;
663
                }
664
                if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
665
                        i = tp->t_rttvar *
666
                            (RTM_RTTUNIT / (hz * TCP_RTTVAR_SCALE));
667
                        if (rt->rt_rmx.rmx_rttvar && i)
668
                                rt->rt_rmx.rmx_rttvar =
669
                                    (rt->rt_rmx.rmx_rttvar + i) / 2;
670
                        else
671
                                rt->rt_rmx.rmx_rttvar = i;
672
                        tcpstat.tcps_cachedrttvar++;
673
                }
674
                /*
675
                 * The old comment here said:
676
                 * update the pipelimit (ssthresh) if it has been updated
677
                 * already or if a pipesize was specified & the threshhold
678
                 * got below half the pipesize.  I.e., wait for bad news
679
                 * before we start updating, then update on both good
680
                 * and bad news.
681
                 *
682
                 * But we want to save the ssthresh even if no pipesize is
683
                 * specified explicitly in the route, because such
684
                 * connections still have an implicit pipesize specified
685
                 * by the global tcp_sendspace.  In the absence of a reliable
686
                 * way to calculate the pipesize, it will have to do.
687
                 */
688
                i = tp->snd_ssthresh;
689
                if (rt->rt_rmx.rmx_sendpipe != 0)
690
                        dosavessthresh = (i < rt->rt_rmx.rmx_sendpipe / 2);
691
                else
692
                        dosavessthresh = (i < so->so_snd.sb_hiwat / 2);
693
                if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
694
                     i != 0 && rt->rt_rmx.rmx_ssthresh != 0)
695
                    || dosavessthresh) {
696
                        /*
697
                         * convert the limit from user data bytes to
698
                         * packets then to packet data bytes.
699
                         */
700
                        i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
701
                        if (i < 2)
702
                                i = 2;
703
                        i *= (u_long)(tp->t_maxseg +
704
#ifdef INET6
705
                                      (isipv6 ? sizeof (struct ip6_hdr) +
706
                                               sizeof (struct tcphdr) :
707
#endif
708
                                       sizeof (struct tcpiphdr)
709
#ifdef INET6
710
                                       )
711
#endif
712
                                      );
713
                        if (rt->rt_rmx.rmx_ssthresh)
714
                                rt->rt_rmx.rmx_ssthresh =
715
                                    (rt->rt_rmx.rmx_ssthresh + i) / 2;
716
                        else
717
                                rt->rt_rmx.rmx_ssthresh = i;
718
                        tcpstat.tcps_cachedssthresh++;
719
                }
720
        }
721
        rt = inp->inp_route.ro_rt;
722
        if (rt) {
723
                /*
724
                 * mark route for deletion if no information is
725
                 * cached.
726
                 */
727
                if ((tp->t_flags & TF_LQ_OVERFLOW) &&
728
                    ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0)){
729
                        if (rt->rt_rmx.rmx_rtt == 0)
730
                                rt->rt_flags |= RTF_DELCLONE;
731
                }
732
        }
733
    no_valid_rt:
734
        /* free the reassembly queue, if any */
735
        while((q = LIST_FIRST(&tp->t_segq)) != NULL) {
736
                LIST_REMOVE(q, tqe_q);
737
                m_freem(q->tqe_m);
738
                FREE(q, M_TSEGQ);
739
#ifdef CYGNUM_NET_TCP_REASS_DIVISOR
740
                tcp_reass_qsize--;
741
#endif
742
        }
743
        inp->inp_ppcb = NULL;
744
        soisdisconnected(so);
745
#ifdef INET6
746
        if (INP_CHECK_SOCKAF(so, AF_INET6))
747
                in6_pcbdetach(inp);
748
        else
749
#endif /* INET6 */
750
        in_pcbdetach(inp);
751
        tcpstat.tcps_closed++;
752
        return ((struct tcpcb *)0);
753
}
754
 
755
void
756
tcp_drain()
757
{
758
        if (do_tcpdrain)
759
        {
760
                struct inpcb *inpb;
761
                struct tcpcb *tcpb;
762
                struct tseg_qent *te;
763
 
764
        /*
765
         * Walk the tcpbs, if existing, and flush the reassembly queue,
766
         * if there is one...
767
         * XXX: The "Net/3" implementation doesn't imply that the TCP
768
         *      reassembly queue should be flushed, but in a situation
769
         *      where we're really low on mbufs, this is potentially
770
         *      usefull.
771
         */
772
                for (inpb = LIST_FIRST(tcbinfo.listhead); inpb;
773
                        inpb = LIST_NEXT(inpb, inp_list)) {
774
                                if ((tcpb = intotcpcb(inpb))) {
775
                                        while ((te = LIST_FIRST(&tcpb->t_segq))
776
                                               != NULL) {
777
                                        LIST_REMOVE(te, tqe_q);
778
                                        m_freem(te->tqe_m);
779
                                        FREE(te, M_TSEGQ);
780
#ifdef CYGNUM_NET_TCP_REASS_DIVISOR
781
                                        tcp_reass_qsize--;
782
#endif
783
                                }
784
                        }
785
                }
786
 
787
        }
788
}
789
 
790
/*
791
 * Notify a tcp user of an asynchronous error;
792
 * store error as soft error, but wake up user
793
 * (for now, won't do anything until can select for soft error).
794
 *
795
 * Do not wake up user since there currently is no mechanism for
796
 * reporting soft errors (yet - a kqueue filter may be added).
797
 */
798
static void
799
tcp_notify(inp, error)
800
        struct inpcb *inp;
801
        int error;
802
{
803
        struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
804
 
805
        /*
806
         * Ignore some errors if we are hooked up.
807
         * If connection hasn't completed, has retransmitted several times,
808
         * and receives a second error, give up now.  This is better
809
         * than waiting a long time to establish a connection that
810
         * can never complete.
811
         */
812
        if (tp->t_state == TCPS_ESTABLISHED &&
813
             (error == EHOSTUNREACH || error == ENETUNREACH ||
814
              error == EHOSTDOWN)) {
815
                return;
816
        } else if (tp->t_state < TCPS_ESTABLISHED && tp->t_rxtshift > 3 &&
817
            tp->t_softerror)
818
                tcp_drop(tp, error);
819
        else
820
                tp->t_softerror = error;
821
#if 0
822
        wakeup((caddr_t) &so->so_timeo);
823
        sorwakeup(so);
824
        sowwakeup(so);
825
#endif
826
}
827
 
828
#ifdef CYGPKG_NET_FREEBSD_SYSCTL
829
static int
830
tcp_pcblist(SYSCTL_HANDLER_ARGS)
831
{
832
        int error, i, n, s;
833
        struct inpcb *inp, **inp_list;
834
        inp_gen_t gencnt;
835
        struct xinpgen xig;
836
 
837
        /*
838
         * The process of preparing the TCB list is too time-consuming and
839
         * resource-intensive to repeat twice on every request.
840
         */
841
        if (req->oldptr == 0) {
842
                n = tcbinfo.ipi_count;
843
                req->oldidx = 2 * (sizeof xig)
844
                        + (n + n/8) * sizeof(struct xtcpcb);
845
                return 0;
846
        }
847
 
848
        if (req->newptr != 0)
849
                return EPERM;
850
 
851
        /*
852
         * OK, now we're committed to doing something.
853
         */
854
        s = splnet();
855
        gencnt = tcbinfo.ipi_gencnt;
856
        n = tcbinfo.ipi_count;
857
        splx(s);
858
 
859
        xig.xig_len = sizeof xig;
860
        xig.xig_count = n;
861
        xig.xig_gen = gencnt;
862
        xig.xig_sogen = so_gencnt;
863
        error = SYSCTL_OUT(req, &xig, sizeof xig);
864
        if (error)
865
                return error;
866
 
867
        inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);
868
        if (inp_list == 0)
869
                return ENOMEM;
870
 
871
        s = splnet();
872
        for (inp = LIST_FIRST(tcbinfo.listhead), i = 0; inp && i < n;
873
             inp = LIST_NEXT(inp, inp_list)) {
874
                if (inp->inp_gencnt <= gencnt)
875
                        inp_list[i++] = inp;
876
        }
877
        splx(s);
878
        n = i;
879
 
880
        error = 0;
881
        for (i = 0; i < n; i++) {
882
                inp = inp_list[i];
883
                if (inp->inp_gencnt <= gencnt) {
884
                        struct xtcpcb xt;
885
                        caddr_t inp_ppcb;
886
                        xt.xt_len = sizeof xt;
887
                        /* XXX should avoid extra copy */
888
                        bcopy(inp, &xt.xt_inp, sizeof *inp);
889
                        inp_ppcb = inp->inp_ppcb;
890
                        if (inp_ppcb != NULL)
891
                                bcopy(inp_ppcb, &xt.xt_tp, sizeof xt.xt_tp);
892
                        else
893
                                bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
894
                        if (inp->inp_socket)
895
                                sotoxsocket(inp->inp_socket, &xt.xt_socket);
896
                        error = SYSCTL_OUT(req, &xt, sizeof xt);
897
                }
898
        }
899
        if (!error) {
900
                /*
901
                 * Give the user an updated idea of our state.
902
                 * If the generation differs from what we told
903
                 * her before, she knows that something happened
904
                 * while we were processing this request, and it
905
                 * might be necessary to retry.
906
                 */
907
                s = splnet();
908
                xig.xig_gen = tcbinfo.ipi_gencnt;
909
                xig.xig_sogen = so_gencnt;
910
                xig.xig_count = tcbinfo.ipi_count;
911
                splx(s);
912
                error = SYSCTL_OUT(req, &xig, sizeof xig);
913
        }
914
        free(inp_list, M_TEMP);
915
        return error;
916
}
917
#endif
918
 
919
SYSCTL_PROC(_net_inet_tcp, TCPCTL_PCBLIST, pcblist, CTLFLAG_RD, 0, 0,
920
            tcp_pcblist, "S,xtcpcb", "List of active TCP connections");
921
 
922
void
923
tcp_ctlinput(cmd, sa, vip)
924
        int cmd;
925
        struct sockaddr *sa;
926
        void *vip;
927
{
928
        struct ip *ip = vip;
929
        struct tcphdr *th;
930
        struct in_addr faddr;
931
        struct inpcb *inp;
932
        struct tcpcb *tp;
933
        void (*notify) __P((struct inpcb *, int)) = tcp_notify;
934
        tcp_seq icmp_seq;
935
        int s;
936
 
937
        faddr = ((struct sockaddr_in *)sa)->sin_addr;
938
        if (sa->sa_family != AF_INET || faddr.s_addr == INADDR_ANY)
939
                return;
940
 
941
        if (cmd == PRC_QUENCH)
942
                notify = tcp_quench;
943
        else if (icmp_may_rst && (cmd == PRC_UNREACH_ADMIN_PROHIB ||
944
                cmd == PRC_UNREACH_PORT) && ip)
945
                notify = tcp_drop_syn_sent;
946
        else if (cmd == PRC_MSGSIZE)
947
                notify = tcp_mtudisc;
948
        else if (PRC_IS_REDIRECT(cmd)) {
949
                ip = 0;
950
                notify = in_rtchange;
951
        } else if (cmd == PRC_HOSTDEAD)
952
                ip = 0;
953
        else if ((unsigned)cmd > PRC_NCMDS || inetctlerrmap[cmd] == 0)
954
                return;
955
        if (ip) {
956
                s = splnet();
957
                th = (struct tcphdr *)((caddr_t)ip
958
                                       + (IP_VHL_HL(ip->ip_vhl) << 2));
959
                inp = in_pcblookup_hash(&tcbinfo, faddr, th->th_dport,
960
                    ip->ip_src, th->th_sport, 0, NULL);
961
                if (inp != NULL && inp->inp_socket != NULL) {
962
                        icmp_seq = htonl(th->th_seq);
963
                        tp = intotcpcb(inp);
964
                        if (SEQ_GEQ(icmp_seq, tp->snd_una) &&
965
                            SEQ_LT(icmp_seq, tp->snd_max))
966
                                (*notify)(inp, inetctlerrmap[cmd]);
967
                }
968
                splx(s);
969
        } else
970
                in_pcbnotifyall(&tcb, faddr, inetctlerrmap[cmd], notify);
971
}
972
 
973
#ifdef INET6
974
void
975
tcp6_ctlinput(cmd, sa, d)
976
        int cmd;
977
        struct sockaddr *sa;
978
        void *d;
979
{
980
        struct tcphdr th;
981
        void (*notify) __P((struct inpcb *, int)) = tcp_notify;
982
        struct ip6_hdr *ip6;
983
        struct mbuf *m;
984
        struct ip6ctlparam *ip6cp = NULL;
985
        const struct sockaddr_in6 *sa6_src = NULL;
986
        int off;
987
        struct tcp_portonly {
988
                u_int16_t th_sport;
989
                u_int16_t th_dport;
990
        } *thp;
991
 
992
        if (sa->sa_family != AF_INET6 ||
993
            sa->sa_len != sizeof(struct sockaddr_in6))
994
                return;
995
 
996
        if (cmd == PRC_QUENCH)
997
                notify = tcp_quench;
998
        else if (cmd == PRC_MSGSIZE)
999
                notify = tcp_mtudisc;
1000
        else if (!PRC_IS_REDIRECT(cmd) &&
1001
                 ((unsigned)cmd > PRC_NCMDS || inet6ctlerrmap[cmd] == 0))
1002
                return;
1003
 
1004
        /* if the parameter is from icmp6, decode it. */
1005
        if (d != NULL) {
1006
                ip6cp = (struct ip6ctlparam *)d;
1007
                m = ip6cp->ip6c_m;
1008
                ip6 = ip6cp->ip6c_ip6;
1009
                off = ip6cp->ip6c_off;
1010
                sa6_src = ip6cp->ip6c_src;
1011
        } else {
1012
                m = NULL;
1013
                ip6 = NULL;
1014
                off = 0; /* fool gcc */
1015
                sa6_src = &sa6_any;
1016
        }
1017
 
1018
        if (ip6) {
1019
                /*
1020
                 * XXX: We assume that when IPV6 is non NULL,
1021
                 * M and OFF are valid.
1022
                 */
1023
 
1024
                /* check if we can safely examine src and dst ports */
1025
                if (m->m_pkthdr.len < off + sizeof(*thp))
1026
                        return;
1027
 
1028
                bzero(&th, sizeof(th));
1029
                m_copydata(m, off, sizeof(*thp), (caddr_t)&th);
1030
 
1031
                in6_pcbnotify(&tcb, sa, th.th_dport,
1032
                    (struct sockaddr *)ip6cp->ip6c_src,
1033
                    th.th_sport, cmd, NULL, notify);
1034
        } else
1035
                in6_pcbnotify(&tcb, sa, 0, (struct sockaddr *)sa6_src,
1036
                              0, cmd, NULL, notify);
1037
}
1038
#endif /* INET6 */
1039
 
1040
/*
1041
 * Following is where TCP initial sequence number generation occurs.
1042
 *
1043
 * There are two places where we must use initial sequence numbers:
1044
 * 1.  In SYN-ACK packets.
1045
 * 2.  In SYN packets.
1046
 *
1047
 * The ISNs in SYN-ACK packets have no monotonicity requirement,
1048
 * and should be as unpredictable as possible to avoid the possibility
1049
 * of spoofing and/or connection hijacking.  To satisfy this
1050
 * requirement, SYN-ACK ISNs are generated via the arc4random()
1051
 * function.  If exact RFC 1948 compliance is requested via sysctl,
1052
 * these ISNs will be generated just like those in SYN packets.
1053
 *
1054
 * The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
1055
 * depends on this property.  In addition, these ISNs should be
1056
 * unguessable so as to prevent connection hijacking.  To satisfy
1057
 * the requirements of this situation, the algorithm outlined in
1058
 * RFC 1948 is used to generate sequence numbers.
1059
 *
1060
 * For more information on the theory of operation, please see
1061
 * RFC 1948.
1062
 *
1063
 * Implementation details:
1064
 *
1065
 * Time is based off the system timer, and is corrected so that it
1066
 * increases by one megabyte per second.  This allows for proper
1067
 * recycling on high speed LANs while still leaving over an hour
1068
 * before rollover.
1069
 *
1070
 * Two sysctls control the generation of ISNs:
1071
 *
1072
 * net.inet.tcp.isn_reseed_interval controls the number of seconds
1073
 * between seeding of isn_secret.  This is normally set to zero,
1074
 * as reseeding should not be necessary.
1075
 *
1076
 * net.inet.tcp.strict_rfc1948 controls whether RFC 1948 is followed
1077
 * strictly.  When strict compliance is requested, reseeding is
1078
 * disabled and SYN-ACKs will be generated in the same manner as
1079
 * SYNs.  Strict mode is disabled by default.
1080
 *
1081
 */
1082
 
1083
#define ISN_BYTES_PER_SECOND 1048576
1084
 
1085
u_char isn_secret[32];
1086
int isn_last_reseed;
1087
MD5_CTX isn_ctx;
1088
 
1089
tcp_seq
1090
tcp_new_isn(tp)
1091
        struct tcpcb *tp;
1092
{
1093
        u_int32_t md5_buffer[4];
1094
        tcp_seq new_isn;
1095
 
1096
        /* Use arc4random for SYN-ACKs when not in exact RFC1948 mode. */
1097
        if (((tp->t_state == TCPS_LISTEN) || (tp->t_state == TCPS_TIME_WAIT))
1098
           && tcp_strict_rfc1948 == 0)
1099
                return arc4random();
1100
 
1101
        /* Seed if this is the first use, reseed if requested. */
1102
        if ((isn_last_reseed == 0) ||
1103
            ((tcp_strict_rfc1948 == 0) && (tcp_isn_reseed_interval > 0) &&
1104
             (((u_int)isn_last_reseed + (u_int)tcp_isn_reseed_interval*hz)
1105
                < (u_int)ticks))) {
1106
                read_random_unlimited(&isn_secret, sizeof(isn_secret));
1107
                isn_last_reseed = ticks;
1108
        }
1109
 
1110
        /* Compute the md5 hash and return the ISN. */
1111
        MD5Init(&isn_ctx);
1112
        MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_fport, sizeof(u_short));
1113
        MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_lport, sizeof(u_short));
1114
#ifdef INET6
1115
        if ((tp->t_inpcb->inp_vflag & INP_IPV6) != 0) {
1116
                MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_faddr,
1117
                          sizeof(struct in6_addr));
1118
                MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->in6p_laddr,
1119
                          sizeof(struct in6_addr));
1120
        } else
1121
#endif
1122
        {
1123
                MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_faddr,
1124
                          sizeof(struct in_addr));
1125
                MD5Update(&isn_ctx, (u_char *) &tp->t_inpcb->inp_laddr,
1126
                          sizeof(struct in_addr));
1127
        }
1128
        MD5Update(&isn_ctx, (u_char *) &isn_secret, sizeof(isn_secret));
1129
        MD5Final((u_char *) &md5_buffer, &isn_ctx);
1130
        new_isn = (tcp_seq) md5_buffer[0];
1131
        new_isn += ticks * (ISN_BYTES_PER_SECOND / hz);
1132
        return new_isn;
1133
}
1134
 
1135
/*
1136
 * When a source quench is received, close congestion window
1137
 * to one segment.  We will gradually open it again as we proceed.
1138
 */
1139
void
1140
tcp_quench(inp, _errno)
1141
        struct inpcb *inp;
1142
        int _errno;
1143
{
1144
        struct tcpcb *tp = intotcpcb(inp);
1145
 
1146
        if (tp)
1147
                tp->snd_cwnd = tp->t_maxseg;
1148
}
1149
 
1150
/*
1151
 * When a specific ICMP unreachable message is received and the
1152
 * connection state is SYN-SENT, drop the connection.  This behavior
1153
 * is controlled by the icmp_may_rst sysctl.
1154
 */
1155
void
1156
tcp_drop_syn_sent(inp, _errno)
1157
        struct inpcb *inp;
1158
        int _errno;
1159
{
1160
        struct tcpcb *tp = intotcpcb(inp);
1161
 
1162
        if (tp && tp->t_state == TCPS_SYN_SENT)
1163
                tcp_drop(tp, _errno);
1164
}
1165
 
1166
/*
1167
 * When `need fragmentation' ICMP is received, update our idea of the MSS
1168
 * based on the new value in the route.  Also nudge TCP to send something,
1169
 * since we know the packet we just sent was dropped.
1170
 * This duplicates some code in the tcp_mss() function in tcp_input.c.
1171
 */
1172
void
1173
tcp_mtudisc(inp, _errno)
1174
        struct inpcb *inp;
1175
        int _errno;
1176
{
1177
        struct tcpcb *tp = intotcpcb(inp);
1178
        struct rtentry *rt;
1179
        struct rmxp_tao *taop;
1180
        struct socket *so = inp->inp_socket;
1181
        int offered;
1182
        int mss;
1183
#ifdef INET6
1184
        int isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0;
1185
#endif /* INET6 */
1186
 
1187
        if (tp) {
1188
#ifdef INET6
1189
                if (isipv6)
1190
                        rt = tcp_rtlookup6(inp);
1191
                else
1192
#endif /* INET6 */
1193
                rt = tcp_rtlookup(inp);
1194
                if (!rt || !rt->rt_rmx.rmx_mtu) {
1195
                        tp->t_maxopd = tp->t_maxseg =
1196
#ifdef INET6
1197
                                isipv6 ? tcp_v6mssdflt :
1198
#endif /* INET6 */
1199
                                tcp_mssdflt;
1200
                        return;
1201
                }
1202
                taop = rmx_taop(rt->rt_rmx);
1203
                offered = taop->tao_mssopt;
1204
                mss = rt->rt_rmx.rmx_mtu -
1205
#ifdef INET6
1206
                        (isipv6 ?
1207
                         sizeof(struct ip6_hdr) + sizeof(struct tcphdr) :
1208
#endif /* INET6 */
1209
                         sizeof(struct tcpiphdr)
1210
#ifdef INET6
1211
                         )
1212
#endif /* INET6 */
1213
                        ;
1214
 
1215
                if (offered)
1216
                        mss = min(mss, offered);
1217
                /*
1218
                 * XXX - The above conditional probably violates the TCP
1219
                 * spec.  The problem is that, since we don't know the
1220
                 * other end's MSS, we are supposed to use a conservative
1221
                 * default.  But, if we do that, then MTU discovery will
1222
                 * never actually take place, because the conservative
1223
                 * default is much less than the MTUs typically seen
1224
                 * on the Internet today.  For the moment, we'll sweep
1225
                 * this under the carpet.
1226
                 *
1227
                 * The conservative default might not actually be a problem
1228
                 * if the only case this occurs is when sending an initial
1229
                 * SYN with options and data to a host we've never talked
1230
                 * to before.  Then, they will reply with an MSS value which
1231
                 * will get recorded and the new parameters should get
1232
                 * recomputed.  For Further Study.
1233
                 */
1234
                if (tp->t_maxopd <= mss)
1235
                        return;
1236
                tp->t_maxopd = mss;
1237
 
1238
                if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP &&
1239
                    (tp->t_flags & TF_RCVD_TSTMP) == TF_RCVD_TSTMP)
1240
                        mss -= TCPOLEN_TSTAMP_APPA;
1241
                if ((tp->t_flags & (TF_REQ_CC|TF_NOOPT)) == TF_REQ_CC &&
1242
                    (tp->t_flags & TF_RCVD_CC) == TF_RCVD_CC)
1243
                        mss -= TCPOLEN_CC_APPA;
1244
#if     (MCLBYTES & (MCLBYTES - 1)) == 0
1245
                if (mss > MCLBYTES)
1246
                        mss &= ~(MCLBYTES-1);
1247
#else
1248
                if (mss > MCLBYTES)
1249
                        mss = mss / MCLBYTES * MCLBYTES;
1250
#endif
1251
                if (so->so_snd.sb_hiwat < mss)
1252
                        mss = so->so_snd.sb_hiwat;
1253
 
1254
                tp->t_maxseg = mss;
1255
 
1256
                tcpstat.tcps_mturesent++;
1257
                tp->t_rtttime = 0;
1258
                tp->snd_nxt = tp->snd_una;
1259
                tcp_output(tp);
1260
        }
1261
}
1262
 
1263
/*
1264
 * Look-up the routing entry to the peer of this inpcb.  If no route
1265
 * is found and it cannot be allocated the return NULL.  This routine
1266
 * is called by TCP routines that access the rmx structure and by tcp_mss
1267
 * to get the interface MTU.
1268
 */
1269
struct rtentry *
1270
tcp_rtlookup(inp)
1271
        struct inpcb *inp;
1272
{
1273
        struct route *ro;
1274
        struct rtentry *rt;
1275
 
1276
        ro = &inp->inp_route;
1277
        rt = ro->ro_rt;
1278
        if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
1279
                /* No route yet, so try to acquire one */
1280
                if (inp->inp_faddr.s_addr != INADDR_ANY) {
1281
                        ro->ro_dst.sa_family = AF_INET;
1282
                        ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
1283
                        ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
1284
                                inp->inp_faddr;
1285
                        rtalloc(ro);
1286
                        rt = ro->ro_rt;
1287
                }
1288
        }
1289
        return rt;
1290
}
1291
 
1292
#ifdef INET6
1293
struct rtentry *
1294
tcp_rtlookup6(inp)
1295
        struct inpcb *inp;
1296
{
1297
#ifdef NEW_STRUCT_ROUTE
1298
        struct route *ro6;
1299
#else
1300
        struct route_in6 *ro6;
1301
#endif
1302
        struct rtentry *rt;
1303
 
1304
        ro6 = &inp->in6p_route;
1305
        rt = ro6->ro_rt;
1306
        if (rt == NULL || !(rt->rt_flags & RTF_UP)) {
1307
                /* No route yet, so try to acquire one */
1308
                if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr)) {
1309
                        struct sockaddr_in6 *dst6;
1310
 
1311
                        dst6 = (struct sockaddr_in6 *)&ro6->ro_dst;
1312
                        dst6->sin6_family = AF_INET6;
1313
                        dst6->sin6_len = sizeof(*dst6);
1314
                        dst6->sin6_addr = inp->in6p_faddr;
1315
                        rtalloc((struct route *)ro6);
1316
                        rt = ro6->ro_rt;
1317
                }
1318
        }
1319
        return rt;
1320
}
1321
#endif /* INET6 */
1322
 
1323
#ifdef IPSEC
1324
/* compute ESP/AH header size for TCP, including outer IP header. */
1325
size_t
1326
ipsec_hdrsiz_tcp(tp)
1327
        struct tcpcb *tp;
1328
{
1329
        struct inpcb *inp;
1330
        struct mbuf *m;
1331
        size_t hdrsiz;
1332
        struct ip *ip;
1333
#ifdef INET6
1334
        struct ip6_hdr *ip6;
1335
#endif /* INET6 */
1336
        struct tcphdr *th;
1337
 
1338
        if ((tp == NULL) || ((inp = tp->t_inpcb) == NULL))
1339
                return 0;
1340
        MGETHDR(m, M_DONTWAIT, MT_DATA);
1341
        if (!m)
1342
                return 0;
1343
 
1344
#ifdef INET6
1345
        if ((inp->inp_vflag & INP_IPV6) != 0) {
1346
                ip6 = mtod(m, struct ip6_hdr *);
1347
                th = (struct tcphdr *)(ip6 + 1);
1348
                m->m_pkthdr.len = m->m_len =
1349
                        sizeof(struct ip6_hdr) + sizeof(struct tcphdr);
1350
                tcp_fillheaders(tp, ip6, th);
1351
                hdrsiz = ipsec6_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
1352
        } else
1353
#endif /* INET6 */
1354
      {
1355
        ip = mtod(m, struct ip *);
1356
        th = (struct tcphdr *)(ip + 1);
1357
        m->m_pkthdr.len = m->m_len = sizeof(struct tcpiphdr);
1358
        tcp_fillheaders(tp, ip, th);
1359
        hdrsiz = ipsec4_hdrsiz(m, IPSEC_DIR_OUTBOUND, inp);
1360
      }
1361
 
1362
        m_free(m);
1363
        return hdrsiz;
1364
}
1365
#endif /*IPSEC*/
1366
 
1367
/*
1368
 * Return a pointer to the cached information about the remote host.
1369
 * The cached information is stored in the protocol specific part of
1370
 * the route metrics.
1371
 */
1372
struct rmxp_tao *
1373
tcp_gettaocache(inp)
1374
        struct inpcb *inp;
1375
{
1376
        struct rtentry *rt;
1377
 
1378
#ifdef INET6
1379
        if ((inp->inp_vflag & INP_IPV6) != 0)
1380
                rt = tcp_rtlookup6(inp);
1381
        else
1382
#endif /* INET6 */
1383
        rt = tcp_rtlookup(inp);
1384
 
1385
        /* Make sure this is a host route and is up. */
1386
        if (rt == NULL ||
1387
            (rt->rt_flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST))
1388
                return NULL;
1389
 
1390
        return rmx_taop(rt->rt_rmx);
1391
}
1392
 
1393
/*
1394
 * Clear all the TAO cache entries, called from tcp_init.
1395
 *
1396
 * XXX
1397
 * This routine is just an empty one, because we assume that the routing
1398
 * routing tables are initialized at the same time when TCP, so there is
1399
 * nothing in the cache left over.
1400
 */
1401
static void
1402
tcp_cleartaocache()
1403
{
1404
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.