[BACK]Return to ipsec.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netipsec

Annotation of src/sys/netipsec/ipsec.c, Revision 1.28

1.28    ! degroote    1: /*     $NetBSD: ipsec.c,v 1.27 2007/03/04 06:03:28 christos Exp $      */
1.1       jonathan    2: /*     $FreeBSD: /usr/local/www/cvsroot/FreeBSD/src/sys/netipsec/ipsec.c,v 1.2.2.2 2003/07/01 01:38:13 sam Exp $       */
                      3: /*     $KAME: ipsec.c,v 1.103 2001/05/24 07:14:18 sakane Exp $ */
                      4:
                      5: /*
                      6:  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
1.26      degroote   13:  *     notice, this list of conditions and the following disclaimer.
1.1       jonathan   14:  * 2. Redistributions in binary form must reproduce the above copyright
1.26      degroote   15:  *     notice, this list of conditions and the following disclaimer in the
                     16:  *     documentation and/or other materials provided with the distribution.
1.1       jonathan   17:  * 3. Neither the name of the project nor the names of its contributors
1.26      degroote   18:  *     may be used to endorse or promote products derived from this software
                     19:  *     without specific prior written permission.
1.1       jonathan   20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
                     22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
                     25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  */
                     33:
                     34: #include <sys/cdefs.h>
1.28    ! degroote   35: __KERNEL_RCSID(0, "$NetBSD: ipsec.c,v 1.27 2007/03/04 06:03:28 christos Exp $");
1.1       jonathan   36:
                     37: /*
                     38:  * IPsec controller part.
                     39:  */
                     40:
                     41: #include "opt_inet.h"
1.2       jonathan   42: #ifdef __FreeBSD__
1.1       jonathan   43: #include "opt_inet6.h"
1.2       jonathan   44: #endif
1.1       jonathan   45: #include "opt_ipsec.h"
                     46:
                     47: #include <sys/param.h>
                     48: #include <sys/systm.h>
                     49: #include <sys/malloc.h>
                     50: #include <sys/mbuf.h>
                     51: #include <sys/domain.h>
                     52: #include <sys/protosw.h>
                     53: #include <sys/socket.h>
                     54: #include <sys/socketvar.h>
                     55: #include <sys/errno.h>
                     56: #include <sys/time.h>
                     57: #include <sys/kernel.h>
                     58: #include <sys/syslog.h>
                     59: #include <sys/sysctl.h>
                     60: #include <sys/proc.h>
                     61:
                     62: #include <net/if.h>
                     63: #include <net/route.h>
                     64:
                     65: #include <netinet/in.h>
                     66: #include <netinet/in_systm.h>
                     67: #include <netinet/ip.h>
                     68: #include <netinet/ip_var.h>
                     69: #include <netinet/in_var.h>
                     70: #include <netinet/udp.h>
                     71: #include <netinet/udp_var.h>
                     72: #include <netinet/tcp.h>
                     73: #include <netinet/udp.h>
                     74:
                     75: #include <netinet/ip6.h>
                     76: #ifdef INET6
                     77: #include <netinet6/ip6_var.h>
                     78: #endif
                     79: #include <netinet/in_pcb.h>
                     80: #ifdef INET6
1.5       jonathan   81: #include <netinet6/in6_pcb.h>
1.1       jonathan   82: #include <netinet/icmp6.h>
                     83: #endif
                     84:
                     85: #include <netipsec/ipsec.h>
1.13      jonathan   86: #include <netipsec/ipsec_var.h>
1.1       jonathan   87: #ifdef INET6
                     88: #include <netipsec/ipsec6.h>
                     89: #endif
                     90: #include <netipsec/ah_var.h>
                     91: #include <netipsec/esp_var.h>
                     92: #include <netipsec/ipcomp.h>           /*XXX*/
                     93: #include <netipsec/ipcomp_var.h>
                     94:
1.4       tls        95: #include <netipsec/key.h>
                     96: #include <netipsec/keydb.h>
                     97: #include <netipsec/key_debug.h>
1.1       jonathan   98:
                     99: #include <netipsec/xform.h>
                    100:
                    101: #include <netipsec/ipsec_osdep.h>
                    102:
                    103: #include <net/net_osdep.h>
                    104:
                    105: #ifdef IPSEC_DEBUG
                    106: int ipsec_debug = 1;
1.21      rpaulo    107:
1.26      degroote  108: /*
1.21      rpaulo    109:  * When set to 1, IPsec will send packets with the same sequence number.
                    110:  * This allows to verify if the other side has proper replay attacks detection.
                    111:  */
                    112: int ipsec_replay = 0;
                    113:
                    114: /*
                    115:  * When set 1, IPsec will send packets with corrupted HMAC.
                    116:  * This allows to verify if the other side properly detects modified packets.
                    117:  */
                    118: int ipsec_integrity = 0;
1.1       jonathan  119: #else
                    120: int ipsec_debug = 0;
                    121: #endif
                    122:
                    123: /* NB: name changed so netstat doesn't use it */
                    124: struct newipsecstat newipsecstat;
                    125: int ip4_ah_offsetmask = 0;     /* maybe IP_DF? */
1.18      christos  126: int ip4_ipsec_dfbit = 2;       /* DF bit on encap. 0: clear 1: set 2: copy */
1.1       jonathan  127: int ip4_esp_trans_deflev = IPSEC_LEVEL_USE;
                    128: int ip4_esp_net_deflev = IPSEC_LEVEL_USE;
                    129: int ip4_ah_trans_deflev = IPSEC_LEVEL_USE;
                    130: int ip4_ah_net_deflev = IPSEC_LEVEL_USE;
                    131: struct secpolicy ip4_def_policy;
                    132: int ip4_ipsec_ecn = 0;         /* ECN ignore(-1)/forbidden(0)/allowed(1) */
                    133: int ip4_esp_randpad = -1;
1.9       thorpej   134:
                    135: #ifdef __NetBSD__
                    136: u_int ipsec_spdgen = 1;                /* SPD generation # */
                    137:
                    138: static struct secpolicy *ipsec_checkpcbcache __P((struct mbuf *,
                    139:        struct inpcbpolicy *, int));
                    140: static int ipsec_fillpcbcache __P((struct inpcbpolicy *, struct mbuf *,
                    141:        struct secpolicy *, int));
                    142: static int ipsec_invalpcbcache __P((struct inpcbpolicy *, int));
                    143: #endif /* __NetBSD__ */
                    144:
1.1       jonathan  145: /*
                    146:  * Crypto support requirements:
                    147:  *
                    148:  *  1  require hardware support
                    149:  * -1  require software support
                    150:  *  0  take anything
                    151:  */
                    152: int    crypto_support = 0;
                    153:
1.5       jonathan  154: static struct secpolicy *ipsec_getpolicybysock(struct mbuf *, u_int,
                    155:        PCB_T *, int *);
                    156:
1.1       jonathan  157: #ifdef __FreeBSD__
                    158: SYSCTL_DECL(_net_inet_ipsec);
                    159:
                    160: /* net.inet.ipsec */
                    161: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_POLICY,
                    162:        def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, "");
                    163: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
                    164:        CTLFLAG_RW, &ip4_esp_trans_deflev,      0, "");
                    165: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
                    166:        CTLFLAG_RW, &ip4_esp_net_deflev,        0, "");
                    167: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
                    168:        CTLFLAG_RW, &ip4_ah_trans_deflev,       0, "");
                    169: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
                    170:        CTLFLAG_RW, &ip4_ah_net_deflev, 0, "");
                    171: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_CLEARTOS,
                    172:        ah_cleartos, CTLFLAG_RW,        &ah_cleartos,   0, "");
                    173: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_AH_OFFSETMASK,
                    174:        ah_offsetmask, CTLFLAG_RW,      &ip4_ah_offsetmask,     0, "");
                    175: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DFBIT,
                    176:        dfbit, CTLFLAG_RW,      &ip4_ipsec_dfbit,       0, "");
                    177: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ECN,
                    178:        ecn, CTLFLAG_RW,        &ip4_ipsec_ecn, 0, "");
                    179: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_DEBUG,
                    180:        debug, CTLFLAG_RW,      &ipsec_debug,   0, "");
                    181: SYSCTL_INT(_net_inet_ipsec, IPSECCTL_ESP_RANDPAD,
                    182:        esp_randpad, CTLFLAG_RW,        &ip4_esp_randpad,       0, "");
                    183: SYSCTL_INT(_net_inet_ipsec, OID_AUTO,
                    184:        crypto_support, CTLFLAG_RW,     &crypto_support,0, "");
                    185: SYSCTL_STRUCT(_net_inet_ipsec, OID_AUTO,
                    186:        ipsecstats,     CTLFLAG_RD,     &newipsecstat,  newipsecstat, "");
1.21      rpaulo    187: SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_replay, CTLFLAG_RW, &ipsec_replay, 0,
1.26      degroote  188:        "Emulate replay attack");
1.21      rpaulo    189: SYSCTL_INT(_net_inet_ipsec, OID_AUTO, test_integrity, CTLFLAG_RW,
1.26      degroote  190:        &ipsec_integrity, 0, "Emulate man-in-the-middle attack");
1.4       tls       191: #endif /* __FreeBSD__ */
1.1       jonathan  192:
                    193: #ifdef INET6
                    194: int ip6_esp_trans_deflev = IPSEC_LEVEL_USE;
                    195: int ip6_esp_net_deflev = IPSEC_LEVEL_USE;
                    196: int ip6_ah_trans_deflev = IPSEC_LEVEL_USE;
                    197: int ip6_ah_net_deflev = IPSEC_LEVEL_USE;
1.5       jonathan  198: struct secpolicy ip6_def_policy;
1.1       jonathan  199: int ip6_ipsec_ecn = 0;         /* ECN ignore(-1)/forbidden(0)/allowed(1) */
                    200: int ip6_esp_randpad = -1;
                    201:
1.5       jonathan  202:
                    203: #ifdef __FreeBSD__
1.1       jonathan  204: SYSCTL_DECL(_net_inet6_ipsec6);
                    205:
                    206: /* net.inet6.ipsec6 */
                    207: #ifdef COMPAT_KAME
                    208: SYSCTL_OID(_net_inet6_ipsec6, IPSECCTL_STATS, stats, CTLFLAG_RD,
                    209:        0,0, compat_ipsecstats_sysctl, "S", "");
                    210: #endif /* COMPAT_KAME */
                    211: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_POLICY,
                    212:        def_policy, CTLFLAG_RW, &ip4_def_policy.policy, 0, "");
                    213: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_TRANSLEV, esp_trans_deflev,
                    214:        CTLFLAG_RW, &ip6_esp_trans_deflev,      0, "");
                    215: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_ESP_NETLEV, esp_net_deflev,
                    216:        CTLFLAG_RW, &ip6_esp_net_deflev,        0, "");
                    217: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_TRANSLEV, ah_trans_deflev,
                    218:        CTLFLAG_RW, &ip6_ah_trans_deflev,       0, "");
                    219: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEF_AH_NETLEV, ah_net_deflev,
                    220:        CTLFLAG_RW, &ip6_ah_net_deflev, 0, "");
                    221: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ECN,
                    222:        ecn, CTLFLAG_RW,        &ip6_ipsec_ecn, 0, "");
                    223: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_DEBUG,
                    224:        debug, CTLFLAG_RW,      &ipsec_debug,   0, "");
                    225: SYSCTL_INT(_net_inet6_ipsec6, IPSECCTL_ESP_RANDPAD,
                    226:        esp_randpad, CTLFLAG_RW,        &ip6_esp_randpad,       0, "");
                    227: #endif /* INET6 */
1.6       jonathan  228: #endif /* __FreeBSD__ */
1.1       jonathan  229:
                    230: static int ipsec4_setspidx_inpcb __P((struct mbuf *, struct inpcb *pcb));
                    231: #ifdef INET6
                    232: static int ipsec6_setspidx_in6pcb __P((struct mbuf *, struct in6pcb *pcb));
                    233: #endif
                    234: static int ipsec_setspidx __P((struct mbuf *, struct secpolicyindex *, int));
                    235: static void ipsec4_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
                    236: static int ipsec4_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
                    237: #ifdef INET6
                    238: static void ipsec6_get_ulp __P((struct mbuf *m, struct secpolicyindex *, int));
                    239: static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
                    240: #endif
                    241: static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
                    242: static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *src));
                    243: static int ipsec_set_policy __P((struct secpolicy **pcb_sp,
1.27      christos  244:        int optname, void *request, size_t len, int priv));
1.1       jonathan  245: static int ipsec_get_policy __P((struct secpolicy *pcb_sp, struct mbuf **mp));
                    246: static void vshiftl __P((unsigned char *, int, int));
                    247: static size_t ipsec_hdrsiz __P((struct secpolicy *));
                    248:
