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

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

1.1       nbrk        1: /* $OpenBSD: ip_spd.c,v 1.53 2007/02/14 00:53:48 jsg Exp $ */
                      2: /*
                      3:  * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu)
                      4:  *
                      5:  * Copyright (c) 2000-2001 Angelos D. Keromytis.
                      6:  *
                      7:  * Permission to use, copy, and modify this software with or without fee
                      8:  * is hereby granted, provided that this entire notice is included in
                      9:  * all copies of any software which is or includes a copy or
                     10:  * modification of this software.
                     11:  * You may use this code under the GNU public license if you so wish. Please
                     12:  * contribute changes back to the authors under this freer than GPL license
                     13:  * so that we may further the use of strong encryption without limitations to
                     14:  * all.
                     15:  *
                     16:  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
                     17:  * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
                     18:  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
                     19:  * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
                     20:  * PURPOSE.
                     21:  */
                     22:
                     23: #include <sys/param.h>
                     24: #include <sys/systm.h>
                     25: #include <sys/mbuf.h>
                     26: #include <sys/socket.h>
                     27: #include <sys/kernel.h>
                     28: #include <sys/socketvar.h>
                     29: #include <sys/protosw.h>
                     30:
                     31: #include <net/if.h>
                     32: #include <net/route.h>
                     33: #include <net/netisr.h>
                     34:
                     35: #ifdef INET
                     36: #include <netinet/in.h>
                     37: #include <netinet/in_systm.h>
                     38: #include <netinet/ip.h>
                     39: #include <netinet/in_pcb.h>
                     40: #include <netinet/in_var.h>
                     41: #endif /* INET */
                     42:
                     43: #ifdef INET6
                     44: #ifndef INET
                     45: #include <netinet/in.h>
                     46: #endif
                     47: #include <netinet6/in6_var.h>
                     48: #endif /* INET6 */
                     49:
                     50: #include <netinet/ip_ipsp.h>
                     51: #include <net/pfkeyv2.h>
                     52:
                     53: #ifdef ENCDEBUG
                     54: #define        DPRINTF(x)      if (encdebug) printf x
                     55: #else
                     56: #define        DPRINTF(x)
                     57: #endif
                     58:
                     59: struct pool ipsec_policy_pool;
                     60: struct pool ipsec_acquire_pool;
                     61: int ipsec_policy_pool_initialized = 0;
                     62: int ipsec_acquire_pool_initialized = 0;
                     63:
                     64: /*
                     65:  * Lookup at the SPD based on the headers contained on the mbuf. The second
                     66:  * argument indicates what protocol family the header at the beginning of
                     67:  * the mbuf is. hlen is the offset of the transport protocol header
                     68:  * in the mbuf.
                     69:  *
                     70:  * Return combinations (of return value and in *error):
                     71:  * - NULL/0 -> no IPsec required on packet
                     72:  * - NULL/-EINVAL -> silently drop the packet
                     73:  * - NULL/errno -> drop packet and return error
                     74:  * or a pointer to a TDB (and 0 in *error).
                     75:  *
                     76:  * In the case of incoming flows, only the first three combinations are
                     77:  * returned.
                     78:  */
                     79: struct tdb *
                     80: ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int *error, int direction,
                     81:     struct tdb *tdbp, struct inpcb *inp)
                     82: {
                     83:        struct route_enc re0, *re = &re0;
                     84:        union sockaddr_union sdst, ssrc;
                     85:        struct sockaddr_encap *ddst;
                     86:        struct ipsec_policy *ipo;
                     87:        int signore = 0, dignore = 0;
                     88:
                     89:        /*
                     90:         * If there are no flows in place, there's no point
                     91:         * continuing with the SPD lookup.
                     92:         */
                     93:        if (!ipsec_in_use && inp == NULL) {
                     94:                *error = 0;
                     95:                return NULL;
                     96:        }
                     97:
                     98:        /*
                     99:         * If an input packet is destined to a BYPASS socket, just accept it.
                    100:         */
                    101:        if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
                    102:            (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
                    103:            (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
                    104:            (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
                    105:                *error = 0;
                    106:                return NULL;
                    107:        }
                    108:
                    109:        bzero((caddr_t) re, sizeof(struct route_enc));
                    110:        bzero((caddr_t) &sdst, sizeof(union sockaddr_union));
                    111:        bzero((caddr_t) &ssrc, sizeof(union sockaddr_union));
                    112:        ddst = (struct sockaddr_encap *) &re->re_dst;
                    113:        ddst->sen_family = PF_KEY;
                    114:        ddst->sen_len = SENT_LEN;
                    115:
                    116:        switch (af) {
                    117: #ifdef INET
                    118:        case AF_INET:
                    119:                if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen) {
                    120:                        *error = EINVAL;
                    121:                        return NULL;
                    122:                }
                    123:                ddst->sen_direction = direction;
                    124:                ddst->sen_type = SENT_IP4;
                    125:
                    126:                m_copydata(m, offsetof(struct ip, ip_src),
                    127:                    sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
                    128:                m_copydata(m, offsetof(struct ip, ip_dst),
                    129:                    sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
                    130:                m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
                    131:                    (caddr_t) &(ddst->sen_proto));
                    132:
                    133:                sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
                    134:                sdst.sin.sin_len = ssrc.sin.sin_len =
                    135:                    sizeof(struct sockaddr_in);
                    136:                ssrc.sin.sin_addr = ddst->sen_ip_src;
                    137:                sdst.sin.sin_addr = ddst->sen_ip_dst;
                    138:
                    139:                /*
                    140:                 * If TCP/UDP, extract the port numbers to use in the lookup.
                    141:                 */
                    142:                switch (ddst->sen_proto) {
                    143:                case IPPROTO_UDP:
                    144:                case IPPROTO_TCP:
                    145:                        /* Make sure there's enough data in the packet. */
                    146:                        if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
                    147:                                *error = EINVAL;
                    148:                                return NULL;
                    149:                        }
                    150:
                    151:                        /*
                    152:                         * Luckily, the offset of the src/dst ports in
                    153:                         * both the UDP and TCP headers is the same (first
                    154:                         * two 16-bit values in the respective headers),
                    155:                         * so we can just copy them.
                    156:                         */
                    157:                        m_copydata(m, hlen, sizeof(u_int16_t),
                    158:                            (caddr_t) &(ddst->sen_sport));
                    159:                        m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
                    160:                            (caddr_t) &(ddst->sen_dport));
                    161:                        break;
                    162:
                    163:                default:
                    164:                        ddst->sen_sport = 0;
                    165:                        ddst->sen_dport = 0;
                    166:                }
                    167:
                    168:                break;
                    169: #endif /* INET */
                    170:
                    171: #ifdef INET6
                    172:        case AF_INET6:
                    173:                if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen) {
                    174:                        *error = EINVAL;
                    175:                        return NULL;
                    176:                }
                    177:                ddst->sen_type = SENT_IP6;
                    178:                ddst->sen_ip6_direction = direction;
                    179:
                    180:                m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
                    181:                    sizeof(struct in6_addr),
                    182:                    (caddr_t) &(ddst->sen_ip6_src));
                    183:                m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
                    184:                    sizeof(struct in6_addr),
                    185:                    (caddr_t) &(ddst->sen_ip6_dst));
                    186:                m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
                    187:                    sizeof(u_int8_t),
                    188:                    (caddr_t) &(ddst->sen_ip6_proto));
                    189:
                    190:                sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
                    191:                sdst.sin6.sin6_len = ssrc.sin6.sin6_family =
                    192:                    sizeof(struct sockaddr_in6);
                    193:                in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src, NULL);
                    194:                in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst, NULL);
                    195:
                    196:                /*
                    197:                 * If TCP/UDP, extract the port numbers to use in the lookup.
                    198:                 */
                    199:                switch (ddst->sen_ip6_proto) {
                    200:                case IPPROTO_UDP:
                    201:                case IPPROTO_TCP:
                    202:                        /* Make sure there's enough data in the packet. */
                    203:                        if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t)) {
                    204:                                *error = EINVAL;
                    205:                                return NULL;
                    206:                        }
                    207:
                    208:                        /*
                    209:                         * Luckily, the offset of the src/dst ports in
                    210:                         * both the UDP and TCP headers is the same
                    211:                         * (first two 16-bit values in the respective
                    212:                         * headers), so we can just copy them.
                    213:                         */
                    214:                        m_copydata(m, hlen, sizeof(u_int16_t),
                    215:                            (caddr_t) &(ddst->sen_ip6_sport));
                    216:                        m_copydata(m, hlen + sizeof(u_int16_t), sizeof(u_int16_t),
                    217:                            (caddr_t) &(ddst->sen_ip6_dport));
                    218:                        break;
                    219:
                    220:                default:
                    221:                        ddst->sen_ip6_sport = 0;
                    222:                        ddst->sen_ip6_dport = 0;
                    223:                }
                    224:
                    225:                break;
                    226: #endif /* INET6 */
                    227:
                    228:        default:
                    229:                *error = EAFNOSUPPORT;
                    230:                return NULL;
                    231:        }
                    232:
                    233:        /* Actual SPD lookup. */
                    234:        rtalloc((struct route *) re);
                    235:        if (re->re_rt == NULL) {
                    236:                /*
                    237:                 * Return whatever the socket requirements are, there are no
                    238:                 * system-wide policies.
                    239:                 */
                    240:                *error = 0;
                    241:                return ipsp_spd_inp(m, af, hlen, error, direction,
                    242:                    tdbp, inp, NULL);
                    243:        }
                    244:
                    245:        /* Sanity check. */
                    246:        if ((re->re_rt->rt_gateway == NULL) ||
                    247:            (((struct sockaddr_encap *) re->re_rt->rt_gateway)->sen_type !=
                    248:                SENT_IPSP)) {
                    249:                RTFREE(re->re_rt);
                    250:                *error = EHOSTUNREACH;
                    251:                DPRINTF(("ip_spd_lookup: no gateway in SPD entry!"));
                    252:                return NULL;
                    253:        }
                    254:
                    255:        ipo = ((struct sockaddr_encap *) (re->re_rt->rt_gateway))->sen_ipsp;
                    256:        RTFREE(re->re_rt);
                    257:        if (ipo == NULL) {
                    258:                *error = EHOSTUNREACH;
                    259:                DPRINTF(("ip_spd_lookup: no policy attached to SPD entry!"));
                    260:                return NULL;
                    261:        }
                    262:
                    263:        switch (ipo->ipo_type) {
                    264:        case IPSP_PERMIT:
                    265:                *error = 0;
                    266:                return ipsp_spd_inp(m, af, hlen, error, direction, tdbp,
                    267:                    inp, ipo);
                    268:
                    269:        case IPSP_DENY:
                    270:                *error = EHOSTUNREACH;
                    271:                return NULL;
                    272:
                    273:        case IPSP_IPSEC_USE:
                    274:        case IPSP_IPSEC_ACQUIRE:
                    275:        case IPSP_IPSEC_REQUIRE:
                    276:        case IPSP_IPSEC_DONTACQ:
                    277:                /* Nothing more needed here. */
                    278:                break;
                    279:
                    280:        default:
                    281:                *error = EINVAL;
                    282:                return NULL;
                    283:        }
                    284:
                    285:        /* Check for non-specific destination in the policy. */
                    286:        switch (ipo->ipo_dst.sa.sa_family) {
                    287: #ifdef INET
                    288:        case AF_INET:
                    289:                if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
                    290:                    (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
                    291:                        dignore = 1;
                    292:                break;
                    293: #endif /* INET */
                    294:
                    295: #ifdef INET6
                    296:        case AF_INET6:
                    297:                if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
                    298:                    (bcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
                    299:                        sizeof(in6mask128)) == 0))
                    300:                        dignore = 1;
                    301:                break;
                    302: #endif /* INET6 */
                    303:        }
                    304:
                    305:        /* Likewise for source. */
                    306:        switch (ipo->ipo_src.sa.sa_family) {
                    307: #ifdef INET
                    308:        case AF_INET:
                    309:                if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
                    310:                        signore = 1;
                    311:                break;
                    312: #endif /* INET */
                    313:
                    314: #ifdef INET6
                    315:        case AF_INET6:
                    316:                if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
                    317:                        signore = 1;
                    318:                break;
                    319: #endif /* INET6 */
                    320:        }
                    321:
                    322:        /* Do we have a cached entry ? If so, check if it's still valid. */
                    323:        if ((ipo->ipo_tdb) && (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
                    324:                TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
                    325:                    ipo_tdb_next);
                    326:                ipo->ipo_tdb = NULL;
                    327:        }
                    328:
                    329:        /* Outgoing packet policy check. */
                    330:        if (direction == IPSP_DIRECTION_OUT) {
                    331:                /*
                    332:                 * If the packet is destined for the policy-specified
                    333:                 * gateway/endhost, and the socket has the BYPASS
                    334:                 * option set, skip IPsec processing.
                    335:                 */
                    336:                if ((inp != NULL) &&
                    337:                    (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
                    338:                    (inp->inp_seclevel[SL_ESP_NETWORK] ==
                    339:                        IPSEC_LEVEL_BYPASS) &&
                    340:                    (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
                    341:                        /* Direct match. */
                    342:                        if (dignore ||
                    343:                            !bcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
                    344:                                *error = 0;
                    345:                                return NULL;
                    346:                        }
                    347:                }
                    348:
                    349:                /* Check that the cached TDB (if present), is appropriate. */
                    350:                if (ipo->ipo_tdb) {
                    351:                        if ((ipo->ipo_last_searched <= ipsec_last_added) ||
                    352:                            (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
                    353:                            bcmp(dignore ? &sdst : &ipo->ipo_dst,
                    354:                                &ipo->ipo_tdb->tdb_dst,
                    355:                                ipo->ipo_tdb->tdb_dst.sa.sa_len))
                    356:                                goto nomatchout;
                    357:
                    358:                        if (!ipsp_aux_match(ipo->ipo_tdb,
                    359:                            ipo->ipo_srcid, ipo->ipo_dstid,
                    360:                            ipo->ipo_local_cred, NULL,
                    361:                            &ipo->ipo_addr, &ipo->ipo_mask))
                    362:                                goto nomatchout;
                    363:
                    364:                        /* Cached entry is good. */
                    365:                        *error = 0;
                    366:                        return ipsp_spd_inp(m, af, hlen, error, direction,
                    367:                            tdbp, inp, ipo);
                    368:
                    369:   nomatchout:
                    370:                        /* Cached TDB was not good. */
                    371:                        TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
                    372:                            ipo_tdb_next);
                    373:                        ipo->ipo_tdb = NULL;
                    374:                        ipo->ipo_last_searched = 0;
                    375:                }
                    376:
                    377:                /*
                    378:                 * If no SA has been added since the last time we did a
                    379:                 * lookup, there's no point searching for one. However, if the
                    380:                 * destination gateway is left unspecified (or is all-1's),
                    381:                 * always lookup since this is a generic-match rule
                    382:                 * (otherwise, we can have situations where SAs to some
                    383:                 * destinations exist but are not used, possibly leading to an
                    384:                 * explosion in the number of acquired SAs).
                    385:                 */
                    386:                if (ipo->ipo_last_searched <= ipsec_last_added) {
                    387:                        /* "Touch" the entry. */
                    388:                        if (dignore == 0)
                    389:                                ipo->ipo_last_searched = time_second;
                    390:
                    391:                        /* Find an appropriate SA from the existing ones. */
                    392:                        ipo->ipo_tdb =
                    393:                            gettdbbyaddr(dignore ? &sdst : &ipo->ipo_dst,
                    394:                                ipo->ipo_sproto, ipo->ipo_srcid,
                    395:                                ipo->ipo_dstid, ipo->ipo_local_cred, m, af,
                    396:                                &ipo->ipo_addr, &ipo->ipo_mask);
                    397:                        if (ipo->ipo_tdb) {
                    398:                                TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
                    399:                                    ipo, ipo_tdb_next);
                    400:                                *error = 0;
                    401:                                return ipsp_spd_inp(m, af, hlen, error,
                    402:                                    direction, tdbp, inp, ipo);
                    403:                        }
                    404:                }
                    405:
                    406:                /* So, we don't have an SA -- just a policy. */
                    407:                switch (ipo->ipo_type) {
                    408:                case IPSP_IPSEC_REQUIRE:
                    409:                        /* Acquire SA through key management. */
                    410:                        if (ipsp_acquire_sa(ipo,
                    411:                            dignore ? &sdst : &ipo->ipo_dst,
                    412:                            signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
                    413:                                *error = EACCES;
                    414:                                return NULL;
                    415:                        }
                    416:
                    417:                        /* FALLTHROUGH */
                    418:                case IPSP_IPSEC_DONTACQ:
                    419:                        *error = -EINVAL; /* Silently drop packet. */
                    420:                        return NULL;
                    421:
                    422:                case IPSP_IPSEC_ACQUIRE:
                    423:                        /* Acquire SA through key management. */
                    424:                        ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
                    425:                            signore ? NULL : &ipo->ipo_src, ddst, NULL);
                    426:
                    427:                        /* FALLTHROUGH */
                    428:                case IPSP_IPSEC_USE:
                    429:                        *error = 0;
                    430:                        return ipsp_spd_inp(m, af, hlen, error, direction,
                    431:                            tdbp, inp, ipo);
                    432:                }
                    433:        } else { /* IPSP_DIRECTION_IN */
                    434:                if (tdbp != NULL) {
                    435:                        /* Direct match in the cache. */
                    436:                        if (ipo->ipo_tdb == tdbp) {
                    437:                                *error = 0;
                    438:                                return ipsp_spd_inp(m, af, hlen, error,
                    439:                                    direction, tdbp, inp, ipo);
                    440:                        }
                    441:
                    442:                        if (bcmp(dignore ? &ssrc : &ipo->ipo_dst,
                    443:                            &tdbp->tdb_src, tdbp->tdb_src.sa.sa_len) ||
                    444:                            (ipo->ipo_sproto != tdbp->tdb_sproto))
                    445:                                goto nomatchin;
                    446:
                    447:                        /* Match source ID. */
                    448:                        if (ipo->ipo_srcid) {
                    449:                                if (tdbp->tdb_dstid == NULL ||
                    450:                                    !ipsp_ref_match(ipo->ipo_srcid,
                    451:                                        tdbp->tdb_dstid))
                    452:                                        goto nomatchin;
                    453:                        }
                    454:
                    455:                        /* Match destination ID. */
                    456:                        if (ipo->ipo_dstid) {
                    457:                                if (tdbp->tdb_srcid == NULL ||
                    458:                                    !ipsp_ref_match(ipo->ipo_dstid,
                    459:                                        tdbp->tdb_srcid))
                    460:                                        goto nomatchin;
                    461:                        }
                    462:
                    463:                        /* Add it to the cache. */
                    464:                        if (ipo->ipo_tdb)
                    465:                                TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
                    466:                                    ipo, ipo_tdb_next);
                    467:                        ipo->ipo_tdb = tdbp;
                    468:                        TAILQ_INSERT_TAIL(&tdbp->tdb_policy_head, ipo,
                    469:                            ipo_tdb_next);
                    470:                        *error = 0;
                    471:                        return ipsp_spd_inp(m, af, hlen, error, direction,
                    472:                            tdbp, inp, ipo);
                    473:
                    474:   nomatchin: /* Nothing needed here, falling through */
                    475:        ;
                    476:                }
                    477:
                    478:                /* Check whether cached entry applies. */
                    479:                if (ipo->ipo_tdb) {
                    480:                        /*
                    481:                         * We only need to check that the correct
                    482:                         * security protocol and security gateway are
                    483:                         * set; credentials/IDs will be the same,
                    484:                         * since the cached entry is linked on this
                    485:                         * policy.
                    486:                         */
                    487:                        if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
                    488:                            !bcmp(&ipo->ipo_tdb->tdb_src,
                    489:                                dignore ? &ssrc : &ipo->ipo_dst,
                    490:                                ipo->ipo_tdb->tdb_src.sa.sa_len))
                    491:                                goto skipinputsearch;
                    492:
                    493:                        /* Not applicable, unlink. */
                    494:                        TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
                    495:                            ipo_tdb_next);
                    496:                        ipo->ipo_last_searched = 0;
                    497:                        ipo->ipo_tdb = NULL;
                    498:                }
                    499:
                    500:                /* Find whether there exists an appropriate SA. */
                    501:                if (ipo->ipo_last_searched <= ipsec_last_added) {
                    502:                        if (dignore == 0)
                    503:                                ipo->ipo_last_searched = time_second;
                    504:
                    505:                        ipo->ipo_tdb =
                    506:                            gettdbbysrc(dignore ? &ssrc : &ipo->ipo_dst,
                    507:                                ipo->ipo_sproto, ipo->ipo_srcid,
                    508:                                ipo->ipo_dstid, m, af, &ipo->ipo_addr,
                    509:                                &ipo->ipo_mask);
                    510:                        if (ipo->ipo_tdb)
                    511:                                TAILQ_INSERT_TAIL(&ipo->ipo_tdb->tdb_policy_head,
                    512:                                    ipo, ipo_tdb_next);
                    513:                }
                    514:   skipinputsearch:
                    515:
                    516:                switch (ipo->ipo_type) {
                    517:                case IPSP_IPSEC_REQUIRE:
                    518:                        /* If appropriate SA exists, don't acquire another. */
                    519:                        if (ipo->ipo_tdb) {
                    520:                                *error = -EINVAL;
                    521:                                return NULL;
                    522:                        }
                    523:
                    524:                        /* Acquire SA through key management. */
                    525:                        if ((*error = ipsp_acquire_sa(ipo,
                    526:                            dignore ? &ssrc : &ipo->ipo_dst,
                    527:                            signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
                    528:                                return NULL;
                    529:
                    530:                        /* FALLTHROUGH */
                    531:                case IPSP_IPSEC_DONTACQ:
                    532:                        /* Drop packet. */
                    533:                        *error = -EINVAL;
                    534:                        return NULL;
                    535:
                    536:                case IPSP_IPSEC_ACQUIRE:
                    537:                        /* If appropriate SA exists, don't acquire another. */
                    538:                        if (ipo->ipo_tdb) {
                    539:                                *error = 0;
                    540:                                return ipsp_spd_inp(m, af, hlen, error,
                    541:                                    direction, tdbp, inp, ipo);
                    542:                        }
                    543:
                    544:                        /* Acquire SA through key management. */
                    545:                        ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
                    546:                            signore ? NULL : &ipo->ipo_src, ddst, NULL);
                    547:
                    548:                        /* FALLTHROUGH */
                    549:                case IPSP_IPSEC_USE:
                    550:                        *error = 0;
                    551:                        return ipsp_spd_inp(m, af, hlen, error, direction,
                    552:                            tdbp, inp, ipo);
                    553:                }
                    554:        }
                    555:
                    556:        /* Shouldn't ever get this far. */
                    557:        *error = EINVAL;
                    558:        return NULL;
                    559: }
                    560:
                    561: /*
                    562:  * Delete a policy from the SPD.
                    563:  */
                    564: int
                    565: ipsec_delete_policy(struct ipsec_policy *ipo)
                    566: {
                    567:        struct ipsec_acquire *ipa;
                    568:        int err = 0;
                    569:
                    570:        if (--ipo->ipo_ref_count > 0)
                    571:                return 0;
                    572:
                    573:        /* Delete from SPD. */
                    574:        if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
                    575:                err = rtrequest(RTM_DELETE, (struct sockaddr *) &ipo->ipo_addr,
                    576:                    (struct sockaddr *) 0,
                    577:                    (struct sockaddr *) &ipo->ipo_mask,
                    578:                    0, (struct rtentry **) 0, 0);       /* XXX other tables? */
                    579:
                    580:        if (ipo->ipo_tdb != NULL)
                    581:                TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
                    582:                    ipo_tdb_next);
                    583:
                    584:        while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
                    585:                ipsp_delete_acquire(ipa);
                    586:
                    587:        TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
                    588:
                    589:        if (ipo->ipo_srcid)
                    590:                ipsp_reffree(ipo->ipo_srcid);
                    591:        if (ipo->ipo_dstid)
                    592:                ipsp_reffree(ipo->ipo_dstid);
                    593:        if (ipo->ipo_local_cred)
                    594:                ipsp_reffree(ipo->ipo_local_cred);
                    595:        if (ipo->ipo_local_auth)
                    596:                ipsp_reffree(ipo->ipo_local_auth);
                    597:
                    598:        pool_put(&ipsec_policy_pool, ipo);
                    599:
                    600:        if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
                    601:                ipsec_in_use--;
                    602:
                    603:        return err;
                    604: }
                    605:
                    606: /*
                    607:  * Add a policy to the SPD.
                    608:  */
                    609: struct ipsec_policy *
                    610: ipsec_add_policy(struct inpcb *inp, int af, int direction)
                    611: {
                    612:        struct ipsec_policy *ipon;
                    613:
                    614:        if (ipsec_policy_pool_initialized == 0) {
                    615:                ipsec_policy_pool_initialized = 1;
                    616:                pool_init(&ipsec_policy_pool, sizeof(struct ipsec_policy),
                    617:                    0, 0, 0, "ipsec policy", NULL);
                    618:        }
                    619:
                    620:        ipon = pool_get(&ipsec_policy_pool, 0);
                    621:        if (ipon == NULL)
                    622:                return NULL;
                    623:
                    624:        bzero(ipon, sizeof(struct ipsec_policy));
                    625:
                    626:        ipon->ipo_ref_count = 1;
                    627:        ipon->ipo_flags |= IPSP_POLICY_SOCKET;
                    628:
                    629:        ipon->ipo_type = IPSP_IPSEC_REQUIRE; /* XXX */
                    630:
                    631:        /* XXX
                    632:         * We should actually be creating a linked list of
                    633:         * policies (for tunnel/transport and ESP/AH), as needed.
                    634:         */
                    635:        ipon->ipo_sproto = IPPROTO_ESP;
                    636:
                    637:        TAILQ_INIT(&ipon->ipo_acquires);
                    638:        TAILQ_INSERT_HEAD(&ipsec_policy_head, ipon, ipo_list);
                    639:
                    640:        ipsec_update_policy(inp, ipon, af, direction);
                    641:
                    642:        return ipon;
                    643: }
                    644:
                    645: /*
                    646:  * Update a PCB-attached policy.
                    647:  */
                    648: void
                    649: ipsec_update_policy(struct inpcb *inp, struct ipsec_policy *ipon, int af,
                    650:     int direction)
                    651: {
                    652:        ipon->ipo_addr.sen_len = ipon->ipo_mask.sen_len = SENT_LEN;
                    653:        ipon->ipo_addr.sen_family = ipon->ipo_mask.sen_family = PF_KEY;
                    654:        ipon->ipo_src.sa.sa_family = ipon->ipo_dst.sa.sa_family = af;
                    655:
                    656:        switch (af) {
                    657:        case AF_INET:
                    658: #ifdef INET
                    659:                ipon->ipo_addr.sen_type = ipon->ipo_mask.sen_type = SENT_IP4;
                    660:                ipon->ipo_addr.sen_ip_src = inp->inp_laddr;
                    661:                ipon->ipo_addr.sen_ip_dst = inp->inp_faddr;
                    662:                ipon->ipo_addr.sen_sport = inp->inp_lport;
                    663:                ipon->ipo_addr.sen_dport = inp->inp_fport;
                    664:                ipon->ipo_addr.sen_proto =
                    665:                    inp->inp_socket->so_proto->pr_protocol;
                    666:                ipon->ipo_addr.sen_direction = direction;
                    667:
                    668:                ipon->ipo_mask.sen_ip_src.s_addr = 0xffffffff;
                    669:                ipon->ipo_mask.sen_ip_dst.s_addr = 0xffffffff;
                    670:                ipon->ipo_mask.sen_sport = ipon->ipo_mask.sen_dport = 0xffff;
                    671:                ipon->ipo_mask.sen_proto = 0xff;
                    672:                ipon->ipo_mask.sen_direction = direction;
                    673:
                    674:                ipon->ipo_src.sa.sa_len = sizeof(struct sockaddr_in);
                    675:                ipon->ipo_dst.sa.sa_len = sizeof(struct sockaddr_in);
                    676:                ipon->ipo_src.sin.sin_addr = inp->inp_laddr;
                    677:                ipon->ipo_dst.sin.sin_addr = inp->inp_faddr;
                    678: #endif /* INET */
                    679:                break;
                    680:
                    681:        case AF_INET6:
                    682: #ifdef INET6
                    683:                ipon->ipo_addr.sen_type = ipon->ipo_mask.sen_type = SENT_IP6;
                    684:                ipon->ipo_addr.sen_ip6_src = inp->inp_laddr6;
                    685:                ipon->ipo_addr.sen_ip6_dst = inp->inp_faddr6;
                    686:                ipon->ipo_addr.sen_ip6_sport = inp->inp_lport;
                    687:                ipon->ipo_addr.sen_ip6_dport = inp->inp_fport;
                    688:                ipon->ipo_addr.sen_ip6_proto =
                    689:                    inp->inp_socket->so_proto->pr_protocol;
                    690:                ipon->ipo_addr.sen_ip6_direction = direction;
                    691:
                    692:                ipon->ipo_mask.sen_ip6_src = in6mask128;
                    693:                ipon->ipo_mask.sen_ip6_dst = in6mask128;
                    694:                ipon->ipo_mask.sen_ip6_sport = 0xffff;
                    695:                ipon->ipo_mask.sen_ip6_dport = 0xffff;
                    696:                ipon->ipo_mask.sen_ip6_proto = 0xff;
                    697:                ipon->ipo_mask.sen_ip6_direction = direction;
                    698:
                    699:                ipon->ipo_src.sa.sa_len = sizeof(struct sockaddr_in6);
                    700:                ipon->ipo_dst.sa.sa_len = sizeof(struct sockaddr_in6);
                    701:                ipon->ipo_src.sin6.sin6_addr = inp->inp_laddr6;
                    702:                ipon->ipo_dst.sin6.sin6_addr = inp->inp_faddr6;
                    703: #endif /* INET6 */
                    704:                break;
                    705:        }
                    706: }
                    707:
                    708: /*
                    709:  * Delete a pending IPsec acquire record.
                    710:  */
                    711: void
                    712: ipsp_delete_acquire(void *v)
                    713: {
                    714:        struct ipsec_acquire *ipa = v;
                    715:
                    716:        timeout_del(&ipa->ipa_timeout);
                    717:        TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
                    718:        if (ipa->ipa_policy != NULL)
                    719:                TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa,
                    720:                    ipa_ipo_next);
                    721:        pool_put(&ipsec_acquire_pool, ipa);
                    722: }
                    723:
                    724: /*
                    725:  * Find out if there's an ACQUIRE pending.
                    726:  * XXX Need a better structure.
                    727:  */
                    728: struct ipsec_acquire *
                    729: ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
                    730: {
                    731:        struct ipsec_acquire *ipa;
                    732:
                    733:        TAILQ_FOREACH (ipa, &ipo->ipo_acquires, ipa_ipo_next) {
                    734:                if (!bcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
                    735:                        return ipa;
                    736:        }
                    737:
                    738:        return NULL;
                    739: }
                    740:
                    741: /*
                    742:  * Signal key management that we need an SA.
                    743:  * XXX For outgoing policies, we could try to hold on to the mbuf.
                    744:  */
                    745: int
                    746: ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
                    747:     union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
                    748: {
                    749:        struct ipsec_acquire *ipa;
                    750:
                    751:        /*
                    752:         * If this is a socket policy, it has to have authentication
                    753:         * information accompanying it --- can't tell key mgmt. to
                    754:         * "find" it for us. This avoids abusing key mgmt. to authenticate
                    755:         * on an application's behalf, even if the application doesn't
                    756:         * have/know (and shouldn't) the appropriate authentication
                    757:         * material (passphrase, private key, etc.)
                    758:         */
                    759:        if (ipo->ipo_flags & IPSP_POLICY_SOCKET &&
                    760:            ipo->ipo_local_auth == NULL)
                    761:                return EINVAL;
                    762:
                    763:        /* Check whether request has been made already. */
                    764:        if ((ipa = ipsp_pending_acquire(ipo, gw)) != NULL)
                    765:                return 0;
                    766:
                    767:        /* Add request in cache and proceed. */
                    768:        if (ipsec_acquire_pool_initialized == 0) {
                    769:                ipsec_acquire_pool_initialized = 1;
                    770:                pool_init(&ipsec_acquire_pool, sizeof(struct ipsec_acquire),
                    771:                    0, 0, 0, "ipsec acquire", NULL);
                    772:        }
                    773:
                    774:        ipa = pool_get(&ipsec_acquire_pool, 0);
                    775:        if (ipa == NULL)
                    776:                return ENOMEM;
                    777:
                    778:        bzero(ipa, sizeof(struct ipsec_acquire));
                    779:        bcopy(gw, &ipa->ipa_addr, sizeof(union sockaddr_union));
                    780:
                    781:        timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire, ipa);
                    782:
                    783:        ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
                    784:        ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
                    785:
                    786:        /* Just copy the right information. */
                    787:        switch (ipo->ipo_addr.sen_type) {
                    788: #ifdef INET
                    789:        case SENT_IP4:
                    790:                ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
                    791:                ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
                    792:                ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
                    793:
                    794:                if (ipo->ipo_mask.sen_ip_src.s_addr == INADDR_ANY ||
                    795:                    ipo->ipo_addr.sen_ip_src.s_addr == INADDR_ANY ||
                    796:                    ipsp_is_unspecified(ipo->ipo_dst)) {
                    797:                        ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
                    798:                        ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
                    799:                } else {
                    800:                        ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
                    801:                        ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
                    802:                }
                    803:
                    804:                if (ipo->ipo_mask.sen_ip_dst.s_addr == INADDR_ANY ||
                    805:                    ipo->ipo_addr.sen_ip_dst.s_addr == INADDR_ANY ||
                    806:                    ipsp_is_unspecified(ipo->ipo_dst)) {
                    807:                        ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
                    808:                        ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
                    809:                } else {
                    810:                        ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
                    811:                        ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
                    812:                }
                    813:
                    814:                ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
                    815:                ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
                    816:
                    817:                if (ipo->ipo_addr.sen_proto) {
                    818:                        ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
                    819:                        ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
                    820:
                    821:                        ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
                    822:                        ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
                    823:                }
                    824:                break;
                    825: #endif /* INET */
                    826:
                    827: #ifdef INET6
                    828:        case SENT_IP6:
                    829:                ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
                    830:                ipa->ipa_info.sen_ip6_direction =
                    831:                    ipo->ipo_addr.sen_ip6_direction;
                    832:                ipa->ipa_mask.sen_ip6_direction =
                    833:                    ipo->ipo_mask.sen_ip6_direction;
                    834:
                    835:                if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_src) ||
                    836:                    IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_src) ||
                    837:                    ipsp_is_unspecified(ipo->ipo_dst)) {
                    838:                        ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
                    839:                        ipa->ipa_mask.sen_ip6_src = in6mask128;
                    840:                } else {
                    841:                        ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
                    842:                        ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
                    843:                }
                    844:
                    845:                if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_mask.sen_ip6_dst) ||
                    846:                    IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_addr.sen_ip6_dst) ||
                    847:                    ipsp_is_unspecified(ipo->ipo_dst)) {
                    848:                        ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
                    849:                        ipa->ipa_mask.sen_ip6_dst = in6mask128;
                    850:                } else {
                    851:                        ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
                    852:                        ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
                    853:                }
                    854:
                    855:                ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
                    856:                ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
                    857:
                    858:                if (ipo->ipo_mask.sen_ip6_proto) {
                    859:                        ipa->ipa_info.sen_ip6_sport =
                    860:                            ipo->ipo_addr.sen_ip6_sport;
                    861:                        ipa->ipa_mask.sen_ip6_sport =
                    862:                            ipo->ipo_mask.sen_ip6_sport;
                    863:                        ipa->ipa_info.sen_ip6_dport =
                    864:                            ipo->ipo_addr.sen_ip6_dport;
                    865:                        ipa->ipa_mask.sen_ip6_dport =
                    866:                            ipo->ipo_mask.sen_ip6_dport;
                    867:                }
                    868:                break;
                    869: #endif /* INET6 */
                    870:
                    871:        default:
                    872:                pool_put(&ipsec_acquire_pool, ipa);
                    873:                return 0;
                    874:        }
                    875:
                    876:        timeout_add(&ipa->ipa_timeout, ipsec_expire_acquire * hz);
                    877:
                    878:        TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
                    879:        TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
                    880:        ipa->ipa_policy = ipo;
                    881:
                    882:        /* PF_KEYv2 notification message. */
                    883:        return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
                    884: }
                    885:
                    886: /*
                    887:  * Deal with PCB security requirements.
                    888:  */
                    889: struct tdb *
                    890: ipsp_spd_inp(struct mbuf *m, int af, int hlen, int *error, int direction,
                    891:     struct tdb *tdbp, struct inpcb *inp, struct ipsec_policy *ipo)
                    892: {
                    893:        struct ipsec_policy sipon;
                    894:        struct tdb_ident *tdbi;
                    895:        struct m_tag *mtag;
                    896:        struct tdb *tdb = NULL;
                    897:
                    898:        /* Sanity check. */
                    899:        if (inp == NULL)
                    900:                goto justreturn;
                    901:
                    902:        /* Verify that we need to check for socket policy. */
                    903:        if ((inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS ||
                    904:            inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_NONE) &&
                    905:            (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS ||
                    906:            inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_NONE) &&
                    907:            (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS ||
                    908:            inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_NONE))
                    909:                goto justreturn;
                    910:
                    911:        switch (direction) {
                    912:        case IPSP_DIRECTION_IN:
                    913:                /*
                    914:                 * Some further checking: if the socket has specified
                    915:                 * that it will accept unencrypted traffic, don't
                    916:                 * bother checking any further -- just accept the packet.
                    917:                 */
                    918:                if ((inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_AVAIL ||
                    919:                    inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_USE) &&
                    920:                    (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_AVAIL ||
                    921:                    inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_USE) &&
                    922:                    (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_AVAIL ||
                    923:                    inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_USE))
                    924:                        goto justreturn;
                    925:
                    926:                /* Initialize socket policy if unset. */
                    927:                if (inp->inp_ipo == NULL) {
                    928:                        inp->inp_ipo = ipsec_add_policy(inp, af,
                    929:                            IPSP_DIRECTION_OUT);
                    930:                        if (inp->inp_ipo == NULL) {
                    931:                                *error = ENOBUFS;
                    932:                                return NULL;
                    933:                        }
                    934:                }
                    935:
                    936:                /*
                    937:                 * So we *must* have protected traffic. Let's see what
                    938:                 * we have received then.
                    939:                 */
                    940:                if (inp->inp_tdb_in != NULL) {
                    941:                        if (inp->inp_tdb_in == tdbp)
                    942:                                goto justreturn; /* We received packet under a
                    943:                                                  * previously-accepted TDB. */
                    944:
                    945:                        /*
                    946:                         * We should be receiving protected traffic, and
                    947:                         * have an SA in place, but packet was received
                    948:                         * unprotected. Simply discard.
                    949:                         */
                    950:                        if (tdbp == NULL) {
                    951:                                *error = -EINVAL;
                    952:                                return NULL;
                    953:                        }
                    954:
                    955:                        /* Update, since we may need all the relevant info. */
                    956:                        ipsec_update_policy(inp, inp->inp_ipo, af,
                    957:                            IPSP_DIRECTION_OUT);
                    958:
                    959:                        /*
                    960:                         * Check that the TDB the packet was received under
                    961:                         * is acceptable under the socket policy. If so,
                    962:                         * accept the packet; otherwise, discard.
                    963:                         */
                    964:                        if (tdbp->tdb_sproto == inp->inp_ipo->ipo_sproto &&
                    965:                            !bcmp(&tdbp->tdb_src, &inp->inp_ipo->ipo_dst,
                    966:                                SA_LEN(&tdbp->tdb_src.sa)) &&
                    967:                            ipsp_aux_match(tdbp,
                    968:                                inp->inp_ipo->ipo_srcid,
                    969:                                inp->inp_ipo->ipo_dstid,
                    970:                                NULL, NULL,
                    971:                                &inp->inp_ipo->ipo_addr,
                    972:                                &inp->inp_ipo->ipo_mask))
                    973:                                goto justreturn;
                    974:                        else {
                    975:                                *error = -EINVAL;
                    976:                                return NULL;
                    977:                        }
                    978:                } else {
                    979:                        /* Update, since we may need all the relevant info. */
                    980:                        ipsec_update_policy(inp, inp->inp_ipo, af,
                    981:                            IPSP_DIRECTION_OUT);
                    982:
                    983:                        /*
                    984:                         * If the packet was received under an SA, see if
                    985:                         * it's acceptable under socket policy. If it is,
                    986:                         * accept the packet.
                    987:                         */
                    988:                        if (tdbp != NULL &&
                    989:                            tdbp->tdb_sproto == inp->inp_ipo->ipo_sproto &&
                    990:                            !bcmp(&tdbp->tdb_src, &inp->inp_ipo->ipo_dst,
                    991:                                SA_LEN(&tdbp->tdb_src.sa)) &&
                    992:                            ipsp_aux_match(tdbp,
                    993:                                inp->inp_ipo->ipo_srcid,
                    994:                                inp->inp_ipo->ipo_dstid,
                    995:                                NULL, NULL,
                    996:                                &inp->inp_ipo->ipo_addr,
                    997:                                &inp->inp_ipo->ipo_mask))
                    998:                                goto justreturn;
                    999:
                   1000:                        /*
                   1001:                         * If the packet was not received under an SA, or
                   1002:                         * if the SA it was received under is not acceptable,
                   1003:                         * see if we already have an acceptable SA
                   1004:                         * established. If we do, discard packet.
                   1005:                         */
                   1006:                        if (inp->inp_ipo->ipo_last_searched <=
                   1007:                            ipsec_last_added) {
                   1008:                                inp->inp_ipo->ipo_last_searched = time_second;
                   1009:
                   1010:                                /* Do we have an SA already established ? */
                   1011:                                if (gettdbbysrc(&inp->inp_ipo->ipo_dst,
                   1012:                                    inp->inp_ipo->ipo_sproto,
                   1013:                                    inp->inp_ipo->ipo_srcid,
                   1014:                                    inp->inp_ipo->ipo_dstid, m, af,
                   1015:                                    &inp->inp_ipo->ipo_addr,
                   1016:                                    &inp->inp_ipo->ipo_mask) != NULL) {
                   1017:                                        *error = -EINVAL;
                   1018:                                        return NULL;
                   1019:                                }
                   1020:                                /* Fall through */
                   1021:                        }
                   1022:
                   1023:                        /*
                   1024:                         * If we don't have an appropriate SA, acquire one
                   1025:                         * and discard the packet.
                   1026:                         */
                   1027:                        ipsp_acquire_sa(inp->inp_ipo, &inp->inp_ipo->ipo_dst,
                   1028:                            &inp->inp_ipo->ipo_src, &inp->inp_ipo->ipo_addr, m);
                   1029:                        *error = -EINVAL;
                   1030:                        return NULL;
                   1031:                }
                   1032:
                   1033:                break;
                   1034:
                   1035:        case IPSP_DIRECTION_OUT:
                   1036:                /* Do we have a cached entry ? */
                   1037:                if (inp->inp_tdb_out != NULL) {
                   1038:                        /*
                   1039:                         * If we also have to apply a different TDB as
                   1040:                         * a result of a system-wide policy, add a tag
                   1041:                         * to the packet.
                   1042:                         */
                   1043:                        if (ipo != NULL && m != NULL &&
                   1044:                            ipo->ipo_tdb != NULL &&
                   1045:                            ipo->ipo_tdb != inp->inp_tdb_out) {
                   1046:                                tdb = inp->inp_tdb_out;
                   1047:                                goto tagandreturn;
                   1048:                        } else
                   1049:                                return inp->inp_tdb_out;
                   1050:                }
                   1051:
                   1052:                /*
                   1053:                 * We need to either find an SA with the appropriate
                   1054:                 * characteristics and link it to the PCB, or acquire
                   1055:                 * one.
                   1056:                 */
                   1057:                /* XXX Only support one policy/protocol for now. */
                   1058:                if (inp->inp_ipo != NULL) {
                   1059:                        if (inp->inp_ipo->ipo_last_searched <=
                   1060:                            ipsec_last_added) {
                   1061:                                inp->inp_ipo->ipo_last_searched = time_second;
                   1062:
                   1063:                                /* Update, just in case. */
                   1064:                                ipsec_update_policy(inp, inp->inp_ipo, af,
                   1065:                                    IPSP_DIRECTION_OUT);
                   1066:
                   1067:                                tdb = gettdbbyaddr(&inp->inp_ipo->ipo_dst,
                   1068:                                    inp->inp_ipo->ipo_sproto,
                   1069:                                    inp->inp_ipo->ipo_srcid,
                   1070:                                    inp->inp_ipo->ipo_dstid,
                   1071:                                    inp->inp_ipo->ipo_local_cred, m, af,
                   1072:                                    &inp->inp_ipo->ipo_addr,
                   1073:                                    &inp->inp_ipo->ipo_mask);
                   1074:                        }
                   1075:                } else {
                   1076:                        /*
                   1077:                         * Construct a pseudo-policy, with just the necessary
                   1078:                         * fields.
                   1079:                         */
                   1080:                        ipsec_update_policy(inp, &sipon, af,
                   1081:                            IPSP_DIRECTION_OUT);
                   1082:
                   1083:                        tdb = gettdbbyaddr(&sipon.ipo_dst, IPPROTO_ESP, NULL,
                   1084:                            NULL, NULL, m, af, &sipon.ipo_addr,
                   1085:                            &sipon.ipo_mask);
                   1086:                }
                   1087:
                   1088:                /* If we found an appropriate SA... */
                   1089:                if (tdb != NULL) {
                   1090:                        tdb_add_inp(tdb, inp, 0); /* Latch onto PCB. */
                   1091:
                   1092:                        if (ipo != NULL && ipo->ipo_tdb != NULL &&
                   1093:                            ipo->ipo_tdb != inp->inp_tdb_out && m != NULL)
                   1094:                                goto tagandreturn;
                   1095:                        else
                   1096:                                return tdb;
                   1097:                } else {
                   1098:                        /* Do we need to acquire one ? */
                   1099:                        switch (inp->inp_seclevel[SL_ESP_TRANS]) {
                   1100:                        case IPSEC_LEVEL_BYPASS:
                   1101:                        case IPSEC_LEVEL_AVAIL:
                   1102:                                /* No need to do anything. */
                   1103:                                goto justreturn;
                   1104:                        case IPSEC_LEVEL_USE:
                   1105:                        case IPSEC_LEVEL_REQUIRE:
                   1106:                        case IPSEC_LEVEL_UNIQUE:
                   1107:                                /* Initialize socket policy if unset. */
                   1108:                                if (inp->inp_ipo == NULL) {
                   1109:                                        inp->inp_ipo = ipsec_add_policy(inp, af, IPSP_DIRECTION_OUT);
                   1110:                                        if (inp->inp_ipo == NULL) {
                   1111:                                                *error = ENOBUFS;
                   1112:                                                return NULL;
                   1113:                                        }
                   1114:                                }
                   1115:
                   1116:                                /* Acquire a new SA. */
                   1117:                                if ((*error = ipsp_acquire_sa(inp->inp_ipo,
                   1118:                                    &inp->inp_ipo->ipo_dst,
                   1119:                                    &inp->inp_ipo->ipo_src,
                   1120:                                    &inp->inp_ipo->ipo_addr, m)) == 0)
                   1121:                                        *error = -EINVAL;
                   1122:
                   1123:                                return NULL;
                   1124:                        default:
                   1125:                                DPRINTF(("ipsp_spd_inp: unknown sock security"
                   1126:                                    " level %d",
                   1127:                                    inp->inp_seclevel[SL_ESP_TRANS]));
                   1128:                                *error = -EINVAL;
                   1129:                                return NULL;
                   1130:                        }
                   1131:                }
                   1132:                break;
                   1133:
                   1134:        default:  /* Should never happen. */
                   1135:                *error = -EINVAL;
                   1136:                return NULL;
                   1137:        }
                   1138:
                   1139:  tagandreturn:
                   1140:        if (tdb == NULL)
                   1141:                goto justreturn;
                   1142:
                   1143:        mtag = m_tag_get(PACKET_TAG_IPSEC_PENDING_TDB,
                   1144:            sizeof (struct tdb_ident), M_NOWAIT);
                   1145:        if (mtag == NULL) {
                   1146:                *error = ENOMEM;
                   1147:                return NULL;
                   1148:        }
                   1149:
                   1150:        tdbi = (struct tdb_ident *)(mtag + 1);
                   1151:        tdbi->spi = ipo->ipo_tdb->tdb_spi;
                   1152:        tdbi->proto = ipo->ipo_tdb->tdb_sproto;
                   1153:        bcopy(&ipo->ipo_tdb->tdb_dst, &tdbi->dst,
                   1154:            ipo->ipo_tdb->tdb_dst.sa.sa_len);
                   1155:        m_tag_prepend(m, mtag);
                   1156:        return tdb;
                   1157:
                   1158:  justreturn:
                   1159:        if (ipo != NULL)
                   1160:                return ipo->ipo_tdb;
                   1161:        else
                   1162:                return NULL;
                   1163: }
                   1164:
                   1165: /*
                   1166:  * Find a pending ACQUIRE record based on its sequence number.
                   1167:  * XXX Need to use a better data structure.
                   1168:  */
                   1169: struct ipsec_acquire *
                   1170: ipsec_get_acquire(u_int32_t seq)
                   1171: {
                   1172:        struct ipsec_acquire *ipa;
                   1173:
                   1174:        TAILQ_FOREACH (ipa, &ipsec_acquire_head, ipa_next)
                   1175:                if (ipa->ipa_seq == seq)
                   1176:                        return ipa;
                   1177:
                   1178:        return NULL;
                   1179: }

CVSweb