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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      sys/netinet/tcp_subr.c
4
//
5
//     
6
//
7
//==========================================================================
8
// ####BSDALTCOPYRIGHTBEGIN####                                             
9
// -------------------------------------------                              
10
// Portions of this software may have been derived from OpenBSD             
11
// or other sources, and if so are covered by the appropriate copyright     
12
// and license included herein.                                             
13
// -------------------------------------------                              
14
// ####BSDALTCOPYRIGHTEND####                                               
15
//==========================================================================
16
//#####DESCRIPTIONBEGIN####
17
//
18
// Author(s):    gthomas
19
// Contributors: gthomas
20
// Date:         2000-01-10
21
// Purpose:      
22
// Description:  
23
//              
24
//
25
//####DESCRIPTIONEND####
26
//
27
//==========================================================================
28
 
29
 
30
/*      $OpenBSD: tcp_subr.c,v 1.21 1999/12/08 06:50:20 itojun Exp $    */
31
/*      $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $   */
32
 
33
/*
34
 * Copyright (c) 1982, 1986, 1988, 1990, 1993
35
 *      The Regents of the University of California.  All rights reserved.
36
 *
37
 * Redistribution and use in source and binary forms, with or without
38
 * modification, are permitted provided that the following conditions
39
 * are met:
40
 * 1. Redistributions of source code must retain the above copyright
41
 *    notice, this list of conditions and the following disclaimer.
42
 * 2. Redistributions in binary form must reproduce the above copyright
43
 *    notice, this list of conditions and the following disclaimer in the
44
 *    documentation and/or other materials provided with the distribution.
45
 * 3. All advertising materials mentioning features or use of this software
46
 *    must display the following acknowledgement:
47
 *      This product includes software developed by the University of
48
 *      California, Berkeley and its contributors.
49
 * 4. Neither the name of the University nor the names of its contributors
50
 *    may be used to endorse or promote products derived from this software
51
 *    without specific prior written permission.
52
 *
53
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63
 * SUCH DAMAGE.
64
 *
65
 *      @(#)tcp_subr.c  8.1 (Berkeley) 6/10/93
66
 */
67
 
68
/*
69
%%% portions-copyright-nrl-95
70
Portions of this software are Copyright 1995-1998 by Randall Atkinson,
71
Ronald Lee, Daniel McDonald, Bao Phan, and Chris Winters. All Rights
72
Reserved. All rights under this copyright have been assigned to the US
73
Naval Research Laboratory (NRL). The NRL Copyright Notice and License
74
Agreement Version 1.1 (January 17, 1995) applies to these portions of the
75
software.
76
You should have received a copy of the license with this software. If you
77
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
78
*/
79
 
80
#include <sys/param.h>
81
#ifndef __ECOS
82
#include <sys/proc.h>
83
#include <sys/systm.h>
84
#endif
85
#include <sys/malloc.h>
86
#include <sys/mbuf.h>
87
#include <sys/socket.h>
88
#include <sys/socketvar.h>
89
#include <sys/protosw.h>
90
#include <sys/errno.h>
91
#ifdef __ECOS
92
#undef errno
93
#endif
94
 
95
#include <net/route.h>
96
#include <net/if.h>
97
 
98
#include <netinet/in.h>
99
#include <netinet/in_systm.h>
100
#include <netinet/ip.h>
101
#include <netinet/in_pcb.h>
102
#include <netinet/ip_var.h>
103
#include <netinet/ip_icmp.h>
104
#include <netinet/tcp.h>
105
#include <netinet/tcp_fsm.h>
106
#include <netinet/tcp_seq.h>
107
#include <netinet/tcp_timer.h>
108
#include <netinet/tcp_var.h>
109
#include <netinet/tcpip.h>
110
#ifndef __ECOS
111
#include <dev/rndvar.h>
112
#endif
113
 
114
#ifdef INET6
115
#include <netinet6/ip6_var.h>
116
#include <netinet6/tcpipv6.h>
117
#include <sys/domain.h>
118
#endif /* INET6 */
119
 
120
#ifdef TCP_SIGNATURE
121
#include <sys/md5k.h>
122
#endif /* TCP_SIGNATURE */
123
 
