/linux-2.6.21.1-rsbac-1.3.4/rsbac/data_structures/gen_lists.c

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

Generated on Wed May 16 11:53:45 2007 for RSBAC by  doxygen 1.5.1