1.9       thorpej   249: #ifdef __NetBSD__
                    250: /*
                    251:  * Try to validate and use cached policy on a PCB.
                    252:  */
                    253: static struct secpolicy *
                    254: ipsec_checkpcbcache(struct mbuf *m, struct inpcbpolicy *pcbsp, int dir)
                    255: {
                    256:        struct secpolicyindex spidx;
                    257:
                    258:        switch (dir) {
                    259:        case IPSEC_DIR_INBOUND:
                    260:        case IPSEC_DIR_OUTBOUND:
                    261:        case IPSEC_DIR_ANY:
                    262:                break;
                    263:        default:
                    264:                return NULL;
                    265:        }
                    266: #ifdef DIAGNOSTIC
1.13      jonathan  267:        if (pcbsp == NULL) {
                    268:                printf("ipsec_checkpcbcache: NULL pcbsp\n");
                    269:                /* XXX panic? */
                    270:                return NULL;
                    271:        }
                    272: #endif
                    273:
                    274: #ifdef DIAGNOSTIC
1.9       thorpej   275:        if (dir >= sizeof(pcbsp->sp_cache)/sizeof(pcbsp->sp_cache[0]))
                    276:                panic("dir too big in ipsec_checkpcbcache");
                    277: #endif
                    278:        /* SPD table change invalidate all the caches. */
                    279:        if (ipsec_spdgen != pcbsp->sp_cache[dir].cachegen) {
                    280:                ipsec_invalpcbcache(pcbsp, dir);
                    281:                return NULL;
                    282:        }
                    283:        if (!pcbsp->sp_cache[dir].cachesp)
                    284:                return NULL;
                    285:        if (pcbsp->sp_cache[dir].cachesp->state != IPSEC_SPSTATE_ALIVE) {
                    286:                ipsec_invalpcbcache(pcbsp, dir);
                    287:                return NULL;
                    288:        }
                    289:        if ((pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) == 0) {
                    290:                if (!pcbsp->sp_cache[dir].cachesp)
                    291:                        return NULL;
                    292:                if (ipsec_setspidx(m, &spidx, 1) != 0)
                    293:                        return NULL;
                    294:                if (bcmp(&pcbsp->sp_cache[dir].cacheidx, &spidx,
                    295:                         sizeof(spidx))) {
                    296:                        if (!key_cmpspidx_withmask(&pcbsp->sp_cache[dir].cachesp->spidx,
1.26      degroote  297:                                &spidx))
1.9       thorpej   298:                                return NULL;
                    299:                        pcbsp->sp_cache[dir].cacheidx = spidx;
                    300:                }
                    301:        } else {
                    302:                /*
                    303:                 * The pcb is connected, and the L4 code is sure that:
                    304:                 * - outgoing side uses inp_[lf]addr
                    305:                 * - incoming side looks up policy after inpcb lookup
                    306:                 * and address pair is know to be stable.  We do not need
                    307:                 * to generate spidx again, nor check the address match again.
                    308:                 *
                    309:                 * For IPv4/v6 SOCK_STREAM sockets, this assumptions holds
                    310:                 * and there are calls to ipsec_pcbconn() from in_pcbconnect().
                    311:                 */
                    312:        }
                    313:
1.23      kardel    314:        pcbsp->sp_cache[dir].cachesp->lastused = time_second;
1.9       thorpej   315:        pcbsp->sp_cache[dir].cachesp->refcnt++;
                    316:        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                    317:                printf("DP ipsec_checkpcbcache cause refcnt++:%d SP:%p\n",
                    318:                pcbsp->sp_cache[dir].cachesp->refcnt,
                    319:                pcbsp->sp_cache[dir].cachesp));
                    320:        return pcbsp->sp_cache[dir].cachesp;
                    321: }
                    322:
                    323: static int
                    324: ipsec_fillpcbcache(struct inpcbpolicy *pcbsp, struct mbuf *m,
1.26      degroote  325:        struct secpolicy *sp, int dir)
1.9       thorpej   326: {
                    327:
                    328:        switch (dir) {
                    329:        case IPSEC_DIR_INBOUND:
                    330:        case IPSEC_DIR_OUTBOUND:
                    331:                break;
                    332:        default:
                    333:                return EINVAL;
                    334:        }
                    335: #ifdef DIAGNOSTIC
                    336:        if (dir >= sizeof(pcbsp->sp_cache)/sizeof(pcbsp->sp_cache[0]))
                    337:                panic("dir too big in ipsec_fillpcbcache");
                    338: #endif
                    339:
                    340:        if (pcbsp->sp_cache[dir].cachesp)
                    341:                KEY_FREESP(&pcbsp->sp_cache[dir].cachesp);
                    342:        pcbsp->sp_cache[dir].cachesp = NULL;
                    343:        pcbsp->sp_cache[dir].cachehint = IPSEC_PCBHINT_MAYBE;
                    344:        if (ipsec_setspidx(m, &pcbsp->sp_cache[dir].cacheidx, 1) != 0) {
                    345:                return EINVAL;
                    346:        }
                    347:        pcbsp->sp_cache[dir].cachesp = sp;
                    348:        if (pcbsp->sp_cache[dir].cachesp) {
                    349:                pcbsp->sp_cache[dir].cachesp->refcnt++;
                    350:                KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                    351:                        printf("DP ipsec_fillpcbcache cause refcnt++:%d SP:%p\n",
                    352:                        pcbsp->sp_cache[dir].cachesp->refcnt,
                    353:                        pcbsp->sp_cache[dir].cachesp));
                    354:
                    355:                /*
                    356:                 * If the PCB is connected, we can remember a hint to
                    357:                 * possibly short-circuit IPsec processing in other places.
                    358:                 */
                    359:                if (pcbsp->sp_cacheflags & IPSEC_PCBSP_CONNECTED) {
                    360:                        switch (pcbsp->sp_cache[dir].cachesp->policy) {
                    361:                        case IPSEC_POLICY_NONE:
                    362:                        case IPSEC_POLICY_BYPASS:
                    363:                                pcbsp->sp_cache[dir].cachehint =
1.26      degroote  364:                                        IPSEC_PCBHINT_NO;
1.9       thorpej   365:                                break;
                    366:                        default:
                    367:                                pcbsp->sp_cache[dir].cachehint =
1.26      degroote  368:                                        IPSEC_PCBHINT_YES;
1.9       thorpej   369:                        }
                    370:                }
                    371:        }
                    372:        pcbsp->sp_cache[dir].cachegen = ipsec_spdgen;
                    373:
                    374:        return 0;
                    375: }
                    376:
                    377: static int
                    378: ipsec_invalpcbcache(struct inpcbpolicy *pcbsp, int dir)
                    379: {
                    380:        int i;
                    381:
                    382:        for (i = IPSEC_DIR_INBOUND; i <= IPSEC_DIR_OUTBOUND; i++) {
                    383:                if (dir != IPSEC_DIR_ANY && i != dir)
                    384:                        continue;
                    385:                if (pcbsp->sp_cache[i].cachesp)
                    386:                        KEY_FREESP(&pcbsp->sp_cache[i].cachesp);
                    387:                pcbsp->sp_cache[i].cachesp = NULL;
                    388:                pcbsp->sp_cache[i].cachehint = IPSEC_PCBHINT_MAYBE;
                    389:                pcbsp->sp_cache[i].cachegen = 0;
                    390:                bzero(&pcbsp->sp_cache[i].cacheidx,
1.26      degroote  391:                          sizeof(pcbsp->sp_cache[i].cacheidx));
1.9       thorpej   392:        }
                    393:        return 0;
                    394: }
                    395:
                    396: void
                    397: ipsec_pcbconn(struct inpcbpolicy *pcbsp)
                    398: {
                    399:
                    400:        pcbsp->sp_cacheflags |= IPSEC_PCBSP_CONNECTED;
                    401:        ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY);
                    402: }
                    403:
                    404: void
                    405: ipsec_pcbdisconn(struct inpcbpolicy *pcbsp)
                    406: {
                    407:
                    408:        pcbsp->sp_cacheflags &= ~IPSEC_PCBSP_CONNECTED;
                    409:        ipsec_invalpcbcache(pcbsp, IPSEC_DIR_ANY);
                    410: }
                    411:
                    412: void
                    413: ipsec_invalpcbcacheall(void)
                    414: {
                    415:
                    416:        if (ipsec_spdgen == UINT_MAX)
                    417:                ipsec_spdgen = 1;
                    418:        else
                    419:                ipsec_spdgen++;
                    420: }
                    421: #endif /* __NetBSD__ */
                    422:
1.1       jonathan  423: /*
                    424:  * Return a held reference to the default SP.
                    425:  */
                    426: static struct secpolicy *
                    427: key_allocsp_default(const char* where, int tag)
                    428: {
                    429:        struct secpolicy *sp;
                    430:
                    431:        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                    432:                printf("DP key_allocsp_default from %s:%u\n", where, tag));
                    433:
                    434:        sp = &ip4_def_policy;
                    435:        if (sp->policy != IPSEC_POLICY_DISCARD &&
1.26      degroote  436:                sp->policy != IPSEC_POLICY_NONE) {
1.1       jonathan  437:                ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n",
1.26      degroote  438:                        sp->policy, IPSEC_POLICY_NONE));
1.1       jonathan  439:                sp->policy = IPSEC_POLICY_NONE;
                    440:        }
                    441:        sp->refcnt++;
                    442:
                    443:        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                    444:                printf("DP key_allocsp_default returns SP:%p (%u)\n",
                    445:                        sp, sp->refcnt));
                    446:        return sp;
                    447: }
                    448: #define        KEY_ALLOCSP_DEFAULT() \
                    449:        key_allocsp_default(__FILE__, __LINE__)
                    450:
                    451: /*
                    452:  * For OUTBOUND packet having a socket. Searching SPD for packet,
                    453:  * and return a pointer to SP.
                    454:  * OUT:        NULL:   no apropreate SP found, the following value is set to error.
                    455:  *             0       : bypass
                    456:  *             EACCES  : discard packet.
                    457:  *             ENOENT  : ipsec_acquire() in progress, maybe.
1.7       wiz       458:  *             others  : error occurred.
1.1       jonathan  459:  *     others: a pointer to SP
                    460:  *
1.20      wiz       461:  * NOTE: IPv6 mapped address concern is implemented here.
1.1       jonathan  462:  */
                    463: struct secpolicy *
                    464: ipsec_getpolicy(struct tdb_ident *tdbi, u_int dir)
                    465: {
                    466:        struct secpolicy *sp;
                    467:
                    468:        IPSEC_ASSERT(tdbi != NULL, ("ipsec_getpolicy: null tdbi"));
                    469:        IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
                    470:                ("ipsec_getpolicy: invalid direction %u", dir));
                    471:
                    472:        sp = KEY_ALLOCSP2(tdbi->spi, &tdbi->dst, tdbi->proto, dir);
                    473:        if (sp == NULL)                 /*XXX????*/
                    474:                sp = KEY_ALLOCSP_DEFAULT();
                    475:        IPSEC_ASSERT(sp != NULL, ("ipsec_getpolicy: null SP"));
                    476:        return sp;
                    477: }
                    478:
                    479: /*
                    480:  * For OUTBOUND packet having a socket. Searching SPD for packet,
                    481:  * and return a pointer to SP.
                    482:  * OUT:        NULL:   no apropreate SP found, the following value is set to error.
                    483:  *             0       : bypass
                    484:  *             EACCES  : discard packet.
                    485:  *             ENOENT  : ipsec_acquire() in progress, maybe.
1.7       wiz       486:  *             others  : error occurred.
1.1       jonathan  487:  *     others: a pointer to SP
                    488:  *
1.20      wiz       489:  * NOTE: IPv6 mapped address concern is implemented here.
1.1       jonathan  490:  */
1.5       jonathan  491: static struct secpolicy *
1.1       jonathan  492: ipsec_getpolicybysock(m, dir, inp, error)
                    493:        struct mbuf *m;
                    494:        u_int dir;
1.5       jonathan  495:        PCB_T *inp;
1.1       jonathan  496:        int *error;
                    497: {
                    498:        struct inpcbpolicy *pcbsp = NULL;
                    499:        struct secpolicy *currsp = NULL;        /* policy on socket */
                    500:        struct secpolicy *sp;
                    501:        int af;
                    502:
                    503:        IPSEC_ASSERT(m != NULL, ("ipsec_getpolicybysock: null mbuf"));
                    504:        IPSEC_ASSERT(inp != NULL, ("ipsec_getpolicybysock: null inpcb"));
                    505:        IPSEC_ASSERT(error != NULL, ("ipsec_getpolicybysock: null error"));
                    506:        IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
                    507:                ("ipsec_getpolicybysock: invalid direction %u", dir));
                    508:
1.9       thorpej   509:        IPSEC_ASSERT(PCB_SOCKET(inp) != NULL,
1.26      degroote  510:                ("ipsec_getppolicybysock: null socket\n"));
1.5       jonathan  511:
                    512:        /* XXX FIXME inpcb/in6pcb  vs socket*/
                    513:        af = PCB_FAMILY(inp);
1.1       jonathan  514:        IPSEC_ASSERT(af == AF_INET || af == AF_INET6,
                    515:                ("ipsec_getpolicybysock: unexpected protocol family %u", af));
                    516:
1.9       thorpej   517: #ifdef __NetBSD__
1.13      jonathan  518:        IPSEC_ASSERT(inp->inph_sp != NULL, ("null PCB policy cache"));
1.9       thorpej   519:        /* If we have a cached entry, and if it is still valid, use it. */
                    520:        ipsecstat.ips_spdcache_lookup++;
                    521:        currsp = ipsec_checkpcbcache(m, /*inpcb_hdr*/inp->inph_sp, dir);
                    522:        if (currsp) {
                    523:                *error = 0;
                    524:                return currsp;
                    525:        }
                    526:        ipsecstat.ips_spdcache_miss++;
                    527: #endif /* __NetBSD__ */
                    528:
1.1       jonathan  529:        switch (af) {
1.5       jonathan  530:        case AF_INET: {
                    531:                struct inpcb *in4p = PCB_TO_IN4PCB(inp);
1.1       jonathan  532:                /* set spidx in pcb */
1.5       jonathan  533:                *error = ipsec4_setspidx_inpcb(m, in4p);
                    534:                pcbsp = in4p->inp_sp;
1.1       jonathan  535:                break;
1.5       jonathan  536:                }
                    537:
                    538: #if defined(INET6)
                    539:        case AF_INET6: {
                    540:                struct in6pcb *in6p = PCB_TO_IN6PCB(inp);
1.1       jonathan  541:                /* set spidx in pcb */
1.5       jonathan  542:                *error = ipsec6_setspidx_in6pcb(m, in6p);
                    543:                pcbsp = in6p->in6p_sp;
1.1       jonathan  544:                break;
1.5       jonathan  545:                }
1.1       jonathan  546: #endif
                    547:        default:
                    548:                *error = EPFNOSUPPORT;
                    549:                break;
                    550:        }
                    551:        if (*error)
                    552:                return NULL;
                    553:
                    554:        IPSEC_ASSERT(pcbsp != NULL, ("ipsec_getpolicybysock: null pcbsp"));
                    555:        switch (dir) {
                    556:        case IPSEC_DIR_INBOUND:
                    557:                currsp = pcbsp->sp_in;
                    558:                break;
                    559:        case IPSEC_DIR_OUTBOUND:
                    560:                currsp = pcbsp->sp_out;
                    561:                break;
                    562:        }
                    563:        IPSEC_ASSERT(currsp != NULL, ("ipsec_getpolicybysock: null currsp"));
                    564:
                    565:        if (pcbsp->priv) {                      /* when privilieged socket */
                    566:                switch (currsp->policy) {
                    567:                case IPSEC_POLICY_BYPASS:
                    568:                case IPSEC_POLICY_IPSEC:
                    569:                        currsp->refcnt++;
                    570:                        sp = currsp;
                    571:                        break;
                    572:
                    573:                case IPSEC_POLICY_ENTRUST:
                    574:                        /* look for a policy in SPD */
                    575:                        sp = KEY_ALLOCSP(&currsp->spidx, dir);
                    576:                        if (sp == NULL)         /* no SP found */
                    577:                                sp = KEY_ALLOCSP_DEFAULT();
                    578:                        break;
                    579:
                    580:                default:
                    581:                        ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
1.26      degroote  582:                                  "Invalid policy for PCB %d\n", currsp->policy));
1.1       jonathan  583:                        *error = EINVAL;
                    584:                        return NULL;
                    585:                }
                    586:        } else {                                /* unpriv, SPD has policy */
                    587:                sp = KEY_ALLOCSP(&currsp->spidx, dir);
                    588:                if (sp == NULL) {               /* no SP found */
                    589:                        switch (currsp->policy) {
                    590:                        case IPSEC_POLICY_BYPASS:
                    591:                                ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
1.26      degroote  592:                                           "Illegal policy for non-priviliged defined %d\n",
1.1       jonathan  593:                                        currsp->policy));
                    594:                                *error = EINVAL;
                    595:                                return NULL;
                    596:
                    597:                        case IPSEC_POLICY_ENTRUST:
                    598:                                sp = KEY_ALLOCSP_DEFAULT();
                    599:                                break;
                    600:
                    601:                        case IPSEC_POLICY_IPSEC:
                    602:                                currsp->refcnt++;
                    603:                                sp = currsp;
                    604:                                break;
                    605:
                    606:                        default:
                    607:                                ipseclog((LOG_ERR, "ipsec_getpolicybysock: "
                    608:                                   "Invalid policy for PCB %d\n", currsp->policy));
                    609:                                *error = EINVAL;
                    610:                                return NULL;
                    611:                        }
                    612:                }
                    613:        }
                    614:        IPSEC_ASSERT(sp != NULL,
                    615:                ("ipsec_getpolicybysock: null SP (priv %u policy %u",
                    616:                 pcbsp->priv, currsp->policy));
                    617:        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                    618:                printf("DP ipsec_getpolicybysock (priv %u policy %u) allocates "
1.26      degroote  619:                           "SP:%p (refcnt %u)\n", pcbsp->priv, currsp->policy,
                    620:                           sp, sp->refcnt));
1.9       thorpej   621: #ifdef __NetBSD__
                    622:        ipsec_fillpcbcache(pcbsp, m, sp, dir);
                    623: #endif /* __NetBSD__ */
1.1       jonathan  624:        return sp;
                    625: }
                    626:
                    627: /*
                    628:  * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet,
                    629:  * and return a pointer to SP.
                    630:  * OUT:        positive: a pointer to the entry for security policy leaf matched.
                    631:  *     NULL:   no apropreate SP found, the following value is set to error.
                    632:  *             0       : bypass
                    633:  *             EACCES  : discard packet.
                    634:  *             ENOENT  : ipsec_acquire() in progress, maybe.
1.7       wiz       635:  *             others  : error occurred.
1.1       jonathan  636:  */
                    637: struct secpolicy *
                    638: ipsec_getpolicybyaddr(m, dir, flag, error)
                    639:        struct mbuf *m;
                    640:        u_int dir;
                    641:        int flag;
                    642:        int *error;
                    643: {
                    644:        struct secpolicyindex spidx;
                    645:        struct secpolicy *sp;
                    646:
                    647:        IPSEC_ASSERT(m != NULL, ("ipsec_getpolicybyaddr: null mbuf"));
                    648:        IPSEC_ASSERT(error != NULL, ("ipsec_getpolicybyaddr: null error"));
                    649:        IPSEC_ASSERT(dir == IPSEC_DIR_INBOUND || dir == IPSEC_DIR_OUTBOUND,
                    650:                ("ipsec4_getpolicybaddr: invalid direction %u", dir));
                    651:
                    652:        sp = NULL;
                    653:        if (key_havesp(dir)) {
                    654:                /* Make an index to look for a policy. */
                    655:                *error = ipsec_setspidx(m, &spidx,
                    656:                                        (flag & IP_FORWARDING) ? 0 : 1);
                    657:                if (*error != 0) {
                    658:                        DPRINTF(("ipsec_getpolicybyaddr: setpidx failed,"
                    659:                                " dir %u flag %u\n", dir, flag));
                    660:                        bzero(&spidx, sizeof (spidx));
                    661:                        return NULL;
                    662:                }
                    663:                spidx.dir = dir;
                    664:
                    665:                sp = KEY_ALLOCSP(&spidx, dir);
                    666:        }
                    667:        if (sp == NULL)                 /* no SP found, use system default */
                    668:                sp = KEY_ALLOCSP_DEFAULT();
                    669:        IPSEC_ASSERT(sp != NULL, ("ipsec_getpolicybyaddr: null SP"));
                    670:        return sp;
                    671: }
                    672:
                    673: struct secpolicy *
                    674: ipsec4_checkpolicy(m, dir, flag, error, inp)
                    675:        struct mbuf *m;
                    676:        u_int dir, flag;
                    677:        int *error;
                    678:        struct inpcb *inp;
                    679: {
                    680:        struct secpolicy *sp;
                    681:
                    682:        *error = 0;
1.5       jonathan  683:
                    684:
                    685:        /* XXX KAME IPv6 calls us with non-null inp but bogus inp_socket? */
                    686:        if (inp == NULL || inp->inp_socket == NULL) {
1.1       jonathan  687:                sp = ipsec_getpolicybyaddr(m, dir, flag, error);
1.5       jonathan  688:        } else
                    689:                sp = ipsec_getpolicybysock(m, dir, IN4PCB_TO_PCB(inp), error);
1.1       jonathan  690:        if (sp == NULL) {
                    691:                IPSEC_ASSERT(*error != 0,
                    692:                        ("ipsec4_checkpolicy: getpolicy failed w/o error"));
                    693:                newipsecstat.ips_out_inval++;
                    694:                return NULL;
                    695:        }
                    696:        IPSEC_ASSERT(*error == 0,
                    697:                ("ipsec4_checkpolicy: sp w/ error set to %u", *error));
                    698:        switch (sp->policy) {
                    699:        case IPSEC_POLICY_ENTRUST:
                    700:        default:
                    701:                printf("ipsec4_checkpolicy: invalid policy %u\n", sp->policy);
                    702:                /* fall thru... */
                    703:        case IPSEC_POLICY_DISCARD:
                    704:                newipsecstat.ips_out_polvio++;
                    705:                *error = -EINVAL;       /* packet is discarded by caller */
                    706:                break;
                    707:        case IPSEC_POLICY_BYPASS:
                    708:        case IPSEC_POLICY_NONE:
                    709:                KEY_FREESP(&sp);
                    710:                sp = NULL;              /* NB: force NULL result */
                    711:                break;
                    712:        case IPSEC_POLICY_IPSEC:
                    713:                if (sp->req == NULL)    /* acquire an SA */
                    714:                        *error = key_spdacquire(sp);
                    715:                break;
                    716:        }
                    717:        if (*error != 0) {
                    718:                KEY_FREESP(&sp);
                    719:                sp = NULL;
                    720:        }
1.5       jonathan  721:        DPRINTF(("ipsecpol: done, sp %p error %d, \n", sp, *error));
1.1       jonathan  722:        return sp;
                    723: }
                    724:
1.26      degroote  725: #ifdef INET6
                    726: struct secpolicy *
                    727: ipsec6_checkpolicy(m, dir, flag, error, in6p)
                    728:        struct mbuf *m;
                    729:        u_int dir, flag;
                    730:        int *error;
                    731:        struct in6pcb *in6p;
                    732: {
                    733:        struct secpolicy *sp;
                    734:
                    735:        *error = 0;
                    736:
                    737:
                    738:        /* XXX KAME IPv6 calls us with non-null inp but bogus inp_socket? */
                    739:        if (in6p == NULL || in6p->in6p_socket == NULL) {
                    740:                sp = ipsec_getpolicybyaddr(m, dir, flag, error);
                    741:        } else
                    742:                sp = ipsec_getpolicybysock(m, dir, IN6PCB_TO_PCB(in6p), error);
                    743:        if (sp == NULL) {
                    744:                IPSEC_ASSERT(*error != 0,
                    745:                        ("ipsec6_checkpolicy: getpolicy failed w/o error"));
                    746:                newipsecstat.ips_out_inval++;
                    747:                return NULL;
                    748:        }
                    749:        IPSEC_ASSERT(*error == 0,
                    750:                ("ipsec6_checkpolicy: sp w/ error set to %u", *error));
                    751:        switch (sp->policy) {
                    752:        case IPSEC_POLICY_ENTRUST:
                    753:        default:
                    754:                printf("ipsec6_checkpolicy: invalid policy %u\n", sp->policy);
                    755:                /* fall thru... */
                    756:        case IPSEC_POLICY_DISCARD:
                    757:                newipsecstat.ips_out_polvio++;
                    758:                *error = -EINVAL;   /* packet is discarded by caller */
                    759:                break;
                    760:        case IPSEC_POLICY_BYPASS:
                    761:        case IPSEC_POLICY_NONE:
                    762:                KEY_FREESP(&sp);
                    763:                sp = NULL;        /* NB: force NULL result */
                    764:                break;
                    765:        case IPSEC_POLICY_IPSEC:
                    766:                if (sp->req == NULL)    /* acquire an SA */
                    767:                        *error = key_spdacquire(sp);
                    768:                break;
                    769:        }
                    770:        if (*error != 0) {
                    771:                KEY_FREESP(&sp);
                    772:                sp = NULL;
                    773:        }
                    774:        DPRINTF(("ipsecpol: done, sp %p error %d, \n", sp, *error));
                    775:        return sp;
                    776: }
                    777: #endif /* INET6 */
                    778:
1.1       jonathan  779: static int
                    780: ipsec4_setspidx_inpcb(m, pcb)
                    781:        struct mbuf *m;
                    782:        struct inpcb *pcb;
                    783: {
                    784:        int error;
                    785:
                    786:        IPSEC_ASSERT(pcb != NULL, ("ipsec4_setspidx_inpcb: null pcb"));
                    787:        IPSEC_ASSERT(pcb->inp_sp != NULL, ("ipsec4_setspidx_inpcb: null inp_sp"));
                    788:        IPSEC_ASSERT(pcb->inp_sp->sp_out != NULL && pcb->inp_sp->sp_in != NULL,
                    789:                ("ipsec4_setspidx_inpcb: null sp_in || sp_out"));
                    790:
                    791:        error = ipsec_setspidx(m, &pcb->inp_sp->sp_in->spidx, 1);
                    792:        if (error == 0) {
                    793:                pcb->inp_sp->sp_in->spidx.dir = IPSEC_DIR_INBOUND;
                    794:                pcb->inp_sp->sp_out->spidx = pcb->inp_sp->sp_in->spidx;
                    795:                pcb->inp_sp->sp_out->spidx.dir = IPSEC_DIR_OUTBOUND;
                    796:        } else {
                    797:                bzero(&pcb->inp_sp->sp_in->spidx,
                    798:                        sizeof (pcb->inp_sp->sp_in->spidx));
                    799:                bzero(&pcb->inp_sp->sp_out->spidx,
                    800:                        sizeof (pcb->inp_sp->sp_in->spidx));
                    801:        }
                    802:        return error;
                    803: }
                    804:
                    805: #ifdef INET6
                    806: static int
                    807: ipsec6_setspidx_in6pcb(m, pcb)
                    808:        struct mbuf *m;
                    809:        struct in6pcb *pcb;
                    810: {
                    811:        struct secpolicyindex *spidx;
                    812:        int error;
                    813:
                    814:        IPSEC_ASSERT(pcb != NULL, ("ipsec6_setspidx_in6pcb: null pcb"));
                    815:        IPSEC_ASSERT(pcb->in6p_sp != NULL, ("ipsec6_setspidx_in6pcb: null inp_sp"));
                    816:        IPSEC_ASSERT(pcb->in6p_sp->sp_out != NULL && pcb->in6p_sp->sp_in != NULL,
                    817:                ("ipsec6_setspidx_in6pcb: null sp_in || sp_out"));
                    818:
                    819:        bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
                    820:        bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
                    821:
                    822:        spidx = &pcb->in6p_sp->sp_in->spidx;
                    823:        error = ipsec_setspidx(m, spidx, 1);
                    824:        if (error)
                    825:                goto bad;
                    826:        spidx->dir = IPSEC_DIR_INBOUND;
                    827:
                    828:        spidx = &pcb->in6p_sp->sp_out->spidx;
                    829:        error = ipsec_setspidx(m, spidx, 1);
                    830:        if (error)
                    831:                goto bad;
                    832:        spidx->dir = IPSEC_DIR_OUTBOUND;
                    833:
                    834:        return 0;
                    835:
                    836: bad:
                    837:        bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx));
                    838:        bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx));
                    839:        return error;
                    840: }
                    841: #endif
                    842:
                    843: /*
                    844:  * configure security policy index (src/dst/proto/sport/dport)
                    845:  * by looking at the content of mbuf.
                    846:  * the caller is responsible for error recovery (like clearing up spidx).
                    847:  */
                    848: static int
                    849: ipsec_setspidx(m, spidx, needport)
                    850:        struct mbuf *m;
                    851:        struct secpolicyindex *spidx;
                    852:        int needport;
                    853: {
                    854:        struct ip *ip = NULL;
                    855:        struct ip ipbuf;
                    856:        u_int v;
                    857:        struct mbuf *n;
                    858:        int len;
                    859:        int error;
                    860:
                    861:        IPSEC_ASSERT(m != NULL, ("ipsec_setspidx: null mbuf"));
                    862:
                    863:        /*
                    864:         * validate m->m_pkthdr.len.  we see incorrect length if we
                    865:         * mistakenly call this function with inconsistent mbuf chain
                    866:         * (like 4.4BSD tcp/udp processing).  XXX should we panic here?
                    867:         */
                    868:        len = 0;
                    869:        for (n = m; n; n = n->m_next)
                    870:                len += n->m_len;
                    871:        if (m->m_pkthdr.len != len) {
                    872:                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                    873:                        printf("ipsec_setspidx: "
1.26      degroote  874:                                   "total of m_len(%d) != pkthdr.len(%d), "
                    875:                                   "ignored.\n",
1.1       jonathan  876:                                len, m->m_pkthdr.len));
                    877:                return EINVAL;
                    878:        }
                    879:
                    880:        if (m->m_pkthdr.len < sizeof(struct ip)) {
                    881:                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                    882:                        printf("ipsec_setspidx: "
1.26      degroote  883:                                "pkthdr.len(%d) < sizeof(struct ip), ignored.\n",
                    884:                                m->m_pkthdr.len));
1.1       jonathan  885:                return EINVAL;
                    886:        }
                    887:
                    888:        if (m->m_len >= sizeof(*ip))
                    889:                ip = mtod(m, struct ip *);
                    890:        else {
1.28    ! degroote  891:                m_copydata(m, 0, sizeof(ipbuf), &ipbuf);
1.1       jonathan  892:                ip = &ipbuf;
                    893:        }
                    894: #ifdef _IP_VHL
                    895:        v = _IP_VHL_V(ip->ip_vhl);
                    896: #else
                    897:        v = ip->ip_v;
                    898: #endif
                    899:        switch (v) {
                    900:        case 4:
                    901:                error = ipsec4_setspidx_ipaddr(m, spidx);
                    902:                if (error)
                    903:                        return error;
                    904:                ipsec4_get_ulp(m, spidx, needport);
                    905:                return 0;
                    906: #ifdef INET6
                    907:        case 6:
                    908:                if (m->m_pkthdr.len < sizeof(struct ip6_hdr)) {
                    909:                        KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                    910:                                printf("ipsec_setspidx: "
1.26      degroote  911:                                        "pkthdr.len(%d) < sizeof(struct ip6_hdr), "
                    912:                                        "ignored.\n", m->m_pkthdr.len));
1.1       jonathan  913:                        return EINVAL;
                    914:                }
                    915:                error = ipsec6_setspidx_ipaddr(m, spidx);
                    916:                if (error)
                    917:                        return error;
                    918:                ipsec6_get_ulp(m, spidx, needport);
                    919:                return 0;
                    920: #endif
                    921:        default:
                    922:                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                    923:                        printf("ipsec_setspidx: "
1.26      degroote  924:                                "unknown IP version %u, ignored.\n", v));
1.1       jonathan  925:                return EINVAL;
                    926:        }
                    927: }
                    928:
                    929: static void
                    930: ipsec4_get_ulp(struct mbuf *m, struct secpolicyindex *spidx, int needport)
                    931: {
                    932:        u_int8_t nxt;
                    933:        int off;
                    934:
                    935:        /* sanity check */
                    936:        IPSEC_ASSERT(m != NULL, ("ipsec4_get_ulp: null mbuf"));
                    937:        IPSEC_ASSERT(m->m_pkthdr.len >= sizeof(struct ip),
                    938:                ("ipsec4_get_ulp: packet too short"));
                    939:
                    940:        /* NB: ip_input() flips it into host endian XXX need more checking */
1.8       thorpej   941:        if (m->m_len >= sizeof(struct ip)) {
1.1       jonathan  942:                struct ip *ip = mtod(m, struct ip *);
                    943:                if (ip->ip_off & (IP_MF | IP_OFFMASK))
                    944:                        goto done;
                    945: #ifdef _IP_VHL
                    946:                off = _IP_VHL_HL(ip->ip_vhl) << 2;
                    947: #else
                    948:                off = ip->ip_hl << 2;
                    949: #endif
                    950:                nxt = ip->ip_p;
                    951:        } else {
                    952:                struct ip ih;
                    953:
1.28    ! degroote  954:                m_copydata(m, 0, sizeof (struct ip), &ih);
1.1       jonathan  955:                if (ih.ip_off & (IP_MF | IP_OFFMASK))
                    956:                        goto done;
                    957: #ifdef _IP_VHL
                    958:                off = _IP_VHL_HL(ih.ip_vhl) << 2;
                    959: #else
                    960:                off = ih.ip_hl << 2;
                    961: #endif
                    962:                nxt = ih.ip_p;
                    963:        }
                    964:
                    965:        while (off < m->m_pkthdr.len) {
                    966:                struct ip6_ext ip6e;
                    967:                struct tcphdr th;
                    968:                struct udphdr uh;
                    969:
                    970:                switch (nxt) {
                    971:                case IPPROTO_TCP:
                    972:                        spidx->ul_proto = nxt;
                    973:                        if (!needport)
                    974:                                goto done_proto;
                    975:                        if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
                    976:                                goto done;
1.28    ! degroote  977:                        m_copydata(m, off, sizeof (th), &th);
1.1       jonathan  978:                        spidx->src.sin.sin_port = th.th_sport;
                    979:                        spidx->dst.sin.sin_port = th.th_dport;
                    980:                        return;
                    981:                case IPPROTO_UDP:
                    982:                        spidx->ul_proto = nxt;
                    983:                        if (!needport)
                    984:                                goto done_proto;
                    985:                        if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
                    986:                                goto done;
1.28    ! degroote  987:                        m_copydata(m, off, sizeof (uh), &uh);
1.1       jonathan  988:                        spidx->src.sin.sin_port = uh.uh_sport;
                    989:                        spidx->dst.sin.sin_port = uh.uh_dport;
                    990:                        return;
                    991:                case IPPROTO_AH:
                    992:                        if (m->m_pkthdr.len > off + sizeof(ip6e))
                    993:                                goto done;
                    994:                        /* XXX sigh, this works but is totally bogus */
1.28    ! degroote  995:                        m_copydata(m, off, sizeof(ip6e), &ip6e);
1.1       jonathan  996:                        off += (ip6e.ip6e_len + 2) << 2;
                    997:                        nxt = ip6e.ip6e_nxt;
                    998:                        break;
                    999:                case IPPROTO_ICMP:
                   1000:                default:
                   1001:                        /* XXX intermediate headers??? */
                   1002:                        spidx->ul_proto = nxt;
                   1003:                        goto done_proto;
                   1004:                }
                   1005:        }
                   1006: done:
                   1007:        spidx->ul_proto = IPSEC_ULPROTO_ANY;
                   1008: done_proto:
                   1009:        spidx->src.sin.sin_port = IPSEC_PORT_ANY;
                   1010:        spidx->dst.sin.sin_port = IPSEC_PORT_ANY;
                   1011: }
                   1012:
                   1013: /* assumes that m is sane */
                   1014: static int
                   1015: ipsec4_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx)
                   1016: {
                   1017:        static const struct sockaddr_in template = {
                   1018:                sizeof (struct sockaddr_in),
                   1019:                AF_INET,
                   1020:                0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 }
                   1021:        };
                   1022:
                   1023:        spidx->src.sin = template;
                   1024:        spidx->dst.sin = template;
                   1025:
                   1026:        if (m->m_len < sizeof (struct ip)) {
                   1027:                m_copydata(m, offsetof(struct ip, ip_src),
                   1028:                           sizeof (struct  in_addr),
1.28    ! degroote 1029:                           &spidx->src.sin.sin_addr);
1.1       jonathan 1030:                m_copydata(m, offsetof(struct ip, ip_dst),
                   1031:                           sizeof (struct  in_addr),
1.28    ! degroote 1032:                           &spidx->dst.sin.sin_addr);
1.1       jonathan 1033:        } else {
                   1034:                struct ip *ip = mtod(m, struct ip *);
                   1035:                spidx->src.sin.sin_addr = ip->ip_src;
                   1036:                spidx->dst.sin.sin_addr = ip->ip_dst;
                   1037:        }
                   1038:
                   1039:        spidx->prefs = sizeof(struct in_addr) << 3;
                   1040:        spidx->prefd = sizeof(struct in_addr) << 3;
                   1041:
                   1042:        return 0;
                   1043: }
                   1044:
                   1045: #ifdef INET6
                   1046: static void
                   1047: ipsec6_get_ulp(m, spidx, needport)
                   1048:        struct mbuf *m;
                   1049:        struct secpolicyindex *spidx;
                   1050:        int needport;
                   1051: {
                   1052:        int off, nxt;
                   1053:        struct tcphdr th;
                   1054:        struct udphdr uh;
                   1055:
                   1056:        /* sanity check */
                   1057:        if (m == NULL)
1.16      christos 1058:                panic("ipsec6_get_ulp: NULL pointer was passed");
1.1       jonathan 1059:
                   1060:        KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                   1061:                printf("ipsec6_get_ulp:\n"); kdebug_mbuf(m));
                   1062:
                   1063:        /* set default */
                   1064:        spidx->ul_proto = IPSEC_ULPROTO_ANY;
                   1065:        ((struct sockaddr_in6 *)&spidx->src)->sin6_port = IPSEC_PORT_ANY;
                   1066:        ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = IPSEC_PORT_ANY;
                   1067:
                   1068:        nxt = -1;
                   1069:        off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
                   1070:        if (off < 0 || m->m_pkthdr.len < off)
                   1071:                return;
                   1072:
                   1073:        switch (nxt) {
                   1074:        case IPPROTO_TCP:
                   1075:                spidx->ul_proto = nxt;
                   1076:                if (!needport)
                   1077:                        break;
                   1078:                if (off + sizeof(struct tcphdr) > m->m_pkthdr.len)
                   1079:                        break;
1.28    ! degroote 1080:                m_copydata(m, off, sizeof(th), &th);
1.1       jonathan 1081:                ((struct sockaddr_in6 *)&spidx->src)->sin6_port = th.th_sport;
                   1082:                ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = th.th_dport;
                   1083:                break;
                   1084:        case IPPROTO_UDP:
                   1085:                spidx->ul_proto = nxt;
                   1086:                if (!needport)
                   1087:                        break;
                   1088:                if (off + sizeof(struct udphdr) > m->m_pkthdr.len)
                   1089:                        break;
1.28    ! degroote 1090:                m_copydata(m, off, sizeof(uh), &uh);
1.1       jonathan 1091:                ((struct sockaddr_in6 *)&spidx->src)->sin6_port = uh.uh_sport;
                   1092:                ((struct sockaddr_in6 *)&spidx->dst)->sin6_port = uh.uh_dport;
                   1093:                break;
                   1094:        case IPPROTO_ICMPV6:
                   1095:        default:
                   1096:                /* XXX intermediate headers??? */
                   1097:                spidx->ul_proto = nxt;
                   1098:                break;
                   1099:        }
                   1100: }
                   1101:
                   1102: /* assumes that m is sane */
                   1103: static int
                   1104: ipsec6_setspidx_ipaddr(m, spidx)
                   1105:        struct mbuf *m;
                   1106:        struct secpolicyindex *spidx;
                   1107: {
                   1108:        struct ip6_hdr *ip6 = NULL;
                   1109:        struct ip6_hdr ip6buf;
                   1110:        struct sockaddr_in6 *sin6;
                   1111:
                   1112:        if (m->m_len >= sizeof(*ip6))
                   1113:                ip6 = mtod(m, struct ip6_hdr *);
                   1114:        else {
1.28    ! degroote 1115:                m_copydata(m, 0, sizeof(ip6buf), &ip6buf);
1.1       jonathan 1116:                ip6 = &ip6buf;
                   1117:        }
                   1118:
                   1119:        sin6 = (struct sockaddr_in6 *)&spidx->src;
                   1120:        bzero(sin6, sizeof(*sin6));
                   1121:        sin6->sin6_family = AF_INET6;
                   1122:        sin6->sin6_len = sizeof(struct sockaddr_in6);
                   1123:        bcopy(&ip6->ip6_src, &sin6->sin6_addr, sizeof(ip6->ip6_src));
                   1124:        if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) {
                   1125:                sin6->sin6_addr.s6_addr16[1] = 0;
                   1126:                sin6->sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]);
                   1127:        }
                   1128:        spidx->prefs = sizeof(struct in6_addr) << 3;
                   1129:
                   1130:        sin6 = (struct sockaddr_in6 *)&spidx->dst;
                   1131:        bzero(sin6, sizeof(*sin6));
                   1132:        sin6->sin6_family = AF_INET6;
                   1133:        sin6->sin6_len = sizeof(struct sockaddr_in6);
                   1134:        bcopy(&ip6->ip6_dst, &sin6->sin6_addr, sizeof(ip6->ip6_dst));
                   1135:        if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
                   1136:                sin6->sin6_addr.s6_addr16[1] = 0;
                   1137:                sin6->sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]);
                   1138:        }
                   1139:        spidx->prefd = sizeof(struct in6_addr) << 3;
                   1140:
                   1141:        return 0;
                   1142: }
                   1143: #endif
                   1144:
                   1145: static void
                   1146: ipsec_delpcbpolicy(p)
                   1147:        struct inpcbpolicy *p;
                   1148: {
                   1149:        free(p, M_SECA);
                   1150: }
                   1151:
                   1152: /* initialize policy in PCB */
                   1153: int
                   1154: ipsec_init_policy(so, pcb_sp)
                   1155:        struct socket *so;
                   1156:        struct inpcbpolicy **pcb_sp;
                   1157: {
                   1158:        struct inpcbpolicy *new;
                   1159:
                   1160:        /* sanity check. */
                   1161:        if (so == NULL || pcb_sp == NULL)
1.16      christos 1162:                panic("ipsec_init_policy: NULL pointer was passed");
1.1       jonathan 1163:
                   1164:        new = (struct inpcbpolicy *) malloc(sizeof(struct inpcbpolicy),
1.26      degroote 1165:                                                M_SECA, M_NOWAIT|M_ZERO);
1.1       jonathan 1166:        if (new == NULL) {
                   1167:                ipseclog((LOG_DEBUG, "ipsec_init_policy: No more memory.\n"));
                   1168:                return ENOBUFS;
                   1169:        }
                   1170:
                   1171:        if (IPSEC_PRIVILEGED_SO(so))
                   1172:                new->priv = 1;
                   1173:        else
                   1174:                new->priv = 0;
                   1175:
                   1176:        if ((new->sp_in = KEY_NEWSP()) == NULL) {
                   1177:                ipsec_delpcbpolicy(new);
                   1178:                return ENOBUFS;
                   1179:        }
                   1180:        new->sp_in->state = IPSEC_SPSTATE_ALIVE;
                   1181:        new->sp_in->policy = IPSEC_POLICY_ENTRUST;
                   1182:
                   1183:        if ((new->sp_out = KEY_NEWSP()) == NULL) {
                   1184:                KEY_FREESP(&new->sp_in);
                   1185:                ipsec_delpcbpolicy(new);
                   1186:                return ENOBUFS;
                   1187:        }
                   1188:        new->sp_out->state = IPSEC_SPSTATE_ALIVE;
                   1189:        new->sp_out->policy = IPSEC_POLICY_ENTRUST;
                   1190:
                   1191:        *pcb_sp = new;
                   1192:
                   1193:        return 0;
                   1194: }
                   1195:
                   1196: /* copy old ipsec policy into new */
                   1197: int
                   1198: ipsec_copy_policy(old, new)
                   1199:        struct inpcbpolicy *old, *new;
                   1200: {
                   1201:        struct secpolicy *sp;
                   1202:
                   1203:        sp = ipsec_deepcopy_policy(old->sp_in);
                   1204:        if (sp) {
                   1205:                KEY_FREESP(&new->sp_in);
                   1206:                new->sp_in = sp;
                   1207:        } else
                   1208:                return ENOBUFS;
                   1209:
                   1210:        sp = ipsec_deepcopy_policy(old->sp_out);
                   1211:        if (sp) {
                   1212:                KEY_FREESP(&new->sp_out);
                   1213:                new->sp_out = sp;
                   1214:        } else
                   1215:                return ENOBUFS;
                   1216:
                   1217:        new->priv = old->priv;
                   1218:
                   1219:        return 0;
                   1220: }
                   1221:
                   1222: /* deep-copy a policy in PCB */
                   1223: static struct secpolicy *
                   1224: ipsec_deepcopy_policy(src)
                   1225:        struct secpolicy *src;
                   1226: {
                   1227:        struct ipsecrequest *newchain = NULL;
                   1228:        struct ipsecrequest *p;
                   1229:        struct ipsecrequest **q;
                   1230:        struct ipsecrequest *r;
                   1231:        struct secpolicy *dst;
                   1232:
                   1233:        if (src == NULL)
                   1234:                return NULL;
                   1235:        dst = KEY_NEWSP();
                   1236:        if (dst == NULL)
                   1237:                return NULL;
                   1238:
                   1239:        /*
                   1240:         * deep-copy IPsec request chain.  This is required since struct
                   1241:         * ipsecrequest is not reference counted.
                   1242:         */
                   1243:        q = &newchain;
                   1244:        for (p = src->req; p; p = p->next) {
                   1245:                *q = (struct ipsecrequest *)malloc(sizeof(struct ipsecrequest),
                   1246:                        M_SECA, M_NOWAIT);
                   1247:                if (*q == NULL)
                   1248:                        goto fail;
                   1249:                bzero(*q, sizeof(**q));
                   1250:                (*q)->next = NULL;
                   1251:
                   1252:                (*q)->saidx.proto = p->saidx.proto;
                   1253:                (*q)->saidx.mode = p->saidx.mode;
                   1254:                (*q)->level = p->level;
                   1255:                (*q)->saidx.reqid = p->saidx.reqid;
                   1256:
                   1257:                bcopy(&p->saidx.src, &(*q)->saidx.src, sizeof((*q)->saidx.src));
                   1258:                bcopy(&p->saidx.dst, &(*q)->saidx.dst, sizeof((*q)->saidx.dst));
                   1259:
                   1260:                (*q)->sav = NULL;
                   1261:                (*q)->sp = dst;
                   1262:
                   1263:                q = &((*q)->next);
                   1264:        }
                   1265:
                   1266:        dst->req = newchain;
                   1267:        dst->state = src->state;
                   1268:        dst->policy = src->policy;
                   1269:        /* do not touch the refcnt fields */
                   1270:
                   1271:        return dst;
                   1272:
                   1273: fail:
                   1274:        for (p = newchain; p; p = r) {
                   1275:                r = p->next;
                   1276:                free(p, M_SECA);
                   1277:                p = NULL;
                   1278:        }
                   1279:        return NULL;
                   1280: }
                   1281:
                   1282: /* set policy and ipsec request if present. */
                   1283: static int