124
/* patchable/settable parameters for tcp */
125
int     tcp_mssdflt = TCP_MSS;
126
int     tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
127
 
128
/*
129
 * Configure kernel with options "TCP_DO_RFC1323=0" to disable RFC1323 stuff.
130
 * This is a good idea over slow SLIP/PPP links, because the timestamp
131
 * pretty well destroys the VJ compression (any packet with a timestamp
132
 * different from the previous one can't be compressed), as well as adding
133
 * more overhead.
134
 * XXX And it should be a settable per route characteristic (with this just
135
 * used as the default).
136
 */
137
#ifndef TCP_DO_RFC1323
138
#define TCP_DO_RFC1323  1
139
#endif
140
int    tcp_do_rfc1323 = TCP_DO_RFC1323;
141
 
142
#ifndef TCP_DO_SACK
143
#ifdef TCP_SACK
144
#define TCP_DO_SACK     0        /* XXX - make this 1 when SACK is fixed */
145
#else
146
#define TCP_DO_SACK     0
147
#endif
148
#endif
149
int    tcp_do_sack = TCP_DO_SACK;               /* RFC 2018 selective ACKs */
150
 
151
#ifndef TCBHASHSIZE
152
#define TCBHASHSIZE     128
153
#endif
154
int     tcbhashsize = TCBHASHSIZE;
155
 
156
#ifdef INET6
157
extern int ip6_defhlim;
158
#endif /* INET6 */
159
 
160
/*
161
 * Tcp initialization
162
 */
163
void
164
tcp_init()
165
{
166
#ifdef TCP_COMPAT_42
167
        tcp_iss = 1;            /* wrong */
168
#else /* TCP_COMPAT_42 */
169
        tcp_iss = arc4random() + 1;
170
#endif /* !TCP_COMPAT_42 */
171
        in_pcbinit(&tcbtable, tcbhashsize);
172
 
173
#ifdef INET6
174
        /*
175
         * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
176
         * do max length checks/computations only on the former.
177
         */
178
        if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)))
179
                max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
180
        if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) >
181
            MHLEN)
182
                panic("tcp_init");
183
#endif /* INET6 */
184
}
185
 
186
/*
187
 * Create template to be used to send tcp packets on a connection.
188
 * Call after host entry created, allocates an mbuf and fills
189
 * in a skeletal tcp/ip header, minimizing the amount of work
190
 * necessary when the connection is used.
191
 *
192
 * To support IPv6 in addition to IPv4 and considering that the sizes of
193
 * the IPv4 and IPv6 headers are not the same, we now use a separate pointer
194
 * for the TCP header.  Also, we made the former tcpiphdr header pointer
195
 * into just an IP overlay pointer, with casting as appropriate for v6. rja
196
 */
197
struct mbuf *
198
tcp_template(tp)
199
        struct tcpcb *tp;
