[BACK]Return to tcp_subr.c CVS log [TXT][DIR] Up to [local] / sys / netinet

Annotation of sys/netinet/tcp_subr.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: tcp_subr.c,v 1.98 2007/06/25 12:17:43 markus Exp $    */
                      2: /*     $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1988, 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. Neither the name of the University nor the names of its contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     24:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     25:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     26:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     27:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     28:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  *
                     32:  *     @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
                     33:  *
                     34:  * NRL grants permission for redistribution and use in source and binary
                     35:  * forms, with or without modification, of the software and documentation
                     36:  * created at NRL provided that the following conditions are met:
                     37:  *
                     38:  * 1. Redistributions of source code must retain the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer.
                     40:  * 2. Redistributions in binary form must reproduce the above copyright
                     41:  *    notice, this list of conditions and the following disclaimer in the
                     42:  *    documentation and/or other materials provided with the distribution.
                     43:  * 3. All advertising materials mentioning features or use of this software
                     44:  *    must display the following acknowledgements:
                     45:  *     This product includes software developed by the University of
                     46:  *     California, Berkeley and its contributors.
                     47:  *     This product includes software developed at the Information
                     48:  *     Technology Division, US Naval Research Laboratory.
                     49:  * 4. Neither the name of the NRL 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:  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
                     54:  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     55:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
                     56:  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
                     57:  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     58:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     59:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
                     60:  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
                     61:  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     62:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     63:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     64:  *
                     65:  * The views and conclusions contained in the software and documentation
                     66:  * are those of the authors and should not be interpreted as representing
                     67:  * official policies, either expressed or implied, of the US Naval
                     68:  * Research Laboratory (NRL).
                     69:  */
                     70:
                     71: #include <sys/param.h>
                     72: #include <sys/systm.h>
                     73: #include <sys/proc.h>
                     74: #include <sys/mbuf.h>
                     75: #include <sys/socket.h>
                     76: #include <sys/socketvar.h>
                     77: #include <sys/protosw.h>
                     78: #include <sys/kernel.h>
                     79:
                     80: #include <net/route.h>
                     81: #include <net/if.h>
                     82:
                     83: #include <netinet/in.h>
                     84: #include <netinet/in_systm.h>
                     85: #include <netinet/ip.h>
                     86: #include <netinet/in_pcb.h>
                     87: #include <netinet/ip_var.h>
                     88: #include <netinet/ip_icmp.h>
                     89: #include <netinet/tcp.h>
                     90: #include <netinet/tcp_fsm.h>
                     91: #include <netinet/tcp_seq.h>
                     92: #include <netinet/tcp_timer.h>
                     93: #include <netinet/tcp_var.h>
                     94: #include <netinet/tcpip.h>
                     95: #include <dev/rndvar.h>
                     96:
                     97: #ifdef INET6
                     98: #include <netinet6/in6_var.h>
                     99: #include <netinet6/ip6protosw.h>
                    100: #endif /* INET6 */
                    101:
                    102: #include <crypto/md5.h>
                    103:
                    104: /* patchable/settable parameters for tcp */
                    105: int    tcp_mssdflt = TCP_MSS;
                    106: int    tcp_rttdflt = TCPTV_SRTTDFLT / PR_SLOWHZ;
                    107:
                    108: /* values controllable via sysctl */
                    109: int    tcp_do_rfc1323 = 1;
                    110: #ifdef TCP_SACK
                    111: int    tcp_do_sack = 1;        /* RFC 2018 selective ACKs */
                    112: #endif
                    113: int    tcp_ack_on_push = 0;    /* set to enable immediate ACK-on-PUSH */
                    114: #ifdef TCP_ECN
                    115: int    tcp_do_ecn = 0;         /* RFC3168 ECN enabled/disabled? */
                    116: #endif
                    117: int    tcp_do_rfc3390 = 1;     /* RFC3390 Increasing TCP's Initial Window */
                    118:
                    119: u_int32_t      tcp_now = 1;
                    120:
                    121: #ifndef TCBHASHSIZE
                    122: #define        TCBHASHSIZE     128
                    123: #endif
                    124: int    tcbhashsize = TCBHASHSIZE;
                    125:
                    126: /* syn hash parameters */
                    127: #define        TCP_SYN_HASH_SIZE       293
                    128: #define        TCP_SYN_BUCKET_SIZE     35
                    129: int    tcp_syn_cache_size = TCP_SYN_HASH_SIZE;
                    130: int    tcp_syn_cache_limit = TCP_SYN_HASH_SIZE*TCP_SYN_BUCKET_SIZE;
                    131: int    tcp_syn_bucket_limit = 3*TCP_SYN_BUCKET_SIZE;
                    132: struct syn_cache_head tcp_syn_cache[TCP_SYN_HASH_SIZE];
                    133:
                    134: int tcp_reass_limit = NMBCLUSTERS / 2; /* hardlimit for tcpqe_pool */
                    135: #ifdef TCP_SACK
                    136: int tcp_sackhole_limit = 32*1024; /* hardlimit for sackhl_pool */
                    137: #endif
                    138:
                    139: #ifdef INET6
                    140: extern int ip6_defhlim;
                    141: #endif /* INET6 */
                    142:
                    143: struct pool tcpcb_pool;
                    144: struct pool tcpqe_pool;
                    145: #ifdef TCP_SACK
                    146: struct pool sackhl_pool;
                    147: #endif
                    148:
                    149: struct tcpstat tcpstat;                /* tcp statistics */
                    150: tcp_seq  tcp_iss;
                    151:
                    152: /*
                    153:  * Tcp initialization
                    154:  */
                    155: void
                    156: tcp_init()
                    157: {
                    158:        tcp_iss = 1;            /* wrong */
                    159:        pool_init(&tcpcb_pool, sizeof(struct tcpcb), 0, 0, 0, "tcpcbpl",
                    160:            NULL);
                    161:        pool_init(&tcpqe_pool, sizeof(struct tcpqent), 0, 0, 0, "tcpqepl",
                    162:            NULL);
                    163:        pool_sethardlimit(&tcpqe_pool, tcp_reass_limit, NULL, 0);
                    164: #ifdef TCP_SACK
                    165:        pool_init(&sackhl_pool, sizeof(struct sackhole), 0, 0, 0, "sackhlpl",
                    166:            NULL);
                    167:        pool_sethardlimit(&sackhl_pool, tcp_sackhole_limit, NULL, 0);
                    168: #endif /* TCP_SACK */
                    169:        in_pcbinit(&tcbtable, tcbhashsize);
                    170:
                    171: #ifdef INET6
                    172:        /*
                    173:         * Since sizeof(struct ip6_hdr) > sizeof(struct ip), we
                    174:         * do max length checks/computations only on the former.
                    175:         */
                    176:        if (max_protohdr < (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)))
                    177:                max_protohdr = (sizeof(struct ip6_hdr) + sizeof(struct tcphdr));
                    178:        if ((max_linkhdr + sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) >
                    179:            MHLEN)
                    180:                panic("tcp_init");
                    181:
                    182:        icmp6_mtudisc_callback_register(tcp6_mtudisc_callback);
                    183: #endif /* INET6 */
                    184:
                    185:        /* Initialize the compressed state engine. */
                    186:        syn_cache_init();
                    187:
                    188:        /* Initialize timer state. */
                    189:        tcp_timer_init();
                    190: }
                    191:
                    192: /*
                    193:  * Create template to be used to send tcp packets on a connection.
                    194:  * Call after host entry created, allocates an mbuf and fills
                    195:  * in a skeletal tcp/ip header, minimizing the amount of work
                    196:  * necessary when the connection is used.
                    197:  *
                    198:  * To support IPv6 in addition to IPv4 and considering that the sizes of
                    199:  * the IPv4 and IPv6 headers are not the same, we now use a separate pointer
                    200:  * for the TCP header.  Also, we made the former tcpiphdr header pointer
                    201:  * into just an IP overlay pointer, with casting as appropriate for v6. rja
                    202:  */
                    203: struct mbuf *
                    204: tcp_template(tp)
                    205:        struct tcpcb *tp;
                    206: {
                    207:        struct inpcb *inp = tp->t_inpcb;
                    208:        struct mbuf *m;
                    209:        struct tcphdr *th;
                    210:
                    211:        if ((m = tp->t_template) == 0) {
                    212:                m = m_get(M_DONTWAIT, MT_HEADER);
                    213:                if (m == NULL)
                    214:                        return (0);
                    215:
                    216:                switch (tp->pf) {
                    217:                case 0: /*default to PF_INET*/
                    218: #ifdef INET
                    219:                case AF_INET:
                    220:                        m->m_len = sizeof(struct ip);
                    221:                        break;
                    222: #endif /* INET */
                    223: #ifdef INET6
                    224:                case AF_INET6:
                    225:                        m->m_len = sizeof(struct ip6_hdr);
                    226:                        break;
                    227: #endif /* INET6 */
                    228:                }
                    229:                m->m_len += sizeof (struct tcphdr);
                    230:
                    231:                /*
                    232:                 * The link header, network header, TCP header, and TCP options
                    233:                 * all must fit in this mbuf. For now, assume the worst case of
                    234:                 * TCP options size. Eventually, compute this from tp flags.
                    235:                 */
                    236:                if (m->m_len + MAX_TCPOPTLEN + max_linkhdr >= MHLEN) {
                    237:                        MCLGET(m, M_DONTWAIT);
                    238:                        if ((m->m_flags & M_EXT) == 0) {
                    239:                                m_free(m);
                    240:                                return (0);
                    241:                        }
                    242:                }
                    243:        }
                    244:
                    245:        switch(tp->pf) {
                    246: #ifdef INET
                    247:        case AF_INET:
                    248:                {
                    249:                        struct ipovly *ipovly;
                    250:
                    251:                        ipovly = mtod(m, struct ipovly *);
                    252:
                    253:                        bzero(ipovly->ih_x1, sizeof ipovly->ih_x1);
                    254:                        ipovly->ih_pr = IPPROTO_TCP;
                    255:                        ipovly->ih_len = htons(sizeof (struct tcphdr));
                    256:                        ipovly->ih_src = inp->inp_laddr;
                    257:                        ipovly->ih_dst = inp->inp_faddr;
                    258:
                    259:                        th = (struct tcphdr *)(mtod(m, caddr_t) +
                    260:                                sizeof(struct ip));
                    261:                        th->th_sum = in_cksum_phdr(ipovly->ih_src.s_addr,
                    262:                            ipovly->ih_dst.s_addr,
                    263:                            htons(sizeof (struct tcphdr) + IPPROTO_TCP));
                    264:                }
                    265:                break;
                    266: #endif /* INET */
                    267: #ifdef INET6
                    268:        case AF_INET6:
                    269:                {
                    270:                        struct ip6_hdr *ip6;
                    271:
                    272:                        ip6 = mtod(m, struct ip6_hdr *);
                    273:
                    274:                        ip6->ip6_src = inp->inp_laddr6;
                    275:                        ip6->ip6_dst = inp->inp_faddr6;
                    276:                        ip6->ip6_flow = htonl(0x60000000) |
                    277:                            (inp->inp_flowinfo & IPV6_FLOWLABEL_MASK);
                    278:
                    279:                        ip6->ip6_nxt = IPPROTO_TCP;
                    280:                        ip6->ip6_plen = htons(sizeof(struct tcphdr)); /*XXX*/
                    281:                        ip6->ip6_hlim = in6_selecthlim(inp, NULL);      /*XXX*/
                    282:
                    283:                        th = (struct tcphdr *)(mtod(m, caddr_t) +
                    284:                                sizeof(struct ip6_hdr));
                    285:                        th->th_sum = 0;
                    286:                }
                    287:                break;
                    288: #endif /* INET6 */
                    289:        }
                    290:
                    291:        th->th_sport = inp->inp_lport;
                    292:        th->th_dport = inp->inp_fport;
                    293:        th->th_seq = 0;
                    294:        th->th_ack = 0;
                    295:        th->th_x2  = 0;
                    296:        th->th_off = 5;
                    297:        th->th_flags = 0;
                    298:        th->th_win = 0;
                    299:        th->th_urp = 0;
                    300:        return (m);
                    301: }
                    302:
                    303: /*
                    304:  * Send a single message to the TCP at address specified by
                    305:  * the given TCP/IP header.  If m == 0, then we make a copy
                    306:  * of the tcpiphdr at ti and send directly to the addressed host.
                    307:  * This is used to force keep alive messages out using the TCP
                    308:  * template for a connection tp->t_template.  If flags are given
                    309:  * then we send a message back to the TCP which originated the
                    310:  * segment ti, and discard the mbuf containing it and any other
                    311:  * attached mbufs.
                    312:  *
                    313:  * In any case the ack and sequence number of the transmitted
                    314:  * segment are as specified by the parameters.
                    315:  */
                    316: #ifdef INET6
                    317: /* This function looks hairy, because it was so IPv4-dependent. */
                    318: #endif /* INET6 */
                    319: void
                    320: tcp_respond(tp, template, m, ack, seq, flags)
                    321:        struct tcpcb *tp;
                    322:        caddr_t template;
                    323:        struct mbuf *m;
                    324:        tcp_seq ack, seq;
                    325:        int flags;
                    326: {
                    327:        int tlen;
                    328:        int win = 0;
                    329:        struct route *ro = 0;
                    330:        struct tcphdr *th;
                    331:        struct tcpiphdr *ti = (struct tcpiphdr *)template;
                    332:        int af;         /* af on wire */
                    333:
                    334:        if (tp) {
                    335:                win = sbspace(&tp->t_inpcb->inp_socket->so_rcv);
                    336:                /*
                    337:                 * If this is called with an unconnected
                    338:                 * socket/tp/pcb (tp->pf is 0), we lose.
                    339:                 */
                    340:                af = tp->pf;
                    341:
                    342:                /*
                    343:                 * The route/route6 distinction is meaningless
                    344:                 * unless you're allocating space or passing parameters.
                    345:                 */
                    346:                ro = &tp->t_inpcb->inp_route;
                    347:        } else
                    348:                af = (((struct ip *)ti)->ip_v == 6) ? AF_INET6 : AF_INET;
                    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:                switch (af) {
                    360: #ifdef INET6
                    361:                case AF_INET6:
                    362:                        bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
                    363:                            sizeof(struct ip6_hdr));
                    364:                        break;
                    365: #endif /* INET6 */
                    366:                case AF_INET:
                    367:                        bcopy(ti, mtod(m, caddr_t), sizeof(struct tcphdr) +
                    368:                            sizeof(struct ip));
                    369:                        break;
                    370:                }
                    371:
                    372:                ti = mtod(m, struct tcpiphdr *);
                    373:                flags = TH_ACK;
                    374:        } else {
                    375:                m_freem(m->m_next);
                    376:                m->m_next = 0;
                    377:                m->m_data = (caddr_t)ti;
                    378:                tlen = 0;
                    379: #define xchg(a,b,type) do { type t; t=a; a=b; b=t; } while (0)
                    380:                switch (af) {
                    381: #ifdef INET6
                    382:                case AF_INET6:
                    383:                        m->m_len = sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
                    384:                        xchg(((struct ip6_hdr *)ti)->ip6_dst,
                    385:                            ((struct ip6_hdr *)ti)->ip6_src, struct in6_addr);
                    386:                        th = (void *)((caddr_t)ti + sizeof(struct ip6_hdr));
                    387:                        break;
                    388: #endif /* INET6 */
                    389:                case AF_INET:
                    390:                        m->m_len = sizeof (struct tcpiphdr);
                    391:                        xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
                    392:                        th = (void *)((caddr_t)ti + sizeof(struct ip));
                    393:                        break;
                    394:                }
                    395:                xchg(th->th_dport, th->th_sport, u_int16_t);
                    396: #undef xchg
                    397:        }
                    398:        switch (af) {
                    399: #ifdef INET6
                    400:        case AF_INET6:
                    401:                tlen += sizeof(struct tcphdr) + sizeof(struct ip6_hdr);
                    402:                th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip6_hdr));
                    403:                break;
                    404: #endif /* INET6 */
                    405:        case AF_INET:
                    406:                ti->ti_len = htons((u_int16_t)(sizeof (struct tcphdr) + tlen));
                    407:                tlen += sizeof (struct tcpiphdr);
                    408:                th = (struct tcphdr *)((caddr_t)ti + sizeof(struct ip));
                    409:                break;
                    410:        }
                    411:
                    412:        m->m_len = tlen;
                    413:        m->m_pkthdr.len = tlen;
                    414:        m->m_pkthdr.rcvif = (struct ifnet *) 0;
                    415:        th->th_seq = htonl(seq);
                    416:        th->th_ack = htonl(ack);
                    417:        th->th_x2 = 0;
                    418:        th->th_off = sizeof (struct tcphdr) >> 2;
                    419:        th->th_flags = flags;
                    420:        if (tp)
                    421:                win >>= tp->rcv_scale;
                    422:        if (win > TCP_MAXWIN)
                    423:                win = TCP_MAXWIN;
                    424:        th->th_win = htons((u_int16_t)win);
                    425:        th->th_urp = 0;
                    426:
                    427:        switch (af) {
                    428: #ifdef INET6
                    429:        case AF_INET6:
                    430:                ((struct ip6_hdr *)ti)->ip6_flow   = htonl(0x60000000);
                    431:                ((struct ip6_hdr *)ti)->ip6_nxt  = IPPROTO_TCP;
                    432:                ((struct ip6_hdr *)ti)->ip6_hlim =
                    433:                        in6_selecthlim(tp ? tp->t_inpcb : NULL, NULL);  /*XXX*/
                    434:                ((struct ip6_hdr *)ti)->ip6_plen = tlen - sizeof(struct ip6_hdr);
                    435:                th->th_sum = 0;
                    436:                th->th_sum = in6_cksum(m, IPPROTO_TCP,
                    437:                   sizeof(struct ip6_hdr), ((struct ip6_hdr *)ti)->ip6_plen);
                    438:                HTONS(((struct ip6_hdr *)ti)->ip6_plen);
                    439:                ip6_output(m, tp ? tp->t_inpcb->inp_outputopts6 : NULL,
                    440:                    (struct route_in6 *)ro, 0, NULL, NULL,
                    441:                    tp ? tp->t_inpcb : NULL);
                    442:                break;
                    443: #endif /* INET6 */
                    444:        case AF_INET:
                    445:                bzero(ti->ti_x1, sizeof ti->ti_x1);
                    446:                ti->ti_len = htons((u_short)tlen - sizeof(struct ip));
                    447:
                    448:                /*
                    449:                 * There's no point deferring to hardware checksum processing
                    450:                 * here, as we only send a minimal TCP packet whose checksum
                    451:                 * we need to compute in any case.
                    452:                 */
                    453:                th->th_sum = 0;
                    454:                th->th_sum = in_cksum(m, tlen);
                    455:                ((struct ip *)ti)->ip_len = htons(tlen);
                    456:                ((struct ip *)ti)->ip_ttl = ip_defttl;
                    457:                ip_output(m, (void *)NULL, ro, ip_mtudisc ? IP_MTUDISC : 0,
                    458:                        (void *)NULL, tp ? tp->t_inpcb : (void *)NULL);
                    459:        }
                    460: }
                    461:
                    462: /*
                    463:  * Create a new TCP control block, making an
                    464:  * empty reassembly queue and hooking it to the argument
                    465:  * protocol control block.
                    466:  */
                    467: struct tcpcb *
                    468: tcp_newtcpcb(struct inpcb *inp)
                    469: {
                    470:        struct tcpcb *tp;
                    471:        int i;
                    472:
                    473:        tp = pool_get(&tcpcb_pool, PR_NOWAIT);
                    474:        if (tp == NULL)
                    475:                return ((struct tcpcb *)0);
                    476:        bzero((char *) tp, sizeof(struct tcpcb));
                    477:        TAILQ_INIT(&tp->t_segq);
                    478:        tp->t_maxseg = tcp_mssdflt;
                    479:        tp->t_maxopd = 0;
                    480:
                    481:        TCP_INIT_DELACK(tp);
                    482:        for (i = 0; i < TCPT_NTIMERS; i++)
                    483:                TCP_TIMER_INIT(tp, i);
                    484:        timeout_set(&tp->t_reap_to, tcp_reaper, tp);
                    485:
                    486: #ifdef TCP_SACK
                    487:        tp->sack_enable = tcp_do_sack;
                    488: #endif
                    489:        tp->t_flags = tcp_do_rfc1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
                    490:        tp->t_inpcb = inp;
                    491:        /*
                    492:         * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
                    493:         * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
                    494:         * reasonable initial retransmit time.
                    495:         */
                    496:        tp->t_srtt = TCPTV_SRTTBASE;
                    497:        tp->t_rttvar = tcp_rttdflt * PR_SLOWHZ <<
                    498:            (TCP_RTTVAR_SHIFT + TCP_RTT_BASE_SHIFT - 1);
                    499:        tp->t_rttmin = TCPTV_MIN;
                    500:        TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp),
                    501:            TCPTV_MIN, TCPTV_REXMTMAX);
                    502:        tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
                    503:        tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
                    504:
                    505:        tp->t_pmtud_mtu_sent = 0;
                    506:        tp->t_pmtud_mss_acked = 0;
                    507:
                    508: #ifdef INET6
                    509:        /* we disallow IPv4 mapped address completely. */
                    510:        if ((inp->inp_flags & INP_IPV6) == 0)
                    511:                tp->pf = PF_INET;
                    512:        else
                    513:                tp->pf = PF_INET6;
                    514: #else
                    515:        tp->pf = PF_INET;
                    516: #endif
                    517:
                    518: #ifdef INET6
                    519:        if (inp->inp_flags & INP_IPV6)
                    520:                inp->inp_ipv6.ip6_hlim = ip6_defhlim;
                    521:        else
                    522: #endif /* INET6 */
                    523:                inp->inp_ip.ip_ttl = ip_defttl;
                    524:
                    525:        inp->inp_ppcb = (caddr_t)tp;
                    526:        return (tp);
                    527: }
                    528:
                    529: /*
                    530:  * Drop a TCP connection, reporting
                    531:  * the specified error.  If connection is synchronized,
                    532:  * then send a RST to peer.
                    533:  */
                    534: struct tcpcb *
                    535: tcp_drop(tp, errno)
                    536:        struct tcpcb *tp;
                    537:        int errno;
                    538: {
                    539:        struct socket *so = tp->t_inpcb->inp_socket;
                    540:
                    541:        if (TCPS_HAVERCVDSYN(tp->t_state)) {
                    542:                tp->t_state = TCPS_CLOSED;
                    543:                (void) tcp_output(tp);
                    544:                tcpstat.tcps_drops++;
                    545:        } else
                    546:                tcpstat.tcps_conndrops++;
                    547:        if (errno == ETIMEDOUT && tp->t_softerror)
                    548:                errno = tp->t_softerror;
                    549:        so->so_error = errno;
                    550:        return (tcp_close(tp));
                    551: }
                    552:
                    553: /*
                    554:  * Close a TCP control block:
                    555:  *     discard all space held by the tcp
                    556:  *     discard internet protocol block
                    557:  *     wake up any sleepers
                    558:  */
                    559: struct tcpcb *
                    560: tcp_close(struct tcpcb *tp)
                    561: {
                    562:        struct inpcb *inp = tp->t_inpcb;
                    563:        struct socket *so = inp->inp_socket;
                    564: #ifdef TCP_SACK
                    565:        struct sackhole *p, *q;
                    566: #endif
                    567:
                    568:        /* free the reassembly queue, if any */
                    569:        tcp_reass_lock(tp);
                    570:        tcp_freeq(tp);
                    571:        tcp_reass_unlock(tp);
                    572:
                    573:        tcp_canceltimers(tp);
                    574:        TCP_CLEAR_DELACK(tp);
                    575:        syn_cache_cleanup(tp);
                    576:
                    577: #ifdef TCP_SACK
                    578:        /* Free SACK holes. */
                    579:        q = p = tp->snd_holes;
                    580:        while (p != 0) {
                    581:                q = p->next;
                    582:                pool_put(&sackhl_pool, p);
                    583:                p = q;
                    584:        }
                    585: #endif
                    586:        if (tp->t_template)
                    587:                (void) m_free(tp->t_template);
                    588:
                    589:        tp->t_flags |= TF_DEAD;
                    590:        timeout_add(&tp->t_reap_to, 0);
                    591:
                    592:        inp->inp_ppcb = 0;
                    593:        soisdisconnected(so);
                    594:        in_pcbdetach(inp);
                    595:        return ((struct tcpcb *)0);
                    596: }
                    597:
                    598: void
                    599: tcp_reaper(void *arg)
                    600: {
                    601:        struct tcpcb *tp = arg;
                    602:        int s;
                    603:
                    604:        s = splsoftnet();
                    605:        pool_put(&tcpcb_pool, tp);
                    606:        splx(s);
                    607:        tcpstat.tcps_closed++;
                    608: }
                    609:
                    610: int
                    611: tcp_freeq(struct tcpcb *tp)
                    612: {
                    613:        struct tcpqent *qe;
                    614:        int rv = 0;
                    615:
                    616:        while ((qe = TAILQ_FIRST(&tp->t_segq)) != NULL) {
                    617:                TAILQ_REMOVE(&tp->t_segq, qe, tcpqe_q);
                    618:                m_freem(qe->tcpqe_m);
                    619:                pool_put(&tcpqe_pool, qe);
                    620:                rv = 1;
                    621:        }
                    622:        return (rv);
                    623: }
                    624:
                    625: void
                    626: tcp_drain()
                    627: {
                    628:        struct inpcb *inp;
                    629:
                    630:        /* called at splnet() */
                    631:        CIRCLEQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) {
                    632:                struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
                    633:
                    634:                if (tp != NULL) {
                    635:                        if (tcp_reass_lock_try(tp) == 0)
                    636:                                continue;
                    637:                        if (tcp_freeq(tp))
                    638:                                tcpstat.tcps_conndrained++;
                    639:                        tcp_reass_unlock(tp);
                    640:                }
                    641:        }
                    642: }
                    643:
                    644: /*
                    645:  * Compute proper scaling value for receiver window from buffer space
                    646:  */
                    647:
                    648: void
                    649: tcp_rscale(struct tcpcb *tp, u_long hiwat)
                    650: {
                    651:        tp->request_r_scale = 0;
                    652:        while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
                    653:               TCP_MAXWIN << tp->request_r_scale < hiwat)
                    654:                tp->request_r_scale++;
                    655: }
                    656:
                    657: /*
                    658:  * Notify a tcp user of an asynchronous error;
                    659:  * store error as soft error, but wake up user
                    660:  * (for now, won't do anything until can select for soft error).
                    661:  */
                    662: void
                    663: tcp_notify(inp, error)
                    664:        struct inpcb *inp;
                    665:        int error;
                    666: {
                    667:        struct tcpcb *tp = (struct tcpcb *)inp->inp_ppcb;
                    668:        struct socket *so = inp->inp_socket;
                    669:
                    670:        /*
                    671:         * Ignore some errors if we are hooked up.
                    672:         * If connection hasn't completed, has retransmitted several times,
                    673:         * and receives a second error, give up now.  This is better
                    674:         * than waiting a long time to establish a connection that
                    675:         * can never complete.
                    676:         */
                    677:        if (tp->t_state == TCPS_ESTABLISHED &&
                    678:             (error == EHOSTUNREACH || error == ENETUNREACH ||
                    679:              error == EHOSTDOWN)) {
                    680:                return;
                    681:        } else if (TCPS_HAVEESTABLISHED(tp->t_state) == 0 &&
                    682:            tp->t_rxtshift > 3 && tp->t_softerror)
                    683:                so->so_error = error;
                    684:        else
                    685:                tp->t_softerror = error;
                    686:        wakeup((caddr_t) &so->so_timeo);
                    687:        sorwakeup(so);
                    688:        sowwakeup(so);
                    689: }
                    690:
                    691: #ifdef INET6
                    692: void
                    693: tcp6_ctlinput(cmd, sa, d)
                    694:        int cmd;
                    695:        struct sockaddr *sa;
                    696:        void *d;
                    697: {
                    698:        struct tcphdr th;
                    699:        struct tcpcb *tp;
                    700:        void (*notify)(struct inpcb *, int) = tcp_notify;
                    701:        struct ip6_hdr *ip6;
                    702:        const struct sockaddr_in6 *sa6_src = NULL;
                    703:        struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
                    704:        struct inpcb *inp;
                    705:        struct mbuf *m;
                    706:        tcp_seq seq;
                    707:        int off;
                    708:        struct {
                    709:                u_int16_t th_sport;
                    710:                u_int16_t th_dport;
                    711:                u_int32_t th_seq;
                    712:        } *thp;
                    713:
                    714:        if (sa->sa_family != AF_INET6 ||
                    715:            sa->sa_len != sizeof(struct sockaddr_in6) ||
                    716:            IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) ||
                    717:            IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr))
                    718:                return;
                    719:        if ((unsigned)cmd >= PRC_NCMDS)
                    720:                return;
                    721:        else if (cmd == PRC_QUENCH) {
                    722:                /*
                    723:                 * Don't honor ICMP Source Quench messages meant for
                    724:                 * TCP connections.
                    725:                 */
                    726:                /* XXX there's no PRC_QUENCH in IPv6 */
                    727:                return;
                    728:        } else if (PRC_IS_REDIRECT(cmd))
                    729:                notify = in_rtchange, d = NULL;
                    730:        else if (cmd == PRC_MSGSIZE)
                    731:                ; /* special code is present, see below */
                    732:        else if (cmd == PRC_HOSTDEAD)
                    733:                d = NULL;
                    734:        else if (inet6ctlerrmap[cmd] == 0)
                    735:                return;
                    736:
                    737:        /* if the parameter is from icmp6, decode it. */
                    738:        if (d != NULL) {
                    739:                struct ip6ctlparam *ip6cp = (struct ip6ctlparam *)d;
                    740:                m = ip6cp->ip6c_m;
                    741:                ip6 = ip6cp->ip6c_ip6;
                    742:                off = ip6cp->ip6c_off;
                    743:                sa6_src = ip6cp->ip6c_src;
                    744:        } else {
                    745:                m = NULL;
                    746:                ip6 = NULL;
                    747:                sa6_src = &sa6_any;
                    748:        }
                    749:
                    750:        if (ip6) {
                    751:                /*
                    752:                 * XXX: We assume that when ip6 is non NULL,
                    753:                 * M and OFF are valid.
                    754:                 */
                    755:
                    756:                /* check if we can safely examine src and dst ports */
                    757:                if (m->m_pkthdr.len < off + sizeof(*thp))
                    758:                        return;
                    759:
                    760:                bzero(&th, sizeof(th));
                    761: #ifdef DIAGNOSTIC
                    762:                if (sizeof(*thp) > sizeof(th))
                    763:                        panic("assumption failed in tcp6_ctlinput");
                    764: #endif
                    765:                m_copydata(m, off, sizeof(*thp), (caddr_t)&th);
                    766:
                    767:                /*
                    768:                 * Check to see if we have a valid TCP connection
                    769:                 * corresponding to the address in the ICMPv6 message
                    770:                 * payload.
                    771:                 */
                    772:                inp = in6_pcbhashlookup(&tcbtable, &sa6->sin6_addr,
                    773:                    th.th_dport, (struct in6_addr *)&sa6_src->sin6_addr,
                    774:                    th.th_sport);
                    775:                if (cmd == PRC_MSGSIZE) {
                    776:                        /*
                    777:                         * Depending on the value of "valid" and routing table
                    778:                         * size (mtudisc_{hi,lo}wat), we will:
                    779:                         * - recalcurate the new MTU and create the
                    780:                         *   corresponding routing entry, or
                    781:                         * - ignore the MTU change notification.
                    782:                         */
                    783:                        icmp6_mtudisc_update((struct ip6ctlparam *)d, inp != NULL);
                    784:                        return;
                    785:                }
                    786:                if (inp) {
                    787:                        seq = ntohl(th.th_seq);
                    788:                        if (inp->inp_socket &&
                    789:                            (tp = intotcpcb(inp)) &&
                    790:                            SEQ_GEQ(seq, tp->snd_una) &&
                    791:                            SEQ_LT(seq, tp->snd_max))
                    792:                                notify(inp, inet6ctlerrmap[cmd]);
                    793:                } else if (syn_cache_count &&
                    794:                    (inet6ctlerrmap[cmd] == EHOSTUNREACH ||
                    795:                     inet6ctlerrmap[cmd] == ENETUNREACH ||
                    796:                     inet6ctlerrmap[cmd] == EHOSTDOWN))
                    797:                        syn_cache_unreach((struct sockaddr *)sa6_src,
                    798:                            sa, &th);
                    799:        } else {
                    800:                (void) in6_pcbnotify(&tcbtable, sa, 0,
                    801:                    (struct sockaddr *)sa6_src, 0, cmd, NULL, notify);
                    802:        }
                    803: }
                    804: #endif
                    805:
                    806: void *
                    807: tcp_ctlinput(cmd, sa, v)
                    808:        int cmd;
                    809:        struct sockaddr *sa;
                    810:        void *v;
                    811: {
                    812:        struct ip *ip = v;
                    813:        struct tcphdr *th;
                    814:        struct tcpcb *tp;
                    815:        struct inpcb *inp;
                    816:        struct in_addr faddr;
                    817:        tcp_seq seq;
                    818:        u_int mtu;
                    819:        extern int inetctlerrmap[];
                    820:        void (*notify)(struct inpcb *, int) = tcp_notify;
                    821:        int errno;
                    822:
                    823:        if (sa->sa_family != AF_INET)
                    824:                return NULL;
                    825:        faddr = satosin(sa)->sin_addr;
                    826:        if (faddr.s_addr == INADDR_ANY)
                    827:                return NULL;
                    828:
                    829:        if ((unsigned)cmd >= PRC_NCMDS)
                    830:                return NULL;
                    831:        errno = inetctlerrmap[cmd];
                    832:        if (cmd == PRC_QUENCH)
                    833:                /*
                    834:                 * Don't honor ICMP Source Quench messages meant for
                    835:                 * TCP connections.
                    836:                 */
                    837:                return NULL;
                    838:        else if (PRC_IS_REDIRECT(cmd))
                    839:                notify = in_rtchange, ip = 0;
                    840:        else if (cmd == PRC_MSGSIZE && ip_mtudisc && ip) {
                    841:                /*
                    842:                 * Verify that the packet in the icmp payload refers
                    843:                 * to an existing TCP connection.
                    844:                 */
                    845:                th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
                    846:                seq = ntohl(th->th_seq);
                    847:                inp = in_pcbhashlookup(&tcbtable,
                    848:                    ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport);
                    849:                if (inp && (tp = intotcpcb(inp)) &&
                    850:                    SEQ_GEQ(seq, tp->snd_una) &&
                    851:                    SEQ_LT(seq, tp->snd_max)) {
                    852:                        struct icmp *icp;
                    853:                        icp = (struct icmp *)((caddr_t)ip -
                    854:                                              offsetof(struct icmp, icmp_ip));
                    855:
                    856:                        /*
                    857:                         * If the ICMP message advertises a Next-Hop MTU
                    858:                         * equal or larger than the maximum packet size we have
                    859:                         * ever sent, drop the message.
                    860:                         */
                    861:                        mtu = (u_int)ntohs(icp->icmp_nextmtu);
                    862:                        if (mtu >= tp->t_pmtud_mtu_sent)
                    863:                                return NULL;
                    864:                        if (mtu >= tcp_hdrsz(tp) + tp->t_pmtud_mss_acked) {
                    865:                                /*
                    866:                                 * Calculate new MTU, and create corresponding
                    867:                                 * route (traditional PMTUD).
                    868:                                 */
                    869:                                tp->t_flags &= ~TF_PMTUD_PEND;
                    870:                                icmp_mtudisc(icp);
                    871:                        } else {
                    872:                                /*
                    873:                                 * Record the information got in the ICMP
                    874:                                 * message; act on it later.
                    875:                                 * If we had already recorded an ICMP message,
                    876:                                 * replace the old one only if the new message
                    877:                                 * refers to an older TCP segment
                    878:                                 */
                    879:                                if (tp->t_flags & TF_PMTUD_PEND) {
                    880:                                        if (SEQ_LT(tp->t_pmtud_th_seq, seq))
                    881:                                                return NULL;
                    882:                                } else
                    883:                                        tp->t_flags |= TF_PMTUD_PEND;
                    884:                                tp->t_pmtud_th_seq = seq;
                    885:                                tp->t_pmtud_nextmtu = icp->icmp_nextmtu;
                    886:                                tp->t_pmtud_ip_len = icp->icmp_ip.ip_len;
                    887:                                tp->t_pmtud_ip_hl = icp->icmp_ip.ip_hl;
                    888:                                return NULL;
                    889:                        }
                    890:                } else {
                    891:                        /* ignore if we don't have a matching connection */
                    892:                        return NULL;
                    893:                }
                    894:                notify = tcp_mtudisc, ip = 0;
                    895:        } else if (cmd == PRC_MTUINC)
                    896:                notify = tcp_mtudisc_increase, ip = 0;
                    897:        else if (cmd == PRC_HOSTDEAD)
                    898:                ip = 0;
                    899:        else if (errno == 0)
                    900:                return NULL;
                    901:
                    902:        if (ip) {
                    903:                th = (struct tcphdr *)((caddr_t)ip + (ip->ip_hl << 2));
                    904:                inp = in_pcbhashlookup(&tcbtable,
                    905:                    ip->ip_dst, th->th_dport, ip->ip_src, th->th_sport);
                    906:                if (inp) {
                    907:                        seq = ntohl(th->th_seq);
                    908:                        if (inp->inp_socket &&
                    909:                            (tp = intotcpcb(inp)) &&
                    910:                            SEQ_GEQ(seq, tp->snd_una) &&
                    911:                            SEQ_LT(seq, tp->snd_max))
                    912:                                notify(inp, errno);
                    913:                } else if (syn_cache_count &&
                    914:                    (inetctlerrmap[cmd] == EHOSTUNREACH ||
                    915:                     inetctlerrmap[cmd] == ENETUNREACH ||
                    916:                     inetctlerrmap[cmd] == EHOSTDOWN)) {
                    917:                        struct sockaddr_in sin;
                    918:
                    919:                        bzero(&sin, sizeof(sin));
                    920:                        sin.sin_len = sizeof(sin);
                    921:                        sin.sin_family = AF_INET;
                    922:                        sin.sin_port = th->th_sport;
                    923:                        sin.sin_addr = ip->ip_src;
                    924:                        syn_cache_unreach((struct sockaddr *)&sin,
                    925:                            sa, th);
                    926:                }
                    927:        } else
                    928:                in_pcbnotifyall(&tcbtable, sa, errno, notify);
                    929:
                    930:        return NULL;
                    931: }
                    932:
                    933:
                    934: #ifdef INET6
                    935: /*
                    936:  * Path MTU Discovery handlers.
                    937:  */
                    938: void
                    939: tcp6_mtudisc_callback(faddr)
                    940:        struct in6_addr *faddr;
                    941: {
                    942:        struct sockaddr_in6 sin6;
                    943:
                    944:        bzero(&sin6, sizeof(sin6));
                    945:        sin6.sin6_family = AF_INET6;
                    946:        sin6.sin6_len = sizeof(struct sockaddr_in6);
                    947:        sin6.sin6_addr = *faddr;
                    948:        (void) in6_pcbnotify(&tcbtable, (struct sockaddr *)&sin6, 0,
                    949:            (struct sockaddr *)&sa6_any, 0, PRC_MSGSIZE, NULL, tcp_mtudisc);
                    950: }
                    951: #endif /* INET6 */
                    952:
                    953: /*
                    954:  * On receipt of path MTU corrections, flush old route and replace it
                    955:  * with the new one.  Retransmit all unacknowledged packets, to ensure
                    956:  * that all packets will be received.
                    957:  */
                    958: void
                    959: tcp_mtudisc(inp, errno)
                    960:        struct inpcb *inp;
                    961:        int errno;
                    962: {
                    963:        struct tcpcb *tp = intotcpcb(inp);
                    964:        struct rtentry *rt = in_pcbrtentry(inp);
                    965:        int change = 0;
                    966:
                    967:        if (tp != 0) {
                    968:                int orig_maxseg = tp->t_maxseg;
                    969:                if (rt != 0) {
                    970:                        /*
                    971:                         * If this was not a host route, remove and realloc.
                    972:                         */
                    973:                        if ((rt->rt_flags & RTF_HOST) == 0) {
                    974:                                in_rtchange(inp, errno);
                    975:                                if ((rt = in_pcbrtentry(inp)) == 0)
                    976:                                        return;
                    977:                        }
                    978:                        if (orig_maxseg != tp->t_maxseg ||
                    979:                            (rt->rt_rmx.rmx_locks & RTV_MTU))
                    980:                                change = 1;
                    981:                }
                    982:                tcp_mss(tp, -1);
                    983:
                    984:                /*
                    985:                 * Resend unacknowledged packets
                    986:                 */
                    987:                tp->snd_nxt = tp->snd_una;
                    988:                if (change || errno > 0)
                    989:                        tcp_output(tp);
                    990:        }
                    991: }
                    992:
                    993: void
                    994: tcp_mtudisc_increase(inp, errno)
                    995:        struct inpcb *inp;
                    996:        int errno;
                    997: {
                    998:        struct tcpcb *tp = intotcpcb(inp);
                    999:        struct rtentry *rt = in_pcbrtentry(inp);
                   1000:
                   1001:        if (tp != 0 && rt != 0) {
                   1002:                /*
                   1003:                 * If this was a host route, remove and realloc.
                   1004:                 */
                   1005:                if (rt->rt_flags & RTF_HOST)
                   1006:                        in_rtchange(inp, errno);
                   1007:
                   1008:                /* also takes care of congestion window */
                   1009:                tcp_mss(tp, -1);
                   1010:        }
                   1011: }
                   1012:
                   1013: #define TCP_ISS_CONN_INC 4096
                   1014: int tcp_secret_init;
                   1015: u_char tcp_secret[16];
                   1016: MD5_CTX tcp_secret_ctx;
                   1017:
                   1018: void
                   1019: tcp_set_iss_tsm(struct tcpcb *tp)
                   1020: {
                   1021:        MD5_CTX ctx;
                   1022:        u_int32_t digest[4];
                   1023:
                   1024:        if (tcp_secret_init == 0) {
                   1025:                arc4random_bytes(tcp_secret, sizeof(tcp_secret));
                   1026:                MD5Init(&tcp_secret_ctx);
                   1027:                MD5Update(&tcp_secret_ctx, tcp_secret, sizeof(tcp_secret));
                   1028:                tcp_secret_init = 1;
                   1029:        }
                   1030:        ctx = tcp_secret_ctx;
                   1031:        MD5Update(&ctx, (char *)&tp->t_inpcb->inp_lport, sizeof(u_short));
                   1032:        MD5Update(&ctx, (char *)&tp->t_inpcb->inp_fport, sizeof(u_short));
                   1033:        if (tp->pf == AF_INET6) {
                   1034:                MD5Update(&ctx, (char *)&tp->t_inpcb->inp_laddr6,
                   1035:                    sizeof(struct in6_addr));
                   1036:                MD5Update(&ctx, (char *)&tp->t_inpcb->inp_faddr6,
                   1037:                    sizeof(struct in6_addr));
                   1038:        } else {
                   1039:                MD5Update(&ctx, (char *)&tp->t_inpcb->inp_laddr,
                   1040:                    sizeof(struct in_addr));
                   1041:                MD5Update(&ctx, (char *)&tp->t_inpcb->inp_faddr,
                   1042:                    sizeof(struct in_addr));
                   1043:        }
                   1044:        MD5Final((u_char *)digest, &ctx);
                   1045:        tcp_iss += TCP_ISS_CONN_INC;
                   1046:        tp->iss = digest[0] + tcp_iss;
                   1047:        tp->ts_modulate = digest[1];
                   1048: }
                   1049:
                   1050: #ifdef TCP_SIGNATURE
                   1051: int
                   1052: tcp_signature_tdb_attach()
                   1053: {
                   1054:        return (0);
                   1055: }
                   1056:
                   1057: int
                   1058: tcp_signature_tdb_init(tdbp, xsp, ii)
                   1059:        struct tdb *tdbp;
                   1060:        struct xformsw *xsp;
                   1061:        struct ipsecinit *ii;
                   1062: {
                   1063:        if ((ii->ii_authkeylen < 1) || (ii->ii_authkeylen > 80))
                   1064:                return (EINVAL);
                   1065:
                   1066:        tdbp->tdb_amxkey = malloc(ii->ii_authkeylen, M_XDATA, M_DONTWAIT);
                   1067:        if (tdbp->tdb_amxkey == NULL)
                   1068:                return (ENOMEM);
                   1069:        bcopy(ii->ii_authkey, tdbp->tdb_amxkey, ii->ii_authkeylen);
                   1070:        tdbp->tdb_amxkeylen = ii->ii_authkeylen;
                   1071:
                   1072:        return (0);
                   1073: }
                   1074:
                   1075: int
                   1076: tcp_signature_tdb_zeroize(tdbp)
                   1077:        struct tdb *tdbp;
                   1078: {
                   1079:        if (tdbp->tdb_amxkey) {
                   1080:                bzero(tdbp->tdb_amxkey, tdbp->tdb_amxkeylen);
                   1081:                free(tdbp->tdb_amxkey, M_XDATA);
                   1082:                tdbp->tdb_amxkey = NULL;
                   1083:        }
                   1084:
                   1085:        return (0);
                   1086: }
                   1087:
                   1088: int
                   1089: tcp_signature_tdb_input(m, tdbp, skip, protoff)
                   1090:        struct mbuf *m;
                   1091:        struct tdb *tdbp;
                   1092:        int skip, protoff;
                   1093: {
                   1094:        return (0);
                   1095: }
                   1096:
                   1097: int
                   1098: tcp_signature_tdb_output(m, tdbp, mp, skip, protoff)
                   1099:        struct mbuf *m;
                   1100:        struct tdb *tdbp;
                   1101:        struct mbuf **mp;
                   1102:        int skip, protoff;
                   1103: {
                   1104:        return (EINVAL);
                   1105: }
                   1106:
                   1107: int
                   1108: tcp_signature_apply(fstate, data, len)
                   1109:        caddr_t fstate;
                   1110:        caddr_t data;
                   1111:        unsigned int len;
                   1112: {
                   1113:        MD5Update((MD5_CTX *)fstate, (char *)data, len);
                   1114:        return 0;
                   1115: }
                   1116:
                   1117: int
                   1118: tcp_signature(struct tdb *tdb, int af, struct mbuf *m, struct tcphdr *th,
                   1119:     int iphlen, int doswap, char *sig)
                   1120: {
                   1121:        MD5_CTX ctx;
                   1122:        int len;
                   1123:        struct tcphdr th0;
                   1124:
                   1125:        MD5Init(&ctx);
                   1126:
                   1127:        switch(af) {
                   1128:        case 0:
                   1129: #ifdef INET
                   1130:        case AF_INET: {
                   1131:                struct ippseudo ippseudo;
                   1132:                struct ip *ip;
                   1133:
                   1134:                ip = mtod(m, struct ip *);
                   1135:
                   1136:                ippseudo.ippseudo_src = ip->ip_src;
                   1137:                ippseudo.ippseudo_dst = ip->ip_dst;
                   1138:                ippseudo.ippseudo_pad = 0;
                   1139:                ippseudo.ippseudo_p = IPPROTO_TCP;
                   1140:                ippseudo.ippseudo_len = htons(m->m_pkthdr.len - iphlen);
                   1141:
                   1142:                MD5Update(&ctx, (char *)&ippseudo,
                   1143:                    sizeof(struct ippseudo));
                   1144:                break;
                   1145:                }
                   1146: #endif
                   1147: #ifdef INET6
                   1148:        case AF_INET6: {
                   1149:                struct ip6_hdr_pseudo ip6pseudo;
                   1150:                struct ip6_hdr *ip6;
                   1151:
                   1152:                ip6 = mtod(m, struct ip6_hdr *);
                   1153:                bzero(&ip6pseudo, sizeof(ip6pseudo));
                   1154:                ip6pseudo.ip6ph_src = ip6->ip6_src;
                   1155:                ip6pseudo.ip6ph_dst = ip6->ip6_dst;
                   1156:                in6_clearscope(&ip6pseudo.ip6ph_src);
                   1157:                in6_clearscope(&ip6pseudo.ip6ph_dst);
                   1158:                ip6pseudo.ip6ph_nxt = IPPROTO_TCP;
                   1159:                ip6pseudo.ip6ph_len = htonl(m->m_pkthdr.len - iphlen);
                   1160:
                   1161:                MD5Update(&ctx, (char *)&ip6pseudo,
                   1162:                    sizeof(ip6pseudo));
                   1163:                break;
                   1164:                }
                   1165: #endif
                   1166:        }
                   1167:
                   1168:        th0 = *th;
                   1169:        th0.th_sum = 0;
                   1170:
                   1171:        if (doswap) {
                   1172:                HTONL(th0.th_seq);
                   1173:                HTONL(th0.th_ack);
                   1174:                HTONS(th0.th_win);
                   1175:                HTONS(th0.th_urp);
                   1176:        }
                   1177:        MD5Update(&ctx, (char *)&th0, sizeof(th0));
                   1178:
                   1179:        len = m->m_pkthdr.len - iphlen - th->th_off * sizeof(uint32_t);
                   1180:
                   1181:        if (len > 0 &&
                   1182:            m_apply(m, iphlen + th->th_off * sizeof(uint32_t), len,
                   1183:            tcp_signature_apply, (caddr_t)&ctx))
                   1184:                return (-1);
                   1185:
                   1186:        MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
                   1187:        MD5Final(sig, &ctx);
                   1188:
                   1189:        return (0);
                   1190: }
                   1191: #endif /* TCP_SIGNATURE */
                   1192:
                   1193: #define TCP_RNDISS_ROUNDS      16
                   1194: #define TCP_RNDISS_OUT 7200
                   1195: #define TCP_RNDISS_MAX 30000
                   1196:
                   1197: u_int8_t tcp_rndiss_sbox[128];
                   1198: u_int16_t tcp_rndiss_msb;
                   1199: u_int16_t tcp_rndiss_cnt;
                   1200: long tcp_rndiss_reseed;
                   1201:
                   1202: u_int16_t
                   1203: tcp_rndiss_encrypt(val)
                   1204:        u_int16_t val;
                   1205: {
                   1206:        u_int16_t sum = 0, i;
                   1207:
                   1208:        for (i = 0; i < TCP_RNDISS_ROUNDS; i++) {
                   1209:                sum += 0x79b9;
                   1210:                val ^= ((u_int16_t)tcp_rndiss_sbox[(val^sum) & 0x7f]) << 7;
                   1211:                val = ((val & 0xff) << 7) | (val >> 8);
                   1212:        }
                   1213:
                   1214:        return val;
                   1215: }
                   1216:
                   1217: void
                   1218: tcp_rndiss_init()
                   1219: {
                   1220:        get_random_bytes(tcp_rndiss_sbox, sizeof(tcp_rndiss_sbox));
                   1221:
                   1222:        tcp_rndiss_reseed = time_second + TCP_RNDISS_OUT;
                   1223:        tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000;
                   1224:        tcp_rndiss_cnt = 0;
                   1225: }
                   1226:
                   1227: tcp_seq
                   1228: tcp_rndiss_next()
                   1229: {
                   1230:         if (tcp_rndiss_cnt >= TCP_RNDISS_MAX ||
                   1231:            time_second > tcp_rndiss_reseed)
                   1232:                 tcp_rndiss_init();
                   1233:
                   1234:        /* (arc4random() & 0x7fff) ensures a 32768 byte gap between ISS */
                   1235:        return ((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | tcp_rndiss_msb) <<16) |
                   1236:                (arc4random() & 0x7fff);
                   1237: }
                   1238:

CVSweb