Print this page
8381 Convert ipsec_alg_lock from mutex to rwlock


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.

  23  */
  24 
  25 #include <sys/param.h>
  26 #include <sys/types.h>
  27 #include <sys/stream.h>
  28 #include <sys/strsubr.h>
  29 #include <sys/strsun.h>
  30 #include <sys/stropts.h>
  31 #include <sys/zone.h>
  32 #include <sys/vnode.h>
  33 #include <sys/sysmacros.h>
  34 #define _SUN_TPI_VERSION 2
  35 #include <sys/tihdr.h>
  36 #include <sys/ddi.h>
  37 #include <sys/sunddi.h>
  38 #include <sys/mkdev.h>
  39 #include <sys/debug.h>
  40 #include <sys/kmem.h>
  41 #include <sys/cmn_err.h>
  42 #include <sys/suntpi.h>


2251         SPD_ATTR_ENCR_INCRBITS
2252 };
2253 
2254 #define ATTRPERALG      6       /* fixed attributes per algs */
2255 
2256 void
2257 spdsock_alglist(queue_t *q, mblk_t *mp)
2258 {
2259         uint_t algtype;
2260         uint_t algidx;
2261         uint_t algcount;
2262         uint_t size;
2263         mblk_t *m;
2264         uint8_t *cur;
2265         spd_msg_t *msg;
2266         struct spd_ext_actions *act;
2267         struct spd_attribute *attr;
2268         spdsock_t *ss = (spdsock_t *)q->q_ptr;
2269         ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
2270 
2271         mutex_enter(&ipss->ipsec_alg_lock);
2272         /*
2273          * The SPD client expects to receive separate entries for
2274          * AH authentication and ESP authentication supported algorithms.
2275          *
2276          * Don't return the "any" algorithms, if defined, as no
2277          * kernel policies can be set for these algorithms.
2278          */
2279         algcount = 2 * ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
2280             ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
2281 
2282         if (ipss->ipsec_alglists[IPSEC_ALG_AUTH][SADB_AALG_NONE] != NULL)
2283                 algcount--;
2284         if (ipss->ipsec_alglists[IPSEC_ALG_ENCR][SADB_EALG_NONE] != NULL)
2285                 algcount--;
2286 
2287         /*
2288          * For each algorithm, we encode:
2289          * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
2290          */
2291 
2292         size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions) +
2293             ATTRPERALG * sizeof (struct spd_attribute) * algcount;
2294 
2295         ASSERT(ALIGNED64(size));
2296 
2297         m = allocb(size, BPRI_HI);
2298         if (m == NULL) {
2299                 mutex_exit(&ipss->ipsec_alg_lock);
2300                 spdsock_error(q, mp, ENOMEM, 0);
2301                 return;
2302         }
2303 
2304         m->b_wptr = m->b_rptr + size;
2305         cur = m->b_rptr;
2306 
2307         msg = (spd_msg_t *)cur;
2308         bcopy(mp->b_rptr, cur, sizeof (*msg));
2309 
2310         msg->spd_msg_len = SPD_8TO64(size);
2311         msg->spd_msg_errno = 0;
2312         msg->spd_msg_diagnostic = 0;
2313 
2314         cur += sizeof (*msg);
2315 
2316         act = (struct spd_ext_actions *)cur;
2317         cur += sizeof (*act);
2318 
2319         act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));