200
{
201
        register struct inpcb *inp = tp->t_inpcb;
202
        register struct mbuf *m;
203
        register struct tcphdr *th = (struct tcphdr *)0;
204
 
205
        if ((m = tp->t_template) == 0) {
206
                m = m_get(M_DONTWAIT, MT_HEADER);
207
                if (m == NULL)
208
                        return (0);
209
 
210
                switch (tp->pf) {
211
                case 0:  /*default to PF_INET*/
212
#ifdef INET
213
                case AF_INET:
214
                        m->m_len = sizeof(struct ip);
215
                        break;
216
#endif /* INET */
217
#ifdef INET6
218
                case AF_INET6:
219
                        m->m_len = sizeof(struct ip6_hdr);
220
                        break;
221
#endif /* INET6 */
222
                }
223
                m->m_len += sizeof (struct tcphdr);
224
 
225
                /*
226
                 * The link header, network header, TCP header, and TCP options
227
                 * all must fit in this mbuf. For now, assume the worst case of
228
                 * TCP options size. Eventually, compute this from tp flags.
229
                 */
230
                if (m->m_len + MAX_TCPOPTLEN + max_linkhdr >= MHLEN) {
231
                        MCLGET(m, M_DONTWAIT);
232
                        if ((m->m_flags & M_EXT) == 0) {
233
                                m_free(m);
234
                                return (0);
235
                        }
236
                }
237
        }
238
 
239
        switch(tp->pf) {
240
#ifdef INET
241
        case AF_INET:
242
                {
243
                        struct ipovly *ipovly;
244
 
245
                        ipovly = mtod(m, struct ipovly *);
246
 
247
                        bzero(ipovly->ih_x1, sizeof ipovly->ih_x1);
248
                        ipovly->ih_pr = IPPROTO_TCP;
249
                        ipovly->ih_len = htons(sizeof (struct tcpiphdr) -
250
                                sizeof (struct ip));
251
                        ipovly->ih_src = inp->inp_laddr;
252
                        ipovly->ih_dst = inp->inp_faddr;
253
 
254
                        th = (struct tcphdr *)(mtod(m, caddr_t) +
255
                                sizeof(struct ip));
256
                }
257
                break;
258
#endif /* INET */
259
#ifdef INET6
260
        case AF_INET6:
261
                {
262
                        struct ip6_hdr *ipv6;
263
 
264
                        ipv6 = mtod(m, struct ip6_hdr *);
265
 
266
                        ipv6->ip6_src = inp->inp_laddr6;
267
                        ipv6->ip6_dst = inp->inp_faddr6;
268
                        ipv6->ip6_flow = htonl(0x60000000) |
269
                            (inp->inp_ipv6.ip6_flow & htonl(0x0fffffff));
270
 
271
 
272
                        ipv6->ip6_nxt = IPPROTO_TCP;
273
                        ipv6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/
274
                        ipv6->ip6_hlim = in6_selecthlim(inp, NULL);     /*XXX*/
275
 
276
                        th = (struct tcphdr *)(mtod(m, caddr_t) +
277
                                sizeof(struct ip6_hdr));
278
                }
279
                break;
280
#endif /* INET6 */
281
        }
282
 
283
        th->th_sport = inp->inp_lport;
284
        th->th_dport = inp->inp_fport;
285
        th->th_seq = 0;
286
        th->th_ack = 0;
287
        th->th_x2  = 0;
288
        th->th_off = 5;
289
        th->th_flags = 0;
290
        th->th_win = 0;
291
        th->th_sum = 0;
292
        th->th_urp = 0;
293
        return (m);
294
}
295
 
296
/*
297
 * Send a single message to the TCP at address specified by
298
 * the given TCP/IP header.  If m == 0, then we make a copy
299
 * of the tcpiphdr at ti and send directly to the addressed host.
300
 * This is used to force keep alive messages out using the TCP
301
 * template for a connection tp->t_template.  If flags are given
302
 * then we send a message back to the TCP which originated the
303
 * segment ti, and discard the mbuf containing it and any other
304
 * attached mbufs.
305
 *
306
 * In any case the ack and sequence number of the transmitted
307
 * segment are as specified by the parameters.
308
 */
309
#ifdef INET6
310
/* This function looks hairy, because it was so IPv4-dependent. */
311
#endif /* INET6 */
312
void
313
tcp_respond(tp, template, m, ack, seq, flags)
314
        struct tcpcb *tp;
315
        caddr_t template;
316
        register struct mbuf *m;
317
        tcp_seq ack, seq;
318
        int flags;
319
{
320
        register int tlen;
321
        int win = 0;
322
        struct route *ro = 0;
323
        register struct tcphdr *th;
324
        register struct tcpiphdr *ti = (struct tcpiphdr *)template;
325
#ifdef INET6
326
        int is_ipv6 = 0;   /* true iff IPv6 */
327
#endif /* INET6 */
328
 
329
        if (tp) {
330
                win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
331
#ifdef INET6
332
                /*
333
                 * If this is called with an unconnected
334
                 * socket/tp/pcb (tp->pf is 0), we lose.
335
                 */
336
                is_ipv6 = (tp->pf == PF_INET6);
337
 
338
                /*
339
                 * The route/route6 distinction is meaningless
340
                 * unless you're allocating space or passing parameters.
341
                 */
342
#endif /* INET6 */
343
                ro = &tp->t_inpcb->inp_route;
344
        }
345
#ifdef INET6
346
        else
347
                is_ipv6 = (((struct ip *)ti)->ip_v == 6);
348
#endif /* INET6 */
349
        if (m == 0) {
350
                m = m_gethdr(M_DONTWAIT, MT_HEADER);
351
                if (m == NULL)
352
                        return;
353
#ifdef TCP_COMPAT_42
354
                tlen = 1;
355
#else
356
                tlen = 0;
357
#endif
358
                m->m_data += max_linkhdr;
359
#ifdef INET6
360
                if (is_ipv6)
361
                        bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
362
                            sizeof(struct ip6_hdr));
363
                else
364
#endif /* INET6 */
365
                        bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
366
                            sizeof(struct ip));