1.24      christos 1284: ipsec_set_policy(
1.26      degroote 1285:        struct secpolicy **pcb_sp,
                   1286:        int optname,
1.27      christos 1287:        void *request,
1.26      degroote 1288:        size_t len,
                   1289:        int priv
1.24      christos 1290: )
1.1       jonathan 1291: {
                   1292:        struct sadb_x_policy *xpl;
                   1293:        struct secpolicy *newsp = NULL;
                   1294:        int error;
                   1295:
                   1296:        /* sanity check. */
                   1297:        if (pcb_sp == NULL || *pcb_sp == NULL || request == NULL)
                   1298:                return EINVAL;
                   1299:        if (len < sizeof(*xpl))
                   1300:                return EINVAL;
                   1301:        xpl = (struct sadb_x_policy *)request;
                   1302:
                   1303:        KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                   1304:                printf("ipsec_set_policy: passed policy\n");
                   1305:                kdebug_sadb_x_policy((struct sadb_ext *)xpl));
                   1306:
                   1307:        /* check policy type */
                   1308:        /* ipsec_set_policy() accepts IPSEC, ENTRUST and BYPASS. */
                   1309:        if (xpl->sadb_x_policy_type == IPSEC_POLICY_DISCARD
                   1310:         || xpl->sadb_x_policy_type == IPSEC_POLICY_NONE)
                   1311:                return EINVAL;
                   1312:
                   1313:        /* check privileged socket */
                   1314:        if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS)
                   1315:                return EACCES;
                   1316:
                   1317:        /* allocation new SP entry */
                   1318:        if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
                   1319:                return error;
                   1320:
                   1321:        newsp->state = IPSEC_SPSTATE_ALIVE;
                   1322:
                   1323:        /* clear old SP and set new SP */
                   1324:        KEY_FREESP(pcb_sp);
                   1325:        *pcb_sp = newsp;
                   1326:        KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                   1327:                printf("ipsec_set_policy: new policy\n");
                   1328:                kdebug_secpolicy(newsp));
                   1329:
                   1330:        return 0;
                   1331: }
                   1332:
                   1333: static int
                   1334: ipsec_get_policy(pcb_sp, mp)
                   1335:        struct secpolicy *pcb_sp;
                   1336:        struct mbuf **mp;
                   1337: {
                   1338:
                   1339:        /* sanity check. */
                   1340:        if (pcb_sp == NULL || mp == NULL)
                   1341:                return EINVAL;
                   1342:
                   1343:        *mp = key_sp2msg(pcb_sp);
                   1344:        if (!*mp) {
                   1345:                ipseclog((LOG_DEBUG, "ipsec_get_policy: No more memory.\n"));
                   1346:                return ENOBUFS;
                   1347:        }
                   1348:
                   1349:        (*mp)->m_type = MT_DATA;
                   1350:        KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
                   1351:                printf("ipsec_get_policy:\n");
                   1352:                kdebug_mbuf(*mp));
                   1353:
                   1354:        return 0;
                   1355: }
                   1356:
                   1357: int
                   1358: ipsec4_set_policy(inp, optname, request, len, priv)
                   1359:        struct inpcb *inp;
                   1360:        int optname;
1.27      christos 1361:        void *request;
1.1       jonathan 1362:        size_t len;
                   1363:        int priv;
                   1364: {
                   1365:        struct sadb_x_policy *xpl;
                   1366:        struct secpolicy **pcb_sp;
                   1367:
                   1368:        /* sanity check. */
                   1369:        if (inp == NULL || request == NULL)
                   1370:                return EINVAL;
                   1371:        if (len < sizeof(*xpl))
                   1372:                return EINVAL;
                   1373:        xpl = (struct sadb_x_policy *)request;
                   1374:
                   1375:        IPSEC_ASSERT(inp->inp_sp != NULL,
1.26      degroote 1376:                         ("ipsec4_set_policy(): null inp->in_sp"));
1.1       jonathan 1377:
                   1378:        /* select direction */
                   1379:        switch (xpl->sadb_x_policy_dir) {
                   1380:        case IPSEC_DIR_INBOUND:
                   1381:                pcb_sp = &inp->inp_sp->sp_in;
                   1382:                break;
                   1383:        case IPSEC_DIR_OUTBOUND:
                   1384:                pcb_sp = &inp->inp_sp->sp_out;
                   1385:                break;
                   1386:        default:
                   1387:                ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
                   1388:                        xpl->sadb_x_policy_dir));
                   1389:                return EINVAL;
                   1390:        }
                   1391:
                   1392:        return ipsec_set_policy(pcb_sp, optname, request, len, priv);
                   1393: }
                   1394:
                   1395: int
                   1396: ipsec4_get_policy(inp, request, len, mp)
                   1397:        struct inpcb *inp;
1.27      christos 1398:        void *request;
1.1       jonathan 1399:        size_t len;
                   1400:        struct mbuf **mp;
                   1401: {
                   1402:        struct sadb_x_policy *xpl;
                   1403:        struct secpolicy *pcb_sp;
                   1404:
                   1405:        /* sanity check. */
                   1406:        if (inp == NULL || request == NULL || mp == NULL)
                   1407:                return EINVAL;
                   1408:        IPSEC_ASSERT(inp->inp_sp != NULL, ("ipsec4_get_policy: null inp_sp"));
                   1409:        if (len < sizeof(*xpl))
                   1410:                return EINVAL;
                   1411:        xpl = (struct sadb_x_policy *)request;
                   1412:
                   1413:        /* select direction */
                   1414:        switch (xpl->sadb_x_policy_dir) {
                   1415:        case IPSEC_DIR_INBOUND:
                   1416:                pcb_sp = inp->inp_sp->sp_in;
                   1417:                break;
                   1418:        case IPSEC_DIR_OUTBOUND:
                   1419:                pcb_sp = inp->inp_sp->sp_out;
                   1420:                break;
                   1421:        default:
                   1422:                ipseclog((LOG_ERR, "ipsec4_set_policy: invalid direction=%u\n",
                   1423:                        xpl->sadb_x_policy_dir));
                   1424:                return EINVAL;
                   1425:        }
                   1426:
                   1427:        return ipsec_get_policy(pcb_sp, mp);
                   1428: }
                   1429:
                   1430: /* delete policy in PCB */
                   1431: int
                   1432: ipsec4_delete_pcbpolicy(inp)
                   1433:        struct inpcb *inp;
                   1434: {
                   1435:        IPSEC_ASSERT(inp != NULL, ("ipsec4_delete_pcbpolicy: null inp"));
                   1436:
                   1437:        if (inp->inp_sp == NULL)
                   1438:                return 0;
                   1439:
                   1440:        if (inp->inp_sp->sp_in != NULL)
                   1441:                KEY_FREESP(&inp->inp_sp->sp_in);
                   1442:
                   1443:        if (inp->inp_sp->sp_out != NULL)
                   1444:                KEY_FREESP(&inp->inp_sp->sp_out);
                   1445:
                   1446:        ipsec_delpcbpolicy(inp->inp_sp);
                   1447:        inp->inp_sp = NULL;
                   1448:
                   1449:        return 0;
                   1450: }
                   1451:
                   1452: #ifdef INET6
                   1453: int
                   1454: ipsec6_set_policy(in6p, optname, request, len, priv)
                   1455:        struct in6pcb *in6p;
                   1456:        int optname;
