The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/ip_spd.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $OpenBSD: ip_spd.c,v 1.117 2022/06/17 13:40:21 bluhm 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/pool.h>
   30 #include <sys/timeout.h>
   31 
   32 #include <net/route.h>
   33 #include <net/netisr.h>
   34 
   35 #include <netinet/in.h>
   36 #include <netinet/ip.h>
   37 #include <netinet/ip_var.h>
   38 #include <netinet/in_pcb.h>
   39 #include <netinet/ip_ipsp.h>
   40 #include <net/pfkeyv2.h>
   41 
   42 int     ipsp_spd_inp(struct mbuf *, struct inpcb *, struct ipsec_policy *,
   43             struct tdb **);
   44 int     ipsp_acquire_sa(struct ipsec_policy *, union sockaddr_union *,
   45             union sockaddr_union *, struct sockaddr_encap *, struct mbuf *);
   46 int     ipsp_pending_acquire(struct ipsec_policy *, union sockaddr_union *);
   47 void    ipsp_delete_acquire_timer(void *);
   48 void    ipsp_delete_acquire_locked(struct ipsec_acquire *);
   49 void    ipsp_delete_acquire(struct ipsec_acquire *);
   50 void    ipsp_unref_acquire_locked(struct ipsec_acquire *);
   51 
   52 struct pool ipsec_policy_pool;
   53 struct pool ipsec_acquire_pool;
   54 
   55 /*
   56  * For tdb_walk() calling tdb_delete_locked() we need lock order
   57  * tdb_sadb_mtx before ipo_tdb_mtx.
   58  */
   59 struct mutex ipo_tdb_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
   60 
   61 /* Protected by the NET_LOCK(). */
   62 struct radix_node_head **spd_tables;
   63 unsigned int spd_table_max;
   64 
   65 struct mutex ipsec_acquire_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
   66 struct ipsec_acquire_head ipsec_acquire_head =
   67     TAILQ_HEAD_INITIALIZER(ipsec_acquire_head);
   68 
   69 struct radix_node_head *
   70 spd_table_get(unsigned int rtableid)
   71 {
   72         unsigned int rdomain;
   73 
   74         NET_ASSERT_LOCKED();
   75 
   76         if (spd_tables == NULL)
   77                 return (NULL);
   78 
   79         rdomain = rtable_l2(rtableid);
   80         if (rdomain > spd_table_max)
   81                 return (NULL);
   82 
   83         return (spd_tables[rdomain]);
   84 }
   85 
   86 struct radix_node_head *
   87 spd_table_add(unsigned int rtableid)
   88 {
   89         struct radix_node_head *rnh = NULL;
   90         unsigned int rdomain;
   91         void *p;
   92 
   93         NET_ASSERT_LOCKED();
   94 
   95         rdomain = rtable_l2(rtableid);
   96         if (spd_tables == NULL || rdomain > spd_table_max) {
   97                 if ((p = mallocarray(rdomain + 1, sizeof(*rnh),
   98                     M_RTABLE, M_NOWAIT|M_ZERO)) == NULL)
   99                         return (NULL);
  100 
  101                 if (spd_tables != NULL) {
  102                         memcpy(p, spd_tables, sizeof(*rnh) * (spd_table_max+1));
  103                         free(spd_tables, M_RTABLE,
  104                             sizeof(*rnh) * (spd_table_max+1));
  105                 }
  106                 spd_tables = p;
  107                 spd_table_max = rdomain;
  108         }
  109 
  110         if (spd_tables[rdomain] == NULL) {
  111                 if (rn_inithead((void **)&rnh,
  112                     offsetof(struct sockaddr_encap, sen_type)) == 0)
  113                         rnh = NULL;
  114                 spd_tables[rdomain] = rnh;
  115         }
  116 
  117         return (spd_tables[rdomain]);
  118 }
  119 
  120 int
  121 spd_table_walk(unsigned int rtableid,
  122     int (*func)(struct ipsec_policy *, void *, unsigned int), void *arg)
  123 {
  124         struct radix_node_head *rnh;
  125         int (*walker)(struct radix_node *, void *, u_int) = (void *)func;
  126         int error;
  127 
  128         rnh = spd_table_get(rtableid);
  129         if (rnh == NULL)
  130                 return (0);
  131 
  132         /* EGAIN means the tree changed. */
  133         while ((error = rn_walktree(rnh, walker, arg)) == EAGAIN)
  134                 continue;
  135 
  136         return (error);
  137 }
  138 
  139 /*
  140  * Lookup at the SPD based on the headers contained on the mbuf. The second
  141  * argument indicates what protocol family the header at the beginning of
  142  * the mbuf is. hlen is the offset of the transport protocol header
  143  * in the mbuf.
  144  *
  145  * Return combinations (of return value and *tdbout):
  146  * - -EINVAL -> silently drop the packet
  147  * - errno   -> drop packet and return error
  148  * - 0/NULL  -> no IPsec required on packet
  149  * - 0/TDB   -> do IPsec
  150  *
  151  * In the case of incoming flows, only the first three combinations are
  152  * returned.
  153  */
  154 int
  155 ipsp_spd_lookup(struct mbuf *m, int af, int hlen, int direction,
  156     struct tdb *tdbin, struct inpcb *inp, struct tdb **tdbout,
  157     struct ipsec_ids *ipsecflowinfo_ids)
  158 {
  159         struct radix_node_head *rnh;
  160         struct radix_node *rn;
  161         union sockaddr_union sdst, ssrc;
  162         struct sockaddr_encap *ddst, dst;
  163         struct ipsec_policy *ipo;
  164         struct ipsec_ids *ids = NULL;
  165         int error, signore = 0, dignore = 0;
  166         u_int rdomain;
  167 
  168         NET_ASSERT_LOCKED();
  169 
  170         /*
  171          * If there are no flows in place, there's no point
  172          * continuing with the SPD lookup.
  173          */
  174         if (!ipsec_in_use)
  175                 return ipsp_spd_inp(m, inp, NULL, tdbout);
  176 
  177         /*
  178          * If an input packet is destined to a BYPASS socket, just accept it.
  179          */
  180         if ((inp != NULL) && (direction == IPSP_DIRECTION_IN) &&
  181             (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
  182             (inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS) &&
  183             (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
  184                 if (tdbout != NULL)
  185                         *tdbout = NULL;
  186                 return 0;
  187         }
  188 
  189         memset(&dst, 0, sizeof(dst));
  190         memset(&sdst, 0, sizeof(union sockaddr_union));
  191         memset(&ssrc, 0, sizeof(union sockaddr_union));
  192         ddst = (struct sockaddr_encap *)&dst;
  193         ddst->sen_family = PF_KEY;
  194         ddst->sen_len = SENT_LEN;
  195 
  196         switch (af) {
  197         case AF_INET:
  198                 if (hlen < sizeof (struct ip) || m->m_pkthdr.len < hlen)
  199                         return EINVAL;
  200 
  201                 ddst->sen_direction = direction;
  202                 ddst->sen_type = SENT_IP4;
  203 
  204                 m_copydata(m, offsetof(struct ip, ip_src),
  205                     sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_src));
  206                 m_copydata(m, offsetof(struct ip, ip_dst),
  207                     sizeof(struct in_addr), (caddr_t) &(ddst->sen_ip_dst));
  208                 m_copydata(m, offsetof(struct ip, ip_p), sizeof(u_int8_t),
  209                     (caddr_t) &(ddst->sen_proto));
  210 
  211                 sdst.sin.sin_family = ssrc.sin.sin_family = AF_INET;
  212                 sdst.sin.sin_len = ssrc.sin.sin_len =
  213                     sizeof(struct sockaddr_in);
  214                 ssrc.sin.sin_addr = ddst->sen_ip_src;
  215                 sdst.sin.sin_addr = ddst->sen_ip_dst;
  216 
  217                 /*
  218                  * If TCP/UDP, extract the port numbers to use in the lookup.
  219                  */
  220                 switch (ddst->sen_proto) {
  221                 case IPPROTO_UDP:
  222                 case IPPROTO_TCP:
  223                         /* Make sure there's enough data in the packet. */
  224                         if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t))
  225                                 return EINVAL;
  226 
  227                         /*
  228                          * Luckily, the offset of the src/dst ports in
  229                          * both the UDP and TCP headers is the same (first
  230                          * two 16-bit values in the respective headers),
  231                          * so we can just copy them.
  232                          */
  233                         m_copydata(m, hlen, sizeof(u_int16_t),
  234                             (caddr_t) &(ddst->sen_sport));
  235                         m_copydata(m, hlen + sizeof(u_int16_t),
  236                             sizeof(u_int16_t),
  237                             (caddr_t) &(ddst->sen_dport));
  238                         break;
  239 
  240                 default:
  241                         ddst->sen_sport = 0;
  242                         ddst->sen_dport = 0;
  243                 }
  244 
  245                 break;
  246 
  247 #ifdef INET6
  248         case AF_INET6:
  249                 if (hlen < sizeof (struct ip6_hdr) || m->m_pkthdr.len < hlen)
  250                         return EINVAL;
  251 
  252                 ddst->sen_type = SENT_IP6;
  253                 ddst->sen_ip6_direction = direction;
  254 
  255                 m_copydata(m, offsetof(struct ip6_hdr, ip6_src),
  256                     sizeof(struct in6_addr),
  257                     (caddr_t) &(ddst->sen_ip6_src));
  258                 m_copydata(m, offsetof(struct ip6_hdr, ip6_dst),
  259                     sizeof(struct in6_addr),
  260                     (caddr_t) &(ddst->sen_ip6_dst));
  261                 m_copydata(m, offsetof(struct ip6_hdr, ip6_nxt),
  262                     sizeof(u_int8_t),
  263                     (caddr_t) &(ddst->sen_ip6_proto));
  264 
  265                 sdst.sin6.sin6_family = ssrc.sin6.sin6_family = AF_INET6;
  266                 sdst.sin6.sin6_len = ssrc.sin6.sin6_len =
  267                     sizeof(struct sockaddr_in6);
  268                 in6_recoverscope(&ssrc.sin6, &ddst->sen_ip6_src);
  269                 in6_recoverscope(&sdst.sin6, &ddst->sen_ip6_dst);
  270 
  271                 /*
  272                  * If TCP/UDP, extract the port numbers to use in the lookup.
  273                  */
  274                 switch (ddst->sen_ip6_proto) {
  275                 case IPPROTO_UDP:
  276                 case IPPROTO_TCP:
  277                         /* Make sure there's enough data in the packet. */
  278                         if (m->m_pkthdr.len < hlen + 2 * sizeof(u_int16_t))
  279                                 return EINVAL;
  280 
  281                         /*
  282                          * Luckily, the offset of the src/dst ports in
  283                          * both the UDP and TCP headers is the same
  284                          * (first two 16-bit values in the respective
  285                          * headers), so we can just copy them.
  286                          */
  287                         m_copydata(m, hlen, sizeof(u_int16_t),
  288                             (caddr_t) &(ddst->sen_ip6_sport));
  289                         m_copydata(m, hlen + sizeof(u_int16_t),
  290                             sizeof(u_int16_t),
  291                             (caddr_t) &(ddst->sen_ip6_dport));
  292                         break;
  293 
  294                 default:
  295                         ddst->sen_ip6_sport = 0;
  296                         ddst->sen_ip6_dport = 0;
  297                 }
  298 
  299                 break;
  300 #endif /* INET6 */
  301 
  302         default:
  303                 return EAFNOSUPPORT;
  304         }
  305 
  306         /* Actual SPD lookup. */
  307         rdomain = rtable_l2(m->m_pkthdr.ph_rtableid);
  308         if ((rnh = spd_table_get(rdomain)) == NULL ||
  309             (rn = rn_match((caddr_t)&dst, rnh)) == NULL) {
  310                 /*
  311                  * Return whatever the socket requirements are, there are no
  312                  * system-wide policies.
  313                  */
  314                 return ipsp_spd_inp(m, inp, NULL, tdbout);
  315         }
  316         ipo = (struct ipsec_policy *)rn;
  317 
  318         switch (ipo->ipo_type) {
  319         case IPSP_PERMIT:
  320                 return ipsp_spd_inp(m, inp, ipo, tdbout);
  321 
  322         case IPSP_DENY:
  323                 return EHOSTUNREACH;
  324 
  325         case IPSP_IPSEC_USE:
  326         case IPSP_IPSEC_ACQUIRE:
  327         case IPSP_IPSEC_REQUIRE:
  328         case IPSP_IPSEC_DONTACQ:
  329                 /* Nothing more needed here. */
  330                 break;
  331 
  332         default:
  333                 return EINVAL;
  334         }
  335 
  336         /* Check for non-specific destination in the policy. */
  337         switch (ipo->ipo_dst.sa.sa_family) {
  338         case AF_INET:
  339                 if ((ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_ANY) ||
  340                     (ipo->ipo_dst.sin.sin_addr.s_addr == INADDR_BROADCAST))
  341                         dignore = 1;
  342                 break;
  343 
  344 #ifdef INET6
  345         case AF_INET6:
  346                 if ((IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_dst.sin6.sin6_addr)) ||
  347                     (memcmp(&ipo->ipo_dst.sin6.sin6_addr, &in6mask128,
  348                     sizeof(in6mask128)) == 0))
  349                         dignore = 1;
  350                 break;
  351 #endif /* INET6 */
  352         }
  353 
  354         /* Likewise for source. */
  355         switch (ipo->ipo_src.sa.sa_family) {
  356         case AF_INET:
  357                 if (ipo->ipo_src.sin.sin_addr.s_addr == INADDR_ANY)
  358                         signore = 1;
  359                 break;
  360 
  361 #ifdef INET6
  362         case AF_INET6:
  363                 if (IN6_IS_ADDR_UNSPECIFIED(&ipo->ipo_src.sin6.sin6_addr))
  364                         signore = 1;
  365                 break;
  366 #endif /* INET6 */
  367         }
  368 
  369         /* Do we have a cached entry ? If so, check if it's still valid. */
  370         mtx_enter(&ipo_tdb_mtx);
  371         if (ipo->ipo_tdb != NULL &&
  372             (ipo->ipo_tdb->tdb_flags & TDBF_INVALID)) {
  373                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
  374                     ipo_tdb_next);
  375                 tdb_unref(ipo->ipo_tdb);
  376                 ipo->ipo_tdb = NULL;
  377         }
  378         mtx_leave(&ipo_tdb_mtx);
  379 
  380         /* Outgoing packet policy check. */
  381         if (direction == IPSP_DIRECTION_OUT) {
  382                 /*
  383                  * If the packet is destined for the policy-specified
  384                  * gateway/endhost, and the socket has the BYPASS
  385                  * option set, skip IPsec processing.
  386                  */
  387                 if ((inp != NULL) &&
  388                     (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS) &&
  389                     (inp->inp_seclevel[SL_ESP_NETWORK] ==
  390                         IPSEC_LEVEL_BYPASS) &&
  391                     (inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)) {
  392                         /* Direct match. */
  393                         if (dignore ||
  394                             !memcmp(&sdst, &ipo->ipo_dst, sdst.sa.sa_len)) {
  395                                 if (tdbout != NULL)
  396                                         *tdbout = NULL;
  397                                 return 0;
  398                         }
  399                 }
  400 
  401                 /* Check that the cached TDB (if present), is appropriate. */
  402                 mtx_enter(&ipo_tdb_mtx);
  403                 if (ipo->ipo_tdb != NULL) {
  404                         if ((ipo->ipo_last_searched <= ipsec_last_added) ||
  405                             (ipo->ipo_sproto != ipo->ipo_tdb->tdb_sproto) ||
  406                             memcmp(dignore ? &sdst : &ipo->ipo_dst,
  407                             &ipo->ipo_tdb->tdb_dst,
  408                             ipo->ipo_tdb->tdb_dst.sa.sa_len))
  409                                 goto nomatchout;
  410 
  411                         if (!ipsp_aux_match(ipo->ipo_tdb,
  412                             ipsecflowinfo_ids? ipsecflowinfo_ids: ipo->ipo_ids,
  413                             &ipo->ipo_addr, &ipo->ipo_mask))
  414                                 goto nomatchout;
  415 
  416                         /* Cached entry is good. */
  417                         error = ipsp_spd_inp(m, inp, ipo, tdbout);
  418                         mtx_leave(&ipo_tdb_mtx);
  419                         return error;
  420 
  421   nomatchout:
  422                         /* Cached TDB was not good. */
  423                         TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
  424                             ipo_tdb_next);
  425                         tdb_unref(ipo->ipo_tdb);
  426                         ipo->ipo_tdb = NULL;
  427                         ipo->ipo_last_searched = 0;
  428                 }
  429 
  430                 /*
  431                  * If no SA has been added since the last time we did a
  432                  * lookup, there's no point searching for one. However, if the
  433                  * destination gateway is left unspecified (or is all-1's),
  434                  * always lookup since this is a generic-match rule
  435                  * (otherwise, we can have situations where SAs to some
  436                  * destinations exist but are not used, possibly leading to an
  437                  * explosion in the number of acquired SAs).
  438                  */
  439                 if (ipo->ipo_last_searched <= ipsec_last_added) {
  440                         struct tdb *tdbp_new;
  441 
  442                         /* "Touch" the entry. */
  443                         if (dignore == 0)
  444                                 ipo->ipo_last_searched = getuptime();
  445 
  446                         /* gettdb() takes tdb_sadb_mtx, preserve lock order */
  447                         mtx_leave(&ipo_tdb_mtx);
  448                         /* Find an appropriate SA from the existing ones. */
  449                         tdbp_new = gettdbbydst(rdomain,
  450                             dignore ? &sdst : &ipo->ipo_dst,
  451                             ipo->ipo_sproto,
  452                             ipsecflowinfo_ids? ipsecflowinfo_ids: ipo->ipo_ids,
  453                             &ipo->ipo_addr, &ipo->ipo_mask);
  454                         ids = NULL;
  455                         mtx_enter(&ipo_tdb_mtx);
  456                         if ((tdbp_new != NULL) &&
  457                             (tdbp_new->tdb_flags & TDBF_DELETED)) {
  458                                 /*
  459                                  * After tdb_delete() has released ipo_tdb_mtx
  460                                  * in tdb_unlink(), never add a new one.
  461                                  * tdb_cleanspd() has to catch all of them.
  462                                  */
  463                                 tdb_unref(tdbp_new);
  464                                 tdbp_new = NULL;
  465                         }
  466                         if (ipo->ipo_tdb != NULL) {
  467                                 /* Remove cached TDB from parallel thread. */
  468                                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
  469                                     ipo, ipo_tdb_next);
  470                                 tdb_unref(ipo->ipo_tdb);
  471                         }
  472                         ipo->ipo_tdb = tdbp_new;
  473                         if (ipo->ipo_tdb != NULL) {
  474                                 /* gettdbbydst() has already refcounted tdb */
  475                                 TAILQ_INSERT_TAIL(
  476                                     &ipo->ipo_tdb->tdb_policy_head,
  477                                     ipo, ipo_tdb_next);
  478                                 error = ipsp_spd_inp(m, inp, ipo, tdbout);
  479                                 mtx_leave(&ipo_tdb_mtx);
  480                                 return error;
  481                         }
  482                 }
  483                 mtx_leave(&ipo_tdb_mtx);
  484 
  485                 /* So, we don't have an SA -- just a policy. */
  486                 switch (ipo->ipo_type) {
  487                 case IPSP_IPSEC_REQUIRE:
  488                         /* Acquire SA through key management. */
  489                         if (ipsp_acquire_sa(ipo,
  490                             dignore ? &sdst : &ipo->ipo_dst,
  491                             signore ? NULL : &ipo->ipo_src, ddst, m) != 0) {
  492                                 return EACCES;
  493                         }
  494 
  495                         /* FALLTHROUGH */
  496                 case IPSP_IPSEC_DONTACQ:
  497                         return -EINVAL;  /* Silently drop packet. */
  498 
  499                 case IPSP_IPSEC_ACQUIRE:
  500                         /* Acquire SA through key management. */
  501                         ipsp_acquire_sa(ipo, dignore ? &sdst : &ipo->ipo_dst,
  502                             signore ? NULL : &ipo->ipo_src, ddst, NULL);
  503 
  504                         /* FALLTHROUGH */
  505                 case IPSP_IPSEC_USE:
  506                         return ipsp_spd_inp(m, inp, ipo, tdbout);
  507                 }
  508         } else { /* IPSP_DIRECTION_IN */
  509                 if (tdbin != NULL) {
  510                         /*
  511                          * Special case for bundled IPcomp/ESP SAs:
  512                          * 1) only IPcomp flows are loaded into kernel
  513                          * 2) input processing processes ESP SA first
  514                          * 3) then optional IPcomp processing happens
  515                          * 4) we only update m_tag for ESP
  516                          * => 'tdbin' is always set to ESP SA
  517                          * => flow has ipo_proto for IPcomp
  518                          * So if 'tdbin' points to an ESP SA and this 'tdbin' is
  519                          * bundled with an IPcomp SA, then we replace 'tdbin'
  520                          * with the IPcomp SA at tdbin->tdb_inext.
  521                          */
  522                         if (ipo->ipo_sproto == IPPROTO_IPCOMP &&
  523                             tdbin->tdb_sproto == IPPROTO_ESP &&
  524                             tdbin->tdb_inext != NULL &&
  525                             tdbin->tdb_inext->tdb_sproto == IPPROTO_IPCOMP)
  526                                 tdbin = tdbin->tdb_inext;
  527 
  528                         /* Direct match in the cache. */
  529                         mtx_enter(&ipo_tdb_mtx);
  530                         if (ipo->ipo_tdb == tdbin) {
  531                                 error = ipsp_spd_inp(m, inp, ipo, tdbout);
  532                                 mtx_leave(&ipo_tdb_mtx);
  533                                 return error;
  534                         }
  535                         mtx_leave(&ipo_tdb_mtx);
  536 
  537                         if (memcmp(dignore ? &ssrc : &ipo->ipo_dst,
  538                             &tdbin->tdb_src, tdbin->tdb_src.sa.sa_len) ||
  539                             (ipo->ipo_sproto != tdbin->tdb_sproto))
  540                                 goto nomatchin;
  541 
  542                         /* Match source/dest IDs. */
  543                         if (ipo->ipo_ids)
  544                                 if (tdbin->tdb_ids == NULL ||
  545                                     !ipsp_ids_match(ipo->ipo_ids,
  546                                     tdbin->tdb_ids))
  547                                         goto nomatchin;
  548 
  549                         /* Add it to the cache. */
  550                         mtx_enter(&ipo_tdb_mtx);
  551                         if (ipo->ipo_tdb != NULL) {
  552                                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
  553                                     ipo, ipo_tdb_next);
  554                                 tdb_unref(ipo->ipo_tdb);
  555                         }
  556                         ipo->ipo_tdb = tdb_ref(tdbin);
  557                         TAILQ_INSERT_TAIL(&tdbin->tdb_policy_head, ipo,
  558                             ipo_tdb_next);
  559                         error = ipsp_spd_inp(m, inp, ipo, tdbout);
  560                         mtx_leave(&ipo_tdb_mtx);
  561                         return error;
  562 
  563   nomatchin: /* Nothing needed here, falling through */
  564         ;
  565                 }
  566 
  567                 /* Check whether cached entry applies. */
  568                 mtx_enter(&ipo_tdb_mtx);
  569                 if (ipo->ipo_tdb != NULL) {
  570                         /*
  571                          * We only need to check that the correct
  572                          * security protocol and security gateway are
  573                          * set; IDs will be the same since the cached
  574                          * entry is linked on this policy.
  575                          */
  576                         if (ipo->ipo_sproto == ipo->ipo_tdb->tdb_sproto &&
  577                             !memcmp(&ipo->ipo_tdb->tdb_src,
  578                             dignore ? &ssrc : &ipo->ipo_dst,
  579                             ipo->ipo_tdb->tdb_src.sa.sa_len))
  580                                 goto skipinputsearch;
  581 
  582                         /* Not applicable, unlink. */
  583                         TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
  584                             ipo_tdb_next);
  585                         tdb_unref(ipo->ipo_tdb);
  586                         ipo->ipo_tdb = NULL;
  587                         ipo->ipo_last_searched = 0;
  588                 }
  589 
  590                 /* Find whether there exists an appropriate SA. */
  591                 if (ipo->ipo_last_searched <= ipsec_last_added) {
  592                         struct tdb *tdbp_new;
  593 
  594                         if (dignore == 0)
  595                                 ipo->ipo_last_searched = getuptime();
  596 
  597                         /* gettdb() takes tdb_sadb_mtx, preserve lock order */
  598                         mtx_leave(&ipo_tdb_mtx);
  599                         tdbp_new = gettdbbysrc(rdomain,
  600                             dignore ? &ssrc : &ipo->ipo_dst,
  601                             ipo->ipo_sproto, ipo->ipo_ids,
  602                             &ipo->ipo_addr, &ipo->ipo_mask);
  603                         mtx_enter(&ipo_tdb_mtx);
  604                         if ((tdbp_new != NULL) &&
  605                             (tdbp_new->tdb_flags & TDBF_DELETED)) {
  606                                 /*
  607                                  * After tdb_delete() has released ipo_tdb_mtx
  608                                  * in tdb_unlink(), never add a new one.
  609                                  * tdb_cleanspd() has to catch all of them.
  610                                  */
  611                                 tdb_unref(tdbp_new);
  612                                 tdbp_new = NULL;
  613                         }
  614                         if (ipo->ipo_tdb != NULL) {
  615                                 /* Remove cached TDB from parallel thread. */
  616                                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
  617                                     ipo, ipo_tdb_next);
  618                                 tdb_unref(ipo->ipo_tdb);
  619                         }
  620                         ipo->ipo_tdb = tdbp_new;
  621                         if (ipo->ipo_tdb != NULL) {
  622                                 /* gettdbbysrc() has already refcounted tdb */
  623                                 TAILQ_INSERT_TAIL(
  624                                     &ipo->ipo_tdb->tdb_policy_head,
  625                                     ipo, ipo_tdb_next);
  626                         }
  627                 }
  628   skipinputsearch:
  629                 mtx_leave(&ipo_tdb_mtx);
  630 
  631                 switch (ipo->ipo_type) {
  632                 case IPSP_IPSEC_REQUIRE:
  633                         /* If appropriate SA exists, don't acquire another. */
  634                         if (ipo->ipo_tdb != NULL)
  635                                 return -EINVAL;  /* Silently drop packet. */
  636 
  637                         /* Acquire SA through key management. */
  638                         if ((error = ipsp_acquire_sa(ipo,
  639                             dignore ? &ssrc : &ipo->ipo_dst,
  640                             signore ? NULL : &ipo->ipo_src, ddst, m)) != 0)
  641                                 return error;
  642 
  643                         /* FALLTHROUGH */
  644                 case IPSP_IPSEC_DONTACQ:
  645                         return -EINVAL;  /* Silently drop packet. */
  646 
  647                 case IPSP_IPSEC_ACQUIRE:
  648                         /* If appropriate SA exists, don't acquire another. */
  649                         if (ipo->ipo_tdb != NULL)
  650                                 return ipsp_spd_inp(m, inp, ipo, tdbout);
  651 
  652                         /* Acquire SA through key management. */
  653                         ipsp_acquire_sa(ipo, dignore ? &ssrc : &ipo->ipo_dst,
  654                             signore ? NULL : &ipo->ipo_src, ddst, NULL);
  655 
  656                         /* FALLTHROUGH */
  657                 case IPSP_IPSEC_USE:
  658                         return ipsp_spd_inp(m, inp, ipo, tdbout);
  659                 }
  660         }
  661 
  662         /* Shouldn't ever get this far. */
  663         return EINVAL;
  664 }
  665 
  666 /*
  667  * Delete a policy from the SPD.
  668  */
  669 int
  670 ipsec_delete_policy(struct ipsec_policy *ipo)
  671 {
  672         struct ipsec_acquire *ipa;
  673         struct radix_node_head *rnh;
  674         struct radix_node *rn = (struct radix_node *)ipo;
  675 
  676         NET_ASSERT_LOCKED();
  677 
  678         if (refcnt_rele(&ipo->ipo_refcnt) == 0)
  679                 return 0;
  680 
  681         /* Delete from SPD. */
  682         if ((rnh = spd_table_get(ipo->ipo_rdomain)) == NULL ||
  683             rn_delete(&ipo->ipo_addr, &ipo->ipo_mask, rnh, rn) == NULL)
  684                 return (ESRCH);
  685 
  686         mtx_enter(&ipo_tdb_mtx);
  687         if (ipo->ipo_tdb != NULL) {
  688                 TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head, ipo,
  689                     ipo_tdb_next);
  690                 tdb_unref(ipo->ipo_tdb);
  691                 ipo->ipo_tdb = NULL;
  692         }
  693         mtx_leave(&ipo_tdb_mtx);
  694 
  695         mtx_enter(&ipsec_acquire_mtx);
  696         while ((ipa = TAILQ_FIRST(&ipo->ipo_acquires)) != NULL)
  697                 ipsp_delete_acquire_locked(ipa);
  698         mtx_leave(&ipsec_acquire_mtx);
  699 
  700         TAILQ_REMOVE(&ipsec_policy_head, ipo, ipo_list);
  701 
  702         if (ipo->ipo_ids)
  703                 ipsp_ids_free(ipo->ipo_ids);
  704 
  705         ipsec_in_use--;
  706 
  707         pool_put(&ipsec_policy_pool, ipo);
  708 
  709         return 0;
  710 }
  711 
  712 void
  713 ipsp_delete_acquire_timer(void *v)
  714 {
  715         struct ipsec_acquire *ipa = v;
  716 
  717         mtx_enter(&ipsec_acquire_mtx);
  718         refcnt_rele(&ipa->ipa_refcnt);
  719         ipsp_delete_acquire_locked(ipa);
  720         mtx_leave(&ipsec_acquire_mtx);
  721 }
  722 
  723 /*
  724  * Delete a pending IPsec acquire record.
  725  */
  726 void
  727 ipsp_delete_acquire(struct ipsec_acquire *ipa)
  728 {
  729         mtx_enter(&ipsec_acquire_mtx);
  730         ipsp_delete_acquire_locked(ipa);
  731         mtx_leave(&ipsec_acquire_mtx);
  732 }
  733 
  734 void
  735 ipsp_delete_acquire_locked(struct ipsec_acquire *ipa)
  736 {
  737         if (timeout_del(&ipa->ipa_timeout) == 1)
  738                 refcnt_rele(&ipa->ipa_refcnt);
  739         ipsp_unref_acquire_locked(ipa);
  740 }
  741 
  742 void
  743 ipsec_unref_acquire(struct ipsec_acquire *ipa)
  744 {
  745         mtx_enter(&ipsec_acquire_mtx);
  746         ipsp_unref_acquire_locked(ipa);
  747         mtx_leave(&ipsec_acquire_mtx);
  748 }
  749 
  750 void
  751 ipsp_unref_acquire_locked(struct ipsec_acquire *ipa)
  752 {
  753         MUTEX_ASSERT_LOCKED(&ipsec_acquire_mtx);
  754 
  755         if (refcnt_rele(&ipa->ipa_refcnt) == 0)
  756                 return;
  757         TAILQ_REMOVE(&ipsec_acquire_head, ipa, ipa_next);
  758         TAILQ_REMOVE(&ipa->ipa_policy->ipo_acquires, ipa, ipa_ipo_next);
  759         ipa->ipa_policy = NULL;
  760 
  761         pool_put(&ipsec_acquire_pool, ipa);
  762 }
  763 
  764 /*
  765  * Find out if there's an ACQUIRE pending.
  766  * XXX Need a better structure.
  767  */
  768 int
  769 ipsp_pending_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw)
  770 {
  771         struct ipsec_acquire *ipa;
  772 
  773         NET_ASSERT_LOCKED();
  774 
  775         mtx_enter(&ipsec_acquire_mtx);
  776         TAILQ_FOREACH(ipa, &ipo->ipo_acquires, ipa_ipo_next) {
  777                 if (!memcmp(gw, &ipa->ipa_addr, gw->sa.sa_len))
  778                         break;
  779         }
  780         mtx_leave(&ipsec_acquire_mtx);
  781 
  782         return (ipa != NULL);
  783 }
  784 
  785 /*
  786  * Signal key management that we need an SA.
  787  * XXX For outgoing policies, we could try to hold on to the mbuf.
  788  */
  789 int
  790 ipsp_acquire_sa(struct ipsec_policy *ipo, union sockaddr_union *gw,
  791     union sockaddr_union *laddr, struct sockaddr_encap *ddst, struct mbuf *m)
  792 {
  793         struct ipsec_acquire *ipa;
  794 
  795         NET_ASSERT_LOCKED();
  796 
  797         /* Check whether request has been made already. */
  798         if (ipsp_pending_acquire(ipo, gw))
  799                 return 0;
  800 
  801         /* Add request in cache and proceed. */
  802         ipa = pool_get(&ipsec_acquire_pool, PR_NOWAIT|PR_ZERO);
  803         if (ipa == NULL)
  804                 return ENOMEM;
  805 
  806         ipa->ipa_addr = *gw;
  807 
  808         refcnt_init(&ipa->ipa_refcnt);
  809         timeout_set(&ipa->ipa_timeout, ipsp_delete_acquire_timer, ipa);
  810 
  811         ipa->ipa_info.sen_len = ipa->ipa_mask.sen_len = SENT_LEN;
  812         ipa->ipa_info.sen_family = ipa->ipa_mask.sen_family = PF_KEY;
  813 
  814         /* Just copy the right information. */
  815         switch (ipo->ipo_addr.sen_type) {
  816         case SENT_IP4:
  817                 ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP4;
  818                 ipa->ipa_info.sen_direction = ipo->ipo_addr.sen_direction;
  819                 ipa->ipa_mask.sen_direction = ipo->ipo_mask.sen_direction;
  820 
  821                 if (ipsp_is_unspecified(ipo->ipo_dst)) {
  822                         ipa->ipa_info.sen_ip_src = ddst->sen_ip_src;
  823                         ipa->ipa_mask.sen_ip_src.s_addr = INADDR_BROADCAST;
  824 
  825                         ipa->ipa_info.sen_ip_dst = ddst->sen_ip_dst;
  826                         ipa->ipa_mask.sen_ip_dst.s_addr = INADDR_BROADCAST;
  827                 } else {
  828                         ipa->ipa_info.sen_ip_src = ipo->ipo_addr.sen_ip_src;
  829                         ipa->ipa_mask.sen_ip_src = ipo->ipo_mask.sen_ip_src;
  830 
  831                         ipa->ipa_info.sen_ip_dst = ipo->ipo_addr.sen_ip_dst;
  832                         ipa->ipa_mask.sen_ip_dst = ipo->ipo_mask.sen_ip_dst;
  833                 }
  834 
  835                 ipa->ipa_info.sen_proto = ipo->ipo_addr.sen_proto;
  836                 ipa->ipa_mask.sen_proto = ipo->ipo_mask.sen_proto;
  837 
  838                 if (ipo->ipo_addr.sen_proto) {
  839                         ipa->ipa_info.sen_sport = ipo->ipo_addr.sen_sport;
  840                         ipa->ipa_mask.sen_sport = ipo->ipo_mask.sen_sport;
  841 
  842                         ipa->ipa_info.sen_dport = ipo->ipo_addr.sen_dport;
  843                         ipa->ipa_mask.sen_dport = ipo->ipo_mask.sen_dport;
  844                 }
  845                 break;
  846 
  847 #ifdef INET6
  848         case SENT_IP6:
  849                 ipa->ipa_info.sen_type = ipa->ipa_mask.sen_type = SENT_IP6;
  850                 ipa->ipa_info.sen_ip6_direction =
  851                     ipo->ipo_addr.sen_ip6_direction;
  852                 ipa->ipa_mask.sen_ip6_direction =
  853                     ipo->ipo_mask.sen_ip6_direction;
  854 
  855                 if (ipsp_is_unspecified(ipo->ipo_dst)) {
  856                         ipa->ipa_info.sen_ip6_src = ddst->sen_ip6_src;
  857                         ipa->ipa_mask.sen_ip6_src = in6mask128;
  858 
  859                         ipa->ipa_info.sen_ip6_dst = ddst->sen_ip6_dst;
  860                         ipa->ipa_mask.sen_ip6_dst = in6mask128;
  861                 } else {
  862                         ipa->ipa_info.sen_ip6_src = ipo->ipo_addr.sen_ip6_src;
  863                         ipa->ipa_mask.sen_ip6_src = ipo->ipo_mask.sen_ip6_src;
  864 
  865                         ipa->ipa_info.sen_ip6_dst = ipo->ipo_addr.sen_ip6_dst;
  866                         ipa->ipa_mask.sen_ip6_dst = ipo->ipo_mask.sen_ip6_dst;
  867                 }
  868 
  869                 ipa->ipa_info.sen_ip6_proto = ipo->ipo_addr.sen_ip6_proto;
  870                 ipa->ipa_mask.sen_ip6_proto = ipo->ipo_mask.sen_ip6_proto;
  871 
  872                 if (ipo->ipo_mask.sen_ip6_proto) {
  873                         ipa->ipa_info.sen_ip6_sport =
  874                             ipo->ipo_addr.sen_ip6_sport;
  875                         ipa->ipa_mask.sen_ip6_sport =
  876                             ipo->ipo_mask.sen_ip6_sport;
  877                         ipa->ipa_info.sen_ip6_dport =
  878                             ipo->ipo_addr.sen_ip6_dport;
  879                         ipa->ipa_mask.sen_ip6_dport =
  880                             ipo->ipo_mask.sen_ip6_dport;
  881                 }
  882                 break;
  883 #endif /* INET6 */
  884 
  885         default:
  886                 pool_put(&ipsec_acquire_pool, ipa);
  887                 return 0;
  888         }
  889 
  890         mtx_enter(&ipsec_acquire_mtx);
  891 #ifdef IPSEC
  892         if (timeout_add_sec(&ipa->ipa_timeout, ipsec_expire_acquire) == 1)
  893                 refcnt_take(&ipa->ipa_refcnt);
  894 #endif
  895         TAILQ_INSERT_TAIL(&ipsec_acquire_head, ipa, ipa_next);
  896         TAILQ_INSERT_TAIL(&ipo->ipo_acquires, ipa, ipa_ipo_next);
  897         ipa->ipa_policy = ipo;
  898         mtx_leave(&ipsec_acquire_mtx);
  899 
  900         /* PF_KEYv2 notification message. */
  901         return pfkeyv2_acquire(ipo, gw, laddr, &ipa->ipa_seq, ddst);
  902 }
  903 
  904 /*
  905  * Deal with PCB security requirements.
  906  */
  907 int
  908 ipsp_spd_inp(struct mbuf *m, struct inpcb *inp, struct ipsec_policy *ipo,
  909     struct tdb **tdbout)
  910 {
  911         /* Sanity check. */
  912         if (inp == NULL)
  913                 goto justreturn;
  914 
  915         /* We only support IPSEC_LEVEL_BYPASS or IPSEC_LEVEL_AVAIL */
  916 
  917         if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_BYPASS &&
  918             inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_BYPASS &&
  919             inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_BYPASS)
  920                 goto justreturn;
  921 
  922         if (inp->inp_seclevel[SL_ESP_TRANS] == IPSEC_LEVEL_AVAIL &&
  923             inp->inp_seclevel[SL_ESP_NETWORK] == IPSEC_LEVEL_AVAIL &&
  924             inp->inp_seclevel[SL_AUTH] == IPSEC_LEVEL_AVAIL)
  925                 goto justreturn;
  926 
  927         return -EINVAL;  /* Silently drop packet. */
  928 
  929  justreturn:
  930         if (tdbout != NULL) {
  931                 if (ipo != NULL)
  932                         *tdbout = tdb_ref(ipo->ipo_tdb);
  933                 else
  934                         *tdbout = NULL;
  935         }
  936         return 0;
  937 }
  938 
  939 /*
  940  * Find a pending ACQUIRE record based on its sequence number.
  941  * XXX Need to use a better data structure.
  942  */
  943 struct ipsec_acquire *
  944 ipsec_get_acquire(u_int32_t seq)
  945 {
  946         struct ipsec_acquire *ipa;
  947 
  948         NET_ASSERT_LOCKED();
  949 
  950         mtx_enter(&ipsec_acquire_mtx);
  951         TAILQ_FOREACH(ipa, &ipsec_acquire_head, ipa_next) {
  952                 if (ipa->ipa_seq == seq) {
  953                         refcnt_take(&ipa->ipa_refcnt);
  954                         break;
  955                 }
  956         }
  957         mtx_leave(&ipsec_acquire_mtx);
  958 
  959         return ipa;
  960 }

Cache object: a1a2d22e2c95186f45450546757a7632


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.