367
 
368
                ti = mtod(m, struct tcpiphdr *);
369
                flags = TH_ACK;
370
        } else {
371
                m_freem(m->m_next);
372
                m->m_next = 0;
373
                m->m_data = (caddr_t)ti;
374
                tlen = 0;
375
#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
376
#ifdef INET6
377
                if (is_ipv6) {
378
                        m->m_len = sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
379
                        xchg(((struct ip6_hdr *)ti)->ip6_dst,\
380
                            ((struct ip6_hdr *)ti)->ip6_src,\
381
                            struct in6_addr);
382
                        th = (void *)ti + sizeof(struct ip6_hdr);
383
                } else
384
#endif /* INET6 */
385
                {
386
                        m->m_len = sizeof (struct tcpiphdr);
387
                        xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
388
                        th = (void *)((caddr_t)ti + sizeof(struct ip));
389
                }
390
                xchg(th->th_dport, th->th_sport, u_int16_t);
391
#undef xchg
392
        }
393
#ifdef INET6
394
        if (is_ipv6) {
395
                tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
396
                th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
397
        } else
398
#endif /* INET6 */
399
        {
400
                ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + tlen));
401
                tlen += sizeof (struct tcpiphdr);
402
                th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip));
403
        }
404
 
405
        m->m_len = tlen;
406
        m->m_pkthdr.len = tlen;
407
        m->m_pkthdr.rcvif = (struct ifnet *) 0;
408
        th->th_seq = htonl(seq);
409
        th->th_ack = htonl(ack);
410
        th->th_x2 = 0;
411
        th->th_off = sizeof (struct tcphdr) >> 2;
412
        th->th_flags = flags;
413
        if (tp)
414
                th->th_win = htons((u_int16_t) (win >> tp->rcv_scale));
415
        else
416
                th->th_win = htons((u_int16_t)win);
417
        th->th_urp = 0;
418
 
419
#ifdef INET6
420
        if (is_ipv6) {
421
                ((struct ip6_hdr *)ti)->ip6_flow   = htonl(0x60000000);
422
                ((struct ip6_hdr *)ti)->ip6_nxt  = IPPROTO_TCP;
423
                ((struct ip6_hdr *)ti)->ip6_hlim =
424
                        in6_selecthlim(tp ? tp->t_inpcb : NULL, NULL);  /*XXX*/
425
                ((struct ip6_hdr *)ti)->ip6_plen = tlen - sizeof(struct ip6_hdr);
426
                th->th_sum = 0;
427
                th->th_sum = in6_cksum(m, IPPROTO_TCP,
428
                   sizeof(struct ip6_hdr), ((struct ip6_hdr *)ti)->ip6_plen);
429
                HTONS(((struct ip6_hdr *)ti)->ip6_plen);
430
                ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL,
431
                        (struct route_in6 *)ro, 0, NULL, NULL);
432
        } else
433
#endif /* INET6 */
434
        {
435
                bzero(ti->ti_x1, sizeof ti->ti_x1);
436
                ti->ti_len = htons((u_short)tlen - sizeof(struct ip));
437
                th->th_sum = in_cksum(m, tlen);
438
                ((struct ip *)ti)->ip_len = tlen;
439
                ((struct ip *)ti)->ip_ttl = ip_defttl;
440
                ip_output(m, NULL, ro, 0, NULL, tp ? tp->t_inpcb : NULL);
441
        }
442
}
443
 
444
/*
445
 * Create a new TCP control block, making an
446
 * empty reassembly queue and hooking it to the argument
447
 * protocol control block.
448
 */
