1 1676 jpk /* 2 1676 jpk * CDDL HEADER START 3 1676 jpk * 4 1676 jpk * The contents of this file are subject to the terms of the 5 1676 jpk * Common Development and Distribution License (the "License"). 6 1676 jpk * You may not use this file except in compliance with the License. 7 1676 jpk * 8 1676 jpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 1676 jpk * or http://www.opensolaris.org/os/licensing. 10 1676 jpk * See the License for the specific language governing permissions 11 1676 jpk * and limitations under the License. 12 1676 jpk * 13 1676 jpk * When distributing Covered Code, include this CDDL HEADER in each 14 1676 jpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 1676 jpk * If applicable, add the following below this CDDL HEADER, with the 16 1676 jpk * fields enclosed by brackets "[]" replaced with your own identifying 17 1676 jpk * information: Portions Copyright [yyyy] [name of copyright owner] 18 1676 jpk * 19 1676 jpk * CDDL HEADER END 20 1676 jpk */ 21 1676 jpk /* 22 8778 Erik * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 1676 jpk * Use is subject to license terms. 24 1676 jpk */ 25 1676 jpk 26 1676 jpk #include <sys/types.h> 27 1676 jpk #include <sys/stream.h> 28 1676 jpk #include <sys/strsubr.h> 29 1676 jpk #include <sys/stropts.h> 30 1676 jpk #include <sys/sunddi.h> 31 1676 jpk #include <sys/cred.h> 32 1676 jpk #include <sys/debug.h> 33 1676 jpk #include <sys/kmem.h> 34 1676 jpk #include <sys/errno.h> 35 1676 jpk #include <sys/disp.h> 36 1676 jpk #include <netinet/in.h> 37 1676 jpk #include <netinet/in_systm.h> 38 1676 jpk #include <netinet/ip.h> 39 1676 jpk #include <netinet/ip_icmp.h> 40 1676 jpk #include <netinet/tcp.h> 41 1676 jpk #include <inet/common.h> 42 1676 jpk #include <inet/ipclassifier.h> 43 1676 jpk #include <inet/ip.h> 44 1676 jpk #include <inet/mib2.h> 45 1676 jpk #include <inet/nd.h> 46 1676 jpk #include <inet/tcp.h> 47 1676 jpk #include <inet/ip_rts.h> 48 1676 jpk #include <inet/ip_ire.h> 49 1676 jpk #include <inet/ip_if.h> 50 1676 jpk #include <sys/modhash.h> 51 1676 jpk 52 1676 jpk #include <sys/tsol/label.h> 53 1676 jpk #include <sys/tsol/label_macro.h> 54 1676 jpk #include <sys/tsol/tnet.h> 55 1676 jpk #include <sys/tsol/tndb.h> 56 1676 jpk #include <sys/strsun.h> 57 1676 jpk 58 1676 jpk /* tunable for strict error-reply behavior (TCP RST and ICMP Unreachable) */ 59 1676 jpk int tsol_strict_error; 60 1676 jpk 61 1676 jpk /* 62 1676 jpk * Some notes on the Trusted Solaris IRE gateway security attributes: 63 1676 jpk * 64 1676 jpk * When running in Trusted mode, the routing subsystem determines whether or 65 1676 jpk * not a packet can be delivered to an off-link host (not directly reachable 66 1676 jpk * through an interface) based on the accreditation checks of the packet's 67 1676 jpk * security attributes against those associated with the next-hop gateway. 68 1676 jpk * 69 1676 jpk * The next-hop gateway's security attributes can be derived from two sources 70 1676 jpk * (in order of preference): route-related and the host database. A Trusted 71 1676 jpk * system must be configured with at least the host database containing an 72 1676 jpk * entry for the next-hop gateway, or otherwise no accreditation checks can 73 1676 jpk * be performed, which may result in the inability to send packets to any 74 1676 jpk * off-link destination host. 75 1676 jpk * 76 1676 jpk * The major differences between the two sources are the number and type of 77 1676 jpk * security attributes used for accreditation checks. A host database entry 78 1676 jpk * can contain at most one set of security attributes, specific only to the 79 1676 jpk * next-hop gateway. On contrast, route-related security attributes are made 80 1676 jpk * up of a collection of security attributes for the distant networks, and 81 1676 jpk * are grouped together per next-hop gateway used to reach those networks. 82 1676 jpk * This is the preferred method, and the routing subsystem will fallback to 83 1676 jpk * the host database entry only if there are no route-related attributes 84 1676 jpk * associated with the next-hop gateway. 85 1676 jpk * 86 1676 jpk * In Trusted mode, all of the IRE entries (except LOCAL/LOOPBACK/BROADCAST/ 87 1676 jpk * INTERFACE type) are initialized to contain a placeholder to store this 88 1676 jpk * information. The ire_gw_secattr structure gets allocated, initialized 89 1676 jpk * and associated with the IRE during the time of the IRE creation. The 90 1676 jpk * initialization process also includes resolving the host database entry 91 1676 jpk * of the next-hop gateway for fallback purposes. It does not include any 92 1676 jpk * route-related attribute setup, as that process comes separately as part 93 1676 jpk * of the route requests (add/change) made to the routing subsystem. 94 1676 jpk * 95 1676 jpk * The underlying logic which involves associating IREs with the gateway 96 1676 jpk * security attributes are represented by the following data structures: 97 1676 jpk * 98 1676 jpk * tsol_gcdb_t, or "gcdb" 99 1676 jpk * 100 1676 jpk * - This is a system-wide collection of records containing the 101 1676 jpk * currently used route-related security attributes, which are fed 102 1676 jpk * through the routing socket interface, e.g. "route add/change". 103 1676 jpk * 104 1676 jpk * tsol_gc_t, or "gc" 105 1676 jpk * 106 1676 jpk * - This is the gateway credential structure, and it provides for the 107 1676 jpk * only mechanism to access the contents of gcdb. More than one gc 108 1676 jpk * entries may refer to the same gcdb record. gc's in the system are 109 1676 jpk * grouped according to the next-hop gateway address. 110 1676 jpk * 111 1676 jpk * tsol_gcgrp_t, or "gcgrp" 112 1676 jpk * 113 1676 jpk * - Group of gateway credentials, and is unique per next-hop gateway 114 1676 jpk * address. When the group is not empty, i.e. when gcgrp_count is 115 1676 jpk * greater than zero, it contains one or more gc's, each pointing to 116 1676 jpk * a gcdb record which indicates the gateway security attributes 117 1676 jpk * associated with the next-hop gateway. 118 1676 jpk * 119 1676 jpk * The fields of the tsol_ire_gw_secattr_t used from within the IRE are: 120 1676 jpk * 121 1676 jpk * igsa_lock 122 1676 jpk * 123 1676 jpk * - Lock that protects all fields within tsol_ire_gw_secattr_t. 124 1676 jpk * 125 1676 jpk * igsa_rhc 126 1676 jpk * 127 1676 jpk * - Remote host cache database entry of next-hop gateway. This is 128 1676 jpk * used in the case when there are no route-related attributes 129 1676 jpk * configured for the IRE. 130 1676 jpk * 131 1676 jpk * igsa_gc 132 1676 jpk * 133 1676 jpk * - A set of route-related attributes that only get set for prefix 134 1676 jpk * IREs. If this is non-NULL, the prefix IRE has been associated 135 1676 jpk * with a set of gateway security attributes by way of route add/ 136 11042 Erik * change functionality. 137 1676 jpk */ 138 1676 jpk 139 1676 jpk static kmem_cache_t *ire_gw_secattr_cache; 140 1676 jpk 141 1676 jpk #define GCDB_HASH_SIZE 101 142 1676 jpk #define GCGRP_HASH_SIZE 101 143 1676 jpk 144 1676 jpk #define GCDB_REFRELE(p) { \ 145 1676 jpk mutex_enter(&gcdb_lock); \ 146 1676 jpk ASSERT((p)->gcdb_refcnt > 0); \ 147 1676 jpk if (--((p)->gcdb_refcnt) == 0) \ 148 1676 jpk gcdb_inactive(p); \ 149 1676 jpk ASSERT(MUTEX_HELD(&gcdb_lock)); \ 150 1676 jpk mutex_exit(&gcdb_lock); \ 151 1676 jpk } 152 1676 jpk 153 1676 jpk static int gcdb_hash_size = GCDB_HASH_SIZE; 154 1676 jpk static int gcgrp_hash_size = GCGRP_HASH_SIZE; 155 1676 jpk static mod_hash_t *gcdb_hash; 156 1676 jpk static mod_hash_t *gcgrp4_hash; 157 1676 jpk static mod_hash_t *gcgrp6_hash; 158 1676 jpk 159 1676 jpk static kmutex_t gcdb_lock; 160 1676 jpk kmutex_t gcgrp_lock; 161 1676 jpk 162 1676 jpk static uint_t gcdb_hash_by_secattr(void *, mod_hash_key_t); 163 1676 jpk static int gcdb_hash_cmp(mod_hash_key_t, mod_hash_key_t); 164 1676 jpk static tsol_gcdb_t *gcdb_lookup(struct rtsa_s *, boolean_t); 165 1676 jpk static void gcdb_inactive(tsol_gcdb_t *); 166 1676 jpk 167 1676 jpk static uint_t gcgrp_hash_by_addr(void *, mod_hash_key_t); 168 1676 jpk static int gcgrp_hash_cmp(mod_hash_key_t, mod_hash_key_t); 169 1676 jpk 170 1676 jpk static int ire_gw_secattr_constructor(void *, void *, int); 171 1676 jpk static void ire_gw_secattr_destructor(void *, void *); 172 1676 jpk 173 1676 jpk void 174 1676 jpk tnet_init(void) 175 1676 jpk { 176 1676 jpk ire_gw_secattr_cache = kmem_cache_create("ire_gw_secattr_cache", 177 1676 jpk sizeof (tsol_ire_gw_secattr_t), 64, ire_gw_secattr_constructor, 178 1676 jpk ire_gw_secattr_destructor, NULL, NULL, NULL, 0); 179 1676 jpk 180 1676 jpk gcdb_hash = mod_hash_create_extended("gcdb_hash", 181 1676 jpk gcdb_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor, 182 1676 jpk gcdb_hash_by_secattr, NULL, gcdb_hash_cmp, KM_SLEEP); 183 1676 jpk 184 1676 jpk gcgrp4_hash = mod_hash_create_extended("gcgrp4_hash", 185 1676 jpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor, 186 1676 jpk gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP); 187 1676 jpk 188 1676 jpk gcgrp6_hash = mod_hash_create_extended("gcgrp6_hash", 189 1676 jpk gcgrp_hash_size, mod_hash_null_keydtor, mod_hash_null_valdtor, 190 1676 jpk gcgrp_hash_by_addr, NULL, gcgrp_hash_cmp, KM_SLEEP); 191 1676 jpk 192 1676 jpk mutex_init(&gcdb_lock, NULL, MUTEX_DEFAULT, NULL); 193 1676 jpk mutex_init(&gcgrp_lock, NULL, MUTEX_DEFAULT, NULL); 194 1676 jpk } 195 1676 jpk 196 1676 jpk void 197 1676 jpk tnet_fini(void) 198 1676 jpk { 199 1676 jpk kmem_cache_destroy(ire_gw_secattr_cache); 200 1676 jpk mod_hash_destroy_hash(gcdb_hash); 201 1676 jpk mod_hash_destroy_hash(gcgrp4_hash); 202 1676 jpk mod_hash_destroy_hash(gcgrp6_hash); 203 1676 jpk mutex_destroy(&gcdb_lock); 204 1676 jpk mutex_destroy(&gcgrp_lock); 205 1676 jpk } 206 1676 jpk 207 1676 jpk /* ARGSUSED */ 208 1676 jpk static int 209 1676 jpk ire_gw_secattr_constructor(void *buf, void *cdrarg, int kmflags) 210 1676 jpk { 211 1676 jpk tsol_ire_gw_secattr_t *attrp = buf; 212 1676 jpk 213 1676 jpk mutex_init(&attrp->igsa_lock, NULL, MUTEX_DEFAULT, NULL); 214 1676 jpk 215 1676 jpk attrp->igsa_rhc = NULL; 216 1676 jpk attrp->igsa_gc = NULL; 217 1676 jpk 218 1676 jpk return (0); 219 1676 jpk } 220 1676 jpk 221 1676 jpk /* ARGSUSED */ 222 1676 jpk static void 223 1676 jpk ire_gw_secattr_destructor(void *buf, void *cdrarg) 224 1676 jpk { 225 1676 jpk tsol_ire_gw_secattr_t *attrp = (tsol_ire_gw_secattr_t *)buf; 226 1676 jpk 227 1676 jpk mutex_destroy(&attrp->igsa_lock); 228 1676 jpk } 229 1676 jpk 230 1676 jpk tsol_ire_gw_secattr_t * 231 1676 jpk ire_gw_secattr_alloc(int kmflags) 232 1676 jpk { 233 1676 jpk return (kmem_cache_alloc(ire_gw_secattr_cache, kmflags)); 234 1676 jpk } 235 1676 jpk 236 1676 jpk void 237 1676 jpk ire_gw_secattr_free(tsol_ire_gw_secattr_t *attrp) 238 1676 jpk { 239 1676 jpk ASSERT(MUTEX_NOT_HELD(&attrp->igsa_lock)); 240 1676 jpk 241 1676 jpk if (attrp->igsa_rhc != NULL) { 242 1676 jpk TNRHC_RELE(attrp->igsa_rhc); 243 1676 jpk attrp->igsa_rhc = NULL; 244 1676 jpk } 245 1676 jpk 246 1676 jpk if (attrp->igsa_gc != NULL) { 247 1676 jpk GC_REFRELE(attrp->igsa_gc); 248 1676 jpk attrp->igsa_gc = NULL; 249 1676 jpk } 250 1676 jpk 251 1676 jpk ASSERT(attrp->igsa_rhc == NULL); 252 1676 jpk ASSERT(attrp->igsa_gc == NULL); 253 1676 jpk 254 1676 jpk kmem_cache_free(ire_gw_secattr_cache, attrp); 255 1676 jpk } 256 1676 jpk 257 1676 jpk /* ARGSUSED */ 258 1676 jpk static uint_t 259 1676 jpk gcdb_hash_by_secattr(void *hash_data, mod_hash_key_t key) 260 1676 jpk { 261 1676 jpk const struct rtsa_s *rp = (struct rtsa_s *)key; 262 1676 jpk const uint32_t *up, *ue; 263 1676 jpk uint_t hash; 264 1676 jpk int i; 265 1676 jpk 266 1676 jpk ASSERT(rp != NULL); 267 1676 jpk 268 1676 jpk /* See comments in hash_bylabel in zone.c for details */ 269 1676 jpk hash = rp->rtsa_doi + (rp->rtsa_doi << 1); 270 1676 jpk up = (const uint32_t *)&rp->rtsa_slrange; 271 1676 jpk ue = up + sizeof (rp->rtsa_slrange) / sizeof (*up); 272 1676 jpk i = 1; 273 1676 jpk while (up < ue) { 274 1676 jpk /* using 2^n + 1, 1 <= n <= 16 as source of many primes */ 275 1676 jpk hash += *up + (*up << ((i % 16) + 1)); 276 1676 jpk up++; 277 1676 jpk i++; 278 1676 jpk } 279 1676 jpk return (hash); 280 1676 jpk } 281 1676 jpk 282 1676 jpk static int 283 1676 jpk gcdb_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2) 284 1676 jpk { 285 1676 jpk struct rtsa_s *rp1 = (struct rtsa_s *)key1; 286 1676 jpk struct rtsa_s *rp2 = (struct rtsa_s *)key2; 287 1676 jpk 288 1676 jpk ASSERT(rp1 != NULL && rp2 != NULL); 289 1676 jpk 290 1676 jpk if (blequal(&rp1->rtsa_slrange.lower_bound, 291 1676 jpk &rp2->rtsa_slrange.lower_bound) && 292 1676 jpk blequal(&rp1->rtsa_slrange.upper_bound, 293 1676 jpk &rp2->rtsa_slrange.upper_bound) && 294 1676 jpk rp1->rtsa_doi == rp2->rtsa_doi) 295 1676 jpk return (0); 296 1676 jpk 297 1676 jpk /* No match; not found */ 298 1676 jpk return (-1); 299 1676 jpk } 300 1676 jpk 301 1676 jpk /* ARGSUSED */ 302 1676 jpk static uint_t 303 1676 jpk gcgrp_hash_by_addr(void *hash_data, mod_hash_key_t key) 304 1676 jpk { 305 1676 jpk tsol_gcgrp_addr_t *ga = (tsol_gcgrp_addr_t *)key; 306 1676 jpk uint_t idx = 0; 307 1676 jpk uint32_t *ap; 308 1676 jpk 309 1676 jpk ASSERT(ga != NULL); 310 1676 jpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6); 311 1676 jpk 312 1676 jpk ap = (uint32_t *)&ga->ga_addr.s6_addr32[0]; 313 1676 jpk idx ^= *ap++; 314 1676 jpk idx ^= *ap++; 315 1676 jpk idx ^= *ap++; 316 1676 jpk idx ^= *ap; 317 1676 jpk 318 1676 jpk return (idx); 319 1676 jpk } 320 1676 jpk 321 1676 jpk static int 322 1676 jpk gcgrp_hash_cmp(mod_hash_key_t key1, mod_hash_key_t key2) 323 1676 jpk { 324 1676 jpk tsol_gcgrp_addr_t *ga1 = (tsol_gcgrp_addr_t *)key1; 325 1676 jpk tsol_gcgrp_addr_t *ga2 = (tsol_gcgrp_addr_t *)key2; 326 1676 jpk 327 1676 jpk ASSERT(ga1 != NULL && ga2 != NULL); 328 1676 jpk 329 1676 jpk /* Address family must match */ 330 1676 jpk if (ga1->ga_af != ga2->ga_af) 331 1676 jpk return (-1); 332 1676 jpk 333 1676 jpk if (ga1->ga_addr.s6_addr32[0] == ga2->ga_addr.s6_addr32[0] && 334 1676 jpk ga1->ga_addr.s6_addr32[1] == ga2->ga_addr.s6_addr32[1] && 335 1676 jpk ga1->ga_addr.s6_addr32[2] == ga2->ga_addr.s6_addr32[2] && 336 1676 jpk ga1->ga_addr.s6_addr32[3] == ga2->ga_addr.s6_addr32[3]) 337 1676 jpk return (0); 338 1676 jpk 339 1676 jpk /* No match; not found */ 340 1676 jpk return (-1); 341 1676 jpk } 342 1676 jpk 343 1676 jpk #define RTSAFLAGS "\20\11cipso\3doi\2max_sl\1min_sl" 344 1676 jpk 345 1676 jpk int 346 1676 jpk rtsa_validate(const struct rtsa_s *rp) 347 1676 jpk { 348 1676 jpk uint32_t mask = rp->rtsa_mask; 349 1676 jpk 350 1676 jpk /* RTSA_CIPSO must be set, and DOI must not be zero */ 351 1676 jpk if ((mask & RTSA_CIPSO) == 0 || rp->rtsa_doi == 0) { 352 1676 jpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *, 353 1676 jpk "rtsa(1) lacks flag or has 0 doi.", 354 1676 jpk rtsa_s *, rp); 355 1676 jpk return (EINVAL); 356 1676 jpk } 357 1676 jpk /* 358 1676 jpk * SL range must be specified, and it must have its 359 1676 jpk * upper bound dominating its lower bound. 360 1676 jpk */ 361 1676 jpk if ((mask & RTSA_SLRANGE) != RTSA_SLRANGE || 362 1676 jpk !bldominates(&rp->rtsa_slrange.upper_bound, 363 1676 jpk &rp->rtsa_slrange.lower_bound)) { 364 1676 jpk DTRACE_PROBE2(tx__gcdb__log__error__rtsa__validate, char *, 365 1676 jpk "rtsa(1) min_sl and max_sl not set or max_sl is " 366 1676 jpk "not dominating.", rtsa_s *, rp); 367 1676 jpk return (EINVAL); 368 1676 jpk } 369 1676 jpk return (0); 370 1676 jpk } 371 1676 jpk 372 1676 jpk /* 373 1676 jpk * A brief explanation of the reference counting scheme: 374 1676 jpk * 375 1676 jpk * Apart from dynamic references due to to reference holds done 376 1676 jpk * actively by threads, we have the following references: 377 1676 jpk * 378 1676 jpk * gcdb_refcnt: 379 1676 jpk * - Every tsol_gc_t pointing to a tsol_gcdb_t contributes a reference 380 1676 jpk * to the gcdb_refcnt. 381 1676 jpk * 382 1676 jpk * gc_refcnt: 383 1676 jpk * - A prefix IRE that points to an igsa_gc contributes a reference 384 1676 jpk * to the gc_refcnt. 385 1676 jpk * 386 1676 jpk * gcgrp_refcnt: 387 1676 jpk * - Every tsol_gc_t in the chain headed by tsol_gcgrp_t contributes 388 1676 jpk * a reference to the gcgrp_refcnt. 389 1676 jpk */ 390 1676 jpk static tsol_gcdb_t * 391 1676 jpk gcdb_lookup(struct rtsa_s *rp, boolean_t alloc) 392 1676 jpk { 393 1676 jpk tsol_gcdb_t *gcdb = NULL; 394 1676 jpk 395 1676 jpk if (rtsa_validate(rp) != 0) 396 1676 jpk return (NULL); 397 1676 jpk 398 1676 jpk mutex_enter(&gcdb_lock); 399 1676 jpk /* Find a copy in the cache; otherwise, create one and cache it */ 400 1676 jpk if (mod_hash_find(gcdb_hash, (mod_hash_key_t)rp, 401 1676 jpk (mod_hash_val_t *)&gcdb) == 0) { 402 1676 jpk gcdb->gcdb_refcnt++; 403 1676 jpk ASSERT(gcdb->gcdb_refcnt != 0); 404 1676 jpk 405 1676 jpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__lookup, char *, 406 1676 jpk "gcdb(1) is in gcdb_hash(global)", tsol_gcdb_t *, gcdb); 407 1676 jpk } else if (alloc) { 408 1676 jpk gcdb = kmem_zalloc(sizeof (*gcdb), KM_NOSLEEP); 409 1676 jpk if (gcdb != NULL) { 410 1676 jpk gcdb->gcdb_refcnt = 1; 411 1676 jpk gcdb->gcdb_mask = rp->rtsa_mask; 412 1676 jpk gcdb->gcdb_doi = rp->rtsa_doi; 413 1676 jpk gcdb->gcdb_slrange = rp->rtsa_slrange; 414 1676 jpk 415 1676 jpk if (mod_hash_insert(gcdb_hash, 416 1676 jpk (mod_hash_key_t)&gcdb->gcdb_attr, 417 1676 jpk (mod_hash_val_t)gcdb) != 0) { 418 1676 jpk mutex_exit(&gcdb_lock); 419 1676 jpk kmem_free(gcdb, sizeof (*gcdb)); 420 1676 jpk return (NULL); 421 1676 jpk } 422 1676 jpk 423 1676 jpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__insert, char *, 424 1676 jpk "gcdb(1) inserted in gcdb_hash(global)", 425 1676 jpk tsol_gcdb_t *, gcdb); 426 1676 jpk } 427 1676 jpk } 428 1676 jpk mutex_exit(&gcdb_lock); 429 1676 jpk return (gcdb); 430 1676 jpk } 431 1676 jpk 432 1676 jpk static void 433 1676 jpk gcdb_inactive(tsol_gcdb_t *gcdb) 434 1676 jpk { 435 1676 jpk ASSERT(MUTEX_HELD(&gcdb_lock)); 436 1676 jpk ASSERT(gcdb != NULL && gcdb->gcdb_refcnt == 0); 437 1676 jpk 438 1676 jpk (void) mod_hash_remove(gcdb_hash, (mod_hash_key_t)&gcdb->gcdb_attr, 439 1676 jpk (mod_hash_val_t *)&gcdb); 440 1676 jpk 441 1676 jpk DTRACE_PROBE2(tx__gcdb__log__info__gcdb__remove, char *, 442 1676 jpk "gcdb(1) removed from gcdb_hash(global)", 443 1676 jpk tsol_gcdb_t *, gcdb); 444 1676 jpk kmem_free(gcdb, sizeof (*gcdb)); 445 1676 jpk } 446 1676 jpk 447 1676 jpk tsol_gc_t * 448 1676 jpk gc_create(struct rtsa_s *rp, tsol_gcgrp_t *gcgrp, boolean_t *gcgrp_xtrarefp) 449 1676 jpk { 450 1676 jpk tsol_gc_t *gc; 451 1676 jpk tsol_gcdb_t *gcdb; 452 1676 jpk 453 1676 jpk *gcgrp_xtrarefp = B_TRUE; 454 1676 jpk 455 1676 jpk rw_enter(&gcgrp->gcgrp_rwlock, RW_WRITER); 456 1676 jpk if ((gcdb = gcdb_lookup(rp, B_TRUE)) == NULL) { 457 1676 jpk rw_exit(&gcgrp->gcgrp_rwlock); 458 1676 jpk return (NULL); 459 1676 jpk } 460 1676 jpk 461 1676 jpk for (gc = gcgrp->gcgrp_head; gc != NULL; gc = gc->gc_next) { 462 1676 jpk if (gc->gc_db == gcdb) { 463 1676 jpk ASSERT(gc->gc_grp == gcgrp); 464 1676 jpk 465 1676 jpk gc->gc_refcnt++; 466 1676 jpk ASSERT(gc->gc_refcnt != 0); 467 1676 jpk 468 1676 jpk GCDB_REFRELE(gcdb); 469 1676 jpk 470 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gc__create, 471 1676 jpk char *, "found gc(1) in gcgrp(2)", 472 1676 jpk tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp); 473 1676 jpk rw_exit(&gcgrp->gcgrp_rwlock); 474 1676 jpk return (gc); 475 1676 jpk } 476 1676 jpk } 477 1676 jpk 478 1676 jpk gc = kmem_zalloc(sizeof (*gc), KM_NOSLEEP); 479 1676 jpk if (gc != NULL) { 480 1676 jpk if (gcgrp->gcgrp_head == NULL) { 481 1676 jpk gcgrp->gcgrp_head = gcgrp->gcgrp_tail = gc; 482 1676 jpk } else { 483 1676 jpk gcgrp->gcgrp_tail->gc_next = gc; 484 1676 jpk gc->gc_prev = gcgrp->gcgrp_tail; 485 1676 jpk gcgrp->gcgrp_tail = gc; 486 1676 jpk } 487 1676 jpk gcgrp->gcgrp_count++; 488 1676 jpk ASSERT(gcgrp->gcgrp_count != 0); 489 1676 jpk 490 1676 jpk /* caller has incremented gcgrp reference for us */ 491 1676 jpk gc->gc_grp = gcgrp; 492 1676 jpk 493 1676 jpk gc->gc_db = gcdb; 494 1676 jpk gc->gc_refcnt = 1; 495 1676 jpk 496 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gc__create, char *, 497 1676 jpk "added gc(1) to gcgrp(2)", tsol_gc_t *, gc, 498 1676 jpk tsol_gcgrp_t *, gcgrp); 499 1676 jpk 500 1676 jpk *gcgrp_xtrarefp = B_FALSE; 501 1676 jpk } 502 1676 jpk rw_exit(&gcgrp->gcgrp_rwlock); 503 1676 jpk 504 1676 jpk return (gc); 505 1676 jpk } 506 1676 jpk 507 1676 jpk void 508 1676 jpk gc_inactive(tsol_gc_t *gc) 509 1676 jpk { 510 1676 jpk tsol_gcgrp_t *gcgrp = gc->gc_grp; 511 1676 jpk 512 1676 jpk ASSERT(gcgrp != NULL); 513 1676 jpk ASSERT(RW_WRITE_HELD(&gcgrp->gcgrp_rwlock)); 514 1676 jpk ASSERT(gc->gc_refcnt == 0); 515 1676 jpk 516 1676 jpk if (gc->gc_prev != NULL) 517 1676 jpk gc->gc_prev->gc_next = gc->gc_next; 518 1676 jpk else 519 1676 jpk gcgrp->gcgrp_head = gc->gc_next; 520 1676 jpk if (gc->gc_next != NULL) 521 1676 jpk gc->gc_next->gc_prev = gc->gc_prev; 522 1676 jpk else 523 1676 jpk gcgrp->gcgrp_tail = gc->gc_prev; 524 1676 jpk ASSERT(gcgrp->gcgrp_count > 0); 525 1676 jpk gcgrp->gcgrp_count--; 526 1676 jpk 527 1676 jpk /* drop lock before it's destroyed */ 528 1676 jpk rw_exit(&gcgrp->gcgrp_rwlock); 529 1676 jpk 530 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gc__remove, char *, 531 1676 jpk "removed inactive gc(1) from gcgrp(2)", 532 1676 jpk tsol_gc_t *, gc, tsol_gcgrp_t *, gcgrp); 533 1676 jpk 534 1676 jpk GCGRP_REFRELE(gcgrp); 535 1676 jpk 536 1676 jpk gc->gc_grp = NULL; 537 1676 jpk gc->gc_prev = gc->gc_next = NULL; 538 1676 jpk 539 1676 jpk if (gc->gc_db != NULL) 540 1676 jpk GCDB_REFRELE(gc->gc_db); 541 1676 jpk 542 1676 jpk kmem_free(gc, sizeof (*gc)); 543 1676 jpk } 544 1676 jpk 545 1676 jpk tsol_gcgrp_t * 546 1676 jpk gcgrp_lookup(tsol_gcgrp_addr_t *ga, boolean_t alloc) 547 1676 jpk { 548 1676 jpk tsol_gcgrp_t *gcgrp = NULL; 549 1676 jpk mod_hash_t *hashp; 550 1676 jpk 551 1676 jpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6); 552 1676 jpk 553 1676 jpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash; 554 1676 jpk 555 1676 jpk mutex_enter(&gcgrp_lock); 556 1676 jpk if (mod_hash_find(hashp, (mod_hash_key_t)ga, 557 1676 jpk (mod_hash_val_t *)&gcgrp) == 0) { 558 1676 jpk gcgrp->gcgrp_refcnt++; 559 1676 jpk ASSERT(gcgrp->gcgrp_refcnt != 0); 560 1676 jpk 561 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__lookup, char *, 562 1676 jpk "found gcgrp(1) in hash(2)", tsol_gcgrp_t *, gcgrp, 563 1676 jpk mod_hash_t *, hashp); 564 1676 jpk 565 1676 jpk } else if (alloc) { 566 1676 jpk gcgrp = kmem_zalloc(sizeof (*gcgrp), KM_NOSLEEP); 567 1676 jpk if (gcgrp != NULL) { 568 1676 jpk gcgrp->gcgrp_refcnt = 1; 569 1676 jpk rw_init(&gcgrp->gcgrp_rwlock, NULL, RW_DEFAULT, NULL); 570 1676 jpk bcopy(ga, &gcgrp->gcgrp_addr, sizeof (*ga)); 571 1676 jpk 572 1676 jpk if (mod_hash_insert(hashp, 573 1676 jpk (mod_hash_key_t)&gcgrp->gcgrp_addr, 574 1676 jpk (mod_hash_val_t)gcgrp) != 0) { 575 1676 jpk mutex_exit(&gcgrp_lock); 576 1676 jpk kmem_free(gcgrp, sizeof (*gcgrp)); 577 1676 jpk return (NULL); 578 1676 jpk } 579 1676 jpk 580 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__insert, 581 1676 jpk char *, "inserted gcgrp(1) in hash(2)", 582 1676 jpk tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp); 583 1676 jpk } 584 1676 jpk } 585 1676 jpk mutex_exit(&gcgrp_lock); 586 1676 jpk return (gcgrp); 587 1676 jpk } 588 1676 jpk 589 1676 jpk void 590 1676 jpk gcgrp_inactive(tsol_gcgrp_t *gcgrp) 591 1676 jpk { 592 1676 jpk tsol_gcgrp_addr_t *ga; 593 1676 jpk mod_hash_t *hashp; 594 1676 jpk 595 1676 jpk ASSERT(MUTEX_HELD(&gcgrp_lock)); 596 1676 jpk ASSERT(gcgrp != NULL && gcgrp->gcgrp_refcnt == 0); 597 1676 jpk ASSERT(gcgrp->gcgrp_head == NULL && gcgrp->gcgrp_count == 0); 598 1676 jpk 599 1676 jpk ga = &gcgrp->gcgrp_addr; 600 1676 jpk ASSERT(ga->ga_af == AF_INET || ga->ga_af == AF_INET6); 601 1676 jpk 602 1676 jpk hashp = (ga->ga_af == AF_INET) ? gcgrp4_hash : gcgrp6_hash; 603 1676 jpk (void) mod_hash_remove(hashp, (mod_hash_key_t)ga, 604 1676 jpk (mod_hash_val_t *)&gcgrp); 605 1676 jpk rw_destroy(&gcgrp->gcgrp_rwlock); 606 1676 jpk 607 1676 jpk DTRACE_PROBE3(tx__gcdb__log__info__gcgrp__remove, char *, 608 1676 jpk "removed inactive gcgrp(1) from hash(2)", 609 1676 jpk tsol_gcgrp_t *, gcgrp, mod_hash_t *, hashp); 610 1676 jpk 611 1676 jpk kmem_free(gcgrp, sizeof (*gcgrp)); 612 1676 jpk } 613 1676 jpk 614 10934 sommerfeld 615 10934 sommerfeld /* 616 10934 sommerfeld * Assign a sensitivity label to inbound traffic which arrived without 617 10934 sommerfeld * an explicit on-the-wire label. 618 10934 sommerfeld * 619 10934 sommerfeld * In the case of CIPSO-type hosts, we assume packets arriving without 620 10934 sommerfeld * a label are at the most sensitive label known for the host, most 621 10934 sommerfeld * likely involving out-of-band key management traffic (such as IKE, 622 10934 sommerfeld * etc.,) 623 10934 sommerfeld */ 624 10934 sommerfeld static boolean_t 625 10934 sommerfeld tsol_find_unlabeled_label(tsol_tpc_t *rhtp, bslabel_t *sl, uint32_t *doi) 626 10934 sommerfeld { 627 10934 sommerfeld *doi = rhtp->tpc_tp.tp_doi; 628 10934 sommerfeld switch (rhtp->tpc_tp.host_type) { 629 10934 sommerfeld case UNLABELED: 630 10934 sommerfeld *sl = rhtp->tpc_tp.tp_def_label; 631 10934 sommerfeld break; 632 10934 sommerfeld case SUN_CIPSO: 633 10934 sommerfeld *sl = rhtp->tpc_tp.tp_sl_range_cipso.upper_bound; 634 10934 sommerfeld break; 635 10934 sommerfeld default: 636 10934 sommerfeld return (B_FALSE); 637 10934 sommerfeld } 638 10934 sommerfeld setbltype(sl, SUN_SL_ID); 639 10934 sommerfeld return (B_TRUE); 640 10934 sommerfeld } 641 10934 sommerfeld 642 1676 jpk /* 643 1676 jpk * Converts CIPSO option to sensitivity label. 644 1676 jpk * Validity checks based on restrictions defined in 645 1676 jpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) (draft-ietf-cipso-ipsecurity) 646 1676 jpk */ 647 1676 jpk static boolean_t 648 1676 jpk cipso_to_sl(const uchar_t *option, bslabel_t *sl) 649 1676 jpk { 650 1676 jpk const struct cipso_option *co = (const struct cipso_option *)option; 651 1676 jpk const struct cipso_tag_type_1 *tt1; 652 1676 jpk 653 1676 jpk tt1 = (struct cipso_tag_type_1 *)&co->cipso_tag_type[0]; 654 1676 jpk if (tt1->tag_type != 1 || 655 1676 jpk tt1->tag_length < TSOL_TT1_MIN_LENGTH || 656 1676 jpk tt1->tag_length > TSOL_TT1_MAX_LENGTH || 657 1676 jpk tt1->tag_length + TSOL_CIPSO_TAG_OFFSET > co->cipso_length) 658 1676 jpk return (B_FALSE); 659 1676 jpk 660 1676 jpk bsllow(sl); /* assumed: sets compartments to all zeroes */ 661 1676 jpk LCLASS_SET((_bslabel_impl_t *)sl, tt1->tag_sl); 662 1676 jpk bcopy(tt1->tag_cat, &((_bslabel_impl_t *)sl)->compartments, 663 1676 jpk tt1->tag_length - TSOL_TT1_MIN_LENGTH); 664 1676 jpk return (B_TRUE); 665 1676 jpk } 666 1676 jpk 667 1676 jpk /* 668 11042 Erik * If present, parse the CIPSO label in the incoming packet and 669 11042 Erik * construct a ts_label_t that reflects the CIPSO label and put it in 670 11042 Erik * the ip_recv_attr_t. Later as the packet flows up through the stack any 671 10934 sommerfeld * code that needs to examine the packet label can inspect the label 672 11042 Erik * from the ira_tsl. This function is 673 11042 Erik * called right in ip_input for all packets, i.e. locally destined and 674 11042 Erik * to be forwarded packets. The forwarding path needs to examine the label 675 11042 Erik * to determine how to forward the packet. 676 1676 jpk * 677 10181 Ken * This routine pulls all message text up into the first mblk. 678 10181 Ken * For IPv4, only the first 20 bytes of the IP header are guaranteed 679 10181 Ken * to exist. For IPv6, only the IPv6 header is guaranteed to exist. 680 1676 jpk */ 681 1676 jpk boolean_t 682 11042 Erik tsol_get_pkt_label(mblk_t *mp, int version, ip_recv_attr_t *ira) 683 1676 jpk { 684 10934 sommerfeld tsol_tpc_t *src_rhtp = NULL; 685 1676 jpk uchar_t *opt_ptr = NULL; 686 1676 jpk const ipha_t *ipha; 687 1676 jpk bslabel_t sl; 688 1676 jpk uint32_t doi; 689 1676 jpk tsol_ip_label_t label_type; 690 10934 sommerfeld uint32_t label_flags = 0; /* flags to set in label */ 691 1676 jpk const cipso_option_t *co; 692 1676 jpk const void *src; 693 1676 jpk const ip6_t *ip6h; 694 8778 Erik cred_t *credp; 695 10934 sommerfeld int proto; 696 1676 jpk 697 1676 jpk ASSERT(DB_TYPE(mp) == M_DATA); 698 9710 Ken 699 9710 Ken if (mp->b_cont != NULL && !pullupmsg(mp, -1)) 700 9710 Ken return (B_FALSE); 701 1676 jpk 702 1676 jpk if (version == IPV4_VERSION) { 703 10181 Ken ASSERT(MBLKL(mp) >= IP_SIMPLE_HDR_LENGTH); 704 1676 jpk ipha = (const ipha_t *)mp->b_rptr; 705 1676 jpk src = &ipha->ipha_src; 706 10181 Ken if (!tsol_get_option_v4(mp, &label_type, &opt_ptr)) 707 10181 Ken return (B_FALSE); 708 1676 jpk } else { 709 10181 Ken ASSERT(MBLKL(mp) >= IPV6_HDR_LEN); 710 1676 jpk ip6h = (const ip6_t *)mp->b_rptr; 711 1676 jpk src = &ip6h->ip6_src; 712 10181 Ken if (!tsol_get_option_v6(mp, &label_type, &opt_ptr)) 713 10181 Ken return (B_FALSE); 714 1676 jpk } 715 1676 jpk 716 1676 jpk switch (label_type) { 717 1676 jpk case OPT_CIPSO: 718 1676 jpk /* 719 1676 jpk * Convert the CIPSO label to the internal format 720 1676 jpk * and attach it to the dblk cred. 721 1676 jpk * Validity checks based on restrictions defined in 722 1676 jpk * COMMERCIAL IP SECURITY OPTION (CIPSO 2.2) 723 1676 jpk * (draft-ietf-cipso-ipsecurity) 724 1676 jpk */ 725 1676 jpk if (version == IPV6_VERSION && ip6opt_ls == 0) 726 1676 jpk return (B_FALSE); 727 1676 jpk co = (const struct cipso_option *)opt_ptr; 728 1676 jpk if ((co->cipso_length < 729 1676 jpk TSOL_CIPSO_TAG_OFFSET + TSOL_TT1_MIN_LENGTH) || 730 1676 jpk (co->cipso_length > IP_MAX_OPT_LENGTH)) 731 1676 jpk return (B_FALSE); 732 1676 jpk bcopy(co->cipso_doi, &doi, sizeof (doi)); 733 1676 jpk doi = ntohl(doi); 734 1676 jpk if (!cipso_to_sl(opt_ptr, &sl)) 735 1676 jpk return (B_FALSE); 736 1676 jpk setbltype(&sl, SUN_SL_ID); 737 10934 sommerfeld 738 10934 sommerfeld /* 739 10934 sommerfeld * If the source was unlabeled, then flag as such, 740 10934 sommerfeld * (since CIPSO routers may add headers) 741 10934 sommerfeld */ 742 10934 sommerfeld 743 10934 sommerfeld if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL) 744 10934 sommerfeld return (B_FALSE); 745 10934 sommerfeld 746 10934 sommerfeld if (src_rhtp->tpc_tp.host_type == UNLABELED) 747 10934 sommerfeld label_flags = TSLF_UNLABELED; 748 10934 sommerfeld 749 10934 sommerfeld TPC_RELE(src_rhtp); 750 10934 sommerfeld 751 1676 jpk break; 752 1676 jpk 753 1676 jpk case OPT_NONE: 754 1676 jpk /* 755 10934 sommerfeld * Handle special cases that may not be labeled, even 756 1676 jpk * though the sending system may otherwise be configured as 757 1676 jpk * labeled. 758 1676 jpk * - IGMP 759 1676 jpk * - IPv4 ICMP Router Discovery 760 1676 jpk * - IPv6 Neighbor Discovery 761 10934 sommerfeld * - IPsec ESP 762 1676 jpk */ 763 1676 jpk if (version == IPV4_VERSION) { 764 10934 sommerfeld proto = ipha->ipha_protocol; 765 10934 sommerfeld if (proto == IPPROTO_IGMP) 766 1676 jpk return (B_TRUE); 767 10934 sommerfeld if (proto == IPPROTO_ICMP) { 768 1676 jpk const struct icmp *icmp = (const struct icmp *) 769 1676 jpk (mp->b_rptr + IPH_HDR_LENGTH(ipha)); 770 1676 jpk 771 10181 Ken if ((uchar_t *)icmp + ICMP_MINLEN > mp->b_wptr) 772 10181 Ken return (B_FALSE); 773 1676 jpk if (icmp->icmp_type == ICMP_ROUTERADVERT || 774 1676 jpk icmp->icmp_type == ICMP_ROUTERSOLICIT) 775 1676 jpk return (B_TRUE); 776 1676 jpk } 777 1676 jpk } else { 778 10934 sommerfeld proto = ip6h->ip6_nxt; 779 10934 sommerfeld if (proto == IPPROTO_ICMPV6) { 780 1676 jpk const icmp6_t *icmp6 = (const icmp6_t *) 781 1676 jpk (mp->b_rptr + IPV6_HDR_LEN); 782 1676 jpk 783 1676 jpk if ((uchar_t *)icmp6 + ICMP6_MINLEN > 784 10181 Ken mp->b_wptr) 785 10181 Ken return (B_FALSE); 786 1676 jpk if (icmp6->icmp6_type >= MLD_LISTENER_QUERY && 787 1676 jpk icmp6->icmp6_type <= ICMP6_MAX_INFO_TYPE) 788 1676 jpk return (B_TRUE); 789 1676 jpk } 790 1676 jpk } 791 1676 jpk 792 1676 jpk /* 793 1676 jpk * Look up the tnrhtp database and get the implicit label 794 10934 sommerfeld * that is associated with the sending host and attach 795 1676 jpk * it to the packet. 796 1676 jpk */ 797 1676 jpk if ((src_rhtp = find_tpc(src, version, B_FALSE)) == NULL) 798 1676 jpk return (B_FALSE); 799 1676 jpk 800 10934 sommerfeld /* 801 10934 sommerfeld * If peer is label-aware, mark as "implicit" rather than 802 10934 sommerfeld * "unlabeled" to cause appropriate mac-exempt processing 803 10934 sommerfeld * to happen. 804 10934 sommerfeld */ 805 10934 sommerfeld if (src_rhtp->tpc_tp.host_type == SUN_CIPSO) 806 10934 sommerfeld label_flags = TSLF_IMPLICIT_IN; 807 10934 sommerfeld else if (src_rhtp->tpc_tp.host_type == UNLABELED) 808 10934 sommerfeld label_flags = TSLF_UNLABELED; 809 10934 sommerfeld else { 810 10934 sommerfeld DTRACE_PROBE2(tx__get__pkt__label, char *, 811 10934 sommerfeld "template(1) has unknown hosttype", 812 10934 sommerfeld tsol_tpc_t *, src_rhtp); 813 10934 sommerfeld } 814 10934 sommerfeld 815 10934 sommerfeld 816 10934 sommerfeld if (!tsol_find_unlabeled_label(src_rhtp, &sl, &doi)) { 817 1676 jpk TPC_RELE(src_rhtp); 818 1676 jpk return (B_FALSE); 819 1676 jpk } 820 1676 jpk TPC_RELE(src_rhtp); 821 1676 jpk break; 822 1676 jpk 823 1676 jpk default: 824 1676 jpk return (B_FALSE); 825 1676 jpk } 826 1676 jpk 827 11042 Erik if (ira->ira_cred == NULL) { 828 8778 Erik credp = newcred_from_bslabel(&sl, doi, KM_NOSLEEP); 829 11042 Erik if (credp == NULL) 830 11042 Erik return (B_FALSE); 831 1676 jpk } else { 832 11077 Erik credp = copycred_from_bslabel(ira->ira_cred, &sl, doi, 833 1676 jpk KM_NOSLEEP); 834 11077 Erik if (credp == NULL) 835 11042 Erik return (B_FALSE); 836 11042 Erik if (ira->ira_free_flags & IRA_FREE_CRED) { 837 11042 Erik crfree(ira->ira_cred); 838 11042 Erik ira->ira_free_flags &= ~IRA_FREE_CRED; 839 11042 Erik ira->ira_cred = NULL; 840 11042 Erik } 841 1676 jpk } 842 10934 sommerfeld 843 11042 Erik /* 844 11042 Erik * Put the label in ira_tsl for convinience, while keeping 845 11042 Erik * the cred in ira_cred for getpeerucred which is used to get 846 11042 Erik * labels with TX. 847 11042 Erik * Note: no explicit refcnt/free_flag for ira_tsl. The free_flag 848 11042 Erik * for IRA_FREE_CRED is sufficient for both. 849 11042 Erik */ 850 11042 Erik ira->ira_tsl = crgetlabel(credp); 851 11042 Erik ira->ira_cred = credp; 852 11042 Erik ira->ira_free_flags |= IRA_FREE_CRED; 853 10934 sommerfeld 854 11042 Erik ira->ira_tsl->tsl_flags |= label_flags; 855 1676 jpk return (B_TRUE); 856 1676 jpk } 857 1676 jpk 858 1676 jpk /* 859 1676 jpk * This routine determines whether the given packet should be accepted locally. 860 1676 jpk * It does a range/set check on the packet's label by looking up the given 861 1676 jpk * address in the remote host database. 862 1676 jpk */ 863 1676 jpk boolean_t 864 1676 jpk tsol_receive_local(const mblk_t *mp, const void *addr, uchar_t version, 865 11042 Erik ip_recv_attr_t *ira, const conn_t *connp) 866 1676 jpk { 867 1676 jpk const cred_t *credp; 868 1676 jpk ts_label_t *plabel, *conn_plabel; 869 1676 jpk tsol_tpc_t *tp; 870 1676 jpk boolean_t retv; 871 1676 jpk const bslabel_t *label, *conn_label; 872 11042 Erik boolean_t shared_addr = (ira->ira_flags & IRAF_TX_SHARED_ADDR); 873 1676 jpk 874 1676 jpk /* 875 11042 Erik * tsol_get_pkt_label intentionally avoids the labeling process for: 876 11042 Erik * - IPv6 router and neighbor discovery as well as redirects. 877 11042 Erik * - MLD packets. (Anything between ICMPv6 code 130 and 138.) 878 11042 Erik * - IGMP packets. 879 11042 Erik * - IPv4 router discovery. 880 11077 Erik * In those cases ira_cred is NULL. 881 1676 jpk */ 882 11042 Erik credp = ira->ira_cred; 883 11042 Erik if (credp == NULL) 884 1676 jpk return (B_TRUE); 885 1676 jpk 886 1676 jpk /* 887 1676 jpk * If this packet is from the inside (not a remote host) and has the 888 1676 jpk * same zoneid as the selected destination, then no checks are 889 1676 jpk * necessary. Membership in the zone is enough proof. This is 890 1676 jpk * intended to be a hot path through this function. 891 11042 Erik * Note: Using crgetzone here is ok since the peer is local. 892 1676 jpk */ 893 1676 jpk if (!crisremote(credp) && 894 1676 jpk crgetzone(credp) == crgetzone(connp->conn_cred)) 895 1676 jpk return (B_TRUE); 896 1676 jpk 897 11042 Erik plabel = ira->ira_tsl; 898 1676 jpk conn_plabel = crgetlabel(connp->conn_cred); 899 1676 jpk ASSERT(plabel != NULL && conn_plabel != NULL); 900 1676 jpk 901 1676 jpk label = label2bslabel(plabel); 902 11042 Erik conn_label = label2bslabel(conn_plabel); 903 1676 jpk 904 10934 sommerfeld 905 10934 sommerfeld /* 906 10934 sommerfeld * Implicitly labeled packets from label-aware sources 907 10934 sommerfeld * go only to privileged receivers 908 10934 sommerfeld */ 909 10934 sommerfeld if ((plabel->tsl_flags & TSLF_IMPLICIT_IN) && 910 10934 sommerfeld (connp->conn_mac_mode != CONN_MAC_IMPLICIT)) { 911 10934 sommerfeld DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac_impl, 912 10934 sommerfeld char *, 913 10934 sommerfeld "implicitly labeled packet mp(1) for conn(2) " 914 10934 sommerfeld "which isn't in implicit mac mode", 915 10934 sommerfeld mblk_t *, mp, conn_t *, connp); 916 10934 sommerfeld 917 10934 sommerfeld return (B_FALSE); 918 10934 sommerfeld } 919 10934 sommerfeld 920 10934 sommerfeld 921 1676 jpk /* 922 1676 jpk * MLPs are always validated using the range and set of the local 923 1676 jpk * address, even when the remote host is unlabeled. 924 1676 jpk */ 925 1676 jpk if (connp->conn_mlp_type == mlptBoth || 926 1676 jpk /* LINTED: no consequent */ 927 1676 jpk connp->conn_mlp_type == (shared_addr ? mlptShared : mlptPrivate)) { 928 1676 jpk ; 929 1676 jpk 930 1676 jpk /* 931 1676 jpk * If this is a packet from an unlabeled sender, then we must apply 932 1676 jpk * different rules. If the label is equal to the zone's label, then 933 1676 jpk * it's allowed. If it's not equal, but the zone is either the global 934 1676 jpk * zone or the label is dominated by the zone's label, then allow it 935 1676 jpk * as long as it's in the range configured for the destination. 936 1676 jpk */ 937 1676 jpk } else if (plabel->tsl_flags & TSLF_UNLABELED) { 938 1676 jpk if (plabel->tsl_doi == conn_plabel->tsl_doi && 939 1676 jpk blequal(label, conn_label)) 940 1676 jpk return (B_TRUE); 941 1676 jpk 942 10934 sommerfeld if ((connp->conn_mac_mode == CONN_MAC_DEFAULT) || 943 11042 Erik (!connp->conn_zone_is_global && 944 1676 jpk (plabel->tsl_doi != conn_plabel->tsl_doi || 945 1676 jpk !bldominates(conn_label, label)))) { 946 1676 jpk DTRACE_PROBE3( 947 1676 jpk tx__ip__log__drop__receivelocal__mac_unl, 948 1676 jpk char *, 949 1676 jpk "unlabeled packet mp(1) fails mac for conn(2)", 950 1676 jpk mblk_t *, mp, conn_t *, connp); 951 1676 jpk return (B_FALSE); 952 1676 jpk } 953 1676 jpk 954 1676 jpk /* 955 4448 kp158701 * If this is a packet from a labeled sender, verify the 956 4448 kp158701 * label on the packet matches the connection label. 957 1676 jpk */ 958 4448 kp158701 } else { 959 4448 kp158701 if (plabel->tsl_doi != conn_plabel->tsl_doi || 960 4448 kp158701 !blequal(label, conn_label)) { 961 4448 kp158701 DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac__slp, 962 4448 kp158701 char *, 963 4448 kp158701 "packet mp(1) failed label match to SLP conn(2)", 964 4448 kp158701 mblk_t *, mp, conn_t *, connp); 965 4448 kp158701 return (B_FALSE); 966 4448 kp158701 } 967 1676 jpk /* 968 4448 kp158701 * No further checks will be needed if this is a zone- 969 4448 kp158701 * specific address because (1) The process for bringing up 970 4448 kp158701 * the interface ensures the zone's label is within the zone- 971 4448 kp158701 * specific address's valid label range; (2) For cases where 972 4448 kp158701 * the conn is bound to the unspecified addresses, ip fanout 973 4448 kp158701 * logic ensures conn's zoneid equals the dest addr's zoneid; 974 4448 kp158701 * (3) Mac-exempt and mlp logic above already handle all 975 4448 kp158701 * cases where the zone label may not be the same as the 976 4448 kp158701 * conn label. 977 1676 jpk */ 978 4448 kp158701 if (!shared_addr) 979 1676 jpk return (B_TRUE); 980 1676 jpk } 981 1676 jpk 982 1676 jpk tp = find_tpc(addr, version, B_FALSE); 983 1676 jpk if (tp == NULL) { 984 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__no__tnr, 985 1676 jpk char *, "dropping mp(1), host(2) lacks entry", 986 1676 jpk mblk_t *, mp, void *, addr); 987 1676 jpk return (B_FALSE); 988 1676 jpk } 989 1676 jpk 990 1676 jpk /* 991 1676 jpk * The local host address should not be unlabeled at this point. The 992 1676 jpk * only way this can happen is that the destination isn't unicast. We 993 1676 jpk * assume that the packet should not have had a label, and thus should 994 1676 jpk * have been handled by the TSLF_UNLABELED logic above. 995 1676 jpk */ 996 1676 jpk if (tp->tpc_tp.host_type == UNLABELED) { 997 1676 jpk retv = B_FALSE; 998 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__flag, char *, 999 1676 jpk "mp(1) unlabeled source, but tp is not unlabeled.", 1000 1676 jpk mblk_t *, mp, tsol_tpc_t *, tp); 1001 1676 jpk 1002 1676 jpk } else if (tp->tpc_tp.host_type != SUN_CIPSO) { 1003 1676 jpk retv = B_FALSE; 1004 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__tptype, char *, 1005 1676 jpk "delivering mp(1), found unrecognized tpc(2) type.", 1006 1676 jpk mblk_t *, mp, tsol_tpc_t *, tp); 1007 1676 jpk 1008 1676 jpk } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) { 1009 1676 jpk retv = B_FALSE; 1010 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *, 1011 1676 jpk "mp(1) could not be delievered to tp(2), doi mismatch", 1012 1676 jpk mblk_t *, mp, tsol_tpc_t *, tp); 1013 1676 jpk 1014 1676 jpk } else if (!_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) && 1015 1676 jpk !blinlset(label, tp->tpc_tp.tp_sl_set_cipso)) { 1016 1676 jpk retv = B_FALSE; 1017 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__receivelocal__mac, char *, 1018 1676 jpk "mp(1) could not be delievered to tp(2), bad mac", 1019 1676 jpk mblk_t *, mp, tsol_tpc_t *, tp); 1020 1676 jpk } else { 1021 1676 jpk retv = B_TRUE; 1022 1676 jpk } 1023 1676 jpk 1024 1676 jpk TPC_RELE(tp); 1025 1676 jpk 1026 1676 jpk return (retv); 1027 1676 jpk } 1028 1676 jpk 1029 1676 jpk boolean_t 1030 11042 Erik tsol_can_accept_raw(mblk_t *mp, ip_recv_attr_t *ira, boolean_t check_host) 1031 1676 jpk { 1032 1676 jpk ts_label_t *plabel = NULL; 1033 1676 jpk tsol_tpc_t *src_rhtp, *dst_rhtp; 1034 1676 jpk boolean_t retv; 1035 1676 jpk 1036 11042 Erik plabel = ira->ira_tsl; 1037 1676 jpk 1038 1676 jpk /* We are bootstrapping or the internal template was never deleted */ 1039 1676 jpk if (plabel == NULL) 1040 1676 jpk return (B_TRUE); 1041 1676 jpk 1042 1676 jpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 1043 1676 jpk ipha_t *ipha = (ipha_t *)mp->b_rptr; 1044 1676 jpk 1045 1676 jpk src_rhtp = find_tpc(&ipha->ipha_src, IPV4_VERSION, 1046 1676 jpk B_FALSE); 1047 1676 jpk if (src_rhtp == NULL) 1048 1676 jpk return (B_FALSE); 1049 1676 jpk dst_rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, 1050 1676 jpk B_FALSE); 1051 1676 jpk } else { 1052 1676 jpk ip6_t *ip6h = (ip6_t *)mp->b_rptr; 1053 1676 jpk 1054 1676 jpk src_rhtp = find_tpc(&ip6h->ip6_src, IPV6_VERSION, 1055 1676 jpk B_FALSE); 1056 1676 jpk if (src_rhtp == NULL) 1057 1676 jpk return (B_FALSE); 1058 1676 jpk dst_rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION, 1059 1676 jpk B_FALSE); 1060 1676 jpk } 1061 1676 jpk if (dst_rhtp == NULL) { 1062 1676 jpk TPC_RELE(src_rhtp); 1063 1676 jpk return (B_FALSE); 1064 1676 jpk } 1065 1676 jpk 1066 1676 jpk if (label2doi(plabel) != src_rhtp->tpc_tp.tp_doi) { 1067 1676 jpk retv = B_FALSE; 1068 1676 jpk 1069 1676 jpk /* 1070 1676 jpk * Check that the packet's label is in the correct range for labeled 1071 1676 jpk * sender, or is equal to the default label for unlabeled sender. 1072 1676 jpk */ 1073 1676 jpk } else if ((src_rhtp->tpc_tp.host_type != UNLABELED && 1074 1676 jpk !_blinrange(label2bslabel(plabel), 1075 1676 jpk &src_rhtp->tpc_tp.tp_sl_range_cipso) && 1076 1676 jpk !blinlset(label2bslabel(plabel), 1077 1676 jpk src_rhtp->tpc_tp.tp_sl_set_cipso)) || 1078 1676 jpk (src_rhtp->tpc_tp.host_type == UNLABELED && 1079 1676 jpk !blequal(&plabel->tsl_label, &src_rhtp->tpc_tp.tp_def_label))) { 1080 1676 jpk retv = B_FALSE; 1081 1676 jpk 1082 1676 jpk } else if (check_host) { 1083 1676 jpk retv = B_TRUE; 1084 1676 jpk 1085 1676 jpk /* 1086 1676 jpk * Until we have SL range in the Zone structure, pass it 1087 1676 jpk * when our own address lookup returned an internal entry. 1088 1676 jpk */ 1089 1676 jpk } else switch (dst_rhtp->tpc_tp.host_type) { 1090 1676 jpk case UNLABELED: 1091 1676 jpk retv = B_TRUE; 1092 1676 jpk break; 1093 1676 jpk 1094 1676 jpk case SUN_CIPSO: 1095 1676 jpk retv = _blinrange(label2bslabel(plabel), 1096 1676 jpk &dst_rhtp->tpc_tp.tp_sl_range_cipso) || 1097 1676 jpk blinlset(label2bslabel(plabel), 1098 1676 jpk dst_rhtp->tpc_tp.tp_sl_set_cipso); 1099 1676 jpk break; 1100 1676 jpk 1101 1676 jpk default: 1102 1676 jpk retv = B_FALSE; 1103 1676 jpk } 1104 1676 jpk TPC_RELE(src_rhtp); 1105 1676 jpk TPC_RELE(dst_rhtp); 1106 1676 jpk return (retv); 1107 1676 jpk } 1108 1676 jpk 1109 1676 jpk /* 1110 1676 jpk * This routine determines whether a response to a failed packet delivery or 1111 1676 jpk * connection should be sent back. By default, the policy is to allow such 1112 1676 jpk * messages to be sent at all times, as these messages reveal little useful 1113 1676 jpk * information and are healthy parts of TCP/IP networking. 1114 1676 jpk * 1115 1676 jpk * If tsol_strict_error is set, then we do strict tests: if the packet label is 1116 1676 jpk * within the label range/set of this host/zone, return B_TRUE; otherwise 1117 1676 jpk * return B_FALSE, which causes the packet to be dropped silently. 1118 1676 jpk * 1119 1676 jpk * Note that tsol_get_pkt_label will cause the packet to drop if the sender is 1120 1676 jpk * marked as labeled in the remote host database, but the packet lacks a label. 1121 1676 jpk * This means that we don't need to do a lookup on the source; the 1122 1676 jpk * TSLF_UNLABELED flag is sufficient. 1123 1676 jpk */ 1124 1676 jpk boolean_t 1125 11042 Erik tsol_can_reply_error(const mblk_t *mp, ip_recv_attr_t *ira) 1126 1676 jpk { 1127 1676 jpk ts_label_t *plabel = NULL; 1128 1676 jpk tsol_tpc_t *rhtp; 1129 1676 jpk const ipha_t *ipha; 1130 1676 jpk const ip6_t *ip6h; 1131 1676 jpk boolean_t retv; 1132 1676 jpk bslabel_t *pktbs; 1133 1676 jpk 1134 1676 jpk /* Caller must pull up at least the IP header */ 1135 1676 jpk ASSERT(MBLKL(mp) >= (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION ? 1136 1676 jpk sizeof (*ipha) : sizeof (*ip6h))); 1137 1676 jpk 1138 1676 jpk if (!tsol_strict_error) 1139 1676 jpk return (B_TRUE); 1140 1676 jpk 1141 11042 Erik plabel = ira->ira_tsl; 1142 1676 jpk 1143 1676 jpk /* We are bootstrapping or the internal template was never deleted */ 1144 1676 jpk if (plabel == NULL) 1145 1676 jpk return (B_TRUE); 1146 1676 jpk 1147 10934 sommerfeld if (plabel->tsl_flags & TSLF_IMPLICIT_IN) { 1148 10934 sommerfeld DTRACE_PROBE3(tx__ip__log__drop__replyerror__unresolved__label, 1149 10934 sommerfeld char *, 1150 10934 sommerfeld "cannot send error report for packet mp(1) with " 1151 10934 sommerfeld "unresolved security label sl(2)", 1152 10934 sommerfeld mblk_t *, mp, ts_label_t *, plabel); 1153 10934 sommerfeld return (B_FALSE); 1154 10934 sommerfeld } 1155 10934 sommerfeld 1156 10934 sommerfeld 1157 1676 jpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 1158 1676 jpk ipha = (const ipha_t *)mp->b_rptr; 1159 1676 jpk rhtp = find_tpc(&ipha->ipha_dst, IPV4_VERSION, B_FALSE); 1160 1676 jpk } else { 1161 1676 jpk ip6h = (const ip6_t *)mp->b_rptr; 1162 1676 jpk rhtp = find_tpc(&ip6h->ip6_dst, IPV6_VERSION, B_FALSE); 1163 1676 jpk } 1164 1676 jpk 1165 1676 jpk if (rhtp == NULL || label2doi(plabel) != rhtp->tpc_tp.tp_doi) { 1166 1676 jpk retv = B_FALSE; 1167 1676 jpk } else { 1168 1676 jpk /* 1169 1676 jpk * If we're in the midst of forwarding, then the destination 1170 1676 jpk * address might not be labeled. In that case, allow unlabeled 1171 1676 jpk * packets through only if the default label is the same, and 1172 1676 jpk * labeled ones if they dominate. 1173 1676 jpk */ 1174 1676 jpk pktbs = label2bslabel(plabel); 1175 1676 jpk switch (rhtp->tpc_tp.host_type) { 1176 1676 jpk case UNLABELED: 1177 1676 jpk if (plabel->tsl_flags & TSLF_UNLABELED) { 1178 1676 jpk retv = blequal(pktbs, 1179 1676 jpk &rhtp->tpc_tp.tp_def_label); 1180 1676 jpk } else { 1181 1676 jpk retv = bldominates(pktbs, 1182 1676 jpk &rhtp->tpc_tp.tp_def_label); 1183 1676 jpk } 1184 1676 jpk break; 1185 1676 jpk 1186 1676 jpk case SUN_CIPSO: 1187 1676 jpk retv = _blinrange(pktbs, 1188 1676 jpk &rhtp->tpc_tp.tp_sl_range_cipso) || 1189 1676 jpk blinlset(pktbs, rhtp->tpc_tp.tp_sl_set_cipso); 1190 1676 jpk break; 1191 1676 jpk 1192 1676 jpk default: 1193 1676 jpk retv = B_FALSE; 1194 1676 jpk break; 1195 1676 jpk } 1196 1676 jpk } 1197 1676 jpk 1198 1676 jpk if (rhtp != NULL) 1199 1676 jpk TPC_RELE(rhtp); 1200 1676 jpk 1201 1676 jpk return (retv); 1202 1676 jpk } 1203 1676 jpk 1204 1676 jpk /* 1205 11042 Erik * Finds the zone associated with the receive attributes. Returns GLOBAL_ZONEID 1206 11042 Erik * if the zone cannot be located. 1207 1676 jpk * 1208 1676 jpk * This is used by the classifier when the packet matches an ALL_ZONES IRE, and 1209 1676 jpk * there's no MLP defined. 1210 3448 dh155122 * 1211 3448 dh155122 * Note that we assume that this is only invoked in the ALL_ZONES case. 1212 11042 Erik * Handling other cases would require handling exclusive IP zones where either 1213 3448 dh155122 * this routine or the callers would have to map from 1214 3448 dh155122 * the zoneid (zone->zone_id) to what IP uses in conn_zoneid etc. 1215 1676 jpk */ 1216 1676 jpk zoneid_t 1217 11042 Erik tsol_attr_to_zoneid(const ip_recv_attr_t *ira) 1218 1676 jpk { 1219 1676 jpk zone_t *zone; 1220 1676 jpk ts_label_t *label; 1221 1676 jpk 1222 11042 Erik if ((label = ira->ira_tsl) != NULL) { 1223 11042 Erik zone = zone_find_by_label(label); 1224 11042 Erik if (zone != NULL) { 1225 11042 Erik zoneid_t zoneid = zone->zone_id; 1226 1676 jpk 1227 11042 Erik zone_rele(zone); 1228 11042 Erik return (zoneid); 1229 1676 jpk } 1230 1676 jpk } 1231 1676 jpk return (GLOBAL_ZONEID); 1232 1676 jpk } 1233 1676 jpk 1234 1676 jpk int 1235 1676 jpk tsol_ire_match_gwattr(ire_t *ire, const ts_label_t *tsl) 1236 1676 jpk { 1237 1676 jpk int error = 0; 1238 1676 jpk tsol_ire_gw_secattr_t *attrp = NULL; 1239 1676 jpk tsol_tnrhc_t *gw_rhc = NULL; 1240 1676 jpk tsol_gcgrp_t *gcgrp = NULL; 1241 1676 jpk tsol_gc_t *gc = NULL; 1242 1676 jpk in_addr_t ga_addr4; 1243 1676 jpk void *paddr = NULL; 1244 1676 jpk 1245 1676 jpk /* Not in Trusted mode or IRE is local/loopback/broadcast/interface */ 1246 1676 jpk if (!is_system_labeled() || 1247 1676 jpk (ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK | IRE_BROADCAST | 1248 11042 Erik IRE_IF_ALL | IRE_MULTICAST | IRE_NOROUTE))) 1249 1676 jpk goto done; 1250 1676 jpk 1251 1676 jpk /* 1252 1676 jpk * If we don't have a label to compare with, or the IRE does not 1253 1676 jpk * contain any gateway security attributes, there's not much that 1254 1676 jpk * we can do. We let the former case pass, and the latter fail, 1255 1676 jpk * since the IRE doesn't qualify for a match due to the lack of 1256 1676 jpk * security attributes. 1257 1676 jpk */ 1258 1676 jpk if (tsl == NULL || ire->ire_gw_secattr == NULL) { 1259 1676 jpk if (tsl != NULL) { 1260 10934 sommerfeld DTRACE_PROBE3( 1261 10934 sommerfeld tx__ip__log__drop__irematch__nogwsec, char *, 1262 10934 sommerfeld "ire(1) lacks ire_gw_secattr when matching " 1263 10934 sommerfeld "label(2)", ire_t *, ire, ts_label_t *, tsl); 1264 1676 jpk error = EACCES; 1265 1676 jpk } 1266 1676 jpk goto done; 1267 1676 jpk } 1268 1676 jpk 1269 1676 jpk attrp = ire->ire_gw_secattr; 1270 1676 jpk 1271 1676 jpk /* 1272 1676 jpk * The possible lock order scenarios related to the tsol gateway 1273 1676 jpk * attribute locks are documented at the beginning of ip.c in the 1274 1676 jpk * lock order scenario section. 1275 1676 jpk */ 1276 1676 jpk mutex_enter(&attrp->igsa_lock); 1277 1676 jpk 1278 1676 jpk /* 1279 11042 Erik * We seek the group 1280 1676 jpk * structure which contains all security credentials of the gateway. 1281 11042 Erik * An offline IRE is associated with at most one gateway credential. 1282 1676 jpk */ 1283 11042 Erik if ((gc = attrp->igsa_gc) != NULL) { 1284 1676 jpk gcgrp = gc->gc_grp; 1285 1676 jpk ASSERT(gcgrp != NULL); 1286 1676 jpk rw_enter(&gcgrp->gcgrp_rwlock, RW_READER); 1287 11042 Erik GCGRP_REFHOLD(gcgrp); 1288 1676 jpk } 1289 1676 jpk 1290 1676 jpk if ((gw_rhc = attrp->igsa_rhc) != NULL) { 1291 1676 jpk /* 1292 1676 jpk * If our cached entry has grown stale, then discard it so we 1293 1676 jpk * can get a new one. 1294 1676 jpk */ 1295 1676 jpk if (gw_rhc->rhc_invalid || gw_rhc->rhc_tpc->tpc_invalid) { 1296 1676 jpk TNRHC_RELE(gw_rhc); 1297 1676 jpk attrp->igsa_rhc = gw_rhc = NULL; 1298 1676 jpk } else { 1299 1676 jpk TNRHC_HOLD(gw_rhc) 1300 1676 jpk } 1301 1676 jpk } 1302 1676 jpk 1303 1676 jpk /* Last attempt at loading the template had failed; try again */ 1304 1676 jpk if (gw_rhc == NULL) { 1305 1676 jpk if (gcgrp != NULL) { 1306 1676 jpk tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr; 1307 1676 jpk 1308 1676 jpk if (ire->ire_ipversion == IPV4_VERSION) { 1309 1676 jpk ASSERT(ga->ga_af == AF_INET); 1310 1676 jpk IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4); 1311 1676 jpk paddr = &ga_addr4; 1312 1676 jpk } else { 1313 1676 jpk ASSERT(ga->ga_af == AF_INET6); 1314 1676 jpk paddr = &ga->ga_addr; 1315 1676 jpk } 1316 11042 Erik } else if (ire->ire_type & IRE_OFFLINK) { 1317 11042 Erik if (ire->ire_ipversion == IPV6_VERSION) 1318 11042 Erik paddr = &ire->ire_gateway_addr_v6; 1319 11042 Erik else if (ire->ire_ipversion == IPV4_VERSION) 1320 11042 Erik paddr = &ire->ire_gateway_addr; 1321 1676 jpk } 1322 1676 jpk 1323 1676 jpk /* We've found a gateway address to do the template lookup */ 1324 1676 jpk if (paddr != NULL) { 1325 1676 jpk ASSERT(gw_rhc == NULL); 1326 3292 kp158701 gw_rhc = find_rhc(paddr, ire->ire_ipversion, B_FALSE); 1327 1676 jpk if (gw_rhc != NULL) { 1328 1676 jpk /* 1329 1676 jpk * Note that if the lookup above returned an 1330 1676 jpk * internal template, we'll use it for the 1331 1676 jpk * time being, and do another lookup next 1332 1676 jpk * time around. 1333 1676 jpk */ 1334 1676 jpk /* Another thread has loaded the template? */ 1335 1676 jpk if (attrp->igsa_rhc != NULL) { 1336 1676 jpk TNRHC_RELE(gw_rhc) 1337 1676 jpk /* reload, it could be different */ 1338 1676 jpk gw_rhc = attrp->igsa_rhc; 1339 1676 jpk } else { 1340 1676 jpk attrp->igsa_rhc = gw_rhc; 1341 1676 jpk } 1342 1676 jpk /* 1343 1676 jpk * Hold an extra reference just like we did 1344 1676 jpk * above prior to dropping the igsa_lock. 1345 1676 jpk */ 1346 1676 jpk TNRHC_HOLD(gw_rhc) 1347 1676 jpk } 1348 1676 jpk } 1349 1676 jpk } 1350 1676 jpk 1351 1676 jpk mutex_exit(&attrp->igsa_lock); 1352 1676 jpk /* Gateway template not found */ 1353 1676 jpk if (gw_rhc == NULL) { 1354 1676 jpk /* 1355 1676 jpk * If destination address is directly reachable through an 1356 1676 jpk * interface rather than through a learned route, pass it. 1357 1676 jpk */ 1358 1676 jpk if (paddr != NULL) { 1359 1676 jpk DTRACE_PROBE3( 1360 1676 jpk tx__ip__log__drop__irematch__nogwtmpl, char *, 1361 1676 jpk "ire(1), label(2) off-link with no gw_rhc", 1362 1676 jpk ire_t *, ire, ts_label_t *, tsl); 1363 1676 jpk error = EINVAL; 1364 1676 jpk } 1365 1676 jpk goto done; 1366 1676 jpk } 1367 1676 jpk 1368 1676 jpk if (gc != NULL) { 1369 11042 Erik 1370 1676 jpk tsol_gcdb_t *gcdb; 1371 1676 jpk /* 1372 1676 jpk * In the case of IRE_CACHE we've got one or more gateway 1373 1676 jpk * security credentials to compare against the passed in label. 1374 1676 jpk * Perform label range comparison against each security 1375 1676 jpk * credential of the gateway. In the case of a prefix ire 1376 1676 jpk * we need to match against the security attributes of 1377 1676 jpk * just the route itself, so the loop is executed only once. 1378 1676 jpk */ 1379 1676 jpk ASSERT(gcgrp != NULL); 1380 11042 Erik gcdb = gc->gc_db; 1381 11042 Erik if (tsl->tsl_doi != gcdb->gcdb_doi || 1382 11042 Erik !_blinrange(&tsl->tsl_label, &gcdb->gcdb_slrange)) { 1383 1676 jpk DTRACE_PROBE3( 1384 1676 jpk tx__ip__log__drop__irematch__nogcmatched, 1385 1676 jpk char *, "ire(1), tsl(2): all gc failed match", 1386 1676 jpk ire_t *, ire, ts_label_t *, tsl); 1387 1676 jpk error = EACCES; 1388 1676 jpk } 1389 1676 jpk } else { 1390 1676 jpk /* 1391 1676 jpk * We didn't find any gateway credentials in the IRE 1392 1676 jpk * attributes; fall back to the gateway's template for 1393 1676 jpk * label range checks, if we are required to do so. 1394 1676 jpk */ 1395 1676 jpk ASSERT(gw_rhc != NULL); 1396 1676 jpk switch (gw_rhc->rhc_tpc->tpc_tp.host_type) { 1397 1676 jpk case SUN_CIPSO: 1398 6596 kp158701 if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi || 1399 1676 jpk (!_blinrange(&tsl->tsl_label, 1400 6596 kp158701 &gw_rhc->rhc_tpc->tpc_tp.tp_sl_range_cipso) && 1401 1676 jpk !blinlset(&tsl->tsl_label, 1402 1676 jpk gw_rhc->rhc_tpc->tpc_tp.tp_sl_set_cipso))) { 1403 1676 jpk error = EACCES; 1404 1676 jpk DTRACE_PROBE4( 1405 1676 jpk tx__ip__log__drop__irematch__deftmpl, 1406 1676 jpk char *, "ire(1), tsl(2), gw_rhc(3) " 1407 1676 jpk "failed match (cipso gw)", 1408 1676 jpk ire_t *, ire, ts_label_t *, tsl, 1409 1676 jpk tsol_tnrhc_t *, gw_rhc); 1410 1676 jpk } 1411 1676 jpk break; 1412 1676 jpk 1413 1676 jpk case UNLABELED: 1414 6596 kp158701 if (tsl->tsl_doi != gw_rhc->rhc_tpc->tpc_tp.tp_doi || 1415 1676 jpk (!_blinrange(&tsl->tsl_label, 1416 1676 jpk &gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_range) && 1417 1676 jpk !blinlset(&tsl->tsl_label, 1418 1676 jpk gw_rhc->rhc_tpc->tpc_tp.tp_gw_sl_set))) { 1419 1676 jpk error = EACCES; 1420 1676 jpk DTRACE_PROBE4( 1421 1676 jpk tx__ip__log__drop__irematch__deftmpl, 1422 1676 jpk char *, "ire(1), tsl(2), gw_rhc(3) " 1423 1676 jpk "failed match (unlabeled gw)", 1424 1676 jpk ire_t *, ire, ts_label_t *, tsl, 1425 1676 jpk tsol_tnrhc_t *, gw_rhc); 1426 1676 jpk } 1427 1676 jpk break; 1428 1676 jpk } 1429 1676 jpk } 1430 1676 jpk 1431 1676 jpk done: 1432 1676 jpk 1433 1676 jpk if (gcgrp != NULL) { 1434 1676 jpk rw_exit(&gcgrp->gcgrp_rwlock); 1435 1676 jpk GCGRP_REFRELE(gcgrp); 1436 1676 jpk } 1437 1676 jpk 1438 1676 jpk if (gw_rhc != NULL) 1439 1676 jpk TNRHC_RELE(gw_rhc) 1440 1676 jpk 1441 1676 jpk return (error); 1442 1676 jpk } 1443 1676 jpk 1444 1676 jpk /* 1445 1676 jpk * Performs label accreditation checks for packet forwarding. 1446 11042 Erik * Add or remove a CIPSO option as needed. 1447 1676 jpk * 1448 1676 jpk * Returns a pointer to the modified mblk if allowed for forwarding, 1449 1676 jpk * or NULL if the packet must be dropped. 1450 1676 jpk */ 1451 1676 jpk mblk_t * 1452 11042 Erik tsol_ip_forward(ire_t *ire, mblk_t *mp, const ip_recv_attr_t *ira) 1453 1676 jpk { 1454 1676 jpk tsol_ire_gw_secattr_t *attrp = NULL; 1455 1676 jpk ipha_t *ipha; 1456 1676 jpk ip6_t *ip6h; 1457 1676 jpk const void *pdst; 1458 1676 jpk const void *psrc; 1459 1676 jpk boolean_t off_link; 1460 1676 jpk tsol_tpc_t *dst_rhtp, *gw_rhtp; 1461 1676 jpk tsol_ip_label_t label_type; 1462 1676 jpk uchar_t *opt_ptr = NULL; 1463 1676 jpk ts_label_t *tsl; 1464 1676 jpk uint8_t proto; 1465 1676 jpk int af, adjust; 1466 1676 jpk uint16_t iplen; 1467 2535 sangeeta boolean_t need_tpc_rele = B_FALSE; 1468 2535 sangeeta ipaddr_t *gw; 1469 3448 dh155122 ip_stack_t *ipst = ire->ire_ipst; 1470 11042 Erik int err; 1471 11042 Erik ts_label_t *effective_tsl = NULL; 1472 1676 jpk 1473 1676 jpk ASSERT(ire != NULL && mp != NULL); 1474 11042 Erik /* 1475 11042 Erik * Note that the ire is the first one found, i.e., an IRE_OFFLINK if 1476 11042 Erik * the destination is offlink. 1477 11042 Erik */ 1478 1676 jpk 1479 1676 jpk af = (ire->ire_ipversion == IPV4_VERSION) ? AF_INET : AF_INET6; 1480 1676 jpk 1481 1676 jpk if (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION) { 1482 1676 jpk ASSERT(ire->ire_ipversion == IPV4_VERSION); 1483 1676 jpk ipha = (ipha_t *)mp->b_rptr; 1484 1676 jpk psrc = &ipha->ipha_src; 1485 1676 jpk pdst = &ipha->ipha_dst; 1486 1676 jpk proto = ipha->ipha_protocol; 1487 10181 Ken if (!tsol_get_option_v4(mp, &label_type, &opt_ptr)) 1488 10181 Ken return (NULL); 1489 1676 jpk } else { 1490 1676 jpk ASSERT(ire->ire_ipversion == IPV6_VERSION); 1491 1676 jpk ip6h = (ip6_t *)mp->b_rptr; 1492 1676 jpk psrc = &ip6h->ip6_src; 1493 1676 jpk pdst = &ip6h->ip6_dst; 1494 1676 jpk proto = ip6h->ip6_nxt; 1495 1676 jpk 1496 1676 jpk if (proto != IPPROTO_TCP && proto != IPPROTO_UDP && 1497 1676 jpk proto != IPPROTO_ICMPV6) { 1498 1676 jpk uint8_t *nexthdrp; 1499 1676 jpk uint16_t hdr_len; 1500 1676 jpk 1501 1676 jpk if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_len, 1502 1676 jpk &nexthdrp)) { 1503 1676 jpk /* malformed packet; drop it */ 1504 1676 jpk return (NULL); 1505 1676 jpk } 1506 1676 jpk proto = *nexthdrp; 1507 1676 jpk } 1508 10181 Ken if (!tsol_get_option_v6(mp, &label_type, &opt_ptr)) 1509 10181 Ken return (NULL); 1510 1676 jpk } 1511 11042 Erik /* 1512 11042 Erik * off_link is TRUE if destination not directly reachable. 1513 11042 Erik */ 1514 11042 Erik off_link = (ire->ire_type & IRE_OFFLINK); 1515 1676 jpk 1516 11042 Erik if ((tsl = ira->ira_tsl) == NULL) 1517 1676 jpk return (mp); 1518 1676 jpk 1519 10934 sommerfeld if (tsl->tsl_flags & TSLF_IMPLICIT_IN) { 1520 10934 sommerfeld DTRACE_PROBE3(tx__ip__log__drop__forward__unresolved__label, 1521 10934 sommerfeld char *, 1522 10934 sommerfeld "cannot forward packet mp(1) with unresolved " 1523 10934 sommerfeld "security label sl(2)", 1524 10934 sommerfeld mblk_t *, mp, ts_label_t *, tsl); 1525 10934 sommerfeld 1526 10934 sommerfeld return (NULL); 1527 10934 sommerfeld } 1528 10934 sommerfeld 1529 10934 sommerfeld 1530 1676 jpk ASSERT(psrc != NULL && pdst != NULL); 1531 1676 jpk dst_rhtp = find_tpc(pdst, ire->ire_ipversion, B_FALSE); 1532 1676 jpk 1533 1676 jpk if (dst_rhtp == NULL) { 1534 1676 jpk /* 1535 1676 jpk * Without a template we do not know if forwarding 1536 1676 jpk * violates MAC 1537 1676 jpk */ 1538 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__forward__nodst, char *, 1539 1676 jpk "mp(1) dropped, no template for destination ip4|6(2)", 1540 1676 jpk mblk_t *, mp, void *, pdst); 1541 1676 jpk return (NULL); 1542 1676 jpk } 1543 1676 jpk 1544 1676 jpk /* 1545 1676 jpk * Gateway template must have existed for off-link destinations, 1546 1676 jpk * since tsol_ire_match_gwattr has ensured such condition. 1547 1676 jpk */ 1548 2535 sangeeta if (ire->ire_ipversion == IPV4_VERSION && off_link) { 1549 2535 sangeeta /* 1550 2535 sangeeta * Surya note: first check if we can get the gw_rhtp from 1551 2535 sangeeta * the ire_gw_secattr->igsa_rhc; if this is null, then 1552 2535 sangeeta * do a lookup based on the ire_addr (address of gw) 1553 2535 sangeeta */ 1554 2535 sangeeta if (ire->ire_gw_secattr != NULL && 1555 2535 sangeeta ire->ire_gw_secattr->igsa_rhc != NULL) { 1556 2535 sangeeta attrp = ire->ire_gw_secattr; 1557 2535 sangeeta gw_rhtp = attrp->igsa_rhc->rhc_tpc; 1558 2535 sangeeta } else { 1559 11042 Erik gw = &ire->ire_gateway_addr; 1560 2535 sangeeta gw_rhtp = find_tpc(gw, ire->ire_ipversion, B_FALSE); 1561 2535 sangeeta need_tpc_rele = B_TRUE; 1562 2535 sangeeta } 1563 2535 sangeeta if (gw_rhtp == NULL) { 1564 2535 sangeeta DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *, 1565 2535 sangeeta "mp(1) dropped, no gateway in ire attributes(2)", 1566 2535 sangeeta mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp); 1567 2535 sangeeta mp = NULL; 1568 2535 sangeeta goto keep_label; 1569 2535 sangeeta } 1570 2535 sangeeta } 1571 2535 sangeeta if (ire->ire_ipversion == IPV6_VERSION && 1572 2535 sangeeta ((attrp = ire->ire_gw_secattr) == NULL || attrp->igsa_rhc == NULL || 1573 1676 jpk (gw_rhtp = attrp->igsa_rhc->rhc_tpc) == NULL) && off_link) { 1574 1676 jpk DTRACE_PROBE3(tx__ip__log__drop__forward__nogw, char *, 1575 1676 jpk "mp(1) dropped, no gateway in ire attributes(2)", 1576 1676 jpk mblk_t *, mp, tsol_ire_gw_secattr_t *, attrp); 1577 1676 jpk mp = NULL; 1578 1676 jpk goto keep_label; 1579 1676 jpk } 1580 1676 jpk 1581 1676 jpk /* 1582 1676 jpk * Check that the label for the packet is acceptable 1583 1676 jpk * by destination host; otherwise, drop it. 1584 1676 jpk */ 1585 1676 jpk switch (dst_rhtp->tpc_tp.host_type) { 1586 1676 jpk case SUN_CIPSO: 1587 1676 jpk if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi || 1588 1676 jpk (!_blinrange(&tsl->tsl_label, 1589 1676 jpk &dst_rhtp->tpc_tp.tp_sl_range_cipso) && 1590 1676 jpk !blinlset(&tsl->tsl_label, 1591 1676 jpk dst_rhtp->tpc_tp.tp_sl_set_cipso))) { 1592 1676 jpk DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *, 1593 1676 jpk "labeled packet mp(1) dropped, label(2) fails " 1594 1676 jpk "destination(3) accredation check", 1595 1676 jpk mblk_t *, mp, ts_label_t *, tsl, 1596 1676 jpk tsol_tpc_t *, dst_rhtp); 1597 1676 jpk mp = NULL; 1598 1676 jpk goto keep_label; 1599 1676 jpk } 1600 1676 jpk break; 1601 1676 jpk 1602 1676 jpk 1603 1676 jpk case UNLABELED: 1604 1676 jpk if (tsl->tsl_doi != dst_rhtp->tpc_tp.tp_doi || 1605 1676 jpk !blequal(&dst_rhtp->tpc_tp.tp_def_label, 1606 1676 jpk &tsl->tsl_label)) { 1607 1676 jpk DTRACE_PROBE4(tx__ip__log__drop__forward__mac, char *, 1608 1676 jpk "unlabeled packet mp(1) dropped, label(2) fails " 1609 1676 jpk "destination(3) accredation check", 1610 1676 jpk mblk_t *, mp, ts_label_t *, tsl, 1611 1676 jpk tsol_tpc_t *, dst_rhtp); 1612 1676 jpk mp = NULL; 1613 1676 jpk goto keep_label; 1614 1676 jpk } 1615 1676 jpk break; 1616 1676 jpk } 1617 1676 jpk if (label_type == OPT_CIPSO) { 1618 1676 jpk /* 1619 1676 jpk * We keep the label on any of the following cases: 1620 1676 jpk * 1621 1676 jpk * 1. The destination is labeled (on/off-link). 1622 1676 jpk * 2. The unlabeled destination is off-link, 1623 1676 jpk * and the next hop gateway is labeled. 1624 1676 jpk */ 1625 1676 jpk if (dst_rhtp->tpc_tp.host_type != UNLABELED || 1626 1676 jpk (off_link && 1627 1676 jpk gw_rhtp->tpc_tp.host_type != UNLABELED)) 1628 1676 jpk goto keep_label; 1629 1676 jpk 1630 1676 jpk /* 1631 1676 jpk * Strip off the CIPSO option from the packet because: the 1632 1676 jpk * unlabeled destination host is directly reachable through 1633 1676 jpk * an interface (on-link); or, the unlabeled destination host 1634 1676 jpk * is not directly reachable (off-link), and the next hop 1635 1676 jpk * gateway is unlabeled. 1636 1676 jpk */ 1637 1676 jpk adjust = (af == AF_INET) ? tsol_remove_secopt(ipha, MBLKL(mp)) : 1638 1676 jpk tsol_remove_secopt_v6(ip6h, MBLKL(mp)); 1639 1676 jpk 1640 1676 jpk ASSERT(adjust <= 0); 1641 1676 jpk if (adjust != 0) { 1642 1676 jpk 1643 1676 jpk /* adjust is negative */ 1644 1676 jpk ASSERT((mp->b_wptr + adjust) >= mp->b_rptr); 1645 1676 jpk mp->b_wptr += adjust; 1646 11042 Erik /* 1647 11042 Erik * Note that caller adjusts ira_pktlen and 1648 11042 Erik * ira_ip_hdr_length 1649 11042 Erik * 1650 11042 Erik * For AF_INET6 note that tsol_remove_secopt_v6 1651 11042 Erik * adjusted ip6_plen. 1652 11042 Erik */ 1653 1676 jpk if (af == AF_INET) { 1654 1676 jpk ipha = (ipha_t *)mp->b_rptr; 1655 1676 jpk iplen = ntohs(ipha->ipha_length) + adjust; 1656 1676 jpk ipha->ipha_length = htons(iplen); 1657 1676 jpk ipha->ipha_hdr_checksum = 0; 1658 1676 jpk ipha->ipha_hdr_checksum = ip_csum_hdr(ipha); 1659 1676 jpk } 1660 1676 jpk DTRACE_PROBE3(tx__ip__log__info__forward__adjust, 1661 1676 jpk char *, 1662 1676 jpk "mp(1) adjusted(2) for CIPSO option removal", 1663 1676 jpk mblk_t *, mp, int, adjust); 1664 1676 jpk } 1665 1676 jpk goto keep_label; 1666 1676 jpk } 1667 1676 jpk 1668 1676 jpk ASSERT(label_type == OPT_NONE); 1669 1676 jpk ASSERT(dst_rhtp != NULL); 1670 1676 jpk 1671 1676 jpk /* 1672 1676 jpk * We need to add CIPSO option if the destination or the next hop 1673 1676 jpk * gateway is labeled. Otherwise, pass the packet as is. 1674 1676 jpk */ 1675 1676 jpk if (dst_rhtp->tpc_tp.host_type == UNLABELED && 1676 1676 jpk (!off_link || gw_rhtp->tpc_tp.host_type == UNLABELED)) 1677 1676 jpk goto keep_label; 1678 1676 jpk 1679 11042 Erik /* 1680 11042 Erik * Since we are forwarding packets we use GLOBAL_ZONEID for 1681 11042 Erik * the IRE lookup in tsol_check_label. 1682 11042 Erik * Since mac_exempt is false the zoneid isn't used for anything 1683 11042 Erik * but the IRE lookup, hence we set zone_is_global to false. 1684 11042 Erik */ 1685 11042 Erik if (af == AF_INET) { 1686 11042 Erik err = tsol_check_label_v4(tsl, GLOBAL_ZONEID, &mp, 1687 11042 Erik CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl); 1688 11042 Erik } else { 1689 11042 Erik err = tsol_check_label_v6(tsl, GLOBAL_ZONEID, &mp, 1690 11042 Erik CONN_MAC_DEFAULT, B_FALSE, ipst, &effective_tsl); 1691 11042 Erik } 1692 11042 Erik if (err != 0) { 1693 11042 Erik BUMP_MIB(&ipst->ips_ip_mib, ipIfStatsOutDiscards); 1694 11042 Erik ip_drop_output("tsol_check_label", mp, NULL); 1695 11042 Erik freemsg(mp); 1696 1676 jpk mp = NULL; 1697 1676 jpk goto keep_label; 1698 1676 jpk } 1699 11042 Erik 1700 11042 Erik /* 1701 11042 Erik * The effective_tsl must never affect the routing decision, hence 1702 11042 Erik * we ignore it here. 1703 11042 Erik */ 1704 11042 Erik if (effective_tsl != NULL) 1705 11042 Erik label_rele(effective_tsl); 1706 1676 jpk 1707 6596 kp158701 if (af == AF_INET) { 1708 6596 kp158701 ipha = (ipha_t *)mp->b_rptr; 1709 6596 kp158701 ipha->ipha_hdr_checksum = 0; 1710 6596 kp158701 ipha->ipha_hdr_checksum = ip_csum_hdr(ipha); 1711 1676 jpk } 1712 1676 jpk 1713 1676 jpk keep_label: 1714 1676 jpk TPC_RELE(dst_rhtp); 1715 2535 sangeeta if (need_tpc_rele && gw_rhtp != NULL) 1716 2535 sangeeta TPC_RELE(gw_rhtp); 1717 1676 jpk return (mp); 1718 1676 jpk } 1719 1676 jpk 1720 1676 jpk /* 1721 4564 wy83408 * Name: tsol_pmtu_adjust() 1722 4564 wy83408 * 1723 4564 wy83408 * Returns the adjusted mtu after removing security option. 1724 4564 wy83408 * Removes/subtracts the option if the packet's cred indicates an unlabeled 1725 4564 wy83408 * sender or if pkt_diff indicates this system enlarged the packet. 1726 4564 wy83408 */ 1727 4564 wy83408 uint32_t 1728 4564 wy83408 tsol_pmtu_adjust(mblk_t *mp, uint32_t mtu, int pkt_diff, int af) 1729 4564 wy83408 { 1730 4564 wy83408 int label_adj = 0; 1731 4564 wy83408 uint32_t min_mtu = IP_MIN_MTU; 1732 4564 wy83408 tsol_tpc_t *src_rhtp; 1733 4564 wy83408 void *src; 1734 4564 wy83408 1735 4564 wy83408 /* 1736 4564 wy83408 * Note: label_adj is non-positive, indicating the number of 1737 4564 wy83408 * bytes removed by removing the security option from the 1738 4564 wy83408 * header. 1739 4564 wy83408 */ 1740 4564 wy83408 if (af == AF_INET6) { 1741 4564 wy83408 ip6_t *ip6h; 1742 4564 wy83408 1743 4564 wy83408 min_mtu = IPV6_MIN_MTU; 1744 4564 wy83408 ip6h = (ip6_t *)mp->b_rptr; 1745 4564 wy83408 src = &ip6h->ip6_src; 1746 4564 wy83408 if ((src_rhtp = find_tpc(src, IPV6_VERSION, B_FALSE)) == NULL) 1747 4564 wy83408 return (mtu); 1748 4564 wy83408 if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED) { 1749 4564 wy83408 label_adj = tsol_remove_secopt_v6( 1750 4564 wy83408 (ip6_t *)mp->b_rptr, MBLKL(mp)); 1751 4564 wy83408 } 1752 4564 wy83408 } else { 1753 4564 wy83408 ipha_t *ipha; 1754 4564 wy83408 1755 4564 wy83408 ASSERT(af == AF_INET); 1756 4564 wy83408 ipha = (ipha_t *)mp->b_rptr; 1757 4564 wy83408 src = &ipha->ipha_src; 1758 4564 wy83408 if ((src_rhtp = find_tpc(src, IPV4_VERSION, B_FALSE)) == NULL) 1759 4564 wy83408 return (mtu); 1760 4564 wy83408 if (pkt_diff > 0 || src_rhtp->tpc_tp.host_type == UNLABELED) 1761 4564 wy83408 label_adj = tsol_remove_secopt( 1762 4564 wy83408 (ipha_t *)mp->b_rptr, MBLKL(mp)); 1763 4564 wy83408 } 1764 4564 wy83408 /* 1765 4564 wy83408 * Make pkt_diff non-negative and the larger of the bytes 1766 4564 wy83408 * previously added (if any) or just removed, since label 1767 4564 wy83408 * addition + subtraction may not be completely idempotent. 1768 4564 wy83408 */ 1769 4564 wy83408 if (pkt_diff < -label_adj) 1770 4564 wy83408 pkt_diff = -label_adj; 1771 4564 wy83408 if (pkt_diff > 0 && pkt_diff < mtu) 1772 4564 wy83408 mtu -= pkt_diff; 1773 4564 wy83408 1774 4564 wy83408 TPC_RELE(src_rhtp); 1775 4564 wy83408 return (MAX(mtu, min_mtu)); 1776 4564 wy83408 } 1777 4564 wy83408 1778 4564 wy83408 /* 1779 1676 jpk * Name: tsol_rtsa_init() 1780 1676 jpk * 1781 1676 jpk * Normal: Sanity checks on the route security attributes provided by 1782 1676 jpk * user. Convert it into a route security parameter list to 1783 1676 jpk * be returned to caller. 1784 1676 jpk * 1785 1676 jpk * Output: EINVAL if bad security attributes in the routing message 1786 1676 jpk * ENOMEM if unable to allocate data structures 1787 1676 jpk * 0 otherwise. 1788 1676 jpk * 1789 1676 jpk * Note: On input, cp must point to the end of any addresses in 1790 1676 jpk * the rt_msghdr_t structure. 1791 1676 jpk */ 1792 1676 jpk int 1793 1676 jpk tsol_rtsa_init(rt_msghdr_t *rtm, tsol_rtsecattr_t *sp, caddr_t cp) 1794 1676 jpk { 1795 1676 jpk uint_t sacnt; 1796 1676 jpk int err; 1797 1676 jpk caddr_t lim; 1798 1676 jpk tsol_rtsecattr_t *tp; 1799 1676 jpk 1800 1676 jpk ASSERT((cp >= (caddr_t)&rtm[1]) && sp != NULL); 1801 1676 jpk 1802 1676 jpk /* 1803 1676 jpk * In theory, we could accept as many security attributes configured 1804 1676 jpk * per route destination. However, the current design is limited 1805 1676 jpk * such that at most only one set security attributes is allowed to 1806 1676 jpk * be associated with a prefix IRE. We therefore assert for now. 1807 1676 jpk */ 1808 1676 jpk /* LINTED */ 1809 1676 jpk ASSERT(TSOL_RTSA_REQUEST_MAX == 1); 1810 1676 jpk 1811 1676 jpk sp->rtsa_cnt = 0; 1812 1676 jpk lim = (caddr_t)rtm + rtm->rtm_msglen; 1813 1676 jpk ASSERT(cp <= lim); 1814 1676 jpk 1815 1676 jpk if ((lim - cp) < sizeof (rtm_ext_t) || 1816 1676 jpk ((rtm_ext_t *)cp)->rtmex_type != RTMEX_GATEWAY_SECATTR) 1817 1676 jpk return (0); 1818 1676 jpk 1819 1676 jpk if (((rtm_ext_t *)cp)->rtmex_len < sizeof (tsol_rtsecattr_t)) 1820 1676 jpk return (EINVAL); 1821 1676 jpk 1822 1676 jpk cp += sizeof (rtm_ext_t); 1823 1676 jpk 1824 1676 jpk if ((lim - cp) < sizeof (*tp) || 1825 1676 jpk (tp = (tsol_rtsecattr_t *)cp, (sacnt = tp->rtsa_cnt) == 0) || 1826 1676 jpk (lim - cp) < TSOL_RTSECATTR_SIZE(sacnt)) 1827 1676 jpk return (EINVAL); 1828 1676 jpk 1829 1676 jpk /* 1830 1676 jpk * Trying to add route security attributes when system 1831 1676 jpk * labeling service is not available, or when user supllies 1832 1676 jpk * more than the maximum number of security attributes 1833 1676 jpk * allowed per request. 1834 1676 jpk */ 1835 1676 jpk if ((sacnt > 0 && !is_system_labeled()) || 1836 1676 jpk sacnt > TSOL_RTSA_REQUEST_MAX) 1837 1676 jpk return (EINVAL); 1838 1676 jpk 1839 1676 jpk /* Ensure valid credentials */ 1840 1676 jpk if ((err = rtsa_validate(&((tsol_rtsecattr_t *)cp)-> 1841 1676 jpk rtsa_attr[0])) != 0) { 1842 1676 jpk cp += sizeof (*sp); 1843 1676 jpk return (err); 1844 1676 jpk } 1845 1676 jpk 1846 1676 jpk bcopy(cp, sp, sizeof (*sp)); 1847 1676 jpk cp += sizeof (*sp); 1848 1676 jpk return (0); 1849 1676 jpk } 1850 1676 jpk 1851 1676 jpk int 1852 11042 Erik tsol_ire_init_gwattr(ire_t *ire, uchar_t ipversion, tsol_gc_t *gc) 1853 1676 jpk { 1854 1676 jpk tsol_ire_gw_secattr_t *attrp; 1855 1676 jpk boolean_t exists = B_FALSE; 1856 1676 jpk in_addr_t ga_addr4; 1857 1676 jpk void *paddr = NULL; 1858 11042 Erik tsol_gcgrp_t *gcgrp = NULL; 1859 1676 jpk 1860 1676 jpk ASSERT(ire != NULL); 1861 1676 jpk 1862 1676 jpk /* 1863 1676 jpk * The only time that attrp can be NULL is when this routine is 1864 1676 jpk * called for the first time during the creation/initialization 1865 1676 jpk * of the corresponding IRE. It will only get cleared when the 1866 1676 jpk * IRE is deleted. 1867 1676 jpk */ 1868 1676 jpk if ((attrp = ire->ire_gw_secattr) == NULL) { 1869 1676 jpk attrp = ire_gw_secattr_alloc(KM_NOSLEEP); 1870 1676 jpk if (attrp == NULL) 1871 1676 jpk return (ENOMEM); 1872 1676 jpk ire->ire_gw_secattr = attrp; 1873 1676 jpk } else { 1874 1676 jpk exists = B_TRUE; 1875 1676 jpk mutex_enter(&attrp->igsa_lock); 1876 1676 jpk 1877 1676 jpk if (attrp->igsa_rhc != NULL) { 1878 1676 jpk TNRHC_RELE(attrp->igsa_rhc); 1879 1676 jpk attrp->igsa_rhc = NULL; 1880 1676 jpk } 1881 1676 jpk 1882 1676 jpk if (attrp->igsa_gc != NULL) 1883 1676 jpk GC_REFRELE(attrp->igsa_gc); 1884 1676 jpk } 1885 1676 jpk ASSERT(!exists || MUTEX_HELD(&attrp->igsa_lock)); 1886 1676 jpk 1887 1676 jpk /* 1888 1676 jpk * References already held by caller and we keep them; 1889 11042 Erik * note that gc may be set to NULL to clear out igsa_gc. 1890 1676 jpk */ 1891 1676 jpk attrp->igsa_gc = gc; 1892 1676 jpk 1893 11042 Erik if (gc != NULL) { 1894 1676 jpk gcgrp = gc->gc_grp; 1895 1676 jpk ASSERT(gcgrp != NULL); 1896 1676 jpk } 1897 1676 jpk 1898 1676 jpk /* 1899 1676 jpk * Intialize the template for gateway; we use the gateway's 1900 1676 jpk * address found in either the passed in gateway credential 1901 1676 jpk * or group pointer, or the ire_gateway_addr{_v6} field. 1902 1676 jpk */ 1903 1676 jpk if (gcgrp != NULL) { 1904 1676 jpk tsol_gcgrp_addr_t *ga = &gcgrp->gcgrp_addr; 1905 1676 jpk 1906 1676 jpk /* 1907 1676 jpk * Caller is holding a reference, and that we don't 1908 1676 jpk * need to hold any lock to access the address. 1909 1676 jpk */ 1910 1676 jpk if (ipversion == IPV4_VERSION) { 1911 1676 jpk ASSERT(ga->ga_af == AF_INET); 1912 1676 jpk IN6_V4MAPPED_TO_IPADDR(&ga->ga_addr, ga_addr4); 1913 1676 jpk paddr = &ga_addr4; 1914 1676 jpk } else { 1915 1676 jpk ASSERT(ga->ga_af == AF_INET6); 1916 1676 jpk paddr = &ga->ga_addr; 1917 1676 jpk } 1918 11042 Erik } else if (ire->ire_type & IRE_OFFLINK) { 1919 11042 Erik if (ipversion == IPV6_VERSION) 1920 11042 Erik paddr = &ire->ire_gateway_addr_v6; 1921 11042 Erik else if (ipversion == IPV4_VERSION) 1922 11042 Erik paddr = &ire->ire_gateway_addr; 1923 1676 jpk } 1924 1676 jpk 1925 1676 jpk /* 1926 1676 jpk * Lookup the gateway template; note that we could get an internal 1927 1676 jpk * template here, which we cache anyway. During IRE matching, we'll 1928 1676 jpk * try to update this gateway template cache and hopefully get a 1929 1676 jpk * real one. 1930 1676 jpk */ 1931 1676 jpk if (paddr != NULL) { 1932 3292 kp158701 attrp->igsa_rhc = find_rhc(paddr, ipversion, B_FALSE); 1933 1676 jpk } 1934 1676 jpk 1935 1676 jpk if (exists) 1936 1676 jpk mutex_exit(&attrp->igsa_lock); 1937 1676 jpk 1938 1676 jpk return (0); 1939 1676 jpk } 1940 1676 jpk 1941 1676 jpk /* 1942 1676 jpk * This function figures the type of MLP that we'll be using based on the 1943 1676 jpk * address that the user is binding and the zone. If the address is 1944 1676 jpk * unspecified, then we're looking at both private and shared. If it's one 1945 1676 jpk * of the zone's private addresses, then it's private only. If it's one 1946 10493 Jarrett * of the global addresses, then it's shared only. Multicast addresses are 1947 10493 Jarrett * treated same as unspecified address. 1948 1676 jpk * 1949 1676 jpk * If we can't figure out what it is, then return mlptSingle. That's actually 1950 1676 jpk * an error case. 1951 3448 dh155122 * 1952 11042 Erik * The callers are assumed to pass in zone->zone_id and not the zoneid that 1953 3448 dh155122 * is stored in a conn_t (since the latter will be GLOBAL_ZONEID in an 1954 3448 dh155122 * exclusive stack zone). 1955 1676 jpk */ 1956 1676 jpk mlp_type_t 1957 3448 dh155122 tsol_mlp_addr_type(zoneid_t zoneid, uchar_t version, const void *addr, 1958 3448 dh155122 ip_stack_t *ipst) 1959 1676 jpk { 1960 1676 jpk in_addr_t in4; 1961 1676 jpk ire_t *ire; 1962 1676 jpk ipif_t *ipif; 1963 1676 jpk zoneid_t addrzone; 1964 3448 dh155122 zoneid_t ip_zoneid; 1965 1676 jpk 1966 1676 jpk ASSERT(addr != NULL); 1967 3448 dh155122 1968 3448 dh155122 /* 1969 3448 dh155122 * For exclusive stacks we set the zoneid to zero 1970 3448 dh155122 * to operate as if in the global zone for IRE and conn_t comparisons. 1971 3448 dh155122 */ 1972 3448 dh155122 if (ipst->ips_netstack->netstack_stackid != GLOBAL_NETSTACKID) 1973 3448 dh155122 ip_zoneid = GLOBAL_ZONEID; 1974 3448 dh155122 else 1975 3448 dh155122 ip_zoneid = zoneid; 1976 1676 jpk 1977 1676 jpk if (version == IPV6_VERSION && 1978 1676 jpk IN6_IS_ADDR_V4MAPPED((const in6_addr_t *)addr)) { 1979 1676 jpk IN6_V4MAPPED_TO_IPADDR((const in6_addr_t *)addr, in4); 1980 1676 jpk addr = &in4; 1981 1676 jpk version = IPV4_VERSION; 1982 1676 jpk } 1983 1676 jpk 1984 11042 Erik /* Check whether the IRE_LOCAL (or ipif) is ALL_ZONES */ 1985 1676 jpk if (version == IPV4_VERSION) { 1986 1676 jpk in4 = *(const in_addr_t *)addr; 1987 10493 Jarrett if ((in4 == INADDR_ANY) || CLASSD(in4)) { 1988 1676 jpk return (mlptBoth); 1989 3448 dh155122 } 1990 11042 Erik ire = ire_ftable_lookup_v4(in4, 0, 0, IRE_LOCAL|IRE_LOOPBACK, 1991 11042 Erik NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY, 1992 11042 Erik 0, ipst, NULL); 1993 1676 jpk } else { 1994 10493 Jarrett if (IN6_IS_ADDR_UNSPECIFIED((const in6_addr_t *)addr) || 1995 10493 Jarrett IN6_IS_ADDR_MULTICAST((const in6_addr_t *)addr)) { 1996 1676 jpk return (mlptBoth); 1997 3448 dh155122 } 1998 11042 Erik ire = ire_ftable_lookup_v6(addr, 0, 0, IRE_LOCAL|IRE_LOOPBACK, 1999 11042 Erik NULL, ip_zoneid, NULL, MATCH_IRE_TYPE | MATCH_IRE_ZONEONLY, 2000 11042 Erik 0, ipst, NULL); 2001 1676 jpk } 2002 1676 jpk /* 2003 1676 jpk * If we can't find the IRE, then we have to behave exactly like 2004 11042 Erik * ip_laddr_verify_{v4,v6}. That means looking up the IPIF so that 2005 11042 Erik * users can bind to addresses on "down" interfaces. 2006 1676 jpk * 2007 1676 jpk * If we can't find that either, then the bind is going to fail, so 2008 1676 jpk * just give up. Note that there's a miniscule chance that the address 2009 1676 jpk * is in transition, but we don't bother handling that. 2010 1676 jpk */ 2011 1676 jpk if (ire == NULL) { 2012 1676 jpk if (version == IPV4_VERSION) 2013 1676 jpk ipif = ipif_lookup_addr(*(const in_addr_t *)addr, NULL, 2014 11042 Erik ip_zoneid, ipst); 2015 1676 jpk else 2016 1676 jpk ipif = ipif_lookup_addr_v6((const in6_addr_t *)addr, 2017 11042 Erik NULL, ip_zoneid, ipst); 2018 3448 dh155122 if (ipif == NULL) { 2019 1676 jpk return (mlptSingle); 2020 3448 dh155122 } 2021 1676 jpk addrzone = ipif->ipif_zoneid; 2022 1676 jpk ipif_refrele(ipif); 2023 1676 jpk } else { 2024 1676 jpk addrzone = ire->ire_zoneid; 2025 1676 jpk ire_refrele(ire); 2026 1676 jpk } 2027 1676 jpk return (addrzone == ALL_ZONES ? mlptShared : mlptPrivate); 2028 1676 jpk } 2029 1676 jpk 2030 1676 jpk /* 2031 1676 jpk * Since we are configuring local interfaces, and we know trusted 2032 1676 jpk * extension CDE requires local interfaces to be cipso host type in 2033 1676 jpk * order to function correctly, we'll associate a cipso template 2034 1676 jpk * to each local interface and let the interface come up. Configuring 2035 1676 jpk * a local interface to be "unlabeled" host type is a configuration error. 2036 1676 jpk * We'll override that error and make the interface host type to be cipso 2037 1676 jpk * here. 2038 1676 jpk * 2039 1676 jpk * The code is optimized for the usual "success" case and unwinds things on 2040 1676 jpk * error. We don't want to go to the trouble and expense of formatting the 2041 1676 jpk * interface name for the usual case where everything is configured correctly. 2042 1676 jpk */ 2043 1676 jpk boolean_t 2044 1676 jpk tsol_check_interface_address(const ipif_t *ipif) 2045 1676 jpk { 2046 1676 jpk tsol_tpc_t *tp; 2047 1676 jpk char addrbuf[INET6_ADDRSTRLEN]; 2048 1676 jpk int af; 2049 1676 jpk const void *addr; 2050 1676 jpk zone_t *zone; 2051 1676 jpk ts_label_t *plabel; 2052 1676 jpk const bslabel_t *label; 2053 1676 jpk char ifbuf[LIFNAMSIZ + 10]; 2054 1676 jpk const char *ifname; 2055 1676 jpk boolean_t retval; 2056 1676 jpk tsol_rhent_t rhent; 2057 3448 dh155122 netstack_t *ns = ipif->ipif_ill->ill_ipst->ips_netstack; 2058 1676 jpk 2059 1676 jpk if (IN6_IS_ADDR_V4MAPPED(&ipif->ipif_v6lcl_addr)) { 2060 1676 jpk af = AF_INET; 2061 1676 jpk addr = &V4_PART_OF_V6(ipif->ipif_v6lcl_addr); 2062 1676 jpk } else { 2063 1676 jpk af = AF_INET6; 2064 1676 jpk addr = &ipif->ipif_v6lcl_addr; 2065 1676 jpk } 2066 1676 jpk 2067 1676 jpk tp = find_tpc(&ipif->ipif_v6lcl_addr, IPV6_VERSION, B_FALSE); 2068 3448 dh155122 2069 3448 dh155122 /* assumes that ALL_ZONES implies that there is no exclusive stack */ 2070 3448 dh155122 if (ipif->ipif_zoneid == ALL_ZONES) { 2071 3448 dh155122 zone = NULL; 2072 3448 dh155122 } else if (ns->netstack_stackid == GLOBAL_NETSTACKID) { 2073 3448 dh155122 /* Shared stack case */ 2074 3448 dh155122 zone = zone_find_by_id(ipif->ipif_zoneid); 2075 3448 dh155122 } else { 2076 3448 dh155122 /* Exclusive stack case */ 2077 3448 dh155122 zone = zone_find_by_id(crgetzoneid(ipif->ipif_ill->ill_credp)); 2078 3448 dh155122 } 2079 1676 jpk if (zone != NULL) { 2080 1676 jpk plabel = zone->zone_slabel; 2081 1676 jpk ASSERT(plabel != NULL); 2082 1676 jpk label = label2bslabel(plabel); 2083 1676 jpk } 2084 1676 jpk 2085 1676 jpk /* 2086 1676 jpk * If it's CIPSO and an all-zones address, then we're done. 2087 1676 jpk * If it's a CIPSO zone specific address, the zone's label 2088 1676 jpk * must be in the range or set specified in the template. 2089 1676 jpk * When the remote host entry is missing or the template 2090 1676 jpk * type is incorrect for this interface, we create a 2091 1676 jpk * CIPSO host entry in kernel and allow the interface to be 2092 1676 jpk * brought up as CIPSO type. 2093 1676 jpk */ 2094 1676 jpk if (tp != NULL && ( 2095 1676 jpk /* The all-zones case */ 2096 1676 jpk (tp->tpc_tp.host_type == SUN_CIPSO && 2097 1676 jpk tp->tpc_tp.tp_doi == default_doi && 2098 1676 jpk ipif->ipif_zoneid == ALL_ZONES) || 2099 1676 jpk /* The local-zone case */ 2100 1676 jpk (zone != NULL && plabel->tsl_doi == tp->tpc_tp.tp_doi && 2101 1676 jpk ((tp->tpc_tp.host_type == SUN_CIPSO && 2102 1676 jpk (_blinrange(label, &tp->tpc_tp.tp_sl_range_cipso) || 2103 1676 jpk blinlset(label, tp->tpc_tp.tp_sl_set_cipso))))))) { 2104 1676 jpk if (zone != NULL) 2105 1676 jpk zone_rele(zone); 2106 1676 jpk TPC_RELE(tp); 2107 1676 jpk return (B_TRUE); 2108 1676 jpk } 2109 1676 jpk 2110 1676 jpk ifname = ipif->ipif_ill->ill_name; 2111 1676 jpk if (ipif->ipif_id != 0) { 2112 1676 jpk (void) snprintf(ifbuf, sizeof (ifbuf), "%s:%u", ifname, 2113 1676 jpk ipif->ipif_id); 2114 1676 jpk ifname = ifbuf; 2115 1676 jpk } 2116 1676 jpk (void) inet_ntop(af, addr, addrbuf, sizeof (addrbuf)); 2117 1676 jpk 2118 1676 jpk if (tp == NULL) { 2119 1676 jpk cmn_err(CE_NOTE, "template entry for %s missing. Default to " 2120 1676 jpk "CIPSO type for %s", ifname, addrbuf); 2121 1676 jpk retval = B_TRUE; 2122 1676 jpk } else if (tp->tpc_tp.host_type == UNLABELED) { 2123 1676 jpk cmn_err(CE_NOTE, "template type for %s incorrectly configured. " 2124 1676 jpk "Change to CIPSO type for %s", ifname, addrbuf); 2125 1676 jpk retval = B_TRUE; 2126 1676 jpk } else if (ipif->ipif_zoneid == ALL_ZONES) { 2127 1676 jpk if (tp->tpc_tp.host_type != SUN_CIPSO) { 2128 1676 jpk cmn_err(CE_NOTE, "%s failed: %s isn't set to CIPSO for " 2129 1676 jpk "all-zones. Converted to CIPSO.", ifname, addrbuf); 2130 1676 jpk retval = B_TRUE; 2131 1676 jpk } else { 2132 1676 jpk cmn_err(CE_NOTE, "%s failed: %s has wrong DOI %d " 2133 1676 jpk "instead of %d", ifname, addrbuf, 2134 1676 jpk tp->tpc_tp.tp_doi, default_doi); 2135 1676 jpk retval = B_FALSE; 2136 1676 jpk } 2137 1676 jpk } else if (zone == NULL) { 2138 1676 jpk cmn_err(CE_NOTE, "%s failed: zoneid %d unknown", 2139 1676 jpk ifname, ipif->ipif_zoneid); 2140 1676 jpk retval = B_FALSE; 2141 1676 jpk } else if (plabel->tsl_doi != tp->tpc_tp.tp_doi) { 2142 1676 jpk cmn_err(CE_NOTE, "%s failed: zone %s has DOI %d but %s has " 2143 1676 jpk "DOI %d", ifname, zone->zone_name, plabel->tsl_doi, 2144 1676 jpk addrbuf, tp->tpc_tp.tp_doi); 2145 1676 jpk retval = B_FALSE; 2146 1676 jpk } else { 2147 1676 jpk cmn_err(CE_NOTE, "%s failed: zone %s label incompatible with " 2148 1676 jpk "%s", ifname, zone->zone_name, addrbuf); 2149 1676 jpk tsol_print_label(label, "zone label"); 2150 1676 jpk retval = B_FALSE; 2151 1676 jpk } 2152 1676 jpk 2153 1676 jpk if (zone != NULL) 2154 1676 jpk zone_rele(zone); 2155 1676 jpk if (tp != NULL) 2156 1676 jpk TPC_RELE(tp); 2157 1676 jpk if (retval) { 2158 1676 jpk /* 2159 1676 jpk * we've corrected a config error and let the interface 2160 1676 jpk * come up as cipso. Need to insert an rhent. 2161 1676 jpk */ 2162 1676 jpk if ((rhent.rh_address.ta_family = af) == AF_INET) { 2163 1676 jpk rhent.rh_prefix = 32; 2164 1676 jpk rhent.rh_address.ta_addr_v4 = *(struct in_addr *)addr; 2165 1676 jpk } else { 2166 1676 jpk rhent.rh_prefix = 128; 2167 1676 jpk rhent.rh_address.ta_addr_v6 = *(in6_addr_t *)addr; 2168 1676 jpk } 2169 1676 jpk (void) strcpy(rhent.rh_template, "cipso"); 2170 1676 jpk if (tnrh_load(&rhent) != 0) { 2171 1676 jpk cmn_err(CE_NOTE, "%s failed: Cannot insert CIPSO " 2172 1676 jpk "template for local addr %s", ifname, addrbuf); 2173 1676 jpk retval = B_FALSE; 2174 1676 jpk } 2175 1676 jpk } 2176 1676 jpk return (retval); 2177 1676 jpk } 2178