1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * CALIPSO - Common Architecture Label IPv6 Security Option 4 * 5 * This is an implementation of the CALIPSO protocol as specified in 6 * RFC 5570. 7 * 8 * Authors: Paul Moore <paul.moore@hp.com> 9 * Huw Davies <huw@codeweavers.com> 10 */ 11 12 /* (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 13 * (c) Copyright Huw Davies <huw@codeweavers.com>, 2015 14 */ 15 16 #include <linux/init.h> 17 #include <linux/types.h> 18 #include <linux/rcupdate.h> 19 #include <linux/list.h> 20 #include <linux/spinlock.h> 21 #include <linux/string.h> 22 #include <linux/jhash.h> 23 #include <linux/audit.h> 24 #include <linux/slab.h> 25 #include <net/ip.h> 26 #include <net/icmp.h> 27 #include <net/tcp.h> 28 #include <net/netlabel.h> 29 #include <net/calipso.h> 30 #include <linux/atomic.h> 31 #include <linux/bug.h> 32 #include <asm/unaligned.h> 33 #include <linux/crc-ccitt.h> 34 35 /* Maximium size of the calipso option including 36 * the two-byte TLV header. 37 */ 38 #define CALIPSO_OPT_LEN_MAX (2 + 252) 39 40 /* Size of the minimum calipso option including 41 * the two-byte TLV header. 42 */ 43 #define CALIPSO_HDR_LEN (2 + 8) 44 45 /* Maximium size of the calipso option including 46 * the two-byte TLV header and upto 3 bytes of 47 * leading pad and 7 bytes of trailing pad. 48 */ 49 #define CALIPSO_OPT_LEN_MAX_WITH_PAD (3 + CALIPSO_OPT_LEN_MAX + 7) 50 51 /* Maximium size of u32 aligned buffer required to hold calipso 52 * option. Max of 3 initial pad bytes starting from buffer + 3. 53 * i.e. the worst case is when the previous tlv finishes on 4n + 3. 54 */ 55 #define CALIPSO_MAX_BUFFER (6 + CALIPSO_OPT_LEN_MAX) 56 57 /* List of available DOI definitions */ 58 static DEFINE_SPINLOCK(calipso_doi_list_lock); 59 static LIST_HEAD(calipso_doi_list); 60 61 /* Label mapping cache */ 62 int calipso_cache_enabled = 1; 63 int calipso_cache_bucketsize = 10; 64 #define CALIPSO_CACHE_BUCKETBITS 7 65 #define CALIPSO_CACHE_BUCKETS BIT(CALIPSO_CACHE_BUCKETBITS) 66 #define CALIPSO_CACHE_REORDERLIMIT 10 67 struct calipso_map_cache_bkt { 68 spinlock_t lock; 69 u32 size; 70 struct list_head list; 71 }; 72 73 struct calipso_map_cache_entry { 74 u32 hash; 75 unsigned char *key; 76 size_t key_len; 77 78 struct netlbl_lsm_cache *lsm_data; 79 80 u32 activity; 81 struct list_head list; 82 }; 83 84 static struct calipso_map_cache_bkt *calipso_cache; 85 86 /* Label Mapping Cache Functions 87 */ 88 89 /** 90 * calipso_cache_entry_free - Frees a cache entry 91 * @entry: the entry to free 92 * 93 * Description: 94 * This function frees the memory associated with a cache entry including the 95 * LSM cache data if there are no longer any users, i.e. reference count == 0. 96 * 97 */ 98 static void calipso_cache_entry_free(struct calipso_map_cache_entry *entry) 99 { 100 if (entry->lsm_data) 101 netlbl_secattr_cache_free(entry->lsm_data); 102 kfree(entry->key); 103 kfree(entry); 104 } 105 106 /** 107 * calipso_map_cache_hash - Hashing function for the CALIPSO cache 108 * @key: the hash key 109 * @key_len: the length of the key in bytes 110 * 111 * Description: 112 * The CALIPSO tag hashing function. Returns a 32-bit hash value. 113 * 114 */ 115 static u32 calipso_map_cache_hash(const unsigned char *key, u32 key_len) 116 { 117 return jhash(key, key_len, 0); 118 } 119 120 /** 121 * calipso_cache_init - Initialize the CALIPSO cache 122 * 123 * Description: 124 * Initializes the CALIPSO label mapping cache, this function should be called 125 * before any of the other functions defined in this file. Returns zero on 126 * success, negative values on error. 127 * 128 */ 129 static int __init calipso_cache_init(void) 130 { 131 u32 iter; 132 133 calipso_cache = kcalloc(CALIPSO_CACHE_BUCKETS, 134 sizeof(struct calipso_map_cache_bkt), 135 GFP_KERNEL); 136 if (!calipso_cache) 137 return -ENOMEM; 138 139 for (iter = 0; iter < CALIPSO_CACHE_BUCKETS; iter++) { 140 spin_lock_init(&calipso_cache[iter].lock); 141 calipso_cache[iter].size = 0; 142 INIT_LIST_HEAD(&calipso_cache[iter].list); 143 } 144 145 return 0; 146 } 147 148 /** 149 * calipso_cache_invalidate - Invalidates the current CALIPSO cache 150 * 151 * Description: 152 * Invalidates and frees any entries in the CALIPSO cache. Returns zero on 153 * success and negative values on failure. 154 * 155 */ 156 static void calipso_cache_invalidate(void) 157 { 158 struct calipso_map_cache_entry *entry, *tmp_entry; 159 u32 iter; 160 161 for (iter = 0; iter < CALIPSO_CACHE_BUCKETS; iter++) { 162 spin_lock_bh(&calipso_cache[iter].lock); 163 list_for_each_entry_safe(entry, 164 tmp_entry, 165 &calipso_cache[iter].list, list) { 166 list_del(&entry->list); 167 calipso_cache_entry_free(entry); 168 } 169 calipso_cache[iter].size = 0; 170 spin_unlock_bh(&calipso_cache[iter].lock); 171 } 172 } 173 174 /** 175 * calipso_cache_check - Check the CALIPSO cache for a label mapping 176 * @key: the buffer to check 177 * @key_len: buffer length in bytes 178 * @secattr: the security attribute struct to use 179 * 180 * Description: 181 * This function checks the cache to see if a label mapping already exists for 182 * the given key. If there is a match then the cache is adjusted and the 183 * @secattr struct is populated with the correct LSM security attributes. The 184 * cache is adjusted in the following manner if the entry is not already the 185 * first in the cache bucket: 186 * 187 * 1. The cache entry's activity counter is incremented 188 * 2. The previous (higher ranking) entry's activity counter is decremented 189 * 3. If the difference between the two activity counters is geater than 190 * CALIPSO_CACHE_REORDERLIMIT the two entries are swapped 191 * 192 * Returns zero on success, -ENOENT for a cache miss, and other negative values 193 * on error. 194 * 195 */ 196 static int calipso_cache_check(const unsigned char *key, 197 u32 key_len, 198 struct netlbl_lsm_secattr *secattr) 199 { 200 u32 bkt; 201 struct calipso_map_cache_entry *entry; 202 struct calipso_map_cache_entry *prev_entry = NULL; 203 u32 hash; 204 205 if (!calipso_cache_enabled) 206 return -ENOENT; 207 208 hash = calipso_map_cache_hash(key, key_len); 209 bkt = hash & (CALIPSO_CACHE_BUCKETS - 1); 210 spin_lock_bh(&calipso_cache[bkt].lock); 211 list_for_each_entry(entry, &calipso_cache[bkt].list, list) { 212 if (entry->hash == hash && 213 entry->key_len == key_len && 214 memcmp(entry->key, key, key_len) == 0) { 215 entry->activity += 1; 216 refcount_inc(&entry->lsm_data->refcount); 217 secattr->cache = entry->lsm_data; 218 secattr->flags |= NETLBL_SECATTR_CACHE; 219 secattr->type = NETLBL_NLTYPE_CALIPSO; 220 if (!prev_entry) { 221 spin_unlock_bh(&calipso_cache[bkt].lock); 222 return 0; 223 } 224 225 if (prev_entry->activity > 0) 226 prev_entry->activity -= 1; 227 if (entry->activity > prev_entry->activity && 228 entry->activity - prev_entry->activity > 229 CALIPSO_CACHE_REORDERLIMIT) { 230 __list_del(entry->list.prev, entry->list.next); 231 __list_add(&entry->list, 232 prev_entry->list.prev, 233 &prev_entry->list); 234 } 235 236 spin_unlock_bh(&calipso_cache[bkt].lock); 237 return 0; 238 } 239 prev_entry = entry; 240 } 241 spin_unlock_bh(&calipso_cache[bkt].lock); 242 243 return -ENOENT; 244 } 245 246 /** 247 * calipso_cache_add - Add an entry to the CALIPSO cache 248 * @calipso_ptr: the CALIPSO option 249 * @secattr: the packet's security attributes 250 * 251 * Description: 252 * Add a new entry into the CALIPSO label mapping cache. Add the new entry to 253 * head of the cache bucket's list, if the cache bucket is out of room remove 254 * the last entry in the list first. It is important to note that there is 255 * currently no checking for duplicate keys. Returns zero on success, 256 * negative values on failure. The key stored starts at calipso_ptr + 2, 257 * i.e. the type and length bytes are not stored, this corresponds to 258 * calipso_ptr[1] bytes of data. 259 * 260 */ 261 static int calipso_cache_add(const unsigned char *calipso_ptr, 262 const struct netlbl_lsm_secattr *secattr) 263 { 264 int ret_val = -EPERM; 265 u32 bkt; 266 struct calipso_map_cache_entry *entry = NULL; 267 struct calipso_map_cache_entry *old_entry = NULL; 268 u32 calipso_ptr_len; 269 270 if (!calipso_cache_enabled || calipso_cache_bucketsize <= 0) 271 return 0; 272 273 calipso_ptr_len = calipso_ptr[1]; 274 275 entry = kzalloc(sizeof(*entry), GFP_ATOMIC); 276 if (!entry) 277 return -ENOMEM; 278 entry->key = kmemdup(calipso_ptr + 2, calipso_ptr_len, GFP_ATOMIC); 279 if (!entry->key) { 280 ret_val = -ENOMEM; 281 goto cache_add_failure; 282 } 283 entry->key_len = calipso_ptr_len; 284 entry->hash = calipso_map_cache_hash(calipso_ptr, calipso_ptr_len); 285 refcount_inc(&secattr->cache->refcount); 286 entry->lsm_data = secattr->cache; 287 288 bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1); 289 spin_lock_bh(&calipso_cache[bkt].lock); 290 if (calipso_cache[bkt].size < calipso_cache_bucketsize) { 291 list_add(&entry->list, &calipso_cache[bkt].list); 292 calipso_cache[bkt].size += 1; 293 } else { 294 old_entry = list_entry(calipso_cache[bkt].list.prev, 295 struct calipso_map_cache_entry, list); 296 list_del(&old_entry->list); 297 list_add(&entry->list, &calipso_cache[bkt].list); 298 calipso_cache_entry_free(old_entry); 299 } 300 spin_unlock_bh(&calipso_cache[bkt].lock); 301 302 return 0; 303 304 cache_add_failure: 305 if (entry) 306 calipso_cache_entry_free(entry); 307 return ret_val; 308 } 309 310 /* DOI List Functions 311 */ 312 313 /** 314 * calipso_doi_search - Searches for a DOI definition 315 * @doi: the DOI to search for 316 * 317 * Description: 318 * Search the DOI definition list for a DOI definition with a DOI value that 319 * matches @doi. The caller is responsible for calling rcu_read_[un]lock(). 320 * Returns a pointer to the DOI definition on success and NULL on failure. 321 */ 322 static struct calipso_doi *calipso_doi_search(u32 doi) 323 { 324 struct calipso_doi *iter; 325 326 list_for_each_entry_rcu(iter, &calipso_doi_list, list) 327 if (iter->doi == doi && refcount_read(&iter->refcount)) 328 return iter; 329 return NULL; 330 } 331 332 /** 333 * calipso_doi_add - Add a new DOI to the CALIPSO protocol engine 334 * @doi_def: the DOI structure 335 * @audit_info: NetLabel audit information 336 * 337 * Description: 338 * The caller defines a new DOI for use by the CALIPSO engine and calls this 339 * function to add it to the list of acceptable domains. The caller must 340 * ensure that the mapping table specified in @doi_def->map meets all of the 341 * requirements of the mapping type (see calipso.h for details). Returns 342 * zero on success and non-zero on failure. 343 * 344 */ 345 static int calipso_doi_add(struct calipso_doi *doi_def, 346 struct netlbl_audit *audit_info) 347 { 348 int ret_val = -EINVAL; 349 u32 doi; 350 u32 doi_type; 351 struct audit_buffer *audit_buf; 352 353 doi = doi_def->doi; 354 doi_type = doi_def->type; 355 356 if (doi_def->doi == CALIPSO_DOI_UNKNOWN) 357 goto doi_add_return; 358 359 refcount_set(&doi_def->refcount, 1); 360 361 spin_lock(&calipso_doi_list_lock); 362 if (calipso_doi_search(doi_def->doi)) { 363 spin_unlock(&calipso_doi_list_lock); 364 ret_val = -EEXIST; 365 goto doi_add_return; 366 } 367 list_add_tail_rcu(&doi_def->list, &calipso_doi_list); 368 spin_unlock(&calipso_doi_list_lock); 369 ret_val = 0; 370 371 doi_add_return: 372 audit_buf = netlbl_audit_start(AUDIT_MAC_CALIPSO_ADD, audit_info); 373 if (audit_buf) { 374 const char *type_str; 375 376 switch (doi_type) { 377 case CALIPSO_MAP_PASS: 378 type_str = "pass"; 379 break; 380 default: 381 type_str = "(unknown)"; 382 } 383 audit_log_format(audit_buf, 384 " calipso_doi=%u calipso_type=%s res=%u", 385 doi, type_str, ret_val == 0 ? 1 : 0); 386 audit_log_end(audit_buf); 387 } 388 389 return ret_val; 390 } 391 392 /** 393 * calipso_doi_free - Frees a DOI definition 394 * @doi_def: the DOI definition 395 * 396 * Description: 397 * This function frees all of the memory associated with a DOI definition. 398 * 399 */ 400 static void calipso_doi_free(struct calipso_doi *doi_def) 401 { 402 kfree(doi_def); 403 } 404 405 /** 406 * calipso_doi_free_rcu - Frees a DOI definition via the RCU pointer 407 * @entry: the entry's RCU field 408 * 409 * Description: 410 * This function is designed to be used as a callback to the call_rcu() 411 * function so that the memory allocated to the DOI definition can be released 412 * safely. 413 * 414 */ 415 static void calipso_doi_free_rcu(struct rcu_head *entry) 416 { 417 struct calipso_doi *doi_def; 418 419 doi_def = container_of(entry, struct calipso_doi, rcu); 420 calipso_doi_free(doi_def); 421 } 422 423 /** 424 * calipso_doi_remove - Remove an existing DOI from the CALIPSO protocol engine 425 * @doi: the DOI value 426 * @audit_secid: the LSM secid to use in the audit message 427 * 428 * Description: 429 * Removes a DOI definition from the CALIPSO engine. The NetLabel routines will 430 * be called to release their own LSM domain mappings as well as our own 431 * domain list. Returns zero on success and negative values on failure. 432 * 433 */ 434 static int calipso_doi_remove(u32 doi, struct netlbl_audit *audit_info) 435 { 436 int ret_val; 437 struct calipso_doi *doi_def; 438 struct audit_buffer *audit_buf; 439 440 spin_lock(&calipso_doi_list_lock); 441 doi_def = calipso_doi_search(doi); 442 if (!doi_def) { 443 spin_unlock(&calipso_doi_list_lock); 444 ret_val = -ENOENT; 445 goto doi_remove_return; 446 } 447 if (!refcount_dec_and_test(&doi_def->refcount)) { 448 spin_unlock(&calipso_doi_list_lock); 449 ret_val = -EBUSY; 450 goto doi_remove_return; 451 } 452 list_del_rcu(&doi_def->list); 453 spin_unlock(&calipso_doi_list_lock); 454 455 call_rcu(&doi_def->rcu, calipso_doi_free_rcu); 456 ret_val = 0; 457 458 doi_remove_return: 459 audit_buf = netlbl_audit_start(AUDIT_MAC_CALIPSO_DEL, audit_info); 460 if (audit_buf) { 461 audit_log_format(audit_buf, 462 " calipso_doi=%u res=%u", 463 doi, ret_val == 0 ? 1 : 0); 464 audit_log_end(audit_buf); 465 } 466 467 return ret_val; 468 } 469 470 /** 471 * calipso_doi_getdef - Returns a reference to a valid DOI definition 472 * @doi: the DOI value 473 * 474 * Description: 475 * Searches for a valid DOI definition and if one is found it is returned to 476 * the caller. Otherwise NULL is returned. The caller must ensure that 477 * calipso_doi_putdef() is called when the caller is done. 478 * 479 */ 480 static struct calipso_doi *calipso_doi_getdef(u32 doi) 481 { 482 struct calipso_doi *doi_def; 483 484 rcu_read_lock(); 485 doi_def = calipso_doi_search(doi); 486 if (!doi_def) 487 goto doi_getdef_return; 488 if (!refcount_inc_not_zero(&doi_def->refcount)) 489 doi_def = NULL; 490 491 doi_getdef_return: 492 rcu_read_unlock(); 493 return doi_def; 494 } 495 496 /** 497 * calipso_doi_putdef - Releases a reference for the given DOI definition 498 * @doi_def: the DOI definition 499 * 500 * Description: 501 * Releases a DOI definition reference obtained from calipso_doi_getdef(). 502 * 503 */ 504 static void calipso_doi_putdef(struct calipso_doi *doi_def) 505 { 506 if (!doi_def) 507 return; 508 509 if (!refcount_dec_and_test(&doi_def->refcount)) 510 return; 511 spin_lock(&calipso_doi_list_lock); 512 list_del_rcu(&doi_def->list); 513 spin_unlock(&calipso_doi_list_lock); 514 515 call_rcu(&doi_def->rcu, calipso_doi_free_rcu); 516 } 517 518 /** 519 * calipso_doi_walk - Iterate through the DOI definitions 520 * @skip_cnt: skip past this number of DOI definitions, updated 521 * @callback: callback for each DOI definition 522 * @cb_arg: argument for the callback function 523 * 524 * Description: 525 * Iterate over the DOI definition list, skipping the first @skip_cnt entries. 526 * For each entry call @callback, if @callback returns a negative value stop 527 * 'walking' through the list and return. Updates the value in @skip_cnt upon 528 * return. Returns zero on success, negative values on failure. 529 * 530 */ 531 static int calipso_doi_walk(u32 *skip_cnt, 532 int (*callback)(struct calipso_doi *doi_def, 533 void *arg), 534 void *cb_arg) 535 { 536 int ret_val = -ENOENT; 537 u32 doi_cnt = 0; 538 struct calipso_doi *iter_doi; 539 540 rcu_read_lock(); 541 list_for_each_entry_rcu(iter_doi, &calipso_doi_list, list) 542 if (refcount_read(&iter_doi->refcount) > 0) { 543 if (doi_cnt++ < *skip_cnt) 544 continue; 545 ret_val = callback(iter_doi, cb_arg); 546 if (ret_val < 0) { 547 doi_cnt--; 548 goto doi_walk_return; 549 } 550 } 551 552 doi_walk_return: 553 rcu_read_unlock(); 554 *skip_cnt = doi_cnt; 555 return ret_val; 556 } 557 558 /** 559 * calipso_validate - Validate a CALIPSO option 560 * @skb: the packet 561 * @option: the start of the option 562 * 563 * Description: 564 * This routine is called to validate a CALIPSO option. 565 * If the option is valid then %true is returned, otherwise 566 * %false is returned. 567 * 568 * The caller should have already checked that the length of the 569 * option (including the TLV header) is >= 10 and that the catmap 570 * length is consistent with the option length. 571 * 572 * We leave checks on the level and categories to the socket layer. 573 */ 574 bool calipso_validate(const struct sk_buff *skb, const unsigned char *option) 575 { 576 struct calipso_doi *doi_def; 577 bool ret_val; 578 u16 crc, len = option[1] + 2; 579 static const u8 zero[2]; 580 581 /* The original CRC runs over the option including the TLV header 582 * with the CRC-16 field (at offset 8) zeroed out. */ 583 crc = crc_ccitt(0xffff, option, 8); 584 crc = crc_ccitt(crc, zero, sizeof(zero)); 585 if (len > 10) 586 crc = crc_ccitt(crc, option + 10, len - 10); 587 crc = ~crc; 588 if (option[8] != (crc & 0xff) || option[9] != ((crc >> 8) & 0xff)) 589 return false; 590 591 rcu_read_lock(); 592 doi_def = calipso_doi_search(get_unaligned_be32(option + 2)); 593 ret_val = !!doi_def; 594 rcu_read_unlock(); 595 596 return ret_val; 597 } 598 599 /** 600 * calipso_map_cat_hton - Perform a category mapping from host to network 601 * @doi_def: the DOI definition 602 * @secattr: the security attributes 603 * @net_cat: the zero'd out category bitmap in network/CALIPSO format 604 * @net_cat_len: the length of the CALIPSO bitmap in bytes 605 * 606 * Description: 607 * Perform a label mapping to translate a local MLS category bitmap to the 608 * correct CALIPSO bitmap using the given DOI definition. Returns the minimum 609 * size in bytes of the network bitmap on success, negative values otherwise. 610 * 611 */ 612 static int calipso_map_cat_hton(const struct calipso_doi *doi_def, 613 const struct netlbl_lsm_secattr *secattr, 614 unsigned char *net_cat, 615 u32 net_cat_len) 616 { 617 int spot = -1; 618 u32 net_spot_max = 0; 619 u32 net_clen_bits = net_cat_len * 8; 620 621 for (;;) { 622 spot = netlbl_catmap_walk(secattr->attr.mls.cat, 623 spot + 1); 624 if (spot < 0) 625 break; 626 if (spot >= net_clen_bits) 627 return -ENOSPC; 628 netlbl_bitmap_setbit(net_cat, spot, 1); 629 630 if (spot > net_spot_max) 631 net_spot_max = spot; 632 } 633 634 return (net_spot_max / 32 + 1) * 4; 635 } 636 637 /** 638 * calipso_map_cat_ntoh - Perform a category mapping from network to host 639 * @doi_def: the DOI definition 640 * @net_cat: the category bitmap in network/CALIPSO format 641 * @net_cat_len: the length of the CALIPSO bitmap in bytes 642 * @secattr: the security attributes 643 * 644 * Description: 645 * Perform a label mapping to translate a CALIPSO bitmap to the correct local 646 * MLS category bitmap using the given DOI definition. Returns zero on 647 * success, negative values on failure. 648 * 649 */ 650 static int calipso_map_cat_ntoh(const struct calipso_doi *doi_def, 651 const unsigned char *net_cat, 652 u32 net_cat_len, 653 struct netlbl_lsm_secattr *secattr) 654 { 655 int ret_val; 656 int spot = -1; 657 u32 net_clen_bits = net_cat_len * 8; 658 659 for (;;) { 660 spot = netlbl_bitmap_walk(net_cat, 661 net_clen_bits, 662 spot + 1, 663 1); 664 if (spot < 0) { 665 if (spot == -2) 666 return -EFAULT; 667 return 0; 668 } 669 670 ret_val = netlbl_catmap_setbit(&secattr->attr.mls.cat, 671 spot, 672 GFP_ATOMIC); 673 if (ret_val != 0) 674 return ret_val; 675 } 676 677 return -EINVAL; 678 } 679 680 /** 681 * calipso_pad_write - Writes pad bytes in TLV format 682 * @buf: the buffer 683 * @offset: offset from start of buffer to write padding 684 * @count: number of pad bytes to write 685 * 686 * Description: 687 * Write @count bytes of TLV padding into @buffer starting at offset @offset. 688 * @count should be less than 8 - see RFC 4942. 689 * 690 */ 691 static int calipso_pad_write(unsigned char *buf, unsigned int offset, 692 unsigned int count) 693 { 694 if (WARN_ON_ONCE(count >= 8)) 695 return -EINVAL; 696 697 switch (count) { 698 case 0: 699 break; 700 case 1: 701 buf[offset] = IPV6_TLV_PAD1; 702 break; 703 default: 704 buf[offset] = IPV6_TLV_PADN; 705 buf[offset + 1] = count - 2; 706 if (count > 2) 707 memset(buf + offset + 2, 0, count - 2); 708 break; 709 } 710 return 0; 711 } 712 713 /** 714 * calipso_genopt - Generate a CALIPSO option 715 * @buf: the option buffer 716 * @start: offset from which to write 717 * @buf_len: the size of opt_buf 718 * @doi_def: the CALIPSO DOI to use 719 * @secattr: the security attributes 720 * 721 * Description: 722 * Generate a CALIPSO option using the DOI definition and security attributes 723 * passed to the function. This also generates upto three bytes of leading 724 * padding that ensures that the option is 4n + 2 aligned. It returns the 725 * number of bytes written (including any initial padding). 726 */ 727 static int calipso_genopt(unsigned char *buf, u32 start, u32 buf_len, 728 const struct calipso_doi *doi_def, 729 const struct netlbl_lsm_secattr *secattr) 730 { 731 int ret_val; 732 u32 len, pad; 733 u16 crc; 734 static const unsigned char padding[4] = {2, 1, 0, 3}; 735 unsigned char *calipso; 736 737 /* CALIPSO has 4n + 2 alignment */ 738 pad = padding[start & 3]; 739 if (buf_len <= start + pad + CALIPSO_HDR_LEN) 740 return -ENOSPC; 741 742 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) 743 return -EPERM; 744 745 len = CALIPSO_HDR_LEN; 746 747 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 748 ret_val = calipso_map_cat_hton(doi_def, 749 secattr, 750 buf + start + pad + len, 751 buf_len - start - pad - len); 752 if (ret_val < 0) 753 return ret_val; 754 len += ret_val; 755 } 756 757 calipso_pad_write(buf, start, pad); 758 calipso = buf + start + pad; 759 760 calipso[0] = IPV6_TLV_CALIPSO; 761 calipso[1] = len - 2; 762 *(__be32 *)(calipso + 2) = htonl(doi_def->doi); 763 calipso[6] = (len - CALIPSO_HDR_LEN) / 4; 764 calipso[7] = secattr->attr.mls.lvl, 765 crc = ~crc_ccitt(0xffff, calipso, len); 766 calipso[8] = crc & 0xff; 767 calipso[9] = (crc >> 8) & 0xff; 768 return pad + len; 769 } 770 771 /* Hop-by-hop hdr helper functions 772 */ 773 774 /** 775 * calipso_opt_update - Replaces socket's hop options with a new set 776 * @sk: the socket 777 * @hop: new hop options 778 * 779 * Description: 780 * Replaces @sk's hop options with @hop. @hop may be NULL to leave 781 * the socket with no hop options. 782 * 783 */ 784 static int calipso_opt_update(struct sock *sk, struct ipv6_opt_hdr *hop) 785 { 786 struct ipv6_txoptions *old = txopt_get(inet6_sk(sk)), *txopts; 787 788 txopts = ipv6_renew_options(sk, old, IPV6_HOPOPTS, hop); 789 txopt_put(old); 790 if (IS_ERR(txopts)) 791 return PTR_ERR(txopts); 792 793 txopts = ipv6_update_options(sk, txopts); 794 if (txopts) { 795 atomic_sub(txopts->tot_len, &sk->sk_omem_alloc); 796 txopt_put(txopts); 797 } 798 799 return 0; 800 } 801 802 /** 803 * calipso_tlv_len - Returns the length of the TLV 804 * @opt: the option header 805 * @offset: offset of the TLV within the header 806 * 807 * Description: 808 * Returns the length of the TLV option at offset @offset within 809 * the option header @opt. Checks that the entire TLV fits inside 810 * the option header, returns a negative value if this is not the case. 811 */ 812 static int calipso_tlv_len(struct ipv6_opt_hdr *opt, unsigned int offset) 813 { 814 unsigned char *tlv = (unsigned char *)opt; 815 unsigned int opt_len = ipv6_optlen(opt), tlv_len; 816 817 if (offset < sizeof(*opt) || offset >= opt_len) 818 return -EINVAL; 819 if (tlv[offset] == IPV6_TLV_PAD1) 820 return 1; 821 if (offset + 1 >= opt_len) 822 return -EINVAL; 823 tlv_len = tlv[offset + 1] + 2; 824 if (offset + tlv_len > opt_len) 825 return -EINVAL; 826 return tlv_len; 827 } 828 829 /** 830 * calipso_opt_find - Finds the CALIPSO option in an IPv6 hop options header 831 * @hop: the hop options header 832 * @start: on return holds the offset of any leading padding 833 * @end: on return holds the offset of the first non-pad TLV after CALIPSO 834 * 835 * Description: 836 * Finds the space occupied by a CALIPSO option (including any leading and 837 * trailing padding). 838 * 839 * If a CALIPSO option exists set @start and @end to the 840 * offsets within @hop of the start of padding before the first 841 * CALIPSO option and the end of padding after the first CALIPSO 842 * option. In this case the function returns 0. 843 * 844 * In the absence of a CALIPSO option, @start and @end will be 845 * set to the start and end of any trailing padding in the header. 846 * This is useful when appending a new option, as the caller may want 847 * to overwrite some of this padding. In this case the function will 848 * return -ENOENT. 849 */ 850 static int calipso_opt_find(struct ipv6_opt_hdr *hop, unsigned int *start, 851 unsigned int *end) 852 { 853 int ret_val = -ENOENT, tlv_len; 854 unsigned int opt_len, offset, offset_s = 0, offset_e = 0; 855 unsigned char *opt = (unsigned char *)hop; 856 857 opt_len = ipv6_optlen(hop); 858 offset = sizeof(*hop); 859 860 while (offset < opt_len) { 861 tlv_len = calipso_tlv_len(hop, offset); 862 if (tlv_len < 0) 863 return tlv_len; 864 865 switch (opt[offset]) { 866 case IPV6_TLV_PAD1: 867 case IPV6_TLV_PADN: 868 if (offset_e) 869 offset_e = offset; 870 break; 871 case IPV6_TLV_CALIPSO: 872 ret_val = 0; 873 offset_e = offset; 874 break; 875 default: 876 if (offset_e == 0) 877 offset_s = offset; 878 else 879 goto out; 880 } 881 offset += tlv_len; 882 } 883 884 out: 885 if (offset_s) 886 *start = offset_s + calipso_tlv_len(hop, offset_s); 887 else 888 *start = sizeof(*hop); 889 if (offset_e) 890 *end = offset_e + calipso_tlv_len(hop, offset_e); 891 else 892 *end = opt_len; 893 894 return ret_val; 895 } 896 897 /** 898 * calipso_opt_insert - Inserts a CALIPSO option into an IPv6 hop opt hdr 899 * @hop: the original hop options header 900 * @doi_def: the CALIPSO DOI to use 901 * @secattr: the specific security attributes of the socket 902 * 903 * Description: 904 * Creates a new hop options header based on @hop with a 905 * CALIPSO option added to it. If @hop already contains a CALIPSO 906 * option this is overwritten, otherwise the new option is appended 907 * after any existing options. If @hop is NULL then the new header 908 * will contain just the CALIPSO option and any needed padding. 909 * 910 */ 911 static struct ipv6_opt_hdr * 912 calipso_opt_insert(struct ipv6_opt_hdr *hop, 913 const struct calipso_doi *doi_def, 914 const struct netlbl_lsm_secattr *secattr) 915 { 916 unsigned int start, end, buf_len, pad, hop_len; 917 struct ipv6_opt_hdr *new; 918 int ret_val; 919 920 if (hop) { 921 hop_len = ipv6_optlen(hop); 922 ret_val = calipso_opt_find(hop, &start, &end); 923 if (ret_val && ret_val != -ENOENT) 924 return ERR_PTR(ret_val); 925 } else { 926 hop_len = 0; 927 start = sizeof(*hop); 928 end = 0; 929 } 930 931 buf_len = hop_len + start - end + CALIPSO_OPT_LEN_MAX_WITH_PAD; 932 new = kzalloc(buf_len, GFP_ATOMIC); 933 if (!new) 934 return ERR_PTR(-ENOMEM); 935 936 if (start > sizeof(*hop)) 937 memcpy(new, hop, start); 938 ret_val = calipso_genopt((unsigned char *)new, start, buf_len, doi_def, 939 secattr); 940 if (ret_val < 0) { 941 kfree(new); 942 return ERR_PTR(ret_val); 943 } 944 945 buf_len = start + ret_val; 946 /* At this point buf_len aligns to 4n, so (buf_len & 4) pads to 8n */ 947 pad = ((buf_len & 4) + (end & 7)) & 7; 948 calipso_pad_write((unsigned char *)new, buf_len, pad); 949 buf_len += pad; 950 951 if (end != hop_len) { 952 memcpy((char *)new + buf_len, (char *)hop + end, hop_len - end); 953 buf_len += hop_len - end; 954 } 955 new->nexthdr = 0; 956 new->hdrlen = buf_len / 8 - 1; 957 958 return new; 959 } 960 961 /** 962 * calipso_opt_del - Removes the CALIPSO option from an option header 963 * @hop: the original header 964 * @new: the new header 965 * 966 * Description: 967 * Creates a new header based on @hop without any CALIPSO option. If @hop 968 * doesn't contain a CALIPSO option it returns -ENOENT. If @hop contains 969 * no other non-padding options, it returns zero with @new set to NULL. 970 * Otherwise it returns zero, creates a new header without the CALIPSO 971 * option (and removing as much padding as possible) and returns with 972 * @new set to that header. 973 * 974 */ 975 static int calipso_opt_del(struct ipv6_opt_hdr *hop, 976 struct ipv6_opt_hdr **new) 977 { 978 int ret_val; 979 unsigned int start, end, delta, pad, hop_len; 980 981 ret_val = calipso_opt_find(hop, &start, &end); 982 if (ret_val) 983 return ret_val; 984 985 hop_len = ipv6_optlen(hop); 986 if (start == sizeof(*hop) && end == hop_len) { 987 /* There's no other option in the header so return NULL */ 988 *new = NULL; 989 return 0; 990 } 991 992 delta = (end - start) & ~7; 993 *new = kzalloc(hop_len - delta, GFP_ATOMIC); 994 if (!*new) 995 return -ENOMEM; 996 997 memcpy(*new, hop, start); 998 (*new)->hdrlen -= delta / 8; 999 pad = (end - start) & 7; 1000 calipso_pad_write((unsigned char *)*new, start, pad); 1001 if (end != hop_len) 1002 memcpy((char *)*new + start + pad, (char *)hop + end, 1003 hop_len - end); 1004 1005 return 0; 1006 } 1007 1008 /** 1009 * calipso_opt_getattr - Get the security attributes from a memory block 1010 * @calipso: the CALIPSO option 1011 * @secattr: the security attributes 1012 * 1013 * Description: 1014 * Inspect @calipso and return the security attributes in @secattr. 1015 * Returns zero on success and negative values on failure. 1016 * 1017 */ 1018 static int calipso_opt_getattr(const unsigned char *calipso, 1019 struct netlbl_lsm_secattr *secattr) 1020 { 1021 int ret_val = -ENOMSG; 1022 u32 doi, len = calipso[1], cat_len = calipso[6] * 4; 1023 struct calipso_doi *doi_def; 1024 1025 if (cat_len + 8 > len) 1026 return -EINVAL; 1027 1028 if (calipso_cache_check(calipso + 2, calipso[1], secattr) == 0) 1029 return 0; 1030 1031 doi = get_unaligned_be32(calipso + 2); 1032 rcu_read_lock(); 1033 doi_def = calipso_doi_search(doi); 1034 if (!doi_def) 1035 goto getattr_return; 1036 1037 secattr->attr.mls.lvl = calipso[7]; 1038 secattr->flags |= NETLBL_SECATTR_MLS_LVL; 1039 1040 if (cat_len) { 1041 ret_val = calipso_map_cat_ntoh(doi_def, 1042 calipso + 10, 1043 cat_len, 1044 secattr); 1045 if (ret_val != 0) { 1046 netlbl_catmap_free(secattr->attr.mls.cat); 1047 goto getattr_return; 1048 } 1049 1050 if (secattr->attr.mls.cat) 1051 secattr->flags |= NETLBL_SECATTR_MLS_CAT; 1052 } 1053 1054 secattr->type = NETLBL_NLTYPE_CALIPSO; 1055 1056 getattr_return: 1057 rcu_read_unlock(); 1058 return ret_val; 1059 } 1060 1061 /* sock functions. 1062 */ 1063 1064 /** 1065 * calipso_sock_getattr - Get the security attributes from a sock 1066 * @sk: the sock 1067 * @secattr: the security attributes 1068 * 1069 * Description: 1070 * Query @sk to see if there is a CALIPSO option attached to the sock and if 1071 * there is return the CALIPSO security attributes in @secattr. This function 1072 * requires that @sk be locked, or privately held, but it does not do any 1073 * locking itself. Returns zero on success and negative values on failure. 1074 * 1075 */ 1076 static int calipso_sock_getattr(struct sock *sk, 1077 struct netlbl_lsm_secattr *secattr) 1078 { 1079 struct ipv6_opt_hdr *hop; 1080 int opt_len, len, ret_val = -ENOMSG, offset; 1081 unsigned char *opt; 1082 struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); 1083 1084 if (!txopts || !txopts->hopopt) 1085 goto done; 1086 1087 hop = txopts->hopopt; 1088 opt = (unsigned char *)hop; 1089 opt_len = ipv6_optlen(hop); 1090 offset = sizeof(*hop); 1091 while (offset < opt_len) { 1092 len = calipso_tlv_len(hop, offset); 1093 if (len < 0) { 1094 ret_val = len; 1095 goto done; 1096 } 1097 switch (opt[offset]) { 1098 case IPV6_TLV_CALIPSO: 1099 if (len < CALIPSO_HDR_LEN) 1100 ret_val = -EINVAL; 1101 else 1102 ret_val = calipso_opt_getattr(&opt[offset], 1103 secattr); 1104 goto done; 1105 default: 1106 offset += len; 1107 break; 1108 } 1109 } 1110 done: 1111 txopt_put(txopts); 1112 return ret_val; 1113 } 1114 1115 /** 1116 * calipso_sock_setattr - Add a CALIPSO option to a socket 1117 * @sk: the socket 1118 * @doi_def: the CALIPSO DOI to use 1119 * @secattr: the specific security attributes of the socket 1120 * 1121 * Description: 1122 * Set the CALIPSO option on the given socket using the DOI definition and 1123 * security attributes passed to the function. This function requires 1124 * exclusive access to @sk, which means it either needs to be in the 1125 * process of being created or locked. Returns zero on success and negative 1126 * values on failure. 1127 * 1128 */ 1129 static int calipso_sock_setattr(struct sock *sk, 1130 const struct calipso_doi *doi_def, 1131 const struct netlbl_lsm_secattr *secattr) 1132 { 1133 int ret_val; 1134 struct ipv6_opt_hdr *old, *new; 1135 struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); 1136 1137 old = NULL; 1138 if (txopts) 1139 old = txopts->hopopt; 1140 1141 new = calipso_opt_insert(old, doi_def, secattr); 1142 txopt_put(txopts); 1143 if (IS_ERR(new)) 1144 return PTR_ERR(new); 1145 1146 ret_val = calipso_opt_update(sk, new); 1147 1148 kfree(new); 1149 return ret_val; 1150 } 1151 1152 /** 1153 * calipso_sock_delattr - Delete the CALIPSO option from a socket 1154 * @sk: the socket 1155 * 1156 * Description: 1157 * Removes the CALIPSO option from a socket, if present. 1158 * 1159 */ 1160 static void calipso_sock_delattr(struct sock *sk) 1161 { 1162 struct ipv6_opt_hdr *new_hop; 1163 struct ipv6_txoptions *txopts = txopt_get(inet6_sk(sk)); 1164 1165 if (!txopts || !txopts->hopopt) 1166 goto done; 1167 1168 if (calipso_opt_del(txopts->hopopt, &new_hop)) 1169 goto done; 1170 1171 calipso_opt_update(sk, new_hop); 1172 kfree(new_hop); 1173 1174 done: 1175 txopt_put(txopts); 1176 } 1177 1178 /* request sock functions. 1179 */ 1180 1181 /** 1182 * calipso_req_setattr - Add a CALIPSO option to a connection request socket 1183 * @req: the connection request socket 1184 * @doi_def: the CALIPSO DOI to use 1185 * @secattr: the specific security attributes of the socket 1186 * 1187 * Description: 1188 * Set the CALIPSO option on the given socket using the DOI definition and 1189 * security attributes passed to the function. Returns zero on success and 1190 * negative values on failure. 1191 * 1192 */ 1193 static int calipso_req_setattr(struct request_sock *req, 1194 const struct calipso_doi *doi_def, 1195 const struct netlbl_lsm_secattr *secattr) 1196 { 1197 struct ipv6_txoptions *txopts; 1198 struct inet_request_sock *req_inet = inet_rsk(req); 1199 struct ipv6_opt_hdr *old, *new; 1200 struct sock *sk = sk_to_full_sk(req_to_sk(req)); 1201 1202 if (req_inet->ipv6_opt && req_inet->ipv6_opt->hopopt) 1203 old = req_inet->ipv6_opt->hopopt; 1204 else 1205 old = NULL; 1206 1207 new = calipso_opt_insert(old, doi_def, secattr); 1208 if (IS_ERR(new)) 1209 return PTR_ERR(new); 1210 1211 txopts = ipv6_renew_options(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, new); 1212 1213 kfree(new); 1214 1215 if (IS_ERR(txopts)) 1216 return PTR_ERR(txopts); 1217 1218 txopts = xchg(&req_inet->ipv6_opt, txopts); 1219 if (txopts) { 1220 atomic_sub(txopts->tot_len, &sk->sk_omem_alloc); 1221 txopt_put(txopts); 1222 } 1223 1224 return 0; 1225 } 1226 1227 /** 1228 * calipso_req_delattr - Delete the CALIPSO option from a request socket 1229 * @reg: the request socket 1230 * 1231 * Description: 1232 * Removes the CALIPSO option from a request socket, if present. 1233 * 1234 */ 1235 static void calipso_req_delattr(struct request_sock *req) 1236 { 1237 struct inet_request_sock *req_inet = inet_rsk(req); 1238 struct ipv6_opt_hdr *new; 1239 struct ipv6_txoptions *txopts; 1240 struct sock *sk = sk_to_full_sk(req_to_sk(req)); 1241 1242 if (!req_inet->ipv6_opt || !req_inet->ipv6_opt->hopopt) 1243 return; 1244 1245 if (calipso_opt_del(req_inet->ipv6_opt->hopopt, &new)) 1246 return; /* Nothing to do */ 1247 1248 txopts = ipv6_renew_options(sk, req_inet->ipv6_opt, IPV6_HOPOPTS, new); 1249 1250 if (!IS_ERR(txopts)) { 1251 txopts = xchg(&req_inet->ipv6_opt, txopts); 1252 if (txopts) { 1253 atomic_sub(txopts->tot_len, &sk->sk_omem_alloc); 1254 txopt_put(txopts); 1255 } 1256 } 1257 kfree(new); 1258 } 1259 1260 /* skbuff functions. 1261 */ 1262 1263 /** 1264 * calipso_skbuff_optptr - Find the CALIPSO option in the packet 1265 * @skb: the packet 1266 * 1267 * Description: 1268 * Parse the packet's IP header looking for a CALIPSO option. Returns a pointer 1269 * to the start of the CALIPSO option on success, NULL if one if not found. 1270 * 1271 */ 1272 static unsigned char *calipso_skbuff_optptr(const struct sk_buff *skb) 1273 { 1274 const struct ipv6hdr *ip6_hdr = ipv6_hdr(skb); 1275 int offset; 1276 1277 if (ip6_hdr->nexthdr != NEXTHDR_HOP) 1278 return NULL; 1279 1280 offset = ipv6_find_tlv(skb, sizeof(*ip6_hdr), IPV6_TLV_CALIPSO); 1281 if (offset >= 0) 1282 return (unsigned char *)ip6_hdr + offset; 1283 1284 return NULL; 1285 } 1286 1287 /** 1288 * calipso_skbuff_setattr - Set the CALIPSO option on a packet 1289 * @skb: the packet 1290 * @doi_def: the CALIPSO DOI to use 1291 * @secattr: the security attributes 1292 * 1293 * Description: 1294 * Set the CALIPSO option on the given packet based on the security attributes. 1295 * Returns a pointer to the IP header on success and NULL on failure. 1296 * 1297 */ 1298 static int calipso_skbuff_setattr(struct sk_buff *skb, 1299 const struct calipso_doi *doi_def, 1300 const struct netlbl_lsm_secattr *secattr) 1301 { 1302 int ret_val; 1303 struct ipv6hdr *ip6_hdr; 1304 struct ipv6_opt_hdr *hop; 1305 unsigned char buf[CALIPSO_MAX_BUFFER]; 1306 int len_delta, new_end, pad, payload; 1307 unsigned int start, end; 1308 1309 ip6_hdr = ipv6_hdr(skb); 1310 if (ip6_hdr->nexthdr == NEXTHDR_HOP) { 1311 hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); 1312 ret_val = calipso_opt_find(hop, &start, &end); 1313 if (ret_val && ret_val != -ENOENT) 1314 return ret_val; 1315 } else { 1316 start = 0; 1317 end = 0; 1318 } 1319 1320 memset(buf, 0, sizeof(buf)); 1321 ret_val = calipso_genopt(buf, start & 3, sizeof(buf), doi_def, secattr); 1322 if (ret_val < 0) 1323 return ret_val; 1324 1325 new_end = start + ret_val; 1326 /* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */ 1327 pad = ((new_end & 4) + (end & 7)) & 7; 1328 len_delta = new_end - (int)end + pad; 1329 ret_val = skb_cow(skb, skb_headroom(skb) + len_delta); 1330 if (ret_val < 0) 1331 return ret_val; 1332 1333 ip6_hdr = ipv6_hdr(skb); /* Reset as skb_cow() may have moved it */ 1334 1335 if (len_delta) { 1336 if (len_delta > 0) 1337 skb_push(skb, len_delta); 1338 else 1339 skb_pull(skb, -len_delta); 1340 memmove((char *)ip6_hdr - len_delta, ip6_hdr, 1341 sizeof(*ip6_hdr) + start); 1342 skb_reset_network_header(skb); 1343 ip6_hdr = ipv6_hdr(skb); 1344 payload = ntohs(ip6_hdr->payload_len); 1345 ip6_hdr->payload_len = htons(payload + len_delta); 1346 } 1347 1348 hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); 1349 if (start == 0) { 1350 struct ipv6_opt_hdr *new_hop = (struct ipv6_opt_hdr *)buf; 1351 1352 new_hop->nexthdr = ip6_hdr->nexthdr; 1353 new_hop->hdrlen = len_delta / 8 - 1; 1354 ip6_hdr->nexthdr = NEXTHDR_HOP; 1355 } else { 1356 hop->hdrlen += len_delta / 8; 1357 } 1358 memcpy((char *)hop + start, buf + (start & 3), new_end - start); 1359 calipso_pad_write((unsigned char *)hop, new_end, pad); 1360 1361 return 0; 1362 } 1363 1364 /** 1365 * calipso_skbuff_delattr - Delete any CALIPSO options from a packet 1366 * @skb: the packet 1367 * 1368 * Description: 1369 * Removes any and all CALIPSO options from the given packet. Returns zero on 1370 * success, negative values on failure. 1371 * 1372 */ 1373 static int calipso_skbuff_delattr(struct sk_buff *skb) 1374 { 1375 int ret_val; 1376 struct ipv6hdr *ip6_hdr; 1377 struct ipv6_opt_hdr *old_hop; 1378 u32 old_hop_len, start = 0, end = 0, delta, size, pad; 1379 1380 if (!calipso_skbuff_optptr(skb)) 1381 return 0; 1382 1383 /* since we are changing the packet we should make a copy */ 1384 ret_val = skb_cow(skb, skb_headroom(skb)); 1385 if (ret_val < 0) 1386 return ret_val; 1387 1388 ip6_hdr = ipv6_hdr(skb); 1389 old_hop = (struct ipv6_opt_hdr *)(ip6_hdr + 1); 1390 old_hop_len = ipv6_optlen(old_hop); 1391 1392 ret_val = calipso_opt_find(old_hop, &start, &end); 1393 if (ret_val) 1394 return ret_val; 1395 1396 if (start == sizeof(*old_hop) && end == old_hop_len) { 1397 /* There's no other option in the header so we delete 1398 * the whole thing. */ 1399 delta = old_hop_len; 1400 size = sizeof(*ip6_hdr); 1401 ip6_hdr->nexthdr = old_hop->nexthdr; 1402 } else { 1403 delta = (end - start) & ~7; 1404 if (delta) 1405 old_hop->hdrlen -= delta / 8; 1406 pad = (end - start) & 7; 1407 size = sizeof(*ip6_hdr) + start + pad; 1408 calipso_pad_write((unsigned char *)old_hop, start, pad); 1409 } 1410 1411 if (delta) { 1412 skb_pull(skb, delta); 1413 memmove((char *)ip6_hdr + delta, ip6_hdr, size); 1414 skb_reset_network_header(skb); 1415 } 1416 1417 return 0; 1418 } 1419 1420 static const struct netlbl_calipso_ops ops = { 1421 .doi_add = calipso_doi_add, 1422 .doi_free = calipso_doi_free, 1423 .doi_remove = calipso_doi_remove, 1424 .doi_getdef = calipso_doi_getdef, 1425 .doi_putdef = calipso_doi_putdef, 1426 .doi_walk = calipso_doi_walk, 1427 .sock_getattr = calipso_sock_getattr, 1428 .sock_setattr = calipso_sock_setattr, 1429 .sock_delattr = calipso_sock_delattr, 1430 .req_setattr = calipso_req_setattr, 1431 .req_delattr = calipso_req_delattr, 1432 .opt_getattr = calipso_opt_getattr, 1433 .skbuff_optptr = calipso_skbuff_optptr, 1434 .skbuff_setattr = calipso_skbuff_setattr, 1435 .skbuff_delattr = calipso_skbuff_delattr, 1436 .cache_invalidate = calipso_cache_invalidate, 1437 .cache_add = calipso_cache_add 1438 }; 1439 1440 /** 1441 * calipso_init - Initialize the CALIPSO module 1442 * 1443 * Description: 1444 * Initialize the CALIPSO module and prepare it for use. Returns zero on 1445 * success and negative values on failure. 1446 * 1447 */ 1448 int __init calipso_init(void) 1449 { 1450 int ret_val; 1451 1452 ret_val = calipso_cache_init(); 1453 if (!ret_val) 1454 netlbl_calipso_ops_register(&ops); 1455 return ret_val; 1456 } 1457 1458 void calipso_exit(void) 1459 { 1460 netlbl_calipso_ops_register(NULL); 1461 calipso_cache_invalidate(); 1462 kfree(calipso_cache); 1463 } 1464