449
struct tcpcb *
450
tcp_newtcpcb(inp)
451
        struct inpcb *inp;
452
{
453
        register struct tcpcb *tp;
454
 
455
        tp = malloc(sizeof(*tp), M_PCB, M_NOWAIT);
456
        if (tp == NULL)
457
                return ((struct tcpcb *)0);
458
        bzero((char *) tp, sizeof(struct tcpcb));
459
        LIST_INIT(&tp->segq);
460
        tp->t_maxseg = tp->t_maxopd = tcp_mssdflt;
461
 
462
#ifdef TCP_SACK
463
        tp->sack_disable = tcp_do_sack ? 0 : 1;
464
#endif
465
        tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
466
        tp->t_inpcb = inp;
467
        /*
468
         * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
469
         * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
470
         * reasonable initial retransmit time.
471
         */
472
        tp->t_srtt = TCPTV_SRTTBASE;
473
        tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ << (TCP_RTTVAR_SHIFT + 2 - 1);
474
        tp->t_rttmin = TCPTV_MIN;
475
        TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
476
            TCPTV_MIN, TCPTV_REXMTMAX);
477
        tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
478
        tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
479
#ifdef INET6
480
        /*
481
         * If we want to use tp->pf for a quick-n-easy way to determine
482
         * the outbound dgram type, we cannot make this decision
483
         * until a connection is established!  Bzero() sets pf to zero, and
484
         * that's the way we want it, unless, of course, it's an AF_INET
485
         * socket...
486
         */
487
        if ((inp->inp_flags & INP_IPV6) == 0)
488
                tp->pf = PF_INET;  /* If AF_INET socket, we can't do v6 from it. */
489
#else
490
        tp->pf = PF_INET;
491
#endif
492
 
493
#ifdef INET6
494
        if (inp->inp_flags & INP_IPV6)
495
                inp->inp_ipv6.ip6_hlim = ip6_defhlim;
496
        else
497
#endif /* INET6 */
498
                inp->inp_ip.ip_ttl = ip_defttl;
499
 
500
        inp->inp_ppcb = (caddr_t)tp;
501
        return (tp);
502
}
503
 
504
/*
505
 * Drop a TCP connection, reporting
506
 * the specified error.  If connection is synchronized,
507
 * then send a RST to peer.
508
 */
509
struct tcpcb *
510
tcp_drop(tp, errno)
511
        register struct tcpcb *tp;
512
        int errno;
513
{
514
        struct socket *so = tp->t_inpcb->inp_socket;
515
 
516
        if (TCPS_HAVERCVDSYN(tp->t_state)) {
517
                tp->t_state = TCPS_CLOSED;
518
                (void) tcp_output(tp);
519
                tcpstat.tcps_drops++;
520
        } else
521
                tcpstat.tcps_conndrops++;
522
        if (errno == ETIMEDOUT && tp->t_softerror)
523
                errno = tp->t_softerror;
524
        so->so_error = errno;
525
        return (tcp_close(tp));
526
}
527
 
528
/*
529
 * Close a TCP control block:
530
 *      discard all space held by the tcp
531
 *      discard internet protocol block
532
 *      wake up any sleepers
533
 */
534
struct tcpcb *
535
tcp_close(tp)
536
        register struct tcpcb *tp;