2350                             ipss->ipsec_alglists[algtype][algid];
2351                         uint_t minbits = alg->alg_minbits;
2352                         uint_t maxbits = alg->alg_maxbits;
2353                         uint_t defbits = alg->alg_default_bits;
2354                         uint_t incr = alg->alg_increment;
2355 
2356                         if (algtype == IPSEC_ALG_AUTH) {
2357                                 if (algid == SADB_AALG_NONE)
2358                                         continue;
2359                                 EMITALGATTRS(SPDSOCK_AH_AUTH);
2360                                 EMITALGATTRS(SPDSOCK_ESP_AUTH);
2361                         } else {
2362                                 if (algid == SADB_EALG_NONE)
2363                                         continue;
2364                                 ASSERT(algtype == IPSEC_ALG_ENCR);
2365                                 EMITALGATTRS(SPDSOCK_ESP_ENCR);
2366                         }
2367                 }
2368         }
2369 
2370         mutex_exit(&ipss->ipsec_alg_lock);
2371 
2372 #undef EMITALGATTRS
2373 #undef EMIT
2374 #undef ATTRPERALG
2375 
2376         attr--;
2377         attr->spd_attr_tag = SPD_ATTR_END;
2378 
2379         freemsg(mp);
2380         qreply(q, m);
2381 }
2382 
2383 /*
2384  * Process a SPD_DUMPALGS request.
2385  */
2386 
2387 #define ATTRPERALG      9       /* fixed attributes per algs */
2388 
2389 void
2390 spdsock_dumpalgs(queue_t *q, mblk_t *mp)
2391 {
2392         uint_t algtype;
2393         uint_t algidx;
2394         uint_t size;
2395         mblk_t *m;
2396         uint8_t *cur;
2397         spd_msg_t *msg;
2398         struct spd_ext_actions *act;
2399         struct spd_attribute *attr;
2400         ipsec_alginfo_t *alg;
2401         uint_t algid;
2402         uint_t i;
2403         uint_t alg_size;
2404         spdsock_t *ss = (spdsock_t *)q->q_ptr;
2405         ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
2406 
2407         mutex_enter(&ipss->ipsec_alg_lock);
2408 
2409         /*
2410          * For each algorithm, we encode:
2411          * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
2412          *
2413          * ALG_ID / ALG_PROTO / ALG_INCRBITS / ALG_NKEYSIZES / ALG_KEYSIZE*
2414          * ALG_NBLOCKSIZES / ALG_BLOCKSIZE* / ALG_NPARAMS / ALG_PARAMS* /
2415          * ALG_MECHNAME / ALG_FLAGS / {END, NEXT}
2416          */
2417 
2418         /*
2419          * Compute the size of the SPD message.
2420          */
2421         size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions);
2422 
2423         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
2424                 for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
2425                     algidx++) {
2426                         algid = ipss->ipsec_sortlist[algtype][algidx];
2427                         alg = ipss->ipsec_alglists[algtype][algid];
2428                         alg_size = sizeof (struct spd_attribute) *
2429                             (ATTRPERALG + alg->alg_nkey_sizes +
2430                             alg->alg_nblock_sizes + alg->alg_nparams) +
2431                             CRYPTO_MAX_MECH_NAME;
2432                         size += alg_size;
2433                 }
2434         }
2435 
2436         ASSERT(ALIGNED64(size));
2437 
2438         m = allocb(size, BPRI_HI);
2439         if (m == NULL) {
2440                 mutex_exit(&ipss->ipsec_alg_lock);
2441                 spdsock_error(q, mp, ENOMEM, 0);
2442                 return;
2443         }
2444 
2445         m->b_wptr = m->b_rptr + size;
2446         cur = m->b_rptr;
2447 
2448         msg = (spd_msg_t *)cur;
2449         bcopy(mp->b_rptr, cur, sizeof (*msg));
2450 
2451         msg->spd_msg_len = SPD_8TO64(size);
2452         msg->spd_msg_errno = 0;
2453         msg->spd_msg_type = SPD_ALGLIST;
2454 
2455         msg->spd_msg_diagnostic = 0;
2456 
2457         cur += sizeof (*msg);
2458 
2459         act = (struct spd_ext_actions *)cur;
2460         cur += sizeof (*act);
2461 
2462         act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));
2463         act->spd_actions_exttype = SPD_EXT_ACTION;
2464         act->spd_actions_count = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
2465             ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
2466         act->spd_actions_reserved = 0;
2467 
2468         /*
2469          * If there aren't any algorithms registered, return an empty message.
2470          * spdsock_get_ext() knows how to deal with this.
2471          */
2472         if (act->spd_actions_count == 0) {
2473                 act->spd_actions_len = 0;
2474                 mutex_exit(&ipss->ipsec_alg_lock);
2475                 goto error;
2476         }
2477 
2478         attr = (struct spd_attribute *)cur;
2479 
2480 #define EMIT(tag, value) {                                      \
2481                 attr->spd_attr_tag = (tag);                  \
2482                 attr->spd_attr_value = (value);              \
2483                 attr++;                                         \
2484         }
2485 
2486         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
2487                 for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
2488                     algidx++) {
2489 
2490                         algid = ipss->ipsec_sortlist[algtype][algidx];
2491                         alg = ipss->ipsec_alglists[algtype][algid];
2492 
2493                         /*
2494                          * If you change the number of EMIT's here, change


2506                         for (i = 0; i < alg->alg_nblock_sizes; i++)
2507                                 EMIT(SPD_ATTR_ALG_BLOCKSIZE,
2508                                     alg->alg_block_sizes[i]);
2509 
2510                         EMIT(SPD_ATTR_ALG_NPARAMS, alg->alg_nparams);
2511                         for (i = 0; i < alg->alg_nparams; i++)
2512                                 EMIT(SPD_ATTR_ALG_PARAMS,
2513                                     alg->alg_params[i]);
2514 
2515                         EMIT(SPD_ATTR_ALG_FLAGS, alg->alg_flags);
2516 
2517                         EMIT(SPD_ATTR_ALG_MECHNAME, CRYPTO_MAX_MECH_NAME);
2518                         bcopy(alg->alg_mech_name, attr, CRYPTO_MAX_MECH_NAME);
2519                         attr = (struct spd_attribute *)((char *)attr +
2520                             CRYPTO_MAX_MECH_NAME);
2521 
2522                         EMIT(SPD_ATTR_NEXT, 0);
2523                 }
2524         }
2525 
2526         mutex_exit(&ipss->ipsec_alg_lock);
2527 
2528 #undef EMITALGATTRS
2529 #undef EMIT
2530 #undef ATTRPERALG
2531 
2532         attr--;
2533         attr->spd_attr_tag = SPD_ATTR_END;
2534 
2535 error:
2536         freemsg(mp);
2537         qreply(q, m);
2538 }
2539 
2540 /*
2541  * Do the actual work of processing an SPD_UPDATEALGS request. Can
2542  * be invoked either once IPsec is loaded on a cached request, or
2543  * when a request is received while IPsec is loaded.
2544  */
2545 static int
2546 spdsock_do_updatealg(spd_ext_t *extv[], spd_stack_t *spds)


3667                         if (alg->alg_id == SADB_EALG_NULL) {
3668                                 alg->alg_mech_type = CRYPTO_MECHANISM_INVALID;
3669                                 alg->alg_flags |= ALG_FLAG_VALID;
3670                                 continue;
3671                         }
3672 
3673                         for (mech_idx = 0; mech_idx < mech_count; mech_idx++) {
3674                                 if (strncmp(alg->alg_mech_name, mechs[mech_idx],
3675                                     CRYPTO_MAX_MECH_NAME) == 0) {
3676                                         mt = crypto_mech2id(alg->alg_mech_name);
3677                                         ASSERT(mt != CRYPTO_MECHANISM_INVALID);
3678                                         algflags = ALG_FLAG_VALID;
3679                                         break;
3680                                 }
3681                         }
3682                         alg->alg_mech_type = mt;
3683                         alg->alg_flags |= algflags;
3684                 }
3685         }
3686 
3687         mutex_enter(&ipss->ipsec_alg_lock);
3688 
3689         /*
3690          * For each algorithm currently defined, check if it is
3691          * present in the new tables created from the SPD_UPDATEALGS
3692          * message received from user-space.
3693          * Delete the algorithm entries that are currently defined
3694          * but not part of the new tables.
3695          */
3696         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
3697                 nalgs = ipss->ipsec_nalgs[algtype];
3698                 for (algidx = 0; algidx < nalgs; algidx++) {
3699                         algid = ipss->ipsec_sortlist[algtype][algidx];
3700                         if (spds->spds_algs[algtype][algid] == NULL)
3701                                 ipsec_alg_unreg(algtype, algid, ns);
3702                 }
3703         }
3704 
3705         /*
3706          * For each algorithm we just received, check if it is
3707          * present in the currently defined tables. If it is, swap


3723                                  */
3724                                 ipsec_alg_reg(algtype, alg, ns);
3725                         } else {
3726                                 /*
3727                                  * Algorithm is already in the table. Swap
3728                                  * the existing entry with the new one.
3729                                  */
3730                                 ipsec_alg_fix_min_max(alg, algtype, ns);
3731                                 ipss->ipsec_alglists[algtype][algid] = alg;
3732                                 ipsec_alg_free(oalg);
3733                         }
3734                         spds->spds_algs[algtype][algid] = NULL;
3735                 }
3736         }
3737 
3738         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
3739                 ipss->ipsec_algs_exec_mode[algtype] =
3740                     spds->spds_algs_exec_mode[algtype];
3741         }
3742 
3743         mutex_exit(&ipss->ipsec_alg_lock);
3744 
3745         crypto_free_mech_list(mechs, mech_count);
3746 
3747         ipsecah_algs_changed(ns);
3748         ipsecesp_algs_changed(ns);
3749 }


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  24  */
  25 
  26 #include <sys/param.h>
  27 #include <sys/types.h>
  28 #include <sys/stream.h>
  29 #include <sys/strsubr.h>
  30 #include <sys/strsun.h>
  31 #include <sys/stropts.h>
  32 #include <sys/zone.h>
  33 #include <sys/vnode.h>
  34 #include <sys/sysmacros.h>
  35 #define _SUN_TPI_VERSION 2
  36 #include <sys/tihdr.h>
  37 #include <sys/ddi.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/mkdev.h>
  40 #include <sys/debug.h>
  41 #include <sys/kmem.h>
  42 #include <sys/cmn_err.h>
  43 #include <sys/suntpi.h>