1.27      christos 1457:        void *request;
1.1       jonathan 1458:        size_t len;
                   1459:        int priv;
                   1460: {
                   1461:        struct sadb_x_policy *xpl;
                   1462:        struct secpolicy **pcb_sp;
                   1463:
                   1464:        /* sanity check. */
                   1465:        if (in6p == NULL || request == NULL)
                   1466:                return EINVAL;
                   1467:        if (len < sizeof(*xpl))
                   1468:                return EINVAL;
                   1469:        xpl = (struct sadb_x_policy *)request;
                   1470:
                   1471:        /* select direction */
                   1472:        switch (xpl->sadb_x_policy_dir) {
                   1473:        case IPSEC_DIR_INBOUND:
                   1474:                pcb_sp = &in6p->in6p_sp->sp_in;
                   1475:                break;
                   1476:        case IPSEC_DIR_OUTBOUND:
                   1477:                pcb_sp = &in6p->in6p_sp->sp_out;
                   1478:                break;
                   1479:        default:
                   1480:                ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
                   1481:                        xpl->sadb_x_policy_dir));
                   1482:                return EINVAL;
                   1483:        }
                   1484:
                   1485:        return ipsec_set_policy(pcb_sp, optname, request, len, priv);
                   1486: }
                   1487:
                   1488: int
                   1489: ipsec6_get_policy(in6p, request, len, mp)
                   1490:        struct in6pcb *in6p;
1.27      christos 1491:        void *request;
1.1       jonathan 1492:        size_t len;
                   1493:        struct mbuf **mp;
                   1494: {
                   1495:        struct sadb_x_policy *xpl;
                   1496:        struct secpolicy *pcb_sp;
                   1497:
                   1498:        /* sanity check. */
                   1499:        if (in6p == NULL || request == NULL || mp == NULL)
                   1500:                return EINVAL;
                   1501:        IPSEC_ASSERT(in6p->in6p_sp != NULL, ("ipsec6_get_policy: null in6p_sp"));
                   1502:        if (len < sizeof(*xpl))
                   1503:                return EINVAL;
                   1504:        xpl = (struct sadb_x_policy *)request;
                   1505:
                   1506:        /* select direction */
                   1507:        switch (xpl->sadb_x_policy_dir) {
                   1508:        case IPSEC_DIR_INBOUND:
                   1509:                pcb_sp = in6p->in6p_sp->sp_in;
                   1510:                break;
                   1511:        case IPSEC_DIR_OUTBOUND:
                   1512:                pcb_sp = in6p->in6p_sp->sp_out;
                   1513:                break;
                   1514:        default:
                   1515:                ipseclog((LOG_ERR, "ipsec6_set_policy: invalid direction=%u\n",
                   1516:                        xpl->sadb_x_policy_dir));
                   1517:                return EINVAL;
                   1518:        }
                   1519:
                   1520:        return ipsec_get_policy(pcb_sp, mp);
                   1521: }
                   1522:
                   1523: int
                   1524: ipsec6_delete_pcbpolicy(in6p)
                   1525:        struct in6pcb *in6p;
                   1526: {
                   1527:        IPSEC_ASSERT(in6p != NULL, ("ipsec6_delete_pcbpolicy: null in6p"));
                   1528:
                   1529:        if (in6p->in6p_sp == NULL)
                   1530:                return 0;
                   1531:
                   1532:        if (in6p->in6p_sp->sp_in != NULL)
                   1533:                KEY_FREESP(&in6p->in6p_sp->sp_in);
                   1534:
                   1535:        if (in6p->in6p_sp->sp_out != NULL)
                   1536:                KEY_FREESP(&in6p->in6p_sp->sp_out);
                   1537:
                   1538:        ipsec_delpcbpolicy(in6p->in6p_sp);
                   1539:        in6p->in6p_sp = NULL;
                   1540:
                   1541:        return 0;
                   1542: }
                   1543: #endif
                   1544:
                   1545: /*
                   1546:  * return current level.
                   1547:  * Either IPSEC_LEVEL_USE or IPSEC_LEVEL_REQUIRE are always returned.
                   1548:  */
                   1549: u_int
                   1550: ipsec_get_reqlevel(isr)
                   1551:        struct ipsecrequest *isr;
                   1552: {
                   1553:        u_int level = 0;
                   1554:        u_int esp_trans_deflev, esp_net_deflev;
                   1555:        u_int ah_trans_deflev, ah_net_deflev;
                   1556:
                   1557:        IPSEC_ASSERT(isr != NULL && isr->sp != NULL,
                   1558:                ("ipsec_get_reqlevel: null argument"));
                   1559:        IPSEC_ASSERT(isr->sp->spidx.src.sa.sa_family == isr->sp->spidx.dst.sa.sa_family,
                   1560:                ("ipsec_get_reqlevel: af family mismatch, src %u, dst %u",
                   1561:                 isr->sp->spidx.src.sa.sa_family,
                   1562:                 isr->sp->spidx.dst.sa.sa_family));
                   1563:
                   1564: /* XXX note that we have ipseclog() expanded here - code sync issue */
                   1565: #define IPSEC_CHECK_DEFAULT(lev) \
1.26      degroote 1566:        (((lev) != IPSEC_LEVEL_USE && (lev) != IPSEC_LEVEL_REQUIRE                \
                   1567:                        && (lev) != IPSEC_LEVEL_UNIQUE)                           \
                   1568:                ? (ipsec_debug                                                    \
1.1       jonathan 1569:                        ? log(LOG_INFO, "fixed system default level " #lev ":%d->%d\n",\
1.26      degroote 1570:                                (lev), IPSEC_LEVEL_REQUIRE)                       \
                   1571:                        : 0),                                                     \
                   1572:                        (lev) = IPSEC_LEVEL_REQUIRE,                              \
                   1573:                        (lev)                                                     \
1.1       jonathan 1574:                : (lev))
                   1575:
                   1576:        /* set default level */
                   1577:        switch (((struct sockaddr *)&isr->sp->spidx.src)->sa_family) {
                   1578: #ifdef INET
                   1579:        case AF_INET:
                   1580:                esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_trans_deflev);
                   1581:                esp_net_deflev = IPSEC_CHECK_DEFAULT(ip4_esp_net_deflev);
                   1582:                ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_trans_deflev);
                   1583:                ah_net_deflev = IPSEC_CHECK_DEFAULT(ip4_ah_net_deflev);
                   1584:                break;
                   1585: #endif
                   1586: #ifdef INET6
                   1587:        case AF_INET6:
                   1588:                esp_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_trans_deflev);
                   1589:                esp_net_deflev = IPSEC_CHECK_DEFAULT(ip6_esp_net_deflev);
                   1590:                ah_trans_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_trans_deflev);
                   1591:                ah_net_deflev = IPSEC_CHECK_DEFAULT(ip6_ah_net_deflev);
                   1592:                break;
                   1593: #endif /* INET6 */
                   1594:        default:
                   1595:                panic("key_get_reqlevel: unknown af %u",
1.26      degroote 1596:                        isr->sp->spidx.src.sa.sa_family);
1.1       jonathan 1597:        }
                   1598:
                   1599: #undef IPSEC_CHECK_DEFAULT
                   1600:
                   1601:        /* set level */
                   1602:        switch (isr->level) {
                   1603:        case IPSEC_LEVEL_DEFAULT:
                   1604:                switch (isr->saidx.proto) {
                   1605:                case IPPROTO_ESP:
                   1606:                        if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
                   1607:                                level = esp_net_deflev;
                   1608:                        else
                   1609:                                level = esp_trans_deflev;
                   1610:                        break;
                   1611:                case IPPROTO_AH:
                   1612:                        if (isr->saidx.mode == IPSEC_MODE_TUNNEL)
                   1613:                                level = ah_net_deflev;
                   1614:                        else
                   1615:                                level = ah_trans_deflev;
1.14      jonathan 1616:                        break;
1.1       jonathan 1617:                case IPPROTO_IPCOMP:
                   1618:                        /*
                   1619:                         * we don't really care, as IPcomp document says that
                   1620:                         * we shouldn't compress small packets
                   1621:                         */
                   1622:                        level = IPSEC_LEVEL_USE;
                   1623:                        break;
                   1624:                default:
1.16      christos 1625:                        panic("ipsec_get_reqlevel: Illegal protocol defined %u",
1.26      degroote 1626:                                isr->saidx.proto);
1.1       jonathan 1627:                }
                   1628:                break;
                   1629:
                   1630:        case IPSEC_LEVEL_USE:
                   1631:        case IPSEC_LEVEL_REQUIRE:
                   1632:                level = isr->level;
                   1633:                break;
                   1634:        case IPSEC_LEVEL_UNIQUE:
                   1635:                level = IPSEC_LEVEL_REQUIRE;
                   1636:                break;
                   1637:
                   1638:        default:
1.16      christos 1639:                panic("ipsec_get_reqlevel: Illegal IPsec level %u",
1.1       jonathan 1640:                        isr->level);
                   1641:        }
                   1642:
                   1643:        return level;
                   1644: }
                   1645:
                   1646: /*
                   1647:  * Check security policy requirements against the actual
                   1648:  * packet contents.  Return one if the packet should be
                   1649:  * reject as "invalid"; otherwiser return zero to have the
                   1650:  * packet treated as "valid".
                   1651:  *
                   1652:  * OUT:
                   1653:  *     0: valid
                   1654:  *     1: invalid
                   1655:  */
                   1656: int
                   1657: ipsec_in_reject(struct secpolicy *sp, struct mbuf *m)
                   1658: {
                   1659:        struct ipsecrequest *isr;
                   1660:        int need_auth;
                   1661:
                   1662:        KEYDEBUG(KEYDEBUG_IPSEC_DATA,
                   1663:                printf("ipsec_in_reject: using SP\n");
                   1664:                kdebug_secpolicy(sp));
                   1665:
                   1666:        /* check policy */
                   1667:        switch (sp->policy) {
                   1668:        case IPSEC_POLICY_DISCARD:
                   1669:                return 1;
                   1670:        case IPSEC_POLICY_BYPASS:
                   1671:        case IPSEC_POLICY_NONE:
                   1672:                return 0;
                   1673:        }
                   1674:
                   1675:        IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
                   1676:                ("ipsec_in_reject: invalid policy %u", sp->policy));
                   1677:
                   1678:        /* XXX should compare policy against ipsec header history */
                   1679:
                   1680:        need_auth = 0;
                   1681:        for (isr = sp->req; isr != NULL; isr = isr->next) {
                   1682:                if (ipsec_get_reqlevel(isr) != IPSEC_LEVEL_REQUIRE)
                   1683:                        continue;
                   1684:                switch (isr->saidx.proto) {
                   1685:                case IPPROTO_ESP:
                   1686:                        if ((m->m_flags & M_DECRYPTED) == 0) {
                   1687:                                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1.26      degroote 1688:                                        printf("ipsec_in_reject: ESP m_flags:%x\n",
                   1689:                                                m->m_flags));
1.1       jonathan 1690:                                return 1;
                   1691:                        }
                   1692:
                   1693:                        if (!need_auth &&
1.26      degroote 1694:                                isr->sav != NULL &&
                   1695:                                isr->sav->tdb_authalgxform != NULL &&
                   1696:                                (m->m_flags & M_AUTHIPDGM) == 0) {
1.1       jonathan 1697:                                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1.26      degroote 1698:                                        printf("ipsec_in_reject: ESP/AH m_flags:%x\n",
                   1699:                                                m->m_flags));
1.1       jonathan 1700:                                return 1;
                   1701:                        }
                   1702:                        break;
                   1703:                case IPPROTO_AH:
                   1704:                        need_auth = 1;
                   1705:                        if ((m->m_flags & M_AUTHIPHDR) == 0) {
                   1706:                                KEYDEBUG(KEYDEBUG_IPSEC_DUMP,
1.26      degroote 1707:                                        printf("ipsec_in_reject: AH m_flags:%x\n",
                   1708:                                                m->m_flags));
1.1       jonathan 1709:                                return 1;
                   1710:                        }
                   1711:                        break;
                   1712:                case IPPROTO_IPCOMP:
                   1713:                        /*
                   1714:                         * we don't really care, as IPcomp document
                   1715:                         * says that we shouldn't compress small
                   1716:                         * packets, IPComp policy should always be
                   1717:                         * treated as being in "use" level.
                   1718:                         */
                   1719:                        break;
                   1720:                }
                   1721:        }
                   1722:        return 0;               /* valid */
                   1723: }
                   1724:
                   1725: /*
                   1726:  * Check AH/ESP integrity.
                   1727:  * This function is called from tcp_input(), udp_input(),
                   1728:  * and {ah,esp}4_input for tunnel mode
                   1729:  */
                   1730: int
                   1731: ipsec4_in_reject(m, inp)
                   1732:        struct mbuf *m;
                   1733:        struct inpcb *inp;
                   1734: {
                   1735:        struct secpolicy *sp;
                   1736:        int error;
                   1737:        int result;
                   1738:
                   1739:        IPSEC_ASSERT(m != NULL, ("ipsec4_in_reject_so: null mbuf"));
                   1740:
                   1741:        /* get SP for this packet.
                   1742:         * When we are called from ip_forward(), we call
                   1743:         * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
                   1744:         */
                   1745:        if (inp == NULL)
                   1746:                sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
                   1747:        else
1.5       jonathan 1748:                sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND,
                   1749:                                           IN4PCB_TO_PCB(inp), &error);