537
{
538
        register struct ipqent *qe;
539
        struct inpcb *inp = tp->t_inpcb;
540
        struct socket *so = inp->inp_socket;
541
#ifdef TCP_SACK
542
        struct sackhole *p, *q;
543
#endif
544
#ifdef RTV_RTT
545
        register struct rtentry *rt;
546
#ifdef INET6
547
        register int bound_to_specific = 0;  /* I.e. non-default */
548
 
549
        /*
550
         * This code checks the nature of the route for this connection.
551
         * Normally this is done by two simple checks in the next
552
         * INET/INET6 ifdef block, but because of two possible lower layers,
553
         * that check is done here.
554
         *
555
         * Perhaps should be doing this only for a RTF_HOST route.
556
         */
557
        rt = inp->inp_route.ro_rt;  /* Same for route or route6. */
558
        if (tp->pf == PF_INET6) {
559
                if (rt)
560
                        bound_to_specific =
561
                            !(IN6_IS_ADDR_UNSPECIFIED(&
562
                            ((struct sockaddr_in6 *)rt_key(rt))->sin6_addr));
563
        } else {
564
                if (rt)
565
                        bound_to_specific =
566
                            (((struct sockaddr_in *)rt_key(rt))->
567
                            sin_addr.s_addr != INADDR_ANY);
568
        }
569
#endif /* INET6 */
570
 
571
        /*
572
         * If we sent enough data to get some meaningful characteristics,
573
         * save them in the routing entry.  'Enough' is arbitrarily
574
         * defined as the sendpipesize (default 4K) * 16.  This would
575
         * give us 16 rtt samples assuming we only get one sample per
576
         * window (the usual case on a long haul net).  16 samples is
577
         * enough for the srtt filter to converge to within 5% of the correct
578
         * value; fewer samples and we could save a very bogus rtt.
579
         *
580
         * Don't update the default route's characteristics and don't
581
         * update anything that the user "locked".
582
         */
583
#ifdef INET6
584
        /*
585
         * Note that rt and bound_to_specific are set above.
586
         */
587
        if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
588
            rt && bound_to_specific) {
589
#else /* INET6 */
590
        if (SEQ_LT(tp->iss + so->so_snd.sb_hiwat * 16, tp->snd_max) &&
591
            (rt = inp->inp_route.ro_rt) &&
592
            satosin(rt_key(rt))->sin_addr.s_addr != INADDR_ANY) {
593
#endif /* INET6 */
594
                register u_long i = 0;
595
 
596
                if ((rt->rt_rmx.rmx_locks & RTV_RTT) == 0) {
597
                        i = tp->t_srtt *
598
                            (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTT_SCALE));
599
                        if (rt->rt_rmx.rmx_rtt && i)
600
                                /*
601
                                 * filter this update to half the old & half
602
                                 * the new values, converting scale.
603
                                 * See route.h and tcp_var.h for a
604
                                 * description of the scaling constants.
605
                                 */
606
                                rt->rt_rmx.rmx_rtt =
607
                                    (rt->rt_rmx.rmx_rtt + i) / 2;
608
                        else
609
                                rt->rt_rmx.rmx_rtt = i;
610
                }
611
                if ((rt->rt_rmx.rmx_locks & RTV_RTTVAR) == 0) {
612
                        i = tp->t_rttvar *
613
                            (RTM_RTTUNIT / (PR_SLOWHZ * TCP_RTTVAR_SCALE));
614
                        if (rt->rt_rmx.rmx_rttvar && i)
615
                                rt->rt_rmx.rmx_rttvar =
616
                                    (rt->rt_rmx.rmx_rttvar + i) / 2;
617
                        else
618
                                rt->rt_rmx.rmx_rttvar = i;
619
                }
620
                /*
621
                 * update the pipelimit (ssthresh) if it has been updated
622
                 * already or if a pipesize was specified & the threshhold
623
                 * got below half the pipesize.  I.e., wait for bad news
624
                 * before we start updating, then update on both good
625
                 * and bad news.
626
                 */
627
                if (((rt->rt_rmx.rmx_locks & RTV_SSTHRESH) == 0 &&
628
                    (i = tp->snd_ssthresh) && rt->rt_rmx.rmx_ssthresh) ||
629
                    i < (rt->rt_rmx.rmx_sendpipe / 2)) {
630
                        /*
631
                         * convert the limit from user data bytes to
632
                         * packets then to packet data bytes.
633
                         */
634
                        i = (i + tp->t_maxseg / 2) / tp->t_maxseg;
635
                        if (i < 2)
636
                                i = 2;
637
#ifdef INET6
638
                        if (tp->pf == PF_INET6)
639
                                i *= (u_long)(tp->t_maxseg + sizeof (struct tcphdr)
640
                                    + sizeof(struct ip6_hdr));
641
                        else
642
#endif /* INET6 */
643
                                i *= (u_long)(tp->t_maxseg +
644
                                    sizeof (struct tcpiphdr));
645
 
646
                        if (rt->rt_rmx.rmx_ssthresh)
647
                                rt->rt_rmx.rmx_ssthresh =
648
                                    (rt->rt_rmx.rmx_ssthresh + i) / 2;
649
                        else
650
                                rt->rt_rmx.rmx_ssthresh = i;
651
                }
652
        }
