Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/net/ipv4/cipso_ipv4.c (Version 2.6.25.8) and /linux/net/ipv4/cipso_ipv4.c (Version 2.6.11.8)


  1 /*                                                  1 
  2  * CIPSO - Commercial IP Security Option          
  3  *                                                
  4  * This is an implementation of the CIPSO 2.2     
  5  * draft-ietf-cipso-ipsecurity-01.txt with add    
  6  * FIPS-188, copies of both documents can be f    
  7  * directory.  While CIPSO never became a full    
  8  * have chosen to adopt the protocol and over     
  9  * de-facto standard for labeled networking.      
 10  *                                                
 11  * Author: Paul Moore <paul.moore@hp.com>         
 12  *                                                
 13  */                                               
 14                                                   
 15 /*                                                
 16  * (c) Copyright Hewlett-Packard Development C    
 17  *                                                
 18  * This program is free software;  you can red    
 19  * it under the terms of the GNU General Publi    
 20  * the Free Software Foundation; either versio    
 21  * (at your option) any later version.            
 22  *                                                
 23  * This program is distributed in the hope tha    
 24  * but WITHOUT ANY WARRANTY;  without even the    
 25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR    
 26  * the GNU General Public License for more det    
 27  *                                                
 28  * You should have received a copy of the GNU     
 29  * along with this program;  if not, write to     
 30  * Foundation, Inc., 59 Temple Place, Suite 33    
 31  *                                                
 32  */                                               
 33                                                   
 34 #include <linux/init.h>                           
 35 #include <linux/types.h>                          
 36 #include <linux/rcupdate.h>                       
 37 #include <linux/list.h>                           
 38 #include <linux/spinlock.h>                       
 39 #include <linux/string.h>                         
 40 #include <linux/jhash.h>                          
 41 #include <net/ip.h>                               
 42 #include <net/icmp.h>                             
 43 #include <net/tcp.h>                              
 44 #include <net/netlabel.h>                         
 45 #include <net/cipso_ipv4.h>                       
 46 #include <asm/atomic.h>                           
 47 #include <asm/bug.h>                              
 48 #include <asm/unaligned.h>                        
 49                                                   
 50 struct cipso_v4_domhsh_entry {                    
 51         char *domain;                             
 52         u32 valid;                                
 53         struct list_head list;                    
 54         struct rcu_head rcu;                      
 55 };                                                
 56                                                   
 57 /* List of available DOI definitions */           
 58 /* XXX - Updates should be minimal so having a    
 59  * cipso_v4_doi_list and the cipso_v4_doi_list    
 60  * okay. */                                       
 61 /* XXX - This currently assumes a minimal numb    
 62  * if in practice there are a lot of different    
 63  * probably be turned into a hash table or som    
 64  * can do quick lookups. */                       
 65 static DEFINE_SPINLOCK(cipso_v4_doi_list_lock)    
 66 static LIST_HEAD(cipso_v4_doi_list);              
 67                                                   
 68 /* Label mapping cache */                         
 69 int cipso_v4_cache_enabled = 1;                   
 70 int cipso_v4_cache_bucketsize = 10;               
 71 #define CIPSO_V4_CACHE_BUCKETBITS     7           
 72 #define CIPSO_V4_CACHE_BUCKETS        (1 << CI    
 73 #define CIPSO_V4_CACHE_REORDERLIMIT   10          
 74 struct cipso_v4_map_cache_bkt {                   
 75         spinlock_t lock;                          
 76         u32 size;                                 
 77         struct list_head list;                    
 78 };                                                
 79 struct cipso_v4_map_cache_entry {                 
 80         u32 hash;                                 
 81         unsigned char *key;                       
 82         size_t key_len;                           
 83                                                   
 84         struct netlbl_lsm_cache *lsm_data;        
 85                                                   
 86         u32 activity;                             
 87         struct list_head list;                    
 88 };                                                
 89 static struct cipso_v4_map_cache_bkt *cipso_v4    
 90                                                   
 91 /* Restricted bitmap (tag #1) flags */            
 92 int cipso_v4_rbm_optfmt = 0;                      
 93 int cipso_v4_rbm_strictvalid = 1;                 
 94                                                   
 95 /*                                                
 96  * Protocol Constants                             
 97  */                                               
 98                                                   
 99 /* Maximum size of the CIPSO IP option, derive    
100  * IPv4 header size is 60 bytes and the base I    
101 #define CIPSO_V4_OPT_LEN_MAX          40          
102                                                   
103 /* Length of the base CIPSO option, this inclu    
104  * option length (1 byte), and the DOI (4 byte    
105 #define CIPSO_V4_HDR_LEN              6           
106                                                   
107 /* Base length of the restrictive category bit    
108 #define CIPSO_V4_TAG_RBM_BLEN         4           
109                                                   
110 /* Base length of the enumerated category tag     
111 #define CIPSO_V4_TAG_ENUM_BLEN        4           
112                                                   
113 /* Base length of the ranged categories bitmap    
114 #define CIPSO_V4_TAG_RNG_BLEN         4           
115 /* The maximum number of category ranges permi    
116  * (tag #5).  You may note that the IETF draft    
117  * of category ranges is 7, but if the low end    
118  * zero then it is possibile to fit 8 category    
119  * be omitted. */                                 
120 #define CIPSO_V4_TAG_RNG_CAT_MAX      8           
121                                                   
122 /*                                                
123  * Helper Functions                               
124  */                                               
125                                                   
126 /**                                               
127  * cipso_v4_bitmap_walk - Walk a bitmap lookin    
128  * @bitmap: the bitmap                            
129  * @bitmap_len: length in bits                    
130  * @offset: starting offset                       
131  * @state: if non-zero, look for a set (1) bit    
132  *                                                
133  * Description:                                   
134  * Starting at @offset, walk the bitmap from l    
135  * desired bit is found or we reach the end.      
136  * not found, or -2 if error.                     
137  */                                               
138 static int cipso_v4_bitmap_walk(const unsigned    
139                                 u32 bitmap_len    
140                                 u32 offset,       
141                                 u8 state)         
142 {                                                 
143         u32 bit_spot;                             
144         u32 byte_offset;                          
145         unsigned char bitmask;                    
146         unsigned char byte;                       
147                                                   
148         /* gcc always rounds to zero when doin    
149         byte_offset = offset / 8;                 
150         byte = bitmap[byte_offset];               
151         bit_spot = offset;                        
152         bitmask = 0x80 >> (offset % 8);           
153                                                   
154         while (bit_spot < bitmap_len) {           
155                 if ((state && (byte & bitmask)    
156                     (state == 0 && (byte & bit    
157                         return bit_spot;          
158                                                   
159                 bit_spot++;                       
160                 bitmask >>= 1;                    
161                 if (bitmask == 0) {               
162                         byte = bitmap[++byte_o    
163                         bitmask = 0x80;           
164                 }                                 
165         }                                         
166                                                   
167         return -1;                                
168 }                                                 
169                                                   
170 /**                                               
171  * cipso_v4_bitmap_setbit - Sets a single bit     
172  * @bitmap: the bitmap                            
173  * @bit: the bit                                  
174  * @state: if non-zero, set the bit (1) else c    
175  *                                                
176  * Description:                                   
177  * Set a single bit in the bitmask.  Returns z    
178  * on error.                                      
179  */                                               
180 static void cipso_v4_bitmap_setbit(unsigned ch    
181                                    u32 bit,       
182                                    u8 state)      
183 {                                                 
184         u32 byte_spot;                            
185         u8 bitmask;                               
186                                                   
187         /* gcc always rounds to zero when doin    
188         byte_spot = bit / 8;                      
189         bitmask = 0x80 >> (bit % 8);              
190         if (state)                                
191                 bitmap[byte_spot] |= bitmask;     
192         else                                      
193                 bitmap[byte_spot] &= ~bitmask;    
194 }                                                 
195                                                   
196 /**                                               
197  * cipso_v4_doi_domhsh_free - Frees a domain l    
198  * @entry: the entry's RCU field                  
199  *                                                
200  * Description:                                   
201  * This function is designed to be used as a c    
202  * function so that the memory allocated to a     
203  * safely.                                        
204  *                                                
205  */                                               
206 static void cipso_v4_doi_domhsh_free(struct rc    
207 {                                                 
208         struct cipso_v4_domhsh_entry *ptr;        
209                                                   
210         ptr = container_of(entry, struct cipso    
211         kfree(ptr->domain);                       
212         kfree(ptr);                               
213 }                                                 
214                                                   
215 /**                                               
216  * cipso_v4_cache_entry_free - Frees a cache e    
217  * @entry: the entry to free                      
218  *                                                
219  * Description:                                   
220  * This function frees the memory associated w    
221  * LSM cache data if there are no longer any u    
222  *                                                
223  */                                               
224 static void cipso_v4_cache_entry_free(struct c    
225 {                                                 
226         if (entry->lsm_data)                      
227                 netlbl_secattr_cache_free(entr    
228         kfree(entry->key);                        
229         kfree(entry);                             
230 }                                                 
231                                                   
232 /**                                               
233  * cipso_v4_map_cache_hash - Hashing function     
234  * @key: the hash key                             
235  * @key_len: the length of the key in bytes       
236  *                                                
237  * Description:                                   
238  * The CIPSO tag hashing function.  Returns a     
239  *                                                
240  */                                               
241 static u32 cipso_v4_map_cache_hash(const unsig    
242 {                                                 
243         return jhash(key, key_len, 0);            
244 }                                                 
245                                                   
246 /*                                                
247  * Label Mapping Cache Functions                  
248  */                                               
249                                                   
250 /**                                               
251  * cipso_v4_cache_init - Initialize the CIPSO     
252  *                                                
253  * Description:                                   
254  * Initializes the CIPSO label mapping cache,     
255  * before any of the other functions defined i    
256  * success, negative values on error.             
257  *                                                
258  */                                               
259 static int cipso_v4_cache_init(void)              
260 {                                                 
261         u32 iter;                                 
262                                                   
263         cipso_v4_cache = kcalloc(CIPSO_V4_CACH    
264                                  sizeof(struct    
265                                  GFP_KERNEL);     
266         if (cipso_v4_cache == NULL)               
267                 return -ENOMEM;                   
268                                                   
269         for (iter = 0; iter < CIPSO_V4_CACHE_B    
270                 spin_lock_init(&cipso_v4_cache    
271                 cipso_v4_cache[iter].size = 0;    
272                 INIT_LIST_HEAD(&cipso_v4_cache    
273         }                                         
274                                                   
275         return 0;                                 
276 }                                                 
277                                                   
278 /**                                               
279  * cipso_v4_cache_invalidate - Invalidates the    
280  *                                                
281  * Description:                                   
282  * Invalidates and frees any entries in the CI    
283  * success and negative values on failure.        
284  *                                                
285  */                                               
286 void cipso_v4_cache_invalidate(void)              
287 {                                                 
288         struct cipso_v4_map_cache_entry *entry    
289         u32 iter;                                 
290                                                   
291         for (iter = 0; iter < CIPSO_V4_CACHE_B    
292                 spin_lock_bh(&cipso_v4_cache[i    
293                 list_for_each_entry_safe(entry    
294                                          tmp_e    
295                                          &cips    
296                         list_del(&entry->list)    
297                         cipso_v4_cache_entry_f    
298                 }                                 
299                 cipso_v4_cache[iter].size = 0;    
300                 spin_unlock_bh(&cipso_v4_cache    
301         }                                         
302                                                   
303         return;                                   
304 }                                                 
305                                                   
306 /**                                               
307  * cipso_v4_cache_check - Check the CIPSO cach    
308  * @key: the buffer to check                      
309  * @key_len: buffer length in bytes               
310  * @secattr: the security attribute struct to     
311  *                                                
312  * Description:                                   
313  * This function checks the cache to see if a     
314  * the given key.  If there is a match then th    
315  * @secattr struct is populated with the corre    
316  * cache is adjusted in the following manner i    
317  * first in the cache bucket:                     
318  *                                                
319  *  1. The cache entry's activity counter is i    
320  *  2. The previous (higher ranking) entry's a    
321  *  3. If the difference between the two activ    
322  *     CIPSO_V4_CACHE_REORDERLIMIT the two ent    
323  *                                                
324  * Returns zero on success, -ENOENT for a cach    
325  * on error.                                      
326  *                                                
327  */                                               
328 static int cipso_v4_cache_check(const unsigned    
329                                 u32 key_len,      
330                                 struct netlbl_    
331 {                                                 
332         u32 bkt;                                  
333         struct cipso_v4_map_cache_entry *entry    
334         struct cipso_v4_map_cache_entry *prev_    
335         u32 hash;                                 
336                                                   
337         if (!cipso_v4_cache_enabled)              
338                 return -ENOENT;                   
339                                                   
340         hash = cipso_v4_map_cache_hash(key, ke    
341         bkt = hash & (CIPSO_V4_CACHE_BUCKETBIT    
342         spin_lock_bh(&cipso_v4_cache[bkt].lock    
343         list_for_each_entry(entry, &cipso_v4_c    
344                 if (entry->hash == hash &&        
345                     entry->key_len == key_len     
346                     memcmp(entry->key, key, ke    
347                         entry->activity += 1;     
348                         atomic_inc(&entry->lsm    
349                         secattr->cache = entry    
350                         secattr->flags |= NETL    
351                         secattr->type = NETLBL    
352                         if (prev_entry == NULL    
353                                 spin_unlock_bh    
354                                 return 0;         
355                         }                         
356                                                   
357                         if (prev_entry->activi    
358                                 prev_entry->ac    
359                         if (entry->activity >     
360                             entry->activity -     
361                             CIPSO_V4_CACHE_REO    
362                                 __list_del(ent    
363                                 __list_add(&en    
364                                            pre    
365                                            &pr    
366                         }                         
367                                                   
368                         spin_unlock_bh(&cipso_    
369                         return 0;                 
370                 }                                 
371                 prev_entry = entry;               
372         }                                         
373         spin_unlock_bh(&cipso_v4_cache[bkt].lo    
374                                                   
375         return -ENOENT;                           
376 }                                                 
377                                                   
378 /**                                               
379  * cipso_v4_cache_add - Add an entry to the CI    
380  * @skb: the packet                               
381  * @secattr: the packet's security attributes     
382  *                                                
383  * Description:                                   
384  * Add a new entry into the CIPSO label mappin    
385  * head of the cache bucket's list, if the cac    
386  * the last entry in the list first.  It is im    
387  * currently no checking for duplicate keys.      
388  * negative values on failure.                    
389  *                                                
390  */                                               
391 int cipso_v4_cache_add(const struct sk_buff *s    
392                        const struct netlbl_lsm    
393 {                                                 
394         int ret_val = -EPERM;                     
395         u32 bkt;                                  
396         struct cipso_v4_map_cache_entry *entry    
397         struct cipso_v4_map_cache_entry *old_e    
398         unsigned char *cipso_ptr;                 
399         u32 cipso_ptr_len;                        
400                                                   
401         if (!cipso_v4_cache_enabled || cipso_v    
402                 return 0;                         
403                                                   
404         cipso_ptr = CIPSO_V4_OPTPTR(skb);         
405         cipso_ptr_len = cipso_ptr[1];             
406                                                   
407         entry = kzalloc(sizeof(*entry), GFP_AT    
408         if (entry == NULL)                        
409                 return -ENOMEM;                   
410         entry->key = kmemdup(cipso_ptr, cipso_    
411         if (entry->key == NULL) {                 
412                 ret_val = -ENOMEM;                
413                 goto cache_add_failure;           
414         }                                         
415         entry->key_len = cipso_ptr_len;           
416         entry->hash = cipso_v4_map_cache_hash(    
417         atomic_inc(&secattr->cache->refcount);    
418         entry->lsm_data = secattr->cache;         
419                                                   
420         bkt = entry->hash & (CIPSO_V4_CACHE_BU    
421         spin_lock_bh(&cipso_v4_cache[bkt].lock    
422         if (cipso_v4_cache[bkt].size < cipso_v    
423                 list_add(&entry->list, &cipso_    
424                 cipso_v4_cache[bkt].size += 1;    
425         } else {                                  
426                 old_entry = list_entry(cipso_v    
427                                        struct     
428                 list_del(&old_entry->list);       
429                 list_add(&entry->list, &cipso_    
430                 cipso_v4_cache_entry_free(old_    
431         }                                         
432         spin_unlock_bh(&cipso_v4_cache[bkt].lo    
433                                                   
434         return 0;                                 
435                                                   
436 cache_add_failure:                                
437         if (entry)                                
438                 cipso_v4_cache_entry_free(entr    
439         return ret_val;                           
440 }                                                 
441                                                   
442 /*                                                
443  * DOI List Functions                             
444  */                                               
445                                                   
446 /**                                               
447  * cipso_v4_doi_search - Searches for a DOI de    
448  * @doi: the DOI to search for                    
449  *                                                
450  * Description:                                   
451  * Search the DOI definition list for a DOI de    
452  * matches @doi.  The caller is responsibile f    
453  * Returns a pointer to the DOI definition on     
454  */                                               
455 static struct cipso_v4_doi *cipso_v4_doi_searc    
456 {                                                 
457         struct cipso_v4_doi *iter;                
458                                                   
459         list_for_each_entry_rcu(iter, &cipso_v    
460                 if (iter->doi == doi && iter->    
461                         return iter;              
462         return NULL;                              
463 }                                                 
464                                                   
465 /**                                               
466  * cipso_v4_doi_add - Add a new DOI to the CIP    
467  * @doi_def: the DOI structure                    
468  *                                                
469  * Description:                                   
470  * The caller defines a new DOI for use by the    
471  * function to add it to the list of acceptabl    
472  * ensure that the mapping table specified in     
473  * requirements of the mapping type (see cipso    
474  * zero on success and non-zero on failure.       
475  *                                                
476  */                                               
477 int cipso_v4_doi_add(struct cipso_v4_doi *doi_    
478 {                                                 
479         u32 iter;                                 
480                                                   
481         if (doi_def == NULL || doi_def->doi ==    
482                 return -EINVAL;                   
483         for (iter = 0; iter < CIPSO_V4_TAG_MAX    
484                 switch (doi_def->tags[iter]) {    
485                 case CIPSO_V4_TAG_RBITMAP:        
486                         break;                    
487                 case CIPSO_V4_TAG_RANGE:          
488                         if (doi_def->type != C    
489                                 return -EINVAL    
490                         break;                    
491                 case CIPSO_V4_TAG_INVALID:        
492                         if (iter == 0)            
493                                 return -EINVAL    
494                         break;                    
495                 case CIPSO_V4_TAG_ENUM:           
496                         if (doi_def->type != C    
497                                 return -EINVAL    
498                         break;                    
499                 default:                          
500                         return -EINVAL;           
501                 }                                 
502         }                                         
503                                                   
504         doi_def->valid = 1;                       
505         INIT_RCU_HEAD(&doi_def->rcu);             
506         INIT_LIST_HEAD(&doi_def->dom_list);       
507                                                   
508         spin_lock(&cipso_v4_doi_list_lock);       
509         if (cipso_v4_doi_search(doi_def->doi)     
510                 goto doi_add_failure;             
511         list_add_tail_rcu(&doi_def->list, &cip    
512         spin_unlock(&cipso_v4_doi_list_lock);     
513                                                   
514         return 0;                                 
515                                                   
516 doi_add_failure:                                  
517         spin_unlock(&cipso_v4_doi_list_lock);     
518         return -EEXIST;                           
519 }                                                 
520                                                   
521 /**                                               
522  * cipso_v4_doi_remove - Remove an existing DO    
523  * @doi: the DOI value                            
524  * @audit_secid: the LSM secid to use in the a    
525  * @callback: the DOI cleanup/free callback       
526  *                                                
527  * Description:                                   
528  * Removes a DOI definition from the CIPSO eng    
529  * free any memory.  The NetLabel routines wil    
530  * LSM domain mappings as well as our own doma    
531  * success and negative values on failure.        
532  *                                                
533  */                                               
534 int cipso_v4_doi_remove(u32 doi,                  
535                         struct netlbl_audit *a    
536                         void (*callback) (stru    
537 {                                                 
538         struct cipso_v4_doi *doi_def;             
539         struct cipso_v4_domhsh_entry *dom_iter    
540                                                   
541         spin_lock(&cipso_v4_doi_list_lock);       
542         doi_def = cipso_v4_doi_search(doi);       
543         if (doi_def != NULL) {                    
544                 doi_def->valid = 0;               
545                 list_del_rcu(&doi_def->list);     
546                 spin_unlock(&cipso_v4_doi_list    
547                 rcu_read_lock();                  
548                 list_for_each_entry_rcu(dom_it    
549                         if (dom_iter->valid)      
550                                 netlbl_cfg_map    
551                                                   
552                 rcu_read_unlock();                
553                 cipso_v4_cache_invalidate();      
554                 call_rcu(&doi_def->rcu, callba    
555                 return 0;                         
556         }                                         
557         spin_unlock(&cipso_v4_doi_list_lock);     
558                                                   
559         return -ENOENT;                           
560 }                                                 
561                                                   
562 /**                                               
563  * cipso_v4_doi_getdef - Returns a pointer to     
564  * @doi: the DOI value                            
565  *                                                
566  * Description:                                   
567  * Searches for a valid DOI definition and if     
568  * the caller.  Otherwise NULL is returned.  T    
569  * rcu_read_lock() is held while accessing the    
570  *                                                
571  */                                               
572 struct cipso_v4_doi *cipso_v4_doi_getdef(u32 d    
573 {                                                 
574         return cipso_v4_doi_search(doi);          
575 }                                                 
576                                                   
577 /**                                               
578  * cipso_v4_doi_walk - Iterate through the DOI    
579  * @skip_cnt: skip past this number of DOI def    
580  * @callback: callback for each DOI definition    
581  * @cb_arg: argument for the callback function    
582  *                                                
583  * Description:                                   
584  * Iterate over the DOI definition list, skipp    
585  * For each entry call @callback, if @callback    
586  * 'walking' through the list and return.  Upd    
587  * return.  Returns zero on success, negative     
588  *                                                
589  */                                               
590 int cipso_v4_doi_walk(u32 *skip_cnt,              
591                      int (*callback) (struct c    
592                      void *cb_arg)                
593 {                                                 
594         int ret_val = -ENOENT;                    
595         u32 doi_cnt = 0;                          
596         struct cipso_v4_doi *iter_doi;            
597                                                   
598         rcu_read_lock();                          
599         list_for_each_entry_rcu(iter_doi, &cip    
600                 if (iter_doi->valid) {            
601                         if (doi_cnt++ < *skip_    
602                                 continue;         
603                         ret_val = callback(ite    
604                         if (ret_val < 0) {        
605                                 doi_cnt--;        
606                                 goto doi_walk_    
607                         }                         
608                 }                                 
609                                                   
610 doi_walk_return:                                  
611         rcu_read_unlock();                        
612         *skip_cnt = doi_cnt;                      
613         return ret_val;                           
614 }                                                 
615                                                   
616 /**                                               
617  * cipso_v4_doi_domhsh_add - Adds a domain ent    
618  * @doi_def: the DOI definition                   
619  * @domain: the domain to add                     
620  *                                                
621  * Description:                                   
622  * Adds the @domain to the DOI specified by @d    
623  * should only be called by external functions    
624  * does allocate memory.  Returns zero on succ    
625  *                                                
626  */                                               
627 int cipso_v4_doi_domhsh_add(struct cipso_v4_do    
628 {                                                 
629         struct cipso_v4_domhsh_entry *iter;       
630         struct cipso_v4_domhsh_entry *new_dom;    
631                                                   
632         new_dom = kzalloc(sizeof(*new_dom), GF    
633         if (new_dom == NULL)                      
634                 return -ENOMEM;                   
635         if (domain) {                             
636                 new_dom->domain = kstrdup(doma    
637                 if (new_dom->domain == NULL) {    
638                         kfree(new_dom);           
639                         return -ENOMEM;           
640                 }                                 
641         }                                         
642         new_dom->valid = 1;                       
643         INIT_RCU_HEAD(&new_dom->rcu);             
644                                                   
645         spin_lock(&cipso_v4_doi_list_lock);       
646         list_for_each_entry(iter, &doi_def->do    
647                 if (iter->valid &&                
648                     ((domain != NULL && iter->    
649                       strcmp(iter->domain, dom    
650                      (domain == NULL && iter->    
651                         spin_unlock(&cipso_v4_    
652                         kfree(new_dom->domain)    
653                         kfree(new_dom);           
654                         return -EEXIST;           
655                 }                                 
656         list_add_tail_rcu(&new_dom->list, &doi    
657         spin_unlock(&cipso_v4_doi_list_lock);     
658                                                   
659         return 0;                                 
660 }                                                 
661                                                   
662 /**                                               
663  * cipso_v4_doi_domhsh_remove - Removes a doma    
664  * @doi_def: the DOI definition                   
665  * @domain: the domain to remove                  
666  *                                                
667  * Description:                                   
668  * Removes the @domain from the DOI specified     
669  * should only be called by external functions    
670  * on success and negative values on error.       
671  *                                                
672  */                                               
673 int cipso_v4_doi_domhsh_remove(struct cipso_v4    
674                                const char *dom    
675 {                                                 
676         struct cipso_v4_domhsh_entry *iter;       
677                                                   
678         spin_lock(&cipso_v4_doi_list_lock);       
679         list_for_each_entry(iter, &doi_def->do    
680                 if (iter->valid &&                
681                     ((domain != NULL && iter->    
682                       strcmp(iter->domain, dom    
683                      (domain == NULL && iter->    
684                         iter->valid = 0;          
685                         list_del_rcu(&iter->li    
686                         spin_unlock(&cipso_v4_    
687                         call_rcu(&iter->rcu, c    
688                         return 0;                 
689                 }                                 
690         spin_unlock(&cipso_v4_doi_list_lock);     
691                                                   
692         return -ENOENT;                           
693 }                                                 
694                                                   
695 /*                                                
696  * Label Mapping Functions                        
697  */                                               
698                                                   
699 /**                                               
700  * cipso_v4_map_lvl_valid - Checks to see if t    
701  * @doi_def: the DOI definition                   
702  * @level: the level to check                     
703  *                                                
704  * Description:                                   
705  * Checks the given level against the given DO    
706  * negative value if the level does not have a    
707  * if the level is defined by the DOI.            
708  *                                                
709  */                                               
710 static int cipso_v4_map_lvl_valid(const struct    
711 {                                                 
712         switch (doi_def->type) {                  
713         case CIPSO_V4_MAP_PASS:                   
714                 return 0;                         
715         case CIPSO_V4_MAP_STD:                    
716                 if (doi_def->map.std->lvl.cips    
717                         return 0;                 
718                 break;                            
719         }                                         
720                                                   
721         return -EFAULT;                           
722 }                                                 
723                                                   
724 /**                                               
725  * cipso_v4_map_lvl_hton - Perform a level map    
726  * @doi_def: the DOI definition                   
727  * @host_lvl: the host MLS level                  
728  * @net_lvl: the network/CIPSO MLS level          
729  *                                                
730  * Description:                                   
731  * Perform a label mapping to translate a loca    
732  * CIPSO level using the given DOI definition.    
733  * negative values otherwise.                     
734  *                                                
735  */                                               
736 static int cipso_v4_map_lvl_hton(const struct     
737                                  u32 host_lvl,    
738                                  u32 *net_lvl)    
739 {                                                 
740         switch (doi_def->type) {                  
741         case CIPSO_V4_MAP_PASS:                   
742                 *net_lvl = host_lvl;              
743                 return 0;                         
744         case CIPSO_V4_MAP_STD:                    
745                 if (host_lvl < doi_def->map.st    
746                     doi_def->map.std->lvl.loca    
747                         *net_lvl = doi_def->ma    
748                         return 0;                 
749                 }                                 
750                 return -EPERM;                    
751         }                                         
752                                                   
753         return -EINVAL;                           
754 }                                                 
755                                                   
756 /**                                               
757  * cipso_v4_map_lvl_ntoh - Perform a level map    
758  * @doi_def: the DOI definition                   
759  * @net_lvl: the network/CIPSO MLS level          
760  * @host_lvl: the host MLS level                  
761  *                                                
762  * Description:                                   
763  * Perform a label mapping to translate a CIPS    
764  * level using the given DOI definition.  Retu    
765  * values otherwise.                              
766  *                                                
767  */                                               
768 static int cipso_v4_map_lvl_ntoh(const struct     
769                                  u32 net_lvl,     
770                                  u32 *host_lvl    
771 {                                                 
772         struct cipso_v4_std_map_tbl *map_tbl;     
773                                                   
774         switch (doi_def->type) {                  
775         case CIPSO_V4_MAP_PASS:                   
776                 *host_lvl = net_lvl;              
777                 return 0;                         
778         case CIPSO_V4_MAP_STD:                    
779                 map_tbl = doi_def->map.std;       
780                 if (net_lvl < map_tbl->lvl.cip    
781                     map_tbl->lvl.cipso[net_lvl    
782                         *host_lvl = doi_def->m    
783                         return 0;                 
784                 }                                 
785                 return -EPERM;                    
786         }                                         
787                                                   
788         return -EINVAL;                           
789 }                                                 
790                                                   
791 /**                                               
792  * cipso_v4_map_cat_rbm_valid - Checks to see     
793  * @doi_def: the DOI definition                   
794  * @bitmap: category bitmap                       
795  * @bitmap_len: bitmap length in bytes            
796  *                                                
797  * Description:                                   
798  * Checks the given category bitmap against th    
799  * returns a negative value if any of the cate    
800  * a valid mapping and a zero value if all of     
801  *                                                
802  */                                               
803 static int cipso_v4_map_cat_rbm_valid(const st    
804                                       const un    
805                                       u32 bitm    
806 {                                                 
807         int cat = -1;                             
808         u32 bitmap_len_bits = bitmap_len * 8;     
809         u32 cipso_cat_size;                       
810         u32 *cipso_array;                         
811                                                   
812         switch (doi_def->type) {                  
813         case CIPSO_V4_MAP_PASS:                   
814                 return 0;                         
815         case CIPSO_V4_MAP_STD:                    
816                 cipso_cat_size = doi_def->map.    
817                 cipso_array = doi_def->map.std    
818                 for (;;) {                        
819                         cat = cipso_v4_bitmap_    
820                                                   
821                                                   
822                                                   
823                         if (cat < 0)              
824                                 break;            
825                         if (cat >= cipso_cat_s    
826                             cipso_array[cat] >    
827                                 return -EFAULT    
828                 }                                 
829                                                   
830                 if (cat == -1)                    
831                         return 0;                 
832                 break;                            
833         }                                         
834                                                   
835         return -EFAULT;                           
836 }                                                 
837                                                   
838 /**                                               
839  * cipso_v4_map_cat_rbm_hton - Perform a categ    
840  * @doi_def: the DOI definition                   
841  * @secattr: the security attributes              
842  * @net_cat: the zero'd out category bitmap in    
843  * @net_cat_len: the length of the CIPSO bitma    
844  *                                                
845  * Description:                                   
846  * Perform a label mapping to translate a loca    
847  * correct CIPSO bitmap using the given DOI de    
848  * size in bytes of the network bitmap on succ    
849  *                                                
850  */                                               
851 static int cipso_v4_map_cat_rbm_hton(const str    
852                                      const str    
853                                      unsigned     
854                                      u32 net_c    
855 {                                                 
856         int host_spot = -1;                       
857         u32 net_spot = CIPSO_V4_INV_CAT;          
858         u32 net_spot_max = 0;                     
859         u32 net_clen_bits = net_cat_len * 8;      
860         u32 host_cat_size = 0;                    
861         u32 *host_cat_array = NULL;               
862                                                   
863         if (doi_def->type == CIPSO_V4_MAP_STD)    
864                 host_cat_size = doi_def->map.s    
865                 host_cat_array = doi_def->map.    
866         }                                         
867                                                   
868         for (;;) {                                
869                 host_spot = netlbl_secattr_cat    
870                                                   
871                 if (host_spot < 0)                
872                         break;                    
873                                                   
874                 switch (doi_def->type) {          
875                 case CIPSO_V4_MAP_PASS:           
876                         net_spot = host_spot;     
877                         break;                    
878                 case CIPSO_V4_MAP_STD:            
879                         if (host_spot >= host_    
880                                 return -EPERM;    
881                         net_spot = host_cat_ar    
882                         if (net_spot >= CIPSO_    
883                                 return -EPERM;    
884                         break;                    
885                 }                                 
886                 if (net_spot >= net_clen_bits)    
887                         return -ENOSPC;           
888                 cipso_v4_bitmap_setbit(net_cat    
889                                                   
890                 if (net_spot > net_spot_max)      
891                         net_spot_max = net_spo    
892         }                                         
893                                                   
894         if (++net_spot_max % 8)                   
895                 return net_spot_max / 8 + 1;      
896         return net_spot_max / 8;                  
897 }                                                 
898                                                   
899 /**                                               
900  * cipso_v4_map_cat_rbm_ntoh - Perform a categ    
901  * @doi_def: the DOI definition                   
902  * @net_cat: the category bitmap in network/CI    
903  * @net_cat_len: the length of the CIPSO bitma    
904  * @secattr: the security attributes              
905  *                                                
906  * Description:                                   
907  * Perform a label mapping to translate a CIPS    
908  * MLS category bitmap using the given DOI def    
909  * success, negative values on failure.           
910  *                                                
911  */                                               
912 static int cipso_v4_map_cat_rbm_ntoh(const str    
913                                      const uns    
914                                      u32 net_c    
915                                      struct ne    
916 {                                                 
917         int ret_val;                              
918         int net_spot = -1;                        
919         u32 host_spot = CIPSO_V4_INV_CAT;         
920         u32 net_clen_bits = net_cat_len * 8;      
921         u32 net_cat_size = 0;                     
922         u32 *net_cat_array = NULL;                
923                                                   
924         if (doi_def->type == CIPSO_V4_MAP_STD)    
925                 net_cat_size = doi_def->map.st    
926                 net_cat_array = doi_def->map.s    
927         }                                         
928                                                   
929         for (;;) {                                
930                 net_spot = cipso_v4_bitmap_wal    
931                                                   
932                                                   
933                                                   
934                 if (net_spot < 0) {               
935                         if (net_spot == -2)       
936                                 return -EFAULT    
937                         return 0;                 
938                 }                                 
939                                                   
940                 switch (doi_def->type) {          
941                 case CIPSO_V4_MAP_PASS:           
942                         host_spot = net_spot;     
943                         break;                    
944                 case CIPSO_V4_MAP_STD:            
945                         if (net_spot >= net_ca    
946                                 return -EPERM;    
947                         host_spot = net_cat_ar    
948                         if (host_spot >= CIPSO    
949                                 return -EPERM;    
950                         break;                    
951                 }                                 
952                 ret_val = netlbl_secattr_catma    
953                                                   
954                                                   
955                 if (ret_val != 0)                 
956                         return ret_val;           
957         }                                         
958                                                   
959         return -EINVAL;                           
960 }                                                 
961                                                   
962 /**                                               
963  * cipso_v4_map_cat_enum_valid - Checks to see    
964  * @doi_def: the DOI definition                   
965  * @enumcat: category list                        
966  * @enumcat_len: length of the category list i    
967  *                                                
968  * Description:                                   
969  * Checks the given categories against the giv    
970  * negative value if any of the categories do     
971  * zero value if all of the categories are val    
972  *                                                
973  */                                               
974 static int cipso_v4_map_cat_enum_valid(const s    
975                                        const u    
976                                        u32 enu    
977 {                                                 
978         u16 cat;                                  
979         int cat_prev = -1;                        
980         u32 iter;                                 
981                                                   
982         if (doi_def->type != CIPSO_V4_MAP_PASS    
983                 return -EFAULT;                   
984                                                   
985         for (iter = 0; iter < enumcat_len; ite    
986                 cat = ntohs(get_unaligned((__b    
987                 if (cat <= cat_prev)              
988                         return -EFAULT;           
989                 cat_prev = cat;                   
990         }                                         
991                                                   
992         return 0;                                 
993 }                                                 
994                                                   
995 /**                                               
996  * cipso_v4_map_cat_enum_hton - Perform a cate    
997  * @doi_def: the DOI definition                   
998  * @secattr: the security attributes              
999  * @net_cat: the zero'd out category list in n    
1000  * @net_cat_len: the length of the CIPSO cate    
1001  *                                               
1002  * Description:                                  
1003  * Perform a label mapping to translate a loc    
1004  * correct CIPSO category list using the give    
1005  * size in bytes of the network category bitm    
1006  * otherwise.                                    
1007  *                                               
1008  */                                              
1009 static int cipso_v4_map_cat_enum_hton(const s    
1010                                       const s    
1011                                       unsigne    
1012                                       u32 net    
1013 {                                                
1014         int cat = -1;                            
1015         u32 cat_iter = 0;                        
1016                                                  
1017         for (;;) {                               
1018                 cat = netlbl_secattr_catmap_w    
1019                                                  
1020                 if (cat < 0)                     
1021                         break;                   
1022                 if ((cat_iter + 2) > net_cat_    
1023                         return -ENOSPC;          
1024                                                  
1025                 *((__be16 *)&net_cat[cat_iter    
1026                 cat_iter += 2;                   
1027         }                                        
1028                                                  
1029         return cat_iter;                         
1030 }                                                
1031                                                  
1032 /**                                              
1033  * cipso_v4_map_cat_enum_ntoh - Perform a cat    
1034  * @doi_def: the DOI definition                  
1035  * @net_cat: the category list in network/CIP    
1036  * @net_cat_len: the length of the CIPSO bitm    
1037  * @secattr: the security attributes             
1038  *                                               
1039  * Description:                                  
1040  * Perform a label mapping to translate a CIP    
1041  * local MLS category bitmap using the given     
1042  * success, negative values on failure.          
1043  *                                               
1044  */                                              
1045 static int cipso_v4_map_cat_enum_ntoh(const s    
1046                                       const u    
1047                                       u32 net    
1048                                       struct     
1049 {                                                
1050         int ret_val;                             
1051         u32 iter;                                
1052                                                  
1053         for (iter = 0; iter < net_cat_len; it    
1054                 ret_val = netlbl_secattr_catm    
1055                                 ntohs(get_una    
1056                                 GFP_ATOMIC);     
1057                 if (ret_val != 0)                
1058                         return ret_val;          
1059         }                                        
1060                                                  
1061         return 0;                                
1062 }                                                
1063                                                  
1064 /**                                              
1065  * cipso_v4_map_cat_rng_valid - Checks to see    
1066  * @doi_def: the DOI definition                  
1067  * @rngcat: category list                        
1068  * @rngcat_len: length of the category list i    
1069  *                                               
1070  * Description:                                  
1071  * Checks the given categories against the gi    
1072  * negative value if any of the categories do    
1073  * zero value if all of the categories are va    
1074  *                                               
1075  */                                              
1076 static int cipso_v4_map_cat_rng_valid(const s    
1077                                       const u    
1078                                       u32 rng    
1079 {                                                
1080         u16 cat_high;                            
1081         u16 cat_low;                             
1082         u32 cat_prev = CIPSO_V4_MAX_REM_CATS     
1083         u32 iter;                                
1084                                                  
1085         if (doi_def->type != CIPSO_V4_MAP_PAS    
1086                 return -EFAULT;                  
1087                                                  
1088         for (iter = 0; iter < rngcat_len; ite    
1089                 cat_high = ntohs(get_unaligne    
1090                 if ((iter + 4) <= rngcat_len)    
1091                         cat_low = ntohs(         
1092                                 get_unaligned    
1093                 else                             
1094                         cat_low = 0;             
1095                                                  
1096                 if (cat_high > cat_prev)         
1097                         return -EFAULT;          
1098                                                  
1099                 cat_prev = cat_low;              
1100         }                                        
1101                                                  
1102         return 0;                                
1103 }                                                
1104                                                  
1105 /**                                              
1106  * cipso_v4_map_cat_rng_hton - Perform a cate    
1107  * @doi_def: the DOI definition                  
1108  * @secattr: the security attributes             
1109  * @net_cat: the zero'd out category list in     
1110  * @net_cat_len: the length of the CIPSO cate    
1111  *                                               
1112  * Description:                                  
1113  * Perform a label mapping to translate a loc    
1114  * correct CIPSO category list using the give    
1115  * size in bytes of the network category bitm    
1116  * otherwise.                                    
1117  *                                               
1118  */                                              
1119 static int cipso_v4_map_cat_rng_hton(const st    
1120                                      const st    
1121                                      unsigned    
1122                                      u32 net_    
1123 {                                                
1124         int iter = -1;                           
1125         u16 array[CIPSO_V4_TAG_RNG_CAT_MAX *     
1126         u32 array_cnt = 0;                       
1127         u32 cat_size = 0;                        
1128                                                  
1129         /* make sure we don't overflow the 'a    
1130         if (net_cat_len >                        
1131             (CIPSO_V4_OPT_LEN_MAX - CIPSO_V4_    
1132                 return -ENOSPC;                  
1133                                                  
1134         for (;;) {                               
1135                 iter = netlbl_secattr_catmap_    
1136                                                  
1137                 if (iter < 0)                    
1138                         break;                   
1139                 cat_size += (iter == 0 ? 0 :     
1140                 if (cat_size > net_cat_len)      
1141                         return -ENOSPC;          
1142                 array[array_cnt++] = iter;       
1143                                                  
1144                 iter = netlbl_secattr_catmap_    
1145                                                  
1146                 if (iter < 0)                    
1147                         return -EFAULT;          
1148                 cat_size += sizeof(u16);         
1149                 if (cat_size > net_cat_len)      
1150                         return -ENOSPC;          
1151                 array[array_cnt++] = iter;       
1152         }                                        
1153                                                  
1154         for (iter = 0; array_cnt > 0;) {         
1155                 *((__be16 *)&net_cat[iter]) =    
1156                 iter += 2;                       
1157                 array_cnt--;                     
1158                 if (array[array_cnt] != 0) {     
1159                         *((__be16 *)&net_cat[    
1160                         iter += 2;               
1161                 }                                
1162         }                                        
1163                                                  
1164         return cat_size;                         
1165 }                                                
1166                                                  
1167 /**                                              
1168  * cipso_v4_map_cat_rng_ntoh - Perform a cate    
1169  * @doi_def: the DOI definition                  
1170  * @net_cat: the category list in network/CIP    
1171  * @net_cat_len: the length of the CIPSO bitm    
1172  * @secattr: the security attributes             
1173  *                                               
1174  * Description:                                  
1175  * Perform a label mapping to translate a CIP    
1176  * local MLS category bitmap using the given     
1177  * success, negative values on failure.          
1178  *                                               
1179  */                                              
1180 static int cipso_v4_map_cat_rng_ntoh(const st    
1181                                      const un    
1182                                      u32 net_    
1183                                      struct n    
1184 {                                                
1185         int ret_val;                             
1186         u32 net_iter;                            
1187         u16 cat_low;                             
1188         u16 cat_high;                            
1189                                                  
1190         for (net_iter = 0; net_iter < net_cat    
1191                 cat_high = ntohs(get_unaligne    
1192                 if ((net_iter + 4) <= net_cat    
1193                         cat_low = ntohs(         
1194                               get_unaligned((    
1195                 else                             
1196                         cat_low = 0;             
1197                                                  
1198                 ret_val = netlbl_secattr_catm    
1199                                                  
1200                                                  
1201                                                  
1202                 if (ret_val != 0)                
1203                         return ret_val;          
1204         }                                        
1205                                                  
1206         return 0;                                
1207 }                                                
1208                                                  
1209 /*                                               
1210  * Protocol Handling Functions                   
1211  */                                              
1212                                                  
1213 /**                                              
1214  * cipso_v4_gentag_hdr - Generate a CIPSO opt    
1215  * @doi_def: the DOI definition                  
1216  * @len: the total tag length in bytes, not i    
1217  * @buf: the CIPSO option buffer                 
1218  *                                               
1219  * Description:                                  
1220  * Write a CIPSO header into the beginning of    
1221  *                                               
1222  */                                              
1223 static void cipso_v4_gentag_hdr(const struct     
1224                                 unsigned char    
1225                                 u32 len)         
1226 {                                                
1227         buf[0] = IPOPT_CIPSO;                    
1228         buf[1] = CIPSO_V4_HDR_LEN + len;         
1229         *(__be32 *)&buf[2] = htonl(doi_def->d    
1230 }                                                
1231                                                  
1232 /**                                              
1233  * cipso_v4_gentag_rbm - Generate a CIPSO res    
1234  * @doi_def: the DOI definition                  
1235  * @secattr: the security attributes             
1236  * @buffer: the option buffer                    
1237  * @buffer_len: length of buffer in bytes        
1238  *                                               
1239  * Description:                                  
1240  * Generate a CIPSO option using the restrict    
1241  * actual buffer length may be larger than th    
1242  * translation between host and network categ    
1243  * the tag on success, negative values on fai    
1244  *                                               
1245  */                                              
1246 static int cipso_v4_gentag_rbm(const struct c    
1247                                const struct n    
1248                                unsigned char     
1249                                u32 buffer_len    
1250 {                                                
1251         int ret_val;                             
1252         u32 tag_len;                             
1253         u32 level;                               
1254                                                  
1255         if ((secattr->flags & NETLBL_SECATTR_    
1256                 return -EPERM;                   
1257                                                  
1258         ret_val = cipso_v4_map_lvl_hton(doi_d    
1259                                         secat    
1260                                         &leve    
1261         if (ret_val != 0)                        
1262                 return ret_val;                  
1263                                                  
1264         if (secattr->flags & NETLBL_SECATTR_M    
1265                 ret_val = cipso_v4_map_cat_rb    
1266                                                  
1267                                                  
1268                                                  
1269                 if (ret_val < 0)                 
1270                         return ret_val;          
1271                                                  
1272                 /* This will send packets usi    
1273                  * possibile as specified in     
1274                  * CIPSO draft. */               
1275                 if (cipso_v4_rbm_optfmt && re    
1276                         tag_len = 14;            
1277                 else                             
1278                         tag_len = 4 + ret_val    
1279         } else                                   
1280                 tag_len = 4;                     
1281                                                  
1282         buffer[0] = 0x01;                        
1283         buffer[1] = tag_len;                     
1284         buffer[3] = level;                       
1285                                                  
1286         return tag_len;                          
1287 }                                                
1288                                                  
1289 /**                                              
1290  * cipso_v4_parsetag_rbm - Parse a CIPSO rest    
1291  * @doi_def: the DOI definition                  
1292  * @tag: the CIPSO tag                           
1293  * @secattr: the security attributes             
1294  *                                               
1295  * Description:                                  
1296  * Parse a CIPSO restricted bitmap tag (tag t    
1297  * attributes in @secattr.  Return zero on su    
1298  * failure.                                      
1299  *                                               
1300  */                                              
1301 static int cipso_v4_parsetag_rbm(const struct    
1302                                  const unsign    
1303                                  struct netlb    
1304 {                                                
1305         int ret_val;                             
1306         u8 tag_len = tag[1];                     
1307         u32 level;                               
1308                                                  
1309         ret_val = cipso_v4_map_lvl_ntoh(doi_d    
1310         if (ret_val != 0)                        
1311                 return ret_val;                  
1312         secattr->attr.mls.lvl = level;           
1313         secattr->flags |= NETLBL_SECATTR_MLS_    
1314                                                  
1315         if (tag_len > 4) {                       
1316                 secattr->attr.mls.cat =          
1317                                        netlbl    
1318                 if (secattr->attr.mls.cat ==     
1319                         return -ENOMEM;          
1320                                                  
1321                 ret_val = cipso_v4_map_cat_rb    
1322                                                  
1323                                                  
1324                                                  
1325                 if (ret_val != 0) {              
1326                         netlbl_secattr_catmap    
1327                         return ret_val;          
1328                 }                                
1329                                                  
1330                 secattr->flags |= NETLBL_SECA    
1331         }                                        
1332                                                  
1333         return 0;                                
1334 }                                                
1335                                                  
1336 /**                                              
1337  * cipso_v4_gentag_enum - Generate a CIPSO en    
1338  * @doi_def: the DOI definition                  
1339  * @secattr: the security attributes             
1340  * @buffer: the option buffer                    
1341  * @buffer_len: length of buffer in bytes        
1342  *                                               
1343  * Description:                                  
1344  * Generate a CIPSO option using the enumerat    
1345  * size of the tag on success, negative value    
1346  *                                               
1347  */                                              
1348 static int cipso_v4_gentag_enum(const struct     
1349                                 const struct     
1350                                 unsigned char    
1351                                 u32 buffer_le    
1352 {                                                
1353         int ret_val;                             
1354         u32 tag_len;                             
1355         u32 level;                               
1356                                                  
1357         if (!(secattr->flags & NETLBL_SECATTR    
1358                 return -EPERM;                   
1359                                                  
1360         ret_val = cipso_v4_map_lvl_hton(doi_d    
1361                                         secat    
1362                                         &leve    
1363         if (ret_val != 0)                        
1364                 return ret_val;                  
1365                                                  
1366         if (secattr->flags & NETLBL_SECATTR_M    
1367                 ret_val = cipso_v4_map_cat_en    
1368                                                  
1369                                                  
1370                                                  
1371                 if (ret_val < 0)                 
1372                         return ret_val;          
1373                                                  
1374                 tag_len = 4 + ret_val;           
1375         } else                                   
1376                 tag_len = 4;                     
1377                                                  
1378         buffer[0] = 0x02;                        
1379         buffer[1] = tag_len;                     
1380         buffer[3] = level;                       
1381                                                  
1382         return tag_len;                          
1383 }                                                
1384                                                  
1385 /**                                              
1386  * cipso_v4_parsetag_enum - Parse a CIPSO enu    
1387  * @doi_def: the DOI definition                  
1388  * @tag: the CIPSO tag                           
1389  * @secattr: the security attributes             
1390  *                                               
1391  * Description:                                  
1392  * Parse a CIPSO enumerated tag (tag type #2)    
1393  * attributes in @secattr.  Return zero on su    
1394  * failure.                                      
1395  *                                               
1396  */                                              
1397 static int cipso_v4_parsetag_enum(const struc    
1398                                   const unsig    
1399                                   struct netl    
1400 {                                                
1401         int ret_val;                             
1402         u8 tag_len = tag[1];                     
1403         u32 level;                               
1404                                                  
1405         ret_val = cipso_v4_map_lvl_ntoh(doi_d    
1406         if (ret_val != 0)                        
1407                 return ret_val;                  
1408         secattr->attr.mls.lvl = level;           
1409         secattr->flags |= NETLBL_SECATTR_MLS_    
1410                                                  
1411         if (tag_len > 4) {                       
1412                 secattr->attr.mls.cat =          
1413                                        netlbl    
1414                 if (secattr->attr.mls.cat ==     
1415                         return -ENOMEM;          
1416                                                  
1417                 ret_val = cipso_v4_map_cat_en    
1418                                                  
1419                                                  
1420                                                  
1421                 if (ret_val != 0) {              
1422                         netlbl_secattr_catmap    
1423                         return ret_val;          
1424                 }                                
1425                                                  
1426                 secattr->flags |= NETLBL_SECA    
1427         }                                        
1428                                                  
1429         return 0;                                
1430 }                                                
1431                                                  
1432 /**                                              
1433  * cipso_v4_gentag_rng - Generate a CIPSO ran    
1434  * @doi_def: the DOI definition                  
1435  * @secattr: the security attributes             
1436  * @buffer: the option buffer                    
1437  * @buffer_len: length of buffer in bytes        
1438  *                                               
1439  * Description:                                  
1440  * Generate a CIPSO option using the ranged t    
1441  * size of the tag on success, negative value    
1442  *                                               
1443  */                                              
1444 static int cipso_v4_gentag_rng(const struct c    
1445                                const struct n    
1446                                unsigned char     
1447                                u32 buffer_len    
1448 {                                                
1449         int ret_val;                             
1450         u32 tag_len;                             
1451         u32 level;                               
1452                                                  
1453         if (!(secattr->flags & NETLBL_SECATTR    
1454                 return -EPERM;                   
1455                                                  
1456         ret_val = cipso_v4_map_lvl_hton(doi_d    
1457                                         secat    
1458                                         &leve    
1459         if (ret_val != 0)                        
1460                 return ret_val;                  
1461                                                  
1462         if (secattr->flags & NETLBL_SECATTR_M    
1463                 ret_val = cipso_v4_map_cat_rn    
1464                                                  
1465                                                  
1466                                                  
1467                 if (ret_val < 0)                 
1468                         return ret_val;          
1469                                                  
1470                 tag_len = 4 + ret_val;           
1471         } else                                   
1472                 tag_len = 4;                     
1473                                                  
1474         buffer[0] = 0x05;                        
1475         buffer[1] = tag_len;                     
1476         buffer[3] = level;                       
1477                                                  
1478         return tag_len;                          
1479 }                                                
1480                                                  
1481 /**                                              
1482  * cipso_v4_parsetag_rng - Parse a CIPSO rang    
1483  * @doi_def: the DOI definition                  
1484  * @tag: the CIPSO tag                           
1485  * @secattr: the security attributes             
1486  *                                               
1487  * Description:                                  
1488  * Parse a CIPSO ranged tag (tag type #5) and    
1489  * in @secattr.  Return zero on success, nega    
1490  *                                               
1491  */                                              
1492 static int cipso_v4_parsetag_rng(const struct    
1493                                  const unsign    
1494                                  struct netlb    
1495 {                                                
1496         int ret_val;                             
1497         u8 tag_len = tag[1];                     
1498         u32 level;                               
1499                                                  
1500         ret_val = cipso_v4_map_lvl_ntoh(doi_d    
1501         if (ret_val != 0)                        
1502                 return ret_val;                  
1503         secattr->attr.mls.lvl = level;           
1504         secattr->flags |= NETLBL_SECATTR_MLS_    
1505                                                  
1506         if (tag_len > 4) {                       
1507                 secattr->attr.mls.cat =          
1508                                        netlbl    
1509                 if (secattr->attr.mls.cat ==     
1510                         return -ENOMEM;          
1511                                                  
1512                 ret_val = cipso_v4_map_cat_rn    
1513                                                  
1514                                                  
1515                                                  
1516                 if (ret_val != 0) {              
1517                         netlbl_secattr_catmap    
1518                         return ret_val;          
1519                 }                                
1520                                                  
1521                 secattr->flags |= NETLBL_SECA    
1522         }                                        
1523                                                  
1524         return 0;                                
1525 }                                                
1526                                                  
1527 /**                                              
1528  * cipso_v4_validate - Validate a CIPSO optio    
1529  * @option: the start of the option, on error    
1530  *                                               
1531  * Description:                                  
1532  * This routine is called to validate a CIPSO    
1533  * fields to ensure that they are at least va    
1534  * for details.  If the option is valid then     
1535  * the value of @option is unchanged.  If the    
1536  * non-zero value is returned and @option is     
1537  * offending portion of the option.  From the    
1538  *                                               
1539  *  "If any field within the CIPSO options, s    
1540  *   recognized the IP datagram is discarded     
1541  *   (type 12) is generated and returned.  Th    
1542  *   parameter' (code 0) and the pointer is s    
1543  *   that is unrecognized."                      
1544  *                                               
1545  */                                              
1546 int cipso_v4_validate(unsigned char **option)    
1547 {                                                
1548         unsigned char *opt = *option;            
1549         unsigned char *tag;                      
1550         unsigned char opt_iter;                  
1551         unsigned char err_offset = 0;            
1552         u8 opt_len;                              
1553         u8 tag_len;                              
1554         struct cipso_v4_doi *doi_def = NULL;     
1555         u32 tag_iter;                            
1556                                                  
1557         /* caller already checks for length v    
1558         opt_len = opt[1];                        
1559         if (opt_len < 8) {                       
1560                 err_offset = 1;                  
1561                 goto validate_return;            
1562         }                                        
1563                                                  
1564         rcu_read_lock();                         
1565         doi_def = cipso_v4_doi_search(ntohl(g    
1566         if (doi_def == NULL) {                   
1567                 err_offset = 2;                  
1568                 goto validate_return_locked;     
1569         }                                        
1570                                                  
1571         opt_iter = 6;                            
1572         tag = opt + opt_iter;                    
1573         while (opt_iter < opt_len) {             
1574                 for (tag_iter = 0; doi_def->t    
1575                         if (doi_def->tags[tag    
1576                             ++tag_iter == CIP    
1577                                 err_offset =     
1578                                 goto validate    
1579                         }                        
1580                                                  
1581                 tag_len = tag[1];                
1582                 if (tag_len > (opt_len - opt_    
1583                         err_offset = opt_iter    
1584                         goto validate_return_    
1585                 }                                
1586                                                  
1587                 switch (tag[0]) {                
1588                 case CIPSO_V4_TAG_RBITMAP:       
1589                         if (tag_len < 4) {       
1590                                 err_offset =     
1591                                 goto validate    
1592                         }                        
1593                                                  
1594                         /* We are already goi    
1595                          * necessary at the s    
1596                          * view it is safe to    
1597                          * work), however, th    
1598                          * all the CIPSO vali    
1599                          * really specify _ex    
1600                          * ... so, just make     
1601                         if (cipso_v4_rbm_stri    
1602                                 if (cipso_v4_    
1603                                                  
1604                                         err_o    
1605                                         goto     
1606                                 }                
1607                                 if (tag_len >    
1608                                     cipso_v4_    
1609                                                  
1610                                                  
1611                                         err_o    
1612                                         goto     
1613                                 }                
1614                         }                        
1615                         break;                   
1616                 case CIPSO_V4_TAG_ENUM:          
1617                         if (tag_len < 4) {       
1618                                 err_offset =     
1619                                 goto validate    
1620                         }                        
1621                                                  
1622                         if (cipso_v4_map_lvl_    
1623                                                  
1624                                 err_offset =     
1625                                 goto validate    
1626                         }                        
1627                         if (tag_len > 4 &&       
1628                             cipso_v4_map_cat_    
1629                                                  
1630                                                  
1631                                 err_offset =     
1632                                 goto validate    
1633                         }                        
1634                         break;                   
1635                 case CIPSO_V4_TAG_RANGE:         
1636                         if (tag_len < 4) {       
1637                                 err_offset =     
1638                                 goto validate    
1639                         }                        
1640                                                  
1641                         if (cipso_v4_map_lvl_    
1642                                                  
1643                                 err_offset =     
1644                                 goto validate    
1645                         }                        
1646                         if (tag_len > 4 &&       
1647                             cipso_v4_map_cat_    
1648                                                  
1649                                                  
1650                                 err_offset =     
1651                                 goto validate    
1652                         }                        
1653                         break;                   
1654                 default:                         
1655                         err_offset = opt_iter    
1656                         goto validate_return_    
1657                 }                                
1658                                                  
1659                 tag += tag_len;                  
1660                 opt_iter += tag_len;             
1661         }                                        
1662                                                  
1663 validate_return_locked:                          
1664         rcu_read_unlock();                       
1665 validate_return:                                 
1666         *option = opt + err_offset;              
1667         return err_offset;                       
1668 }                                                
1669                                                  
1670 /**                                              
1671  * cipso_v4_error - Send the correct reponse     
1672  * @skb: the packet                              
1673  * @error: the error code                        
1674  * @gateway: CIPSO gateway flag                  
1675  *                                               
1676  * Description:                                  
1677  * Based on the error code given in @error, s    
1678  * the originating host.  From the IETF draft    
1679  *                                               
1680  *  "If the contents of the CIPSO [option] ar    
1681  *   outside of the configured host or port l    
1682  *   discarded and an ICMP 'destination unrea    
1683  *   returned.  The code field of the ICMP is    
1684  *   destination network administratively pro    
1685  *   'communication with destination host adm    
1686  *   (code 10).  The value of the code is dep    
1687  *   of the ICMP message is acting as a CIPSO    
1688  *   recipient of the ICMP message MUST be ab    
1689  *   same procedure is performed if a CIPSO [    
1690  *   IP packet because it is too large to fit    
1691  *                                               
1692  *  "If the error is triggered by receipt of     
1693  *   discarded and no response is permitted (    
1694  *   processing rules)."                         
1695  *                                               
1696  */                                              
1697 void cipso_v4_error(struct sk_buff *skb, int     
1698 {                                                
1699         if (ip_hdr(skb)->protocol == IPPROTO_    
1700                 return;                          
1701                                                  
1702         if (gateway)                             
1703                 icmp_send(skb, ICMP_DEST_UNRE    
1704         else                                     
1705                 icmp_send(skb, ICMP_DEST_UNRE    
1706 }                                                
1707                                                  
1708 /**                                              
1709  * cipso_v4_sock_setattr - Add a CIPSO option    
1710  * @sk: the socket                               
1711  * @doi_def: the CIPSO DOI to use                
1712  * @secattr: the specific security attributes    
1713  *                                               
1714  * Description:                                  
1715  * Set the CIPSO option on the given socket u    
1716  * security attributes passed to the function    
1717  * exclusive access to @sk, which means it ei    
1718  * process of being created or locked.  Retur    
1719  * values on failure.                            
1720  *                                               
1721  */                                              
1722 int cipso_v4_sock_setattr(struct sock *sk,       
1723                           const struct cipso_    
1724                           const struct netlbl    
1725 {                                                
1726         int ret_val = -EPERM;                    
1727         u32 iter;                                
1728         unsigned char *buf;                      
1729         u32 buf_len = 0;                         
1730         u32 opt_len;                             
1731         struct ip_options *opt = NULL;           
1732         struct inet_sock *sk_inet;               
1733         struct inet_connection_sock *sk_conn;    
1734                                                  
1735         /* In the case of sock_create_lite(),    
1736          * defined yet but it is not a proble    
1737          * "lite" PF_INET sockets are functio    
1738          * afterwards so we will label the so    
1739         if (sk == NULL)                          
1740                 return 0;                        
1741                                                  
1742         /* We allocate the maximum CIPSO opti    
1743          * being a little wasteful, but it ma    
1744          * on and after all we are only talki    
1745         buf_len = CIPSO_V4_OPT_LEN_MAX;          
1746         buf = kmalloc(buf_len, GFP_ATOMIC);      
1747         if (buf == NULL) {                       
1748                 ret_val = -ENOMEM;               
1749                 goto socket_setattr_failure;     
1750         }                                        
1751                                                  
1752         /* XXX - This code assumes only one t    
1753          * really a good assumption to make b    
1754          * tags right now it is a safe assump    
1755         iter = 0;                                
1756         do {                                     
1757                 memset(buf, 0, buf_len);         
1758                 switch (doi_def->tags[iter])     
1759                 case CIPSO_V4_TAG_RBITMAP:       
1760                         ret_val = cipso_v4_ge    
1761                                                  
1762                                                  
1763                                                  
1764                         break;                   
1765                 case CIPSO_V4_TAG_ENUM:          
1766                         ret_val = cipso_v4_ge    
1767                                                  
1768                                                  
1769                                                  
1770                         break;                   
1771                 case CIPSO_V4_TAG_RANGE:         
1772                         ret_val = cipso_v4_ge    
1773                                                  
1774                                                  
1775                                                  
1776                         break;                   
1777                 default:                         
1778                         ret_val = -EPERM;        
1779                         goto socket_setattr_f    
1780                 }                                
1781                                                  
1782                 iter++;                          
1783         } while (ret_val < 0 &&                  
1784                  iter < CIPSO_V4_TAG_MAXCNT &    
1785                  doi_def->tags[iter] != CIPSO    
1786         if (ret_val < 0)                         
1787                 goto socket_setattr_failure;     
1788         cipso_v4_gentag_hdr(doi_def, buf, ret    
1789         buf_len = CIPSO_V4_HDR_LEN + ret_val;    
1790                                                  
1791         /* We can't use ip_options_get() dire    
1792          * ip_options_get_alloc() which alloc    
1793          * we won't always have CAP_NET_RAW e    
1794          * set the IPOPT_CIPSO option. */        
1795         opt_len = (buf_len + 3) & ~3;            
1796         opt = kzalloc(sizeof(*opt) + opt_len,    
1797         if (opt == NULL) {                       
1798                 ret_val = -ENOMEM;               
1799                 goto socket_setattr_failure;     
1800         }                                        
1801         memcpy(opt->__data, buf, buf_len);       
1802         opt->optlen = opt_len;                   
1803         opt->is_data = 1;                        
1804         opt->cipso = sizeof(struct iphdr);       
1805         kfree(buf);                              
1806         buf = NULL;                              
1807                                                  
1808         sk_inet = inet_sk(sk);                   
1809         if (sk_inet->is_icsk) {                  
1810                 sk_conn = inet_csk(sk);          
1811                 if (sk_inet->opt)                
1812                         sk_conn->icsk_ext_hdr    
1813                 sk_conn->icsk_ext_hdr_len +=     
1814                 sk_conn->icsk_sync_mss(sk, sk    
1815         }                                        
1816         opt = xchg(&sk_inet->opt, opt);          
1817         kfree(opt);                              
1818                                                  
1819         return 0;                                
1820                                                  
1821 socket_setattr_failure:                          
1822         kfree(buf);                              
1823         kfree(opt);                              
1824         return ret_val;                          
1825 }                                                
1826                                                  
1827 /**                                              
1828  * cipso_v4_getattr - Helper function for the    
1829  * @cipso: the CIPSO v4 option                   
1830  * @secattr: the security attributes             
1831  *                                               
1832  * Description:                                  
1833  * Inspect @cipso and return the security att    
1834  * on success and negative values on failure.    
1835  *                                               
1836  */                                              
1837 static int cipso_v4_getattr(const unsigned ch    
1838                             struct netlbl_lsm    
1839 {                                                
1840         int ret_val = -ENOMSG;                   
1841         u32 doi;                                 
1842         struct cipso_v4_doi *doi_def;            
1843                                                  
1844         if (cipso_v4_cache_check(cipso, cipso    
1845                 return 0;                        
1846                                                  
1847         doi = ntohl(get_unaligned((__be32 *)&    
1848         rcu_read_lock();                         
1849         doi_def = cipso_v4_doi_search(doi);      
1850         if (doi_def == NULL)                     
1851                 goto getattr_return;             
1852         /* XXX - This code assumes only one t    
1853          * really a good assumption to make b    
1854          * tags right now it is a safe assump    
1855         switch (cipso[6]) {                      
1856         case CIPSO_V4_TAG_RBITMAP:               
1857                 ret_val = cipso_v4_parsetag_r    
1858                 break;                           
1859         case CIPSO_V4_TAG_ENUM:                  
1860                 ret_val = cipso_v4_parsetag_e    
1861                 break;                           
1862         case CIPSO_V4_TAG_RANGE:                 
1863                 ret_val = cipso_v4_parsetag_r    
1864                 break;                           
1865         }                                        
1866         if (ret_val == 0)                        
1867                 secattr->type = NETLBL_NLTYPE    
1868                                                  
1869 getattr_return:                                  
1870         rcu_read_unlock();                       
1871         return ret_val;                          
1872 }                                                
1873                                                  
1874 /**                                              
1875  * cipso_v4_sock_getattr - Get the security a    
1876  * @sk: the sock                                 
1877  * @secattr: the security attributes             
1878  *                                               
1879  * Description:                                  
1880  * Query @sk to see if there is a CIPSO optio    
1881  * there is return the CIPSO security attribu    
1882  * requires that @sk be locked, or privately     
1883  * locking itself.  Returns zero on success a    
1884  *                                               
1885  */                                              
1886 int cipso_v4_sock_getattr(struct sock *sk, st    
1887 {                                                
1888         struct ip_options *opt;                  
1889                                                  
1890         opt = inet_sk(sk)->opt;                  
1891         if (opt == NULL || opt->cipso == 0)      
1892                 return -ENOMSG;                  
1893                                                  
1894         return cipso_v4_getattr(opt->__data +    
1895                                 secattr);        
1896 }                                                
1897                                                  
1898 /**                                              
1899  * cipso_v4_skbuff_getattr - Get the security    
1900  * @skb: the packet                              
1901  * @secattr: the security attributes             
1902  *                                               
1903  * Description:                                  
1904  * Parse the given packet's CIPSO option and     
1905  * Returns zero on success and negative value    
1906  *                                               
1907  */                                              
1908 int cipso_v4_skbuff_getattr(const struct sk_b    
1909                             struct netlbl_lsm    
1910 {                                                
1911         return cipso_v4_getattr(CIPSO_V4_OPTP    
1912 }                                                
1913                                                  
1914 /*                                               
1915  * Setup Functions                               
1916  */                                              
1917                                                  
1918 /**                                              
1919  * cipso_v4_init - Initialize the CIPSO modul    
1920  *                                               
1921  * Description:                                  
1922  * Initialize the CIPSO module and prepare it    
1923  * and negative values on failure.               
1924  *                                               
1925  */                                              
1926 static int __init cipso_v4_init(void)            
1927 {                                                
1928         int ret_val;                             
1929                                                  
1930         ret_val = cipso_v4_cache_init();         
1931         if (ret_val != 0)                        
1932                 panic("Failed to initialize t    
1933                       ret_val);                  
1934                                                  
1935         return 0;                                
1936 }                                                
1937                                                  
1938 subsys_initcall(cipso_v4_init);                  
1939                                                  
  This page was automatically generated by the LXR engine.