2252         SPD_ATTR_ENCR_INCRBITS
2253 };
2254 
2255 #define ATTRPERALG      6       /* fixed attributes per algs */
2256 
2257 void
2258 spdsock_alglist(queue_t *q, mblk_t *mp)
2259 {
2260         uint_t algtype;
2261         uint_t algidx;
2262         uint_t algcount;
2263         uint_t size;
2264         mblk_t *m;
2265         uint8_t *cur;
2266         spd_msg_t *msg;
2267         struct spd_ext_actions *act;
2268         struct spd_attribute *attr;
2269         spdsock_t *ss = (spdsock_t *)q->q_ptr;
2270         ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
2271 
2272         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
2273         /*
2274          * The SPD client expects to receive separate entries for
2275          * AH authentication and ESP authentication supported algorithms.
2276          *
2277          * Don't return the "any" algorithms, if defined, as no
2278          * kernel policies can be set for these algorithms.
2279          */
2280         algcount = 2 * ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
2281             ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
2282 
2283         if (ipss->ipsec_alglists[IPSEC_ALG_AUTH][SADB_AALG_NONE] != NULL)
2284                 algcount--;
2285         if (ipss->ipsec_alglists[IPSEC_ALG_ENCR][SADB_EALG_NONE] != NULL)
2286                 algcount--;
2287 
2288         /*
2289          * For each algorithm, we encode:
2290          * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
2291          */
2292 
2293         size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions) +
2294             ATTRPERALG * sizeof (struct spd_attribute) * algcount;
2295 
2296         ASSERT(ALIGNED64(size));
2297 
2298         m = allocb(size, BPRI_HI);
2299         if (m == NULL) {
2300                 rw_exit(&ipss->ipsec_alg_lock);
2301                 spdsock_error(q, mp, ENOMEM, 0);
2302                 return;
2303         }
2304 
2305         m->b_wptr = m->b_rptr + size;
2306         cur = m->b_rptr;
2307 
2308         msg = (spd_msg_t *)cur;
2309         bcopy(mp->b_rptr, cur, sizeof (*msg));
2310 
2311         msg->spd_msg_len = SPD_8TO64(size);
2312         msg->spd_msg_errno = 0;
2313         msg->spd_msg_diagnostic = 0;
2314 
2315         cur += sizeof (*msg);
2316 
2317         act = (struct spd_ext_actions *)cur;
2318         cur += sizeof (*act);
2319 
2320         act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));