653
#endif /* RTV_RTT */
654
 
655
        /* free the reassembly queue, if any */
656
#ifdef INET6
657
        /* Reassembling TCP segments in v6 might be sufficiently different
658
         * to merit two codepaths to free the reasssembly queue.
659
         * If an undecided TCP socket, then the IPv4 codepath will be used
660
         * because it won't matter much anyway.
661
         */
662
        if (tp->pf == AF_INET6) {
663
                while ((qe = tp->segq.lh_first) != NULL) {
664
                        LIST_REMOVE(qe, ipqe_q);
665
                        m_freem(qe->ipqe_m);
666
                        FREE(qe, M_IPQ);
667
                }
668
        } else
669
#endif /* INET6 */
670
                while ((qe = tp->segq.lh_first) != NULL) {
671
                        LIST_REMOVE(qe, ipqe_q);
672
                        m_freem(qe->ipqe_m);
673
                        FREE(qe, M_IPQ);
674
                }
675
#ifdef TCP_SACK
676
        /* Free SACK holes. */
677
        q = p = tp->snd_holes;
678
        while (p != 0) {
679
                q = p->next;
680
                free(p, M_PCB);
681
                p = q;
682
        }
683
#endif
684
        if (tp->t_template)
685
                (void) m_free(tp->t_template);
686
        free(tp, M_PCB);
687
        inp->inp_ppcb = 0;
688
        soisdisconnected(so);
689
        in_pcbdetach(inp);
690
        tcpstat.tcps_closed++;
691
        return ((struct tcpcb *)0);
692
}
693
 
694
void
695
tcp_drain()
696
{
697
 
698
}
699
 
700
/*
701
 * Notify a tcp user of an asynchronous error;
702
 * store error as soft error, but wake up user
703
 * (for now, won't do anything until can select for soft error).
704
 */
705
void
706
tcp_notify(inp, error)
707
        struct inpcb *inp;
708
        int error;
709
{
710
        register struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
711
        register struct socket *so = inp->inp_socket;
712
 
713
        /*
714
         * Ignore some errors if we are hooked up.
715
         * If connection hasn't completed, has retransmitted several times,
716
         * and receives a second error, give up now.  This is better
717
         * than waiting a long time to establish a connection that
718
         * can never complete.
719
         */
720
        if (tp->t_state == TCPS_ESTABLISHED &&
721
             (error == EHOSTUNREACH || error == ENETUNREACH ||
722
              error == EHOSTDOWN)) {
723
                return;
724
        } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
725
            tp->t_rxtshift > 3 && tp->t_softerror)
726
                so->so_error = error;
727
        else
728
                tp->t_softerror = error;
729
        wakeup((caddr_t) &so->so_timeo);
730
        sorwakeup(so);
731
        sowwakeup(so);
732
}
733
 
734
#if defined(INET6) && !defined(TCP6)
735
void
736
tcp6_ctlinput(cmd, sa, d)
737
        int cmd;
738
        struct sockaddr *sa;
739
        void *d;
740
{
741
        (void)tcp_ctlinput(cmd, sa, NULL);      /*XXX*/
742
}
743
#endif
744
 
745
void *
746
tcp_ctlinput(cmd, sa, v)
747
        int cmd;
748
        struct sockaddr *sa;
749
        register void *v;