1.1       jonathan 1750:
                   1751:        if (sp != NULL) {
                   1752:                result = ipsec_in_reject(sp, m);
                   1753:                if (result)
                   1754:                        newipsecstat.ips_in_polvio++;
                   1755:                KEY_FREESP(&sp);
                   1756:        } else {
                   1757:                result = 0;     /* XXX should be panic ?
                   1758:                                 * -> No, there may be error. */
                   1759:        }
                   1760:        return result;
                   1761: }
                   1762:
                   1763:
                   1764: #ifdef INET6
                   1765: /*
                   1766:  * Check AH/ESP integrity.
                   1767:  * This function is called from tcp6_input(), udp6_input(),
                   1768:  * and {ah,esp}6_input for tunnel mode
                   1769:  */
                   1770: int
1.5       jonathan 1771: ipsec6_in_reject(m, in6p)
1.1       jonathan 1772:        struct mbuf *m;
1.5       jonathan 1773:        struct in6pcb *in6p;
1.1       jonathan 1774: {
                   1775:        struct secpolicy *sp = NULL;
                   1776:        int error;
                   1777:        int result;
                   1778:
                   1779:        /* sanity check */
                   1780:        if (m == NULL)
                   1781:                return 0;       /* XXX should be panic ? */
                   1782:
                   1783:        /* get SP for this packet.
                   1784:         * When we are called from ip_forward(), we call
                   1785:         * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
                   1786:         */
1.5       jonathan 1787:        if (in6p == NULL)
1.1       jonathan 1788:                sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, IP_FORWARDING, &error);
                   1789:        else
1.5       jonathan 1790:                sp = ipsec_getpolicybysock(m, IPSEC_DIR_INBOUND,
                   1791:                        IN6PCB_TO_PCB(in6p),
                   1792:                        &error);
1.1       jonathan 1793:
                   1794:        if (sp != NULL) {
                   1795:                result = ipsec_in_reject(sp, m);
                   1796:                if (result)
                   1797:                        newipsecstat.ips_in_polvio++;
                   1798:                KEY_FREESP(&sp);
                   1799:        } else {
                   1800:                result = 0;
                   1801:        }
                   1802:        return result;
                   1803: }
                   1804: #endif
                   1805:
                   1806: /*
                   1807:  * compute the byte size to be occupied by IPsec header.
                   1808:  * in case it is tunneled, it includes the size of outer IP header.
                   1809:  * NOTE: SP passed is free in this function.
                   1810:  */
                   1811: static size_t
                   1812: ipsec_hdrsiz(struct secpolicy *sp)
                   1813: {
                   1814:        struct ipsecrequest *isr;
                   1815:        size_t siz;
                   1816:
                   1817:        KEYDEBUG(KEYDEBUG_IPSEC_DATA,
                   1818:                printf("ipsec_hdrsiz: using SP\n");
                   1819:                kdebug_secpolicy(sp));
                   1820:
                   1821:        switch (sp->policy) {
                   1822:        case IPSEC_POLICY_DISCARD:
                   1823:        case IPSEC_POLICY_BYPASS:
                   1824:        case IPSEC_POLICY_NONE:
                   1825:                return 0;
                   1826:        }
                   1827:
                   1828:        IPSEC_ASSERT(sp->policy == IPSEC_POLICY_IPSEC,
                   1829:                ("ipsec_hdrsiz: invalid policy %u", sp->policy));
                   1830:
                   1831:        siz = 0;
                   1832:        for (isr = sp->req; isr != NULL; isr = isr->next) {
                   1833:                size_t clen = 0;
                   1834:
                   1835:                switch (isr->saidx.proto) {
                   1836:                case IPPROTO_ESP:
                   1837:                        clen = esp_hdrsiz(isr->sav);
                   1838:                        break;
                   1839:                case IPPROTO_AH:
                   1840:                        clen = ah_hdrsiz(isr->sav);
                   1841:                        break;
                   1842:                case IPPROTO_IPCOMP:
                   1843:                        clen = sizeof(struct ipcomp);
                   1844:                        break;
                   1845:                }
                   1846:
                   1847:                if (isr->saidx.mode == IPSEC_MODE_TUNNEL) {
                   1848:                        switch (isr->saidx.dst.sa.sa_family) {
                   1849:                        case AF_INET:
                   1850:                                clen += sizeof(struct ip);
                   1851:                                break;
                   1852: #ifdef INET6
                   1853:                        case AF_INET6:
                   1854:                                clen += sizeof(struct ip6_hdr);
                   1855:                                break;
                   1856: #endif
                   1857:                        default:
                   1858:                                ipseclog((LOG_ERR, "ipsec_hdrsiz: "
1.26      degroote 1859:                                        "unknown AF %d in IPsec tunnel SA\n",
                   1860:                                        ((struct sockaddr *)&isr->saidx.dst)->sa_family));
1.1       jonathan 1861:                                break;
                   1862:                        }
                   1863:                }
                   1864:                siz += clen;
                   1865:        }
                   1866:
                   1867:        return siz;
                   1868: }
                   1869:
                   1870: /* This function is called from ip_forward() and ipsec4_hdrsize_tcp(). */
                   1871: size_t
                   1872: ipsec4_hdrsiz(m, dir, inp)
                   1873:        struct mbuf *m;
                   1874:        u_int dir;
                   1875:        struct inpcb *inp;
                   1876: {
                   1877:        struct secpolicy *sp;
                   1878:        int error;
                   1879:        size_t size;
                   1880:
                   1881:        IPSEC_ASSERT(m != NULL, ("ipsec4_hdrsiz: null mbuf"));
                   1882:        IPSEC_ASSERT(inp == NULL || inp->inp_socket != NULL,
                   1883:                ("ipsec4_hdrsize: socket w/o inpcb"));
                   1884:
                   1885:        /* get SP for this packet.
                   1886:         * When we are called from ip_forward(), we call
                   1887:         * ipsec_getpolicybyaddr() with IP_FORWARDING flag.
                   1888:         */
                   1889:        if (inp == NULL)
                   1890:                sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
                   1891:        else
1.5       jonathan 1892:                sp = ipsec_getpolicybysock(m, dir,
                   1893:                                           IN4PCB_TO_PCB(inp), &error);
1.1       jonathan 1894:
                   1895:        if (sp != NULL) {
                   1896:                size = ipsec_hdrsiz(sp);
                   1897:                KEYDEBUG(KEYDEBUG_IPSEC_DATA,
                   1898:                        printf("ipsec4_hdrsiz: size:%lu.\n",
                   1899:                                (unsigned long)size));
                   1900:
                   1901:                KEY_FREESP(&sp);
                   1902:        } else {
                   1903:                size = 0;       /* XXX should be panic ? */
                   1904:        }
                   1905:        return size;
                   1906: }
                   1907:
                   1908: #ifdef INET6
                   1909: /* This function is called from ipsec6_hdrsize_tcp(),
                   1910:  * and maybe from ip6_forward.()
                   1911:  */
                   1912: size_t
                   1913: ipsec6_hdrsiz(m, dir, in6p)
                   1914:        struct mbuf *m;
                   1915:        u_int dir;
                   1916:        struct in6pcb *in6p;
                   1917: {
                   1918:        struct secpolicy *sp;
                   1919:        int error;
                   1920:        size_t size;
                   1921:
                   1922:        IPSEC_ASSERT(m != NULL, ("ipsec6_hdrsiz: null mbuf"));
                   1923:        IPSEC_ASSERT(in6p == NULL || in6p->in6p_socket != NULL,
                   1924:                ("ipsec6_hdrsize: socket w/o inpcb"));
                   1925:
                   1926:        /* get SP for this packet */
                   1927:        /* XXX Is it right to call with IP_FORWARDING. */
                   1928:        if (in6p == NULL)
                   1929:                sp = ipsec_getpolicybyaddr(m, dir, IP_FORWARDING, &error);
                   1930:        else
1.15      perry    1931:                sp = ipsec_getpolicybysock(m, dir,
1.5       jonathan 1932:                        IN6PCB_TO_PCB(in6p),
                   1933:                        &error);
1.1       jonathan 1934:
                   1935:        if (sp == NULL)
                   1936:                return 0;
                   1937:        size = ipsec_hdrsiz(sp);
                   1938:        KEYDEBUG(KEYDEBUG_IPSEC_DATA,
                   1939:                printf("ipsec6_hdrsiz: size:%lu.\n", (unsigned long)size));
                   1940:        KEY_FREESP(&sp);
                   1941:
                   1942:        return size;
                   1943: }
                   1944: #endif /*INET6*/
                   1945:
                   1946: /*
                   1947:  * Check the variable replay window.
                   1948:  * ipsec_chkreplay() performs replay check before ICV verification.
                   1949:  * ipsec_updatereplay() updates replay bitmap.  This must be called after
                   1950:  * ICV verification (it also performs replay check, which is usually done
                   1951:  * beforehand).
                   1952:  * 0 (zero) is returned if packet disallowed, 1 if packet permitted.
                   1953:  *
                   1954:  * based on RFC 2401.
                   1955:  */
                   1956: int
                   1957: ipsec_chkreplay(seq, sav)
                   1958:        u_int32_t seq;
                   1959:        struct secasvar *sav;
                   1960: {
                   1961:        const struct secreplay *replay;
                   1962:        u_int32_t diff;
                   1963:        int fr;
                   1964:        u_int32_t wsizeb;       /* constant: bits of window size */
                   1965:        int frlast;             /* constant: last frame */
                   1966:
                   1967:        IPSEC_SPLASSERT_SOFTNET("ipsec_chkreplay");
                   1968:
                   1969:        IPSEC_ASSERT(sav != NULL, ("ipsec_chkreplay: Null SA"));
                   1970:        IPSEC_ASSERT(sav->replay != NULL, ("ipsec_chkreplay: Null replay state"));
                   1971:
                   1972:        replay = sav->replay;
                   1973:
                   1974:        if (replay->wsize == 0)
                   1975:                return 1;       /* no need to check replay. */
                   1976:
                   1977:        /* constant */
                   1978:        frlast = replay->wsize - 1;
                   1979:        wsizeb = replay->wsize << 3;
                   1980:
                   1981:        /* sequence number of 0 is invalid */
                   1982:        if (seq == 0)
                   1983:                return 0;
                   1984:
                   1985:        /* first time is always okay */
                   1986:        if (replay->count == 0)
                   1987:                return 1;
                   1988:
                   1989:        if (seq > replay->lastseq) {
                   1990:                /* larger sequences are okay */
                   1991:                return 1;
                   1992:        } else {
                   1993:                /* seq is equal or less than lastseq. */
                   1994:                diff = replay->lastseq - seq;
                   1995:
                   1996:                /* over range to check, i.e. too old or wrapped */
                   1997:                if (diff >= wsizeb)
                   1998:                        return 0;
                   1999:
                   2000:                fr = frlast - diff / 8;
                   2001:
                   2002:                /* this packet already seen ? */
                   2003:                if ((replay->bitmap)[fr] & (1 << (diff % 8)))
                   2004:                        return 0;
                   2005:
                   2006:                /* out of order but good */
                   2007:                return 1;
                   2008:        }
                   2009: }
                   2010:
                   2011: /*
                   2012:  * check replay counter whether to update or not.
                   2013:  * OUT:        0:      OK
                   2014:  *     1:      NG
                   2015:  */
                   2016: int
                   2017: ipsec_updatereplay(seq, sav)
                   2018:        u_int32_t seq;
                   2019:        struct secasvar *sav;
                   2020: {
                   2021:        struct secreplay *replay;
                   2022:        u_int32_t diff;
                   2023:        int fr;
                   2024:        u_int32_t wsizeb;       /* constant: bits of window size */
                   2025:        int frlast;             /* constant: last frame */
                   2026:
                   2027:        IPSEC_SPLASSERT_SOFTNET("ipsec_updatereplay");
                   2028:
                   2029:        IPSEC_ASSERT(sav != NULL, ("ipsec_updatereplay: Null SA"));
                   2030:        IPSEC_ASSERT(sav->replay != NULL, ("ipsec_updatereplay: Null replay state"));
                   2031:
                   2032:        replay = sav->replay;
                   2033:
                   2034:        if (replay->wsize == 0)
                   2035:                goto ok;        /* no need to check replay. */
                   2036:
                   2037:        /* constant */
                   2038:        frlast = replay->wsize - 1;
                   2039:        wsizeb = replay->wsize << 3;
                   2040:
                   2041:        /* sequence number of 0 is invalid */
                   2042:        if (seq == 0)
                   2043:                return 1;
                   2044:
                   2045:        /* first time */
                   2046:        if (replay->count == 0) {
                   2047:                replay->lastseq = seq;
                   2048:                bzero(replay->bitmap, replay->wsize);
                   2049:                (replay->bitmap)[frlast] = 1;
                   2050:                goto ok;
                   2051:        }
                   2052:
                   2053:        if (seq > replay->lastseq) {
                   2054:                /* seq is larger than lastseq. */
                   2055:                diff = seq - replay->lastseq;
                   2056:
                   2057:                /* new larger sequence number */
                   2058:                if (diff < wsizeb) {
                   2059:                        /* In window */
                   2060:                        /* set bit for this packet */
                   2061:                        vshiftl(replay->bitmap, diff, replay->wsize);
                   2062:                        (replay->bitmap)[frlast] |= 1;
                   2063:                } else {
                   2064:                        /* this packet has a "way larger" */
                   2065:                        bzero(replay->bitmap, replay->wsize);
                   2066:                        (replay->bitmap)[frlast] = 1;
                   2067:                }
                   2068:                replay->lastseq = seq;
                   2069:
                   2070:                /* larger is good */
                   2071:        } else {
                   2072:                /* seq is equal or less than lastseq. */
                   2073:                diff = replay->lastseq - seq;
                   2074:
                   2075:                /* over range to check, i.e. too old or wrapped */
                   2076:                if (diff >= wsizeb)
                   2077:                        return 1;
                   2078:
                   2079:                fr = frlast - diff / 8;
                   2080:
                   2081:                /* this packet already seen ? */
                   2082:                if ((replay->bitmap)[fr] & (1 << (diff % 8)))
                   2083:                        return 1;
                   2084:
                   2085:                /* mark as seen */
                   2086:                (replay->bitmap)[fr] |= (1 << (diff % 8));
                   2087:
                   2088:                /* out of order but good */
                   2089:        }
                   2090:
                   2091: ok:
                   2092:        if (replay->count == ~0) {
                   2093:
                   2094:                /* set overflow flag */
                   2095:                replay->overflow++;
                   2096:
                   2097:                /* don't increment, no more packets accepted */
                   2098:                if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0)
                   2099:                        return 1;
                   2100:
                   2101:                ipseclog((LOG_WARNING, "replay counter made %d cycle. %s\n",
1.26      degroote 2102:                        replay->overflow, ipsec_logsastr(sav)));
1.1       jonathan 2103:        }
                   2104:
                   2105:        replay->count++;
                   2106:
                   2107:        return 0;
                   2108: }
                   2109:
                   2110: /*
                   2111:  * shift variable length bunffer to left.
                   2112:  * IN: bitmap: pointer to the buffer
                   2113:  *     nbit:   the number of to shift.
                   2114:  *     wsize:  buffer size (bytes).
                   2115:  */
                   2116: static void
                   2117: vshiftl(bitmap, nbit, wsize)
                   2118:        unsigned char *bitmap;
                   2119:        int nbit, wsize;
                   2120: {
                   2121:        int s, j, i;
                   2122:        unsigned char over;
                   2123:
                   2124:        for (j = 0; j < nbit; j += 8) {
                   2125:                s = (nbit - j < 8) ? (nbit - j): 8;
                   2126:                bitmap[0] <<= s;
                   2127:                for (i = 1; i < wsize; i++) {
                   2128:                        over = (bitmap[i] >> (8 - s));
                   2129:                        bitmap[i] <<= s;
                   2130:                        bitmap[i-1] |= over;
                   2131:                }
                   2132:        }
                   2133:
                   2134:        return;
                   2135: }
                   2136:
                   2137: /* Return a printable string for the IPv4 address. */
                   2138: static char *
                   2139: inet_ntoa4(struct in_addr ina)
                   2140: {
                   2141:        static char buf[4][4 * sizeof "123" + 4];
                   2142:        unsigned char *ucp = (unsigned char *) &ina;
                   2143:        static int i = 3;
                   2144:
                   2145:        i = (i + 1) % 4;
1.11      itojun   2146:        snprintf(buf[i], sizeof(buf[i]), "%d.%d.%d.%d",
1.26      degroote 2147:                ucp[0] & 0xff, ucp[1] & 0xff, ucp[2] & 0xff, ucp[3] & 0xff);
1.1       jonathan 2148:        return (buf[i]);
                   2149: }
                   2150:
                   2151: /* Return a printable string for the address. */
