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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [net/] [tcpip/] [v2_0/] [src/] [sys/] [netinet/] [tcp_subr.c] - Blame information for rev 174

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
//==========================================================================
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 */

powered by: WebSVN 2.1.0

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