750
{
751
        register struct ip *ip = v;
752
        register struct tcphdr *th;
753
        extern int inetctlerrmap[];
754
        void (*notify) __P((struct inpcb *, int)) = tcp_notify;
755
        int errno;
756
 
757
        if ((unsigned)cmd >= PRC_NCMDS)
758
                return NULL;
759
        errno = inetctlerrmap[cmd];
760
        if (cmd == PRC_QUENCH)
761
                notify = tcp_quench;
762
        else if (PRC_IS_REDIRECT(cmd))
763
                notify = in_rtchange, ip = 0;
764
        else if (cmd == PRC_HOSTDEAD)
765
                ip = 0;
766
        else if (errno == 0)
767
                return NULL;
768
 
769
#ifdef INET6
770
        if (sa->sa_family == AF_INET6) {
771
                if (ip) {
772
                        struct ip6_hdr *ipv6 = (struct ip6_hdr *)ip;
773
 
774
                        th = (struct tcphdr *)(ipv6 + 1);
775
#if 0 /*XXX*/
776
                        in6_pcbnotify(&tcbtable, sa, th->th_dport,
777
                            &ipv6->ip6_src, th->th_sport, cmd, notify);
778
#endif
779
                } else {
780
#if 0 /*XXX*/
781
                        in6_pcbnotify(&tcbtable, sa, 0,
782
                            (struct in6_addr *)&in6addr_any, 0, cmd, notify);
783
#endif
784
                }
785
        } else
786
#endif /* INET6 */
787
        {
788
                if (ip) {
789
                        th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
790
                        in_pcbnotify(&tcbtable, sa, th->th_dport, ip->ip_src,
791
                            th->th_sport, errno, notify);
792
                } else
793
                        in_pcbnotifyall(&tcbtable, sa, errno, notify);
794
        }
795
        return NULL;
796
}
797
 
798
/*
799
 * When a source quench is received, close congestion window
800
 * to one segment.  We will gradually open it again as we proceed.
801
 */
802
void
803
tcp_quench(inp, errno)
804
        struct inpcb *inp;
805
        int errno;
806
{
807
        struct tcpcb *tp = intotcpcb(inp);
808
 
809
        if (tp)
810
                tp->snd_cwnd = tp->t_maxseg;
811
}
812
 
813
#ifdef TCP_SIGNATURE
814
int
815
tcp_signature_tdb_attach()
816
{
817
        return (0);
818
}
819
 
820
int
821
tcp_signature_tdb_init(tdbp, xsp, ii)
822
        struct tdb *tdbp;
823
        struct xformsw *xsp;
824
        struct ipsecinit *ii;
825
{
826
        char *c;
827
#define isdigit(c)        (((c) >= '0') && ((c) <= '9'))
828
#define isalpha(c)      ( (((c) >= 'A') && ((c) <= 'Z')) || \
829
                          (((c) >= 'a') && ((c) <= 'z')) )
830
 
831
        if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))
832
                return (EINVAL);
833
 
834
        c = (char *)ii->ii_authkey;
835
 
836
        while (c < (char *)ii->ii_authkey + ii->ii_authkeylen - 1) {
837
                if (isdigit(*c)) {
838
                        if (*(c + 1) == ' ')
839
                                return (EINVAL);
840
                } else {
841
                        if (!isalpha(*c))
842
                                return (EINVAL);
843
                }
844
 
845
                c++;
846
        }
847
 
848
        if (!isdigit(*c) && !isalpha(*c))
849
                return (EINVAL);
850
 
851
        tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
852
        if (tdbp->tdb_amxkey == NULL)
853
                return (ENOMEM);
854
        bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
855
        tdbp->tdb_amxkeylen = ii->ii_authkeylen;
856
 
857
        return (0);
858
}
859
 
860
int
861
tcp_signature_tdb_zeroize(tdbp)
862
        struct tdb *tdbp;
863
{
864
        if (tdbp->tdb_amxkey) {
865
                bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
866
                free(tdbp->tdb_amxkey, M_XDATA);
867
                tdbp->tdb_amxkey = NULL;
868
        }
869
 
870
        return (0);
871
}
872
 
873
struct mbuf *
874
tcp_signature_tdb_input(m, tdbp)
875
        struct mbuf *m;
876
        struct tdb *tdbp;
877
{
878
        return (0);
879
}
880
 
881
int
882
tcp_signature_tdb_output(m, tdbp, mp)
883
        struct mbuf *m;
884
        struct tdb *tdbp;
885
        struct mbuf **mp;
886
{
887
        return (EINVAL);
888
}
889
 
890
int
891
tcp_signature_apply(fstate, data, len)
892
        caddr_t fstate;
893
        caddr_t data;
894
        unsigned int len;
895
{
896
        MD5Update((MD5_CTX *)fstate, (char *)data, len);
897
        return 0;
898
}
899
#endif /* TCP_SIGNATURE */

powered by: WebSVN 2.1.0

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