gen_lists.c

Go to the documentation of this file.
00001 /************************************* */
00002 /* Rule Set Based Access Control       */
00003 /* Author and (c) 1999-2005:           */
00004 /*   Amon Ott <ao@rsbac.org>           */
00005 /* Generic lists for all parts         */
00006 /* Last modified: 01/Apr/2005          */
00007 /************************************* */
00008 
00009 #include <linux/sched.h>
00010 #include <linux/smp_lock.h>
00011 #include <linux/module.h>
00012 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
00013 #include <linux/random.h>
00014 #endif
00015 #include <asm/uaccess.h>
00016 #include <rsbac/types.h>
00017 #include <rsbac/error.h>
00018 #include <rsbac/helpers.h>
00019 #include <rsbac/getname.h>
00020 #include <rsbac/debug.h>
00021 #include <rsbac/adf.h>
00022 #include <rsbac/aci_data_structures.h>
00023 #include <rsbac/proc_fs.h>
00024 #include <rsbac/rkmem.h>
00025 #include <rsbac/lists.h>
00026 #include <rsbac/gen_lists.h>
00027 
00028 /********************/
00029 /* Global Variables */
00030 /********************/
00031 
00032 static struct rsbac_list_reg_head_t       reg_head;
00033 static struct rsbac_list_lol_reg_head_t   lol_reg_head;
00034 static        rsbac_boolean_t             list_initialized = FALSE;
00035 
00036 #ifdef CONFIG_RSBAC_LIST_TRANS
00037 static struct rsbac_list_reg_item_t     * ta_handle = NULL;
00038 static        spinlock_t                  ta_lock = SPIN_LOCK_UNLOCKED;
00039 static        rsbac_boolean_t             ta_committing = FALSE;
00040 static        rsbac_boolean_t             ta_forgetting = FALSE;
00041 #ifndef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
00042               rsbac_list_ta_number_t      ta_next = 1;
00043 #endif
00044 #endif
00045 
00046 #ifdef CONFIG_RSBAC_LIST_TRANS
00047 static int do_forget(rsbac_list_ta_number_t ta_number);
00048 #endif
00049 
00050 #ifdef CONFIG_RSBAC_LIST_REPL
00051 static struct rsbac_nanotime_t repl_last;
00052 static struct rsbac_list_reg_item_t * repl_partner_handle = NULL;
00053 #endif
00054 
00055 
00056 /*********************************/
00057 /* Data Structures               */
00058 /*********************************/
00059 
00060 static struct rsbac_list_item_t * lookup_item_compare(
00061     struct rsbac_list_reg_item_t * list,
00062     void * desc)
00063     {
00064       struct rsbac_list_item_t  * curr;
00065 
00066       if(!list || !desc || !list->compare)
00067         return NULL;
00068 
00069       curr = list->curr;
00070       if(!curr)
00071         {
00072           curr = list->head;
00073           if(!curr)
00074             return NULL;
00075         }
00076       /* if current item is not the right one, search... */
00077       /* note: item desc is behind official struct */
00078       if(list->compare(desc, &curr[1]))
00079         {
00080           if((list->compare(desc, &curr[1]) > 0))
00081             {
00082               curr = curr->next;
00083               while (   curr
00084                      && (list->compare(desc, &curr[1]) > 0)
00085                     )
00086                 curr = curr->next;
00087             }
00088           else
00089             {
00090               curr = curr->prev;
00091               while (   curr
00092                      && (list->compare(desc, &curr[1]) < 0)
00093                     )
00094                 curr = curr->prev;
00095             }
00096           if (curr)
00097             {
00098               /* keep for speedup */
00099               list->curr = curr;
00100               if(!list->compare(desc, &curr[1]))
00101                 return curr;
00102             }
00103           /* NULL or not found */
00104           return NULL;
00105         }
00106       /* it is the current item -> return it */
00107       return curr;
00108     }
00109 
00110 static struct rsbac_list_item_t * lookup_item_memcmp(
00111     struct rsbac_list_reg_item_t * list,
00112     void * desc)
00113     {
00114       struct rsbac_list_item_t  * curr;
00115 
00116       if(!list || !desc)
00117         return NULL;
00118 
00119       curr = list->curr;
00120       if(!curr)
00121         {
00122           curr = list->head;
00123           if(!curr)
00124             return NULL;
00125         }
00126       /* if current item is not the right one, search... */
00127       /* note: item desc is behind official struct */
00128       if(memcmp(desc,
00129                 &curr[1],
00130                 list->info.desc_size))
00131         {
00132           if(memcmp(desc,
00133                     &curr[1],
00134                     list->info.desc_size) > 0)
00135             {
00136               curr = curr->next;
00137               while (   curr
00138                      && (memcmp(desc,
00139                                 &curr[1],
00140                                 list->info.desc_size) > 0)
00141                     )
00142                 curr = curr->next;
00143             }
00144           else
00145             {
00146               curr = curr->prev;
00147               while (   curr
00148                      && (memcmp(desc,
00149                                 &curr[1],
00150                                 list->info.desc_size) < 0)
00151                     )
00152                 curr = curr->prev;
00153             }
00154           if (curr)
00155             {
00156               /* keep for speedup */
00157               list->curr = curr;
00158               if(!memcmp(desc,
00159                          &curr[1],
00160                          list->info.desc_size))
00161                 return curr;
00162             }
00163           /* not found */
00164           return NULL;
00165         }
00166       /* it is the current item -> return it */
00167       return curr;
00168     }
00169 
00170 static struct rsbac_list_item_t * lookup_item(
00171     struct rsbac_list_reg_item_t * list,
00172     void * desc)
00173     {
00174       if(!list || !desc)
00175         return NULL;
00176 
00177       if(list->compare)
00178         return lookup_item_compare(list, desc);
00179       else
00180         return lookup_item_memcmp(list, desc);
00181     }
00182 
00183 #ifdef CONFIG_RSBAC_LIST_TRANS
00184 static struct rsbac_list_item_t * ta_lookup_item_compare(
00185     struct rsbac_list_reg_item_t * list,
00186     void * desc)
00187     {
00188       struct rsbac_list_item_t  * curr;
00189 
00190       if(!list || !desc || !list->compare)
00191         return NULL;
00192 
00193       curr = list->ta_curr;
00194       if(!curr)
00195         {
00196           curr = list->ta_head;
00197           if(!curr)
00198             return NULL;
00199         }
00200       /* if current item is not the right one, search... */
00201       /* note: item desc is behind official struct */
00202       if(list->compare(desc, &curr[1]))
00203         {
00204           if((list->compare(desc, &curr[1]) > 0))
00205             {
00206               curr = curr->next;
00207               while (   curr
00208                      && (list->compare(desc, &curr[1]) > 0)
00209                     )
00210                 curr = curr->next;
00211             }
00212           else
00213             {
00214               curr = curr->prev;
00215               while (   curr
00216                      && (list->compare(desc, &curr[1]) < 0)
00217                     )
00218                 curr = curr->prev;
00219             }
00220           if(curr)
00221             {
00222               /* keep for speedup */
00223               list->ta_curr = curr;
00224               if(!list->compare(desc, &curr[1]))
00225                 return curr;
00226             }
00227           /* NULL or not found */
00228           return NULL;
00229         }
00230       /* it is the current item -> return it */
00231       return curr;
00232     }
00233 
00234 static struct rsbac_list_item_t * ta_lookup_item_memcmp(
00235     struct rsbac_list_reg_item_t * list,
00236     void * desc)
00237     {
00238       struct rsbac_list_item_t  * curr;
00239 
00240       if(!list || !desc)
00241         return NULL;
00242 
00243       curr = list->ta_curr;
00244       if(!curr)
00245         {
00246           curr = list->ta_head;
00247           if(!curr)
00248             return NULL;
00249         }
00250       /* if current item is not the right one, search... */
00251       /* note: item desc is behind official struct */
00252       if(memcmp(desc,
00253                 &curr[1],
00254                 list->info.desc_size))
00255         {
00256           if(memcmp(desc,
00257                     &curr[1],
00258                     list->info.desc_size) > 0)
00259             {
00260               curr = curr->next;
00261               while (   curr
00262                      && (memcmp(desc,
00263                                 &curr[1],
00264                                 list->info.desc_size) > 0)
00265                     )
00266                 curr = curr->next;
00267             }
00268           else
00269             {
00270               curr = curr->prev;
00271               while (   curr
00272                      && (memcmp(desc,
00273                                 &curr[1],
00274                                 list->info.desc_size) < 0)
00275                     )
00276                 curr = curr->prev;
00277             }
00278           if (curr)
00279             {
00280               /* keep for speedup */
00281               list->ta_curr = curr;
00282               if(!memcmp(desc,
00283                          &curr[1],
00284                          list->info.desc_size))
00285                 return curr;
00286             }
00287           /* not found */
00288           return NULL;
00289         }
00290       /* it is the current item -> return it */
00291       return curr;
00292     }
00293 
00294 static struct rsbac_list_item_t * ta_lookup_item(
00295     rsbac_list_ta_number_t ta_number,
00296     struct rsbac_list_reg_item_t * list,
00297     void * desc)
00298     {
00299       if(!list || !desc)
00300         return NULL;
00301 
00302       if(!list->ta_copied)
00303         return lookup_item(list, desc);
00304       if(list->ta_copied != ta_number)
00305         return NULL;
00306 
00307       if(list->compare)
00308         return ta_lookup_item_compare(list, desc);
00309       else
00310         return ta_lookup_item_memcmp(list, desc);
00311     }
00312 #endif
00313 
00314 static struct rsbac_list_item_t * lookup_item_data_compare(
00315     struct rsbac_list_reg_item_t * list,
00316     void * data,
00317     rsbac_list_data_compare_function_t compare)
00318     {
00319       struct rsbac_list_item_t  * curr;
00320 
00321       if(!list || !data || !compare)
00322         return NULL;
00323 
00324       curr = list->head;
00325 
00326       /* note: item desc is behind official struct */
00327       while (   curr
00328              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00329                  || compare((char *)curr + sizeof(*curr) + list->info.desc_size, data)
00330                 )
00331             )
00332         curr = curr->next;
00333       /* it is the current item -> return it */
00334       return curr;
00335     }
00336 
00337 static struct rsbac_list_item_t * lookup_item_data_memcmp(
00338     struct rsbac_list_reg_item_t * list,
00339     void * data)
00340     {
00341       struct rsbac_list_item_t  * curr;
00342 
00343       if(!list || !data)
00344         return NULL;
00345 
00346       curr = list->head;
00347 
00348       /* note: item desc is behind official struct */
00349       while (   curr
00350              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00351                  || memcmp(data,
00352                            &curr[1] + list->info.desc_size,
00353                            list->info.data_size)
00354                 )
00355             )
00356         curr = curr->next;
00357       /* it is the current item -> return it */
00358       return curr;
00359     }
00360 
00361 static struct rsbac_list_item_t * lookup_item_data(
00362     struct rsbac_list_reg_item_t * list,
00363     void * data,
00364     rsbac_list_data_compare_function_t compare)
00365     {
00366       if(!list || !data)
00367         return NULL;
00368 
00369       if(compare)
00370         return lookup_item_data_compare(list, data, compare);
00371       else
00372         return lookup_item_data_memcmp(list, data);
00373     }
00374 
00375 #ifdef CONFIG_RSBAC_LIST_TRANS
00376 static struct rsbac_list_item_t * ta_lookup_item_data_compare(
00377     struct rsbac_list_reg_item_t * list,
00378     void * data,
00379     rsbac_list_data_compare_function_t compare)
00380     {
00381       struct rsbac_list_item_t  * curr;
00382 
00383       if(!list || !data || !compare)
00384         return NULL;
00385 
00386       curr = list->ta_head;
00387 
00388       /* note: item desc is behind official struct */
00389       while (   curr
00390              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00391                  || compare((char *)curr + sizeof(*curr) + list->info.desc_size, data)
00392                 )
00393             )
00394         curr = curr->next;
00395       /* it is the current item -> return it */
00396       return curr;
00397     }
00398 
00399 static struct rsbac_list_item_t * ta_lookup_item_data_memcmp(
00400     struct rsbac_list_reg_item_t * list,
00401     void * data)
00402     {
00403       struct rsbac_list_item_t  * curr;
00404 
00405       if(!list || !data)
00406         return NULL;
00407 
00408       curr = list->ta_head;
00409 
00410       /* note: item desc is behind official struct */
00411       while (   curr
00412              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00413                  || memcmp(data,
00414                            &curr[1] + list->info.desc_size,
00415                            list->info.data_size)
00416                 )
00417             )
00418         curr = curr->next;
00419       /* it is the current item -> return it */
00420       return curr;
00421     }
00422 
00423 static struct rsbac_list_item_t * ta_lookup_item_data(
00424     rsbac_list_ta_number_t ta_number,
00425     struct rsbac_list_reg_item_t * list,
00426     void * data,
00427     rsbac_list_data_compare_function_t compare)
00428     {
00429       if(!list || !data)
00430         return NULL;
00431 
00432       if(!list->ta_copied || list->ta_copied != ta_number)
00433         return lookup_item_data(list, data, compare);
00434 
00435       if(compare)
00436         return ta_lookup_item_data_compare(list, data, compare);
00437       else
00438         return ta_lookup_item_data_memcmp(list, data);
00439     }
00440 #endif
00441 
00442 /* list of lists - subitems */
00443 
00444 static struct rsbac_list_item_t * lookup_lol_subitem_compare(
00445     struct rsbac_list_lol_reg_item_t * list,
00446     struct rsbac_list_lol_item_t * sublist,
00447     void * subdesc,
00448     rsbac_list_compare_function_t compare)
00449     {
00450       struct rsbac_list_item_t  * curr;
00451 
00452       if(!list || !sublist || !subdesc || !compare)
00453         return NULL;
00454 
00455       curr = sublist->curr;
00456       if(!curr)
00457         {
00458           curr = sublist->head;
00459           if(!curr)
00460             return NULL;
00461         }
00462       /* if current item is not the right one, search... */
00463       /* note: item desc is behind official struct */
00464       if(compare(&curr[1],subdesc))
00465         {
00466           if((compare(&curr[1], subdesc) < 0))
00467             {
00468               curr = curr->next;
00469               while (   curr
00470                      && (compare(&curr[1], subdesc) < 0)
00471                     )
00472                 curr = curr->next;
00473             }
00474           else
00475             {
00476               curr = curr->prev;
00477               while (   curr
00478                      && (compare(&curr[1], subdesc) > 0)
00479                     )
00480                 curr = curr->prev;
00481             }
00482           if (curr)
00483             {
00484               /* keep for speedup */
00485               sublist->curr = curr;
00486               if(!compare(&curr[1], subdesc))
00487                 return curr;
00488             }
00489           /* not found */
00490           return NULL;
00491         }
00492       /* it is the current item -> return it */
00493       return curr;
00494     }
00495 
00496 static struct rsbac_list_item_t * lookup_lol_subitem_memcmp(
00497     struct rsbac_list_lol_reg_item_t * list,
00498     struct rsbac_list_lol_item_t * sublist,
00499     void * subdesc)
00500     {
00501       struct rsbac_list_item_t  * curr;
00502 
00503       if(!list || !sublist || !subdesc)
00504         return NULL;
00505 
00506       curr = sublist->curr;
00507       if(!curr)
00508         {
00509           curr = sublist->head;
00510           if(!curr)
00511             return NULL;
00512         }
00513       /* if current item is not the right one, search... */
00514       /* note: item desc is behind official struct */
00515       if(memcmp(subdesc,
00516                 &curr[1],
00517                 list->info.subdesc_size))
00518         {
00519           if(memcmp(subdesc,
00520                     &curr[1],
00521                     list->info.subdesc_size) > 0)
00522             {
00523               curr = curr->next;
00524               while (   curr
00525                      && (memcmp(subdesc,
00526                                 &curr[1],
00527                                 list->info.subdesc_size) > 0)
00528                     )
00529                 curr = curr->next;
00530             }
00531           else
00532             {
00533               curr = curr->prev;
00534               while (   curr
00535                      && (memcmp(subdesc,
00536                                 &curr[1],
00537                                 list->info.subdesc_size) < 0)
00538                     )
00539                 curr = curr->prev;
00540             }
00541           if (curr)
00542             {
00543               /* keep for speedup */
00544               sublist->curr = curr;
00545               if(!memcmp(subdesc,
00546                          &curr[1],
00547                          list->info.subdesc_size))
00548                 return curr;
00549             }
00550           /* not found */
00551           return NULL;
00552         }
00553       /* it is the current item -> return it */
00554       return curr;
00555     }
00556 
00557 static struct rsbac_list_item_t * lookup_lol_subitem(
00558     struct rsbac_list_lol_reg_item_t * list,
00559     struct rsbac_list_lol_item_t * sublist,
00560     void * subdesc)
00561     {
00562       if(!list || !sublist || !subdesc)
00563         return NULL;
00564 
00565       if(list->subcompare)
00566         return lookup_lol_subitem_compare(list, sublist, subdesc, list->subcompare);
00567       else
00568         return lookup_lol_subitem_memcmp(list, sublist, subdesc);
00569     }
00570 
00571 static struct rsbac_list_item_t * lookup_lol_subitem_user_compare(
00572     struct rsbac_list_lol_reg_item_t * list,
00573     struct rsbac_list_lol_item_t * sublist,
00574     void * subdesc,
00575     rsbac_list_compare_function_t compare)
00576     {
00577       struct rsbac_list_item_t  * curr;
00578 
00579       if(!list || !sublist || !subdesc || !compare)
00580         return NULL;
00581 
00582       curr = sublist->head;
00583       /* note: item desc is behind official struct */
00584       while(curr)
00585         {
00586           if(!compare(&curr[1],subdesc))
00587             return curr;
00588           curr = curr->next;
00589         }
00590       return curr;
00591     }
00592 
00593 /* list of lists - items */
00594 
00595 static struct rsbac_list_lol_item_t * lookup_lol_item_compare(
00596     struct rsbac_list_lol_reg_item_t * list,
00597     void * desc)
00598     {
00599       struct rsbac_list_lol_item_t  * curr;
00600 
00601       if(!list || !desc || !list->compare)
00602         return NULL;
00603 
00604       curr = list->curr;
00605       if(!curr)
00606         {
00607           curr = list->head;
00608           if(!curr)
00609             return NULL;
00610         }
00611       /* if current item is not the right one, search... */
00612       /* note: item desc is behind official struct */
00613       if(list->compare(desc, &curr[1]))
00614         {
00615           if((list->compare(desc, &curr[1]) > 0))
00616             {
00617               curr = curr->next;
00618               while (   curr
00619                      && (list->compare(desc, &curr[1]) > 0)
00620                     )
00621                 curr = curr->next;
00622             }
00623           else
00624             {
00625               curr = curr->prev;
00626               while (   curr
00627                      && (list->compare(desc, &curr[1]) < 0)
00628                     )
00629                 curr = curr->prev;
00630             }
00631           if (curr)
00632             {
00633               /* keep for speedup */
00634               list->curr = curr;
00635               if(!list->compare(desc, &curr[1]))
00636                 return curr;
00637             }
00638           /* not found */
00639           return NULL;
00640         }
00641       /* it is the current item -> return it */
00642       return curr;
00643     }
00644 
00645 static struct rsbac_list_lol_item_t * lookup_lol_item_memcmp(
00646     struct rsbac_list_lol_reg_item_t * list,
00647     void * desc)
00648     {
00649       struct rsbac_list_lol_item_t  * curr;
00650 
00651       if(!list || !desc)
00652         return NULL;
00653 
00654       curr = list->curr;
00655       if(!curr)
00656         {
00657           curr = list->head;
00658           if(!curr)
00659             return NULL;
00660         }
00661       /* if current item is not the right one, search... */
00662       /* note: item desc is behind official struct */
00663       if(memcmp(desc,
00664                 &curr[1],
00665                 list->info.desc_size))
00666         {
00667           if(memcmp(desc,
00668                     &curr[1],
00669                     list->info.desc_size) > 0)
00670             {
00671               curr = curr->next;
00672               while (   curr
00673                      && (memcmp(desc,
00674                                 &curr[1],
00675                                 list->info.desc_size) > 0)
00676                     )
00677                 curr = curr->next;
00678             }
00679           else
00680             {
00681               curr = curr->prev;
00682               while (   curr
00683                      && (memcmp(desc,
00684                                 &curr[1],
00685                                 list->info.desc_size) < 0)
00686                     )
00687                 curr = curr->prev;
00688             }
00689           if (curr)
00690             {
00691               /* keep for speedup */
00692               list->curr = curr;
00693               if(!memcmp(desc,
00694                          &curr[1],
00695                          list->info.desc_size))
00696                 return curr;
00697             }
00698           /* not found */
00699           return NULL;
00700         }
00701       /* it is the current item -> return it */
00702       return curr;
00703     }
00704 
00705 static struct rsbac_list_lol_item_t * lookup_lol_item(
00706     struct rsbac_list_lol_reg_item_t * list,
00707     void * desc)
00708     {
00709       if(!list || !desc)
00710         return NULL;
00711 
00712       if(list->compare)
00713         return lookup_lol_item_compare(list, desc);
00714       else
00715         return lookup_lol_item_memcmp(list, desc);
00716     }
00717 
00718 #ifdef CONFIG_RSBAC_LIST_TRANS
00719 static struct rsbac_list_lol_item_t * ta_lookup_lol_item_compare(
00720     struct rsbac_list_lol_reg_item_t * list,
00721     void * desc)
00722     {
00723       struct rsbac_list_lol_item_t  * curr;
00724 
00725       if(!list || !desc || !list->compare)
00726         return NULL;
00727 
00728       curr = list->ta_curr;
00729       if(!curr)
00730         {
00731           curr = list->ta_head;
00732           if(!curr)
00733             return NULL;
00734         }
00735       /* if current item is not the right one, search... */
00736       /* note: item desc is behind official struct */
00737       if(list->compare(desc, &curr[1]))
00738         {
00739           if((list->compare(desc, &curr[1]) > 0))
00740             {
00741               curr = curr->next;
00742               while (   curr
00743                      && (list->compare(desc, &curr[1]) > 0)
00744                     )
00745                 curr = curr->next;
00746             }
00747           else
00748             {
00749               curr = curr->prev;
00750               while (   curr
00751                      && (list->compare(desc, &curr[1]) < 0)
00752                     )
00753                 curr = curr->prev;
00754             }
00755           if (curr)
00756             {
00757               /* keep for speedup */
00758               list->ta_curr = curr;
00759               if(!list->compare(desc, &curr[1]))
00760                 return curr;
00761             }
00762           /* not found */
00763           return NULL;
00764         }
00765       /* it is the current item -> return it */
00766       return curr;
00767     }
00768 
00769 static struct rsbac_list_lol_item_t * ta_lookup_lol_item_memcmp(
00770     struct rsbac_list_lol_reg_item_t * list,
00771     void * desc)
00772     {
00773       struct rsbac_list_lol_item_t  * curr;
00774 
00775       if(!list || !desc)
00776         return NULL;
00777 
00778       curr = list->ta_curr;
00779       if(!curr)
00780         {
00781           curr = list->ta_head;
00782           if(!curr)
00783             return NULL;
00784         }
00785       /* if current item is not the right one, search... */
00786       /* note: item desc is behind official struct */
00787       if(memcmp(desc,
00788                 &curr[1],
00789                 list->info.desc_size))
00790         {
00791           if(memcmp(desc,
00792                     &curr[1],
00793                     list->info.desc_size) > 0)
00794             {
00795               curr = curr->next;
00796               while (   curr
00797                      && (memcmp(desc,
00798                                 &curr[1],
00799                                 list->info.desc_size) > 0)
00800                     )
00801                 curr = curr->next;
00802             }
00803           else
00804             {
00805               curr = curr->prev;
00806               while (   curr
00807                      && (memcmp(desc,
00808                                 &curr[1],
00809                                 list->info.desc_size) < 0)
00810                     )
00811                 curr = curr->prev;
00812             }
00813           if (curr)
00814             {
00815               /* keep for speedup */
00816               list->ta_curr = curr;
00817               if(!memcmp(desc,
00818                          &curr[1],
00819                          list->info.desc_size))
00820                 return curr;
00821             }
00822           /* not found */
00823           return NULL;
00824         }
00825       /* it is the current item -> return it */
00826       return curr;
00827     }
00828 
00829 static struct rsbac_list_lol_item_t * ta_lookup_lol_item(
00830     rsbac_list_ta_number_t ta_number,
00831     struct rsbac_list_lol_reg_item_t * list,
00832     void * desc)
00833     {
00834       if(!list || !desc)
00835         return NULL;
00836 
00837       if(!list->ta_copied)
00838         return lookup_lol_item(list, desc);
00839       if(list->ta_copied != ta_number)
00840         return NULL;
00841 
00842       if(list->compare)
00843         return ta_lookup_lol_item_compare(list, desc);
00844       else
00845         return ta_lookup_lol_item_memcmp(list, desc);
00846     }
00847 #endif
00848 
00849 static struct rsbac_list_lol_item_t * lookup_lol_item_data_compare(
00850     struct rsbac_list_lol_reg_item_t * list,
00851     void * data,
00852     rsbac_list_data_compare_function_t compare)
00853     {
00854       struct rsbac_list_lol_item_t  * curr;
00855 
00856       if(!list || !data || !compare)
00857         return NULL;
00858 
00859       curr = list->head;
00860 
00861       /* note: item desc is behind official struct */
00862       while (   curr
00863              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00864                  || compare((char *)curr + sizeof(*curr) + list->info.desc_size, data)
00865                 )
00866             )
00867         curr = curr->next;
00868       /* it is the current item -> return it */
00869       return curr;
00870     }
00871 
00872 static struct rsbac_list_lol_item_t * lookup_lol_item_data_memcmp(
00873     struct rsbac_list_lol_reg_item_t * list,
00874     void * data)
00875     {
00876       struct rsbac_list_lol_item_t  * curr;
00877 
00878       if(!list || !data)
00879         return NULL;
00880 
00881       curr = list->head;
00882 
00883       /* note: item desc is behind official struct */
00884       while (   curr
00885              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00886                  || memcmp(data,
00887                            &curr[1] + list->info.desc_size,
00888                            list->info.data_size)
00889                 )
00890             )
00891         curr = curr->next;
00892       /* it is the current item -> return it */
00893       return curr;
00894     }
00895 
00896 static struct rsbac_list_lol_item_t * lookup_lol_item_data(
00897     struct rsbac_list_lol_reg_item_t * list,
00898     void * data,
00899     rsbac_list_data_compare_function_t compare)
00900     {
00901       if(!list || !data)
00902         return NULL;
00903 
00904       if(compare)
00905         return lookup_lol_item_data_compare(list, data, compare);
00906       else
00907         return lookup_lol_item_data_memcmp(list, data);
00908     }
00909 
00910 #ifdef CONFIG_RSBAC_LIST_TRANS
00911 static struct rsbac_list_lol_item_t * ta_lookup_lol_item_data_compare(
00912     struct rsbac_list_lol_reg_item_t * list,
00913     void * data,
00914     rsbac_list_data_compare_function_t compare)
00915     {
00916       struct rsbac_list_lol_item_t  * curr;
00917 
00918       if(!list || !data || !compare)
00919         return NULL;
00920 
00921       curr = list->ta_head;
00922 
00923       /* note: item desc is behind official struct */
00924       while (   curr
00925              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00926                  || compare((char *)curr + sizeof(*curr) + list->info.desc_size, data)
00927                 )
00928             )
00929         curr = curr->next;
00930       /* it is the current item -> return it */
00931       return curr;
00932     }
00933 
00934 static struct rsbac_list_lol_item_t * ta_lookup_lol_item_data_memcmp(
00935     struct rsbac_list_lol_reg_item_t * list,
00936     void * data)
00937     {
00938       struct rsbac_list_lol_item_t  * curr;
00939 
00940       if(!list || !data)
00941         return NULL;
00942 
00943       curr = list->ta_head;
00944 
00945       /* note: item desc is behind official struct */
00946       while (   curr
00947              && (   (curr->max_age && (curr->max_age <= RSBAC_CURRENT_TIME))
00948                  || memcmp(data,
00949                            &curr[1] + list->info.desc_size,
00950                            list->info.data_size)
00951                 )
00952             )
00953         curr = curr->next;
00954       /* it is the current item -> return it */
00955       return curr;
00956     }
00957 
00958 static struct rsbac_list_lol_item_t * ta_lookup_lol_item_data(
00959     rsbac_list_ta_number_t ta_number,
00960     struct rsbac_list_lol_reg_item_t * list,
00961     void * data,
00962     rsbac_list_data_compare_function_t compare)
00963     {
00964       if(!list || !data)
00965         return NULL;
00966 
00967       if(!list->ta_copied || list->ta_copied != ta_number)
00968         return lookup_lol_item_data(list, data, compare);
00969 
00970       if(compare)
00971         return ta_lookup_lol_item_data_compare(list, data, compare);
00972       else
00973         return ta_lookup_lol_item_data_memcmp(list, data);
00974     }
00975 #endif
00976 
00977 /* Registration lookup */
00978 
00979 static struct rsbac_list_reg_item_t * lookup_reg(struct rsbac_list_reg_item_t *  handle)
00980     {
00981       struct rsbac_list_reg_item_t  * curr = reg_head.curr;
00982       
00983       if(!handle)
00984         return NULL;
00985       /* if there is no current item or it is not the right one, search... */
00986       if(curr != handle)
00987         {
00988           curr = reg_head.head;
00989           while (curr && curr != handle)
00990             curr = curr->next;
00991           if (curr)
00992             reg_head.curr=curr;
00993 #ifdef CONFIG_RSBAC_DEBUG
00994           else
00995             if(rsbac_debug_lists)
00996               {
00997                 rsbac_printk(KERN_DEBUG "lookup_reg(): Lookup of unknown list handle %p\n",
00998                        handle);
00999               }
01000 #endif
01001         }
01002       /* it is the current item -> return it */
01003       return curr;
01004     }
01005 
01006 static struct rsbac_list_reg_item_t * lookup_reg_name(char * name, kdev_t device)
01007     {
01008       struct rsbac_list_reg_item_t  * curr = reg_head.curr;
01009       
01010       if(!name)
01011         return NULL;
01012       /* if there is no current item or it is not the right one, search... */
01013       if(   !curr
01014          || (   strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01015              || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01016              || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01017             )
01018         )
01019         {
01020           curr = reg_head.head;
01021           while (   curr
01022                  && (   strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01023                      || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01024                      || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01025                     )
01026                 )
01027             curr = curr->next;
01028           if (curr)
01029             reg_head.curr=curr;
01030 #ifdef CONFIG_RSBAC_DEBUG
01031           else
01032             if(rsbac_debug_lists)
01033               {
01034                 rsbac_printk(KERN_DEBUG "lookup_reg_name(): Lookup of unknown list name %s on device %02u:%02u\n",
01035                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
01036               }
01037 #endif
01038         }
01039       /* it is the current item -> return it */
01040       return curr;
01041     }
01042 
01043 /* List of lists registration lookup */
01044 
01045 static struct rsbac_list_lol_reg_item_t * lookup_lol_reg(struct rsbac_list_lol_reg_item_t *  handle)
01046     {
01047       struct rsbac_list_lol_reg_item_t  * curr = lol_reg_head.curr;
01048       
01049       if(!handle)
01050         return NULL;
01051       /* if there is no current item or it is not the right one, search... */
01052       if(curr != handle)
01053         {
01054           curr = lol_reg_head.head;
01055           while (curr && curr != handle)
01056             curr = curr->next;
01057           if (curr)
01058             lol_reg_head.curr=curr;
01059 #ifdef CONFIG_RSBAC_DEBUG
01060           else
01061             if(rsbac_debug_lists)
01062               {
01063                 rsbac_printk(KERN_DEBUG "lookup_lol_reg(): Lookup of unknown list handle %p\n",
01064                        handle);
01065               }
01066 #endif
01067         }
01068       /* it is the current item -> return it */
01069       return curr;
01070     }
01071 
01072 static struct rsbac_list_lol_reg_item_t * lookup_lol_reg_name(char * name, kdev_t device)
01073     {
01074       struct rsbac_list_lol_reg_item_t  * curr = lol_reg_head.curr;
01075       
01076       if(!name)
01077         return NULL;
01078       /* if there is no current item or it is not the right one, search... */
01079       if(   !curr
01080          || (   strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01081              || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01082              || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01083             )
01084         )
01085         {
01086           curr = lol_reg_head.head;
01087           while (   curr
01088                  && (   strncmp(curr->name, name, RSBAC_LIST_MAX_FILENAME)
01089                      || (RSBAC_MAJOR(curr->device) != RSBAC_MAJOR(device))
01090                      || (RSBAC_MINOR(curr->device) != RSBAC_MINOR(device))
01091                     )
01092                 )
01093             curr = curr->next;
01094           if (curr)
01095             lol_reg_head.curr=curr;
01096 #ifdef CONFIG_RSBAC_DEBUG
01097           else
01098             if(rsbac_debug_lists)
01099               {
01100                 rsbac_printk(KERN_DEBUG "lookup_lol_reg_name(): Lookup of unknown list name %s on device %02u:%02u\n",
01101                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
01102               }
01103 #endif
01104         }
01105       /* it is the current item -> return it */
01106       return curr;
01107     }
01108 
01109 /*************/
01110 /* Add items */
01111 
01112 static struct rsbac_list_item_t * insert_item_compare(
01113     struct rsbac_list_reg_item_t * list,
01114     void * desc,
01115     struct rsbac_list_item_t * new_item_p)
01116     {
01117       struct rsbac_list_item_t * curr;
01118 
01119       curr = list->curr;
01120       if(!curr)
01121         curr = list->head;
01122       if((list->compare(desc, &curr[1]) > 0))
01123         {
01124           curr = curr->next;
01125           while (   curr
01126                  && (list->compare(desc, &curr[1]) > 0)
01127                 )
01128             curr = curr->next;
01129           if (curr)
01130             {
01131               /* insert before curr */
01132               new_item_p->prev=curr->prev;
01133               new_item_p->next=curr;
01134               curr->prev->next=new_item_p;
01135               curr->prev=new_item_p;
01136             }
01137           else
01138             {
01139               /* insert as last item */
01140               new_item_p->prev=list->tail;
01141               new_item_p->next=NULL;
01142               list->tail->next=new_item_p;
01143               list->tail=new_item_p;
01144             }
01145         }
01146       else
01147         {
01148           curr = curr->prev;
01149           while (   curr
01150                  && (list->compare(desc, &curr[1]) < 0)
01151                 )
01152             curr = curr->prev;
01153           if (curr)
01154             {
01155               /* insert after curr */
01156               new_item_p->prev=curr;
01157               new_item_p->next=curr->next;
01158               curr->next->prev=new_item_p;
01159               curr->next=new_item_p;
01160             }
01161           else
01162             {
01163               /* insert as first item */
01164               new_item_p->prev=NULL;
01165               new_item_p->next=list->head;
01166               list->head->prev=new_item_p;
01167               list->head=new_item_p;
01168             }
01169         }
01170       list->count++;
01171       list->curr=new_item_p;
01172       return new_item_p;
01173     }
01174 
01175 static struct rsbac_list_item_t * insert_item_memcmp(
01176     struct rsbac_list_reg_item_t * list,
01177     void * desc,
01178     struct rsbac_list_item_t * new_item_p)
01179     {
01180       struct rsbac_list_item_t * curr;
01181 
01182       curr = list->curr;
01183       if(!curr)
01184         curr = list->head;
01185       if(memcmp(desc,
01186                 &curr[1],
01187                 list->info.desc_size) > 0)
01188         {
01189           curr = curr->next;
01190           while (   curr
01191                  && (memcmp(desc,
01192                            &curr[1],
01193                            list->info.desc_size) > 0
01194                     )
01195                 )
01196             curr = curr->next;
01197           if (curr)
01198             {
01199               /* insert before curr */
01200               new_item_p->prev=curr->prev;
01201               new_item_p->next=curr;
01202               curr->prev->next=new_item_p;
01203               curr->prev=new_item_p;
01204             }
01205           else
01206             {
01207               /* insert as last item */
01208               new_item_p->prev=list->tail;
01209               new_item_p->next=NULL;
01210               list->tail->next=new_item_p;
01211               list->tail=new_item_p;
01212             }
01213         }
01214       else
01215         {
01216           curr = curr->prev;
01217           while (   curr
01218                  && (memcmp(desc,
01219                            &curr[1],
01220                            list->info.desc_size) < 0
01221                     )
01222                 )
01223             curr = curr->prev;
01224           if (curr)
01225             {
01226               /* insert after curr */
01227               new_item_p->prev=curr;
01228               new_item_p->next=curr->next;
01229               curr->next->prev=new_item_p;
01230               curr->next=new_item_p;
01231             }
01232           else
01233             {
01234               /* insert as first item */
01235               new_item_p->prev=NULL;
01236               new_item_p->next=list->head;
01237               list->head->prev=new_item_p;
01238               list->head=new_item_p;
01239             }
01240         }
01241       list->count++;
01242       list->curr=new_item_p;
01243       return new_item_p;
01244     }
01245 
01246 static struct rsbac_list_item_t * add_item(
01247     struct rsbac_list_reg_item_t * list,
01248     rsbac_time_t max_age,
01249     void * desc,
01250     void * data)
01251     {
01252       struct rsbac_list_item_t * new_item_p = NULL;
01253 
01254       if(!list || !desc)
01255         return NULL;
01256 
01257       if(!list || !desc)
01258         return NULL;
01259       if(list->info.data_size && !data)
01260         return NULL;
01261       /* item desc and data are behind official struct */
01262       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size + list->info.data_size)) )
01263         return(NULL);
01264       new_item_p->max_age = max_age;
01265       /* item desc is behind official struct */
01266       memcpy(&new_item_p[1],
01267              desc, list->info.desc_size);
01268       /* item data is behind official struct and desc */
01269       /* data might be empty! */
01270       if(data && list->info.data_size)
01271         memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) + list->info.desc_size,
01272                data,
01273                list->info.data_size);
01274 
01275       if (!list->head)
01276         {
01277           list->head=new_item_p;
01278           list->tail=new_item_p;
01279           list->curr=new_item_p;
01280           list->count = 1;
01281           new_item_p->prev=NULL;
01282           new_item_p->next=NULL;
01283           return new_item_p;
01284         }
01285       if(list->compare)
01286         return insert_item_compare(list, desc, new_item_p);
01287       else
01288         return insert_item_memcmp(list, desc, new_item_p);
01289     }
01290 
01291 #ifdef CONFIG_RSBAC_LIST_TRANS
01292 static void ta_remove_all_items(struct rsbac_list_reg_item_t * list);
01293 
01294 static int ta_copy(
01295   rsbac_list_ta_number_t ta_number,
01296   struct rsbac_list_reg_item_t * list)
01297   {
01298     struct rsbac_list_item_t * curr;
01299     struct rsbac_list_item_t * new_item_p;
01300     u_int item_size =   sizeof(*new_item_p)
01301                       + list->info.desc_size
01302                       + list->info.data_size;
01303 
01304     curr = list->head;
01305     if(curr)
01306       {
01307         if ( !(new_item_p = rsbac_kmalloc(item_size) ))
01308           {
01309             ta_remove_all_items(list);
01310             return(-RSBAC_ENOMEM);
01311           }
01312         memcpy(new_item_p, curr, item_size);
01313         new_item_p->prev = NULL;
01314         new_item_p->next = NULL;
01315         list->ta_head = new_item_p;
01316         list->ta_tail = new_item_p;
01317         list->ta_curr = new_item_p;
01318         list->ta_count = 1;
01319         curr = curr->next;
01320       }
01321     else
01322       {
01323         list->ta_head = NULL;
01324         list->ta_tail = NULL;
01325         list->ta_curr = NULL;
01326         list->ta_count = 0;
01327         list->ta_copied = ta_number;
01328         return 0;
01329       }
01330     while(curr)
01331       {
01332         if ( !(new_item_p = rsbac_kmalloc(item_size)) )
01333           {
01334             ta_remove_all_items(list);
01335             return(-RSBAC_ENOMEM);
01336           }
01337         memcpy(new_item_p, curr, item_size);
01338         new_item_p->prev = list->ta_tail;
01339         new_item_p->next = NULL;
01340         list->ta_tail->next = new_item_p;
01341         list->ta_tail = new_item_p;
01342         list->ta_count++;
01343         curr = curr->next;
01344       }
01345     list->ta_copied = ta_number;
01346     return 0;
01347   }
01348 
01349 static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t * list);
01350 
01351 static int ta_lol_copy(
01352   rsbac_list_ta_number_t ta_number,
01353   struct rsbac_list_lol_reg_item_t * list)
01354   {
01355     struct rsbac_list_lol_item_t * curr;
01356     struct rsbac_list_lol_item_t * new_item_p;
01357     struct rsbac_list_item_t * sub_curr;
01358     struct rsbac_list_item_t * new_subitem_p;
01359     u_int item_size =   sizeof(*new_item_p)
01360                       + list->info.desc_size
01361                       + list->info.data_size;
01362     u_int subitem_size =   sizeof(*new_subitem_p)
01363                          + list->info.subdesc_size
01364                          + list->info.subdata_size;
01365 
01366     list->ta_head = NULL;
01367     list->ta_tail = NULL;
01368     list->ta_curr = NULL;
01369     list->ta_count = 0;
01370 
01371     curr = list->head;
01372     while(curr)
01373       {
01374         if ( !(new_item_p = rsbac_kmalloc(item_size)) )
01375           {
01376             ta_remove_all_lol_items(list);
01377             return(-RSBAC_ENOMEM);
01378           }
01379         memcpy(new_item_p, curr, item_size);
01380         new_item_p->head = NULL;
01381         new_item_p->tail = NULL;
01382         new_item_p->curr = NULL;
01383         new_item_p->count = 0;
01384         new_item_p->prev = NULL;
01385         new_item_p->next = NULL;
01386         sub_curr = curr->head;
01387         while(sub_curr)
01388           {
01389             if ( !(new_subitem_p = rsbac_kmalloc(subitem_size)) )
01390               {
01391                 ta_remove_all_lol_items(list);
01392                 rsbac_kfree(new_item_p);
01393                 return(-RSBAC_ENOMEM);
01394               }
01395             memcpy(new_subitem_p, sub_curr, subitem_size);
01396             new_subitem_p->prev = NULL;
01397             new_subitem_p->next = NULL;
01398             if(new_item_p->tail)
01399               {
01400                 new_subitem_p->prev = new_item_p->tail;
01401                 new_item_p->tail->next = new_subitem_p;
01402                 new_item_p->tail = new_subitem_p;
01403                 new_item_p->count++;
01404               }
01405             else
01406               {
01407                 new_item_p->head = new_subitem_p;
01408                 new_item_p->tail = new_subitem_p;
01409                 new_item_p->count = 1;
01410               }
01411             sub_curr = sub_curr->next;
01412           }
01413         if(list->ta_tail)
01414           {
01415             new_item_p->prev = list->ta_tail;
01416             list->ta_tail->next = new_item_p;
01417             list->ta_tail = new_item_p;
01418             list->ta_count++;
01419           }
01420         else
01421           {
01422             list->ta_head = new_item_p;
01423             list->ta_tail = new_item_p;
01424             list->ta_curr = new_item_p;
01425             list->ta_count = 1;
01426           }
01427         curr = curr->next;
01428       }
01429     list->ta_copied = ta_number;
01430     return 0;
01431   }
01432 
01433 static struct rsbac_list_item_t * ta_insert_item_compare(
01434     struct rsbac_list_reg_item_t * list,
01435     void * desc,
01436     struct rsbac_list_item_t * new_item_p)
01437     {
01438       struct rsbac_list_item_t * curr;
01439 
01440       curr = list->ta_curr;
01441       if(!curr)
01442         curr = list->ta_head;
01443       if((list->compare(desc, &curr[1]) > 0))
01444         {
01445           curr = curr->next;
01446           while (   curr
01447                  && (list->compare(desc, &curr[1]) > 0)
01448                 )
01449             curr = curr->next;
01450           if (curr)
01451             {
01452               /* insert before curr */
01453               new_item_p->prev=curr->prev;
01454               new_item_p->next=curr;
01455               curr->prev->next=new_item_p;
01456               curr->prev=new_item_p;
01457             }
01458           else
01459             {
01460               /* insert as last item */
01461               new_item_p->prev=list->ta_tail;
01462               new_item_p->next=NULL;
01463               list->ta_tail->next=new_item_p;
01464               list->ta_tail=new_item_p;
01465             }
01466         }
01467       else
01468         {
01469           curr = curr->prev;
01470           while (   curr
01471                  && (list->compare(desc, &curr[1]) < 0)
01472                 )
01473             curr = curr->prev;
01474           if (curr)
01475             {
01476               /* insert after curr */
01477               new_item_p->prev=curr;
01478               new_item_p->next=curr->next;
01479               curr->next->prev=new_item_p;
01480               curr->next=new_item_p;
01481             }
01482           else
01483             {
01484               /* insert as first item */
01485               new_item_p->prev=NULL;
01486               new_item_p->next=list->ta_head;
01487               list->ta_head->prev=new_item_p;
01488               list->ta_head=new_item_p;
01489             }
01490         }
01491       list->ta_count++;
01492       list->ta_curr=new_item_p;
01493       return new_item_p;
01494     }
01495 
01496 static struct rsbac_list_item_t * ta_insert_item_memcmp(
01497     struct rsbac_list_reg_item_t * list,
01498     void * desc,
01499     struct rsbac_list_item_t * new_item_p)
01500     {
01501       struct rsbac_list_item_t * curr;
01502 
01503       curr = list->ta_curr;
01504       if(!curr)
01505         curr = list->ta_head;
01506       if(memcmp(desc,
01507                 &curr[1],
01508                 list->info.desc_size) > 0)
01509         {
01510           curr = curr->next;
01511           while (   curr
01512                  && (memcmp(desc,
01513                            &curr[1],
01514                            list->info.desc_size) > 0
01515                     )
01516                 )
01517             curr = curr->next;
01518           if (curr)
01519             {
01520               /* insert before curr */
01521               new_item_p->prev=curr->prev;
01522               new_item_p->next=curr;
01523               curr->prev->next=new_item_p;
01524               curr->prev=new_item_p;
01525             }
01526           else
01527             {
01528               /* insert as last item */
01529               new_item_p->prev=list->ta_tail;
01530               new_item_p->next=NULL;
01531               list->ta_tail->next=new_item_p;
01532               list->ta_tail=new_item_p;
01533             }
01534         }
01535       else
01536         {
01537           curr = curr->prev;
01538           while (   curr
01539                  && (memcmp(desc,
01540                            &curr[1],
01541                            list->info.desc_size) < 0
01542                     )
01543                 )
01544             curr = curr->prev;
01545           if (curr)
01546             {
01547               /* insert after curr */
01548               new_item_p->prev=curr;
01549               new_item_p->next=curr->next;
01550               curr->next->prev=new_item_p;
01551               curr->next=new_item_p;
01552             }
01553           else
01554             {
01555               /* insert as first item */
01556               new_item_p->prev=NULL;
01557               new_item_p->next=list->ta_head;
01558               list->ta_head->prev=new_item_p;
01559               list->ta_head=new_item_p;
01560             }
01561         }
01562       list->ta_count++;
01563       list->ta_curr=new_item_p;
01564       return new_item_p;
01565     }
01566 
01567 static struct rsbac_list_item_t * ta_add_item(
01568     rsbac_list_ta_number_t ta_number,
01569     struct rsbac_list_reg_item_t * list,
01570     rsbac_time_t max_age,
01571     void * desc,
01572     void * data)
01573     {
01574       struct rsbac_list_item_t * new_item_p = NULL;
01575 
01576       if(!list || !desc)
01577         return NULL;
01578 
01579       if(!list || !desc)
01580         return NULL;
01581       if(list->info.data_size && !data)
01582         return NULL;
01583       if(!ta_number)
01584         return add_item(list, max_age, desc, data);
01585       /* item desc and data are behind official struct */
01586       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size + list->info.data_size)) )
01587         return(NULL);
01588       new_item_p->max_age = max_age;
01589       /* item desc is behind official struct */
01590       memcpy(&new_item_p[1],
01591              desc, list->info.desc_size);
01592       /* item data is behind official struct and desc */
01593       /* data might be empty! */
01594       if(data && list->info.data_size)
01595         memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) + list->info.desc_size,
01596                data,
01597                list->info.data_size);
01598 
01599       if(!list->ta_copied)
01600         { /* copy list to ta_list */
01601           if(ta_copy(ta_number, list))
01602             {
01603               rsbac_kfree(new_item_p);
01604               return NULL;
01605             }
01606         }
01607       else
01608         {
01609           if(list->ta_copied != ta_number)
01610             {
01611               rsbac_kfree(new_item_p);
01612               return NULL;
01613             }
01614         }
01615 
01616       if (!list->ta_head)
01617         {
01618           list->ta_head=new_item_p;
01619           list->ta_tail=new_item_p;
01620           list->ta_curr=new_item_p;
01621           list->ta_count = 1;
01622           new_item_p->prev=NULL;
01623           new_item_p->next=NULL;
01624           return new_item_p;
01625         }
01626       if(list->compare)
01627         return ta_insert_item_compare(list, desc, new_item_p);
01628       else
01629         return ta_insert_item_memcmp(list, desc, new_item_p);
01630     }
01631 #endif
01632 
01633 
01634 static struct rsbac_list_item_t * insert_lol_subitem_compare(
01635     struct rsbac_list_lol_reg_item_t * list,
01636     struct rsbac_list_lol_item_t * sublist,
01637     void * subdesc,
01638     struct rsbac_list_item_t * new_item_p)
01639     {
01640       struct rsbac_list_item_t * curr;
01641 
01642       curr = sublist->curr;
01643       if(!curr)
01644         curr = sublist->head;
01645       if((list->subcompare(subdesc, &curr[1]) > 0))
01646         {
01647           curr = curr->next;
01648           while (   curr
01649                  && (list->subcompare(subdesc, &curr[1]) > 0)
01650                 )
01651             curr = curr->next;
01652           if (curr)
01653             {
01654               /* insert before curr */
01655               new_item_p->prev=curr->prev;
01656               new_item_p->next=curr;
01657               curr->prev->next=new_item_p;
01658               curr->prev=new_item_p;
01659             }
01660           else
01661             {
01662               /* insert as last item */
01663               new_item_p->prev=sublist->tail;
01664               new_item_p->next=NULL;
01665               sublist->tail->next=new_item_p;
01666               sublist->tail=new_item_p;
01667             }
01668         }
01669       else
01670         {
01671           curr = curr->prev;
01672           while (   curr
01673                  && (list->subcompare(subdesc, &curr[1]) < 0)
01674                 )
01675             curr = curr->prev;
01676           if (curr)
01677             {
01678               /* insert after curr */
01679               new_item_p->prev=curr;
01680               new_item_p->next=curr->next;
01681               curr->next->prev=new_item_p;
01682               curr->next=new_item_p;
01683             }
01684           else
01685             {
01686               /* insert as first item */
01687               new_item_p->prev=NULL;
01688               new_item_p->next=sublist->head;
01689               sublist->head->prev=new_item_p;
01690               sublist->head=new_item_p;
01691             }
01692         }
01693       sublist->count++;
01694       sublist->curr=new_item_p;
01695       return new_item_p;
01696     }
01697 
01698 static struct rsbac_list_item_t * insert_lol_subitem_memcmp(
01699     struct rsbac_list_lol_reg_item_t * list,
01700     struct rsbac_list_lol_item_t * sublist,
01701     void * subdesc,
01702     struct rsbac_list_item_t * new_item_p)
01703     {
01704       struct rsbac_list_item_t * curr;
01705 
01706       curr = sublist->curr;
01707       if(!curr)
01708         curr = sublist->head;
01709       if(memcmp(subdesc,
01710                 &curr[1],
01711                 list->info.subdesc_size) > 0)
01712         {
01713           curr = curr->next;
01714           while (   curr
01715                  && (memcmp(subdesc,
01716                            &curr[1],
01717                            list->info.subdesc_size) > 0
01718                     )
01719                 )
01720             curr = curr->next;
01721           if (curr)
01722             {
01723               /* insert before curr */
01724               new_item_p->prev=curr->prev;
01725               new_item_p->next=curr;
01726               curr->prev->next=new_item_p;
01727               curr->prev=new_item_p;
01728             }
01729           else
01730             {
01731               /* insert as last item */
01732               new_item_p->prev=sublist->tail;
01733               new_item_p->next=NULL;
01734               sublist->tail->next=new_item_p;
01735               sublist->tail=new_item_p;
01736             }
01737         }
01738       else
01739         {
01740           curr = curr->prev;
01741           while (   curr
01742                  && (memcmp(subdesc,
01743                            &curr[1],
01744                            list->info.subdesc_size) < 0
01745                     )
01746                 )
01747             curr = curr->prev;
01748           if (curr)
01749             {
01750               /* insert after curr */
01751               new_item_p->prev=curr;
01752               new_item_p->next=curr->next;
01753               curr->next->prev=new_item_p;
01754               curr->next=new_item_p;
01755             }
01756           else
01757             {
01758               /* insert as first item */
01759               new_item_p->prev=NULL;
01760               new_item_p->next=sublist->head;
01761               sublist->head->prev=new_item_p;
01762               sublist->head=new_item_p;
01763             }
01764         }
01765       sublist->count++;
01766       sublist->curr=new_item_p;
01767       return new_item_p;
01768     }
01769 
01770 static struct rsbac_list_item_t * add_lol_subitem(
01771     struct rsbac_list_lol_reg_item_t * list,
01772     struct rsbac_list_lol_item_t     * sublist,
01773     rsbac_time_t max_age,
01774     void * subdesc,
01775     void * subdata)
01776     {
01777       struct rsbac_list_item_t * new_item_p = NULL;
01778 
01779       if(!list || !sublist || !subdesc)
01780         return NULL;
01781       if(list->info.subdata_size && !subdata)
01782         return NULL;
01783       /* item desc and data are behind official struct */
01784       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p) + list->info.subdesc_size + list->info.subdata_size)) )
01785         return(NULL);
01786       new_item_p->max_age = max_age;
01787       /* item desc is behind official struct */
01788       memcpy(&new_item_p[1],
01789              subdesc,
01790              list->info.subdesc_size);
01791       /* item data is behind official struct and desc */
01792       /* subdata might be empty! */
01793       if(subdata && list->info.subdata_size)
01794         memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) + list->info.subdesc_size,
01795                subdata,
01796                list->info.subdata_size);
01797 
01798       /* Sublist was empty */
01799       if (!sublist->head)
01800         {
01801           sublist->head=new_item_p;
01802           sublist->tail=new_item_p;
01803           sublist->curr=new_item_p;
01804           sublist->count = 1;
01805           new_item_p->prev=NULL;
01806           new_item_p->next=NULL;          
01807           return(new_item_p);
01808         }  
01809       if(list->subcompare)
01810         return insert_lol_subitem_compare(list, sublist, subdesc, new_item_p);
01811       else
01812         return insert_lol_subitem_memcmp(list, sublist, subdesc, new_item_p);
01813     }
01814 
01815 static struct rsbac_list_lol_item_t * insert_lol_item_compare(
01816     struct rsbac_list_lol_reg_item_t * list,
01817     void * desc,
01818     struct rsbac_list_lol_item_t * new_item_p)
01819     {
01820       struct rsbac_list_lol_item_t * curr;
01821 
01822       curr = list->curr;
01823       if(!curr)
01824         curr = list->head;
01825       if((list->compare(desc, &curr[1]) > 0))
01826         {
01827           curr = curr->next;
01828           while (   curr
01829                  && (list->compare(desc, &curr[1]) > 0)
01830                 )
01831             curr = curr->next;
01832           if (curr)
01833             {
01834               /* insert before curr */
01835               new_item_p->prev=curr->prev;
01836               new_item_p->next=curr;
01837               curr->prev->next=new_item_p;
01838               curr->prev=new_item_p;
01839             }
01840           else
01841             {
01842               /* insert as last item */
01843               new_item_p->prev=list->tail;
01844               new_item_p->next=NULL;
01845               list->tail->next=new_item_p;
01846               list->tail=new_item_p;
01847             }
01848         }
01849       else
01850         {
01851           curr = curr->prev;
01852           while (   curr
01853                  && (list->compare(desc, &curr[1]) < 0)
01854                 )
01855             curr = curr->prev;
01856           if (curr)
01857             {
01858               /* insert after curr */
01859               new_item_p->prev=curr;
01860               new_item_p->next=curr->next;
01861               curr->next->prev=new_item_p;
01862               curr->next=new_item_p;
01863             }
01864           else
01865             {
01866               /* insert as first item */
01867               new_item_p->prev=NULL;
01868               new_item_p->next=list->head;
01869               list->head->prev=new_item_p;
01870               list->head=new_item_p;
01871             }
01872         }
01873       list->count++;
01874       list->curr=new_item_p;
01875       return new_item_p;
01876     }
01877 
01878 static struct rsbac_list_lol_item_t * insert_lol_item_memcmp(
01879     struct rsbac_list_lol_reg_item_t * list,
01880     void * desc,
01881     struct rsbac_list_lol_item_t * new_item_p)
01882     {
01883       struct rsbac_list_lol_item_t * curr;
01884 
01885       curr = list->curr;
01886       if(!curr)
01887         curr = list->head;
01888       if(memcmp(desc,
01889                 &curr[1],
01890                 list->info.desc_size) > 0)
01891         {
01892           curr = curr->next;
01893           while (   curr
01894                  && (memcmp(desc,
01895                            &curr[1],
01896                            list->info.desc_size) > 0
01897                     )
01898                 )
01899             curr = curr->next;
01900           if (curr)
01901             {
01902               /* insert before curr */
01903               new_item_p->prev=curr->prev;
01904               new_item_p->next=curr;
01905               curr->prev->next=new_item_p;
01906               curr->prev=new_item_p;
01907             }
01908           else
01909             {
01910               /* insert as last item */
01911               new_item_p->prev=list->tail;
01912               new_item_p->next=NULL;
01913               list->tail->next=new_item_p;
01914               list->tail=new_item_p;
01915             }
01916         }
01917       else
01918         {
01919           curr = curr->prev;
01920           while (   curr
01921                  && (memcmp(desc,
01922                            &curr[1],
01923                            list->info.desc_size) < 0
01924                     )
01925                 )
01926             curr = curr->prev;
01927           if (curr)
01928             {
01929               /* insert after curr */
01930               new_item_p->prev=curr;
01931               new_item_p->next=curr->next;
01932               curr->next->prev=new_item_p;
01933               curr->next=new_item_p;
01934             }
01935           else
01936             {
01937               /* insert as first item */
01938               new_item_p->prev=NULL;
01939               new_item_p->next=list->head;
01940               list->head->prev=new_item_p;
01941               list->head=new_item_p;
01942             }
01943         }
01944       list->count++;
01945       list->curr=new_item_p;
01946       return new_item_p;
01947     }
01948 
01949 static struct rsbac_list_lol_item_t * add_lol_item(
01950     struct rsbac_list_lol_reg_item_t * list,
01951     rsbac_time_t max_age,
01952     void * desc,
01953     void * data)
01954     {
01955       struct rsbac_list_lol_item_t * new_item_p = NULL;
01956 
01957       if(!list || !desc)
01958         return NULL;
01959       if(list->info.data_size && !data)
01960         return NULL;
01961       /* item desc and data are behind official struct */
01962       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size + list->info.data_size)) )
01963         return(NULL);
01964       /* Init sublist */
01965       new_item_p->head = NULL;
01966       new_item_p->tail = NULL;
01967       new_item_p->curr = NULL;
01968       new_item_p->count = 0;
01969       new_item_p->max_age = max_age;
01970       /* item desc is behind official struct */
01971       memcpy(&new_item_p[1],
01972              desc,
01973              list->info.desc_size);
01974       /* item data is behind official struct and desc */
01975       /* data might be empty! */
01976       if(data && list->info.data_size)
01977         memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) + list->info.desc_size,
01978                data,
01979                list->info.data_size);
01980 
01981       if (!list->head)
01982         {
01983           list->head=new_item_p;
01984           list->tail=new_item_p;
01985           list->curr=new_item_p;
01986           list->count = 1;
01987           new_item_p->prev=NULL;
01988           new_item_p->next=NULL;          
01989           return(new_item_p);
01990         }
01991       if(list->compare)
01992         return insert_lol_item_compare(list, desc, new_item_p);
01993       else
01994         return insert_lol_item_memcmp(list, desc, new_item_p);
01995     }
01996 
01997 #ifdef CONFIG_RSBAC_LIST_TRANS
01998 static struct rsbac_list_lol_item_t * ta_insert_lol_item_compare(
01999     struct rsbac_list_lol_reg_item_t * list,
02000     void * desc,
02001     struct rsbac_list_lol_item_t * new_item_p)
02002     {
02003       struct rsbac_list_lol_item_t * curr;
02004 
02005       curr = list->ta_curr;
02006       if(!curr)
02007         curr = list->ta_head;
02008       if((list->compare(desc, &curr[1]) > 0))
02009         {
02010           curr = curr->next;
02011           while (   curr
02012                  && (list->compare(desc, &curr[1]) > 0)
02013                 )
02014             curr = curr->next;
02015           if (curr)
02016             {
02017               /* insert before curr */
02018               new_item_p->prev=curr->prev;
02019               new_item_p->next=curr;
02020               curr->prev->next=new_item_p;
02021               curr->prev=new_item_p;
02022             }
02023           else
02024             {
02025               /* insert as last item */
02026               new_item_p->prev=list->ta_tail;
02027               new_item_p->next=NULL;
02028               list->ta_tail->next=new_item_p;
02029               list->ta_tail=new_item_p;
02030             }
02031         }
02032       else
02033         {
02034           curr = curr->prev;
02035           while (   curr
02036                  && (list->compare(desc, &curr[1]) < 0)
02037                 )
02038             curr = curr->prev;
02039           if (curr)
02040             {
02041               /* insert after curr */
02042               new_item_p->prev=curr;
02043               new_item_p->next=curr->next;
02044               curr->next->prev=new_item_p;
02045               curr->next=new_item_p;
02046             }
02047           else
02048             {
02049               /* insert as first item */
02050               new_item_p->prev=NULL;
02051               new_item_p->next=list->ta_head;
02052               list->ta_head->prev=new_item_p;
02053               list->ta_head=new_item_p;
02054             }
02055         }
02056       list->ta_count++;
02057       list->ta_curr=new_item_p;
02058       return new_item_p;
02059     }
02060 
02061 static struct rsbac_list_lol_item_t * ta_insert_lol_item_memcmp(
02062     struct rsbac_list_lol_reg_item_t * list,
02063     void * desc,
02064     struct rsbac_list_lol_item_t * new_item_p)
02065     {
02066       struct rsbac_list_lol_item_t * curr;
02067 
02068       curr = list->ta_curr;
02069       if(!curr)
02070         curr = list->ta_head;
02071       if(memcmp(desc,
02072                 &curr[1],
02073                 list->info.desc_size) > 0)
02074         {
02075           curr = curr->next;
02076           while (   curr
02077                  && (memcmp(desc,
02078                            &curr[1],
02079                            list->info.desc_size) > 0
02080                     )
02081                 )
02082             curr = curr->next;
02083           if (curr)
02084             {
02085               /* insert before curr */
02086               new_item_p->prev=curr->prev;
02087               new_item_p->next=curr;
02088               curr->prev->next=new_item_p;
02089               curr->prev=new_item_p;
02090             }
02091           else
02092             {
02093               /* insert as last item */
02094               new_item_p->prev=list->ta_tail;
02095               new_item_p->next=NULL;
02096               list->ta_tail->next=new_item_p;
02097               list->ta_tail=new_item_p;
02098             }
02099         }
02100       else
02101         {
02102           curr = curr->prev;
02103           while (   curr
02104                  && (memcmp(desc,
02105                            &curr[1],
02106                            list->info.desc_size) < 0
02107                     )
02108                 )
02109             curr = curr->prev;
02110           if (curr)
02111             {
02112               /* insert after curr */
02113               new_item_p->prev=curr;
02114               new_item_p->next=curr->next;
02115               curr->next->prev=new_item_p;
02116               curr->next=new_item_p;
02117             }
02118           else
02119             {
02120               /* insert as first item */
02121               new_item_p->prev=NULL;
02122               new_item_p->next=list->ta_head;
02123               list->ta_head->prev=new_item_p;
02124               list->ta_head=new_item_p;
02125             }
02126         }
02127       list->ta_count++;
02128       list->ta_curr=new_item_p;
02129       return new_item_p;
02130     }
02131 
02132 static struct rsbac_list_lol_item_t * ta_add_lol_item(
02133     rsbac_list_ta_number_t ta_number,
02134     struct rsbac_list_lol_reg_item_t * list,
02135     rsbac_time_t max_age,
02136     void * desc,
02137     void * data)
02138     {
02139       struct rsbac_list_lol_item_t * new_item_p = NULL;
02140 
02141       if(!list || !desc)
02142         return NULL;
02143       if(list->info.data_size && !data)
02144         return NULL;
02145       if(!ta_number)
02146         return add_lol_item(list, max_age, desc, data);
02147       /* item desc and data are behind official struct */
02148       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p) + list->info.desc_size + list->info.data_size)) )
02149         return(NULL);
02150       /* Init sublist */
02151       new_item_p->head = NULL;
02152       new_item_p->tail = NULL;
02153       new_item_p->curr = NULL;
02154       new_item_p->count = 0;
02155       new_item_p->max_age = max_age;
02156       new_item_p->prev=NULL;
02157       new_item_p->next=NULL;          
02158       /* item desc is behind official struct */
02159       memcpy(&new_item_p[1],
02160              desc,
02161              list->info.desc_size);
02162       /* item data is behind official struct and desc */
02163       /* data might be empty! */
02164       if(data && list->info.data_size)
02165         memcpy(((__u8 *) new_item_p) + sizeof(*new_item_p) + list->info.desc_size,
02166                data,
02167                list->info.data_size);
02168 
02169       if(!list->ta_copied)
02170         { /* copy list to ta_list */
02171           if(ta_lol_copy(ta_number, list))
02172             {
02173               rsbac_kfree(new_item_p);
02174               return NULL;
02175             }
02176         }
02177       else
02178         {
02179           if(list->ta_copied != ta_number)
02180             {
02181               rsbac_kfree(new_item_p);
02182               return NULL;
02183             }
02184         }
02185 
02186       if (!list->ta_head)
02187         {
02188           list->ta_head=new_item_p;
02189           list->ta_tail=new_item_p;
02190           list->ta_curr=new_item_p;
02191           list->ta_count = 1;
02192           return(new_item_p);
02193         }
02194       if(list->compare)
02195         return ta_insert_lol_item_compare(list, desc, new_item_p);
02196       else
02197         return ta_insert_lol_item_memcmp(list, desc, new_item_p);
02198     }
02199 #endif
02200 
02201 /* Add registration items */
02202 
02203 /* no locking needed */
02204 static inline struct rsbac_list_reg_item_t* 
02205          create_reg(struct rsbac_list_info_t             * info_p,
02206                            u_int                         flags,
02207                            rsbac_list_compare_function_t * compare,
02208                            rsbac_list_get_conv_t       * get_conv,
02209                            void                        * def_data,
02210                            char                        * name,
02211                            kdev_t                        device)
02212     {
02213       struct rsbac_list_reg_item_t * new_item_p = NULL;
02214 
02215       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p))) )
02216         return(NULL);
02217       new_item_p->info = *info_p;
02218       if(!def_data)
02219         flags &= ~RSBAC_LIST_DEF_DATA;
02220       new_item_p->flags = flags;
02221       new_item_p->compare = compare;
02222       new_item_p->get_conv = get_conv;
02223       if(flags & RSBAC_LIST_DEF_DATA)
02224         {
02225           new_item_p->def_data = rsbac_kmalloc(info_p->data_size);
02226           if(new_item_p->def_data)
02227             memcpy(new_item_p->def_data, def_data, info_p->data_size);
02228           else
02229             {
02230               rsbac_kfree(new_item_p);
02231               return NULL;
02232             }
02233         }
02234       else
02235         new_item_p->def_data = NULL;
02236       if(name)
02237         {
02238           strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
02239           new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
02240         }
02241       else
02242         {
02243           strcpy(new_item_p->name, RSBAC_LIST_NONAME);
02244         }
02245       new_item_p->device = device;
02246       new_item_p->head   = NULL;
02247       new_item_p->tail   = NULL;
02248       new_item_p->curr   = NULL;
02249       new_item_p->lock   = RW_LOCK_UNLOCKED;
02250       new_item_p->count  = 0;
02251       new_item_p->dirty  = FALSE;
02252       if(flags & RSBAC_LIST_NO_WRITE)
02253         new_item_p->no_write = TRUE;
02254       else
02255         new_item_p->no_write = FALSE;
02256       new_item_p->lastchange.sec = 0;
02257       new_item_p->lastchange.nsec = 0;
02258 #ifdef CONFIG_RSBAC_LIST_TRANS
02259       new_item_p->ta_copied = FALSE;
02260       new_item_p->ta_head   = NULL;
02261       new_item_p->ta_tail   = NULL;
02262       new_item_p->ta_curr   = NULL;
02263       new_item_p->ta_count  = 0;
02264 #endif
02265       new_item_p->self = new_item_p;
02266       return new_item_p;
02267     }
02268 
02269 /* locking needed */
02270 static struct rsbac_list_reg_item_t* 
02271          add_reg(struct rsbac_list_reg_item_t* new_item_p)
02272     {
02273       if (!reg_head.head)
02274         {
02275           reg_head.head=new_item_p;
02276           reg_head.tail=new_item_p;
02277           reg_head.curr=new_item_p;
02278           reg_head.count = 1;
02279           new_item_p->prev=NULL;
02280           new_item_p->next=NULL;          
02281         }  
02282       else
02283         {
02284           new_item_p->prev=reg_head.tail;
02285           new_item_p->next=NULL;
02286           reg_head.tail->next=new_item_p;
02287           reg_head.tail=new_item_p;
02288           reg_head.curr=new_item_p;
02289           reg_head.count++;
02290         };
02291       return(new_item_p);
02292     }
02293 
02294 /* no locking needed */
02295 static inline struct rsbac_list_lol_reg_item_t* 
02296      create_lol_reg(struct rsbac_list_lol_info_t       * info_p,
02297                            u_int                         flags,
02298                            rsbac_list_compare_function_t * compare,
02299                            rsbac_list_compare_function_t * subcompare,
02300                            rsbac_list_get_conv_t       * get_conv,
02301                            rsbac_list_get_conv_t       * get_subconv,
02302                            void                        * def_data,
02303                            void                        * def_subdata,
02304                            char                        * name,
02305                            kdev_t                        device)
02306     {
02307       struct rsbac_list_lol_reg_item_t * new_item_p = NULL;
02308 
02309       if ( !(new_item_p = rsbac_kmalloc(sizeof(*new_item_p))) )
02310         return(NULL);
02311       new_item_p->info = *info_p;
02312       if(info_p->data_size && !def_data)
02313         flags &= ~RSBAC_LIST_DEF_DATA;
02314       if(!def_subdata)
02315         flags &= ~RSBAC_LIST_DEF_SUBDATA;
02316       new_item_p->flags = flags;
02317       new_item_p->compare = compare;
02318       new_item_p->subcompare = subcompare;
02319       new_item_p->get_conv = get_conv;
02320       new_item_p->get_subconv = get_subconv;
02321       if(   (flags & RSBAC_LIST_DEF_DATA)
02322          && (info_p->data_size)
02323         )
02324         {
02325           new_item_p->def_data = rsbac_kmalloc(info_p->data_size);
02326           if(new_item_p->def_data)
02327             memcpy(new_item_p->def_data, def_data, info_p->data_size);
02328           else
02329             {
02330               rsbac_kfree(new_item_p);
02331               return NULL;
02332             }
02333         }
02334       else
02335         new_item_p->def_data = NULL;
02336       if(flags & RSBAC_LIST_DEF_SUBDATA)
02337         {
02338           new_item_p->def_subdata = rsbac_kmalloc(info_p->subdata_size);
02339           if(new_item_p->def_subdata)
02340             memcpy(new_item_p->def_subdata, def_subdata, info_p->subdata_size);
02341           else
02342             {
02343               if(new_item_p->def_data)
02344                 rsbac_kfree(new_item_p->def_data);
02345               rsbac_kfree(new_item_p);
02346               return NULL;
02347             }
02348         }
02349       else
02350         new_item_p->def_subdata = NULL;
02351       if(name)
02352         {
02353           strncpy(new_item_p->name, name, RSBAC_LIST_MAX_FILENAME);
02354           new_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
02355         }
02356       else
02357         {
02358           strcpy(new_item_p->name, RSBAC_LIST_NONAME);
02359         }
02360       new_item_p->device = device;
02361       new_item_p->head   = NULL;
02362       new_item_p->tail   = NULL;
02363       new_item_p->curr   = NULL;
02364       new_item_p->lock   = RW_LOCK_UNLOCKED;
02365       new_item_p->count  = 0;
02366       new_item_p->dirty  = FALSE;
02367       if(flags & RSBAC_LIST_NO_WRITE)
02368         new_item_p->no_write = TRUE;
02369       else
02370         new_item_p->no_write = FALSE;
02371       new_item_p->lastchange.sec = 0;
02372       new_item_p->lastchange.nsec = 0;
02373 #ifdef CONFIG_RSBAC_LIST_TRANS
02374       new_item_p->ta_copied = FALSE;
02375       new_item_p->ta_head   = NULL;
02376       new_item_p->ta_tail   = NULL;
02377       new_item_p->ta_curr   = NULL;
02378       new_item_p->ta_count  = 0;
02379 #endif
02380       new_item_p->self = new_item_p;
02381       return(new_item_p);
02382     }
02383 
02384 /* locking needed */
02385 static struct rsbac_list_lol_reg_item_t* 
02386      add_lol_reg(struct rsbac_list_lol_reg_item_t * new_item_p)
02387     {
02388       if (!lol_reg_head.head)
02389         {
02390           lol_reg_head.head=new_item_p;
02391           lol_reg_head.tail=new_item_p;
02392           lol_reg_head.curr=new_item_p;
02393           lol_reg_head.count = 1;
02394           new_item_p->prev=NULL;
02395           new_item_p->next=NULL;          
02396         }  
02397       else
02398         {
02399           new_item_p->prev=lol_reg_head.tail;
02400           new_item_p->next=NULL;
02401           lol_reg_head.tail->next=new_item_p;
02402           lol_reg_head.tail=new_item_p;
02403           lol_reg_head.curr=new_item_p;
02404           lol_reg_head.count++;
02405         };
02406       return(new_item_p);
02407     }
02408 
02409 /* Removing items */
02410 
02411 static void do_remove_item(
02412     struct rsbac_list_reg_item_t * list,
02413     struct rsbac_list_item_t * item_p)
02414   {
02415     if(!list || !item_p)
02416       return;
02417 
02418     if ( (list->head == item_p) )
02419        { /* item is head */
02420          if ( (list->tail == item_p) )
02421            { /* item is head and tail = only item -> list will be empty*/
02422              list->head = NULL;
02423              list->tail = NULL;
02424            }
02425          else
02426            { /* item is head, but not tail -> next item becomes head */
02427              item_p->next->prev = NULL;
02428              list->head = item_p->next;
02429            };
02430        }
02431     else
02432        { /* item is not head */
02433          if ( (list->tail == item_p) )
02434            { /*item is not head, but tail -> previous item becomes tail*/
02435              item_p->prev->next = NULL;
02436              list->tail = item_p->prev;
02437            }
02438          else
02439            { /* item is neither head nor tail -> item is cut out */
02440              item_p->prev->next = item_p->next;
02441              item_p->next->prev = item_p->prev;
02442            }
02443        }
02444     /* curr is no longer valid -> reset */
02445     list->curr=NULL;
02446     /* adjust counter */
02447     list->count--;
02448     /* now we can remove the item from memory */
02449     rsbac_kfree(item_p);    
02450   } /* end of do_remove_item() */
02451 
02452 static void remove_item(
02453     struct rsbac_list_reg_item_t * list,
02454     void * desc)
02455   {
02456     struct rsbac_list_item_t * item_p;
02457 
02458     if(!list || !desc)
02459       return;
02460     /* first we must locate the item. */
02461     if ( (item_p = lookup_item(list, desc)) )
02462       {
02463         do_remove_item(list, item_p);
02464       }
02465   }
02466 
02467 static void remove_all_items(struct rsbac_list_reg_item_t * list)
02468     {
02469       struct rsbac_list_item_t     * item_p;
02470       struct rsbac_list_item_t     * next_item_p;
02471 
02472       /* cleanup all items */
02473       item_p = list->head;
02474       while(item_p)
02475         {
02476           next_item_p = item_p->next;
02477           rsbac_kfree(item_p);
02478           item_p = next_item_p;
02479         }
02480       list->head = NULL;
02481       list->tail = NULL;
02482       list->curr = NULL;
02483       list->count = 0;
02484     }
02485 
02486 #ifdef CONFIG_RSBAC_LIST_TRANS
02487 static void ta_do_remove_item(
02488     struct rsbac_list_reg_item_t * list,
02489     struct rsbac_list_item_t * item_p)
02490   {
02491     if(!list || !item_p)
02492       return;
02493 
02494     if ( (list->ta_head == item_p) )
02495        { /* item is head */
02496          if ( (list->ta_tail == item_p) )
02497            { /* item is head and tail = only item -> list will be empty*/
02498              list->ta_head = NULL;
02499              list->ta_tail = NULL;
02500            }
02501          else
02502            { /* item is head, but not tail -> next item becomes head */
02503              item_p->next->prev = NULL;
02504              list->ta_head = item_p->next;
02505            }
02506        }
02507     else
02508        { /* item is not head */
02509          if ( (list->ta_tail == item_p) )
02510            { /*item is not head, but tail -> previous item becomes tail*/
02511              item_p->prev->next = NULL;
02512              list->ta_tail = item_p->prev;
02513            }
02514          else
02515            { /* item is neither head nor tail -> item is cut out */
02516              item_p->prev->next = item_p->next;
02517              item_p->next->prev = item_p->prev;
02518            }
02519        }
02520     /* curr is no longer valid -> reset */
02521     list->ta_curr=NULL;
02522     /* adjust counter */
02523     list->ta_count--;
02524     /* now we can remove the item from memory */
02525     rsbac_kfree(item_p);    
02526   }
02527 
02528 static void ta_remove_item(
02529     rsbac_list_ta_number_t ta_number,
02530     struct rsbac_list_reg_item_t * list,
02531     void * desc)
02532   {
02533     struct rsbac_list_item_t * item_p;
02534 
02535     if(!list || !desc)
02536       return;
02537     if(!ta_number)
02538       return remove_item(list, desc);
02539     /* first we must locate the item. */
02540     if ( (item_p = ta_lookup_item(ta_number, list, desc)) )
02541       {
02542         ta_do_remove_item(list, item_p);
02543       }
02544   }
02545 
02546 static void ta_remove_all_items(struct rsbac_list_reg_item_t * list)
02547     {
02548       struct rsbac_list_item_t     * item_p;
02549       struct rsbac_list_item_t     * next_item_p;
02550 
02551       /* cleanup all items */
02552       item_p = list->ta_head;
02553       while(item_p)
02554         {
02555           next_item_p = item_p->next;
02556           rsbac_kfree(item_p);
02557           item_p = next_item_p;
02558         }
02559       list->ta_head = NULL;
02560       list->ta_tail = NULL;
02561       list->ta_curr = NULL;
02562       list->ta_count = 0;
02563     }
02564 #endif
02565 
02566 static void do_remove_lol_subitem(
02567     struct rsbac_list_lol_item_t * sublist,
02568     struct rsbac_list_item_t     * item_p)
02569   {
02570     if(!sublist || !item_p)
02571       return;
02572 
02573     if ( (sublist->head == item_p) )
02574       { /* item is head */
02575         if ( (sublist->tail == item_p) )
02576           { /* item is head and tail = only item -> list will be empty*/
02577             sublist->head = NULL;
02578             sublist->tail = NULL;
02579           }
02580         else
02581           { /* item is head, but not tail -> next item becomes head */
02582             item_p->next->prev = NULL;
02583             sublist->head = item_p->next;
02584           }
02585       }
02586     else
02587       { /* item is not head */
02588         if ( (sublist->tail == item_p) )
02589           { /*item is not head, but tail -> previous item becomes tail*/
02590             item_p->prev->next = NULL;
02591             sublist->tail = item_p->prev;
02592           }
02593         else
02594           { /* item is neither head nor tail -> item is cut out */
02595             item_p->prev->next = item_p->next;
02596             item_p->next->prev = item_p->prev;
02597           }
02598       }
02599     /* curr is no longer valid -> reset */
02600     sublist->curr=NULL;
02601     /* adjust counter */
02602     sublist->count--;
02603     /* now we can remove the item from memory */
02604     rsbac_kfree(item_p);    
02605   }
02606 
02607 static void remove_lol_subitem(
02608     struct rsbac_list_lol_reg_item_t * list,
02609     struct rsbac_list_lol_item_t     * sublist,
02610     void * subdesc)
02611   {
02612     struct rsbac_list_item_t     * item_p;
02613 
02614     if(!list || !sublist || !subdesc)
02615       return;
02616 
02617     /* first we must locate the item. */
02618     if ( (item_p = lookup_lol_subitem(list, sublist, subdesc)) )
02619       {
02620         do_remove_lol_subitem(sublist, item_p);
02621       }
02622   }
02623 
02624 
02625 static void do_remove_lol_item(
02626     struct rsbac_list_lol_reg_item_t * list,
02627     struct rsbac_list_lol_item_t * item_p)
02628   {
02629     struct rsbac_list_item_t     * subitem_p;
02630     struct rsbac_list_item_t     * next_subitem_p;
02631 
02632     if(!list || !item_p)
02633       return;
02634 
02635     if ( (list->head == item_p) )
02636        { /* item is head */
02637          if ( (list->tail == item_p) )
02638            { /* item is head and tail = only item -> list will be empty*/
02639              list->head = NULL;
02640              list->tail = NULL;
02641            }
02642          else
02643            { /* item is head, but not tail -> next item becomes head */
02644 #ifdef CONFIG_RSBAC_DEBUG
02645              if(!item_p->next)
02646                { /* list corrupted! */
02647                  rsbac_printk(KERN_WARNING
02648                         "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02649                         list->name);
02650                }
02651              else
02652 #endif
02653                {
02654                  item_p->next->prev = NULL;
02655                  list->head = item_p->next;
02656                }
02657            }
02658        }
02659     else
02660        { /* item is not head */
02661          if ( (list->tail == item_p) )
02662            { /*item is not head, but tail -> previous item becomes tail*/
02663 #ifdef CONFIG_RSBAC_DEBUG
02664              if(!item_p->prev)
02665                { /* list corrupted! */
02666                  rsbac_printk(KERN_WARNING
02667                         "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02668                         list->name);
02669                }
02670              else
02671 #endif
02672                {
02673                  item_p->prev->next = NULL;
02674                  list->tail = item_p->prev;
02675                }
02676            }
02677          else
02678            { /* item is neither head nor tail -> item is cut out */
02679 #ifdef CONFIG_RSBAC_DEBUG
02680              if(!item_p->prev)
02681                { /* list corrupted! */
02682                  rsbac_printk(KERN_WARNING
02683                         "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02684                         list->name);
02685                }
02686              else
02687              if(!item_p->next)
02688                { /* list corrupted! */
02689                  rsbac_printk(KERN_WARNING
02690                         "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02691                         list->name);
02692                }
02693              else
02694 #endif
02695                {
02696                  item_p->prev->next = item_p->next;
02697                  item_p->next->prev = item_p->prev;
02698                }
02699            }
02700        }
02701     /* curr is no longer valid -> reset */
02702     list->curr=NULL;
02703     /* adjust counter */
02704     list->count--;
02705     /* first remove subitems */
02706     subitem_p = item_p->head;
02707     while(subitem_p)
02708       {
02709         next_subitem_p = subitem_p->next;
02710         rsbac_kfree(subitem_p);
02711         subitem_p = next_subitem_p;
02712       }
02713     /* now we can remove the item from memory */
02714     rsbac_kfree(item_p);    
02715   }
02716 
02717 static void remove_lol_item(
02718     struct rsbac_list_lol_reg_item_t * list,
02719     void * desc)
02720   {
02721     struct rsbac_list_lol_item_t * item_p;
02722 
02723     if(!list || !desc)
02724       return;
02725 
02726     /* first we must locate the item. */
02727     if ( (item_p = lookup_lol_item(list, desc)) )
02728       {
02729         do_remove_lol_item(list, item_p);
02730       }
02731   }
02732 
02733 #ifdef CONFIG_RSBAC_LIST_TRANS
02734 static void ta_do_remove_lol_item(
02735     struct rsbac_list_lol_reg_item_t * list,
02736     struct rsbac_list_lol_item_t * item_p)
02737   {
02738     struct rsbac_list_item_t     * subitem_p;
02739     struct rsbac_list_item_t     * next_subitem_p;
02740 
02741     if(!list || !item_p)
02742       return;
02743 
02744     if ( (list->ta_head == item_p) )
02745        { /* item is head */
02746          if ( (list->ta_tail == item_p) )
02747            { /* item is head and tail = only item -> list will be empty*/
02748              list->ta_head = NULL;
02749              list->ta_tail = NULL;
02750            }
02751          else
02752            { /* item is head, but not tail -> next item becomes head */
02753 #ifdef CONFIG_RSBAC_DEBUG
02754              if(!item_p->next)
02755                { /* list corrupted! */
02756                  rsbac_printk(KERN_WARNING
02757                         "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02758                         list->name);
02759                }
02760              else
02761 #endif
02762                {
02763                  item_p->next->prev = NULL;
02764                  list->ta_head = item_p->next;
02765                }
02766            }
02767        }
02768     else
02769        { /* item is not head */
02770          if ( (list->ta_tail == item_p) )
02771            { /*item is not head, but tail -> previous item becomes tail*/
02772 #ifdef CONFIG_RSBAC_DEBUG
02773              if(!item_p->prev)
02774                { /* list corrupted! */
02775                  rsbac_printk(KERN_WARNING
02776                         "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02777                         list->name);
02778                }
02779              else
02780 #endif
02781                {
02782                  item_p->prev->next = NULL;
02783                  list->ta_tail = item_p->prev;
02784                }
02785            }
02786          else
02787            { /* item is neither head nor tail -> item is cut out */
02788 #ifdef CONFIG_RSBAC_DEBUG
02789              if(!item_p->prev)
02790                { /* list corrupted! */
02791                  rsbac_printk(KERN_WARNING
02792                         "do_remove_lol_item(): list %s corrupted: invalid prev!\n",
02793                         list->name);
02794                }
02795              else
02796              if(!item_p->next)
02797                { /* list corrupted! */
02798                  rsbac_printk(KERN_WARNING
02799                         "do_remove_lol_item(): list %s corrupted: invalid next!\n",
02800                         list->name);
02801                }
02802              else
02803 #endif
02804                {
02805                  item_p->prev->next = item_p->next;
02806                  item_p->next->prev = item_p->prev;
02807                }
02808            }
02809        }
02810     /* curr is no longer valid -> reset */
02811     list->ta_curr=NULL;
02812     /* adjust counter */
02813     list->ta_count--;
02814 
02815     /* remove subitems */
02816     subitem_p = item_p->head;
02817     while(subitem_p)
02818       {
02819         next_subitem_p = subitem_p->next;
02820         rsbac_kfree(subitem_p);
02821         subitem_p = next_subitem_p;
02822       }
02823     /* now we can remove the item from memory */
02824     rsbac_kfree(item_p);    
02825   }
02826 
02827 static void ta_remove_lol_item(
02828     rsbac_list_ta_number_t ta_number,
02829     struct rsbac_list_lol_reg_item_t * list,
02830     void * desc)
02831   {
02832     struct rsbac_list_lol_item_t * item_p;
02833 
02834     if(!list || !desc)
02835       return;
02836 
02837     /* first we must locate the item. */
02838     if ( (item_p = ta_lookup_lol_item(ta_number, list, desc)) )
02839       {
02840         ta_do_remove_lol_item(list, item_p);
02841       }
02842   }
02843 #endif
02844 
02845 static void remove_all_lol_subitems(
02846     struct rsbac_list_lol_item_t     * sublist)
02847     {
02848       struct rsbac_list_item_t     * subitem_p;
02849       struct rsbac_list_item_t     * next_subitem_p;
02850 
02851       /* cleanup all items */
02852       subitem_p = sublist->head;
02853       while(subitem_p)
02854         {
02855           next_subitem_p = subitem_p->next;
02856           rsbac_kfree(subitem_p);
02857           subitem_p = next_subitem_p;
02858         }
02859       sublist->head = NULL;
02860       sublist->tail = NULL;
02861       sublist->curr = NULL;
02862       sublist->count = 0;
02863     }
02864 
02865 static void remove_all_lol_items(struct rsbac_list_lol_reg_item_t * list)
02866     {
02867       struct rsbac_list_lol_item_t * item_p;
02868       struct rsbac_list_lol_item_t * next_item_p;
02869       struct rsbac_list_item_t     * subitem_p;
02870       struct rsbac_list_item_t     * next_subitem_p;
02871 
02872       /* cleanup all items */
02873       item_p = list->head;
02874       while(item_p)
02875         {
02876           /* first remove subitems */
02877           subitem_p = item_p->head;
02878           while(subitem_p)
02879             {
02880               next_subitem_p = subitem_p->next;
02881               rsbac_kfree(subitem_p);
02882               subitem_p = next_subitem_p;
02883             }
02884           next_item_p = item_p->next;
02885           rsbac_kfree(item_p);
02886           item_p = next_item_p;
02887         }
02888       list->head = NULL;
02889       list->tail = NULL;
02890       list->curr = NULL;
02891       list->count = 0;
02892     }
02893 
02894 #ifdef CONFIG_RSBAC_LIST_TRANS
02895 static void ta_remove_all_lol_items(struct rsbac_list_lol_reg_item_t * list)
02896     {
02897       struct rsbac_list_lol_item_t * item_p;
02898       struct rsbac_list_lol_item_t * next_item_p;
02899       struct rsbac_list_item_t     * subitem_p;
02900       struct rsbac_list_item_t     * next_subitem_p;
02901 
02902       /* cleanup all items */
02903       item_p = list->ta_head;
02904       while(item_p)
02905         {
02906           /* first remove subitems */
02907           subitem_p = item_p->head;
02908           while(subitem_p)
02909             {
02910               next_subitem_p = subitem_p->next;
02911               rsbac_kfree(subitem_p);
02912               subitem_p = next_subitem_p;
02913             }
02914           next_item_p = item_p->next;
02915           rsbac_kfree(item_p);
02916           item_p = next_item_p;
02917         }
02918       list->ta_head = NULL;
02919       list->ta_tail = NULL;
02920       list->ta_curr = NULL;
02921       list->ta_count = 0;
02922     }
02923 #endif
02924 
02925 /* Remove registration items */
02926 
02927 /* no locking needed */
02928 static void clear_reg(struct rsbac_list_reg_item_t * item_p)
02929     {
02930       if(item_p)
02931         {
02932           /* now we can remove the item from memory */
02933           remove_all_items(item_p);
02934           if(item_p->def_data)
02935             rsbac_kfree(item_p->def_data);
02936           rsbac_kfree(item_p);
02937         }
02938     }
02939 
02940 /* locking needed */
02941 static void remove_reg(struct rsbac_list_reg_item_t *  handle)
02942     {
02943       struct rsbac_list_reg_item_t * item_p;
02944 
02945       /* first we must locate the item. */
02946       if ( (item_p = lookup_reg(handle)) )
02947         { /* ok, item was found */
02948           /* protect against reuse */
02949           item_p->self = NULL;
02950           if ( (reg_head.head == item_p) )
02951              { /* item is head */
02952                if ( (reg_head.tail == item_p) )
02953                  { /* item is head and tail = only item -> list will be empty*/
02954                    reg_head.head = NULL;
02955                    reg_head.tail = NULL;
02956                  }
02957                else
02958                  { /* item is head, but not tail -> next item becomes head */
02959                    item_p->next->prev = NULL;
02960                    reg_head.head = item_p->next;
02961                  }
02962              }
02963           else
02964              { /* item is not head */
02965                if ( (reg_head.tail == item_p) )
02966                  { /*item is not head, but tail -> previous item becomes tail*/
02967                    item_p->prev->next = NULL;
02968                    reg_head.tail = item_p->prev;
02969                  }
02970                else
02971                  { /* item is neither head nor tail -> item is cut out */
02972                    item_p->prev->next = item_p->next;
02973                    item_p->next->prev = item_p->prev;
02974                  }
02975              }
02976              
02977           /* curr is no longer valid -> reset */
02978           reg_head.curr=NULL;
02979           /* adjust counter */
02980           reg_head.count--;
02981           /* now we can remove the item from memory */
02982           clear_reg(item_p);
02983         }  /* end of if: item was found */
02984     }
02985 
02986 /* no locking needed */
02987 static void clear_lol_reg(struct rsbac_list_lol_reg_item_t * item_p)
02988     {
02989       if(item_p)
02990         {
02991           /* now we can remove the item from memory */
02992           remove_all_lol_items(item_p);
02993           if(item_p->def_data)
02994             rsbac_kfree(item_p->def_data);
02995           if(item_p->def_subdata)
02996             rsbac_kfree(item_p->def_subdata);
02997           rsbac_kfree(item_p);    
02998         }
02999     }
03000 
03001 /* locking needed */
03002 static void remove_lol_reg(struct rsbac_list_lol_reg_item_t *  handle)
03003     {
03004       struct rsbac_list_lol_reg_item_t * item_p;
03005 
03006       /* first we must locate the item. */
03007       if ( (item_p = lookup_lol_reg(handle)) )
03008         { /* ok, item was found */
03009           /* protect against reuse */
03010           item_p->self = NULL;
03011           if ( (lol_reg_head.head == item_p) )
03012              { /* item is head */
03013                if ( (lol_reg_head.tail == item_p) )
03014                  { /* item is head and tail = only item -> list will be empty*/
03015                    lol_reg_head.head = NULL;
03016                    lol_reg_head.tail = NULL;
03017                  }
03018                else
03019                  { /* item is head, but not tail -> next item becomes head */
03020                    item_p->next->prev = NULL;
03021                    lol_reg_head.head = item_p->next;
03022                  };
03023              }
03024           else
03025              { /* item is not head */
03026                if ( (lol_reg_head.tail == item_p) )
03027                  { /*item is not head, but tail -> previous item becomes tail*/
03028                    item_p->prev->next = NULL;
03029                    lol_reg_head.tail = item_p->prev;
03030                  }
03031                else
03032                  { /* item is neither head nor tail -> item is cut out */
03033                    item_p->prev->next = item_p->next;
03034                    item_p->next->prev = item_p->prev;
03035                  }
03036              }
03037              
03038           /* curr is no longer valid -> reset */
03039           lol_reg_head.curr=NULL;
03040           /* adjust counter */
03041           lol_reg_head.count--;
03042           /* now we can remove the item from memory */
03043           clear_lol_reg(item_p);
03044         }  /* end of if: item was found */
03045     }
03046 
03047 #if defined(CONFIG_RSBAC_LIST_REPL)
03048 inline void touch(struct rsbac_list_reg_item_t * list)
03049   {
03050     rsbac_get_current_nanotime(&list->lastchange);
03051   }
03052 #else
03053 #define touch(x)
03054 #endif
03055 
03056 #if defined(CONFIG_RSBAC_LIST_REPL)
03057 inline void lol_touch(struct rsbac_list_lol_reg_item_t * list)
03058   {
03059     rsbac_get_current_nanotime(&list->lastchange);
03060   }
03061 #else
03062 #define lol_touch(x)
03063 #endif
03064 
03065 /********************/
03066 /* Read/Write       */
03067 /********************/
03068 
03069 static int read_list(struct rsbac_list_reg_item_t * list)
03070   {
03071     struct file                   * file_p;
03072     int                             err = 0;
03073     int                             tmperr;
03074     int                             converr;
03075     rsbac_version_t                 list_version;
03076     u_long                          read_count = 0;
03077     u_long                          flags;
03078     char                          * old_buf;
03079     char                          * new_buf;
03080     char                          * old_data;
03081     char                          * new_data;
03082     struct rsbac_list_info_t      * list_info_p;
03083     rsbac_list_count_t              list_count;
03084     rsbac_time_t                    timestamp;
03085     struct rsbac_nanotime_t         lastchange;
03086     rsbac_time_t                    max_age = 0;
03087     rsbac_list_conv_function_t    * conv = NULL;
03088     rsbac_boolean_t                 timeout = FALSE;
03089     mm_segment_t                    oldfs;
03090 
03091     list_info_p = rsbac_kmalloc(sizeof(*list_info_p));
03092     if(!list_info_p)
03093       return -RSBAC_ENOMEM;
03094     file_p = rsbac_kmalloc(sizeof(*file_p));
03095     if(!file_p)
03096       {
03097         rsbac_kfree(list_info_p);
03098         return -RSBAC_ENOMEM;
03099       }
03100     /* open file */
03101     if ((err = rsbac_read_open(list->name,
03102                                file_p,
03103                                list->device) ))
03104       {
03105         rsbac_kfree(list_info_p);
03106         rsbac_kfree(file_p);
03107         return(err);
03108       }
03109 
03110     /* OK, now we can start reading */
03111     /* There is a read function for this file, so check info and read as
03112      * many items as possible. A positive return value means a read success,
03113      * 0 end of file and a negative value an error. */
03114 
03115     /* Set current user space to kernel space, because read() writes */
03116     /* to user space */
03117     oldfs = get_fs();
03118     set_fs(KERNEL_DS);
03119 
03120     /* check gen-list on-disk version */
03121     tmperr = file_p->f_op->read(file_p,
03122                              (__u8 *) &list_version,
03123                              sizeof(list_version),
03124                              &file_p->f_pos);
03125     set_fs(oldfs);
03126     /* error? */
03127     if (tmperr < sizeof(list_version))
03128       {
03129         rsbac_printk(KERN_WARNING
03130                "read_list(): read error from file!\n");
03131         err = -RSBAC_EREADFAILED;
03132         goto end_read;
03133       }
03134     /* if wrong list on-disk version, fail */
03135     switch(list_version)
03136       {
03137         case RSBAC_LIST_DISK_VERSION:
03138         case RSBAC_LIST_DISK_OLD_VERSION:
03139             break;
03140         default:
03141             rsbac_printk(KERN_WARNING
03142                    "read_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
03143                    list_version,
03144                    list->name,
03145                    RSBAC_LIST_DISK_VERSION);
03146             err = -RSBAC_EREADFAILED;
03147             goto end_read;
03148       }
03149 
03150     /* get timestamp */
03151     set_fs(KERNEL_DS);
03152     tmperr = file_p->f_op->read(file_p,
03153                              (__u8 *) &timestamp,
03154                              sizeof(timestamp),
03155                              &file_p->f_pos);
03156     set_fs(oldfs);
03157     /* error? */
03158     if (tmperr < sizeof(timestamp))
03159       {
03160         rsbac_printk(KERN_WARNING
03161                "read_list(): timestamp read error from file %s!\n",
03162                list->name);
03163         err = -RSBAC_EREADFAILED;
03164         goto end_read;
03165       }
03166 
03167     /* get list info */
03168     set_fs(KERNEL_DS);
03169     tmperr = file_p->f_op->read(file_p,
03170                              (__u8 *) list_info_p,
03171                              sizeof(*list_info_p),
03172                              &file_p->f_pos);
03173     set_fs(oldfs);
03174     /* error? */
03175     if (tmperr < sizeof(*list_info_p))
03176       {
03177         rsbac_printk(KERN_WARNING
03178                "read_list(): list info read error from file %s!\n",
03179                list->name);
03180         err = -RSBAC_EREADFAILED;
03181         goto end_read;
03182       }
03183 
03184     /* list timed out? System time is measured in seconds. */
03185     if(   list_info_p->max_age
03186        && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
03187       timeout = TRUE;
03188 
03189     /* Valid key? */
03190     if (list_info_p->key != list->info.key)
03191       {
03192         if(timeout)
03193           {
03194             rsbac_printk(KERN_WARNING
03195                    "read_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
03196                    list->name);
03197             goto end_read;
03198           }
03199         else
03200           {
03201             rsbac_printk(KERN_WARNING
03202                    "read_list(): try to access list %s with wrong key!\n",
03203                    list->name);
03204             err = -EPERM;
03205             goto end_read;
03206           }
03207       }
03208 
03209     /* skip the rest, if ignore is requested */
03210     if(list->flags & RSBAC_LIST_IGNORE_OLD)
03211       goto end_read;
03212 
03213     switch(list_version)
03214       {
03215         case RSBAC_LIST_DISK_VERSION:
03216             set_fs(KERNEL_DS);
03217             tmperr = file_p->f_op->read(file_p,
03218                                         (char *) &lastchange,
03219                                         sizeof(lastchange),
03220                                         &file_p->f_pos);
03221             set_fs(oldfs);
03222             /* error? */
03223             if (tmperr < sizeof(lastchange))
03224               {
03225                 rsbac_printk(KERN_WARNING
03226                              "read_list(): lastchange read error from file %s!\n",
03227                              list->name);
03228                 err = -RSBAC_EREADFAILED;
03229                 goto end_read;
03230               }
03231 #if defined(CONFIG_RSBAC_LIST_REPL)
03232             else
03233               list->lastchange = lastchange;
03234 #endif
03235             break;
03236         case RSBAC_LIST_DISK_OLD_VERSION:
03237             break;
03238         default:
03239             break;
03240       }
03241     /* if wrong list version, try to get_conv */
03242     if(list_info_p->version != list->info.version)
03243       {
03244         if(list->get_conv)
03245           conv = list->get_conv(list_info_p->version);
03246         if(!conv)
03247           {
03248             if(timeout)
03249               {
03250                 rsbac_printk(KERN_WARNING
03251                        "read_list(): accessing timed out list %s without conversion function, ignoring old contents!\n",
03252                        list->name);
03253                 goto end_read;
03254               }
03255             else
03256               {
03257                 /* complain and set error, if ignore is not requested */
03258                 if(!(list->flags & RSBAC_LIST_IGNORE_UNSUPP_VERSION))
03259                   {
03260                     rsbac_printk(KERN_WARNING
03261                            "read_list(): cannot convert list version %u of file %s to version %u!\n",
03262                            list_info_p->version,
03263                            list->name,
03264                            list->info.version);
03265                     err = -RSBAC_EINVALIDVERSION;
03266                   }
03267                 goto end_read;
03268               }
03269           }
03270         else
03271           {
03272             rsbac_printk(KERN_WARNING
03273                    "read_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
03274                    list_info_p->version,
03275                    list->name,
03276                    RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device),
03277                    list->info.version);
03278           }
03279       }
03280     else /* same version needs same sizes */
03281       {
03282         if(   (list_info_p->desc_size != list->info.desc_size)
03283            || (list_info_p->data_size != list->info.data_size)
03284           )
03285           {
03286             if(timeout)
03287               {
03288                 rsbac_printk(KERN_WARNING
03289                        "read_list(): accessing timed out list %s with wrong desc or data size, ignoring old contents!\n",
03290                        list->name);
03291                 goto end_read;
03292               }
03293             else
03294               {
03295                 rsbac_printk(KERN_WARNING
03296                        "read_list(): desc or data size mismatch on list %s!\n",
03297                        list->name);
03298                 err = -RSBAC_EINVALIDVALUE;
03299                 goto end_read;
03300               }
03301           }
03302       }
03303 
03304     /* get list count */
03305     set_fs(KERNEL_DS);
03306     tmperr = file_p->f_op->read(file_p,
03307                              (__u8 *) &list_count,
03308                              sizeof(list_count),
03309                              &file_p->f_pos);
03310     set_fs(oldfs);
03311     /* error? */
03312     if (tmperr < sizeof(list_count))
03313       {
03314         rsbac_printk(KERN_WARNING
03315                "read_list(): list count read error from file %s!\n",
03316                list->name);
03317         err = -RSBAC_EREADFAILED;
03318         goto end_read;
03319       }
03320 
03321     /* alloc mem for old and converted item */
03322     old_buf = rsbac_kmalloc(list_info_p->desc_size + list_info_p->data_size);
03323     if(!old_buf)
03324       {
03325         rsbac_printk(KERN_WARNING
03326                "read_list(): cannot allocate memory!\n");
03327         err = -RSBAC_ENOMEM;
03328         goto end_read;
03329       }
03330     new_buf = rsbac_kmalloc(list->info.desc_size + list->info.data_size);
03331     if(!new_buf)
03332       {
03333         rsbac_printk(KERN_WARNING
03334                "read_list(): cannot allocate memory!\n");
03335         rsbac_kfree(old_buf);
03336         err = -RSBAC_ENOMEM;
03337         goto end_read;
03338       }
03339     /* calculate data pointers */
03340     if(list_info_p->data_size)
03341       old_data = old_buf + list_info_p->desc_size;
03342     else
03343       old_data = NULL;
03344     if(list->info.data_size)
03345       new_data = new_buf + list->info.desc_size;
03346     else
03347       new_data = NULL;
03348 
03349     /* actual reading */
03350     do
03351       {
03352         set_fs(KERNEL_DS);
03353         tmperr = file_p->f_op->read(file_p,
03354                                     (char *) &max_age,
03355                                     sizeof(max_age),
03356                                     &file_p->f_pos);
03357         set_fs(oldfs);
03358         if(conv)
03359           {
03360             set_fs(KERNEL_DS);
03361             tmperr = file_p->f_op->read(file_p,
03362                                      old_buf,
03363                                      list_info_p->desc_size + list_info_p->data_size,
03364                                      &file_p->f_pos);
03365             set_fs(oldfs);
03366             if(tmperr > 0)
03367               { /* convert */
03368                 converr = conv(old_buf, old_data,
03369                                new_buf, new_data);
03370                 if(converr)
03371                   tmperr = converr;
03372               }
03373           }
03374         else
03375           {
03376             set_fs(KERNEL_DS);
03377             tmperr = file_p->f_op->read(file_p,
03378                                      new_buf,
03379                                      list->info.desc_size + list->info.data_size,
03380                                      &file_p->f_pos);
03381             set_fs(oldfs);
03382           }
03383         /* if successful, add item */
03384         if (tmperr > 0)
03385           {
03386             /* wait for write access to list */
03387             rsbac_write_lock(&list->lock, &flags);
03388             add_item(list, max_age, new_buf, new_data);
03389             /* allow access */
03390             rsbac_write_unlock(&list->lock, &flags);
03391             read_count++;
03392 /*
03393 #ifdef CONFIG_RSBAC_DEBUG
03394                 if (rsbac_debug_lists) rsbac_printk(KERN_DEBUG "read_list(): read item %i\n",
03395                      user_aci.id);
03396 #endif
03397 */
03398           }
03399       }
03400     while (tmperr > 0); /* end of do */
03401 
03402     if (tmperr < 0)
03403       {
03404         rsbac_printk(KERN_WARNING "read_list(): read error from file %s!\n",
03405                list->name);
03406         err = -RSBAC_EREADFAILED;
03407       }
03408     rsbac_kfree(old_buf);
03409     rsbac_kfree(new_buf);
03410 
03411     if (read_count != list_count)
03412       {
03413         rsbac_printk(KERN_WARNING "read_list(): read %lu, expected %u items from file %s!\n",
03414                read_count,
03415                list_count,
03416                list->name);
03417         err = -RSBAC_EREADFAILED;
03418       }
03419 
03420 end_read:
03421 
03422 #ifdef CONFIG_RSBAC_DEBUG
03423     if (rsbac_debug_lists)
03424       {
03425         rsbac_printk(KERN_DEBUG "read_list(): %lu entries read.\n",
03426                read_count);
03427       }
03428 #endif
03429     /* We do not need this file any more */
03430     rsbac_read_close(file_p);
03431     rsbac_kfree(list_info_p);
03432     rsbac_kfree(file_p);
03433     return(err);
03434   }
03435 
03436 
03437 static int read_lol_list(struct rsbac_list_lol_reg_item_t * list)
03438   {
03439     struct file                   * file_p;
03440     int                             err = 0;
03441     int                             tmperr;
03442     int                             converr;
03443     rsbac_version_t                 list_version;
03444     u_long                          read_count = 0;
03445     u_long                          flags;
03446     u_long                          sublen;
03447     u_long                          i;
03448     char                          * old_buf;
03449     char                          * new_buf;
03450     char                          * old_data;
03451     char                          * new_data;
03452     char                          * old_subbuf;
03453     char                          * new_subbuf;
03454     char                          * old_subdata;
03455     char                          * new_subdata;
03456     struct rsbac_list_lol_info_t  * list_info_p;
03457     rsbac_list_count_t              list_count;
03458     rsbac_time_t                    timestamp;
03459     struct rsbac_nanotime_t         lastchange;
03460     rsbac_time_t                    max_age = 0;
03461     rsbac_list_conv_function_t    * conv = NULL;
03462     rsbac_list_conv_function_t    * subconv = NULL;
03463     rsbac_boolean_t                 timeout = FALSE;
03464     struct rsbac_list_lol_item_t  * item_p;
03465     mm_segment_t                    oldfs;
03466 
03467     list_info_p = rsbac_kmalloc(sizeof(*list_info_p));
03468     if(!list_info_p)
03469       return -RSBAC_ENOMEM;
03470     file_p = rsbac_kmalloc(sizeof(*file_p));
03471     if(!file_p)
03472       {
03473         rsbac_kfree(list_info_p);
03474         return -RSBAC_ENOMEM;
03475       }
03476     /* open file */
03477     if ((err = rsbac_read_open(list->name,
03478                                file_p,
03479                                list->device) ))
03480       {
03481         rsbac_kfree(list_info_p);
03482         rsbac_kfree(file_p);
03483         return(err);
03484       }
03485 
03486     /* OK, now we can start reading */
03487     /* There is a read function for this file, so check info and read as
03488      * many items as possible. A positive return value means a read success,
03489      * 0 end of file and a negative value an error. */
03490 
03491     /* Set current user space to kernel space, because read() writes */
03492     /* to user space */
03493     oldfs = get_fs();
03494     set_fs(KERNEL_DS);
03495 
03496     /* check gen-list on-disk version */
03497     tmperr = file_p->f_op->read(file_p,
03498                              (__u8 *) &list_version,
03499                              sizeof(list_version),
03500                              &file_p->f_pos);
03501     set_fs(oldfs);
03502     /* error? */
03503     if (tmperr < sizeof(list_version))
03504       {
03505         printk(KERN_WARNING
03506                "read_lol_list(): read error from file!\n");
03507         err = -RSBAC_EREADFAILED;
03508         goto end_read;
03509       }
03510     /* if wrong list on-disk version, fail */
03511     switch(list_version)
03512       {
03513         case RSBAC_LIST_DISK_VERSION:
03514         case RSBAC_LIST_DISK_OLD_VERSION:
03515             break;
03516         default:
03517             rsbac_printk(KERN_WARNING
03518                    "read_lol_list(): wrong on-disk list version %u in file %s, expected %u - error!\n",
03519                    list_version,
03520                    list->name,
03521                    RSBAC_LIST_DISK_VERSION);
03522             err = -RSBAC_EREADFAILED;
03523             goto end_read;
03524       }
03525 
03526     /* get timestamp */
03527     set_fs(KERNEL_DS);
03528     tmperr = file_p->f_op->read(file_p,
03529                              (__u8 *) &timestamp,
03530                              sizeof(timestamp),
03531                              &file_p->f_pos);
03532     set_fs(oldfs);
03533     /* error? */
03534     if (tmperr < sizeof(timestamp))
03535       {
03536         rsbac_printk(KERN_WARNING
03537                "read_lol_list(): timestamp read error from file %s!\n",
03538                list->name);
03539         err = -RSBAC_EREADFAILED;
03540         goto end_read;
03541       }
03542 
03543     /* get list info */
03544     set_fs(KERNEL_DS);
03545     tmperr = file_p->f_op->read(file_p,
03546                              (__u8 *) list_info_p,
03547                              sizeof(*list_info_p),
03548                              &file_p->f_pos);
03549     set_fs(oldfs);
03550     /* error? */
03551     if (tmperr < sizeof(*list_info_p))
03552       {
03553         rsbac_printk(KERN_WARNING
03554                "read_lol_list(): list info read error from file %s!\n",
03555                list->name);
03556         err = -RSBAC_EREADFAILED;
03557         goto end_read;
03558       }
03559 
03560     /* list timed out? System time is measured in seconds. */
03561     if(   list_info_p->max_age
03562        && (timestamp + list_info_p->max_age) <= RSBAC_CURRENT_TIME)
03563       timeout = TRUE;
03564 
03565     /* Valid key? */
03566     if (list_info_p->key != list->info.key)
03567       {
03568         if(timeout)
03569           {
03570             rsbac_printk(KERN_WARNING
03571                    "read_lol_list(): accessing timed out list %s with wrong key, ignoring old contents!\n",
03572                    list->name);
03573             goto end_read;
03574           }
03575         else
03576           {
03577             rsbac_printk(KERN_WARNING
03578                    "read_lol_list(): try to access list %s with wrong key!\n",
03579                    list->name);
03580             err = -EPERM;
03581             goto end_read;
03582           }
03583       }
03584 
03585     /* skip the rest, if ignore is requested */
03586     if(list->flags & RSBAC_LIST_IGNORE_OLD)
03587       goto end_read;
03588 
03589     switch(list_version)
03590       {
03591         case RSBAC_LIST_DISK_VERSION:
03592             set_fs(KERNEL_DS);
03593             tmperr = file_p->f_op->read(file_p,
03594                                         (char *) &lastchange,
03595                                         sizeof(lastchange),
03596                                         &file_p->f_pos);
03597             set_fs(oldfs);
03598             /* error? */
03599             if (tmperr < sizeof(lastchange))
03600               {
03601                 rsbac_printk(KERN_WARNING
03602                              "read_list(): lastchange read error from file %s!\n",
03603                              list->name);
03604                 err = -RSBAC_EREADFAILED;
03605                 goto end_read;
03606               }
03607 #if defined(CONFIG_RSBAC_LIST_REPL)
03608             else
03609               list->lastchange = lastchange;
03610 #endif
03611             break;
03612         case RSBAC_LIST_DISK_OLD_VERSION:
03613             break;
03614         default:
03615             break;
03616       }
03617     /* if wrong list version, try to get_conv */
03618     if(list_info_p->version != list->info.version)
03619       {
03620         if(list->get_conv)
03621           conv = list->get_conv(list_info_p->version);
03622         if(list->get_subconv)
03623           subconv = list->get_subconv(list_info_p->version);
03624         if(!conv || !subconv)
03625           {
03626             if(timeout)
03627               {
03628                 rsbac_printk(KERN_WARNING
03629                        "read_lol_list(): accessing timed out list %s without both conversion functions, ignoring old contents!\n",
03630                        list->name);
03631                 goto end_read;
03632               }
03633             else
03634               {
03635                 /* complain and set error, if ignore is not requested */
03636                 if(!(list->flags & RSBAC_LIST_IGNORE_UNSUPP_VERSION))
03637                   {
03638                     rsbac_printk(KERN_WARNING
03639                            "read_lol_list(): cannot convert list version %u of file %s to version %u!\n",
03640                            list_info_p->version,
03641                            list->name,
03642                            list->info.version);
03643                     err = -RSBAC_EINVALIDVERSION;
03644                   }
03645                 goto end_read;
03646               }
03647           }
03648         else
03649           {
03650             rsbac_printk(KERN_WARNING
03651                    "read_lol_list(): converting list version %u of file %s on device %02u:%02u to version %u!\n",
03652                    list_info_p->version,
03653                    list->name,
03654                    RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device),
03655                    list->info.version);
03656           }
03657       }
03658     else /* same version needs same sizes */
03659       {
03660         if(   (list_info_p->desc_size != list->info.desc_size)
03661            || (list_info_p->data_size != list->info.data_size)
03662            || (list_info_p->subdesc_size != list->info.subdesc_size)
03663            || (list_info_p->subdata_size != list->info.subdata_size)
03664           )
03665           {
03666             if(timeout)
03667               {
03668                 rsbac_printk(KERN_WARNING
03669                        "read_lol_list(): accessing timed out list %s with wrong desc or data size(s), ignoring old contents!\n",
03670                        list->name);
03671                 goto end_read;
03672               }
03673             else
03674               {
03675                 rsbac_printk(KERN_WARNING
03676                        "read_lol_list(): desc or data size mismatch on list %s!\n",
03677                        list->name);
03678                 err = -RSBAC_EINVALIDVALUE;
03679                 goto end_read;
03680               }
03681           }
03682       }
03683 
03684     /* get list count */
03685     set_fs(KERNEL_DS);
03686     tmperr = file_p->f_op->read(file_p,
03687                              (__u8 *) &list_count,
03688                              sizeof(list_count),
03689                              &file_p->f_pos);
03690     set_fs(oldfs);
03691     /* error? */
03692     if (tmperr < sizeof(list_count))
03693       {
03694         rsbac_printk(KERN_WARNING
03695                "read_lol_list(): list count read error from file %s!\n",
03696                list->name);
03697         err = -RSBAC_EREADFAILED;
03698         goto end_read;
03699       }
03700 
03701     /* alloc mem for old and converted items */
03702     old_buf = rsbac_kmalloc(list_info_p->desc_size + list_info_p->data_size);
03703     if(!old_buf)
03704       {
03705         rsbac_printk(KERN_WARNING
03706                "read_lol_list(): cannot allocate memory!\n");
03707         err = -RSBAC_ENOMEM;
03708         goto end_read;
03709       }
03710     new_buf = rsbac_kmalloc(list->info.desc_size + list->info.data_size);
03711     if(!new_buf)
03712       {
03713         rsbac_printk(KERN_WARNING
03714                "read_lol_list(): cannot allocate memory!\n");
03715         rsbac_kfree(old_buf);
03716         err = -RSBAC_ENOMEM;
03717         goto end_read;
03718       }
03719     old_subbuf = rsbac_kmalloc(list_info_p->subdesc_size + list_info_p->subdata_size);
03720     if(!old_subbuf)
03721       {
03722         rsbac_printk(KERN_WARNING
03723                "read_lol_list(): cannot allocate memory!\n");
03724         rsbac_kfree(old_buf);
03725         rsbac_kfree(new_buf);
03726         err = -RSBAC_ENOMEM;
03727         goto end_read;
03728       }
03729     new_subbuf = rsbac_kmalloc(list->info.subdesc_size + list->info.subdata_size);
03730     if(!new_subbuf)
03731       {
03732         rsbac_printk(KERN_WARNING
03733                "read_lol_list(): cannot allocate memory!\n");
03734         rsbac_kfree(old_buf);
03735         rsbac_kfree(new_buf);
03736         rsbac_kfree(old_subbuf);
03737         err = -RSBAC_ENOMEM;
03738         goto end_read;
03739       }
03740     /* calculate data pointers */
03741     if(list_info_p->data_size)
03742       old_data = old_buf + list_info_p->desc_size;
03743     else
03744       old_data = NULL;
03745     if(list->info.data_size)
03746       new_data = new_buf + list->info.desc_size;
03747     else
03748       new_data = NULL;
03749     if(list_info_p->subdata_size)
03750       old_subdata = old_subbuf + list_info_p->subdesc_size;
03751     else
03752       old_subdata = NULL;
03753     if(list->info.subdata_size)
03754       new_subdata = new_subbuf + list->info.subdesc_size;
03755     else
03756       new_subdata = NULL;
03757 
03758     /* actual reading */
03759     do
03760       {
03761         set_fs(KERNEL_DS);
03762         tmperr = file_p->f_op->read(file_p,
03763                                     (char *) &max_age,
03764                                     sizeof(max_age),
03765                                     &file_p->f_pos);
03766         set_fs(oldfs);
03767         if(conv)
03768           {
03769             set_fs(KERNEL_DS);
03770             tmperr = file_p->f_op->read(file_p,
03771                                      old_buf,
03772                                      list_info_p->desc_size + list_info_p->data_size,
03773                                      &file_p->f_pos);
03774             set_fs(oldfs);
03775             if(tmperr > 0)
03776               { /* convert */
03777                 converr = conv(old_buf, old_data,
03778                                new_buf, new_data);
03779                 if(converr)
03780                   tmperr = converr;
03781               }
03782           }
03783         else
03784           {
03785             set_fs(KERNEL_DS);
03786             tmperr = file_p->f_op->read(file_p,
03787                                      new_buf,
03788                                      list->info.desc_size + list->info.data_size,
03789                                      &file_p->f_pos);
03790             set_fs(oldfs);
03791           }
03792         /* if successful, add item */
03793         if (tmperr > 0)
03794           {
03795             /* wait for write access to list */
03796             rsbac_write_lock(&list->lock, &flags);
03797             item_p = add_lol_item(list, max_age, new_buf, new_data);
03798             /* allow access */
03799             rsbac_write_unlock(&list->lock, &flags);
03800             if(!item_p)
03801               {
03802                 err = -RSBAC_ENOMEM;
03803                 goto end_read_free;
03804               }
03805             read_count++;
03806 /*
03807 #ifdef CONFIG_RSBAC_DEBUG
03808                 if (rsbac_debug_lists) rsbac_printk(KERN_DEBUG "read_lol_list(): read item %i\n",
03809                      user_aci.id);
03810 #endif
03811 */
03812             set_fs(KERNEL_DS);
03813             tmperr = file_p->f_op->read(file_p,
03814                                      (__u8 *) &sublen,
03815                                      sizeof(sublen),
03816                                      &file_p->f_pos);
03817             set_fs(oldfs);
03818             /* if successful, read and add sublen subitems */
03819             if (tmperr > 0)
03820               {
03821                 for(i=0;i<sublen;i++)
03822                   {
03823                     set_fs(KERNEL_DS);
03824                     tmperr = file_p->f_op->read(file_p,
03825                                                 (char *) &max_age,
03826                                                 sizeof(max_age),
03827                                                 &file_p->f_pos);
03828                     set_fs(oldfs);
03829                     if(subconv)
03830                       {
03831                         set_fs(KERNEL_DS);
03832                         tmperr = file_p->f_op->read(file_p,
03833                                                  old_subbuf,
03834                                                  list_info_p->subdesc_size + list_info_p->subdata_size,
03835                                                  &file_p->f_pos);
03836                         set_fs(oldfs);
03837                         if(tmperr > 0)
03838                           { /* convert */
03839                             converr = subconv(old_subbuf, old_subdata,
03840                                               new_subbuf, new_subdata);
03841                             if(converr)
03842                               tmperr = converr;
03843                           }
03844                       }
03845                     else
03846                       {
03847                         set_fs(KERNEL_DS);
03848                         tmperr = file_p->f_op->read(file_p,
03849                                                  new_subbuf,
03850                                                  list->info.subdesc_size + list->info.subdata_size,
03851                                                  &file_p->f_pos);
03852                         set_fs(oldfs);
03853                       }
03854                     if(tmperr > 0)
03855                       {
03856                         /* wait for write access to list */
03857                         rsbac_write_lock(&list->lock, &flags);
03858                         if (!add_lol_subitem(list,
03859                                              item_p,
03860                                              max_age,
03861                                              new_subbuf,
03862                                              new_subdata))
03863                           {
03864                             rsbac_printk(KERN_WARNING
03865                                    "read_lol_list(): could not add subitem!\n");
03866                             i = sublen;
03867                             tmperr = -1;
03868                           }
03869                         /* allow access */
03870                         rsbac_write_unlock(&list->lock, &flags);
03871                       }
03872                     else
03873                       {
03874                         i = sublen;
03875                         tmperr = -1;
03876                       }
03877                   }
03878               }
03879           }
03880       }
03881     while (tmperr > 0); /* end of do */
03882 
03883     if (tmperr < 0)
03884       {
03885         rsbac_printk(KERN_WARNING "read_lol_list(): read error from file %s!\n",
03886                list->name);
03887         err = -RSBAC_EREADFAILED;
03888       }
03889 
03890     if (read_count != list_count)
03891       {
03892         rsbac_printk(KERN_WARNING "read_lol_list(): read %lu, expected %u items from file %s!\n",
03893                read_count,
03894                list_count,
03895                list->name);
03896         err = -RSBAC_EREADFAILED;
03897       }
03898 
03899 end_read_free:
03900     rsbac_kfree(old_buf);
03901     rsbac_kfree(new_buf);
03902     rsbac_kfree(old_subbuf);
03903     rsbac_kfree(new_subbuf);
03904 
03905 end_read:
03906 
03907 #ifdef CONFIG_RSBAC_DEBUG
03908     if (rsbac_debug_lists)
03909       {
03910         rsbac_printk(KERN_DEBUG "read_lol_list(): %lu entries read.\n",
03911                read_count);
03912       }
03913 #endif
03914     /* We do not need this file any more */
03915     rsbac_read_close(file_p);
03916     rsbac_kfree(list_info_p);
03917     rsbac_kfree(file_p);
03918     return(err);
03919   } /* end of read_lol_list() */
03920 
03921 
03922 #ifndef CONFIG_RSBAC_NO_WRITE
03923 static int fill_buffer(struct rsbac_list_reg_item_t * list,
03924                        struct rsbac_list_write_item_t ** write_item_pp)
03925   {
03926     struct rsbac_list_write_item_t * write_item_p;
03927     struct rsbac_list_item_t * current_p;
03928            u_long              flags;
03929            char              * buffer = NULL;
03930            u_long              buflen;
03931            u_long              write_count = 0;
03932            rsbac_boolean_t     vmalloc_used = FALSE;
03933            rsbac_version_t     list_version = RSBAC_LIST_DISK_VERSION;
03934            rsbac_time_t        timestamp = RSBAC_CURRENT_TIME;
03935 
03936     write_item_p = rsbac_kmalloc(sizeof(*write_item_p));
03937     if(!write_item_p)
03938       {
03939         *write_item_pp = NULL;
03940         return(-RSBAC_ENOMEM);
03941       }
03942 
03943     /* protect this list */
03944     rsbac_read_lock(&list->lock, &flags);
03945     /* allocate mem */
03946     buflen =   sizeof(list_version)
03947              + sizeof(timestamp)
03948              + sizeof(list->info)
03949              + sizeof(list->lastchange)
03950              + sizeof(list->count)
03951              + list->count * (sizeof(current_p->max_age) + list->info.desc_size + list->info.data_size);
03952     /* try to rsbac_vkmalloc */
03953     buffer = (char *) rsbac_vkmalloc(buflen, &vmalloc_used);
03954     if(!buffer)
03955       {
03956         /* unprotect this list */
03957         rsbac_read_unlock(&list->lock, &flags);
03958         rsbac_kfree(write_item_p);
03959         *write_item_pp = NULL;
03960         return(-RSBAC_ENOMEM);
03961       }
03962     /* copy version */
03963     memcpy(buffer,
03964            (char *) &list_version,
03965            sizeof(list_version));
03966     write_count = sizeof(list_version);
03967     /* copy timestamp */
03968     memcpy(buffer+write_count,
03969            (char *) &timestamp,
03970            sizeof(timestamp));
03971     write_count += sizeof(timestamp);
03972     /* copy info */
03973     memcpy(buffer+write_count,
03974            (char *) &list->info,
03975            sizeof(list->info));
03976     write_count += sizeof(list->info);
03977     /* copy lastchange */
03978     memcpy(buffer+write_count,
03979            (char *) &list->lastchange,
03980            sizeof(list->lastchange));
03981     write_count += sizeof(list->lastchange);
03982     /* copy count */
03983     memcpy(buffer+write_count,
03984            (char *) &list->count,
03985            sizeof(list->count));
03986     write_count += sizeof(list->count);
03987     /* copy list */
03988     current_p = list->head;
03989     while (current_p) 
03990       {
03991         memcpy(buffer+write_count,
03992                &current_p->max_age,
03993                sizeof(current_p->max_age));
03994         write_count += sizeof(current_p->max_age);
03995         memcpy(buffer+write_count,
03996                ((char *) current_p) + sizeof(*current_p),
03997                list->info.desc_size + list->info.data_size);
03998         write_count += list->info.desc_size + list->info.data_size;
03999         current_p = current_p->next;
04000       }
04001 
04002     /* fill write_item */
04003     write_item_p->prev = NULL;
04004     write_item_p->next = NULL;
04005     write_item_p->list = list;
04006     write_item_p->buflen = write_count;
04007     write_item_p->buf = buffer;
04008     write_item_p->vmalloc_used = vmalloc_used;
04009     strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
04010     write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
04011     write_item_p->device = list->device;
04012 
04013     *write_item_pp = write_item_p;
04014 
04015     /* unprotect this list */
04016     rsbac_read_unlock(&list->lock, &flags);
04017 
04018     return 0;
04019   }
04020 
04021 static int rsbac_list_write_buffers(struct rsbac_list_write_head_t write_head,
04022                          rsbac_boolean_t need_lock)
04023   {
04024     struct file              * file_p;
04025            int                 count = 0;
04026            mm_segment_t        oldfs;
04027            u_long              written;
04028            u_long              bytes;
04029            int                 tmperr = 0;
04030     struct rsbac_list_write_item_t * write_item_p;
04031     struct rsbac_list_write_item_t * next_item_p;
04032 
04033     file_p = rsbac_kmalloc(sizeof(*file_p));
04034     if(!file_p)
04035       {
04036         return -RSBAC_ENOMEM;
04037       }
04038     write_item_p = write_head.head;
04039     while(write_item_p)
04040       {
04041     #ifdef CONFIG_RSBAC_DEBUG
04042         if (rsbac_debug_write)
04043           {
04044             rsbac_printk(KERN_DEBUG "rsbac_list_write_buffers(): write list %s on device %02u:%02u.\n",
04045                    write_item_p->name,
04046                    RSBAC_MAJOR(write_item_p->device),
04047                    RSBAC_MINOR(write_item_p->device));
04048           }
04049     #endif
04050         if(need_lock)
04051           lock_kernel();
04052         /* open file */
04053         if ((tmperr = rsbac_write_open(write_item_p->name,
04054                                        file_p,
04055                                        write_item_p->device) ))
04056           {
04057             if(tmperr != -RSBAC_ENOTWRITABLE)
04058               {
04059                 rsbac_printk(KERN_WARNING
04060                        "rsbac_list_write_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
04061                        write_item_p->name,
04062                        RSBAC_MAJOR(write_item_p->device),
04063                        RSBAC_MINOR(write_item_p->device),
04064                        tmperr);
04065               }
04066             count = tmperr;
04067             goto free_item;
04068           }
04069 
04070         /* OK, now we can start writing the buffer. */
04071         /* Set current user space to kernel space, because write() reads    */
04072         /* from user space */
04073         oldfs = get_fs();
04074         set_fs(KERNEL_DS);
04075     
04076         written = 0;
04077         while ((written < write_item_p->buflen) && (tmperr >= 0)) 
04078           {
04079             bytes = rsbac_min(write_item_p->buflen - written, RSBAC_MAX_WRITE_CHUNK);
04080             tmperr = file_p->f_op->write(file_p,
04081                                       write_item_p->buf + written,
04082                                       bytes,
04083                                       &file_p->f_pos);
04084             if(tmperr > 0)
04085               {
04086                 written += tmperr;
04087               }
04088           }
04089         if (tmperr < 0)
04090           {
04091             rsbac_printk(KERN_WARNING
04092                    "rsbac_list_write_buffers(): write error %i on device %02u:%02u file %s!\n",
04093                    tmperr,
04094                    RSBAC_MAJOR(write_item_p->device),
04095                    RSBAC_MINOR(write_item_p->device),
04096                    write_item_p->name);
04097             if(write_item_p->list->self == write_item_p->list)
04098               write_item_p->list->dirty = TRUE;
04099           }
04100         else
04101           count++;
04102 
04103         /* Set current user space back to user space, because write() reads */
04104         /* from user space */
04105         set_fs(oldfs);
04106     
04107     #ifdef CONFIG_RSBAC_DEBUG
04108         if (rsbac_debug_write)
04109           {
04110             rsbac_printk(KERN_DEBUG "rsbac_list_write_buffers(): %lu bytes written.\n",
04111                    written);
04112           }
04113     #endif
04114         /* End of write access */
04115         rsbac_write_close(file_p);
04116 
04117 free_item:
04118         if(need_lock)
04119           unlock_kernel();
04120         /* free buffer */
04121         rsbac_vkfree(write_item_p->buf, write_item_p->vmalloc_used);
04122         next_item_p = write_item_p->next;
04123         rsbac_kfree(write_item_p);
04124         write_item_p = next_item_p;
04125       }
04126     /* Ready. */
04127     rsbac_kfree(file_p);
04128     return count;
04129   }
04130 
04131 static int fill_lol_buffer(struct rsbac_list_lol_reg_item_t * list,
04132                            struct rsbac_list_lol_write_item_t ** write_item_pp)
04133   {
04134     struct rsbac_list_lol_write_item_t * write_item_p;
04135     struct rsbac_list_lol_item_t       * current_p;
04136     struct rsbac_list_item_t           * sub_p;
04137            u_long              flags;
04138            char              * buffer = NULL;
04139            u_long              buflen;
04140            u_long              write_count = 0;
04141            rsbac_boolean_t     vmalloc_used = FALSE;
04142            rsbac_version_t     list_version = RSBAC_LIST_DISK_VERSION;
04143            rsbac_time_t        timestamp = RSBAC_CURRENT_TIME;
04144 
04145     write_item_p = rsbac_kmalloc(sizeof(*write_item_p));
04146     if(!write_item_p)
04147       {
04148         *write_item_pp = NULL;
04149         return(-RSBAC_ENOMEM);
04150       }
04151 
04152     /* protect this list */
04153     rsbac_read_lock(&list->lock, &flags);
04154 
04155     /* allocate mem */
04156     buflen =   sizeof(list_version)
04157              + sizeof(timestamp)
04158              + sizeof(list->info)
04159              + sizeof(list->lastchange)
04160              + sizeof(list->count)
04161              + list->count * (sizeof(current_p->max_age) + list->info.desc_size + list->info.data_size);
04162     current_p = list->head;
04163     while(current_p)
04164       {
04165         buflen += sizeof(current_p->count);
04166         buflen += current_p->count * (sizeof(current_p->max_age) + list->info.subdesc_size + list->info.subdata_size);
04167         current_p = current_p->next;
04168       }
04169     /* try to rsbac_vkmalloc */
04170     buffer = (char *) rsbac_vkmalloc(buflen, &vmalloc_used);
04171     if(!buffer)
04172       {
04173         /* unprotect this list */
04174         rsbac_read_unlock(&list->lock, &flags);
04175         rsbac_kfree(write_item_p);
04176         *write_item_pp = NULL;
04177         return(-RSBAC_ENOMEM);
04178       }
04179     /* copy version */
04180     memcpy(buffer,
04181            (char *) &list_version,
04182            sizeof(list_version));
04183     write_count = sizeof(list_version);
04184     /* copy timestamp */
04185     memcpy(buffer+write_count,
04186            (char *) &timestamp,
04187            sizeof(timestamp));
04188     write_count += sizeof(timestamp);
04189     /* copy info */
04190     memcpy(buffer+write_count,
04191            (char *) &list->info,
04192            sizeof(list->info));
04193     write_count += sizeof(list->info);
04194     /* copy lastchange */
04195     memcpy(buffer+write_count,
04196            (char *) &list->lastchange,
04197            sizeof(list->lastchange));
04198     write_count += sizeof(list->lastchange);
04199     /* copy count */
04200     memcpy(buffer+write_count,
04201            (char *) &list->count,
04202            sizeof(list->count));
04203     write_count += sizeof(list->count);
04204     /* copy list */
04205     current_p = list->head;
04206     while (current_p) 
04207       {
04208         memcpy(buffer+write_count,
04209                &current_p->max_age,
04210                sizeof(current_p->max_age));
04211         write_count += sizeof(current_p->max_age);
04212         memcpy(buffer+write_count,
04213                ((char *) current_p) + sizeof(*current_p),
04214                list->info.desc_size + list->info.data_size);
04215         write_count += list->info.desc_size + list->info.data_size;
04216         memcpy(buffer+write_count,
04217                &current_p->count,
04218                sizeof(current_p->count));
04219         write_count += sizeof(current_p->count);
04220         /* copy subitems */
04221         sub_p = current_p->head;
04222         while (sub_p) 
04223           {
04224             memcpy(buffer+write_count,
04225                    &sub_p->max_age,
04226                    sizeof(sub_p->max_age));
04227             write_count += sizeof(sub_p->max_age);
04228             memcpy(buffer+write_count,
04229                    ((char *) sub_p) + sizeof(*sub_p),
04230                    list->info.subdesc_size + list->info.subdata_size);
04231             write_count += list->info.subdesc_size + list->info.subdata_size;
04232             sub_p = sub_p->next;
04233           }
04234         current_p = current_p->next;
04235       }
04236 
04237     /* fill write_item */
04238     write_item_p->prev = NULL;
04239     write_item_p->next = NULL;
04240     write_item_p->list = list;
04241     write_item_p->buflen = write_count;
04242     write_item_p->buf = buffer;
04243     write_item_p->vmalloc_used = vmalloc_used;
04244     strncpy(write_item_p->name, list->name, RSBAC_LIST_MAX_FILENAME);
04245     write_item_p->name[RSBAC_LIST_MAX_FILENAME] = 0;
04246     write_item_p->device = list->device;
04247     *write_item_pp = write_item_p;
04248 
04249     /* unprotect this list */
04250     rsbac_read_unlock(&list->lock, &flags);
04251 
04252     return 0;
04253   }
04254 
04255 static int rsbac_list_write_lol_buffers(struct rsbac_list_lol_write_head_t write_head,
04256                              rsbac_boolean_t need_lock)
04257   {
04258     struct file              * file_p;
04259            int                 count = 0;
04260            mm_segment_t        oldfs;
04261            u_long              written;
04262            u_long              bytes;
04263            int                 tmperr = 0;
04264     struct rsbac_list_lol_write_item_t * write_item_p;
04265     struct rsbac_list_lol_write_item_t * next_item_p;
04266 
04267     file_p = rsbac_kmalloc(sizeof(*file_p));
04268     if(!file_p)
04269       {
04270         return -RSBAC_ENOMEM;
04271       }
04272     write_item_p = write_head.head;
04273     while(write_item_p)
04274       {
04275     #ifdef CONFIG_RSBAC_DEBUG
04276         if (rsbac_debug_write)
04277           {
04278             rsbac_printk(KERN_DEBUG "rsbac_list_write_lol_buffers(): write list %s on device %02u:%02u.\n",
04279                    write_item_p->name,
04280                    RSBAC_MAJOR(write_item_p->device),
04281                    RSBAC_MINOR(write_item_p->device));
04282           }
04283     #endif
04284         if(need_lock)
04285           lock_kernel();
04286         /* open file */
04287         if ((tmperr = rsbac_write_open(write_item_p->name,
04288                                        file_p,
04289                                        write_item_p->device) ))
04290           {
04291             if(tmperr != -RSBAC_ENOTWRITABLE)
04292               {
04293                 rsbac_printk(KERN_WARNING
04294                        "rsbac_list_write_lol_buffers(): opening file %s on device %02u:%02u failed with error %i!\n",
04295                        write_item_p->name,
04296                        RSBAC_MAJOR(write_item_p->device),
04297                        RSBAC_MINOR(write_item_p->device),
04298                        tmperr);
04299               }
04300             goto free_item;
04301           }
04302     
04303         /* OK, now we can start writing the buffer. */
04304         /* Set current user space to kernel space, because write() reads    */
04305         /* from user space */
04306         oldfs = get_fs();
04307         set_fs(KERNEL_DS);
04308     
04309         written = 0;
04310         while ((written < write_item_p->buflen) && (tmperr >= 0)) 
04311           {
04312             bytes = rsbac_min(write_item_p->buflen - written, RSBAC_MAX_WRITE_CHUNK);
04313             tmperr = file_p->f_op->write(file_p,
04314                                       write_item_p->buf + written,
04315                                       bytes,
04316                                       &file_p->f_pos);
04317             if(tmperr > 0)
04318               {
04319                 written += tmperr;
04320               }
04321           }
04322         if (tmperr < 0)
04323           {
04324             rsbac_printk(KERN_WARNING
04325                    "rsbac_list_write_lol_buffers(): write error %i on device %02u:%02u file %s!\n",
04326                    tmperr,
04327                    RSBAC_MAJOR(write_item_p->device),
04328                    RSBAC_MINOR(write_item_p->device),
04329                    write_item_p->name);
04330             if(write_item_p->list->self == write_item_p->list)
04331               write_item_p->list->dirty = TRUE;
04332           }
04333         else
04334           count++;
04335 
04336         /* Set current user space back to user space, because write() reads */
04337         /* from user space */
04338         set_fs(oldfs);
04339     
04340     #ifdef CONFIG_RSBAC_DEBUG
04341         if (rsbac_debug_write)
04342           {
04343             rsbac_printk(KERN_DEBUG "rsbac_list_write_lol_buffers(): %lu bytes written.\n",
04344                    written);
04345           }
04346     #endif
04347         /* End of write access */
04348         rsbac_write_close(file_p);
04349 
04350 free_item:
04351         if(need_lock)
04352           unlock_kernel();
04353         /* free buffer */
04354         rsbac_vkfree(write_item_p->buf, write_item_p->vmalloc_used);
04355         next_item_p = write_item_p->next;
04356         rsbac_kfree(write_item_p);
04357         write_item_p = next_item_p;
04358       }
04359     /* Ready. */
04360     rsbac_kfree(file_p);
04361     return count;
04362   }
04363 #endif /* ifndef CONFIG_RSBAC_NO_WRITE */
04364 
04365 
04366 /************************************************* */
04367 /*           PROC support                          */
04368 /************************************************* */
04369 
04370 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
04371 static int
04372 lists_proc_info(char *buffer, char **start, off_t offset, int length)
04373 {
04374   int len = 0;
04375   off_t pos   = 0;
04376   off_t begin = 0;
04377 
04378   union rsbac_target_id_t            rsbac_target_id;
04379   union rsbac_attribute_value_t      rsbac_attribute_value;
04380   struct rsbac_list_reg_item_t     * item_p;
04381   struct rsbac_list_lol_reg_item_t * lol_item_p;
04382          u_long                      flags;
04383 
04384   if (!rsbac_is_initialized())
04385     return (-ENOSYS);
04386 
04387 #ifdef CONFIG_RSBAC_DEBUG
04388   if (rsbac_debug_aef)
04389     {
04390       rsbac_printk(KERN_DEBUG "lists_proc_info(): calling ADF\n");
04391     }
04392 #endif
04393   rsbac_target_id.scd = ST_rsbac;
04394   rsbac_attribute_value.dummy = 0;
04395   if (!rsbac_adf_request(R_GET_STATUS_DATA,
04396                          current->pid,
04397                          T_SCD,
04398                          rsbac_target_id,
04399                          A_none,
04400                          rsbac_attribute_value))
04401     {
04402       return -EPERM;
04403     }
04404 
04405   len += sprintf(buffer, "Generic Lists Status\n--------------------\n");
04406 #ifdef CONFIG_RSBAC_LIST_TRANS
04407   if(rsbac_list_count(ta_handle) > 0)
04408     {
04409       int list_count;
04410       rsbac_list_ta_number_t * desc_array;
04411       struct rsbac_list_ta_data_t data;
04412 
04413       len += sprintf(buffer+len, "Transactions active:\n\n");
04414       pos = begin + len;
04415       if (pos < offset)
04416         {
04417           len = 0;
04418           begin = pos;
04419         }
04420       if (pos > offset+length)
04421         goto out;
04422 
04423       list_count = rsbac_list_get_all_desc(ta_handle, (void **) &desc_array);
04424       if(list_count > 0)
04425         {
04426           int i;
04427           rsbac_time_t now = RSBAC_CURRENT_TIME;
04428 
04429           for(i=0; i<list_count; i++)
04430             {
04431               if(!rsbac_list_get_data(ta_handle, &desc_array[i], &data))
04432                 {
04433                   len += sprintf(buffer+len, "%u (ttl %is)\n",
04434                                  desc_array[i], data.timeout - now);
04435                   pos = begin + len;
04436                   if (pos < offset)
04437                     {
04438                       len = 0;
04439                       begin = pos;
04440                     }
04441                   if (pos > offset+length)
04442                     goto out;
04443                 }
04444             }
04445           rsbac_vfree(desc_array);
04446         }
04447 
04448       len += sprintf(buffer+len, "\nLists in Transaction\n--------------------\nName\t\tdevice\tta\t     count\n");
04449       pos = begin + len;
04450       if (pos < offset)
04451         {
04452           len = 0;
04453           begin = pos;
04454         }
04455       if (pos > offset+length)
04456         goto out;
04457 
04458       list_count = 0;
04459       rsbac_read_lock(&reg_head.lock, &flags);
04460       item_p=reg_head.head;
04461       while(item_p)
04462         {
04463           if(item_p->ta_copied)
04464             {
04465               len += sprintf(buffer + len, "%-16s%02u:%02u\t%10u\t%u\n",
04466                              item_p->name,
04467                              RSBAC_MAJOR(item_p->device), RSBAC_MINOR(item_p->device),
04468                              item_p->ta_copied,
04469                              item_p->ta_count);
04470               pos = begin + len;
04471               if (pos < offset)
04472                 {
04473                   len = 0;
04474                   begin = pos;
04475                 }
04476               if (pos > offset+length)
04477                 {
04478                   rsbac_read_unlock(&reg_head.lock, &flags);
04479                   goto out;
04480                 }
04481               list_count++;
04482             }
04483           item_p = item_p->next;
04484         }
04485       rsbac_read_unlock(&reg_head.lock, &flags);
04486 
04487       len += sprintf(buffer + len, "\n %u lists in transaction.\n\n",
04488                      list_count);
04489       pos = begin + len;
04490       if (pos < offset)
04491         {
04492           len = 0;
04493           begin = pos;
04494         }
04495       if (pos > offset+length)
04496         goto out;
04497 
04498       len += sprintf(buffer+len, "Lists of Lists in Transaction\n-----------------------------\nName\t\tdevice\tta\t     count\n");
04499       pos = begin + len;
04500       if (pos < offset)
04501         {
04502           len = 0;
04503           begin = pos;
04504         }
04505       if (pos > offset+length)
04506         goto out;
04507 
04508       list_count = 0;
04509       rsbac_read_lock(&lol_reg_head.lock, &flags);
04510       lol_item_p=lol_reg_head.head;
04511       while(lol_item_p)
04512         {
04513           if(lol_item_p->ta_copied)
04514             {
04515               len += sprintf(buffer + len, "%-16s%02u:%02u\t%10u\t%u\n",
04516                              lol_item_p->name,
04517                              RSBAC_MAJOR(lol_item_p->device), RSBAC_MINOR(lol_item_p->device),
04518                              lol_item_p->ta_copied,
04519                              lol_item_p->ta_count);
04520               pos = begin + len;
04521               if (pos < offset)
04522                 {
04523                   len = 0;
04524                   begin = pos;
04525                 }
04526               if (pos > offset+length)
04527                 {
04528                   rsbac_read_unlock(&lol_reg_head.lock, &flags);
04529                   goto out;
04530                 }
04531               list_count++;
04532             }
04533           lol_item_p = lol_item_p->next;
04534         }
04535       rsbac_read_unlock(&lol_reg_head.lock, &flags);
04536 
04537       len += sprintf(buffer + len, "\n %u lists of lists in transaction.\n\n\n",
04538                      list_count);
04539       pos = begin + len;
04540       if (pos < offset)
04541         {
04542           len = 0;
04543           begin = pos;
04544         }
04545       if (pos > offset+length)
04546         goto out;
04547     }
04548   else
04549     len += sprintf(buffer+len, "No active transaction\n\n");
04550   pos = begin + len;
04551   if (pos < offset)
04552     {
04553       len = 0;
04554       begin = pos;
04555     }
04556   if (pos > offset+length)
04557     goto out;
04558 #endif
04559 
04560   len += sprintf(buffer+len, "Registered Generic Lists\n------------------------\nName\t\tdevice\tcount\tdesc\tdata\tpersist\tnowrite\tflags\tdirty\n");
04561   pos = begin + len;
04562   if (pos < offset)
04563     {
04564       len = 0;
04565       begin = pos;
04566     }
04567   if (pos > offset+length)
04568     goto out;
04569 
04570   rsbac_read_lock(&reg_head.lock, &flags);
04571   item_p=reg_head.head;
04572   while(item_p)
04573     {
04574       len += sprintf(buffer + len, "%-16s%02u:%02u\t%u\t%u\t%u\t%u\t%u\t%u\t%u\n",
04575                      item_p->name,
04576                      RSBAC_MAJOR(item_p->device), RSBAC_MINOR(item_p->device),
04577                      item_p->count,
04578                      item_p->info.desc_size,
04579                      item_p->info.data_size,
04580                      item_p->flags & RSBAC_LIST_PERSIST,
04581                      item_p->no_write,
04582                      item_p->flags,
04583                      item_p->dirty & (item_p->flags & RSBAC_LIST_PERSIST));
04584       pos = begin + len;
04585       if (pos < offset)
04586         {
04587           len = 0;
04588           begin = pos;
04589         }
04590       if (pos > offset+length)
04591         {
04592           rsbac_read_unlock(&reg_head.lock, &flags);
04593           goto out;
04594         }
04595       item_p = item_p->next;
04596     }
04597   rsbac_read_unlock(&reg_head.lock, &flags);
04598 
04599   len += sprintf(buffer + len, "\n %u lists registered.\n\n",
04600                  reg_head.count);
04601   pos = begin + len;
04602   if (pos < offset)
04603     {
04604       len = 0;
04605       begin = pos;
04606     }
04607   if (pos > offset+length)
04608     goto out;
04609 
04610   len += sprintf(buffer + len, "Registered Generic Lists of Lists\n---------------------------------\nName\t\tdevice\tcount\tdesc\tdata\tpersist\tnowrite\tflags\tdirty\n");
04611   pos = begin + len;
04612   if (pos < offset)
04613     {
04614       len = 0;
04615       begin = pos;
04616     }
04617   if (pos > offset+length)
04618     goto out;
04619 
04620   rsbac_read_lock(&lol_reg_head.lock, &flags);
04621   lol_item_p=lol_reg_head.head;
04622   while(lol_item_p)
04623     {
04624       len += sprintf(buffer + len, "%-16s%02u:%02u\t%u\t%u+%u\t%u+%u\t%u\t%u\t%u\t%u\n",
04625                      lol_item_p->name,
04626                      RSBAC_MAJOR(lol_item_p->device), RSBAC_MINOR(lol_item_p->device),
04627                      lol_item_p->count,
04628                      lol_item_p->info.desc_size,
04629                      lol_item_p->info.subdesc_size,
04630                      lol_item_p->info.data_size,
04631                      lol_item_p->info.subdata_size,
04632                      lol_item_p->flags & RSBAC_LIST_PERSIST,
04633                      lol_item_p->no_write,
04634                      lol_item_p->flags,
04635                      lol_item_p->dirty & (lol_item_p->flags & RSBAC_LIST_PERSIST));
04636       pos = begin + len;
04637       if (pos < offset)
04638         {
04639           len = 0;
04640           begin = pos;
04641         }
04642       if (pos > offset+length)
04643         {
04644           rsbac_read_unlock(&lol_reg_head.lock, &flags);
04645           goto out;
04646         }
04647       lol_item_p = lol_item_p->next;
04648     }
04649   rsbac_read_unlock(&lol_reg_head.lock, &flags);
04650 
04651   len += sprintf(buffer + len, "\n %u lists of lists registered.\n",
04652                  lol_reg_head.count);
04653   pos = begin + len;
04654   if (pos < offset)
04655     {
04656       len = 0;
04657       begin = pos;
04658     }
04659   if (pos > offset+length)
04660     goto out;
04661 
04662 out:
04663   *start = buffer + (offset - begin);
04664   len -= (offset - begin);
04665   
04666   if (len > length)
04667     len = length;
04668   return len;
04669 }
04670 
04671 #if defined(CONFIG_RSBAC_LIST_REPL)
04672 static int
04673 repl_lists_proc_info(char *buffer, char **start, off_t offset, int length)
04674 {
04675   int len = 0;
04676   off_t pos   = 0;
04677   off_t begin = 0;
04678 
04679   union rsbac_target_id_t            rsbac_target_id;
04680   union rsbac_attribute_value_t      rsbac_attribute_value;
04681   struct rsbac_list_reg_item_t     * item_p;
04682   struct rsbac_list_lol_reg_item_t * lol_item_p;
04683          u_long                      flags;
04684 
04685   if (!rsbac_is_initialized())
04686     return (-ENOSYS);
04687 
04688 #ifdef CONFIG_RSBAC_DEBUG
04689   if (rsbac_debug_aef)
04690     {
04691       rsbac_printk(KERN_DEBUG "repl_lists_proc_info(): calling ADF\n");
04692     }
04693 #endif
04694   rsbac_target_id.scd = ST_rsbac;
04695   rsbac_attribute_value.dummy = 0;
04696   if (!rsbac_adf_request(R_GET_STATUS_DATA,
04697                          current->pid,
04698                          T_SCD,
04699                          rsbac_target_id,
04700                          A_none,
04701                          rsbac_attribute_value))
04702     {
04703       return -EPERM;
04704     }
04705 
04706   len += sprintf(buffer, "List Replication Status\n--------------------\n");
04707   len += sprintf(buffer, "Last Replication at: %u:%u",
04708                  repl_last.sec, repl_last.nsec);
04709 
04710   len += sprintf(buffer+len, "Lists\n-----\nName\t\tdevice\tlastchange\n");
04711   pos = begin + len;
04712   if (pos < offset)
04713     {
04714       len = 0;
04715       begin = pos;
04716     }
04717   if (pos > offset+length)
04718     goto out;
04719 
04720   rsbac_read_lock(&reg_head.lock, &flags);
04721   item_p=reg_head.head;
04722   while(item_p)
04723     {
04724       len += sprintf(buffer + len, "%-16s%02u:%02u\t%u:%u\n",
04725                      item_p->name,
04726                      RSBAC_MAJOR(item_p->device), RSBAC_MINOR(item_p->device),
04727                      item_p->lastchange.sec,
04728                      item_p->lastchange.nsec);
04729       pos = begin + len;
04730       if (pos < offset)
04731         {
04732           len = 0;
04733           begin = pos;
04734         }
04735       if (pos > offset+length)
04736         {
04737           rsbac_read_unlock(&reg_head.lock, &flags);
04738           goto out;
04739         }
04740       item_p = item_p->next;
04741     }
04742   rsbac_read_unlock(&reg_head.lock, &flags);
04743 
04744   len += sprintf(buffer + len, "\n %u lists registered.\n\n",
04745                  reg_head.count);
04746   pos = begin + len;
04747   if (pos < offset)
04748     {
04749       len = 0;
04750       begin = pos;
04751     }
04752   if (pos > offset+length)
04753     goto out;
04754 
04755   len += sprintf(buffer + len, "Lists of Lists\n-----------------\nName\t\tdevice\tlastchange\n");
04756   pos = begin + len;
04757   if (pos < offset)
04758     {
04759       len = 0;
04760       begin = pos;
04761     }
04762   if (pos > offset+length)
04763     goto out;
04764 
04765   rsbac_read_lock(&lol_reg_head.lock, &flags);
04766   lol_item_p=lol_reg_head.head;
04767   while(lol_item_p)
04768     {
04769       len += sprintf(buffer + len, "%-16s%02u:%02u\t%u:%u\n",
04770                      lol_item_p->name,
04771                      RSBAC_MAJOR(lol_item_p->device), RSBAC_MINOR(lol_item_p->device),
04772                      lol_item_p->lastchange.sec,
04773                      lol_item_p->lastchange.nsec);
04774       pos = begin + len;
04775       if (pos < offset)
04776         {
04777           len = 0;
04778           begin = pos;
04779         }
04780       if (pos > offset+length)
04781         {
04782           rsbac_read_unlock(&lol_reg_head.lock, &flags);
04783           goto out;
04784         }
04785       lol_item_p = lol_item_p->next;
04786     }
04787   rsbac_read_unlock(&lol_reg_head.lock, &flags);
04788 
04789   len += sprintf(buffer + len, "\n %u lists of lists registered.\n",
04790                  lol_reg_head.count);
04791   pos = begin + len;
04792   if (pos < offset)
04793     {
04794       len = 0;
04795       begin = pos;
04796     }
04797   if (pos > offset+length)
04798     goto out;
04799 
04800 out:
04801   *start = buffer + (offset - begin);
04802   len -= (offset - begin);
04803   
04804   if (len > length)
04805     len = length;
04806   return len;
04807 }
04808 #endif /* CONFIG_RSBAC_LIST_REPL */
04809 
04810 /* Generic backup generation function */
04811 static int backup_proc_read(char *page, char **start, off_t off,
04812   int count, int *eof, void *data)
04813   {
04814     int len = 0;
04815     off_t pos   = 0;
04816     off_t begin = 0;
04817 
04818     union  rsbac_target_id_t         rsbac_target_id;
04819     union  rsbac_attribute_value_t   rsbac_attribute_value;
04820     struct rsbac_list_reg_item_t   * list;
04821     struct rsbac_list_item_t       * current_p;
04822            rsbac_version_t           list_version = RSBAC_LIST_DISK_VERSION;
04823            rsbac_time_t              timestamp = RSBAC_CURRENT_TIME;
04824            u_long                    rflags, flags;
04825 
04826     if (!rsbac_is_initialized())
04827       return -ENOSYS;
04828 
04829 #ifdef CONFIG_RSBAC_DEBUG
04830     if (rsbac_debug_aef)
04831       {
04832         rsbac_printk(KERN_DEBUG "backup_proc_read(): calling ADF\n");
04833       }
04834 #endif
04835     rsbac_target_id.scd = ST_rsbac;
04836     rsbac_attribute_value.dummy = 0;
04837     if (!rsbac_adf_request(R_GET_STATUS_DATA,
04838                            current->pid,
04839                            T_SCD,
04840                            rsbac_target_id,
04841                            A_none,
04842                            rsbac_attribute_value))
04843       {
04844         return -EPERM;
04845       }
04846 
04847     rsbac_read_lock(&reg_head.lock, &rflags);
04848     list=lookup_reg(data);
04849     if(!list)
04850       {
04851         rsbac_read_unlock(&reg_head.lock, &rflags);
04852         return -ENOSYS;
04853       }
04854     /* lock list */
04855     rsbac_read_lock(&list->lock, &flags);
04856     /* copy version */
04857     memcpy(page,
04858            (char *) &list_version,
04859            sizeof(list_version));
04860     len = sizeof(list_version);
04861     /* copy version */
04862     memcpy(page+len,
04863            (char *) &timestamp,
04864            sizeof(timestamp));
04865     len += sizeof(timestamp);
04866     /* copy info */
04867     memcpy(page+len,
04868            (char *) &list->info,
04869            sizeof(list->info));
04870     len += sizeof(list->info);
04871     pos = begin + len;
04872     if (pos < off)
04873       {
04874         len = 0;
04875         begin = pos;
04876       }
04877     if (pos > off+count)
04878       {
04879         goto out;
04880       }
04881 
04882     /* copy list */
04883     current_p = list->head;
04884     while (current_p) 
04885       {
04886         memcpy(page+len,
04887                ((char *) current_p) + sizeof(*current_p),
04888                list->info.desc_size + list->info.data_size);
04889         len += list->info.desc_size + list->info.data_size;
04890         pos = begin + len;
04891         if (pos < off)
04892           {
04893             len = 0;
04894             begin = pos;
04895           }
04896         if (pos > off+count)
04897           {
04898             goto out;
04899           }
04900         current_p = current_p->next;
04901       }
04902 
04903   out:
04904     /* unprotect this list */
04905     rsbac_read_unlock(&list->lock, &flags);
04906     rsbac_read_unlock(&reg_head.lock, &rflags);
04907     if(len <= off+count)
04908       *eof=1;
04909     *start = page + (off - begin);
04910     len -= (off - begin);
04911   
04912     if (len > count)
04913       len = count;
04914     return len;
04915   }
04916 
04917 /* Generic lists of lists backup generation function */
04918 static int lol_backup_proc_read(char *page, char **start, off_t off,
04919   int count, int *eof, void *data)
04920   {
04921     int len = 0;
04922     off_t pos   = 0;
04923     off_t begin = 0;
04924 
04925     union  rsbac_target_id_t           rsbac_target_id;
04926     union  rsbac_attribute_value_t     rsbac_attribute_value;
04927     struct rsbac_list_lol_reg_item_t * list;
04928     struct rsbac_list_lol_item_t     * current_p;
04929     struct rsbac_list_item_t         * sub_p;
04930            rsbac_version_t             list_version = RSBAC_LIST_DISK_VERSION;
04931            rsbac_time_t                timestamp = RSBAC_CURRENT_TIME;
04932            u_long                      rflags, flags;
04933 
04934     if (!rsbac_is_initialized())
04935       return (-ENOSYS);
04936 
04937 #ifdef CONFIG_RSBAC_DEBUG
04938     if (rsbac_debug_aef)
04939       {
04940         rsbac_printk(KERN_DEBUG "lol_backup_proc_read(): calling ADF\n");
04941       }
04942 #endif
04943     rsbac_target_id.scd = ST_rsbac;
04944     rsbac_attribute_value.dummy = 0;
04945     if (!rsbac_adf_request(R_GET_STATUS_DATA,
04946                            current->pid,
04947                            T_SCD,
04948                            rsbac_target_id,
04949                            A_none,
04950                            rsbac_attribute_value))
04951       {
04952         return -EPERM;
04953       }
04954 
04955     rsbac_read_lock(&lol_reg_head.lock, &rflags);
04956     list=lookup_lol_reg(data);
04957     if(!list)
04958       {
04959         rsbac_read_unlock(&lol_reg_head.lock, &rflags);
04960         return -ENOSYS;
04961       }
04962     /* lock list */
04963     rsbac_read_lock(&list->lock, &flags);
04964     /* copy version */
04965     memcpy(page,
04966            (char *) &list_version,
04967            sizeof(list_version));
04968     len = sizeof(list_version);
04969     /* copy version */
04970     memcpy(page+len,
04971            (char *) &timestamp,
04972            sizeof(timestamp));
04973     len += sizeof(timestamp);
04974     /* copy info */
04975     memcpy(page+len,
04976            (char *) &list->info,
04977            sizeof(list->info));
04978     len += sizeof(list->info);
04979     pos = begin + len;
04980     if (pos < off)
04981       {
04982         len = 0;
04983         begin = pos;
04984       }
04985     if (pos > off+count)
04986       {
04987         goto out;
04988       }
04989 
04990     /* copy list */
04991     current_p = list->head;
04992     while (current_p) 
04993       {
04994         memcpy(page+len,
04995                ((char *) current_p) + sizeof(*current_p),
04996                list->info.desc_size + list->info.data_size);
04997         len += list->info.desc_size + list->info.data_size;
04998         memcpy(page+len,
04999                &current_p->count,
05000                sizeof(current_p->count));
05001         len += sizeof(current_p->count);
05002         pos = begin + len;
05003         if (pos < off)
05004           {
05005             len = 0;
05006             begin = pos;
05007           }
05008         if (pos > off+count)
05009           {
05010             goto out;
05011           }
05012         /* copy sublist */
05013         sub_p = current_p->head;
05014         while (sub_p)
05015           {
05016             memcpy(page+len,
05017                    ((char *) sub_p) + sizeof(*sub_p),
05018                    list->info.subdesc_size + list->info.subdata_size);
05019             len += list->info.subdesc_size + list->info.subdata_size;
05020             pos = begin + len;
05021             if (pos < off)
05022               {
05023                 len = 0;
05024                 begin = pos;
05025               }
05026             if (pos > off+count)
05027               {
05028                 goto out;
05029               }
05030             sub_p = sub_p->next;
05031           }
05032         current_p = current_p->next;
05033       }
05034 
05035   out:
05036     /* unprotect this list */
05037     rsbac_read_unlock(&list->lock, &flags);
05038     rsbac_read_unlock(&lol_reg_head.lock, &rflags);
05039     if(len <= off+count)
05040       *eof=1;
05041     *start = page + (off - begin);
05042     len -= (off - begin);
05043   
05044     if (len > count)
05045       len = count;
05046     return len;
05047   }
05048 #endif /* PROC */
05049 
05050 
05051 /********************/
05052 /* Init and general */
05053 /********************/
05054 
05055 int rsbac_list_compare_u32(void * desc1, void * desc2)
05056   {
05057     if( *((__u32*) desc1) < *((__u32*) desc2))
05058       return -1;
05059     return( *((__u32*) desc1) != *((__u32*) desc2));
05060   }
05061 
05062 #ifdef CONFIG_RSBAC_INIT_DELAY
05063 int rsbac_list_init(void)
05064 #else
05065 int __init rsbac_list_init(void)
05066 #endif
05067   {
05068     #ifdef CONFIG_RSBAC_LIST_TRANS
05069     int err;
05070     struct rsbac_list_info_t * list_info_p;
05071     #endif
05072 
05073     reg_head.head  = NULL;
05074     reg_head.tail  = NULL;
05075     reg_head.curr  = NULL;
05076     reg_head.lock  = RW_LOCK_UNLOCKED;
05077     reg_head.count = 0;
05078 
05079     lol_reg_head.head  = NULL;
05080     lol_reg_head.tail  = NULL;
05081     lol_reg_head.curr  = NULL;
05082     lol_reg_head.lock  = RW_LOCK_UNLOCKED;
05083     lol_reg_head.count = 0;
05084 
05085     list_initialized = TRUE;
05086 
05087     #ifdef CONFIG_RSBAC_LIST_REPL
05088     repl_last.sec = 0;
05089     repl_last.nsec = 0;
05090     #endif
05091 
05092     /* init proc entry */
05093     #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
05094     {
05095       struct proc_dir_entry * tmp_entry_p;
05096 
05097       tmp_entry_p = create_proc_entry(RSBAC_LIST_PROC_NAME,
05098                                       S_IFREG | S_IRUGO,
05099                                       proc_rsbac_root_p);
05100       if(tmp_entry_p)
05101         {
05102           tmp_entry_p->get_info = lists_proc_info;
05103         }
05104       #if defined(CONFIG_RSBAC_LIST_REPL)
05105       tmp_entry_p = create_proc_entry(RSBAC_LIST_REPL_PROC_NAME,
05106                                       S_IFREG | S_IRUGO,
05107                                       proc_rsbac_root_p);
05108       if(tmp_entry_p)
05109         {
05110           tmp_entry_p->get_info = repl_lists_proc_info;
05111         }
05112       #endif
05113     }
05114     #endif
05115 
05116     #ifdef CONFIG_RSBAC_LIST_TRANS
05117     rsbac_printk(KERN_INFO
05118                  "rsbac_list_init(): Registering transaction list.\n");
05119     list_info_p = kmalloc(sizeof(*list_info_p), GFP_KERNEL);
05120     if(!list_info_p)
05121       {
05122         return -ENOMEM;
05123       }
05124     list_info_p->version = 1;
05125     list_info_p->key = RSBAC_LIST_TA_KEY;
05126     list_info_p->desc_size = sizeof(rsbac_list_ta_number_t);
05127     list_info_p->data_size = sizeof(struct rsbac_list_ta_data_t);
05128     list_info_p->max_age = 0;
05129     err = rsbac_list_register(RSBAC_LIST_VERSION,
05130                               (void **) &ta_handle,
05131                               list_info_p,
05132                               0,
05133                               rsbac_list_compare_u32,
05134                               NULL,
05135                               NULL,
05136                               "transactions",
05137                               RSBAC_AUTO_DEV);
05138     if(err)
05139       {
05140         char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
05141 
05142         if(tmp)
05143           {
05144             rsbac_printk(KERN_WARNING
05145                    "rsbac_list_init(): Registering transaction list failed with error %s\n",
05146                    get_error_name(tmp, err));
05147             kfree(tmp);
05148           }
05149       }
05150     kfree(list_info_p);
05151     #endif
05152 
05153     #ifdef CONFIG_RSBAC_LIST_REPL
05154     rsbac_printk(KERN_INFO
05155                  "rsbac_list_init(): Registering replication partner list.\n");
05156     list_info_p = kmalloc(sizeof(*list_info_p), GFP_KERNEL);
05157     if(!list_info_p)
05158       {
05159         return -ENOMEM;
05160       }
05161     list_info_p->version = RSBAC_LIST_REPL_PARTNER_VERSION;
05162     list_info_p->key = RSBAC_LIST_REPL_PARTNER_KEY;
05163     list_info_p->desc_size = sizeof(rsbac_list_repl_partner_number_t);
05164     list_info_p->data_size = sizeof(struct rsbac_list_repl_partner_entry_t);
05165     list_info_p->max_age = 0;
05166     err = rsbac_list_register(RSBAC_LIST_VERSION,
05167                               (void **) &repl_partner_handle,
05168                               list_info_p,
05169                               RSBAC_LIST_PERSIST,
05170                               NULL,
05171                               NULL,
05172                               NULL,
05173                               RSBAC_LIST_REPL_PARTNER_FILENAME,
05174                               RSBAC_AUTO_DEV);
05175     if(err)
05176       {
05177         char * tmp = kmalloc(RSBAC_MAXNAMELEN, GFP_KERNEL);
05178 
05179         if(tmp)
05180           {
05181             rsbac_printk(KERN_WARNING
05182                    "rsbac_list_init(): Registering replication partner list failed with error %s\n",
05183                    get_error_name(tmp, err));
05184             kfree(tmp);
05185           }
05186       }
05187     kfree(list_info_p);
05188     #endif
05189 
05190     return 0;
05191   }
05192 
05193 int rsbac_list_mount(kdev_t kdev)
05194   {
05195     return 0;
05196   }
05197 
05198 int rsbac_list_umount(kdev_t kdev)
05199   {
05200     return 0;
05201   }
05202 
05203 #ifdef CONFIG_RSBAC_AUTO_WRITE
05204 int rsbac_write_lists(rsbac_boolean_t need_lock)
05205   {
05206     int count = 0;
05207     int subcount = 0;
05208     int error = 0;
05209     struct rsbac_list_reg_item_t       * item_p;
05210     struct rsbac_list_lol_reg_item_t   * lol_item_p;
05211            u_long                        lock_flags;
05212     struct rsbac_list_write_head_t       write_head;
05213     struct rsbac_list_write_item_t     * write_item_p;
05214     struct rsbac_list_lol_write_head_t   write_lol_head;
05215     struct rsbac_list_lol_write_item_t * write_lol_item_p;
05216 
05217 /*
05218 #ifdef CONFIG_RSBAC_DEBUG
05219     if(rsbac_debug_lists)
05220       rsbac_printk(KERN_DEBUG "rsbac_write_lists() called.\n");
05221 #endif
05222 */
05223     if(!list_initialized)
05224       return -RSBAC_ENOTINITIALIZED;
05225 
05226 #ifdef CONFIG_RSBAC_LIST_TRANS
05227     if(rsbac_list_count(ta_handle) > 0)
05228       {
05229         int list_count;
05230         rsbac_list_ta_number_t * desc_array;
05231         struct rsbac_list_ta_data_t data;
05232 
05233         list_count = rsbac_list_get_all_desc(ta_handle, (void **) &desc_array);
05234         if(list_count > 0)
05235           {
05236             int i;
05237             rsbac_time_t now = RSBAC_CURRENT_TIME;
05238 
05239             for(i=0; i<list_count; i++)
05240               {
05241                 if(!rsbac_list_get_data(ta_handle, &desc_array[i], &data))
05242                   {
05243                     if(data.timeout < now)
05244                       {
05245                         rsbac_printk(KERN_WARNING
05246                                      "rsbac_write_lists(): transaction %u timed out, forcing forget\n",
05247                                      desc_array[i]);
05248                         do_forget(desc_array[i]);
05249                       }
05250                   }
05251               }
05252             rsbac_vfree(desc_array);
05253           }
05254       }
05255 #endif
05256 
05257     /* Init buffer list */
05258     write_head.head=NULL;
05259     write_head.tail=NULL;
05260     write_head.total=0;
05261     write_head.count=0;
05262 
05263     rsbac_read_lock(&reg_head.lock, &lock_flags);
05264     item_p=reg_head.head;
05265     while(item_p)
05266       {
05267         if(   (item_p->flags & RSBAC_LIST_PERSIST)
05268            && item_p->dirty
05269            && !item_p->no_write
05270           )
05271           {
05272             item_p->dirty = FALSE;
05273             /* list locking is done in fill_buffer */
05274             error = fill_buffer(item_p, &write_item_p);
05275             if(!error)
05276               {
05277                 if(!write_head.head)
05278                   {
05279                     write_head.head = write_item_p;
05280                     write_head.tail = write_item_p;
05281                     write_head.total = write_item_p->buflen;
05282                     write_head.count = 1;
05283                   }
05284                 else
05285                   {
05286                     write_head.tail->next = write_item_p;
05287                     write_item_p->prev = write_head.tail;
05288                     write_head.tail = write_item_p;
05289                     write_head.total += write_item_p->buflen;
05290                     write_head.count++;
05291                   }
05292               }
05293             else
05294               {
05295                 if(   (error != -RSBAC_ENOTWRITABLE)
05296                    && (error != -RSBAC_ENOMEM)
05297                   )
05298                   {
05299                     rsbac_printk(KERN_WARNING
05300                            "rsbac_write_lists(): fill_buffer() for list %s returned error %i\n",
05301                            item_p->name, error);
05302                   }
05303                 item_p->dirty = TRUE;
05304               }
05305           }
05306         item_p=item_p->next;
05307       }
05308     rsbac_read_unlock(&reg_head.lock, &lock_flags);
05309 
05310 #ifdef CONFIG_RSBAC_DEBUG
05311     if(   rsbac_debug_write
05312        && (write_head.count > 0)
05313       )
05314       {
05315         rsbac_printk(KERN_DEBUG
05316                "rsbac_write_lists(): %u lists copied to buffers, total of %lu bytes\n",
05317                write_head.count,
05318                write_head.total);
05319       }
05320 #endif
05321 
05322     /* write all buffers */
05323     if(write_head.count)
05324       {
05325         count = rsbac_list_write_buffers(write_head, need_lock);
05326 #ifdef CONFIG_RSBAC_DEBUG
05327         if(rsbac_debug_write)
05328           {
05329             rsbac_printk(KERN_DEBUG
05330                    "rsbac_write_lists(): %u lists written to disk\n",
05331                    count);
05332           }
05333 #endif
05334       }
05335 
05336     /* LOL */
05337     /* Init buffer list */
05338     write_lol_head.head=NULL;
05339     write_lol_head.tail=NULL;
05340     write_lol_head.total=0;
05341     write_lol_head.count=0;
05342 
05343     rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
05344     lol_item_p=lol_reg_head.head;
05345     while(lol_item_p)
05346       {
05347         if(   (lol_item_p->flags & RSBAC_LIST_PERSIST)
05348            && lol_item_p->dirty
05349            && !lol_item_p->no_write
05350           )
05351           {
05352             lol_item_p->dirty = FALSE;
05353             /* list locking is done in fill_buffer */
05354             error = fill_lol_buffer(lol_item_p, &write_lol_item_p);
05355             if(!error)
05356               {
05357                 if(!write_lol_head.head)
05358                   {
05359                     write_lol_head.head = write_lol_item_p;
05360                     write_lol_head.tail = write_lol_item_p;
05361                     write_lol_head.total = write_lol_item_p->buflen;
05362                     write_lol_head.count = 1;
05363                   }
05364                 else
05365                   {
05366                     write_lol_head.tail->next = write_lol_item_p;
05367                     write_lol_item_p->prev = write_lol_head.tail;
05368                     write_lol_head.tail = write_lol_item_p;
05369                     write_lol_head.total += write_lol_item_p->buflen;
05370                     write_lol_head.count++;
05371                   }
05372               }
05373             else
05374               {
05375                 if(   (error != -RSBAC_ENOTWRITABLE)
05376                    && (error != -RSBAC_ENOMEM)
05377                   )
05378                   {
05379                     rsbac_printk(KERN_WARNING
05380                            "rsbac_write_lists(): fill_lol_buffer() for list %s returned error %i\n",
05381                            lol_item_p->name, error);
05382                   }
05383                 item_p->dirty = TRUE;
05384               }
05385           }
05386         lol_item_p=lol_item_p->next;
05387       }
05388     rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
05389 
05390 #ifdef CONFIG_RSBAC_DEBUG
05391     if(   rsbac_debug_write
05392        && (write_lol_head.count > 0)
05393       )
05394       {
05395         rsbac_printk(KERN_DEBUG
05396                "rsbac_write_lists(): %u lists of lists copied to buffers, total of %lu bytes\n",
05397                write_lol_head.count,
05398                write_lol_head.total);
05399       }
05400 #endif
05401 
05402     /* write all buffers */
05403     if(write_lol_head.count)
05404       {
05405         subcount = rsbac_list_write_lol_buffers(write_lol_head, need_lock);
05406         count += subcount;
05407 #ifdef CONFIG_RSBAC_DEBUG
05408         if(rsbac_debug_write)
05409           {
05410             rsbac_printk(KERN_DEBUG
05411                    "rsbac_write_lists(): %u lists of lists written to disk\n",
05412                    subcount);
05413           }
05414 #endif
05415       }
05416 
05417 #ifdef CONFIG_RSBAC_DEBUG
05418     if (rsbac_debug_write)
05419       {
05420         rsbac_printk(KERN_DEBUG "rsbac_write_lists(): %u lists with a total of %lu bytes written.\n",
05421                count, write_head.total + write_lol_head.total);
05422       }
05423 #endif
05424     return count;
05425   }
05426 #endif /* CONFIG_RSBAC_AUTO_WRITE */
05427 
05428 /* Status checking */
05429 int rsbac_check_lists(int correct)
05430   {
05431     struct rsbac_list_reg_item_t     * list;
05432     struct rsbac_list_lol_reg_item_t * lol_list;
05433     struct rsbac_list_item_t         * item_p;
05434     struct rsbac_list_item_t         * next_item_p;
05435     struct rsbac_list_lol_item_t     * lol_item_p;
05436     struct rsbac_list_lol_item_t     * next_lol_item_p;
05437     struct rsbac_list_item_t         * lol_subitem_p;
05438     struct rsbac_list_item_t         * next_lol_subitem_p;
05439            u_long                      lock_flags, rlock_flags;
05440            u_long                      tmp_count;
05441            u_long                      tmp_subcount;
05442            u_long                      subitem_count;
05443            u_long                      dirty = 0;
05444 
05445 #ifdef CONFIG_RSBAC_DEBUG
05446     if(rsbac_debug_lists)
05447       {
05448         rsbac_printk(KERN_DEBUG "rsbac_check_lists() called.\n");
05449       }
05450 #endif
05451     if(!list_initialized)
05452       return -RSBAC_ENOTINITIALIZED;
05453     rsbac_read_lock(&reg_head.lock, &rlock_flags);
05454     list = reg_head.head;
05455     while(list)
05456       {
05457         /* check list */
05458         rsbac_write_lock(&list->lock, &lock_flags);
05459         tmp_count = 0;
05460         item_p = list->head;
05461         while(item_p)
05462           {
05463             if(   (   item_p->max_age
05464                    && (item_p->max_age <= RSBAC_CURRENT_TIME)
05465                   )
05466                || (   list->def_data
05467                    && !memcmp(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
05468                               list->def_data,
05469                               list->info.data_size)
05470                   )
05471               )
05472               {
05473                 next_item_p = item_p->next;
05474                 do_remove_item(list, item_p);
05475                 item_p = next_item_p;
05476               }
05477             else
05478               {
05479                 tmp_count++;
05480                 item_p = item_p->next;
05481               }
05482           }
05483         if(tmp_count != list->count)
05484           {
05485             if(correct)
05486               {
05487                 rsbac_printk(KERN_WARNING
05488                        "rsbac_check_lists(): correcting count mismatch for list %s on device %02u:%02u - was %u, counted %lu!\n",
05489                        list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count, tmp_count);
05490                 list->count = tmp_count;
05491               }
05492             else
05493               {
05494                 rsbac_printk(KERN_WARNING
05495                        "rsbac_check_lists(): count mismatch for list %s on device %02u:%02u - is %u, counted %lu!\n",
05496                        list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count, tmp_count);
05497               }
05498           }
05499         rsbac_write_unlock(&list->lock, &lock_flags);
05500         if(list->dirty && (list->flags & RSBAC_LIST_PERSIST))
05501           {
05502             dirty++;
05503 #ifdef CONFIG_RSBAC_DEBUG
05504             if(rsbac_debug_lists)
05505               {
05506                 rsbac_printk(KERN_DEBUG
05507                        "rsbac_check_lists(): %s on %02u:%02u has %u items (list is dirty)\n",
05508                        list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count);
05509               }
05510 #endif
05511           }
05512 #ifdef CONFIG_RSBAC_DEBUG
05513         else
05514           {
05515             if(rsbac_debug_lists)
05516               {
05517                 rsbac_printk(KERN_DEBUG
05518                        "rsbac_check_lists(): %s on %02u:%02u has %u items\n",
05519                        list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count);
05520               }
05521           }
05522 #endif
05523         list = list->next;
05524       }
05525     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
05526 
05527     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
05528     lol_list = lol_reg_head.head;
05529     while(lol_list)
05530       {
05531         /* check list */
05532         rsbac_write_lock(&lol_list->lock, &lock_flags);
05533         tmp_count = 0;
05534         subitem_count = 0;
05535         lol_item_p = lol_list->head;
05536         while(lol_item_p)
05537           {
05538             if(   (   lol_item_p->max_age
05539                    && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
05540                   )
05541                || (   lol_list->def_data
05542                    && !lol_item_p->count
05543                    && !memcmp(((char *) lol_item_p) + sizeof(*lol_item_p) + lol_list->info.desc_size,
05544                               lol_list->def_data,
05545                               lol_list->info.data_size)
05546                   )
05547                || (   !lol_list->info.data_size
05548                    && (lol_list->flags & RSBAC_LIST_DEF_DATA)
05549                    && !lol_item_p->count
05550                   )
05551               )
05552               {
05553                 next_lol_item_p = lol_item_p->next;
05554                 do_remove_lol_item(lol_list, lol_item_p);
05555                 lol_item_p = next_lol_item_p;
05556               }
05557             else
05558               {
05559                 tmp_count++;
05560                 tmp_subcount = 0;
05561                 lol_subitem_p = lol_item_p->head;
05562                 while(lol_subitem_p)
05563                   {
05564                     if(   (   lol_subitem_p->max_age
05565                            && (lol_subitem_p->max_age <= RSBAC_CURRENT_TIME)
05566                           )
05567                        || (   lol_list->def_subdata
05568                            && !memcmp(((char *) lol_subitem_p) + sizeof(*lol_subitem_p) + lol_list->info.subdesc_size,
05569                                       lol_list->def_subdata,
05570                                       lol_list->info.subdata_size)
05571                           )
05572                       )
05573                       {
05574                         next_lol_subitem_p = lol_subitem_p->next;
05575                         do_remove_lol_subitem(lol_item_p, lol_subitem_p);
05576                         lol_subitem_p = next_lol_subitem_p;
05577                       }
05578                     else
05579                       {
05580                         tmp_subcount++;
05581                         lol_subitem_p = lol_subitem_p->next;
05582                       }
05583                   }
05584                 if(tmp_subcount != lol_item_p->count)
05585                   {
05586                     if(correct)
05587                       {
05588                         rsbac_printk(KERN_WARNING
05589                                "rsbac_check_lists(): correcting count mismatch for list of lists %s sublist on %02u:%02u - was %lu, counted %lu!\n",
05590                                lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_item_p->count, tmp_subcount);
05591                         lol_item_p->count = tmp_subcount;
05592                       }
05593                     else
05594                       {
05595                         rsbac_printk(KERN_WARNING
05596                                "rsbac_check_lists(): count mismatch for list of lists %s sublist on %02u:%02u - is %lu, counted %lu!\n",
05597                                lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_item_p->count, tmp_subcount);
05598                       }
05599                   }
05600                 subitem_count += lol_item_p->count;
05601                 lol_item_p = lol_item_p->next;
05602               }
05603           }
05604         if(tmp_count != lol_list->count)
05605           {
05606             if(correct)
05607               {
05608                 rsbac_printk(KERN_WARNING
05609                        "rsbac_check_lists(): correcting count mismatch for list of lists %s on %02u:%02u - was %u, counted %lu!\n",
05610                        lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, tmp_count);
05611                 lol_list->count = tmp_count;
05612               }
05613             else
05614               {
05615                 rsbac_printk(KERN_WARNING
05616                        "rsbac_check_lists(): count mismatch for list of lists %s on %02u:%02u - is %u, counted %lu!\n",
05617                        lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, tmp_count);
05618               }
05619           }
05620         rsbac_write_unlock(&lol_list->lock, &lock_flags);
05621         if(lol_list->dirty && (lol_list->flags & RSBAC_LIST_PERSIST))
05622           {
05623             dirty++;
05624 #ifdef CONFIG_RSBAC_DEBUG
05625             if(rsbac_debug_lists)
05626               {
05627                 rsbac_printk(KERN_DEBUG
05628                        "rsbac_check_lists(): %s on %02u:%02u has %u items and %lu subitems (list is dirty)\n",
05629                        lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, subitem_count);
05630               }
05631 #endif
05632           }
05633 #ifdef CONFIG_RSBAC_DEBUG
05634         else
05635           {
05636             if(rsbac_debug_lists)
05637               {
05638                 rsbac_printk(KERN_DEBUG
05639                        "rsbac_check_lists(): %s on %02u:%02u has %u items and %lu subitems\n",
05640                        lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, subitem_count);
05641               }
05642           }
05643 #endif
05644         lol_list = lol_list->next;
05645       }
05646     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
05647     return 0;
05648   }
05649 
05650 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05651 EXPORT_SYMBOL(rsbac_list_check);
05652 #endif
05653 int rsbac_list_check(
05654   rsbac_list_handle_t handle,
05655   int correct)
05656   {
05657     struct rsbac_list_reg_item_t * list;
05658     struct rsbac_list_item_t     * item_p;
05659     struct rsbac_list_item_t     * next_item_p;
05660     u_long lock_flags;
05661     u_long rlock_flags;
05662     u_long tmp_count;
05663 
05664     if(!handle)
05665       return -RSBAC_EINVALIDVALUE;
05666     if(!list_initialized)
05667       return -RSBAC_ENOTINITIALIZED;
05668 
05669     list = (struct rsbac_list_reg_item_t *) handle;
05670     if(!list || (list->self != list))
05671       return -RSBAC_EINVALIDVALUE;
05672 
05673     rsbac_read_lock(&reg_head.lock, &rlock_flags);
05674 #ifdef CONFIG_RSBAC_DEBUG
05675     if(rsbac_debug_lists)
05676       rsbac_printk(KERN_DEBUG "rsbac_list_check: checking list %s.\n",
05677              list->name);
05678 #endif
05679     rsbac_write_lock(&list->lock, &lock_flags);
05680     tmp_count = 0;
05681     item_p = list->head;
05682     while(item_p)
05683       {
05684         if(   (   item_p->max_age
05685                && (item_p->max_age <= RSBAC_CURRENT_TIME)
05686               )
05687            || (   list->def_data
05688                && !memcmp(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
05689                           list->def_data,
05690                           list->info.data_size)
05691               )
05692           )
05693           {
05694             next_item_p = item_p->next;
05695             do_remove_item(list, item_p);
05696             item_p = next_item_p;
05697             list->dirty = TRUE;
05698           }
05699         else
05700           {
05701             tmp_count++;
05702             item_p = item_p->next;
05703           }
05704       }
05705     if(tmp_count != list->count)
05706       {
05707         if(correct)
05708           {
05709             rsbac_printk(KERN_WARNING
05710                          "rsbac_list_check(): correcting count mismatch for list %s on device %02u:%02u - was %u, counted %lu!\n",
05711                          list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count, tmp_count);
05712             list->count = tmp_count;
05713             list->dirty = TRUE;
05714           }
05715         else
05716           {
05717             rsbac_printk(KERN_WARNING
05718                          "rsbac_list_check(): count mismatch for list %s on device %02u:%02u - is %u, counted %lu!\n",
05719                          list->name, RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device), list->count, tmp_count);
05720           }
05721       }
05722     rsbac_write_unlock(&list->lock, &lock_flags);
05723     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
05724     return 0;
05725   }
05726 
05727 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05728 EXPORT_SYMBOL(rsbac_list_lol_check);
05729 #endif
05730 int rsbac_list_lol_check(
05731   rsbac_list_handle_t handle,
05732   int correct)
05733   {
05734     struct rsbac_list_lol_reg_item_t * lol_list;
05735     struct rsbac_list_lol_item_t     * lol_item_p;
05736     struct rsbac_list_lol_item_t     * next_lol_item_p;
05737     struct rsbac_list_item_t         * lol_subitem_p;
05738     struct rsbac_list_item_t         * next_lol_subitem_p;
05739     u_long lock_flags;
05740     u_long rlock_flags;
05741     u_long tmp_count;
05742     u_long tmp_subcount;
05743 
05744     if(!handle)
05745       return -RSBAC_EINVALIDVALUE;
05746     if(!list_initialized)
05747       return -RSBAC_ENOTINITIALIZED;
05748 
05749     lol_list = (struct rsbac_list_lol_reg_item_t *) handle;
05750     if(!lol_list || (lol_list->self != lol_list))
05751       return -RSBAC_EINVALIDVALUE;
05752 
05753     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
05754 #ifdef CONFIG_RSBAC_DEBUG
05755     if(rsbac_debug_lists)
05756       rsbac_printk(KERN_DEBUG "rsbac_list_lol_check: checking list %s.\n",
05757              lol_list->name);
05758 #endif
05759     rsbac_write_lock(&lol_list->lock, &lock_flags);
05760     tmp_count = 0;
05761     lol_item_p = lol_list->head;
05762     while(lol_item_p)
05763       {
05764         if(   (   lol_item_p->max_age
05765                && (lol_item_p->max_age <= RSBAC_CURRENT_TIME)
05766               )
05767            || (   lol_list->def_data
05768                && !lol_item_p->count
05769                && !memcmp(((char *) lol_item_p) + sizeof(*lol_item_p) + lol_list->info.desc_size,
05770                           lol_list->def_data,
05771                           lol_list->info.data_size)
05772               )
05773            || (   !lol_list->info.data_size
05774                && (lol_list->flags & RSBAC_LIST_DEF_DATA)
05775                && !lol_item_p->count
05776               )
05777           )
05778           {
05779             next_lol_item_p = lol_item_p->next;
05780             do_remove_lol_item(lol_list, lol_item_p);
05781             lol_item_p = next_lol_item_p;
05782           }
05783         else
05784           {
05785             tmp_count++;
05786             tmp_subcount = 0;
05787             lol_subitem_p = lol_item_p->head;
05788             while(lol_subitem_p)
05789               {
05790                 if(   (   lol_subitem_p->max_age
05791                        && (lol_subitem_p->max_age <= RSBAC_CURRENT_TIME)
05792                       )
05793                    || (   lol_list->def_subdata
05794                        && !memcmp(((char *) lol_subitem_p) + sizeof(*lol_subitem_p) + lol_list->info.subdesc_size,
05795                                   lol_list->def_subdata,
05796                                   lol_list->info.subdata_size)
05797                       )
05798                   )
05799                   {
05800                     next_lol_subitem_p = lol_subitem_p->next;
05801                     do_remove_lol_subitem(lol_item_p, lol_subitem_p);
05802                     lol_subitem_p = next_lol_subitem_p;
05803                   }
05804                 else
05805                   {
05806                     tmp_subcount++;
05807                     lol_subitem_p = lol_subitem_p->next;
05808                   }
05809               }
05810             if(tmp_subcount != lol_item_p->count)
05811               {
05812                 if(correct)
05813                   {
05814                      rsbac_printk(KERN_WARNING
05815                                   "rsbac_list_lol_check(): correcting count mismatch for list of lists %s sublist on %02u:%02u - was %lu, counted %lu!\n",
05816                                   lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_item_p->count, tmp_subcount);
05817                     lol_item_p->count = tmp_subcount;
05818                   }
05819                 else
05820                   {
05821                     rsbac_printk(KERN_WARNING
05822                                  "rsbac_list_lol_check(): count mismatch for list of lists %s sublist on %02u:%02u - is %lu, counted %lu!\n",
05823                                  lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_item_p->count, tmp_subcount);
05824                   }
05825               }
05826             lol_item_p = lol_item_p->next;
05827           }
05828       }
05829     if(tmp_count != lol_list->count)
05830       {
05831         if(correct)
05832           {
05833             rsbac_printk(KERN_WARNING
05834                          "rsbac_list_lol_check(): correcting count mismatch for list of lists %s on %02u:%02u - was %u, counted %lu!\n",
05835                          lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, tmp_count);
05836             lol_list->count = tmp_count;
05837           }
05838         else
05839           {
05840             rsbac_printk(KERN_WARNING
05841                          "rsbac_list_lol_check(): count mismatch for list of lists %s on %02u:%02u - is %u, counted %lu!\n",
05842                          lol_list->name, RSBAC_MAJOR(lol_list->device), RSBAC_MINOR(lol_list->device), lol_list->count, tmp_count);
05843           }
05844       }
05845     rsbac_write_unlock(&lol_list->lock, &lock_flags);
05846     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
05847     return 0;
05848   }
05849 
05850 
05851 /********************/
05852 /* Registration     */
05853 /********************/
05854 
05855 /* get generic list registration version */
05856 rsbac_version_t rsbac_list_version(void)
05857   {
05858     return RSBAC_LIST_VERSION;
05859   }
05860 
05861 /* register a new list */
05862 /*
05863  * If list with same name exists in memory, error -RSBAC_EEXISTS is returned.
05864  * If list with same name and key exists on device, it is restored depending on the flags.
05865  * If list with same name, but different key exists, access is denied (error -EPERM).
05866  *
05867  * ds_version: for binary modules, must be RSBAC_LIST_VERSION. If version differs, return error.
05868  * handle_p: for all list accesses, an opaque handle is put into *handle_p.
05869  * key: positive, secret __u32 key, which must be the same as in on-disk version, if persistent
05870  * list_version: positive __u32 version number for the list. If old on-disk version is
05871    different, upconversion is tried (depending on flags and get_conv function)
05872  * flags: see flag values
05873  * desc_size: size of the descriptor (error is returned, if value is 0 or list exists and value differs)
05874  * data_size: size of data (error is returned, if list exists and value differs). Can be 0 for sets.
05875  * compare: for lookup and list optimization, can be NULL, then
05876    memcmp(desc1, desc2, desc_size) is used
05877  * def_data: default data value for flag RSBAC_LIST_DEF_DATA
05878    (if NULL, flag is cleared)
05879  * name: the on-disk name, must be distinct and max. 7 or 8.2 chars
05880    (only used for statistics, if non-persistent)
05881  * device: the device to read list from or to save list to - use 0 for root dev
05882    (ignored, if non-persistent)
05883  */
05884 
05885 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
05886 EXPORT_SYMBOL(rsbac_list_register);
05887 #endif
05888 int rsbac_list_register(
05889   rsbac_version_t ds_version,
05890   rsbac_list_handle_t *handle_p,
05891   struct rsbac_list_info_t * info_p,
05892   u_int flags,
05893   rsbac_list_compare_function_t * compare,
05894   rsbac_list_get_conv_t * get_conv,
05895   void * def_data,
05896   char * name,
05897   kdev_t device)
05898   {
05899     struct rsbac_list_reg_item_t     * reg_item_p;
05900     struct rsbac_list_reg_item_t     * new_reg_item_p;
05901     u_long lock_flags;
05902     int    err = 0;
05903 
05904     if(ds_version != RSBAC_LIST_VERSION)
05905       {
05906         if(name)
05907           {
05908             rsbac_printk(KERN_WARNING
05909                    "rsbac_list_register: wrong ds_version %u for list %s, expected %u!\n",
05910                    ds_version,
05911                    name,
05912                    RSBAC_LIST_VERSION);
05913           }
05914         return -RSBAC_EINVALIDVERSION;
05915       }
05916     if(!handle_p || !info_p)
05917       return -RSBAC_EINVALIDPOINTER;
05918     *handle_p = NULL;
05919     if(!info_p->key || !info_p->version || !info_p->desc_size)
05920       return -RSBAC_EINVALIDVALUE;
05921     if(info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT)
05922       return -RSBAC_EINVALIDVALUE;
05923     if(info_p->desc_size + info_p->data_size > RSBAC_LIST_MAX_ITEM_SIZE)
05924       return -RSBAC_EINVALIDVALUE;
05925     if(!list_initialized)
05926       return -RSBAC_ENOTINITIALIZED;
05927     if(name)
05928       {
05929         struct rsbac_list_lol_reg_item_t * lol_reg_item_p;
05930 
05931         rsbac_read_lock(&reg_head.lock, &lock_flags);
05932         reg_item_p = lookup_reg_name(name, device);
05933         rsbac_read_unlock(&reg_head.lock, &lock_flags);
05934         if(reg_item_p)
05935           {
05936 #ifdef CONFIG_RSBAC_DEBUG
05937             if(rsbac_debug_lists)
05938               {
05939                 rsbac_printk(KERN_DEBUG "rsbac_list_register: list name %s already exists on device %02u:%02u!\n",
05940                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
05941               }
05942 #endif
05943             return -RSBAC_EEXISTS;
05944           }
05945         rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
05946         lol_reg_item_p = lookup_lol_reg_name(name, device);
05947         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
05948         if(lol_reg_item_p)
05949           {
05950 #ifdef CONFIG_RSBAC_DEBUG
05951             if(rsbac_debug_lists)
05952               {
05953                 rsbac_printk(KERN_DEBUG "rsbac_list_register: list name %s already exists on device %02u:%02u!\n",
05954                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
05955               }
05956 #endif
05957             return -RSBAC_EEXISTS;
05958           }
05959       }
05960     else
05961       if(flags & RSBAC_LIST_PERSIST)
05962         {
05963           rsbac_printk(KERN_WARNING
05964                  "rsbac_list_register: trial to register persistent list without name.\n");
05965           return -RSBAC_EINVALIDVALUE;
05966         }
05967 
05968     if(flags & RSBAC_LIST_PERSIST)
05969       {
05970         if(RSBAC_IS_AUTO_DEV(device))
05971           device = rsbac_root_dev;
05972         if(!RSBAC_MAJOR(device))
05973           flags &= ~RSBAC_LIST_PERSIST;
05974       }
05975 
05976 #ifdef CONFIG_RSBAC_DEBUG
05977     if(rsbac_debug_lists)
05978       {
05979         rsbac_printk(KERN_DEBUG "rsbac_list_register: registering list %s for device %02u:%02u.\n",
05980                name, RSBAC_MAJOR(device),RSBAC_MINOR(device));
05981       }
05982 #endif
05983     new_reg_item_p = create_reg(info_p, flags, compare, get_conv, def_data, name, device);
05984     if(!new_reg_item_p)
05985       {
05986         return -RSBAC_ECOULDNOTADDITEM;
05987       }
05988     /* Restore from disk, but only for real device mounts */
05989     if(   (flags & RSBAC_LIST_PERSIST)
05990        && RSBAC_MAJOR(device)
05991       )
05992       {
05993 #ifdef CONFIG_RSBAC_DEBUG
05994         if(rsbac_debug_lists)
05995           {
05996             rsbac_printk(KERN_DEBUG "rsbac_list_register: restoring list %s from device %02u:%02u.\n",
05997                    name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
05998           }
05999 #endif
06000         err = read_list(new_reg_item_p);
06001         /* not found is no error */
06002         if(err == -RSBAC_ENOTFOUND)
06003           err = 0;
06004         else
06005         if(err)
06006           {
06007 #ifdef CONFIG_RSBAC_DEBUG
06008             if(rsbac_debug_lists)
06009               {
06010                 char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
06011 
06012                 if(tmp)
06013                   {
06014                     get_error_name(tmp, err);
06015                     rsbac_printk(KERN_DEBUG "rsbac_list_register: restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n",
06016                            name,
06017                            RSBAC_MAJOR(device),RSBAC_MINOR(device),
06018                            tmp);
06019                     rsbac_kfree(tmp);
06020                   }
06021               }
06022 #endif
06023             clear_reg(new_reg_item_p);
06024             return err;
06025           }
06026 #ifdef CONFIG_RSBAC_DEBUG
06027         else
06028           {
06029             if(rsbac_debug_lists)
06030               {
06031                 rsbac_printk(KERN_DEBUG "rsbac_list_register: restoring list %s from device %02u:%02u was successful.\n",
06032                        name,
06033                        RSBAC_MAJOR(device),RSBAC_MINOR(device));
06034               }
06035           }
06036 #endif
06037       }
06038 
06039     rsbac_write_lock(&reg_head.lock, &lock_flags);
06040     reg_item_p = add_reg(new_reg_item_p);
06041     rsbac_write_unlock(&reg_head.lock, &lock_flags);
06042     if(!reg_item_p)
06043       {
06044         rsbac_printk(KERN_WARNING
06045                "rsbac_list_register: inserting list %s failed!\n",
06046                name);
06047         /* cleanup */
06048         clear_reg(new_reg_item_p);
06049         return -RSBAC_ECOULDNOTADDITEM;
06050       }
06051 
06052     /* finish */
06053 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06054     /* create proc entry, if requested */
06055     if(flags & RSBAC_LIST_BACKUP)
06056       {
06057         reg_item_p->proc_entry_p = create_proc_entry(reg_item_p->name,
06058                                                      S_IFREG | S_IRUGO,
06059                                                      proc_rsbac_backup_p);
06060         if(reg_item_p->proc_entry_p)
06061           {
06062             reg_item_p->proc_entry_p->read_proc = backup_proc_read;
06063             reg_item_p->proc_entry_p->data = reg_item_p;
06064           }
06065       }
06066     else
06067       {
06068         reg_item_p->proc_entry_p = NULL;
06069       }
06070 #endif
06071     *handle_p = reg_item_p;
06072     return err;
06073   }
06074 
06075 /* register a new list of lists */
06076 /*
06077  * If list with same name exists in memory, error -RSBAC_EEXISTS is returned.
06078  * If list with same name and key exists on device, it is restored depending on the flags.
06079  * If list with same name, but different key exists, access is denied (error -EPERM).
06080  *
06081  * ds_version: for binary modules, must be RSBAC_LIST_VERSION. If version differs, return error.
06082  * handle_p: for all list accesses, an opaque handle is put into *handle_p.
06083  * key: positive, secret __u32 key, which must be the same as in on-disk version, if persistent
06084  * list_version: positive __u32 version number for the list. If old on-disk version is
06085    different, upconversion is tried (depending on flags and get_conv function)
06086  * flags: see flag values
06087  * desc_size: size of the descriptor (error is returned, if value is 0 or list exists and value differs)
06088  * subdesc_size: size of the sublist descriptor (error is returned, if value is 0 or list exists
06089    and value differs)
06090  * data_size: size of data (error is returned, if list exists and value differs). Can be 0 for sets.
06091  * subdata_size: size of sublist data (error is returned, if list exists and value differs).
06092    Can be 0 for sets.
06093  * compare: for lookup and list optimization, can be NULL, then
06094    memcmp(desc1, desc2, desc_size) is used
06095  * subcompare: for item lookup and optimization of sublist, can be NULL, then
06096    memcmp(desc1, desc2, desc_size) is used
06097  * def_data: default data value for flag RSBAC_LIST_DEF_DATA
06098    (if NULL, flag is cleared)
06099  * def_subdata: default subdata value for flag RSBAC_LIST_DEF_SUBDATA
06100    (if NULL, flag is cleared)
06101  * name: the on-disk name, must be distinct and max. 7 or 8.2 chars
06102    (only used for info, if non-persistent)
06103  * device: the device to read list from or to save list to - use 0 for root dev
06104    (ignored, if non-persistent)
06105  */
06106 
06107 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06108 EXPORT_SYMBOL(rsbac_list_lol_register);
06109 #endif
06110 int rsbac_list_lol_register(
06111   rsbac_version_t ds_version,
06112   rsbac_list_handle_t *handle_p,
06113   struct rsbac_list_lol_info_t * info_p,
06114   u_int flags,
06115   rsbac_list_compare_function_t * compare,
06116   rsbac_list_compare_function_t * subcompare,
06117   rsbac_list_get_conv_t * get_conv,
06118   rsbac_list_get_conv_t * get_subconv,
06119   void * def_data,
06120   void * def_subdata,
06121   char * name,
06122   kdev_t device)
06123   {
06124     struct rsbac_list_lol_reg_item_t * reg_item_p;
06125     struct rsbac_list_lol_reg_item_t * new_reg_item_p;
06126     u_long lock_flags;
06127     int    err = 0;
06128 
06129     if(ds_version != RSBAC_LIST_VERSION)
06130       return -RSBAC_EINVALIDVERSION;
06131     if(!handle_p)
06132       return -RSBAC_EINVALIDPOINTER;
06133     *handle_p = NULL;
06134     if(!info_p->key || !info_p->version || !info_p->desc_size)
06135       return -RSBAC_EINVALIDVALUE;
06136     if(info_p->max_age > RSBAC_LIST_MAX_AGE_LIMIT)
06137       return -RSBAC_EINVALIDVALUE;
06138     if(info_p->desc_size + info_p->data_size > RSBAC_LIST_MAX_ITEM_SIZE)
06139       return -RSBAC_EINVALIDVALUE;
06140     if(info_p->subdesc_size + info_p->subdata_size > RSBAC_LIST_MAX_ITEM_SIZE)
06141       return -RSBAC_EINVALIDVALUE;
06142     if(!list_initialized)
06143       return -RSBAC_ENOTINITIALIZED;
06144     if(name)
06145       {
06146         struct rsbac_list_reg_item_t     * std_reg_item_p;
06147 
06148         rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06149         reg_item_p = lookup_lol_reg_name(name, device);
06150         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06151         if(reg_item_p)
06152           {
06153 #ifdef CONFIG_RSBAC_DEBUG
06154             if(rsbac_debug_lists)
06155               {
06156                 rsbac_printk(KERN_DEBUG "rsbac_list_lol_register: list name %s already exists on device %02u:%02u!\n",
06157                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
06158               }
06159 #endif
06160             return -RSBAC_EEXISTS;
06161           }
06162         rsbac_read_lock(&reg_head.lock, &lock_flags);
06163         std_reg_item_p = lookup_reg_name(name, device);
06164         rsbac_read_unlock(&reg_head.lock, &lock_flags);
06165         if(std_reg_item_p)
06166           {
06167 #ifdef CONFIG_RSBAC_DEBUG
06168             if(rsbac_debug_lists)
06169               {
06170                 rsbac_printk(KERN_DEBUG "rsbac_list_register: list name %s already exists on device %02u:%02u!\n",
06171                        name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
06172               }
06173 #endif
06174             return -RSBAC_EEXISTS;
06175           }
06176       }
06177     else
06178       if(flags & RSBAC_LIST_PERSIST)
06179         {
06180           rsbac_printk(KERN_WARNING
06181                  "rsbac_list_lol_register: trial to register persistent list of lists without name.\n");
06182           return -RSBAC_EINVALIDVALUE;
06183         }
06184 
06185     if(flags & RSBAC_LIST_PERSIST)
06186       {
06187         if(RSBAC_IS_AUTO_DEV(device))
06188           device = rsbac_root_dev;
06189         if(!RSBAC_MAJOR(device))
06190           flags &= ~RSBAC_LIST_PERSIST;
06191       }
06192 
06193 #ifdef CONFIG_RSBAC_DEBUG
06194     if(rsbac_debug_lists)
06195       {
06196         rsbac_printk(KERN_DEBUG "rsbac_list_lol_register: registering list of lists %s.\n",
06197                name);
06198       }
06199 #endif
06200     new_reg_item_p = create_lol_reg(info_p, flags, compare, subcompare,
06201                                     get_conv, get_subconv,
06202                                     def_data, def_subdata,
06203                                     name, device);
06204     if(!new_reg_item_p)
06205       {
06206         return -RSBAC_ECOULDNOTADDITEM;
06207       }
06208     /* Restore from disk */
06209     if(flags & RSBAC_LIST_PERSIST)
06210       {
06211 #ifdef CONFIG_RSBAC_DEBUG
06212         if(rsbac_debug_lists)
06213           {
06214             rsbac_printk(KERN_DEBUG "rsbac_list_lol_register: restoring list %s from device %02u:%02u.\n",
06215                    name, RSBAC_MAJOR(device), RSBAC_MINOR(device));
06216           }
06217 #endif
06218         err = read_lol_list(new_reg_item_p);
06219         /* not found is no error */
06220         if(err == -RSBAC_ENOTFOUND)
06221           err = 0;
06222         else
06223         if(err)
06224           {
06225 #ifdef CONFIG_RSBAC_DEBUG
06226             if(rsbac_debug_lists)
06227               {
06228                 char * tmp = rsbac_kmalloc(RSBAC_MAXNAMELEN);
06229 
06230                 if(tmp)
06231                   {
06232                     get_error_name(tmp, err);
06233                     rsbac_printk(KERN_DEBUG "rsbac_list_lol_register: restoring list %s from device %02u:%02u failed with error %s, unregistering list.\n",
06234                            name,
06235                            RSBAC_MAJOR(device),RSBAC_MINOR(device),
06236                            tmp);
06237                     rsbac_kfree(tmp);
06238                   }
06239               }
06240 #endif
06241             clear_lol_reg(new_reg_item_p);
06242             return err;
06243           }
06244 #ifdef CONFIG_RSBAC_DEBUG
06245         else
06246           {
06247             if(rsbac_debug_lists)
06248               {
06249                 rsbac_printk(KERN_DEBUG "rsbac_list_lol_register: restoring list %s from device %02u:%02u was successful.\n",
06250                        name,
06251                        RSBAC_MAJOR(device),RSBAC_MINOR(device));
06252               }
06253           }
06254 #endif
06255       }
06256 
06257     rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06258     reg_item_p = add_lol_reg(new_reg_item_p);
06259     rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06260     if(!reg_item_p)
06261       {
06262         rsbac_printk(KERN_WARNING
06263                "rsbac_list_lol_register: inserting list %s failed!\n",
06264                name);
06265         /* cleanup */
06266         clear_lol_reg(new_reg_item_p);
06267         return -RSBAC_ECOULDNOTADDITEM;
06268       }
06269 
06270     /* finish */
06271 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06272     /* create proc entry, if requested */
06273     if(flags & RSBAC_LIST_BACKUP)
06274       {
06275         reg_item_p->proc_entry_p = create_proc_entry(reg_item_p->name,
06276                                                      S_IFREG | S_IRUGO,
06277                                                      proc_rsbac_backup_p);
06278         if(reg_item_p->proc_entry_p)
06279           {
06280             reg_item_p->proc_entry_p->read_proc = lol_backup_proc_read;
06281             reg_item_p->proc_entry_p->data = reg_item_p;
06282           }
06283       }
06284     else
06285       {
06286         reg_item_p->proc_entry_p = NULL;
06287       }
06288 #endif
06289     *handle_p = reg_item_p;
06290     return err;
06291   }
06292 
06293 /* destroy list */
06294 /* list is destroyed, disk file is deleted */
06295 /* list must have been opened with register */
06296 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06297 EXPORT_SYMBOL(rsbac_list_destroy);
06298 #endif
06299 int rsbac_list_destroy(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
06300   {
06301     struct rsbac_list_reg_item_t * reg_item_p;
06302     u_long lock_flags;
06303     int err = 0;
06304 
06305     if(!handle_p)
06306       return -RSBAC_EINVALIDPOINTER;
06307     if(!*handle_p)
06308       return -RSBAC_EINVALIDVALUE;
06309     if(!list_initialized)
06310       return -RSBAC_ENOTINITIALIZED;
06311 
06312     rsbac_write_lock(&reg_head.lock, &lock_flags);
06313     reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
06314     if(!reg_item_p)
06315       {
06316         rsbac_write_unlock(&reg_head.lock, &lock_flags);
06317         rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list failed due to invalid handle!\n");
06318         return -RSBAC_EINVALIDVALUE;
06319       }
06320     if(reg_item_p->info.key != key)
06321       {
06322         rsbac_write_unlock(&reg_head.lock, &lock_flags);
06323         rsbac_printk(KERN_WARNING "rsbac_list_destroy: destroying list %s denied due to invalid key!\n",
06324                reg_item_p->name);
06325         return -EPERM;
06326       }
06327 #ifdef CONFIG_RSBAC_DEBUG
06328     if(rsbac_debug_lists)
06329       {
06330         rsbac_printk(KERN_DEBUG "rsbac_list_destroy: destroying list %s.\n",
06331                reg_item_p->name);
06332       }
06333 #endif
06334 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06335     /* delete proc entry, if it exists */
06336     if(   (reg_item_p->flags & RSBAC_LIST_BACKUP)
06337        && reg_item_p->proc_entry_p
06338       )
06339       {
06340         remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06341         reg_item_p->proc_entry_p = NULL;
06342       }
06343 #endif
06344 
06345 #if 0
06346     if(reg_item_p->flags & RSBAC_LIST_PERSIST)
06347       err = unlink_list(reg_item_p);
06348 #endif
06349 
06350     remove_reg(reg_item_p);
06351     *handle_p = NULL; 
06352     rsbac_write_unlock(&reg_head.lock, &lock_flags);
06353     return err;
06354   }
06355 
06356 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06357 EXPORT_SYMBOL(rsbac_list_lol_destroy);
06358 #endif
06359 int rsbac_list_lol_destroy(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
06360   {
06361     struct rsbac_list_lol_reg_item_t * reg_item_p;
06362     u_long lock_flags;
06363     int err = 0;
06364 
06365     if(!handle_p)
06366       return -RSBAC_EINVALIDPOINTER;
06367     if(!*handle_p)
06368       return -RSBAC_EINVALIDVALUE;
06369     if(!list_initialized)
06370       return -RSBAC_ENOTINITIALIZED;
06371 
06372     rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06373     reg_item_p = lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
06374     if(!reg_item_p)
06375       {
06376         rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06377         rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list failed due to invalid handle!\n");
06378         return -RSBAC_EINVALIDVALUE;
06379       }
06380     if(reg_item_p->info.key != key)
06381       {
06382         rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06383         rsbac_printk(KERN_WARNING "rsbac_list_lol_destroy: destroying list %s denied due to invalid key %u!\n",
06384                reg_item_p->name,
06385                key);
06386         return -EPERM;
06387       }
06388 #ifdef CONFIG_RSBAC_DEBUG
06389     if(rsbac_debug_lists)
06390       {
06391         rsbac_printk(KERN_DEBUG "rsbac_list_lol_destroy: destroying list %s.\n",
06392                reg_item_p->name);
06393       }
06394 #endif
06395 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06396     /* delete proc entry, if it exists */
06397     if(   (reg_item_p->flags & RSBAC_LIST_BACKUP)
06398        && reg_item_p->proc_entry_p
06399       )
06400       {
06401         remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06402         reg_item_p->proc_entry_p = NULL;
06403       }
06404 #endif
06405 #if 0
06406     if(reg_item_p->flags & RSBAC_LIST_PERSIST)
06407       err = unlink_lol_list(reg_item_p);
06408 #endif
06409 
06410     remove_lol_reg(reg_item_p);
06411     *handle_p = NULL; 
06412     rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06413     return err;
06414   }
06415 
06416 /* detach from list */
06417 /* list is saved and removed from memory. Call register for new access. */
06418 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06419 EXPORT_SYMBOL(rsbac_list_detach);
06420 #endif
06421 int rsbac_list_detach(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
06422   {
06423     struct rsbac_list_reg_item_t * reg_item_p;
06424     u_long lock_flags;
06425     int err = 0;
06426 
06427     if(!handle_p)
06428       return -RSBAC_EINVALIDPOINTER;
06429     if(!*handle_p)
06430       return -RSBAC_EINVALIDVALUE;
06431     if(!list_initialized)
06432       return -RSBAC_ENOTINITIALIZED;
06433 
06434     rsbac_read_lock(&reg_head.lock, &lock_flags);
06435     reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) *handle_p);
06436     if(!reg_item_p)
06437       {
06438         rsbac_read_unlock(&reg_head.lock, &lock_flags);
06439         rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list failed due to invalid handle!\n");
06440         return -RSBAC_EINVALIDVALUE;
06441       }
06442     if(reg_item_p->info.key != key)
06443       {
06444         rsbac_read_unlock(&reg_head.lock, &lock_flags);
06445         rsbac_printk(KERN_WARNING "rsbac_list_detach: detaching list %s denied due to invalid key %u!\n",
06446                reg_item_p->name,
06447                key);
06448         return -EPERM;
06449       }
06450 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06451     /* delete proc entry, if it exists */
06452     if(   (reg_item_p->flags & RSBAC_LIST_BACKUP)
06453        && reg_item_p->proc_entry_p
06454       )
06455       {
06456         remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06457         reg_item_p->proc_entry_p = NULL;
06458       }
06459 #endif
06460 #ifndef CONFIG_RSBAC_NO_WRITE
06461     /* final write, if dirty etc. */
06462     if(   (reg_item_p->flags & RSBAC_LIST_PERSIST)
06463        && reg_item_p->dirty
06464        && !reg_item_p->no_write
06465       )
06466       {
06467         struct rsbac_list_write_head_t       write_head;
06468         struct rsbac_list_write_item_t     * write_item_p;
06469 
06470         reg_item_p->dirty = FALSE;
06471         err = fill_buffer(reg_item_p, &write_item_p);
06472         if(!err)
06473           {
06474             write_head.head = write_item_p;
06475             write_head.tail = write_item_p;
06476             write_head.total = write_item_p->buflen;
06477             write_head.count = 1;
06478             rsbac_read_unlock(&reg_head.lock, &lock_flags);
06479             rsbac_list_write_buffers(write_head, TRUE);
06480           }
06481         else
06482           {
06483             rsbac_read_unlock(&reg_head.lock, &lock_flags);
06484             if(err != -RSBAC_ENOTWRITABLE)
06485               {
06486                 rsbac_printk(KERN_WARNING
06487                        "rsbac_list_detach(): fill_buffer() for list %s returned error %i\n",
06488                        reg_item_p->name, err);
06489               }
06490           }
06491       }
06492     else
06493       rsbac_read_unlock(&reg_head.lock, &lock_flags);
06494 #else
06495     rsbac_read_unlock(&reg_head.lock, &lock_flags);
06496 #endif
06497     /* disable handle */
06498     *handle_p = NULL; 
06499     /* too bad that the list might have been changed again - we do not care anymore */
06500     rsbac_write_lock(&reg_head.lock, &lock_flags);
06501     remove_reg(reg_item_p);
06502     rsbac_write_unlock(&reg_head.lock, &lock_flags);
06503     return err;
06504   }
06505 
06506 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06507 EXPORT_SYMBOL(rsbac_list_lol_detach);
06508 #endif
06509 int rsbac_list_lol_detach(rsbac_list_handle_t * handle_p, rsbac_list_key_t key)
06510   {
06511     struct rsbac_list_lol_reg_item_t * reg_item_p;
06512     u_long lock_flags;
06513     int err = 0;
06514 
06515     if(!handle_p)
06516       return -RSBAC_EINVALIDPOINTER;
06517     if(!*handle_p)
06518       return -RSBAC_EINVALIDVALUE;
06519     if(!list_initialized)
06520       return -RSBAC_ENOTINITIALIZED;
06521 
06522     rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06523     reg_item_p = lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) *handle_p);
06524     if(!reg_item_p)
06525       {
06526         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06527         rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list failed due to invalid handle!\n");
06528         return -RSBAC_EINVALIDVALUE;
06529       }
06530     if(reg_item_p->info.key != key)
06531       {
06532         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06533         rsbac_printk(KERN_WARNING "rsbac_list_lol_detach: detaching list %s denied due to invalid key %u!\n",
06534                reg_item_p->name,
06535                key);
06536         return -EPERM;
06537       }
06538 #if defined(CONFIG_RSBAC_PROC) && defined(CONFIG_PROC_FS)
06539     /* delete proc entry, if it exists */
06540     if(   (reg_item_p->flags & RSBAC_LIST_BACKUP)
06541        && reg_item_p->proc_entry_p
06542       )
06543       {
06544         remove_proc_entry(reg_item_p->name, proc_rsbac_backup_p);
06545         reg_item_p->proc_entry_p = NULL;
06546       }
06547 #endif
06548 #ifndef CONFIG_RSBAC_NO_WRITE
06549     /* final write, if dirty etc. */
06550     if(   (reg_item_p->flags & RSBAC_LIST_PERSIST)
06551        && reg_item_p->dirty
06552        && !reg_item_p->no_write
06553       )
06554       {
06555         struct rsbac_list_lol_write_head_t       write_head;
06556         struct rsbac_list_lol_write_item_t     * write_item_p;
06557 
06558         reg_item_p->dirty = FALSE;
06559         err = fill_lol_buffer(reg_item_p, &write_item_p);
06560         if(!err)
06561           {
06562             write_head.head = write_item_p;
06563             write_head.tail = write_item_p;
06564             write_head.total = write_item_p->buflen;
06565             write_head.count = 1;
06566             rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06567             rsbac_list_write_lol_buffers(write_head, TRUE);
06568           }
06569         else
06570           {
06571             rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06572             if(err != -RSBAC_ENOTWRITABLE)
06573               {
06574                 rsbac_printk(KERN_WARNING
06575                        "rsbac_list_lol_detach(): fill_buffer() for list %s returned error %i\n",
06576                        reg_item_p->name, err);
06577               }
06578           }
06579       }
06580     else
06581       rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06582 #else
06583     rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06584 #endif
06585     /* disable handle */
06586     *handle_p = NULL; 
06587     /* too bad that the list might have been changed again - we do not care anymore */
06588     rsbac_write_lock(&lol_reg_head.lock, &lock_flags);
06589     remove_lol_reg(reg_item_p);
06590     rsbac_write_unlock(&lol_reg_head.lock, &lock_flags);
06591     return err;
06592   }
06593 
06594 /* set list's no_write flag */
06595 /* TRUE: do not write to disk, FALSE: writing allowed */
06596 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06597 EXPORT_SYMBOL(rsbac_list_no_write);
06598 #endif
06599 int rsbac_list_no_write(rsbac_list_handle_t handle, rsbac_list_key_t key, rsbac_boolean_t no_write)
06600   {
06601     struct rsbac_list_reg_item_t * reg_item_p;
06602     u_long lock_flags;
06603 
06604     if(   !handle
06605        || (   (no_write != FALSE )
06606            && (no_write != TRUE )
06607           )
06608       )
06609       return -RSBAC_EINVALIDVALUE;
06610     if(!list_initialized)
06611       return -RSBAC_ENOTINITIALIZED;
06612 
06613     rsbac_read_lock(&reg_head.lock, &lock_flags);
06614     reg_item_p = lookup_reg((struct rsbac_list_reg_item_t *) handle);
06615     if(!reg_item_p)
06616       {
06617         rsbac_read_unlock(&reg_head.lock, &lock_flags);
06618         rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list denied due to invalid handle!\n");
06619         return -RSBAC_EINVALIDVALUE;
06620       }
06621     if(reg_item_p->info.key != key)
06622       {
06623         rsbac_read_unlock(&reg_head.lock, &lock_flags);
06624         rsbac_printk(KERN_WARNING "rsbac_list_no_write: setting no_write for list %s denied due to invalid key %u!\n",
06625                reg_item_p->name,
06626                key);
06627         return -EPERM;
06628       }
06629     reg_item_p->no_write = no_write;
06630     rsbac_read_unlock(&reg_head.lock, &lock_flags);
06631     return 0;
06632   }
06633 
06634 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06635 EXPORT_SYMBOL(rsbac_list_lol_no_write);
06636 #endif
06637 int rsbac_list_lol_no_write(rsbac_list_handle_t handle, rsbac_list_key_t key, rsbac_boolean_t no_write)
06638   {
06639     struct rsbac_list_lol_reg_item_t * reg_item_p;
06640     u_long lock_flags;
06641 
06642     if(   !handle
06643        || (   (no_write != FALSE )
06644            && (no_write != TRUE )
06645           )
06646       )
06647       return -RSBAC_EINVALIDVALUE;
06648     if(!list_initialized)
06649       return -RSBAC_ENOTINITIALIZED;
06650 
06651     rsbac_read_lock(&lol_reg_head.lock, &lock_flags);
06652     reg_item_p = lookup_lol_reg((struct rsbac_list_lol_reg_item_t *) handle);
06653     if(!reg_item_p)
06654       {
06655         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06656         rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list denied due to invalid handle!\n");
06657         return -RSBAC_EINVALIDVALUE;
06658       }
06659     if(reg_item_p->info.key != key)
06660       {
06661         rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06662         rsbac_printk(KERN_WARNING "rsbac_list_lol_no_write: setting no_write for list %s denied due to invalid key %u!\n",
06663                reg_item_p->name,
06664                key);
06665         return -EPERM;
06666       }
06667     reg_item_p->no_write = no_write;
06668     rsbac_read_unlock(&lol_reg_head.lock, &lock_flags);
06669     return 0;
06670   }
06671 
06672 
06673 /********************/
06674 /* Transactions     */
06675 /********************/
06676 
06677 #ifdef CONFIG_RSBAC_LIST_TRANS
06678 static int do_commit(rsbac_list_ta_number_t ta_number)
06679   {
06680     /* Get both big list and lol_list locks,
06681      * for all lists and lol_lists
06682      *   if ta_copied
06683      *     free all items
06684      *     move ta_head to head, ta_tail to tail, ta_curr to curr
06685      *     reset ta_copied
06686      *     set dirty
06687      *   endif
06688      * release both big locks
06689      */
06690     struct rsbac_list_reg_item_t     * list;
06691     struct rsbac_list_lol_reg_item_t * lol_list;
06692     u_long lock_flags;
06693     u_long lol_lock_flags;
06694 
06695     rsbac_write_lock(&reg_head.lock, &lock_flags);
06696     rsbac_write_lock(&lol_reg_head.lock, &lol_lock_flags);
06697     list = reg_head.head;
06698     while(list)
06699       {
06700         if(list->ta_copied == ta_number)
06701           {
06702             remove_all_items(list);
06703             list->head = list->ta_head;
06704             list->tail = list->ta_tail;
06705             list->curr = list->ta_curr;
06706             list->count = list->ta_count;
06707             list->ta_head = NULL;
06708             list->ta_tail = NULL;
06709             list->ta_curr = NULL;
06710             list->ta_count = 0;
06711             list->ta_copied = 0;
06712             list->dirty = TRUE;
06713           }
06714         list = list->next;
06715       }
06716     lol_list = lol_reg_head.head;
06717     while(lol_list)
06718       {
06719         if(lol_list->ta_copied == ta_number)
06720           {
06721             remove_all_lol_items(lol_list);
06722             lol_list->head = lol_list->ta_head;
06723             lol_list->tail = lol_list->ta_tail;
06724             lol_list->curr = lol_list->ta_curr;
06725             lol_list->count = lol_list->ta_count;
06726             lol_list->ta_head = NULL;
06727             lol_list->ta_tail = NULL;
06728             lol_list->ta_curr = NULL;
06729             lol_list->ta_count = 0;
06730             lol_list->ta_copied = 0;
06731             lol_list->dirty = TRUE;
06732           }
06733         lol_list = lol_list->next;
06734       }
06735     rsbac_write_unlock(&lol_reg_head.lock, &lol_lock_flags);
06736     rsbac_write_unlock(&reg_head.lock, &lock_flags);
06737 
06738     return 0;
06739   }
06740 
06741 int rsbac_list_ta_commit(rsbac_list_ta_number_t ta_number,
06742                          char * password)
06743   {
06744     int err;
06745     struct rsbac_list_ta_data_t ta_data;
06746 
06747     err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06748     if(err)
06749       return err;
06750     if(   (ta_data.commit_uid != RSBAC_ALL_USERS)
06751        && (ta_data.commit_uid != current->uid)
06752       )
06753       return -EPERM;
06754 
06755     if(ta_data.password[0])
06756       {
06757         if(!password)
06758           return -EPERM;
06759         if(strncmp(ta_data.password, password, RSBAC_LIST_TA_MAX_PASSLEN))
06760           return -EPERM;
06761       }
06762     spin_lock(&ta_lock);
06763     if(ta_committing || ta_forgetting)
06764       {
06765         spin_unlock(&ta_lock);
06766         return -RSBAC_EBUSY;
06767       }
06768     ta_committing = TRUE;
06769     spin_unlock(&ta_lock);
06770 
06771     rsbac_printk(KERN_INFO "rsbac_list_ta_commit(): committing transaction %u\n",
06772                  ta_number);
06773 
06774     err = do_commit(ta_number);
06775     if(!err)
06776       rsbac_list_remove(ta_handle, &ta_number);
06777     ta_committing = FALSE;
06778     return err;
06779   }
06780 
06781 static int do_forget(rsbac_list_ta_number_t ta_number)
06782   {
06783     struct rsbac_list_reg_item_t     * list;
06784     struct rsbac_list_lol_reg_item_t * lol_list;
06785     u_long lock_flags;
06786     u_long lol_lock_flags;
06787 
06788     spin_lock(&ta_lock);
06789     if(ta_committing || ta_forgetting)
06790       {
06791         spin_unlock(&ta_lock);
06792         return -RSBAC_EBUSY;
06793       }
06794     ta_forgetting = TRUE;
06795     spin_unlock(&ta_lock);
06796 
06797     rsbac_printk(KERN_INFO "rsbac_list_ta_forget(): removing transaction %u\n",
06798                  ta_number);
06799 
06800     /* Get both big list and lol_list locks,
06801      * for all lists and lol_lists
06802      *   if ta_copied
06803      *     free all ta_items
06804      *     reset ta_copied
06805      *   endif
06806      * release both big locks
06807      */
06808     rsbac_write_lock(&reg_head.lock, &lock_flags);
06809     rsbac_write_lock(&lol_reg_head.lock, &lol_lock_flags);
06810     list = reg_head.head;
06811     while(list)
06812       {
06813         if(list->ta_copied == ta_number)
06814           {
06815             ta_remove_all_items(list);
06816             list->ta_copied = 0;
06817           }
06818         list = list->next;
06819       }
06820     lol_list = lol_reg_head.head;
06821     while(lol_list)
06822       {
06823         if(lol_list->ta_copied == ta_number)
06824           {
06825             ta_remove_all_lol_items(lol_list);
06826             lol_list->ta_copied = 0;
06827           }
06828         lol_list = lol_list->next;
06829       }
06830     rsbac_write_unlock(&lol_reg_head.lock, &lol_lock_flags);
06831     rsbac_write_unlock(&reg_head.lock, &lock_flags);
06832 
06833     rsbac_list_remove(ta_handle, &ta_number);
06834     ta_forgetting = FALSE;
06835 
06836     return 0;
06837   }
06838 
06839 int rsbac_list_ta_forget(rsbac_list_ta_number_t ta_number,
06840                          char * password)
06841   {
06842     int err;
06843     struct rsbac_list_ta_data_t ta_data;
06844 
06845     err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06846     if(err)
06847       return err;
06848     if(   (ta_data.commit_uid != RSBAC_ALL_USERS)
06849        && (ta_data.commit_uid != current->uid)
06850       )
06851       return -EPERM;
06852     if(ta_data.password[0])
06853       {
06854         if(!password)
06855           return -EPERM;
06856         if(strncmp(ta_data.password, password, RSBAC_LIST_TA_MAX_PASSLEN))
06857           return -EPERM;
06858       }
06859     return do_forget(ta_number);
06860   }
06861 
06862 int rsbac_list_ta_begin(
06863   rsbac_time_t ttl,
06864   rsbac_list_ta_number_t * ta_number_p,
06865   rsbac_uid_t commit_uid,
06866   char * password)
06867   {
06868     int err;
06869     rsbac_list_ta_number_t ta;
06870     struct rsbac_list_ta_data_t ta_data;
06871 
06872 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
06873     get_random_bytes(&ta, sizeof(ta));
06874 #else
06875     ta = ta_next++;
06876 #endif
06877     while(rsbac_list_exist(ta_handle, &ta))
06878       {
06879 #ifdef CONFIG_RSBAC_LIST_TRANS_RANDOM_TA
06880         get_random_bytes(&ta, sizeof(ta));
06881 #else
06882         ta = ta_next++;
06883 #endif
06884       }
06885     if(!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
06886       ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
06887 
06888     rsbac_printk(KERN_INFO "rsbac_list_ta_begin(): starting transaction %u with ttl of %us\n",
06889                  ta, ttl);
06890 
06891     ta_data.start = RSBAC_CURRENT_TIME;
06892     ta_data.timeout = ta_data.start + ttl;
06893     ta_data.commit_uid = commit_uid;
06894     if(password)
06895       {
06896         strncpy(ta_data.password, password, RSBAC_LIST_TA_MAX_PASSLEN - 1);
06897         ta_data.password[RSBAC_LIST_TA_MAX_PASSLEN - 1] = 0;
06898       }
06899     else
06900       ta_data.password[0] = 0;
06901     err = rsbac_list_add(ta_handle, &ta, &ta_data);
06902     if(!err)
06903       *ta_number_p = ta;
06904     return err;
06905   }
06906 
06907 int rsbac_list_ta_refresh(
06908   rsbac_time_t ttl,
06909   rsbac_list_ta_number_t ta_number,
06910   char * password)
06911   {
06912     struct rsbac_list_ta_data_t ta_data;
06913     int err;
06914 
06915     if(!rsbac_list_exist(ta_handle, &ta_number))
06916       {
06917         return -RSBAC_ENOTFOUND;
06918       }
06919     if(!ttl || (ttl > CONFIG_RSBAC_LIST_TRANS_MAX_TTL))
06920       ttl = CONFIG_RSBAC_LIST_TRANS_MAX_TTL;
06921 
06922     rsbac_printk(KERN_INFO "rsbac_list_ta_refresh(): refreshing transaction %u for %us\n",
06923                  ta_number, ttl);
06924 
06925     err = rsbac_list_get_data(ta_handle, &ta_number, &ta_data);
06926     if(err)
06927       return err;
06928     if(   (ta_data.commit_uid != RSBAC_ALL_USERS)
06929        && (ta_data.commit_uid != current->uid)
06930       )
06931       return -EPERM;
06932     if(ta_data.password[0])
06933       {
06934         if(!password)
06935           return -EPERM;
06936         if(strncmp(ta_data.password, password, RSBAC_LIST_TA_MAX_PASSLEN))
06937           return -EPERM;
06938       }
06939     ta_data.timeout = RSBAC_CURRENT_TIME + ttl;
06940     return rsbac_list_add(ta_handle, &ta_number, &ta_data);
06941   }
06942 #endif
06943 
06944 
06945 /********************/
06946 /* List Access      */
06947 /********************/
06948 
06949 /* add item */
06950 /* if item for desc exists, the data is updated */
06951 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
06952 EXPORT_SYMBOL(rsbac_ta_list_add_ttl);
06953 #endif
06954 int rsbac_ta_list_add_ttl(
06955   rsbac_list_ta_number_t ta_number,
06956   rsbac_list_handle_t handle,
06957   rsbac_time_t ttl,
06958   void * desc,
06959   void * data)
06960   {
06961     struct rsbac_list_reg_item_t * list;
06962     struct rsbac_list_item_t     * item_p;
06963     u_long lock_flags, rlock_flags;
06964 
06965     if(!handle || !desc)
06966       return -RSBAC_EINVALIDVALUE;
06967     if(!list_initialized)
06968       return -RSBAC_ENOTINITIALIZED;
06969 
06970     list = (struct rsbac_list_reg_item_t *) handle;
06971     if(!list || (list->self != list))
06972       return -RSBAC_EINVALIDVALUE;
06973 
06974 #ifdef CONFIG_RSBAC_LIST_TRANS
06975     if(ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
06976       return -RSBAC_EINVALIDTRANSACTION;
06977 #endif
06978 
06979     rsbac_read_lock(&reg_head.lock, &rlock_flags);
06980     if(list->info.data_size && !data)
06981       {
06982         rsbac_read_unlock(&reg_head.lock, &rlock_flags);
06983         return -RSBAC_EINVALIDVALUE;
06984       }
06985 
06986 /*
06987 #ifdef CONFIG_RSBAC_DEBUG
06988     if(rsbac_debug_lists)
06989       rsbac_printk(KERN_DEBUG "rsbac_ta_list_add_ttl: adding to list %s.\n",
06990              list->name);
06991 #endif
06992 */
06993     if(ttl && (ttl != RSBAC_LIST_TTL_KEEP))
06994       {
06995         if(ttl > RSBAC_LIST_MAX_AGE_LIMIT)
06996           ttl = RSBAC_LIST_MAX_AGE_LIMIT;
06997         ttl += RSBAC_CURRENT_TIME;
06998       }
06999     rsbac_write_lock(&list->lock, &lock_flags);
07000 
07001 #ifdef CONFIG_RSBAC_LIST_TRANS
07002     if(!ta_number)
07003 #endif
07004       {
07005         item_p = lookup_item(list, desc);
07006         if(item_p)
07007           { /* exists -> update data, if any */
07008             if(ttl != RSBAC_LIST_TTL_KEEP)
07009               item_p->max_age = ttl;
07010             if(data && list->info.data_size)
07011               {
07012                 if(   list->def_data
07013                    && !item_p->max_age
07014                    && !memcmp(list->def_data, data, list->info.data_size)
07015                   )
07016                   do_remove_item(list, item_p);
07017                 else
07018                   memcpy(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
07019                          data, list->info.data_size);
07020               }
07021           }
07022         else
07023           {
07024             if(ttl == RSBAC_LIST_TTL_KEEP)
07025               ttl = 0;
07026             if(   !list->def_data
07027                || memcmp(list->def_data, data, list->info.data_size)
07028               )
07029               add_item(list, ttl, desc, data);
07030           }
07031         touch(list);
07032         list->dirty = TRUE;
07033       }
07034 #ifdef CONFIG_RSBAC_LIST_TRANS
07035     if(   list->ta_copied
07036        || ta_number
07037       )
07038       {
07039         if(!list->ta_copied)
07040           ta_copy(ta_number, list);
07041         else
07042           if(ta_number)
07043             {
07044               if(list->ta_copied != ta_number)
07045                 {
07046                   rsbac_write_unlock(&list->lock, &lock_flags);
07047                   rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07048                   return -RSBAC_EBUSY;
07049                 }
07050             }
07051           else
07052             ta_number = list->ta_copied;
07053         item_p = ta_lookup_item(ta_number, list, desc);
07054         if(item_p)
07055           { /* exists -> update data, if any */
07056             if(ttl != RSBAC_LIST_TTL_KEEP)
07057               item_p->max_age = ttl;
07058             if(data && list->info.data_size)
07059               {
07060                 if(   list->def_data
07061                    && !item_p->max_age
07062                    && !memcmp(list->def_data, data, list->info.data_size)
07063                   )
07064                   ta_do_remove_item(list, item_p);
07065                 else
07066                   memcpy(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
07067                          data, list->info.data_size);
07068               }
07069           }
07070         else
07071           {
07072             if(ttl == RSBAC_LIST_TTL_KEEP)
07073               ttl = 0;
07074             if(   !list->def_data
07075                || memcmp(list->def_data, data, list->info.data_size)
07076               )
07077               ta_add_item(ta_number, list, ttl, desc, data);
07078           }
07079       }
07080 #endif
07081     rsbac_write_unlock(&list->lock, &lock_flags);
07082     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07083     return 0;
07084   }
07085 
07086 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07087 EXPORT_SYMBOL(rsbac_list_add_ttl);
07088 #endif
07089 int rsbac_list_add_ttl(
07090   rsbac_list_handle_t handle,
07091   rsbac_time_t ttl,
07092   void * desc,
07093   void * data)
07094   {
07095     return rsbac_ta_list_add_ttl(0, handle, ttl, desc, data);
07096   }
07097 
07098 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07099 EXPORT_SYMBOL(rsbac_list_add);
07100 #endif
07101 int rsbac_list_add(
07102   rsbac_list_handle_t handle,
07103   void * desc,
07104   void * data)
07105   {
07106     return rsbac_ta_list_add_ttl(0, handle, RSBAC_LIST_TTL_KEEP, desc, data);
07107   }
07108 
07109 /* add list of lists sublist item */
07110 /* if item for desc exists, the data is updated */
07111 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07112 EXPORT_SYMBOL(rsbac_ta_list_lol_subadd_ttl);
07113 #endif
07114 int rsbac_ta_list_lol_subadd_ttl(
07115   rsbac_list_ta_number_t ta_number,
07116   rsbac_list_handle_t handle,
07117   rsbac_time_t ttl,
07118   void * desc,
07119   void * subdesc,
07120   void * subdata)
07121   {
07122     struct rsbac_list_lol_reg_item_t * list;
07123     struct rsbac_list_lol_item_t     * sublist;
07124     struct rsbac_list_item_t     * item_p;
07125     u_long lock_flags, rlock_flags;
07126     int err = 0;
07127 
07128     if(!handle || !desc || !subdesc)
07129       return -RSBAC_EINVALIDVALUE;
07130     if(!list_initialized)
07131       return -RSBAC_ENOTINITIALIZED;
07132 
07133     list = (struct rsbac_list_lol_reg_item_t *) handle;
07134     if(!list || (list->self != list))
07135       return -RSBAC_EINVALIDVALUE;
07136 
07137 #ifdef CONFIG_RSBAC_LIST_TRANS
07138     if(ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
07139       return -RSBAC_EINVALIDTRANSACTION;
07140 #endif
07141 
07142     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07143     if(list->info.subdata_size && !subdata)
07144       {
07145         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07146         return -RSBAC_EINVALIDVALUE;
07147       }
07148 
07149 /*
07150 #ifdef CONFIG_RSBAC_DEBUG
07151     if(rsbac_debug_lists)
07152       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subadd: adding to list %s.\n",
07153              list->name);
07154 #endif
07155 */
07156     rsbac_write_lock(&list->lock, &lock_flags);
07157 
07158 #ifdef CONFIG_RSBAC_LIST_TRANS
07159     if(!ta_number)
07160 #endif
07161       {
07162         sublist = lookup_lol_item(list, desc);
07163         if(   !sublist
07164            && (list->flags & RSBAC_LIST_DEF_DATA)
07165           )
07166           sublist = add_lol_item(list, 0, desc, list->def_data);
07167         if(sublist)
07168           {
07169             if(   sublist->max_age
07170                && (sublist->max_age <= RSBAC_CURRENT_TIME)
07171               )
07172               {
07173                 remove_lol_item(list, desc);
07174                 err = -RSBAC_EINVALIDTARGET;
07175               }
07176             else
07177               {
07178                 /* exists -> lookup subitem */
07179                 if(ttl && (ttl != RSBAC_LIST_TTL_KEEP))
07180                   {
07181                     if(ttl > RSBAC_LIST_MAX_AGE_LIMIT)
07182                       ttl = RSBAC_LIST_MAX_AGE_LIMIT;
07183                     ttl += RSBAC_CURRENT_TIME;
07184                   }
07185                 item_p = lookup_lol_subitem(list, sublist, subdesc);
07186                 if(item_p)
07187                   { /* exists -> update data, if any */
07188                     if(ttl != RSBAC_LIST_TTL_KEEP)
07189                       item_p->max_age = ttl;
07190                     if(subdata && list->info.subdata_size)
07191                       {
07192                         if(   list->def_subdata
07193                            && !item_p->max_age
07194                            && !memcmp(list->def_subdata, subdata, list->info.subdata_size)
07195                           )
07196                           do_remove_lol_subitem(sublist, item_p);
07197                         else
07198                           memcpy(((char *) item_p) + sizeof(*item_p) + list->info.subdesc_size,
07199                                  subdata,
07200                                  list->info.subdata_size);
07201                       }
07202                   }
07203                 else
07204                   {
07205                     if(ttl == RSBAC_LIST_TTL_KEEP)
07206                       ttl = 0;
07207                     if(   !list->def_subdata
07208                        || memcmp(list->def_subdata, subdata, list->info.subdata_size)
07209                       )
07210                       add_lol_subitem(list, sublist, ttl, subdesc, subdata);
07211                   }
07212                 lol_touch(list);
07213                 list->dirty = TRUE;
07214               }
07215           }
07216         else
07217           {
07218             err = -RSBAC_EINVALIDTARGET;
07219             goto out_unlock;
07220           }
07221       }
07222 #ifdef CONFIG_RSBAC_LIST_TRANS
07223     if(list->ta_copied || ta_number)
07224       {
07225         if(!list->ta_copied)
07226           {
07227             if((err = ta_lol_copy(ta_number,list)))
07228               goto out_unlock;
07229           }
07230         else
07231           if(ta_number)
07232             {
07233               if(list->ta_copied != ta_number)
07234                 {
07235                   err = -RSBAC_EBUSY;
07236                   goto out_unlock;
07237                 }
07238             }
07239           else
07240             ta_number = list->ta_copied;
07241         sublist = ta_lookup_lol_item(ta_number, list, desc);
07242         if(   !sublist
07243            && (list->flags & RSBAC_LIST_DEF_DATA)
07244           )
07245           sublist = ta_add_lol_item(ta_number, list, 0, desc, list->def_data);
07246         if(sublist)
07247           {
07248             if(   sublist->max_age
07249                && (sublist->max_age <= RSBAC_CURRENT_TIME)
07250               )
07251               {
07252                 ta_remove_lol_item(ta_number, list, desc);
07253                 err = -RSBAC_EINVALIDTARGET;
07254               }
07255             else
07256               {
07257                 /* exists -> lookup subitem */
07258                 if(ttl && (ttl != RSBAC_LIST_TTL_KEEP))
07259                   {
07260                     if(ttl > RSBAC_LIST_MAX_AGE_LIMIT)
07261                       ttl = RSBAC_LIST_MAX_AGE_LIMIT;
07262                     ttl += RSBAC_CURRENT_TIME;
07263                   }
07264                 item_p = lookup_lol_subitem(list, sublist, subdesc);
07265                 if(item_p)
07266                   { /* exists -> update data, if any */
07267                     if(ttl != RSBAC_LIST_TTL_KEEP)
07268                       item_p->max_age = ttl;
07269                     if(subdata && list->info.subdata_size)
07270                       {
07271                         if(   list->def_subdata
07272                            && !item_p->max_age
07273                            && !memcmp(list->def_subdata, subdata, list->info.subdata_size)
07274                           )
07275                           do_remove_lol_subitem(sublist, item_p);
07276                         else
07277                           memcpy(((char *) item_p) + sizeof(*item_p) + list->info.subdesc_size,
07278                                  subdata,
07279                                  list->info.subdata_size);
07280                       }
07281                   }
07282                 else
07283                   {
07284                     if(ttl == RSBAC_LIST_TTL_KEEP)
07285                       ttl = 0;
07286                     if(   !list->def_subdata
07287                        || memcmp(list->def_subdata, subdata, list->info.subdata_size)
07288                       )
07289                       add_lol_subitem(list, sublist, ttl, subdesc, subdata);
07290                   }
07291               }
07292           }
07293         else
07294           {
07295             err = -RSBAC_EINVALIDTARGET;
07296           }
07297       }
07298 #endif
07299 
07300 out_unlock:
07301     rsbac_write_unlock(&list->lock, &lock_flags);
07302     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07303     return err;
07304   }
07305 
07306 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07307 EXPORT_SYMBOL(rsbac_list_lol_subadd_ttl);
07308 #endif
07309 int rsbac_list_lol_subadd_ttl(
07310   rsbac_list_handle_t handle,
07311   rsbac_time_t ttl,
07312   void * desc,
07313   void * subdesc,
07314   void * subdata)
07315   {
07316     return rsbac_ta_list_lol_subadd_ttl(0, handle, ttl, desc, subdesc, subdata);
07317   }
07318 
07319 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07320 EXPORT_SYMBOL(rsbac_list_lol_subadd);
07321 #endif
07322 int rsbac_list_lol_subadd(
07323   rsbac_list_handle_t handle,
07324   void * desc,
07325   void * subdesc,
07326   void * subdata)
07327   {
07328     return rsbac_ta_list_lol_subadd_ttl(0, handle, RSBAC_LIST_TTL_KEEP, desc, subdesc, subdata);
07329   }
07330 
07331 /* add list of lists item */
07332 /* if item for desc exists, the data is updated */
07333 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07334 EXPORT_SYMBOL(rsbac_ta_list_lol_add_ttl);
07335 #endif
07336 int rsbac_ta_list_lol_add_ttl(
07337   rsbac_list_ta_number_t ta_number,
07338   rsbac_list_handle_t handle,
07339   rsbac_time_t ttl,
07340   void * desc,
07341   void * data)
07342   {
07343     struct rsbac_list_lol_reg_item_t * list;
07344     struct rsbac_list_lol_item_t     * item_p;
07345     u_long lock_flags, rlock_flags;
07346 
07347     if(!handle || !desc)
07348       return -RSBAC_EINVALIDVALUE;
07349     if(!list_initialized)
07350       return -RSBAC_ENOTINITIALIZED;
07351 
07352     list = (struct rsbac_list_lol_reg_item_t *) handle;
07353     if(!list || (list->self != list))
07354       return -RSBAC_EINVALIDVALUE;
07355 
07356 #ifdef CONFIG_RSBAC_LIST_TRANS
07357     if(ta_number && !rsbac_ta_list_exist(0, ta_handle, &ta_number))
07358       return -RSBAC_EINVALIDTRANSACTION;
07359 #endif
07360 
07361     if(ttl && (ttl != RSBAC_LIST_TTL_KEEP))
07362       {
07363         if(ttl > RSBAC_LIST_MAX_AGE_LIMIT)
07364           ttl = RSBAC_LIST_MAX_AGE_LIMIT;
07365         ttl += RSBAC_CURRENT_TIME;
07366       }
07367 
07368     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07369     if(list->info.data_size && !data)
07370       {
07371         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07372         return -RSBAC_EINVALIDVALUE;
07373       }
07374 
07375 /*
07376 #ifdef CONFIG_RSBAC_DEBUG
07377     if(rsbac_debug_lists)
07378       rsbac_printk(KERN_DEBUG "rsbac_list_lol_add: adding to list %s.\n",
07379              list->name);
07380 #endif
07381 */
07382     rsbac_write_lock(&list->lock, &lock_flags);
07383 
07384 #ifdef CONFIG_RSBAC_LIST_TRANS
07385     if(!ta_number)
07386 #endif
07387       {
07388         item_p = lookup_lol_item(list, desc);
07389         if(item_p)
07390           { /* exists -> update data, if any */
07391             if(ttl != RSBAC_LIST_TTL_KEEP)
07392               item_p->max_age = ttl;
07393             if(data && list->info.data_size)
07394               {
07395                 if(   list->def_data
07396                    && !item_p->max_age
07397                    && !memcmp(list->def_data, data, list->info.data_size)
07398                    && !item_p->count
07399                   )
07400                   do_remove_lol_item(list, item_p);
07401                 else
07402                   memcpy(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
07403                          data, list->info.data_size);
07404               }
07405           }
07406         else
07407           {
07408             if(ttl == RSBAC_LIST_TTL_KEEP)
07409               ttl = 0;
07410             if(   !list->def_data
07411                || memcmp(list->def_data, data, list->info.data_size)
07412               )
07413               add_lol_item(list, ttl, desc, data);
07414           }
07415         lol_touch(list);
07416         list->dirty = TRUE;
07417       }
07418 #ifdef CONFIG_RSBAC_LIST_TRANS
07419     if(list->ta_copied || ta_number)
07420       {
07421         if(!list->ta_copied)
07422           ta_lol_copy(ta_number, list);
07423         else
07424           if(ta_number)
07425             {
07426               if(list->ta_copied != ta_number)
07427                 {
07428                   rsbac_write_unlock(&list->lock, &lock_flags);
07429                   rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07430                   return -RSBAC_EBUSY;
07431                 }
07432             }
07433           else
07434             ta_number = list->ta_copied;
07435         item_p = ta_lookup_lol_item(ta_number, list, desc);
07436         if(item_p)
07437           { /* exists -> update data, if any */
07438             if(ttl != RSBAC_LIST_TTL_KEEP)
07439               item_p->max_age = ttl;
07440             if(data && list->info.data_size)
07441               {
07442                 if(   list->def_data
07443                    && !item_p->max_age
07444                    && !memcmp(list->def_data, data, list->info.data_size)
07445                    && !item_p->count
07446                   )
07447                   ta_do_remove_lol_item(list, item_p);
07448                 else
07449                   memcpy(((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
07450                          data, list->info.data_size);
07451               }
07452           }
07453         else
07454           {
07455             if(ttl == RSBAC_LIST_TTL_KEEP)
07456               ttl = 0;
07457             if(   !list->def_data
07458                || memcmp(list->def_data, data, list->info.data_size)
07459               )
07460               ta_add_lol_item(ta_number, list, ttl, desc, data);
07461           }
07462       }
07463 #endif
07464     rsbac_write_unlock(&list->lock, &lock_flags);
07465     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07466     return 0;
07467   }
07468 
07469 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07470 EXPORT_SYMBOL(rsbac_list_lol_add_ttl);
07471 #endif
07472 int rsbac_list_lol_add_ttl(
07473   rsbac_list_handle_t handle,
07474   rsbac_time_t ttl,
07475   void * desc,
07476   void * data)
07477   {
07478     return rsbac_ta_list_lol_add_ttl(0, handle, ttl, desc, data);
07479   }
07480 
07481 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07482 EXPORT_SYMBOL(rsbac_list_lol_add);
07483 #endif
07484 int rsbac_list_lol_add(
07485   rsbac_list_handle_t handle,
07486   void * desc,
07487   void * data)
07488   {
07489     return rsbac_ta_list_lol_add_ttl(0, handle, RSBAC_LIST_TTL_KEEP, desc, data);
07490   }
07491 
07492 /* remove item */
07493 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07494 EXPORT_SYMBOL(rsbac_ta_list_remove);
07495 #endif
07496 int rsbac_ta_list_remove(
07497   rsbac_list_ta_number_t ta_number,
07498   rsbac_list_handle_t handle,
07499   void * desc)
07500   {
07501     struct rsbac_list_reg_item_t * list;
07502     u_long lock_flags, rlock_flags;
07503 
07504     if(!handle || !desc)
07505       return -RSBAC_EINVALIDVALUE;
07506     if(!list_initialized)
07507       return -RSBAC_ENOTINITIALIZED;
07508 
07509     list = (struct rsbac_list_reg_item_t *) handle;
07510     if(!list || (list->self != list))
07511       return -RSBAC_EINVALIDVALUE;
07512 
07513 #ifdef CONFIG_RSBAC_LIST_TRANS
07514     if(ta_number)
07515       {
07516         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07517           return -RSBAC_EINVALIDTRANSACTION;
07518       }
07519 #endif
07520 
07521     rsbac_read_lock(&reg_head.lock, &rlock_flags);
07522 /*
07523 #ifdef CONFIG_RSBAC_DEBUG
07524     if(rsbac_debug_lists)
07525       rsbac_printk(KERN_DEBUG "rsbac_list_ta_remove: removing from list %s.\n",
07526              list->name);
07527 #endif
07528 */
07529     rsbac_write_lock(&list->lock, &lock_flags);
07530 #ifdef CONFIG_RSBAC_LIST_TRANS
07531     if(list->ta_copied)
07532       {
07533         if(ta_number)
07534           {
07535             if(ta_lookup_item(list->ta_copied, list, desc))
07536               {
07537                 if(list->ta_copied != ta_number)
07538                   {
07539                     rsbac_write_unlock(&list->lock, &lock_flags);
07540                     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07541                     return -RSBAC_EBUSY;
07542                   }
07543                 else
07544                   ta_remove_item(ta_number, list, desc);
07545               }
07546           }
07547         else
07548           ta_remove_item(list->ta_copied, list, desc);
07549       }
07550     else
07551       {
07552         if(ta_number && lookup_item(list, desc))
07553           {
07554             ta_copy(ta_number, list);
07555             ta_remove_item(ta_number, list, desc);
07556           }
07557       }
07558     if(!ta_number)
07559 #endif
07560       {
07561         if(lookup_item(list, desc))
07562           { /* exists -> remove */
07563             remove_item(list, desc);
07564             touch(list);
07565             list->dirty = TRUE;
07566           }
07567       }
07568     rsbac_write_unlock(&list->lock, &lock_flags);
07569     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07570     return 0;
07571   }
07572 
07573 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07574 EXPORT_SYMBOL(rsbac_list_remove);
07575 #endif
07576 int rsbac_list_remove(
07577   rsbac_list_handle_t handle,
07578   void * desc)
07579   {
07580     return rsbac_ta_list_remove(0, handle, desc);
07581   }
07582 
07583 /* remove all items */
07584 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07585 EXPORT_SYMBOL(rsbac_ta_list_remove_all);
07586 #endif
07587 int rsbac_ta_list_remove_all(rsbac_list_ta_number_t ta_number, rsbac_list_handle_t handle)
07588   {
07589     struct rsbac_list_reg_item_t * list;
07590     u_long lock_flags, rlock_flags;
07591 
07592     if(!handle)
07593       return -RSBAC_EINVALIDVALUE;
07594     if(!list_initialized)
07595       return -RSBAC_ENOTINITIALIZED;
07596 
07597     list = (struct rsbac_list_reg_item_t *) handle;
07598     if(list->self != list)
07599       return -RSBAC_EINVALIDVALUE;
07600 
07601 #ifdef CONFIG_RSBAC_LIST_TRANS
07602     if(ta_number)
07603       {
07604         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07605           return -RSBAC_EINVALIDTRANSACTION;
07606       }
07607 #endif
07608 
07609     rsbac_read_lock(&reg_head.lock, &rlock_flags);
07610 /*
07611 #ifdef CONFIG_RSBAC_DEBUG
07612     if(rsbac_debug_lists)
07613       rsbac_printk(KERN_DEBUG "rsbac_ta_list_remove_all: removing all items from list %s.\n",
07614              list->name);
07615 #endif
07616 */
07617     rsbac_write_lock(&list->lock, &lock_flags);
07618 #ifdef CONFIG_RSBAC_LIST_TRANS
07619     if(list->ta_copied)
07620       {
07621         if(ta_number)
07622           {
07623             if(list->ta_copied == ta_number)
07624               {
07625                 ta_remove_all_items(list);
07626                 if(!list->head)
07627                   {
07628                     list->ta_copied = 0;
07629                   }
07630               }
07631             else
07632               {
07633                 rsbac_write_unlock(&list->lock, &lock_flags);
07634                 rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07635                 return -RSBAC_EBUSY;
07636               }
07637           }
07638         else
07639           ta_remove_all_items(list);
07640       }
07641     else
07642       {
07643         if(ta_number)
07644           {
07645             if(list->head)
07646               {
07647                 list->ta_head = NULL;
07648                 list->ta_tail = NULL;
07649                 list->ta_curr = NULL;
07650                 list->ta_count = 0;
07651                 list->ta_copied = ta_number;
07652               }
07653           }
07654       }
07655 
07656     if(!ta_number)
07657 #endif
07658       if(list->head)
07659         {
07660           remove_all_items(list);
07661           touch(list);
07662           list->dirty = TRUE;
07663         }
07664     rsbac_write_unlock(&list->lock, &lock_flags);
07665     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
07666     return 0;
07667   }
07668 
07669 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07670 EXPORT_SYMBOL(rsbac_list_remove_all);
07671 #endif
07672 int rsbac_list_remove_all(rsbac_list_handle_t handle)
07673   {
07674     return rsbac_ta_list_remove_all(0, handle);
07675   }
07676 
07677 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07678 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove);
07679 #endif
07680 int rsbac_ta_list_lol_subremove(
07681   rsbac_list_ta_number_t ta_number,
07682   rsbac_list_handle_t handle,
07683   void * desc,
07684   void * subdesc)
07685   {
07686     struct rsbac_list_lol_reg_item_t * list;
07687     struct rsbac_list_lol_item_t     * sublist;
07688     u_long lock_flags, rlock_flags;
07689 
07690     if(!handle || !desc || !subdesc)
07691       return -RSBAC_EINVALIDVALUE;
07692     if(!list_initialized)
07693       return -RSBAC_ENOTINITIALIZED;
07694 
07695     list = (struct rsbac_list_lol_reg_item_t *) handle;
07696     if(list->self != list)
07697       return -RSBAC_EINVALIDVALUE;
07698 
07699 #ifdef CONFIG_RSBAC_LIST_TRANS
07700     if(ta_number)
07701       {
07702         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07703           return -RSBAC_EINVALIDTRANSACTION;
07704       }
07705 #endif
07706 
07707     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07708 /*
07709 #ifdef CONFIG_RSBAC_DEBUG
07710     if(rsbac_debug_lists)
07711       rsbac_printk(KERN_DEBUG "rsbac_ta_list_lol_subremove: removing from list of lists %s, device %02u:%02u.\n",
07712              list->name,
07713              RSBAC_MAJOR(list->device), RSBAC_MINOR(list->device));
07714 #endif
07715 */
07716     rsbac_write_lock(&list->lock, &lock_flags);
07717 #ifdef CONFIG_RSBAC_LIST_TRANS
07718     if(list->ta_copied)
07719       {
07720         sublist = ta_lookup_lol_item(list->ta_copied, list, desc);
07721         if(sublist)
07722           {
07723             if(   sublist->max_age
07724                && (sublist->max_age <= RSBAC_CURRENT_TIME)
07725               )
07726               {
07727                 ta_do_remove_lol_item(list, sublist);
07728               }
07729             else
07730               {
07731                 if(ta_number && (list->ta_copied != ta_number))
07732                   {
07733                     rsbac_write_unlock(&list->lock, &lock_flags);
07734                     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07735                     return -RSBAC_EBUSY;
07736                   }
07737                 if(lookup_lol_subitem(list, sublist, subdesc))
07738                   remove_lol_subitem(list, sublist, subdesc);
07739                 if(   !sublist->count
07740                    && (   (   list->def_data
07741                            && !memcmp(((char *) sublist) + sizeof(*sublist) + list->info.desc_size,
07742                                       list->def_data,
07743                                       list->info.data_size)
07744                           )
07745                        || (   !list->info.data_size
07746                            && (list->flags & RSBAC_LIST_DEF_DATA)
07747                           )
07748                       )
07749                       )
07750                   {
07751                     ta_do_remove_lol_item(list, sublist);
07752                   }
07753               }
07754           }
07755       }
07756     else
07757       {
07758         if(ta_number && lookup_lol_item(list, desc))
07759           {
07760             ta_lol_copy(ta_number, list);
07761             ta_remove_lol_item(ta_number, list, desc);
07762           }
07763       }
07764     if(!ta_number)
07765 #endif
07766       {
07767         sublist = lookup_lol_item(list, desc);
07768         if(sublist)
07769           {
07770             if(   sublist->max_age
07771                && (sublist->max_age <= RSBAC_CURRENT_TIME)
07772               )
07773               {
07774                 do_remove_lol_item(list, sublist);
07775                 lol_touch(list);
07776                 list->dirty = TRUE;
07777               }
07778             else
07779               {
07780                 if(lookup_lol_subitem(list, sublist, subdesc))
07781                   { /* exists -> remove and set dirty */
07782                     remove_lol_subitem(list, sublist, subdesc);
07783                     lol_touch(list);
07784                     list->dirty = TRUE;
07785                   }
07786                 if(   !sublist->count
07787                    && (   (   list->def_data
07788                            && !memcmp(((char *) sublist) + sizeof(*sublist) + list->info.desc_size,
07789                                       list->def_data,
07790                                       list->info.data_size)
07791                           )
07792                        || (   !list->info.data_size
07793                            && (list->flags & RSBAC_LIST_DEF_DATA)
07794                           )
07795                       )
07796                   )
07797                   {
07798                     do_remove_lol_item(list, sublist);
07799                     lol_touch(list);
07800                     list->dirty = TRUE;
07801                   }
07802               }
07803           }
07804       }
07805     rsbac_write_unlock(&list->lock, &lock_flags);
07806     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07807     return 0;
07808   }
07809 
07810 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07811 EXPORT_SYMBOL(rsbac_list_lol_subremove);
07812 #endif
07813 int rsbac_list_lol_subremove(
07814   rsbac_list_handle_t handle,
07815   void * desc,
07816   void * subdesc)
07817   {
07818     return rsbac_ta_list_lol_subremove(0, handle, desc, subdesc);
07819   }
07820 
07821 /* remove same subitem from all items */
07822 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07823 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_from_all);
07824 #endif
07825 int rsbac_ta_list_lol_subremove_from_all(
07826   rsbac_list_ta_number_t ta_number,
07827   rsbac_list_handle_t handle,
07828   void * subdesc)
07829   {
07830     struct rsbac_list_lol_reg_item_t * list;
07831     struct rsbac_list_lol_item_t     * sublist;
07832     u_long lock_flags, rlock_flags;
07833 
07834     if(!handle || !subdesc)
07835       return -RSBAC_EINVALIDVALUE;
07836     if(!list_initialized)
07837       return -RSBAC_ENOTINITIALIZED;
07838 
07839     list = (struct rsbac_list_lol_reg_item_t *) handle;
07840     if(list->self != list)
07841       return -RSBAC_EINVALIDVALUE;
07842 
07843 #ifdef CONFIG_RSBAC_LIST_TRANS
07844     if(ta_number)
07845       {
07846         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07847           return -RSBAC_EINVALIDTRANSACTION;
07848       }
07849 #endif
07850 
07851     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07852 /*
07853 #ifdef CONFIG_RSBAC_DEBUG
07854     if(rsbac_debug_lists)
07855       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subremove_from_all: removing from list of lists %s.\n",
07856              list->name);
07857 #endif
07858 */
07859     rsbac_write_lock(&list->lock, &lock_flags);
07860 #ifdef CONFIG_RSBAC_LIST_TRANS
07861     if(list->ta_copied)
07862       {
07863         if(ta_number && (list->ta_copied != ta_number))
07864           {
07865             rsbac_write_unlock(&list->lock, &lock_flags);
07866             rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07867             return -RSBAC_EBUSY;
07868           }
07869         sublist = list->head;
07870         while(sublist)
07871           {
07872             remove_lol_subitem(list, sublist, subdesc);
07873             sublist = sublist->next;
07874           }
07875       }
07876     else
07877       {
07878         if(ta_number)
07879           {
07880             ta_lol_copy(ta_number, list);
07881             sublist = list->head;
07882             while(sublist)
07883               {
07884                 remove_lol_subitem(list, sublist, subdesc);
07885                 sublist = sublist->next;
07886               }
07887           }
07888       }
07889     if(!ta_number)
07890 #endif
07891       {
07892         sublist = list->head;
07893         while(sublist)
07894           {
07895             if(lookup_lol_subitem(list, sublist, subdesc))
07896               { /* exists -> remove and set dirty */
07897                 remove_lol_subitem(list, sublist, subdesc);
07898                 lol_touch(list);
07899                 list->dirty = TRUE;
07900               }
07901             sublist = sublist->next;
07902           }
07903       }
07904     rsbac_write_unlock(&list->lock, &lock_flags);
07905     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07906     return 0;
07907   }
07908 
07909 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07910 EXPORT_SYMBOL(rsbac_list_lol_subremove_from_all);
07911 #endif
07912 int rsbac_list_lol_subremove_from_all(
07913   rsbac_list_handle_t handle,
07914   void * subdesc)
07915   {
07916     return rsbac_ta_list_lol_subremove_from_all(0, handle, subdesc);
07917   }
07918 
07919 /* remove all subitems */
07920 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
07921 EXPORT_SYMBOL(rsbac_ta_list_lol_subremove_all);
07922 #endif
07923 int rsbac_ta_list_lol_subremove_all(
07924   rsbac_list_ta_number_t ta_number,
07925   rsbac_list_handle_t handle,
07926   void * desc)
07927   {
07928     struct rsbac_list_lol_reg_item_t * list;
07929     struct rsbac_list_lol_item_t     * sublist;
07930     u_long lock_flags, rlock_flags;
07931 
07932     if(!handle)
07933       return -RSBAC_EINVALIDVALUE;
07934     if(!list_initialized)
07935       return -RSBAC_ENOTINITIALIZED;
07936 
07937     list = (struct rsbac_list_lol_reg_item_t *) handle;
07938     if(list->self != list)
07939       return -RSBAC_EINVALIDVALUE;
07940 
07941 #ifdef CONFIG_RSBAC_LIST_TRANS
07942     if(ta_number)
07943       {
07944         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
07945           return -RSBAC_EINVALIDTRANSACTION;
07946       }
07947 #endif
07948 
07949     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
07950 /*
07951 #ifdef CONFIG_RSBAC_DEBUG
07952     if(rsbac_debug_lists)
07953       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subremove_all: removing all subitems from list of lists %s.\n",
07954              list->name);
07955 #endif
07956 */
07957     rsbac_write_lock(&list->lock, &lock_flags);
07958 #ifdef CONFIG_RSBAC_LIST_TRANS
07959     if(list->ta_copied)
07960       {
07961         sublist = ta_lookup_lol_item(list->ta_copied, list, desc);
07962         if(sublist)
07963           {
07964             if(   sublist->max_age
07965                && (sublist->max_age <= RSBAC_CURRENT_TIME)
07966               )
07967               {
07968                 ta_do_remove_lol_item(list, sublist);
07969               }
07970             else
07971               {
07972                 if(ta_number && (list->ta_copied != ta_number))
07973                   {
07974                     rsbac_write_unlock(&list->lock, &lock_flags);
07975                     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
07976                     return -RSBAC_EBUSY;
07977                   }
07978                 remove_all_lol_subitems(sublist);
07979                 if(   (   list->def_data
07980                        && !memcmp(((char *) sublist) + sizeof(*sublist) + list->info.desc_size,
07981                                   list->def_data,
07982                                   list->info.data_size)
07983                       )
07984                    || (   !list->info.data_size
07985                        && (list->flags & RSBAC_LIST_DEF_DATA)
07986                       )
07987                    
07988                   )
07989                   {
07990                     ta_do_remove_lol_item(list, sublist);
07991                   }
07992               }
07993           }
07994       }
07995     else
07996       {
07997         if(ta_number && lookup_lol_item(list, desc))
07998           {
07999             ta_lol_copy(ta_number, list);
08000             sublist = ta_lookup_lol_item(ta_number, list, desc);
08001             if(sublist)
08002               remove_all_lol_subitems(sublist);
08003           }
08004       }
08005     if(!ta_number)
08006 #endif
08007       {
08008         sublist = lookup_lol_item(list, desc);
08009         if(sublist && sublist->head)
08010           {
08011             remove_all_lol_subitems(sublist);
08012             lol_touch(list);
08013             list->dirty = TRUE;
08014           }
08015       }
08016     rsbac_write_unlock(&list->lock, &lock_flags);
08017     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08018     return 0;
08019   }
08020 
08021 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08022 EXPORT_SYMBOL(rsbac_list_lol_subremove_all);
08023 #endif
08024 int rsbac_list_lol_subremove_all(rsbac_list_handle_t handle, void * desc)
08025   {
08026     return rsbac_ta_list_lol_subremove_all(0, handle, desc);
08027   }
08028 
08029 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08030 EXPORT_SYMBOL(rsbac_ta_list_lol_remove);
08031 #endif
08032 int rsbac_ta_list_lol_remove(
08033   rsbac_list_ta_number_t ta_number,
08034   rsbac_list_handle_t handle,
08035   void * desc)
08036   {
08037     struct rsbac_list_lol_reg_item_t * list;
08038     u_long lock_flags, rlock_flags;
08039 
08040     if(!handle || !desc)
08041       return -RSBAC_EINVALIDVALUE;
08042     if(!list_initialized)
08043       return -RSBAC_ENOTINITIALIZED;
08044 
08045     list = (struct rsbac_list_lol_reg_item_t *) handle;
08046     if(list->self != list)
08047       return -RSBAC_EINVALIDVALUE;
08048 
08049 #ifdef CONFIG_RSBAC_LIST_TRANS
08050     if(ta_number)
08051       {
08052         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08053           return -RSBAC_EINVALIDTRANSACTION;
08054       }
08055 #endif
08056 
08057     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08058 /*
08059 #ifdef CONFIG_RSBAC_DEBUG
08060     if(rsbac_debug_lists)
08061       rsbac_printk(KERN_DEBUG "rsbac_list_lol_remove: removing from list of lists %s.\n",
08062              list->name);
08063 #endif
08064 */
08065     rsbac_write_lock(&list->lock, &lock_flags);
08066 #ifdef CONFIG_RSBAC_LIST_TRANS
08067     if(list->ta_copied)
08068       {
08069         if(ta_number)
08070           {
08071             if(ta_lookup_lol_item(list->ta_copied, list, desc))
08072               {
08073                 if(list->ta_copied != ta_number)
08074                   {
08075                     rsbac_write_unlock(&list->lock, &lock_flags);
08076                     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08077                     return -RSBAC_EBUSY;
08078                   }
08079                 else
08080                   ta_remove_lol_item(ta_number, list, desc);
08081               }
08082           }
08083         else
08084           ta_remove_lol_item(list->ta_copied, list, desc);
08085       }
08086     else
08087       {
08088         if(ta_number && lookup_lol_item(list, desc))
08089           {
08090             ta_lol_copy(ta_number, list);
08091             ta_remove_lol_item(ta_number, list, desc);
08092           }
08093       }
08094     if(!ta_number)
08095 #endif
08096       {
08097         if(lookup_lol_item(list, desc))
08098           { /* exists -> remove */
08099             remove_lol_item(list, desc);
08100             lol_touch(list);
08101             list->dirty = TRUE;
08102           }
08103       }
08104     rsbac_write_unlock(&list->lock, &lock_flags);
08105     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08106     return 0;
08107   }
08108 
08109 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08110 EXPORT_SYMBOL(rsbac_list_lol_remove);
08111 #endif
08112 int rsbac_list_lol_remove(
08113   rsbac_list_handle_t handle,
08114   void * desc)
08115   {
08116     return rsbac_ta_list_lol_remove(0, handle, desc);
08117   }
08118 
08119 /* remove all items */
08120 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08121 EXPORT_SYMBOL(rsbac_ta_list_lol_remove_all);
08122 #endif
08123 int rsbac_ta_list_lol_remove_all(rsbac_list_ta_number_t ta_number, rsbac_list_handle_t handle)
08124   {
08125     struct rsbac_list_lol_reg_item_t * list;
08126     u_long lock_flags, rlock_flags;
08127 
08128     if(!handle)
08129       return -RSBAC_EINVALIDVALUE;
08130     if(!list_initialized)
08131       return -RSBAC_ENOTINITIALIZED;
08132 
08133     list = (struct rsbac_list_lol_reg_item_t *) handle;
08134     if(list->self != list)
08135       return -RSBAC_EINVALIDVALUE;
08136 
08137 #ifdef CONFIG_RSBAC_LIST_TRANS
08138     if(ta_number)
08139       {
08140         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08141           return -RSBAC_EINVALIDTRANSACTION;
08142       }
08143 #endif
08144 
08145     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08146 /*
08147 #ifdef CONFIG_RSBAC_DEBUG
08148     if(rsbac_debug_lists)
08149       rsbac_printk(KERN_DEBUG "rsbac_list_lol_remove_all: removing all items from list of lists %s.\n",
08150              list->name);
08151 #endif
08152 */
08153     rsbac_write_lock(&list->lock, &lock_flags);
08154 #ifdef CONFIG_RSBAC_LIST_TRANS
08155     if(list->ta_copied)
08156       {
08157         if(ta_number)
08158           {
08159             if(list->ta_copied == ta_number)
08160               {
08161                 ta_remove_all_lol_items(list);
08162                 if(!list->head)
08163                   {
08164                     list->ta_copied = 0;
08165                   }
08166               }
08167             else
08168               {
08169                 rsbac_write_unlock(&list->lock, &lock_flags);
08170                 rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08171                 return -RSBAC_EBUSY;
08172               }
08173           }
08174         else
08175           ta_remove_all_lol_items(list);
08176       }
08177     else
08178       {
08179         if(ta_number)
08180           {
08181             if(list->head)
08182               {
08183                 list->ta_head = NULL;
08184                 list->ta_tail = NULL;
08185                 list->ta_curr = NULL;
08186                 list->ta_count = 0;
08187                 list->ta_copied = ta_number;
08188               }
08189           }
08190       }
08191 
08192     if(!ta_number)
08193 #endif
08194       if(list->head)
08195         {
08196           remove_all_lol_items(list);
08197           lol_touch(list);
08198           list->dirty = TRUE;
08199         }
08200     rsbac_write_unlock(&list->lock, &lock_flags);
08201     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08202     return 0;
08203   }
08204 
08205 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08206 EXPORT_SYMBOL(rsbac_list_lol_remove_all);
08207 #endif
08208 int rsbac_list_lol_remove_all(rsbac_list_handle_t handle)
08209   {
08210     return rsbac_ta_list_lol_remove_all(0, handle);
08211   }
08212 
08213 /* get item data */
08214 /* Item data is copied - we cannot give a pointer, because item could be
08215  * removed */
08216 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08217 EXPORT_SYMBOL(rsbac_ta_list_get_data_ttl);
08218 #endif
08219 int rsbac_ta_list_get_data_ttl(
08220   rsbac_list_ta_number_t ta_number,
08221   rsbac_list_handle_t handle,
08222   rsbac_time_t * ttl_p,
08223   void * desc,
08224   void * data)
08225   {
08226     struct rsbac_list_reg_item_t * list;
08227     struct rsbac_list_item_t     * item_p;
08228     u_long lock_flags, rlock_flags;
08229     int err = 0;
08230 
08231     if(!handle || !desc)
08232       return -RSBAC_EINVALIDVALUE;
08233     if(!list_initialized)
08234       return -RSBAC_ENOTINITIALIZED;
08235 
08236     list = (struct rsbac_list_reg_item_t *) handle;
08237     if(list->self != list)
08238       return -RSBAC_EINVALIDVALUE;
08239 
08240 #ifdef CONFIG_RSBAC_LIST_TRANS
08241     if(ta_number)
08242       {
08243         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08244           return -RSBAC_EINVALIDTRANSACTION;
08245       }
08246 #endif
08247 
08248     rsbac_read_lock(&reg_head.lock, &rlock_flags);
08249 /*
08250 #ifdef CONFIG_RSBAC_DEBUG
08251     if(rsbac_debug_lists)
08252       rsbac_printk(KERN_DEBUG "rsbac_list_get_data: getting data from list %s.\n",
08253              list->name);
08254 #endif
08255 */
08256     if(data && !list->info.data_size)
08257       {
08258         rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08259         return -RSBAC_EINVALIDREQUEST;
08260       }
08261 
08262     rsbac_read_lock(&list->lock, &lock_flags);
08263 #ifdef CONFIG_RSBAC_LIST_TRANS
08264     if(ta_number && (list->ta_copied == ta_number))
08265       item_p = ta_lookup_item(ta_number, list, desc);
08266     else
08267 #endif
08268       item_p = lookup_item(list, desc);
08269     if(   item_p
08270        && (   !item_p->max_age
08271            || (item_p->max_age > RSBAC_CURRENT_TIME)
08272           )
08273       )
08274       { /* exists -> copy data, if any */
08275         if(ttl_p)
08276           {
08277             if(item_p->max_age)
08278               *ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
08279             else
08280               *ttl_p = 0;
08281           }
08282         if(data)
08283           {
08284             memcpy(data,
08285                    ((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
08286                    list->info.data_size);
08287           }
08288       }
08289     else
08290       {
08291         if(!list->def_data)
08292           err = -RSBAC_ENOTFOUND;
08293         else
08294           {
08295             if(ttl_p)
08296               *ttl_p = 0;
08297             if(data)
08298               memcpy(data,
08299                      list->def_data,
08300                      list->info.data_size);
08301           }
08302       }
08303     rsbac_read_unlock(&list->lock, &lock_flags);
08304     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08305     return err;
08306   }
08307 
08308 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08309 EXPORT_SYMBOL(rsbac_list_get_data_ttl);
08310 #endif
08311 int rsbac_list_get_data_ttl(rsbac_list_handle_t handle,
08312                             rsbac_time_t * ttl_p,
08313                             void * desc,
08314                             void * data)
08315   {
08316     return rsbac_ta_list_get_data_ttl(0, handle, ttl_p, desc, data);
08317   }
08318 
08319 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08320 EXPORT_SYMBOL(rsbac_list_get_data);
08321 #endif
08322 int rsbac_list_get_data(rsbac_list_handle_t handle, void * desc, void * data)
08323   {
08324     return rsbac_ta_list_get_data_ttl(0, handle, NULL, desc, data);
08325   }
08326 
08327 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08328 EXPORT_SYMBOL(rsbac_ta_list_lol_get_subdata_ttl);
08329 #endif
08330 int rsbac_ta_list_lol_get_subdata_ttl(
08331   rsbac_list_ta_number_t ta_number,
08332   rsbac_list_handle_t handle,
08333   rsbac_time_t * ttl_p,
08334   void * desc,
08335   void * subdesc,
08336   void * subdata)
08337   {
08338     struct rsbac_list_lol_reg_item_t * list;
08339     struct rsbac_list_lol_item_t     * sublist;
08340     struct rsbac_list_item_t         * item_p;
08341     u_long lock_flags, rlock_flags;
08342     int err = 0;
08343 
08344     if(!handle || !desc || !subdesc)
08345       return -RSBAC_EINVALIDVALUE;
08346     if(!list_initialized)
08347       return -RSBAC_ENOTINITIALIZED;
08348 
08349     list = (struct rsbac_list_lol_reg_item_t *) handle;
08350     if(list->self != list)
08351       return -RSBAC_EINVALIDVALUE;
08352 
08353 #ifdef CONFIG_RSBAC_LIST_TRANS
08354     if(ta_number)
08355       {
08356         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08357           return -RSBAC_EINVALIDTRANSACTION;
08358       }
08359 #endif
08360 
08361     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08362 /*
08363 #ifdef CONFIG_RSBAC_DEBUG
08364     if(rsbac_debug_lists)
08365       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_subdata: getting data from list %s.\n",
08366              list->name);
08367 #endif
08368 */
08369     if(subdata && !list->info.subdata_size)
08370       {
08371         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08372         return -RSBAC_EINVALIDREQUEST;
08373       }
08374 
08375     rsbac_read_lock(&list->lock, &lock_flags);
08376 
08377 #ifdef CONFIG_RSBAC_LIST_TRANS
08378     if(ta_number && (list->ta_copied == ta_number))
08379       sublist = ta_lookup_lol_item(ta_number, list, desc);
08380     else
08381 #endif
08382     sublist = lookup_lol_item(list, desc);
08383     if(sublist)
08384       { /* exists -> lookup subitem */
08385         item_p = lookup_lol_subitem(list, sublist, subdesc);
08386         if(   item_p
08387            && (   !item_p->max_age
08388                || (item_p->max_age > RSBAC_CURRENT_TIME)
08389               )
08390           )
08391           { /* exists -> copy data, if any */
08392             if(ttl_p)
08393               {
08394                 if(item_p->max_age)
08395                   *ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
08396                 else
08397                   *ttl_p = 0;
08398               }
08399             if(subdata)
08400               {
08401                 memcpy(subdata,
08402                        ((char *) item_p) + sizeof(*item_p) + list->info.subdesc_size,
08403                        list->info.subdata_size);
08404               }
08405           }
08406         else
08407           {
08408             if(!list->def_subdata)
08409               err = -RSBAC_ENOTFOUND;
08410             else
08411               {
08412                 if(ttl_p)
08413                   *ttl_p = 0;
08414                 if(subdata)
08415                   memcpy(subdata,
08416                          list->def_subdata,
08417                          list->info.subdata_size);
08418               }
08419           }
08420       }
08421     else
08422       {
08423         if(!list->def_subdata)
08424           err = -RSBAC_ENOTFOUND;
08425         else
08426           {
08427             if(ttl_p)
08428               *ttl_p = 0;
08429             if(subdata)
08430               memcpy(subdata,
08431                      list->def_subdata,
08432                      list->info.subdata_size);
08433           }
08434       }
08435     rsbac_read_unlock(&list->lock, &lock_flags);
08436     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08437     return err;
08438   }
08439 
08440 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08441 EXPORT_SYMBOL(rsbac_list_lol_get_subdata_ttl);
08442 #endif
08443 int rsbac_list_lol_get_subdata_ttl(
08444   rsbac_list_handle_t handle,
08445   rsbac_time_t * ttl_p,
08446   void * desc,
08447   void * subdesc,
08448   void * subdata)
08449   {
08450     return rsbac_ta_list_lol_get_subdata_ttl(0, handle,
08451                                              ttl_p, desc, subdesc, subdata);
08452   }
08453 
08454 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08455 EXPORT_SYMBOL(rsbac_list_lol_get_subdata);
08456 #endif
08457 int rsbac_list_lol_get_subdata(
08458   rsbac_list_handle_t handle,
08459   void * desc,
08460   void * subdesc,
08461   void * subdata)
08462   {
08463     return rsbac_ta_list_lol_get_subdata_ttl(0, handle, NULL, desc, subdesc, subdata);
08464   }
08465 
08466 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08467 EXPORT_SYMBOL(rsbac_ta_list_lol_get_data_ttl);
08468 #endif
08469 int rsbac_ta_list_lol_get_data_ttl(
08470   rsbac_list_ta_number_t ta_number,
08471   rsbac_list_handle_t handle,
08472   rsbac_time_t * ttl_p,
08473   void * desc,
08474   void * data)
08475   {
08476     struct rsbac_list_lol_reg_item_t * list;
08477     struct rsbac_list_lol_item_t     * item_p;
08478     u_long lock_flags, rlock_flags;
08479     int err = 0;
08480 
08481     if(!handle || !desc)
08482       return -RSBAC_EINVALIDVALUE;
08483     if(!list_initialized)
08484       return -RSBAC_ENOTINITIALIZED;
08485 
08486     list = (struct rsbac_list_lol_reg_item_t *) handle;
08487     if(list->self != list)
08488       return -RSBAC_EINVALIDVALUE;
08489 
08490 #ifdef CONFIG_RSBAC_LIST_TRANS
08491     if(ta_number)
08492       {
08493         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08494           return -RSBAC_EINVALIDTRANSACTION;
08495       }
08496 #endif
08497 
08498     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08499 /*
08500 #ifdef CONFIG_RSBAC_DEBUG
08501     if(rsbac_debug_lists)
08502       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_data: getting data from list %s.\n",
08503              list->name);
08504 #endif
08505 */
08506     if(data && !list->info.data_size)
08507       {
08508         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08509         return -RSBAC_EINVALIDREQUEST;
08510       }
08511 
08512     rsbac_read_lock(&list->lock, &lock_flags);
08513 
08514 #ifdef CONFIG_RSBAC_LIST_TRANS
08515     if(ta_number && (list->ta_copied == ta_number))
08516       item_p = ta_lookup_lol_item(ta_number, list, desc);
08517     else
08518 #endif
08519     item_p = lookup_lol_item(list, desc);
08520     if(   item_p
08521        && (   !item_p->max_age
08522            || (item_p->max_age > RSBAC_CURRENT_TIME)
08523           )
08524       )
08525       { /* exists -> copy data, if any */
08526         if(ttl_p)
08527           {
08528             if(item_p->max_age)
08529               *ttl_p = item_p->max_age - RSBAC_CURRENT_TIME;
08530             else
08531               *ttl_p = 0;
08532           }
08533         if(data)
08534           {
08535             memcpy(data,
08536                    ((char *) item_p) + sizeof(*item_p) + list->info.desc_size,
08537                    list->info.data_size);
08538           }
08539       }
08540     else
08541       {
08542         if(!list->def_data)
08543           err = -RSBAC_ENOTFOUND;
08544         else
08545           {
08546             if(ttl_p)
08547               *ttl_p = 0;
08548             if(data)
08549               memcpy(data,
08550                      list->def_data,
08551                      list->info.data_size);
08552           }
08553       }
08554     rsbac_read_unlock(&list->lock, &lock_flags);
08555     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08556     return err;
08557   }
08558 
08559 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08560 EXPORT_SYMBOL(rsbac_list_lol_get_data_ttl);
08561 #endif
08562 int rsbac_list_lol_get_data_ttl(rsbac_list_handle_t handle,
08563                                 rsbac_time_t * ttl_p,
08564                                 void * desc,
08565                                 void * data)
08566   {
08567     return rsbac_ta_list_lol_get_data_ttl(0, handle, ttl_p, desc, data);
08568   }
08569 
08570 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08571 EXPORT_SYMBOL(rsbac_list_lol_get_data);
08572 #endif
08573 int rsbac_list_lol_get_data(rsbac_list_handle_t handle,
08574                             void * desc,
08575                             void * data)
08576   {
08577     return rsbac_ta_list_lol_get_data_ttl(0, handle, NULL, desc, data);
08578   }
08579 
08580 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08581 EXPORT_SYMBOL(rsbac_ta_list_get_max_desc);
08582 #endif
08583 int rsbac_ta_list_get_max_desc(
08584   rsbac_list_ta_number_t ta_number,
08585   rsbac_list_handle_t handle,
08586   void * desc)
08587   {
08588     struct rsbac_list_reg_item_t * list;
08589     struct rsbac_list_item_t * item_p;
08590     u_long lock_flags, rlock_flags;
08591     int err = 0;
08592 
08593     if(!handle)
08594       return -RSBAC_EINVALIDVALUE;
08595     if(!list_initialized)
08596       return -RSBAC_ENOTINITIALIZED;
08597 
08598     list = (struct rsbac_list_reg_item_t *) handle;
08599     if(list->self != list)
08600       return -RSBAC_EINVALIDVALUE;
08601 
08602 #ifdef CONFIG_RSBAC_LIST_TRANS
08603     if(ta_number)
08604       {
08605         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08606           return -RSBAC_EINVALIDTRANSACTION;
08607       }
08608 #endif
08609 
08610     rsbac_read_lock(&reg_head.lock, &rlock_flags);
08611 /*
08612 #ifdef CONFIG_RSBAC_DEBUG
08613     if(rsbac_debug_lists)
08614       rsbac_printk(KERN_DEBUG "rsbac_list_get_max_desc: list %s.\n",
08615              list->name);
08616 #endif
08617 */
08618     rsbac_read_lock(&list->lock, &lock_flags);
08619 #ifdef CONFIG_RSBAC_LIST_TRANS
08620     if(ta_number && (list->ta_copied == ta_number))
08621       item_p = list->ta_tail;
08622     else
08623 #endif
08624     item_p = list->tail;
08625     while(   item_p
08626           && item_p->max_age
08627           && (item_p->max_age > RSBAC_CURRENT_TIME)
08628          )
08629       item_p = item_p->prev;
08630     if(item_p)
08631       memcpy(desc, (char *)item_p + sizeof(*item_p), list->info.desc_size);
08632     else
08633       {
08634         memset(desc, 0, list->info.desc_size);
08635         err = -RSBAC_ENOTFOUND;
08636       }
08637     rsbac_read_unlock(&list->lock, &lock_flags);
08638     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08639     return err;
08640   }
08641 
08642 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08643 EXPORT_SYMBOL(rsbac_list_get_max_desc);
08644 #endif
08645 int rsbac_list_get_max_desc(rsbac_list_handle_t handle, void * desc)
08646   {
08647     return rsbac_ta_list_get_max_desc(0, handle, desc);
08648   }
08649 
08650 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08651 EXPORT_SYMBOL(rsbac_ta_list_get_next_desc);
08652 #endif
08653 int rsbac_ta_list_get_next_desc(
08654   rsbac_list_ta_number_t ta_number,
08655   rsbac_list_handle_t handle,
08656   void * old_desc,
08657   void * next_desc)
08658   {
08659     struct rsbac_list_reg_item_t * list;
08660     struct rsbac_list_item_t * item_p;
08661     u_long lock_flags, rlock_flags;
08662 
08663     if(!handle)
08664       return -RSBAC_EINVALIDVALUE;
08665     if(!list_initialized)
08666       return -RSBAC_ENOTINITIALIZED;
08667     if(!next_desc)
08668       return -RSBAC_EINVALIDPOINTER;
08669 
08670     list = (struct rsbac_list_reg_item_t *) handle;
08671     if(list->self != list)
08672       return -RSBAC_EINVALIDVALUE;
08673 
08674 #ifdef CONFIG_RSBAC_LIST_TRANS
08675     if(ta_number)
08676       {
08677         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08678           return -RSBAC_EINVALIDTRANSACTION;
08679       }
08680 #endif
08681 
08682     rsbac_read_lock(&reg_head.lock, &rlock_flags);
08683 /*
08684 #ifdef CONFIG_RSBAC_DEBUG
08685     if(rsbac_debug_lists)
08686       rsbac_printk(KERN_DEBUG "rsbac_list_get_next_desc: list %s.\n",
08687              list->name);
08688 #endif
08689 */
08690     rsbac_read_lock(&list->lock, &lock_flags);
08691     if(old_desc)
08692       {
08693 #ifdef CONFIG_RSBAC_LIST_TRANS
08694         if(ta_number && (list->ta_copied == ta_number))
08695           item_p = ta_lookup_item(ta_number, list, old_desc);
08696         else
08697 #endif
08698         item_p = lookup_item(list, old_desc);
08699         if(item_p)
08700           item_p = item_p->next;
08701       }
08702     else
08703 #ifdef CONFIG_RSBAC_LIST_TRANS
08704       if(ta_number && (list->ta_copied == ta_number))
08705         item_p = list->ta_head;
08706       else
08707 #endif
08708       item_p = list->head;
08709     while(   item_p
08710           && item_p->max_age
08711           && (item_p->max_age > RSBAC_CURRENT_TIME)
08712          )
08713       item_p = item_p->next;
08714     if(item_p)
08715       {
08716         memcpy(next_desc, (char *)item_p + sizeof(*item_p), list->info.desc_size);
08717         list->curr = item_p;
08718       }
08719     rsbac_read_unlock(&list->lock, &lock_flags);
08720     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08721     if(item_p)
08722       return 0;
08723     else
08724       return -RSBAC_ENOTFOUND;
08725   }
08726 
08727 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08728 EXPORT_SYMBOL(rsbac_list_get_next_desc);
08729 #endif
08730 int rsbac_list_get_next_desc(rsbac_list_handle_t handle, void * old_desc, void * next_desc)
08731   {
08732     return rsbac_ta_list_get_next_desc(0, handle, old_desc, next_desc);
08733   }
08734 
08735 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08736 EXPORT_SYMBOL(rsbac_ta_list_lol_get_next_desc);
08737 #endif
08738 int rsbac_ta_list_lol_get_next_desc(
08739   rsbac_list_ta_number_t ta_number,
08740   rsbac_list_handle_t handle,
08741   void * old_desc,
08742   void * next_desc)
08743   {
08744     struct rsbac_list_lol_reg_item_t * list;
08745     struct rsbac_list_lol_item_t * item_p;
08746     u_long lock_flags, rlock_flags;
08747 
08748     if(!handle)
08749       return -RSBAC_EINVALIDVALUE;
08750     if(!list_initialized)
08751       return -RSBAC_ENOTINITIALIZED;
08752     if(!next_desc)
08753       return -RSBAC_EINVALIDPOINTER;
08754 
08755     list = (struct rsbac_list_lol_reg_item_t *) handle;
08756     if(list->self != list)
08757       return -RSBAC_EINVALIDVALUE;
08758 
08759 #ifdef CONFIG_RSBAC_LIST_TRANS
08760     if(ta_number)
08761       {
08762         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08763           return -RSBAC_EINVALIDTRANSACTION;
08764       }
08765 #endif
08766 
08767     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08768 /*
08769 #ifdef CONFIG_RSBAC_DEBUG
08770     if(rsbac_debug_lists)
08771       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_next_desc: list %s.\n",
08772              list->name);
08773 #endif
08774 */
08775     rsbac_read_lock(&list->lock, &lock_flags);
08776     if(old_desc)
08777       {
08778 #ifdef CONFIG_RSBAC_LIST_TRANS
08779         if(ta_number && (list->ta_copied == ta_number))
08780           item_p = ta_lookup_lol_item(ta_number, list, old_desc);
08781         else
08782 #endif
08783         item_p = lookup_lol_item(list, old_desc);
08784         if(item_p)
08785           item_p = item_p->next;
08786       }
08787     else
08788 #ifdef CONFIG_RSBAC_LIST_TRANS
08789       if(ta_number && (list->ta_copied == ta_number))
08790         item_p = list->ta_head;
08791       else
08792 #endif
08793       item_p = list->head;
08794     while(   item_p
08795           && item_p->max_age
08796           && (item_p->max_age > RSBAC_CURRENT_TIME)
08797          )
08798       item_p = item_p->next;
08799     if(item_p)
08800       {
08801         memcpy(next_desc, (char *)item_p + sizeof(*item_p), list->info.desc_size);
08802         list->curr = item_p;
08803       }
08804     rsbac_read_unlock(&list->lock, &lock_flags);
08805     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08806     if(item_p)
08807       return 0;
08808     else
08809       return -RSBAC_ENOTFOUND;
08810   }
08811 
08812 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08813 EXPORT_SYMBOL(rsbac_list_lol_get_next_desc);
08814 #endif
08815 int rsbac_list_lol_get_next_desc(
08816   rsbac_list_handle_t handle,
08817   void * old_desc,
08818   void * next_desc)
08819   {
08820     return rsbac_ta_list_lol_get_next_desc(0, handle, old_desc, next_desc);
08821   }
08822 
08823 /* get item desc by data */
08824 /* Item desc is copied - we cannot give a pointer, because item could be
08825  * removed.
08826  * If no compare function is provided (NULL value), memcmp is used.
08827  * Note: The data value given here is always used as second parameter to the
08828  *       compare function, so you can use different types for storage and
08829  *       lookup.
08830  */
08831 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08832 EXPORT_SYMBOL(rsbac_ta_list_get_desc);
08833 #endif
08834 int rsbac_ta_list_get_desc(
08835   rsbac_list_ta_number_t ta_number,
08836   rsbac_list_handle_t handle,
08837   void * desc,
08838   void * data,
08839   rsbac_list_data_compare_function_t compare)
08840   {
08841     struct rsbac_list_reg_item_t * list;
08842     struct rsbac_list_item_t     * item_p;
08843     u_long lock_flags, rlock_flags;
08844     int err = 0;
08845 
08846     if(!handle || !desc || !data)
08847       return -RSBAC_EINVALIDVALUE;
08848     if(!list_initialized)
08849       return -RSBAC_ENOTINITIALIZED;
08850 
08851     list = (struct rsbac_list_reg_item_t *) handle;
08852     if(list->self != list)
08853       return -RSBAC_EINVALIDVALUE;
08854 
08855 #ifdef CONFIG_RSBAC_LIST_TRANS
08856     if(ta_number)
08857       {
08858         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08859           return -RSBAC_EINVALIDTRANSACTION;
08860       }
08861 #endif
08862 
08863     rsbac_read_lock(&reg_head.lock, &rlock_flags);
08864 /*
08865 #ifdef CONFIG_RSBAC_DEBUG
08866     if(rsbac_debug_lists)
08867       rsbac_printk(KERN_DEBUG "rsbac_list_get_desc: getting desc from list %s.\n",
08868              list->name);
08869 #endif
08870 */
08871     if(!list->info.data_size)
08872       {
08873         rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08874         return -RSBAC_EINVALIDREQUEST;
08875       }
08876 
08877     rsbac_read_lock(&list->lock, &lock_flags);
08878 
08879 #ifdef CONFIG_RSBAC_LIST_TRANS
08880     if(ta_number && (list->ta_copied == ta_number))
08881       item_p = ta_lookup_item_data(ta_number, list, data, compare);
08882     else
08883 #endif
08884     item_p = lookup_item_data(list, data, compare);
08885     if(item_p)
08886       { /* exists -> copy desc */
08887         memcpy(desc,
08888                ((char *) item_p) + sizeof(*item_p),
08889                list->info.desc_size);
08890       }
08891     else
08892       {
08893         err = -RSBAC_ENOTFOUND;
08894       }
08895     rsbac_read_unlock(&list->lock, &lock_flags);
08896     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
08897     return err;
08898   }
08899 
08900 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08901 EXPORT_SYMBOL(rsbac_list_get_desc);
08902 #endif
08903 int rsbac_list_get_desc(
08904   rsbac_list_handle_t handle,
08905   void * desc,
08906   void * data,
08907   rsbac_list_data_compare_function_t compare)
08908   {
08909     return rsbac_ta_list_get_desc(0, handle, desc, data, compare);
08910   }
08911 
08912 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08913 EXPORT_SYMBOL(rsbac_ta_list_lol_get_desc);
08914 #endif
08915 int rsbac_ta_list_lol_get_desc(
08916   rsbac_list_ta_number_t ta_number,
08917   rsbac_list_handle_t handle,
08918   void * desc,
08919   void * data,
08920   rsbac_list_data_compare_function_t compare)
08921   {
08922     struct rsbac_list_lol_reg_item_t * list;
08923     struct rsbac_list_lol_item_t     * item_p;
08924     u_long lock_flags, rlock_flags;
08925     int err = 0;
08926 
08927     if(!handle || !desc || !data)
08928       return -RSBAC_EINVALIDVALUE;
08929     if(!list_initialized)
08930       return -RSBAC_ENOTINITIALIZED;
08931 
08932     list = (struct rsbac_list_lol_reg_item_t *) handle;
08933     if(list->self != list)
08934       return -RSBAC_EINVALIDVALUE;
08935 
08936 #ifdef CONFIG_RSBAC_LIST_TRANS
08937     if(ta_number)
08938       {
08939         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
08940           return -RSBAC_EINVALIDTRANSACTION;
08941       }
08942 #endif
08943 
08944     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
08945 /*
08946 #ifdef CONFIG_RSBAC_DEBUG
08947     if(rsbac_debug_lists)
08948       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_desc: getting desc from list %s.\n",
08949              list->name);
08950 #endif
08951 */
08952     if(!list->info.data_size)
08953       {
08954         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08955         return -RSBAC_EINVALIDREQUEST;
08956       }
08957 
08958     rsbac_read_lock(&list->lock, &lock_flags);
08959 
08960 #ifdef CONFIG_RSBAC_LIST_TRANS
08961     if(ta_number && (list->ta_copied == ta_number))
08962       item_p = ta_lookup_lol_item_data(ta_number, list, data, compare);
08963     else
08964 #endif
08965     item_p = lookup_lol_item_data(list, data, compare);
08966     if(item_p)
08967       { /* exists -> copy desc */
08968         memcpy(desc,
08969                ((char *) item_p) + sizeof(*item_p),
08970                list->info.desc_size);
08971       }
08972     else
08973       {
08974         err = -RSBAC_ENOTFOUND;
08975       }
08976     rsbac_read_unlock(&list->lock, &lock_flags);
08977     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
08978     return err;
08979   }
08980 
08981 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08982 EXPORT_SYMBOL(rsbac_list_lol_get_desc);
08983 #endif
08984 int rsbac_list_lol_get_desc(
08985   rsbac_list_handle_t handle,
08986   void * desc,
08987   void * data,
08988   rsbac_list_data_compare_function_t compare)
08989   {
08990     return rsbac_ta_list_lol_get_desc(0, handle, desc, data, compare);
08991   }
08992 
08993 /* returns TRUE, if item exists or def_data is defined, FALSE, if not */
08994 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
08995 EXPORT_SYMBOL(rsbac_ta_list_exist);
08996 #endif
08997 int rsbac_ta_list_exist(
08998   rsbac_list_ta_number_t ta_number,
08999   rsbac_list_handle_t handle,
09000   void * desc)
09001   {
09002     struct rsbac_list_reg_item_t * list;
09003     u_long lock_flags, rlock_flags;
09004     struct rsbac_list_item_t     * item_p;
09005     int result;
09006 
09007     if(!handle || !desc)
09008       return FALSE;
09009     if(!list_initialized)
09010       return FALSE;
09011 
09012     list = (struct rsbac_list_reg_item_t *) handle;
09013     if(list->self != list)
09014       return -RSBAC_EINVALIDVALUE;
09015 
09016 #ifdef CONFIG_RSBAC_LIST_TRANS
09017     if(ta_number)
09018       {
09019         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09020           return -RSBAC_EINVALIDTRANSACTION;
09021       }
09022 #endif
09023 
09024     rsbac_read_lock(&reg_head.lock, &rlock_flags);
09025 /*
09026 #ifdef CONFIG_RSBAC_DEBUG
09027     if(rsbac_debug_lists)
09028       rsbac_printk(KERN_DEBUG "rsbac_list_exist: testing on list %s.\n",
09029              list->name);
09030 #endif
09031 */
09032     rsbac_read_lock(&list->lock, &lock_flags);
09033 
09034 #ifdef CONFIG_RSBAC_LIST_TRANS
09035     if(ta_number && (list->ta_copied == ta_number))
09036       item_p = ta_lookup_item(ta_number, list, desc);
09037     else
09038 #endif
09039     item_p = lookup_item(list, desc);
09040     if(   item_p
09041        && (   !item_p->max_age
09042            || (item_p->max_age > RSBAC_CURRENT_TIME)
09043           )
09044       )
09045       { /* exists -> TRUE */
09046         result = TRUE;
09047       }
09048     else
09049       {
09050         result = FALSE;
09051       }
09052     rsbac_read_unlock(&list->lock, &lock_flags);
09053     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
09054     return result;
09055   }
09056 
09057 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09058 EXPORT_SYMBOL(rsbac_list_exist);
09059 #endif
09060 int rsbac_list_exist(
09061   rsbac_list_handle_t handle,
09062   void * desc)
09063   {
09064     return rsbac_ta_list_exist(0, handle, desc);
09065   }
09066 
09067 /* does item exist? */
09068 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09069 EXPORT_SYMBOL(rsbac_ta_list_lol_subexist);
09070 #endif
09071 int rsbac_ta_list_lol_subexist(
09072   rsbac_list_ta_number_t ta_number,
09073   rsbac_list_handle_t handle,
09074   void * desc,
09075   void * subdesc)
09076   {
09077     struct rsbac_list_lol_reg_item_t * list;
09078     struct rsbac_list_lol_item_t     * sublist;
09079     u_long lock_flags, rlock_flags;
09080     struct rsbac_list_item_t     * item_p;
09081     int result;
09082 
09083     if(!handle || !desc || !subdesc)
09084       return FALSE;
09085     if(!list_initialized)
09086       return FALSE;
09087 
09088     list = (struct rsbac_list_lol_reg_item_t *) handle;
09089     if(list->self != list)
09090       return -RSBAC_EINVALIDVALUE;
09091 
09092 #ifdef CONFIG_RSBAC_LIST_TRANS
09093     if(ta_number)
09094       {
09095         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09096           return -RSBAC_EINVALIDTRANSACTION;
09097       }
09098 #endif
09099 
09100     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09101 /*
09102 #ifdef CONFIG_RSBAC_DEBUG
09103     if(rsbac_debug_lists)
09104       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subexist: testing on list %s.\n",
09105              list->name);
09106 #endif
09107 */
09108     rsbac_read_lock(&list->lock, &lock_flags);
09109 
09110 #ifdef CONFIG_RSBAC_LIST_TRANS
09111     if(ta_number && (list->ta_copied == ta_number))
09112       sublist = ta_lookup_lol_item(ta_number, list, desc);
09113     else
09114 #endif
09115     sublist = lookup_lol_item(list, desc);
09116     if(sublist)
09117       { /* exists -> lookup subitem */
09118         item_p = lookup_lol_subitem(list, sublist, subdesc);
09119         if(   item_p
09120            && (   !item_p->max_age
09121                || (item_p->max_age > RSBAC_CURRENT_TIME)
09122               )
09123           )
09124           { /* exists -> TRUE */
09125             result = TRUE;
09126           }
09127         else
09128           {
09129             result = FALSE;
09130           }
09131       }
09132     else
09133       {
09134         result = FALSE;
09135       }
09136     rsbac_read_unlock(&list->lock, &lock_flags);
09137     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09138     return result;
09139   }
09140 
09141 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09142 EXPORT_SYMBOL(rsbac_list_lol_subexist);
09143 #endif
09144 int rsbac_list_lol_subexist(
09145   rsbac_list_handle_t handle,
09146   void * desc,
09147   void * subdesc)
09148   {
09149     return rsbac_ta_list_lol_subexist(0, handle, desc, subdesc);
09150   }
09151 
09152 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09153 EXPORT_SYMBOL(rsbac_ta_list_lol_subexist_compare);
09154 #endif
09155 int rsbac_ta_list_lol_subexist_compare(
09156   rsbac_list_ta_number_t ta_number,
09157   rsbac_list_handle_t handle,
09158   void * desc,
09159   void * subdesc,
09160   rsbac_list_compare_function_t compare)
09161   {
09162     struct rsbac_list_lol_reg_item_t * list;
09163     struct rsbac_list_lol_item_t     * sublist;
09164     u_long lock_flags, rlock_flags;
09165     struct rsbac_list_item_t     * item_p;
09166     int result;
09167 
09168     if(!handle || !desc || !subdesc)
09169       return FALSE;
09170     if(!list_initialized)
09171       return FALSE;
09172     /* Use standard function, if compare is not provided. */
09173     if(!compare)
09174       return rsbac_list_lol_subexist(handle, desc, subdesc);
09175 
09176     list = (struct rsbac_list_lol_reg_item_t *) handle;
09177     if(list->self != list)
09178       return -RSBAC_EINVALIDVALUE;
09179 
09180 #ifdef CONFIG_RSBAC_LIST_TRANS
09181     if(ta_number)
09182       {
09183         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09184           return -RSBAC_EINVALIDTRANSACTION;
09185       }
09186 #endif
09187 
09188     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09189 /*
09190 #ifdef CONFIG_RSBAC_DEBUG
09191     if(rsbac_debug_lists)
09192       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subexist_compare: testing on list %s.\n",
09193              list->name);
09194 #endif
09195 */
09196     rsbac_read_lock(&list->lock, &lock_flags);
09197 
09198 #ifdef CONFIG_RSBAC_LIST_TRANS
09199     if(ta_number && (list->ta_copied == ta_number))
09200       sublist = ta_lookup_lol_item(ta_number, list, desc);
09201     else
09202 #endif
09203     sublist = lookup_lol_item(list, desc);
09204     if(sublist)
09205       { /* exists -> lookup subitem */
09206         item_p = lookup_lol_subitem_user_compare(list, sublist, subdesc, compare);
09207         if(   item_p
09208            && (   !item_p->max_age
09209                || (item_p->max_age > RSBAC_CURRENT_TIME)
09210               )
09211           )
09212           { /* exists -> TRUE */
09213             result = TRUE;
09214           }
09215         else
09216           {
09217             result = FALSE;
09218           }
09219       }
09220     else
09221       {
09222         result = FALSE;
09223       }
09224     rsbac_read_unlock(&list->lock, &lock_flags);
09225     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09226     return result;
09227   }
09228 
09229 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09230 EXPORT_SYMBOL(rsbac_list_lol_subexist_compare);
09231 #endif
09232 int rsbac_list_lol_subexist_compare(
09233   rsbac_list_handle_t handle,
09234   void * desc,
09235   void * subdesc,
09236   rsbac_list_compare_function_t compare)
09237   {
09238     return rsbac_ta_list_lol_subexist_compare(0, handle,
09239                                               desc, subdesc, compare);
09240   }
09241 
09242 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09243 EXPORT_SYMBOL(rsbac_ta_list_lol_exist);
09244 #endif
09245 int rsbac_ta_list_lol_exist(
09246   rsbac_list_ta_number_t ta_number,
09247   rsbac_list_handle_t handle,
09248   void * desc)
09249   {
09250     struct rsbac_list_lol_reg_item_t * list;
09251     u_long lock_flags, rlock_flags;
09252     struct rsbac_list_lol_item_t     * item_p;
09253     int result;
09254 
09255     if(!handle || !desc)
09256       return FALSE;
09257     if(!list_initialized)
09258       return FALSE;
09259 
09260     list = (struct rsbac_list_lol_reg_item_t *) handle;
09261     if(list->self != list)
09262       return -RSBAC_EINVALIDVALUE;
09263 
09264 #ifdef CONFIG_RSBAC_LIST_TRANS
09265     if(ta_number)
09266       {
09267         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09268           return -RSBAC_EINVALIDTRANSACTION;
09269       }
09270 #endif
09271 
09272     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09273 /*
09274 #ifdef CONFIG_RSBAC_DEBUG
09275     if(rsbac_debug_lists)
09276       rsbac_printk(KERN_DEBUG "rsbac_list_lol_exist: testing on list %s.\n",
09277              list->name);
09278 #endif
09279 */
09280     rsbac_read_lock(&list->lock, &lock_flags);
09281 
09282 #ifdef CONFIG_RSBAC_LIST_TRANS
09283     if(ta_number && (list->ta_copied == ta_number))
09284       item_p = ta_lookup_lol_item(ta_number, list, desc);
09285     else
09286 #endif
09287     item_p = lookup_lol_item(list, desc);
09288     if(   item_p
09289        && (   !item_p->max_age
09290            || (item_p->max_age > RSBAC_CURRENT_TIME)
09291           )
09292       )
09293       { /* exists -> TRUE */
09294         result = TRUE;
09295       }
09296     else
09297       {
09298         result = FALSE;
09299       }
09300     rsbac_read_unlock(&list->lock, &lock_flags);
09301     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09302     return result;
09303   }
09304 
09305 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09306 EXPORT_SYMBOL(rsbac_list_lol_exist);
09307 #endif
09308 int rsbac_list_lol_exist(
09309   rsbac_list_handle_t handle,
09310   void * desc)
09311   {
09312     return rsbac_ta_list_lol_exist(0, handle, desc);
09313   }
09314 
09315 /* count number of elements */
09316 /* returns number of elements or negative error code */
09317 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09318 EXPORT_SYMBOL(rsbac_ta_list_lol_subcount);
09319 #endif
09320 long rsbac_ta_list_lol_subcount(
09321   rsbac_list_ta_number_t ta_number,
09322   rsbac_list_handle_t handle,
09323   void * desc)
09324   {
09325     struct rsbac_list_lol_reg_item_t * list;
09326     struct rsbac_list_lol_item_t     * sublist;
09327     u_long lock_flags, rlock_flags;
09328     long result;
09329 
09330     if(!handle)
09331       return -RSBAC_EINVALIDVALUE;
09332     if(!list_initialized)
09333       return -RSBAC_ENOTINITIALIZED;
09334 
09335     list = (struct rsbac_list_lol_reg_item_t *) handle;
09336     if(list->self != list)
09337       return -RSBAC_EINVALIDVALUE;
09338 
09339 #ifdef CONFIG_RSBAC_LIST_TRANS
09340     if(ta_number)
09341       {
09342         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09343           return -RSBAC_EINVALIDTRANSACTION;
09344       }
09345 #endif
09346 
09347     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09348 /*
09349 #ifdef CONFIG_RSBAC_DEBUG
09350     if(rsbac_debug_lists)
09351       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subcount: list %s.\n",
09352              list->name);
09353 #endif
09354 */
09355     rsbac_read_lock(&list->lock, &lock_flags);
09356 
09357 #ifdef CONFIG_RSBAC_LIST_TRANS
09358     if(ta_number && (list->ta_copied == ta_number))
09359       sublist = ta_lookup_lol_item(ta_number, list, desc);
09360     else
09361 #endif
09362     sublist = lookup_lol_item(list, desc);
09363     if(sublist)
09364       {
09365         result = sublist->count;
09366       }
09367     else
09368       {
09369         result = -RSBAC_ENOTFOUND;
09370       }
09371     rsbac_read_unlock(&list->lock, &lock_flags);
09372     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09373     return result;
09374   }
09375 
09376 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09377 EXPORT_SYMBOL(rsbac_list_lol_subcount);
09378 #endif
09379 long rsbac_list_lol_subcount(
09380   rsbac_list_handle_t handle,
09381   void * desc)
09382   {
09383     return rsbac_ta_list_lol_subcount(0, handle, desc);
09384   }
09385 
09386 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09387 EXPORT_SYMBOL(rsbac_ta_list_lol_all_subcount);
09388 #endif
09389 long rsbac_ta_list_lol_all_subcount(
09390   rsbac_list_ta_number_t ta_number,
09391   rsbac_list_handle_t handle)
09392   {
09393     struct rsbac_list_lol_reg_item_t * list;
09394     struct rsbac_list_lol_item_t     * sublist;
09395     u_long lock_flags, rlock_flags;
09396     long result = 0;
09397 
09398     if(!handle)
09399       return -RSBAC_EINVALIDVALUE;
09400     if(!list_initialized)
09401       return -RSBAC_ENOTINITIALIZED;
09402 
09403     list = (struct rsbac_list_lol_reg_item_t *) handle;
09404     if(list->self != list)
09405       return -RSBAC_EINVALIDVALUE;
09406 
09407 #ifdef CONFIG_RSBAC_LIST_TRANS
09408     if(ta_number)
09409       {
09410         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09411           return -RSBAC_EINVALIDTRANSACTION;
09412       }
09413 #endif
09414 
09415     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09416 /*
09417 #ifdef CONFIG_RSBAC_DEBUG
09418     if(rsbac_debug_lists)
09419       rsbac_printk(KERN_DEBUG "rsbac_list_lol_subcount: list %s.\n",
09420              list->name);
09421 #endif
09422 */
09423     rsbac_read_lock(&list->lock, &lock_flags);
09424 
09425 #ifdef CONFIG_RSBAC_LIST_TRANS
09426     if(ta_number && (list->ta_copied == ta_number))
09427       sublist = list->ta_head;
09428     else
09429 #endif
09430     sublist = list->head;
09431     while(sublist)
09432       {
09433         result += sublist->count;
09434         sublist = sublist->next;
09435       }
09436     rsbac_read_unlock(&list->lock, &lock_flags);
09437     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09438     return result;
09439   }
09440 
09441 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09442 EXPORT_SYMBOL(rsbac_list_lol_all_subcount);
09443 #endif
09444 long rsbac_list_lol_all_subcount(rsbac_list_handle_t handle)
09445   {
09446     return rsbac_ta_list_lol_all_subcount(0, handle);
09447   }
09448 
09449 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09450 EXPORT_SYMBOL(rsbac_ta_list_lol_count);
09451 #endif
09452 long rsbac_ta_list_lol_count(
09453   rsbac_list_ta_number_t ta_number,
09454   rsbac_list_handle_t handle)
09455   {
09456     struct rsbac_list_lol_reg_item_t * list;
09457 
09458     if(!handle)
09459       return -RSBAC_EINVALIDVALUE;
09460     if(!list_initialized)
09461       return -RSBAC_ENOTINITIALIZED;
09462 
09463     list = (struct rsbac_list_lol_reg_item_t *) handle;
09464     if(list->self != list)
09465       return -RSBAC_EINVALIDVALUE;
09466 
09467 #ifdef CONFIG_RSBAC_LIST_TRANS
09468     if(ta_number)
09469       {
09470         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09471           return -RSBAC_EINVALIDTRANSACTION;
09472       }
09473 #endif
09474 
09475 /*
09476 #ifdef CONFIG_RSBAC_DEBUG
09477     if(rsbac_debug_lists)
09478       rsbac_printk(KERN_DEBUG "rsbac_list_lol_count: list %s.\n",
09479              list->name);
09480 #endif
09481 */
09482 #ifdef CONFIG_RSBAC_LIST_TRANS
09483     if(ta_number && (list->ta_copied == ta_number))
09484       return list->ta_count;
09485     else
09486 #endif
09487     return list->count;
09488   }
09489 
09490 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09491 EXPORT_SYMBOL(rsbac_list_lol_count);
09492 #endif
09493 long rsbac_list_lol_count(rsbac_list_handle_t handle)
09494   {
09495     return rsbac_ta_list_lol_count(0, handle);
09496   }
09497 
09498 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09499 EXPORT_SYMBOL(rsbac_ta_list_count);
09500 #endif
09501 long rsbac_ta_list_count(
09502   rsbac_list_ta_number_t ta_number,
09503   rsbac_list_handle_t handle)
09504   {
09505     struct rsbac_list_reg_item_t * list;
09506 
09507     if(!handle)
09508       return -RSBAC_EINVALIDVALUE;
09509     if(!list_initialized)
09510       return -RSBAC_ENOTINITIALIZED;
09511 
09512     list = (struct rsbac_list_reg_item_t *) handle;
09513     if(list->self != list)
09514       return -RSBAC_EINVALIDVALUE;
09515 
09516 #ifdef CONFIG_RSBAC_LIST_TRANS
09517     if(ta_number)
09518       {
09519         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09520           return -RSBAC_EINVALIDTRANSACTION;
09521       }
09522 #endif
09523 
09524 #ifdef CONFIG_RSBAC_LIST_TRANS
09525     if(ta_number && (list->ta_copied == ta_number))
09526       return list->ta_count;
09527     else
09528 #endif
09529     return list->count;
09530   }
09531 
09532 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09533 EXPORT_SYMBOL(rsbac_list_count);
09534 #endif
09535 long rsbac_list_count(rsbac_list_handle_t handle)
09536   {
09537     return rsbac_ta_list_count(0, handle);
09538   }
09539 
09540 /* Get array of all descriptors */
09541 /* Returns number of elements or negative error code */
09542 /* If return value > 0, *array_p contains a pointer to a vmalloc'd array of descs,
09543    otherwise *array_p is set to NULL. If *array_p has been set, caller must call
09544    rsbac_vfree(*array_p) after use! */
09545 
09546 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09547 EXPORT_SYMBOL(rsbac_ta_list_get_all_desc);
09548 #endif
09549 long rsbac_ta_list_get_all_desc(
09550   rsbac_list_ta_number_t ta_number,
09551   rsbac_list_handle_t handle,
09552   void ** array_p)
09553   {
09554     struct rsbac_list_reg_item_t * list;
09555     struct rsbac_list_item_t     * item_p;
09556            char                  * buffer;
09557     u_long lock_flags, rlock_flags;
09558     u_long offset = 0;
09559     long result = 0;
09560     u_int item_size;
09561 
09562     if(!handle)
09563       return -RSBAC_EINVALIDVALUE;
09564     if(!array_p)
09565       return -RSBAC_EINVALIDVALUE;
09566     if(!list_initialized)
09567       return -RSBAC_ENOTINITIALIZED;
09568 
09569     list = (struct rsbac_list_reg_item_t *) handle;
09570     if(list->self != list)
09571       return -RSBAC_EINVALIDVALUE;
09572     *array_p = NULL;
09573 
09574 #ifdef CONFIG_RSBAC_LIST_TRANS
09575     if(ta_number)
09576       {
09577         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09578           return -RSBAC_EINVALIDTRANSACTION;
09579       }
09580 #endif
09581 
09582     rsbac_read_lock(&reg_head.lock, &rlock_flags);
09583 /*
09584 #ifdef CONFIG_RSBAC_DEBUG
09585     if(rsbac_debug_lists)
09586       rsbac_printk(KERN_DEBUG "rsbac_list_get_all_desc: list %s.\n",
09587              list->name);
09588 #endif
09589 */
09590     rsbac_read_lock(&list->lock, &lock_flags);
09591 #ifdef CONFIG_RSBAC_LIST_TRANS
09592     if(ta_number && (list->ta_copied == ta_number))
09593       {
09594         if(list->ta_count)
09595           {
09596             item_size = list->info.desc_size;
09597             buffer = rsbac_vmalloc(item_size * list->ta_count);
09598             if(buffer)
09599               {
09600                 item_p = list->ta_head;
09601                 while(item_p)
09602                   {
09603                     if(   !item_p->max_age
09604                        || (item_p->max_age > RSBAC_CURRENT_TIME)
09605                       )
09606                       {
09607                         memcpy(buffer + offset,
09608                                ((char *) item_p) + sizeof(*item_p),
09609                                item_size);
09610                         offset += item_size;
09611                         result++;
09612                       }
09613                     item_p = item_p->next;
09614                   }
09615                 *array_p = buffer;
09616               }
09617             else
09618               {
09619                 result = -RSBAC_ENOMEM;
09620               }
09621           }
09622       }
09623     else
09624 #endif
09625     if(list->count)
09626       {
09627         item_size = list->info.desc_size;
09628         buffer = rsbac_vmalloc(item_size * list->count);
09629         if(buffer)
09630           {
09631             item_p = list->head;
09632             while(item_p)
09633               {
09634                 if(   !item_p->max_age
09635                    || (item_p->max_age > RSBAC_CURRENT_TIME)
09636                   )
09637                   {
09638                     memcpy(buffer + offset,
09639                            ((char *) item_p) + sizeof(*item_p),
09640                            item_size);
09641                     offset += item_size;
09642                     result++;
09643                   }
09644                 item_p = item_p->next;
09645               }
09646             *array_p = buffer;
09647           }
09648         else
09649           {
09650             result = -RSBAC_ENOMEM;
09651           }
09652       }
09653     rsbac_read_unlock(&list->lock, &lock_flags);
09654     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
09655     return result;
09656   }
09657 
09658 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09659 EXPORT_SYMBOL(rsbac_list_get_all_desc);
09660 #endif
09661 long rsbac_list_get_all_desc(
09662   rsbac_list_handle_t handle,
09663   void ** array_p)
09664   {
09665     return rsbac_ta_list_get_all_desc(0, handle, array_p);
09666   }
09667 
09668 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09669 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdesc_ttl);
09670 #endif
09671 long rsbac_ta_list_lol_get_all_subdesc_ttl(
09672   rsbac_list_ta_number_t ta_number,
09673   rsbac_list_handle_t handle,
09674   void * desc,
09675   void ** array_p,
09676   rsbac_time_t ** ttl_array_p)
09677   {
09678     struct rsbac_list_lol_reg_item_t * list;
09679     struct rsbac_list_lol_item_t     * sublist;
09680     struct rsbac_list_item_t         * item_p;
09681            char                      * buffer;
09682            rsbac_time_t              * ttl_p = NULL;
09683     u_long lock_flags, rlock_flags;
09684     u_long offset = 0;
09685     long result = 0;
09686     u_int item_size;
09687 
09688     if(!handle)
09689       return -RSBAC_EINVALIDVALUE;
09690     if(!array_p)
09691       return -RSBAC_EINVALIDVALUE;
09692     if(!list_initialized)
09693       return -RSBAC_ENOTINITIALIZED;
09694 
09695     list = (struct rsbac_list_lol_reg_item_t *) handle;
09696     if(list->self != list)
09697       return -RSBAC_EINVALIDVALUE;
09698     *array_p = NULL;
09699 
09700 #ifdef CONFIG_RSBAC_LIST_TRANS
09701     if(ta_number)
09702       {
09703         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09704           return -RSBAC_EINVALIDTRANSACTION;
09705       }
09706 #endif
09707 
09708     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09709 /*
09710 #ifdef CONFIG_RSBAC_DEBUG
09711     if(rsbac_debug_lists)
09712       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_all_desc: list %s.\n",
09713              list->name);
09714 #endif
09715 */
09716     rsbac_read_lock(&list->lock, &lock_flags);
09717 #ifdef CONFIG_RSBAC_LIST_TRANS
09718     if(ta_number && (list->ta_copied == ta_number))
09719       sublist = ta_lookup_lol_item(ta_number, list, desc);
09720     else
09721 #endif
09722     sublist = lookup_lol_item(list, desc);
09723     if(sublist && sublist->count)
09724       {
09725         item_size = list->info.subdesc_size;
09726         buffer = rsbac_vmalloc(item_size * sublist->count);
09727         if(buffer)
09728           {
09729             if(ttl_array_p)
09730               ttl_p = rsbac_vmalloc(sizeof(**ttl_array_p) * sublist->count);
09731             item_p = sublist->head;
09732             while(item_p)
09733               {
09734                 if(   !item_p->max_age
09735                    || (item_p->max_age > RSBAC_CURRENT_TIME)
09736                   )
09737                   {
09738                     memcpy(buffer + offset,
09739                            ((char *) item_p) + sizeof(*item_p),
09740                            item_size);
09741                     if(ttl_p)
09742                       {
09743                         if(item_p->max_age)
09744                           ttl_p[result] = item_p->max_age - RSBAC_CURRENT_TIME;
09745                         else
09746                           ttl_p[result] = 0;
09747                       }
09748                     offset += item_size;
09749                     result++;
09750                   }
09751                 item_p = item_p->next;
09752               }
09753             *array_p = buffer;
09754             if(ttl_array_p)
09755               *ttl_array_p = ttl_p;
09756           }
09757         else
09758           {
09759             result = -RSBAC_ENOMEM;
09760           }
09761       }
09762     rsbac_read_unlock(&list->lock, &lock_flags);
09763     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09764     return result;
09765   }
09766 
09767 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09768 EXPORT_SYMBOL(rsbac_list_lol_get_all_subdesc_ttl);
09769 #endif
09770 long rsbac_list_lol_get_all_subdesc_ttl(
09771   rsbac_list_handle_t handle,
09772   void * desc,
09773   void ** array_p,
09774   rsbac_time_t ** ttl_array_p)
09775   {
09776     return rsbac_ta_list_lol_get_all_subdesc_ttl(0,
09777                                                  handle,
09778                                                  desc,
09779                                                  array_p,
09780                                                  ttl_array_p);
09781   }
09782 
09783 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09784 EXPORT_SYMBOL(rsbac_list_lol_get_all_subdesc);
09785 #endif
09786 long rsbac_list_lol_get_all_subdesc(rsbac_list_handle_t handle, void * desc, void ** array_p)
09787   {
09788     return rsbac_ta_list_lol_get_all_subdesc_ttl(0, handle,
09789                                                  desc, array_p, NULL);
09790   }
09791 
09792 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09793 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_desc);
09794 #endif
09795 long rsbac_ta_list_lol_get_all_desc(
09796   rsbac_list_ta_number_t ta_number,
09797   rsbac_list_handle_t handle,
09798   void ** array_p)
09799   {
09800     struct rsbac_list_lol_reg_item_t * list;
09801     struct rsbac_list_lol_item_t     * item_p;
09802            char                      * buffer;
09803     u_long lock_flags, rlock_flags;
09804     u_long offset = 0;
09805     long result = 0;
09806     u_int item_size;
09807 
09808     if(!handle)
09809       return -RSBAC_EINVALIDVALUE;
09810     if(!array_p)
09811       return -RSBAC_EINVALIDVALUE;
09812     if(!list_initialized)
09813       return -RSBAC_ENOTINITIALIZED;
09814 
09815     list = (struct rsbac_list_lol_reg_item_t *) handle;
09816     if(list->self != list)
09817       return -RSBAC_EINVALIDVALUE;
09818     *array_p = NULL;
09819 
09820 #ifdef CONFIG_RSBAC_LIST_TRANS
09821     if(ta_number)
09822       {
09823         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09824           return -RSBAC_EINVALIDTRANSACTION;
09825       }
09826 #endif
09827 
09828     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
09829 /*
09830 #ifdef CONFIG_RSBAC_DEBUG
09831     if(rsbac_debug_lists)
09832       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_all_desc: list %s.\n",
09833              list->name);
09834 #endif
09835 */
09836     rsbac_read_lock(&list->lock, &lock_flags);
09837 #ifdef CONFIG_RSBAC_LIST_TRANS
09838     if(ta_number && (list->ta_copied == ta_number))
09839       {
09840         if(list->ta_count)
09841           {
09842             item_size = list->info.desc_size;
09843             buffer = rsbac_vmalloc(item_size * list->ta_count);
09844             if(buffer)
09845               {
09846                 item_p = list->ta_head;
09847                 while(item_p)
09848                   {
09849                     if(   !item_p->max_age
09850                        || (item_p->max_age > RSBAC_CURRENT_TIME)
09851                       )
09852                       {
09853                         memcpy(buffer + offset,
09854                                ((char *) item_p) + sizeof(*item_p),
09855                                item_size);
09856                         offset += item_size;
09857                         result++;
09858                       }
09859                     item_p = item_p->next;
09860                   }
09861                 *array_p = buffer;
09862               }
09863             else
09864               {
09865                 result = -RSBAC_ENOMEM;
09866               }
09867           }
09868       }
09869     else
09870 #endif
09871     if(list->count)
09872       {
09873         item_size = list->info.desc_size;
09874         buffer = rsbac_vmalloc(item_size * list->count);
09875         if(buffer)
09876           {
09877             item_p = list->head;
09878             while(item_p)
09879               {
09880                 if(   !item_p->max_age
09881                    || (item_p->max_age > RSBAC_CURRENT_TIME)
09882                   )
09883                   {
09884                     memcpy(buffer + offset,
09885                            ((char *) item_p) + sizeof(*item_p),
09886                            item_size);
09887                     offset += item_size;
09888                     result++;
09889                   }
09890                 item_p = item_p->next;
09891               }
09892             *array_p = buffer;
09893           }
09894         else
09895           {
09896             result = -RSBAC_ENOMEM;
09897           }
09898       }
09899     rsbac_read_unlock(&list->lock, &lock_flags);
09900     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
09901     return result;
09902   }
09903 
09904 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09905 EXPORT_SYMBOL(rsbac_list_lol_get_all_desc);
09906 #endif
09907 long rsbac_list_lol_get_all_desc(rsbac_list_handle_t handle, void ** array_p)
09908   {
09909     return rsbac_ta_list_lol_get_all_desc(0, handle, array_p);
09910   }
09911 
09912 /* Get array of all data */
09913 /* Returns number of elements or negative error code */
09914 /* If return value > 0, *array_p contains a pointer to a vmalloc'd array of datas,
09915    otherwise *array_p is set to NULL. If *array_p has been set, caller must call
09916    rsbac_vfree(*array_p) after use! */
09917 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
09918 EXPORT_SYMBOL(rsbac_ta_list_get_all_data);
09919 #endif
09920 long rsbac_ta_list_get_all_data(
09921   rsbac_list_ta_number_t ta_number,
09922   rsbac_list_handle_t handle,
09923   void ** array_p)
09924   {
09925     struct rsbac_list_reg_item_t * list;
09926     struct rsbac_list_item_t     * item_p;
09927            char                  * buffer;
09928     u_long lock_flags, rlock_flags;
09929     u_long offset = 0;
09930     long result = 0;
09931     u_int item_size;
09932     u_int item_offset;
09933 
09934     if(!handle)
09935       return -RSBAC_EINVALIDVALUE;
09936     if(!array_p)
09937       return -RSBAC_EINVALIDVALUE;
09938     if(!list_initialized)
09939       return -RSBAC_ENOTINITIALIZED;
09940 
09941     list = (struct rsbac_list_reg_item_t *) handle;
09942     if(list->self != list)
09943       return -RSBAC_EINVALIDVALUE;
09944     *array_p = NULL;
09945 
09946 #ifdef CONFIG_RSBAC_LIST_TRANS
09947     if(ta_number)
09948       {
09949         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
09950           return -RSBAC_EINVALIDTRANSACTION;
09951       }
09952 #endif
09953 
09954     rsbac_read_lock(&reg_head.lock, &rlock_flags);
09955 /*
09956 #ifdef CONFIG_RSBAC_DEBUG
09957     if(rsbac_debug_lists)
09958       rsbac_printk(KERN_DEBUG "rsbac_list_get_all_data: list %s.\n",
09959              list->name);
09960 #endif
09961 */
09962     rsbac_read_lock(&list->lock, &lock_flags);
09963     if(!list->info.data_size)
09964       {
09965         rsbac_read_unlock(&list->lock, &lock_flags);
09966         rsbac_read_unlock(&reg_head.lock, &rlock_flags);
09967         return -RSBAC_EINVALIDREQUEST;
09968       }
09969 #ifdef CONFIG_RSBAC_LIST_TRANS
09970     if(ta_number && (list->ta_copied == ta_number))
09971       {
09972         if(list->ta_count)
09973           {
09974             item_size = list->info.data_size;
09975             item_offset = list->info.desc_size;
09976             buffer = rsbac_vmalloc(item_size * list->ta_count);
09977             if(buffer)
09978               {
09979                 item_p = list->ta_head;
09980                 while(item_p)
09981                   {
09982                     if(   !item_p->max_age
09983                        || (item_p->max_age > RSBAC_CURRENT_TIME)
09984                       )
09985                       {
09986                         memcpy(buffer + offset,
09987                                ((char *) item_p) + sizeof(*item_p) + item_offset,
09988                                item_size);
09989                         offset += item_size;
09990                         result++;
09991                       }
09992                     item_p = item_p->next;
09993                   }
09994                 *array_p = buffer;
09995               }
09996             else
09997               {
09998                 result = -RSBAC_ENOMEM;
09999               }
10000           }
10001       }
10002     else
10003 #endif
10004     if(list->count)
10005       {
10006         item_size = list->info.data_size;
10007         item_offset = list->info.desc_size;
10008         buffer = rsbac_vmalloc(item_size * list->count);
10009         if(buffer)
10010           {
10011             item_p = list->head;
10012             while(item_p)
10013               {
10014                 if(   !item_p->max_age
10015                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10016                   )
10017                   {
10018                     memcpy(buffer + offset,
10019                            ((char *) item_p) + sizeof(*item_p) + item_offset,
10020                            item_size);
10021                     offset += item_size;
10022                     result++;
10023                   }
10024                 item_p = item_p->next;
10025               }
10026             *array_p = buffer;
10027           }
10028         else
10029           {
10030             result = -RSBAC_ENOMEM;
10031           }
10032       }
10033     rsbac_read_unlock(&list->lock, &lock_flags);
10034     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
10035     return result;
10036   }
10037 
10038 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10039 EXPORT_SYMBOL(rsbac_list_get_all_data);
10040 #endif
10041 long rsbac_list_get_all_data(
10042   rsbac_list_handle_t handle,
10043   void ** array_p)
10044   {
10045     return rsbac_ta_list_get_all_data(0, handle, array_p);
10046   }
10047 
10048 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10049 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subdata);
10050 #endif
10051 long rsbac_ta_list_lol_get_all_subdata(
10052   rsbac_list_ta_number_t ta_number,
10053   rsbac_list_handle_t handle,
10054   void * desc,
10055   void ** array_p)
10056   {
10057     struct rsbac_list_lol_reg_item_t * list;
10058     struct rsbac_list_lol_item_t     * sublist;
10059     struct rsbac_list_item_t         * item_p;
10060            char                      * buffer;
10061     u_long lock_flags, rlock_flags;
10062     u_long offset = 0;
10063     long result = 0;
10064     u_int item_size;
10065     u_int item_offset;
10066 
10067     if(!handle)
10068       return -RSBAC_EINVALIDVALUE;
10069     if(!array_p)
10070       return -RSBAC_EINVALIDVALUE;
10071     if(!list_initialized)
10072       return -RSBAC_ENOTINITIALIZED;
10073 
10074     list = (struct rsbac_list_lol_reg_item_t *) handle;
10075     if(list->self != list)
10076       return -RSBAC_EINVALIDVALUE;
10077     *array_p = NULL;
10078 
10079 #ifdef CONFIG_RSBAC_LIST_TRANS
10080     if(ta_number)
10081       {
10082         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10083           return -RSBAC_EINVALIDTRANSACTION;
10084       }
10085 #endif
10086 
10087     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10088 /*
10089 #ifdef CONFIG_RSBAC_DEBUG
10090     if(rsbac_debug_lists)
10091       rsbac_printk(KERN_DEBUG "rsbac_ta_list_lol_get_all_desc: list %s.\n",
10092              list->name);
10093 #endif
10094 */
10095     rsbac_read_lock(&list->lock, &lock_flags);
10096     if(!list->info.subdata_size)
10097       {
10098         rsbac_read_unlock(&list->lock, &lock_flags);
10099         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10100         return -RSBAC_EINVALIDREQUEST;
10101       }
10102 #ifdef CONFIG_RSBAC_LIST_TRANS
10103     if(ta_number && (list->ta_copied == ta_number))
10104       sublist = ta_lookup_lol_item(ta_number, list, desc);
10105     else
10106 #endif
10107     sublist = lookup_lol_item(list, desc);
10108     if(sublist && sublist->count)
10109       {
10110         item_size = list->info.subdata_size;
10111         item_offset = list->info.subdesc_size;
10112         buffer = rsbac_vmalloc(item_size * sublist->count);
10113         if(buffer)
10114           {
10115             item_p = sublist->head;
10116             while(item_p)
10117               {
10118                 if(   !item_p->max_age
10119                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10120                   )
10121                   {
10122                     memcpy(buffer + offset,
10123                            ((char *) item_p) + sizeof(*item_p) + item_offset,
10124                            item_size);
10125                     offset += item_size;
10126                     result++;
10127                   }
10128                 item_p = item_p->next;
10129               }
10130             *array_p = buffer;
10131           }
10132         else
10133           {
10134             result = -RSBAC_ENOMEM;
10135           }
10136       }
10137     rsbac_read_unlock(&list->lock, &lock_flags);
10138     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10139     return result;
10140   }
10141 
10142 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10143 EXPORT_SYMBOL(rsbac_list_lol_get_all_subdata);
10144 #endif
10145 long rsbac_list_lol_get_all_subdata(
10146   rsbac_list_handle_t handle,
10147   void * desc,
10148   void ** array_p)
10149   {
10150     return rsbac_ta_list_lol_get_all_subdata(0, handle, desc, array_p);
10151   }
10152 
10153 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10154 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_data);
10155 #endif
10156 long rsbac_ta_list_lol_get_all_data(
10157   rsbac_list_ta_number_t ta_number,
10158   rsbac_list_handle_t handle,
10159   void ** array_p)
10160   {
10161     struct rsbac_list_lol_reg_item_t * list;
10162     struct rsbac_list_lol_item_t     * item_p;
10163            char                      * buffer;
10164     u_long lock_flags, rlock_flags;
10165     u_long offset = 0;
10166     long result = 0;
10167     u_int item_size;
10168     u_int item_offset;
10169 
10170     if(!handle)
10171       return -RSBAC_EINVALIDVALUE;
10172     if(!array_p)
10173       return -RSBAC_EINVALIDVALUE;
10174     if(!list_initialized)
10175       return -RSBAC_ENOTINITIALIZED;
10176 
10177     list = (struct rsbac_list_lol_reg_item_t *) handle;
10178     if(list->self != list)
10179       return -RSBAC_EINVALIDVALUE;
10180     *array_p = NULL;
10181 
10182 #ifdef CONFIG_RSBAC_LIST_TRANS
10183     if(ta_number)
10184       {
10185         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10186           return -RSBAC_EINVALIDTRANSACTION;
10187       }
10188 #endif
10189 
10190     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10191 /*
10192 #ifdef CONFIG_RSBAC_DEBUG
10193     if(rsbac_debug_lists)
10194       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_all_desc: list %s.\n",
10195              list->name);
10196 #endif
10197 */
10198     rsbac_read_lock(&list->lock, &lock_flags);
10199     if(!list->info.data_size)
10200       {
10201         rsbac_read_unlock(&list->lock, &lock_flags);
10202         rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10203         return -RSBAC_EINVALIDREQUEST;
10204       }
10205 #ifdef CONFIG_RSBAC_LIST_TRANS
10206     if(ta_number && (list->ta_copied == ta_number))
10207       {
10208         if(list->ta_count)
10209           {
10210             item_size = list->info.data_size;
10211             item_offset = list->info.desc_size;
10212             buffer = rsbac_vmalloc(item_size * list->ta_count);
10213             if(buffer)
10214               {
10215                 item_p = list->ta_head;
10216                 while(item_p)
10217                   {
10218                     if(   !item_p->max_age
10219                        || (item_p->max_age > RSBAC_CURRENT_TIME)
10220                       )
10221                       {
10222                         memcpy(buffer + offset,
10223                                ((char *) item_p) + sizeof(*item_p) + item_offset,
10224                                item_size);
10225                         offset += item_size;
10226                         result++;
10227                       }
10228                     item_p = item_p->next;
10229                   }
10230                 *array_p = buffer;
10231               }
10232             else
10233               {
10234                 result = -RSBAC_ENOMEM;
10235               }
10236           }
10237       }
10238     else
10239 #endif
10240     if(list->count)
10241       {
10242         item_size = list->info.data_size;
10243         item_offset = list->info.desc_size;
10244         buffer = rsbac_vmalloc(item_size * list->count);
10245         if(buffer)
10246           {
10247             item_p = list->head;
10248             while(item_p)
10249               {
10250                 if(   !item_p->max_age
10251                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10252                   )
10253                   {
10254                     memcpy(buffer + offset,
10255                            ((char *) item_p) + sizeof(*item_p) + item_offset,
10256                            item_size);
10257                     offset += item_size;
10258                     result++;
10259                   }
10260                 item_p = item_p->next;
10261               }
10262             *array_p = buffer;
10263           }
10264         else
10265           {
10266             result = -RSBAC_ENOMEM;
10267           }
10268       }
10269     rsbac_read_unlock(&list->lock, &lock_flags);
10270     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10271     return result;
10272   }
10273 
10274 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10275 EXPORT_SYMBOL(rsbac_list_lol_get_all_data);
10276 #endif
10277 long rsbac_list_lol_get_all_data(
10278   rsbac_list_handle_t handle,
10279   void ** array_p)
10280   {
10281     return rsbac_ta_list_lol_get_all_data(0, handle, array_p);
10282   }
10283 
10284 /* Get item size */
10285 
10286 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10287 EXPORT_SYMBOL(rsbac_list_get_item_size);
10288 #endif
10289 int rsbac_list_get_item_size(rsbac_list_handle_t handle)
10290   {
10291     struct rsbac_list_reg_item_t * list;
10292 
10293     if(!handle)
10294       return -RSBAC_EINVALIDVALUE;
10295     if(!list_initialized)
10296       return -RSBAC_ENOTINITIALIZED;
10297 
10298     list = (struct rsbac_list_reg_item_t *) handle;
10299     if(list->self != list)
10300       return -RSBAC_EINVALIDVALUE;
10301     return list->info.desc_size + list->info.data_size;
10302   }
10303 
10304 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10305 EXPORT_SYMBOL(rsbac_list_lol_get_subitem_size);
10306 #endif
10307 int rsbac_list_lol_get_subitem_size(rsbac_list_handle_t handle)
10308   {
10309     struct rsbac_list_lol_reg_item_t * list;
10310 
10311     if(!handle)
10312       return -RSBAC_EINVALIDVALUE;
10313     if(!list_initialized)
10314       return -RSBAC_ENOTINITIALIZED;
10315 
10316     list = (struct rsbac_list_lol_reg_item_t *) handle;
10317     if(list->self != list)
10318       return -RSBAC_EINVALIDVALUE;
10319     return list->info.subdesc_size + list->info.subdata_size;
10320   }
10321 
10322 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10323 EXPORT_SYMBOL(rsbac_list_lol_get_item_size);
10324 #endif
10325 int rsbac_list_lol_get_item_size(rsbac_list_handle_t handle)
10326   {
10327     struct rsbac_list_lol_reg_item_t * list;
10328 
10329     if(!handle)
10330       return -RSBAC_EINVALIDVALUE;
10331     if(!list_initialized)
10332       return -RSBAC_ENOTINITIALIZED;
10333 
10334     list = (struct rsbac_list_lol_reg_item_t *) handle;
10335     if(list->self != list)
10336       return -RSBAC_EINVALIDVALUE;
10337     return list->info.desc_size + list->info.data_size;
10338   }
10339 
10340 /* Get array of all items */
10341 /* Returns number of items or negative error code */
10342 /* If return value > 0, *array_p contains a pointer to a rsbac_vmalloc'd array of items,
10343    where desc and data are placed directly behind each other.
10344    If *array_p has been set (return value > 0), caller must call rsbac_vfree(*array_p) after use! */
10345 
10346 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10347 EXPORT_SYMBOL(rsbac_ta_list_get_all_items_ttl);
10348 #endif
10349 long rsbac_ta_list_get_all_items_ttl(
10350   rsbac_list_ta_number_t ta_number,
10351   rsbac_list_handle_t handle,
10352   void ** array_p,
10353   rsbac_time_t ** ttl_array_p)
10354   {
10355     struct rsbac_list_reg_item_t * list;
10356     struct rsbac_list_item_t     * item_p;
10357            char                  * buffer;
10358            rsbac_time_t              * ttl_p = NULL;
10359     u_long lock_flags, rlock_flags;
10360     u_long offset = 0;
10361     long result = 0;
10362     u_int item_size;
10363 
10364     if(!handle)
10365       return -RSBAC_EINVALIDVALUE;
10366     if(!array_p)
10367       return -RSBAC_EINVALIDPOINTER;
10368     if(!list_initialized)
10369       return -RSBAC_ENOTINITIALIZED;
10370 
10371     list = (struct rsbac_list_reg_item_t *) handle;
10372     if(list->self != list)
10373       return -RSBAC_EINVALIDVALUE;
10374     *array_p = NULL;
10375 
10376 #ifdef CONFIG_RSBAC_LIST_TRANS
10377     if(ta_number)
10378       {
10379         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10380           return -RSBAC_EINVALIDTRANSACTION;
10381       }
10382 #endif
10383 
10384     rsbac_read_lock(&reg_head.lock, &rlock_flags);
10385 /*
10386 #ifdef CONFIG_RSBAC_DEBUG
10387     if(rsbac_debug_lists)
10388       rsbac_printk(KERN_DEBUG "rsbac_list_get_all_items: list %s.\n",
10389              list->name);
10390 #endif
10391 */
10392     rsbac_read_lock(&list->lock, &lock_flags);
10393 #ifdef CONFIG_RSBAC_LIST_TRANS
10394     if(ta_number && (list->ta_copied == ta_number))
10395       {
10396         if(list->ta_count)
10397           {
10398             item_size = list->info.desc_size + list->info.data_size;
10399             buffer = rsbac_vmalloc(item_size * list->ta_count);
10400             if(buffer)
10401               {
10402                 if(ttl_array_p)
10403                   ttl_p = rsbac_vmalloc(sizeof(**ttl_array_p) * list->ta_count);
10404                 item_p = list->ta_head;
10405                 while(item_p)
10406                   {
10407                     if(   !item_p->max_age
10408                        || (item_p->max_age > RSBAC_CURRENT_TIME)
10409                       )
10410                       {
10411                         memcpy(buffer + offset,
10412                                ((char *) item_p) + sizeof(*item_p),
10413                                item_size);
10414                         if(ttl_p)
10415                           {
10416                             if(item_p->max_age)
10417                               ttl_p[result] = item_p->max_age - RSBAC_CURRENT_TIME;
10418                             else
10419                               ttl_p[result] = 0;
10420                           }
10421                         offset += item_size;
10422                         result++;
10423                       }
10424                     item_p = item_p->next;
10425                   }
10426                 *array_p = buffer;
10427                 if(ttl_array_p)
10428                   *ttl_array_p = ttl_p;
10429               }
10430             else
10431               {
10432                 result = -RSBAC_ENOMEM;
10433               }
10434           }
10435       }
10436     else
10437 #endif
10438     if(list->count)
10439       {
10440         item_size = list->info.desc_size + list->info.data_size;
10441         buffer = rsbac_vmalloc(item_size * list->count);
10442         if(buffer)
10443           {
10444             if(ttl_array_p)
10445               ttl_p = rsbac_vmalloc(sizeof(**ttl_array_p) * list->count);
10446             item_p = list->head;
10447             while(item_p)
10448               {
10449                 if(   !item_p->max_age
10450                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10451                   )
10452                   {
10453                     memcpy(buffer + offset,
10454                            ((char *) item_p) + sizeof(*item_p),
10455                            item_size);
10456                     if(ttl_p)
10457                       {
10458                         if(item_p->max_age)
10459                           ttl_p[result] = item_p->max_age - RSBAC_CURRENT_TIME;
10460                         else
10461                           ttl_p[result] = 0;
10462                       }
10463                     offset += item_size;
10464                     result++;
10465                   }
10466                 item_p = item_p->next;
10467               }
10468             *array_p = buffer;
10469             if(ttl_array_p)
10470               *ttl_array_p = ttl_p;
10471           }
10472         else
10473           {
10474             result = -RSBAC_ENOMEM;
10475           }
10476       }
10477     rsbac_read_unlock(&list->lock, &lock_flags);
10478     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
10479     return result;
10480   }
10481 
10482 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10483 EXPORT_SYMBOL(rsbac_list_get_all_items_ttl);
10484 #endif
10485 long rsbac_list_get_all_items_ttl(
10486   rsbac_list_handle_t handle,
10487   void ** array_p,
10488   rsbac_time_t ** ttl_array_p)
10489   {
10490     return rsbac_ta_list_get_all_items_ttl(0, handle, array_p, ttl_array_p);
10491   }
10492 
10493 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10494 EXPORT_SYMBOL(rsbac_list_get_all_items);
10495 #endif
10496 long rsbac_list_get_all_items(rsbac_list_handle_t handle, void ** array_p)
10497   {
10498     return rsbac_ta_list_get_all_items_ttl(0, handle, array_p, NULL);
10499   }
10500 
10501 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10502 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_subitems_ttl);
10503 #endif
10504 long rsbac_ta_list_lol_get_all_subitems_ttl(
10505   rsbac_list_ta_number_t ta_number,
10506   rsbac_list_handle_t handle,
10507   void * desc,
10508   void ** array_p,
10509   rsbac_time_t ** ttl_array_p)
10510   {
10511     struct rsbac_list_lol_reg_item_t * list;
10512     struct rsbac_list_lol_item_t     * sublist;
10513     struct rsbac_list_item_t         * item_p;
10514            char                      * buffer;
10515            rsbac_time_t              * ttl_p = NULL;
10516     u_long lock_flags, rlock_flags;
10517     u_long offset = 0;
10518     long result = 0;
10519     u_int item_size;
10520 
10521     if(!handle)
10522       return -RSBAC_EINVALIDVALUE;
10523     if(!array_p)
10524       return -RSBAC_EINVALIDVALUE;
10525     if(!list_initialized)
10526       return -RSBAC_ENOTINITIALIZED;
10527 
10528     list = (struct rsbac_list_lol_reg_item_t *) handle;
10529     if(list->self != list)
10530       return -RSBAC_EINVALIDVALUE;
10531     *array_p = NULL;
10532 
10533 #ifdef CONFIG_RSBAC_LIST_TRANS
10534     if(ta_number)
10535       {
10536         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10537           return -RSBAC_EINVALIDTRANSACTION;
10538       }
10539 #endif
10540 
10541     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10542 /*
10543 #ifdef CONFIG_RSBAC_DEBUG
10544     if(rsbac_debug_lists)
10545       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_all_subitems: list %s.\n",
10546              list->name);
10547 #endif
10548 */
10549     rsbac_read_lock(&list->lock, &lock_flags);
10550 #ifdef CONFIG_RSBAC_LIST_TRANS
10551     if(ta_number && (list->ta_copied == ta_number))
10552       sublist = ta_lookup_lol_item(ta_number, list, desc);
10553     else
10554 #endif
10555     sublist = lookup_lol_item(list, desc);
10556     if(sublist && sublist->count)
10557       {
10558         item_size = list->info.subdesc_size + list->info.subdata_size;
10559         buffer = rsbac_vmalloc(item_size * sublist->count);
10560         if(buffer)
10561           {
10562             if(ttl_array_p)
10563               ttl_p = rsbac_vmalloc(sizeof(**ttl_array_p) * sublist->count);
10564             item_p = sublist->head;
10565             while(item_p)
10566               {
10567                 if(   !item_p->max_age
10568                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10569                   )
10570                   {
10571                     memcpy(buffer + offset,
10572                            ((char *) item_p) + sizeof(*item_p),
10573                            item_size);
10574                     if(ttl_p)
10575                       {
10576                         if(item_p->max_age)
10577                           ttl_p[result] = item_p->max_age - RSBAC_CURRENT_TIME;
10578                         else
10579                           ttl_p[result] = 0;
10580                       }
10581                     offset += item_size;
10582                     result++;
10583                   }
10584                 item_p = item_p->next;
10585               }
10586             *array_p = buffer;
10587             if(ttl_array_p)
10588               *ttl_array_p = ttl_p;
10589           }
10590         else
10591           {
10592             result = -RSBAC_ENOMEM;
10593           }
10594       }
10595     rsbac_read_unlock(&list->lock, &lock_flags);
10596     rsbac_read_unlock(&lol_reg_head.lock, &rlock_flags);
10597     return result;
10598   }
10599 
10600 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10601 EXPORT_SYMBOL(rsbac_list_lol_get_all_subitems_ttl);
10602 #endif
10603 long rsbac_list_lol_get_all_subitems_ttl(
10604   rsbac_list_handle_t handle,
10605   void * desc,
10606   void ** array_p,
10607   rsbac_time_t ** ttl_array_p)
10608   {
10609     return rsbac_ta_list_lol_get_all_subitems_ttl(0, handle, desc,
10610                                                   array_p, ttl_array_p);
10611   }
10612 
10613 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10614 EXPORT_SYMBOL(rsbac_list_lol_get_all_subitems);
10615 #endif
10616 long rsbac_list_lol_get_all_subitems(rsbac_list_handle_t handle, void * desc, void ** array_p)
10617   {
10618     return rsbac_ta_list_lol_get_all_subitems_ttl(0, handle, desc,
10619                                                   array_p, NULL);
10620   }
10621 
10622 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10623 EXPORT_SYMBOL(rsbac_ta_list_lol_get_all_items);
10624 #endif
10625 long rsbac_ta_list_lol_get_all_items(
10626   rsbac_list_ta_number_t ta_number,
10627   rsbac_list_handle_t handle,
10628   void ** array_p)
10629   {
10630     struct rsbac_list_lol_reg_item_t * list;
10631     struct rsbac_list_lol_item_t     * item_p;
10632            char                      * buffer;
10633     u_long lock_flags, rlock_flags;
10634     u_long offset = 0;
10635     long result = 0;
10636     u_int item_size;
10637 
10638     if(!handle)
10639       return -RSBAC_EINVALIDVALUE;
10640     if(!array_p)
10641       return -RSBAC_EINVALIDVALUE;
10642     if(!list_initialized)
10643       return -RSBAC_ENOTINITIALIZED;
10644 
10645     list = (struct rsbac_list_lol_reg_item_t *) handle;
10646     if(list->self != list)
10647       return -RSBAC_EINVALIDVALUE;
10648     *array_p = NULL;
10649 
10650 #ifdef CONFIG_RSBAC_LIST_TRANS
10651     if(ta_number)
10652       {
10653         if(!rsbac_ta_list_exist(0, ta_handle, &ta_number))
10654           return -RSBAC_EINVALIDTRANSACTION;
10655       }
10656 #endif
10657 
10658     rsbac_read_lock(&lol_reg_head.lock, &rlock_flags);
10659 /*
10660 #ifdef CONFIG_RSBAC_DEBUG
10661     if(rsbac_debug_lists)
10662       rsbac_printk(KERN_DEBUG "rsbac_list_lol_get_all_items: list %s.\n",
10663              list->name);
10664 #endif
10665 */
10666     rsbac_read_lock(&list->lock, &lock_flags);
10667 #ifdef CONFIG_RSBAC_LIST_TRANS
10668     if(ta_number && (list->ta_copied == ta_number))
10669       {
10670         if(list->ta_count)
10671           {
10672             item_size = list->info.desc_size + list->info.data_size;
10673             buffer = rsbac_vmalloc(item_size * list->ta_count);
10674             if(buffer)
10675               {
10676                 item_p = list->ta_head;
10677                 while(item_p)
10678                   {
10679                     if(   !item_p->max_age
10680                        || (item_p->max_age > RSBAC_CURRENT_TIME)
10681                       )
10682                       {
10683                         memcpy(buffer + offset,
10684                                ((char *) item_p) + sizeof(*item_p),
10685                                item_size);
10686                         offset += item_size;
10687                         result++;
10688                       }
10689                     item_p = item_p->next;
10690                   }
10691                 *array_p = buffer;
10692               }
10693             else
10694               {
10695                 result = -RSBAC_ENOMEM;
10696               }
10697           }
10698       }
10699     else
10700 #endif
10701     if(list->count)
10702       {
10703         item_size = list->info.desc_size + list->info.data_size;
10704         buffer = rsbac_vmalloc(item_size * list->count);
10705         if(buffer)
10706           {
10707             item_p = list->head;
10708             while(item_p)
10709               {
10710                 if(   !item_p->max_age
10711                    || (item_p->max_age > RSBAC_CURRENT_TIME)
10712                   )
10713                   {
10714                     memcpy(buffer + offset,
10715                            ((char *) item_p) + sizeof(*item_p),
10716                            item_size);
10717                     offset += item_size;
10718                     result++;
10719                   }
10720                 item_p = item_p->next;
10721               }
10722             *array_p = buffer;
10723           }
10724         else
10725           {
10726             result = -RSBAC_ENOMEM;
10727           }
10728       }
10729     rsbac_read_unlock(&list->lock, &lock_flags);
10730     rsbac_read_unlock(&reg_head.lock, &rlock_flags);
10731     return result;
10732   }
10733 
10734 #if defined(CONFIG_RSBAC_REG) || defined(CONFIG_RSBAC_REG_MAINT)
10735 EXPORT_SYMBOL(rsbac_list_lol_get_all_items);
10736 #endif
10737 long rsbac_list_lol_get_all_items(
10738   rsbac_list_handle_t handle,
10739   void ** array_p)
10740   {
10741     return rsbac_ta_list_lol_get_all_items(0, handle, array_p);
10742   }
10743 
10744 /* end of gen_lists.c */

Generated on Sun May 21 14:30:54 2006 for RSBAC by  doxygen 1.4.2