2351                             ipss->ipsec_alglists[algtype][algid];
2352                         uint_t minbits = alg->alg_minbits;
2353                         uint_t maxbits = alg->alg_maxbits;
2354                         uint_t defbits = alg->alg_default_bits;
2355                         uint_t incr = alg->alg_increment;
2356 
2357                         if (algtype == IPSEC_ALG_AUTH) {
2358                                 if (algid == SADB_AALG_NONE)
2359                                         continue;
2360                                 EMITALGATTRS(SPDSOCK_AH_AUTH);
2361                                 EMITALGATTRS(SPDSOCK_ESP_AUTH);
2362                         } else {
2363                                 if (algid == SADB_EALG_NONE)
2364                                         continue;
2365                                 ASSERT(algtype == IPSEC_ALG_ENCR);
2366                                 EMITALGATTRS(SPDSOCK_ESP_ENCR);
2367                         }
2368                 }
2369         }
2370 
2371         rw_exit(&ipss->ipsec_alg_lock);
2372 
2373 #undef EMITALGATTRS
2374 #undef EMIT
2375 #undef ATTRPERALG
2376 
2377         attr--;
2378         attr->spd_attr_tag = SPD_ATTR_END;
2379 
2380         freemsg(mp);
2381         qreply(q, m);
2382 }
2383 
2384 /*
2385  * Process a SPD_DUMPALGS request.
2386  */
2387 
2388 #define ATTRPERALG      9       /* fixed attributes per algs */
2389 
2390 void
2391 spdsock_dumpalgs(queue_t *q, mblk_t *mp)
2392 {
2393         uint_t algtype;
2394         uint_t algidx;
2395         uint_t size;
2396         mblk_t *m;
2397         uint8_t *cur;
2398         spd_msg_t *msg;
2399         struct spd_ext_actions *act;
2400         struct spd_attribute *attr;
2401         ipsec_alginfo_t *alg;
2402         uint_t algid;
2403         uint_t i;
2404         uint_t alg_size;
2405         spdsock_t *ss = (spdsock_t *)q->q_ptr;
2406         ipsec_stack_t *ipss = ss->spdsock_spds->spds_netstack->netstack_ipsec;
2407 
2408         rw_enter(&ipss->ipsec_alg_lock, RW_READER);
2409 
2410         /*
2411          * For each algorithm, we encode:
2412          * ALG / MINBITS / MAXBITS / DEFBITS / INCRBITS / {END, NEXT}
2413          *
2414          * ALG_ID / ALG_PROTO / ALG_INCRBITS / ALG_NKEYSIZES / ALG_KEYSIZE*
2415          * ALG_NBLOCKSIZES / ALG_BLOCKSIZE* / ALG_NPARAMS / ALG_PARAMS* /
2416          * ALG_MECHNAME / ALG_FLAGS / {END, NEXT}
2417          */
2418 
2419         /*
2420          * Compute the size of the SPD message.
2421          */
2422         size = sizeof (spd_msg_t) + sizeof (struct spd_ext_actions);
2423 
2424         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
2425                 for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
2426                     algidx++) {
2427                         algid = ipss->ipsec_sortlist[algtype][algidx];
2428                         alg = ipss->ipsec_alglists[algtype][algid];
2429                         alg_size = sizeof (struct spd_attribute) *
2430                             (ATTRPERALG + alg->alg_nkey_sizes +
2431                             alg->alg_nblock_sizes + alg->alg_nparams) +
2432                             CRYPTO_MAX_MECH_NAME;
2433                         size += alg_size;
2434                 }
2435         }
2436 
2437         ASSERT(ALIGNED64(size));
2438 
2439         m = allocb(size, BPRI_HI);
2440         if (m == NULL) {
2441                 rw_exit(&ipss->ipsec_alg_lock);
2442                 spdsock_error(q, mp, ENOMEM, 0);
2443                 return;
2444         }
2445 
2446         m->b_wptr = m->b_rptr + size;
2447         cur = m->b_rptr;
2448 
2449         msg = (spd_msg_t *)cur;
2450         bcopy(mp->b_rptr, cur, sizeof (*msg));
2451 
2452         msg->spd_msg_len = SPD_8TO64(size);
2453         msg->spd_msg_errno = 0;
2454         msg->spd_msg_type = SPD_ALGLIST;
2455 
2456         msg->spd_msg_diagnostic = 0;
2457 
2458         cur += sizeof (*msg);
2459 
2460         act = (struct spd_ext_actions *)cur;
2461         cur += sizeof (*act);
2462 
2463         act->spd_actions_len = SPD_8TO64(size - sizeof (spd_msg_t));
2464         act->spd_actions_exttype = SPD_EXT_ACTION;
2465         act->spd_actions_count = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] +
2466             ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
2467         act->spd_actions_reserved = 0;
2468 
2469         /*
2470          * If there aren't any algorithms registered, return an empty message.
2471          * spdsock_get_ext() knows how to deal with this.
2472          */
2473         if (act->spd_actions_count == 0) {
2474                 act->spd_actions_len = 0;
2475                 rw_exit(&ipss->ipsec_alg_lock);
2476                 goto error;
2477         }
2478 
2479         attr = (struct spd_attribute *)cur;
2480 
2481 #define EMIT(tag, value) {                                      \
2482                 attr->spd_attr_tag = (tag);                  \
2483                 attr->spd_attr_value = (value);              \
2484                 attr++;                                         \
2485         }
2486 
2487         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
2488                 for (algidx = 0; algidx < ipss->ipsec_nalgs[algtype];
2489                     algidx++) {
2490 
2491                         algid = ipss->ipsec_sortlist[algtype][algidx];
2492                         alg = ipss->ipsec_alglists[algtype][algid];
2493 
2494                         /*
2495                          * If you change the number of EMIT's here, change


2507                         for (i = 0; i < alg->alg_nblock_sizes; i++)
2508                                 EMIT(SPD_ATTR_ALG_BLOCKSIZE,
2509                                     alg->alg_block_sizes[i]);
2510 
2511                         EMIT(SPD_ATTR_ALG_NPARAMS, alg->alg_nparams);
2512                         for (i = 0; i < alg->alg_nparams; i++)
2513                                 EMIT(SPD_ATTR_ALG_PARAMS,
2514                                     alg->alg_params[i]);
2515 
2516                         EMIT(SPD_ATTR_ALG_FLAGS, alg->alg_flags);
2517 
2518                         EMIT(SPD_ATTR_ALG_MECHNAME, CRYPTO_MAX_MECH_NAME);
2519                         bcopy(alg->alg_mech_name, attr, CRYPTO_MAX_MECH_NAME);
2520                         attr = (struct spd_attribute *)((char *)attr +
2521                             CRYPTO_MAX_MECH_NAME);
2522 
2523                         EMIT(SPD_ATTR_NEXT, 0);
2524                 }
2525         }
2526 
2527         rw_exit(&ipss->ipsec_alg_lock);
2528 
2529 #undef EMITALGATTRS
2530 #undef EMIT
2531 #undef ATTRPERALG
2532 
2533         attr--;
2534         attr->spd_attr_tag = SPD_ATTR_END;
2535 
2536 error:
2537         freemsg(mp);
2538         qreply(q, m);
2539 }
2540 
2541 /*
2542  * Do the actual work of processing an SPD_UPDATEALGS request. Can
2543  * be invoked either once IPsec is loaded on a cached request, or
2544  * when a request is received while IPsec is loaded.
2545  */
2546 static int
2547 spdsock_do_updatealg(spd_ext_t *extv[], spd_stack_t *spds)


3668                         if (alg->alg_id == SADB_EALG_NULL) {
3669                                 alg->alg_mech_type = CRYPTO_MECHANISM_INVALID;
3670                                 alg->alg_flags |= ALG_FLAG_VALID;
3671                                 continue;
3672                         }
3673 
3674                         for (mech_idx = 0; mech_idx < mech_count; mech_idx++) {
3675                                 if (strncmp(alg->alg_mech_name, mechs[mech_idx],
3676                                     CRYPTO_MAX_MECH_NAME) == 0) {
3677                                         mt = crypto_mech2id(alg->alg_mech_name);
3678                                         ASSERT(mt != CRYPTO_MECHANISM_INVALID);
3679                                         algflags = ALG_FLAG_VALID;
3680                                         break;
3681                                 }
3682                         }
3683                         alg->alg_mech_type = mt;
3684                         alg->alg_flags |= algflags;
3685                 }
3686         }
3687 
3688         rw_enter(&ipss->ipsec_alg_lock, RW_WRITER);
3689 
3690         /*
3691          * For each algorithm currently defined, check if it is
3692          * present in the new tables created from the SPD_UPDATEALGS
3693          * message received from user-space.
3694          * Delete the algorithm entries that are currently defined
3695          * but not part of the new tables.
3696          */
3697         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
3698                 nalgs = ipss->ipsec_nalgs[algtype];
3699                 for (algidx = 0; algidx < nalgs; algidx++) {
3700                         algid = ipss->ipsec_sortlist[algtype][algidx];
3701                         if (spds->spds_algs[algtype][algid] == NULL)
3702                                 ipsec_alg_unreg(algtype, algid, ns);
3703                 }
3704         }
3705 
3706         /*
3707          * For each algorithm we just received, check if it is
3708          * present in the currently defined tables. If it is, swap


3724                                  */
3725                                 ipsec_alg_reg(algtype, alg, ns);
3726                         } else {
3727                                 /*
3728                                  * Algorithm is already in the table. Swap
3729                                  * the existing entry with the new one.
3730                                  */
3731                                 ipsec_alg_fix_min_max(alg, algtype, ns);
3732                                 ipss->ipsec_alglists[algtype][algid] = alg;
3733                                 ipsec_alg_free(oalg);
3734                         }
3735                         spds->spds_algs[algtype][algid] = NULL;
3736                 }
3737         }
3738 
3739         for (algtype = 0; algtype < IPSEC_NALGTYPES; algtype++) {
3740                 ipss->ipsec_algs_exec_mode[algtype] =
3741                     spds->spds_algs_exec_mode[algtype];
3742         }
3743 
3744         rw_exit(&ipss->ipsec_alg_lock);
3745 
3746         crypto_free_mech_list(mechs, mech_count);
3747 
3748         ipsecah_algs_changed(ns);
3749         ipsecesp_algs_changed(ns);
3750 }