1.17      christos 2152: const char *
1.1       jonathan 2153: ipsec_address(union sockaddr_union* sa)
                   2154: {
                   2155:        switch (sa->sa.sa_family) {
                   2156: #if INET
                   2157:        case AF_INET:
                   2158:                return inet_ntoa4(sa->sin.sin_addr);
                   2159: #endif /* INET */
                   2160:
                   2161: #if INET6
                   2162:        case AF_INET6:
                   2163:                return ip6_sprintf(&sa->sin6.sin6_addr);
                   2164: #endif /* INET6 */
                   2165:
                   2166:        default:
                   2167:                return "(unknown address family)";
                   2168:        }
                   2169: }
                   2170:
                   2171: const char *
                   2172: ipsec_logsastr(sav)
                   2173:        struct secasvar *sav;
                   2174: {
                   2175:        static char buf[256];
                   2176:        char *p;
                   2177:        struct secasindex *saidx = &sav->sah->saidx;
                   2178:
                   2179:        IPSEC_ASSERT(saidx->src.sa.sa_family == saidx->dst.sa.sa_family,
                   2180:                ("ipsec_logsastr: address family mismatch"));
                   2181:
                   2182:        p = buf;
                   2183:        snprintf(buf, sizeof(buf), "SA(SPI=%u ", (u_int32_t)ntohl(sav->spi));
                   2184:        while (p && *p)
                   2185:                p++;
                   2186:        /* NB: only use ipsec_address on one address at a time */
                   2187:        snprintf(p, sizeof (buf) - (p - buf), "src=%s ",
                   2188:                ipsec_address(&saidx->src));
                   2189:        while (p && *p)
                   2190:                p++;
                   2191:        snprintf(p, sizeof (buf) - (p - buf), "dst=%s)",
                   2192:                ipsec_address(&saidx->dst));
                   2193:
                   2194:        return buf;
                   2195: }
                   2196:
                   2197: void
                   2198: ipsec_dumpmbuf(m)
                   2199:        struct mbuf *m;
                   2200: {
                   2201:        int totlen;
                   2202:        int i;
                   2203:        u_char *p;
                   2204:
                   2205:        totlen = 0;
                   2206:        printf("---\n");
                   2207:        while (m) {
                   2208:                p = mtod(m, u_char *);
                   2209:                for (i = 0; i < m->m_len; i++) {
                   2210:                        printf("%02x ", p[i]);
                   2211:                        totlen++;
                   2212:                        if (totlen % 16 == 0)
                   2213:                                printf("\n");
                   2214:                }
                   2215:                m = m->m_next;
                   2216:        }
                   2217:        if (totlen % 16 != 0)
                   2218:                printf("\n");
                   2219:        printf("---\n");
                   2220: }
                   2221:
1.26      degroote 2222: #ifdef INET6
                   2223: struct secpolicy *
                   2224: ipsec6_check_policy(m,so,flags,needipsecp,errorp)
                   2225:        struct mbuf * m;
                   2226:        const struct socket * so;
                   2227:        int flags;
                   2228:        int * needipsecp;
                   2229:        int * errorp;
                   2230: {
                   2231:        struct in6pcb *in6p = NULL;
                   2232:        struct m_tag *mtag;
                   2233:        struct secpolicy *sp = NULL;
                   2234:        struct tdb_ident *tdbi;
                   2235:        int s;
                   2236:        int error = 0;
                   2237:        int needipsec = 0;
                   2238:
                   2239:        if (so != NULL && so->so_proto->pr_domain->dom_family == AF_INET6)
                   2240:                in6p = sotoin6pcb(so);
                   2241:
                   2242:        mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
                   2243:        s = splsoftnet();
                   2244:        if (mtag != NULL) {
                   2245:                tdbi = (struct tdb_ident *)(mtag + 1);
                   2246:                sp = ipsec_getpolicy(tdbi, IPSEC_DIR_OUTBOUND);
                   2247:                if (sp == NULL)
                   2248:                        error = -EINVAL;        /* force silent drop */
                   2249:                m_tag_delete(m, mtag);
                   2250:        } else {
                   2251:                if (in6p != NULL &&
                   2252:                        IPSEC_PCB_SKIP_IPSEC(in6p->in6p_sp, IPSEC_DIR_OUTBOUND))
                   2253:                        goto skippolicycheck;
                   2254:                sp = ipsec6_checkpolicy(m, IPSEC_DIR_OUTBOUND, flags, &error,in6p);
                   2255:        }
                   2256:
                   2257:        /*
                   2258:         * There are four return cases:
                   2259:         *      sp != NULL                      apply IPsec policy
                   2260:         *      sp == NULL, error == 0          no IPsec handling needed
                   2261:         *      sp == NULL, error == -EINVAL  discard packet w/o error
                   2262:         *      sp == NULL, error != 0          discard packet, report error
                   2263:         */
                   2264:
                   2265:        if (sp == NULL) {
                   2266:                splx(s);
                   2267:
                   2268:                if (error != 0) {
                   2269:                        needipsec = 0;
                   2270:                } else {
                   2271:                        /* No IPsec processing for this packet. */
                   2272:                        needipsec = 0;
                   2273:                }
                   2274:        } else {
                   2275:                /* Loop detection, check if ipsec processing already done */
                   2276:                IPSEC_ASSERT(sp->req != NULL, ("ip6_output: no ipsec request"));
                   2277:                for (mtag = m_tag_first(m); mtag != NULL;
                   2278:                         mtag = m_tag_next(m, mtag)) {
                   2279: #ifdef MTAG_ABI_COMPAT
                   2280:                        if (mtag->m_tag_cookie != MTAG_ABI_COMPAT)
                   2281:                                continue;
                   2282: #endif
                   2283:                        if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
                   2284:                                mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
                   2285:                                continue;
                   2286:                        /*
                   2287:                         * Check if policy has an SA associated with it.
                   2288:                         * This can happen when an SP has yet to acquire
                   2289:                         * an SA; e.g. on first reference.  If it occurs,
                   2290:                         * then we let ipsec4_process_packet do its thing.
                   2291:                         */
                   2292:                        if (sp->req->sav == NULL)
                   2293:                                break;
                   2294:                        tdbi = (struct tdb_ident *)(mtag + 1);
                   2295:                        if (tdbi->spi == sp->req->sav->spi &&
                   2296:                                tdbi->proto == sp->req->sav->sah->saidx.proto &&
                   2297:                                bcmp(&tdbi->dst, &sp->req->sav->sah->saidx.dst,
                   2298:                                 sizeof (union sockaddr_union)) == 0) {
                   2299:                                /*
                   2300:                                 * No IPsec processing is needed, free
                   2301:                                 * reference to SP.
                   2302:                                 *
                   2303:                                 * NB: null pointer to avoid free at
                   2304:                                 *       done: below.
                   2305:                                 */
                   2306:                                KEY_FREESP(&sp), sp = NULL;
                   2307:                                needipsec = 0;
                   2308:                                splx(s);
                   2309:                                goto skippolicycheck;
                   2310:                        }
                   2311:                }
                   2312:                splx(s);
                   2313:                needipsec = 1;
                   2314:        }
                   2315: skippolicycheck:;
                   2316:
                   2317:        *errorp = error;
                   2318:        *needipsecp = needipsec;
                   2319:        return sp;
                   2320: }
                   2321: #endif
                   2322:
                   2323:
                   2324:
1.1       jonathan 2325: /* XXX this stuff doesn't belong here... */
                   2326:
                   2327: static struct xformsw* xforms = NULL;
                   2328:
                   2329: /*
                   2330:  * Register a transform; typically at system startup.
                   2331:  */
                   2332: void
                   2333: xform_register(struct xformsw* xsp)
                   2334: {
                   2335:        xsp->xf_next = xforms;
                   2336:        xforms = xsp;
                   2337: }
                   2338:
                   2339: /*
                   2340:  * Initialize transform support in an sav.
                   2341:  */
                   2342: int
                   2343: xform_init(struct secasvar *sav, int xftype)
                   2344: {
                   2345:        struct xformsw *xsp;
                   2346:
                   2347:        if (sav->tdb_xform != NULL)     /* previously initialized */
                   2348:                return 0;
                   2349:        for (xsp = xforms; xsp; xsp = xsp->xf_next)
                   2350:                if (xsp->xf_type == xftype)
                   2351:                        return (*xsp->xf_init)(sav, xsp);
                   2352:
                   2353:        DPRINTF(("xform_init: no match for xform type %d\n", xftype));
                   2354:        return EINVAL;
                   2355: }
                   2356:
                   2357: #ifdef __NetBSD__
                   2358: void
                   2359: ipsec_attach(void)
                   2360: {
                   2361:        printf("initializing IPsec...");
                   2362:        ah_attach();
                   2363:        esp_attach();
                   2364:        ipcomp_attach();
                   2365:        ipe4_attach();
1.12      jonathan 2366: #ifdef TCP_SIGNATURE
                   2367:        tcpsignature_attach();
                   2368: #endif
1.1       jonathan 2369:        printf(" done\n");
                   2370: }
                   2371: #endif /* __NetBSD__ */

CVSweb <webmaster@jp.NetBSD.org>