00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "dazuko_platform.h"
00036 #include "dazuko_core.h"
00037 #include "dazuko_version.h"
00038
00039
00040 #include "dazuko_call.h"
00041
00042
00043 const char *DAZUKO_VERSION_STAMP = "\nDazukoVersion=" DAZUKO_VERSION_MAJOR "." DAZUKO_VERSION_MINOR "." DAZUKO_VERSION_REVISION "." DAZUKO_VERSION_RELEASE "\n";
00044
00045
00046 const char *VERSION_STRING = DAZUKO_VERSION_MAJOR "." DAZUKO_VERSION_MINOR "." DAZUKO_VERSION_REVISION
00047 #ifdef DAZUKO_PRERELEASE
00048 "-pre" DAZUKO_VERSION_RELEASE
00049 #endif
00050 ;
00051
00052
00053 const char *VERSION_NUMBER = DAZUKO_VERSION_MAJOR "." DAZUKO_VERSION_MINOR "." DAZUKO_VERSION_REVISION "." DAZUKO_VERSION_RELEASE;
00054
00055 #define NUM_SLOT_LISTS 5
00056 #define NUM_SLOTS 25
00057 #define NUM_EVENTS 7
00058
00059 #define AMC_UNSET 255
00060
00061
00062 #define DAZUKO_FREE 0
00063 #define DAZUKO_READY 1
00064 #define DAZUKO_WAITING 2
00065 #define DAZUKO_WORKING 3
00066 #define DAZUKO_DONE 4
00067 #define DAZUKO_BROKEN 5
00068
00069 #define TRUSTED_APPLICATION_SUPPORT
00070
00071 struct path
00072 {
00073
00074
00075
00076 struct path *next;
00077 int len;
00078 char *path;
00079 };
00080
00081 struct daemon_id
00082 {
00083 int unique;
00084 struct xp_daemon_id *xp_id;
00085 };
00086
00087 #ifdef TRUSTED_APPLICATION_SUPPORT
00088 struct trusted_container
00089 {
00090 struct xp_daemon_id *xp_id;
00091 char *token;
00092 int token_length;
00093 int trust_children;
00094 struct trusted_container *next;
00095 };
00096 #endif
00097
00098 struct slot_list;
00099
00100 struct slot
00101 {
00102
00103
00104
00105
00106
00107 int id;
00108 struct daemon_id did;
00109 int write_mode;
00110 int state;
00111 int response;
00112 int event;
00113 int filenamelength;
00114 char *filename;
00115 struct event_properties event_p;
00116 struct file_properties file_p;
00117 struct xp_mutex mutex;
00118 struct slot_list *slot_list;
00119 struct xp_queue wait_daemon_waiting_until_this_slot_not_READY;
00120 struct xp_queue wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING;
00121 struct xp_queue wait_daemon_waiting_until_this_slot_not_DONE;
00122 };
00123
00124 struct slot_list
00125 {
00126 struct xp_atomic use_count;
00127 struct slot slots[NUM_SLOTS];
00128 struct path *incl_paths;
00129 struct path *excl_paths;
00130 char *reg_name;
00131 struct xp_rwlock lock_lists;
00132 char access_mask;
00133 #ifdef TRUSTED_APPLICATION_SUPPORT
00134 struct xp_rwlock lock_trusted_list;
00135 struct trusted_container *trusted_list;
00136 char set_trusted_list;
00137 #endif
00138 struct xp_queue wait_kernel_waiting_for_any_READY_slot_or_zero_use_count;
00139 };
00140
00141 struct slot_list_container
00142 {
00143 struct slot_list *slot_list;
00144 struct xp_mutex mutex;
00145 };
00146
00147 struct one_slot_state_not_condition_param
00148 {
00149 struct slot *slot;
00150 int state;
00151 };
00152
00153 struct two_slot_state_not_condition_param
00154 {
00155 struct slot *slot1;
00156 int state1;
00157 struct slot *slot2;
00158 int state2;
00159 };
00160
00161 struct get_ready_slot_condition_param
00162 {
00163 struct slot *slot;
00164 struct slot_list *slotlist;
00165 };
00166
00167 static int unique_count = 1;
00168 static struct slot_list_container slot_lists[NUM_SLOT_LISTS];
00169 static struct xp_atomic active;
00170 static struct xp_atomic groupcount;
00171 static struct xp_mutex mutex_unique_count;
00172 static unsigned char access_mask_cache[NUM_EVENTS][NUM_SLOT_LISTS];
00173 static struct xp_mutex mutex_amc;
00174
00175
00176 int dazuko_vsnprintf(char *str, size_t size, const char *format, va_list ap)
00177 {
00178 char *target;
00179 const char *end;
00180 int overflow = 0;
00181 char number_buffer[32];
00182 const char *s;
00183
00184 if (str == NULL || size < 1 || format == NULL)
00185 return -1;
00186
00187 target = str;
00188 end = (target + size) - 1;
00189
00190 #define DAZUKO_VSNPRINTF_PRINTSTRING \
00191 for ( ; *s ; s++) \
00192 { \
00193 if (target == end) \
00194 { \
00195 overflow = 1; \
00196 goto dazuko_vsnprintf_out; \
00197 } \
00198 *target = *s; \
00199 target++; \
00200 }
00201
00202 for ( ; *format ; format++)
00203 {
00204 if (target == end)
00205 {
00206 overflow = 1;
00207 goto dazuko_vsnprintf_out;
00208 }
00209
00210 if (*format == '%')
00211 {
00212 format++;
00213
00214 switch (*format)
00215 {
00216 case 's':
00217 s = va_arg(ap, char *);
00218 if (s == NULL)
00219 s = "(null)";
00220 DAZUKO_VSNPRINTF_PRINTSTRING
00221 break;
00222
00223 case 'd':
00224 sprintf(number_buffer, "%d", va_arg(ap, int));
00225 s = number_buffer;
00226 DAZUKO_VSNPRINTF_PRINTSTRING
00227 break;
00228
00229 case 'p':
00230 sprintf(number_buffer, "%p", va_arg(ap, void *));
00231 s = number_buffer;
00232 DAZUKO_VSNPRINTF_PRINTSTRING
00233 break;
00234
00235 case 'c':
00236 *target = va_arg(ap, int);
00237 target++;
00238 break;
00239
00240 case 'l':
00241 format++;
00242 if (*format != 'u')
00243 {
00244
00245 goto dazuko_vsnprintf_out;
00246 }
00247 sprintf(number_buffer, "%lu", va_arg(ap, unsigned long));
00248 s = number_buffer;
00249 DAZUKO_VSNPRINTF_PRINTSTRING
00250 break;
00251
00252 case '0':
00253 format++;
00254 if (*format != '2')
00255 {
00256
00257 goto dazuko_vsnprintf_out;
00258 }
00259 format++;
00260 if (*format != 'x')
00261 {
00262
00263 goto dazuko_vsnprintf_out;
00264 }
00265 sprintf(number_buffer, "%02x", va_arg(ap, int));
00266 s = number_buffer;
00267 DAZUKO_VSNPRINTF_PRINTSTRING
00268 break;
00269
00270 default:
00271
00272 goto dazuko_vsnprintf_out;
00273 }
00274 }
00275 else
00276 {
00277 *target = *format;
00278 target++;
00279 }
00280 }
00281
00282 dazuko_vsnprintf_out:
00283
00284 *target = 0;
00285
00286
00287
00288
00289
00290
00291 return ((target - str) + overflow);
00292 }
00293
00294 int dazuko_snprintf(char *str, size_t size, const char *format, ...)
00295 {
00296 va_list ap;
00297 int ret;
00298
00299 va_start(ap, format);
00300 ret = dazuko_vsnprintf(str, size, format, ap);
00301 va_end(ap);
00302
00303 return ret;
00304 }
00305
00306 inline void dazuko_bzero(void *p, int len)
00307 {
00308
00309
00310 char *ptr = (char *)p;
00311
00312 while (len--)
00313 *ptr++ = 0;
00314 }
00315
00316 static inline int dazuko_event2index(unsigned long event)
00317 {
00318 switch (event)
00319 {
00320 case DAZUKO_ON_OPEN:
00321 return 0;
00322 case DAZUKO_ON_CLOSE:
00323 return 1;
00324 case DAZUKO_ON_EXEC:
00325 return 2;
00326 case DAZUKO_ON_CLOSE_MODIFIED:
00327 return 3;
00328 case DAZUKO_ON_UNLINK:
00329 return 4;
00330 case DAZUKO_ON_RMDIR:
00331 return 5;
00332 case DAZUKO_TRUST_REQUEST:
00333 return 6;
00334 }
00335
00336 return -1;
00337 }
00338
00339 static inline unsigned long dazuko_index2event(int index)
00340 {
00341 switch (index)
00342 {
00343 case 0:
00344 return DAZUKO_ON_OPEN;
00345 case 1:
00346 return DAZUKO_ON_CLOSE;
00347 case 2:
00348 return DAZUKO_ON_EXEC;
00349 case 3:
00350 return DAZUKO_ON_CLOSE_MODIFIED;
00351 case 4:
00352 return DAZUKO_ON_UNLINK;
00353 case 5:
00354 return DAZUKO_ON_RMDIR;
00355 case 6:
00356 return DAZUKO_TRUST_REQUEST;
00357 }
00358
00359 return 0;
00360 }
00361
00362 static void dazuko_setup_amc_cache(void)
00363 {
00364 int i;
00365 int j;
00366 struct slot_list *sl;
00367 unsigned long event;
00368 int index;
00369
00370
00371 call_xp_down(&mutex_amc);
00372
00373 memset(&access_mask_cache, AMC_UNSET, sizeof(access_mask_cache));
00374
00375 for (i=0 ; i<NUM_EVENTS ; i++)
00376 {
00377 event = dazuko_index2event(i);
00378 if (event == 0)
00379 continue;
00380
00381 index = 0;
00382
00383 for (j=0 ; j<NUM_SLOT_LISTS ; j++)
00384 {
00385
00386 call_xp_down(&(slot_lists[j].mutex));
00387
00388 sl = slot_lists[j].slot_list;
00389
00390 call_xp_up(&(slot_lists[j].mutex));
00391
00392
00393 if (sl == NULL)
00394 continue;
00395
00396 switch (event)
00397 {
00398 case DAZUKO_ON_CLOSE:
00399
00400
00401
00402 if (((DAZUKO_ON_CLOSE | DAZUKO_ON_CLOSE_MODIFIED) & (sl->access_mask)) == 0)
00403 continue;
00404 break;
00405 default:
00406 if ((event & (sl->access_mask)) == 0)
00407 continue;
00408 break;
00409 }
00410
00411
00412
00413
00414 access_mask_cache[i][index] = j;
00415 index++;
00416 }
00417 }
00418
00419 call_xp_up(&mutex_amc);
00420
00421 }
00422
00423
00424 static inline int dazuko_get_new_unique(void)
00425 {
00426 int unique;
00427
00428
00429 call_xp_down(&mutex_unique_count);
00430
00431 unique = unique_count;
00432 unique_count++;
00433
00434 call_xp_up(&mutex_unique_count);
00435
00436
00437 return unique;
00438 }
00439
00440 static inline int dazuko_slot_state(struct slot *s)
00441 {
00442 int state;
00443
00444
00445 call_xp_down(&(s->mutex));
00446
00447 state = s->state;
00448
00449 call_xp_up(&(s->mutex));
00450
00451
00452 return state;
00453 }
00454
00455 static int one_slot_state_not_condition(void *param)
00456 {
00457 return (dazuko_slot_state(((struct one_slot_state_not_condition_param *)param)->slot)
00458 != ((struct one_slot_state_not_condition_param *)param)->state);
00459 }
00460
00461 static int two_slot_state_not_condition(void *param)
00462 {
00463 return (dazuko_slot_state(((struct two_slot_state_not_condition_param *)param)->slot1)
00464 != ((struct two_slot_state_not_condition_param *)param)->state1
00465 && dazuko_slot_state(((struct two_slot_state_not_condition_param *)param)->slot2)
00466 != ((struct two_slot_state_not_condition_param *)param)->state2);
00467 }
00468
00469 static inline int __dazuko_change_slot_state(struct slot *s, int from_state, int to_state)
00470 {
00471
00472
00473
00474
00475 if (to_state != from_state)
00476 {
00477
00478
00479 if (s->state != from_state || s->did.unique == 0)
00480 return 0;
00481 }
00482
00483 s->state = to_state;
00484
00485
00486
00487
00488 return 1;
00489 }
00490
00491 static int dazuko_change_slot_state(struct slot *s, int from_state, int to_state, int release)
00492 {
00493
00494
00495
00496
00497
00498
00499
00500 int success;
00501
00502
00503 call_xp_down(&(s->mutex));
00504
00505 success = __dazuko_change_slot_state(s, from_state, to_state);
00506
00507
00508
00509 if (!success || release)
00510 call_xp_up(&(s->mutex));
00511
00512
00513
00514 return success;
00515 }
00516
00517 static struct slot * _dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *sl)
00518 {
00519
00520
00521
00522
00523
00524
00525 int i;
00526 struct slot *s = NULL;
00527
00528 if (sl == NULL)
00529 {
00530 call_xp_print("dazuko: invalid slot_list given (bug!)\n");
00531 return NULL;
00532 }
00533
00534 for (i=0 ; i<NUM_SLOTS ; i++)
00535 {
00536 s = &(sl->slots[i]);
00537
00538 call_xp_down(&(s->mutex));
00539
00540 if (did == NULL)
00541 {
00542
00543 if (s->did.unique == 0 && s->did.xp_id == NULL)
00544 {
00545
00546
00547 if (release)
00548 call_xp_up(&(s->mutex));
00549
00550
00551
00552 return s;
00553 }
00554 }
00555 else if (s->did.unique == 0 && s->did.xp_id == NULL)
00556 {
00557
00558
00559
00560 }
00561
00562 else if (call_xp_id_compare(s->did.xp_id, did->xp_id, 0) == DAZUKO_SAME)
00563 {
00564
00565
00566 if (did->unique < 0 || (s->did.unique == did->unique))
00567 {
00568
00569
00570 if (release)
00571 call_xp_up(&(s->mutex));
00572
00573
00574
00575 return s;
00576 }
00577 }
00578
00579 call_xp_up(&(s->mutex));
00580
00581 }
00582
00583 return NULL;
00584 }
00585
00586 static struct slot * dazuko_find_slot_and_slotlist(struct daemon_id *did, int release, struct slot_list *slist, struct slot_list **sl_result)
00587 {
00588 struct slot *s;
00589 int i;
00590 struct slot_list *sl;
00591
00592 if (slist == NULL)
00593 {
00594 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
00595 {
00596
00597 call_xp_down(&(slot_lists[i].mutex));
00598
00599 sl = slot_lists[i].slot_list;
00600
00601 call_xp_up(&(slot_lists[i].mutex));
00602
00603
00604 if (sl != NULL)
00605 {
00606 s = _dazuko_find_slot(did, release, sl);
00607 if (s != NULL)
00608 {
00609
00610 if (sl_result != NULL)
00611 *sl_result = sl;
00612
00613 return s;
00614 }
00615 }
00616 }
00617 }
00618 else
00619 {
00620 return _dazuko_find_slot(did, release, slist);
00621 }
00622
00623 return NULL;
00624 }
00625
00626 static inline struct slot * dazuko_find_slot(struct daemon_id *did, int release, struct slot_list *slist)
00627 {
00628 return dazuko_find_slot_and_slotlist(did, release, slist, NULL);
00629 }
00630
00631 static int dazuko_insert_path_fs(struct path **list, struct xp_rwlock *lock_lists, char *fs_path, int fs_len)
00632 {
00633
00634
00635
00636
00637
00638
00639 struct path *newitem;
00640 struct path *tmp;
00641
00642 if (list == NULL || lock_lists == NULL || fs_path == NULL || fs_len < 1)
00643 return XP_ERROR_INVALID;
00644
00645
00646 if (!call_xp_is_absolute_path(fs_path))
00647 return XP_ERROR_INVALID;
00648
00649
00650 newitem = (struct path *)call_xp_malloc(sizeof(struct path));
00651 if (newitem == NULL)
00652 return XP_ERROR_FAULT;
00653
00654 newitem->path = (char *)call_xp_malloc(fs_len + 1);
00655 if (newitem->path == NULL)
00656 {
00657 call_xp_free(newitem);
00658 return XP_ERROR_FAULT;
00659 }
00660
00661
00662 memcpy(newitem->path, fs_path, fs_len);
00663
00664 newitem->path[fs_len] = 0;
00665
00666 while (newitem->path[fs_len-1] == 0)
00667 {
00668 fs_len--;
00669 if (fs_len == 0)
00670 break;
00671 }
00672
00673 if (fs_len < 1)
00674 {
00675 call_xp_free(newitem->path);
00676 call_xp_free(newitem);
00677 return XP_ERROR_INVALID;
00678 }
00679
00680 newitem->len = fs_len;
00681
00682
00683 for (tmp=*list ; tmp ; tmp=tmp->next)
00684 {
00685 if (newitem->len == tmp->len)
00686 {
00687 if (memcmp(newitem->path, tmp->path, tmp->len) == 0)
00688 {
00689
00690
00691 call_xp_free(newitem->path);
00692 call_xp_free(newitem);
00693
00694 return 0;
00695 }
00696 }
00697 }
00698
00699 DPRINT(("dazuko: adding path %s\n", newitem->path));
00700
00701
00702
00703 call_xp_write_lock(lock_lists);
00704 newitem->next = *list;
00705 *list = newitem;
00706 call_xp_write_unlock(lock_lists);
00707
00708
00709 return 0;
00710 }
00711
00712 static void dazuko_remove_all_paths(struct slot_list *slist)
00713 {
00714
00715
00716
00717 struct path *tmp;
00718
00719 if (slist == NULL)
00720 return;
00721
00722
00723 call_xp_write_lock(&(slist->lock_lists));
00724
00725
00726 while (slist->incl_paths)
00727 {
00728 tmp = slist->incl_paths;
00729 slist->incl_paths = slist->incl_paths->next;
00730
00731 DPRINT(("dazuko: removing incl %s\n", tmp->path));
00732
00733 if (tmp->path != NULL)
00734 call_xp_free(tmp->path);
00735 call_xp_free(tmp);
00736 }
00737
00738
00739 while (slist->excl_paths)
00740 {
00741 tmp = slist->excl_paths;
00742 slist->excl_paths = slist->excl_paths->next;
00743
00744 DPRINT(("dazuko: removing excl %s\n", tmp->path));
00745
00746 if (tmp->path != NULL)
00747 call_xp_free(tmp->path);
00748 call_xp_free(tmp);
00749 }
00750
00751 call_xp_write_unlock(&(slist->lock_lists));
00752
00753 }
00754
00755 static int _dazuko_unregister_daemon(struct daemon_id *did)
00756 {
00757
00758
00759
00760
00761 struct slot *s;
00762 struct slot_list *sl;
00763
00764 DPRINT(("dazuko: dazuko_unregister_daemon() [%d]\n", did->unique));
00765
00766
00767
00768
00769 s = dazuko_find_slot_and_slotlist(did, 0, NULL, &sl);
00770
00771 if (s == NULL)
00772 {
00773
00774 return 0;
00775 }
00776
00777
00778
00779
00780 s->did.unique = 0;
00781 call_xp_id_free(s->did.xp_id);
00782 s->did.xp_id = NULL;
00783
00784
00785 __dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE);
00786
00787 call_xp_up(&(s->mutex));
00788
00789
00790 call_xp_atomic_dec(&(sl->use_count));
00791
00792
00793
00794
00795 if (call_xp_atomic_read(&(sl->use_count)) == 0)
00796 {
00797 sl->access_mask = 0;
00798 dazuko_setup_amc_cache();
00799 dazuko_remove_all_paths(sl);
00800
00801
00802 call_xp_atomic_dec(&groupcount);
00803 }
00804
00805
00806
00807 if (call_xp_atomic_read(&active) > 0)
00808 {
00809
00810
00811
00812
00813 call_xp_atomic_dec(&active);
00814 }
00815 else
00816 {
00817 call_xp_print("dazuko: active count error (possible bug)\n");
00818 }
00819
00820
00821
00822
00823
00824 call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE));
00825 call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
00826 call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_READY));
00827
00828
00829 call_xp_notify(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
00830
00831 return 0;
00832 }
00833
00834 int dazuko_unregister_daemon(struct xp_daemon_id *xp_id)
00835 {
00836 struct daemon_id did;
00837 int ret;
00838
00839 if (xp_id == NULL)
00840 return 0;
00841
00842 did.unique = -1;
00843 did.xp_id = call_xp_id_copy(xp_id);
00844
00845 ret = _dazuko_unregister_daemon(&did);
00846
00847 call_xp_id_free(did.xp_id);
00848
00849 return ret;
00850 }
00851
00852 static inline struct slot_list* find_slot_list_from_groupname(const char *group_name)
00853 {
00854 int i;
00855 struct slot_list *sl;
00856 const char *p1;
00857 const char *p2;
00858
00859 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
00860 {
00861
00862 call_xp_down(&(slot_lists[i].mutex));
00863
00864 sl = slot_lists[i].slot_list;
00865
00866 call_xp_up(&(slot_lists[i].mutex));
00867
00868
00869 if (sl != NULL)
00870 {
00871 p1 = group_name;
00872 p2 = sl->reg_name;
00873
00874 while (*p1 == *p2)
00875 {
00876 if (*p1 == 0)
00877 break;
00878
00879 p1++;
00880 p2++;
00881 }
00882
00883 if (*p1 == *p2)
00884 return sl;
00885 }
00886 }
00887
00888 return NULL;
00889 }
00890
00891 static int dazuko_register_daemon(struct daemon_id *did, const char *reg_name, int string_length, int write_mode)
00892 {
00893 const char *p1;
00894 char *p2;
00895 struct slot *s;
00896 struct slot_list *sl;
00897 int i;
00898
00899 DPRINT(("dazuko: dazuko_register_daemon() [%d]\n", did->unique));
00900
00901 if (did == NULL || reg_name == NULL)
00902 return XP_ERROR_PERMISSION;
00903
00904 s = dazuko_find_slot(did, 1, NULL);
00905
00906 if (s != NULL)
00907 {
00908
00909
00910 call_xp_print("dazuko: daemon %d already assigned to slot[%d]\n", did->unique, s->id);
00911
00912 return XP_ERROR_PERMISSION;
00913 }
00914
00915
00916
00917 sl = find_slot_list_from_groupname(reg_name);
00918
00919 if (sl == NULL)
00920 {
00921
00922
00923
00924 sl = (struct slot_list *)call_xp_malloc(sizeof(struct slot_list));
00925 if (sl == NULL)
00926 return XP_ERROR_FAULT;
00927
00928 dazuko_bzero(sl, sizeof(struct slot_list));
00929
00930 sl->reg_name = call_xp_malloc(string_length + 1);
00931 if (sl->reg_name == NULL)
00932 {
00933 call_xp_free(sl);
00934 return XP_ERROR_FAULT;
00935 }
00936 dazuko_bzero(sl->reg_name, string_length + 1);
00937
00938 call_xp_atomic_set(&(sl->use_count), 0);
00939 call_xp_init_rwlock(&(sl->lock_lists));
00940 #ifdef TRUSTED_APPLICATION_SUPPORT
00941 call_xp_init_rwlock(&(sl->lock_trusted_list));
00942 #endif
00943 call_xp_init_queue(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
00944
00945 p1 = reg_name;
00946 p2 = sl->reg_name;
00947
00948 while (*p1)
00949 {
00950 *p2 = *p1;
00951
00952 p1++;
00953 p2++;
00954 }
00955 *p2 = 0;
00956
00957
00958 for (i=0 ; i<NUM_SLOTS ; i++)
00959 {
00960 sl->slots[i].id = i;
00961 sl->slots[i].slot_list = sl;
00962 call_xp_init_mutex(&(sl->slots[i].mutex));
00963 call_xp_init_queue(&(sl->slots[i].wait_daemon_waiting_until_this_slot_not_READY));
00964 call_xp_init_queue(&(sl->slots[i].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
00965 call_xp_init_queue(&(sl->slots[i].wait_daemon_waiting_until_this_slot_not_DONE));
00966 }
00967
00968
00969 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
00970 {
00971
00972 call_xp_down(&(slot_lists[i].mutex));
00973
00974 if (slot_lists[i].slot_list == NULL)
00975 {
00976 slot_lists[i].slot_list = sl;
00977
00978 call_xp_up(&(slot_lists[i].mutex));
00979
00980 break;
00981 }
00982
00983 call_xp_up(&(slot_lists[i].mutex));
00984
00985 }
00986
00987 if (i == NUM_SLOT_LISTS)
00988 {
00989
00990
00991 call_xp_free(sl->reg_name);
00992 call_xp_free(sl);
00993
00994 return XP_ERROR_BUSY;
00995 }
00996 }
00997
00998
00999
01000
01001 s = dazuko_find_slot(NULL, 0, sl);
01002
01003 if (s == NULL)
01004 return XP_ERROR_BUSY;
01005
01006
01007
01008
01009
01010
01011
01012
01013 call_xp_atomic_inc(&active);
01014
01015
01016 did->unique = dazuko_get_new_unique();
01017
01018 s->did.unique = did->unique;
01019 s->did.xp_id = call_xp_id_copy(did->xp_id);
01020 s->write_mode = write_mode;
01021
01022 call_xp_atomic_inc(&(sl->use_count));
01023
01024 if (call_xp_atomic_read(&(sl->use_count)) == 1)
01025 {
01026
01027 call_xp_atomic_inc(&groupcount);
01028 }
01029
01030
01031
01032 __dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE);
01033
01034 DPRINT(("dazuko: slot[%d] assigned to daemon %d\n", s->id, s->did.unique));
01035
01036 call_xp_up(&(s->mutex));
01037
01038
01039
01040
01041
01042 return 0;
01043 }
01044
01045 static struct slot* dazuko_get_an_access(struct daemon_id *did)
01046 {
01047
01048
01049
01050
01051
01052
01053
01054
01055 int i;
01056 struct slot *s;
01057 struct one_slot_state_not_condition_param cond_p;
01058
01059 tryagain:
01060
01061 s = dazuko_find_slot(did, 1, NULL);
01062
01063 if (s == NULL)
01064 {
01065 i = dazuko_register_daemon(did, "_COMPAT", 7, 1);
01066 if (i != 0)
01067 {
01068 call_xp_print("dazuko: unregistered daemon %d attempted to get access\n", did->unique);
01069 return NULL;
01070 }
01071
01072 s = dazuko_find_slot(did, 1, NULL);
01073 if (s == NULL)
01074 {
01075 call_xp_print("dazuko: unregistered daemon %d attempted to get access\n", did->unique);
01076 return NULL;
01077 }
01078
01079 call_xp_print("dazuko: warning: daemon %d is using a deprecated protocol\n", did->unique);
01080 }
01081
01082
01083
01084 if (!dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_READY, 1))
01085 {
01086
01087 dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_READY, 1);
01088
01089
01090 call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
01091 }
01092
01093
01094 call_xp_notify(&(s->slot_list->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
01095
01096 cond_p.slot = s;
01097 cond_p.state = DAZUKO_READY;
01098 if (call_xp_wait_until_condition(&(s->wait_daemon_waiting_until_this_slot_not_READY), one_slot_state_not_condition, &cond_p, 1) != 0)
01099 {
01100
01101
01102
01103
01104 DPRINT(("dazuko: daemon %d killed while waiting for work\n", did->unique));
01105
01106 if (dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_BROKEN, 1) || dazuko_change_slot_state(s, DAZUKO_WAITING, DAZUKO_BROKEN, 1))
01107 {
01108
01109 call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
01110 }
01111
01112 return NULL;
01113 }
01114
01115
01116
01117
01118
01119
01120
01121 if (!dazuko_change_slot_state(s, DAZUKO_WAITING, DAZUKO_WORKING, 0))
01122 {
01123
01124
01125 goto tryagain;
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135 return s;
01136 }
01137
01138 static int dazuko_initialize_cache(struct daemon_id *did, unsigned long ttl)
01139 {
01140
01141 if (dazuko_find_slot(did, 1, NULL) == NULL)
01142 {
01143
01144
01145 return -1;
01146 }
01147
01148 return call_xp_init_cache(ttl);
01149 }
01150
01151 static int dazuko_return_access(struct daemon_id *did, int response, struct slot *s)
01152 {
01153
01154
01155
01156
01157 struct one_slot_state_not_condition_param cond_p;
01158
01159 if (s == NULL)
01160 return -1;
01161
01162
01163
01164
01165
01166 if (!dazuko_change_slot_state(s, DAZUKO_WORKING, DAZUKO_DONE, 0))
01167 {
01168
01169
01170
01171
01172 DPRINT(("dazuko: response from daemon %d on slot[%d] not needed\n", did->unique, s->id));
01173
01174 return 0;
01175 }
01176
01177
01178
01179 s->response = response;
01180
01181 call_xp_up(&(s->mutex));
01182
01183
01184
01185 call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
01186
01187 cond_p.slot = s;
01188 cond_p.state = DAZUKO_DONE;
01189 if (call_xp_wait_until_condition(&(s->wait_daemon_waiting_until_this_slot_not_DONE), one_slot_state_not_condition, &cond_p, 1) != 0)
01190 {
01191
01192
01193
01194
01195 DPRINT(("dazuko: daemon %d killed while waiting for response acknowledgement\n", did->unique));
01196
01197 return XP_ERROR_INTERRUPT;
01198 }
01199
01200 return 0;
01201 }
01202
01203 static inline int dazuko_isdigit(const char c)
01204 {
01205 return (c >= '0' && c <= '9');
01206 }
01207
01208 static inline unsigned long dazuko_strtoul(const char *string)
01209 {
01210 unsigned long num = 1;
01211 const char *p = string;
01212
01213 if (string == NULL)
01214 return 0;
01215
01216 if (dazuko_isdigit(*p))
01217 {
01218 num *= *p - '0';
01219 p++;
01220 }
01221 else
01222 {
01223 return 0;
01224 }
01225
01226 while (dazuko_isdigit(*p))
01227 {
01228 num *= 10;
01229 num += *p - '0';
01230 p++;
01231 }
01232
01233 return num;
01234 }
01235
01236 static inline long dazuko_strtol(const char *string)
01237 {
01238 const char *p = string;
01239
01240 if (string == NULL)
01241 return 0;
01242
01243 switch (*p)
01244 {
01245 case '-':
01246 p++;
01247 return (-1 * ((long)(dazuko_strtoul(p))));
01248
01249 case '+':
01250 p++;
01251 break;
01252 }
01253
01254 return (long)dazuko_strtoul(p);
01255 }
01256
01257 static inline int dazuko_strlen(const char *string)
01258 {
01259 const char *p;
01260
01261 if (string == NULL)
01262 return -1;
01263
01264 for (p=string ; *p ; p++)
01265 continue;
01266
01267 return (p - string);
01268 }
01269
01270 static inline const char* dazuko_strchr(const char *haystack, char needle)
01271 {
01272 const char *p;
01273
01274 if (haystack == NULL)
01275 return NULL;
01276
01277 for (p=haystack ; *p ; p++)
01278 {
01279 if (*p == needle)
01280 return p;
01281 }
01282
01283 return NULL;
01284 }
01285
01286 static inline const char* dazuko_strstr(const char *haystack, const char *needle)
01287 {
01288 const char *p1;
01289 const char *p2;
01290 const char *p3;
01291
01292 if (haystack == NULL || needle == NULL)
01293 return NULL;
01294
01295 for (p1=haystack ; *p1 ; p1++)
01296 {
01297 for (p2=needle,p3=p1 ; *p2&&*p3 ; p2++,p3++)
01298 {
01299 if (*p2 != *p3)
01300 break;
01301 }
01302
01303 if (*p2 == 0)
01304 return p1;
01305 }
01306
01307 return NULL;
01308 }
01309
01310 int dazuko_get_value(const char *key, const char *string, char **value)
01311 {
01312 const char *p1;
01313 const char *p2;
01314 int size;
01315
01316 if (value == NULL)
01317 return -1;
01318
01319 *value = NULL;
01320
01321 if (key == NULL || string == NULL)
01322 return -1;
01323
01324 p1 = dazuko_strstr(string, key);
01325 if (p1 == NULL)
01326 return -1;
01327
01328 p1 += dazuko_strlen(key);
01329
01330 for (p2=p1 ; *p2 && *p2!='\n' ; p2++)
01331 continue;
01332
01333 size = (p2 - p1) + 1;
01334 *value = call_xp_malloc(size);
01335 if (*value == NULL)
01336 return -1;
01337
01338 memcpy(*value, p1, size - 1);
01339 (*value)[size - 1] = 0;
01340
01341 return 0;
01342 }
01343
01344 static inline void dazuko_clear_replybuffer(struct dazuko_request *request)
01345 {
01346 dazuko_bzero(request->reply_buffer, request->reply_buffer_size);
01347 request->reply_buffer_size_used = 0;
01348 }
01349
01350 static inline void dazuko_close_replybuffer(struct dazuko_request *request)
01351 {
01352 request->reply_buffer[request->reply_buffer_size_used] = 0;
01353 request->reply_buffer_size_used++;
01354 }
01355
01356 static void dazuko_add_keyvalue_to_replybuffer(struct dazuko_request *request, const char *key, void *value, char vtype)
01357 {
01358
01359 #define DAZUKO_VSNPRINT(type, name) dazuko_snprintf(request->reply_buffer + request->reply_buffer_size_used, (request->reply_buffer_size - request->reply_buffer_size_used) - 1, "%s%" #type , key, *((name *)value))
01360
01361 switch (vtype)
01362 {
01363 case 'd':
01364 DAZUKO_VSNPRINT(d, const int);
01365 break;
01366
01367 case 's':
01368 DAZUKO_VSNPRINT(s, const char *);
01369 break;
01370
01371 case 'l':
01372 DAZUKO_VSNPRINT(lu, const unsigned long);
01373 break;
01374
01375 default:
01376
01377 DAZUKO_VSNPRINT(c, const char);
01378 break;
01379 }
01380
01381
01382 request->reply_buffer_size_used += dazuko_strlen(request->reply_buffer + request->reply_buffer_size_used);
01383 }
01384
01385 static inline int dazuko_printable(char c)
01386 {
01387
01388
01389 return ((c >= ' ') && (c <= '~') && (c != '\\'));
01390 }
01391
01392 static inline void dazuko_add_esc_to_replybuffer(struct dazuko_request *request, const char *key, char **filename)
01393 {
01394 int found = 0;
01395 char *p_rq;
01396 const char *limit;
01397 const char *p_fn;
01398 unsigned char c;
01399
01400
01401 for (p_fn=*filename ; *p_fn ; p_fn++)
01402 {
01403 if (!dazuko_printable(*p_fn))
01404 {
01405 found = 1;
01406 break;
01407 }
01408 }
01409
01410 if (found)
01411 {
01412
01413
01414 p_rq = request->reply_buffer + request->reply_buffer_size_used;
01415 limit = request->reply_buffer + request->reply_buffer_size - 1;
01416
01417 dazuko_snprintf(p_rq, limit - p_rq, "%s", key);
01418 p_rq += dazuko_strlen(p_rq);
01419
01420 for (p_fn=*filename ; *p_fn && (p_rq<limit) ; p_fn++)
01421 {
01422 if (dazuko_printable(*p_fn))
01423 {
01424 *p_rq = *p_fn;
01425 p_rq++;
01426 }
01427 else
01428 {
01429 c = *p_fn & 0xFF;
01430 dazuko_snprintf(p_rq, limit - p_rq, "\\x%02x", c);
01431 p_rq += dazuko_strlen(p_rq);
01432 }
01433 }
01434
01435 request->reply_buffer_size_used += dazuko_strlen(request->reply_buffer + request->reply_buffer_size_used);
01436 }
01437 else
01438 {
01439
01440
01441 dazuko_add_keyvalue_to_replybuffer(request, key, filename, 's');
01442 }
01443 }
01444
01445 #ifdef TRUSTED_APPLICATION_SUPPORT
01446 static inline void dazuko_remove_all_trusted(struct slot_list *sl)
01447 {
01448 struct trusted_container *tc;
01449
01450 if (sl == NULL)
01451 return;
01452
01453
01454 call_xp_read_lock(&(sl->lock_trusted_list));
01455
01456 while (sl->trusted_list != NULL)
01457 {
01458 tc = sl->trusted_list;
01459 sl->trusted_list = sl->trusted_list->next;
01460 call_xp_id_free(tc->xp_id);
01461 call_xp_free(tc->token);
01462 call_xp_free(tc);
01463 }
01464
01465 call_xp_read_unlock(&(sl->lock_trusted_list));
01466
01467 }
01468
01469 static inline void dazuko_remove_trusted(struct slot_list *sl, char *token, int token_length)
01470 {
01471 struct trusted_container *cur = NULL;
01472 struct trusted_container *prev = NULL;
01473 struct trusted_container *temp = NULL;
01474
01475
01476 call_xp_read_lock(&(sl->lock_trusted_list));
01477
01478 cur = sl->trusted_list;
01479 while (cur != NULL)
01480 {
01481 if (token_length != cur->token_length)
01482 continue;
01483
01484 if (memcmp(token, cur->token, token_length) == 0)
01485 {
01486
01487
01488 temp = cur;
01489
01490 cur = cur->next;
01491
01492 if (prev == NULL)
01493 {
01494 sl->trusted_list = cur;
01495 }
01496 else
01497 {
01498 prev->next = cur;
01499 }
01500
01501 call_xp_id_free(temp->xp_id);
01502 call_xp_free(temp->token);
01503 call_xp_free(temp);
01504 }
01505 else
01506 {
01507 prev = cur;
01508 cur = cur->next;
01509 }
01510 }
01511
01512 call_xp_read_unlock(&(sl->lock_trusted_list));
01513
01514 }
01515 #endif
01516
01517 static int dazuko_set_option(struct daemon_id *did, int opt, void *param, int len)
01518 {
01519
01520
01521
01522 struct slot *s;
01523 struct slot_list *sl;
01524 int error = 0;
01525
01526
01527 if (len < 0 || len > 8192)
01528 return XP_ERROR_PERMISSION;
01529
01530
01531
01532
01533
01534 s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl);
01535
01536 switch (opt)
01537 {
01538 case REGISTER:
01539 call_xp_print("dazuko: dazuko_set_option does not support REGISTER (bug!)\n");
01540 return XP_ERROR_PERMISSION;
01541
01542 case UNREGISTER:
01543 if (s == NULL)
01544 {
01545
01546
01547 return 0;
01548 }
01549 break;
01550
01551 default:
01552 if (s == NULL)
01553 {
01554 error = dazuko_register_daemon(did, "_COMPAT", 7, 1);
01555 if (error)
01556 {
01557 call_xp_print("dazuko: unregistered daemon %d attempted access\n", did->unique);
01558 return XP_ERROR_PERMISSION;
01559 }
01560
01561 s = dazuko_find_slot_and_slotlist(did, 1, NULL, &sl);
01562 if (s == NULL)
01563 {
01564 call_xp_print("dazuko: unregistered daemon %d attempted access\n", did->unique);
01565 return XP_ERROR_PERMISSION;
01566 }
01567
01568 call_xp_print("dazuko: warning: daemon %d is using a deprecated protocol (opt=%d)\n", did->unique, opt);
01569 }
01570 break;
01571 }
01572
01573
01574 switch (opt)
01575 {
01576 case UNREGISTER:
01577 error = _dazuko_unregister_daemon(did);
01578 break;
01579
01580 case SET_ACCESS_MASK:
01581 sl->access_mask = (char)dazuko_strtoul((char *)param);
01582
01583
01584 dazuko_setup_amc_cache();
01585 break;
01586
01587 case ADD_INCLUDE_PATH:
01588 error = dazuko_insert_path_fs(&(sl->incl_paths), &(sl->lock_lists), (char *)param, len);
01589 break;
01590
01591 case ADD_EXCLUDE_PATH:
01592 error = dazuko_insert_path_fs(&(sl->excl_paths), &(sl->lock_lists), (char *)param, len);
01593 break;
01594
01595 case REMOVE_ALL_PATHS:
01596 dazuko_remove_all_paths(sl);
01597 break;
01598
01599 #ifdef TRUSTED_APPLICATION_SUPPORT
01600 case REMOVE_ALL_TRUSTED:
01601 dazuko_remove_all_trusted(sl);
01602 break;
01603
01604 case REMOVE_TRUSTED:
01605 dazuko_remove_trusted(sl, (char *)param, len);
01606 break;
01607 #endif
01608
01609 default:
01610 error = XP_ERROR_INVALID;
01611 break;
01612 }
01613
01614 return error;
01615 }
01616
01617 static struct slot * dazuko_get_and_hold_ready_slot(struct slot_list *sl)
01618 {
01619
01620
01621
01622
01623
01624
01625
01626
01627 int i;
01628 struct slot *s;
01629
01630 for (i=0 ; i<NUM_SLOTS ; i++)
01631 {
01632 s = &(sl->slots[i]);
01633
01634 if (dazuko_change_slot_state(s, DAZUKO_READY, DAZUKO_WAITING, 0))
01635 {
01636
01637 return s;
01638 }
01639 }
01640
01641
01642
01643 return NULL;
01644 }
01645
01646 static int get_ready_slot_condition(void *param)
01647 {
01648 return ((((struct get_ready_slot_condition_param *)param)->slot = dazuko_get_and_hold_ready_slot(((struct get_ready_slot_condition_param *)param)->slotlist)) != NULL
01649 || call_xp_atomic_read(&(((struct get_ready_slot_condition_param *)param)->slotlist->use_count)) == 0);
01650 }
01651
01652 static int dazuko_run_daemon_on_slotlist(unsigned long event, char *filename, int filenamelength, struct event_properties *event_p, struct file_properties *file_p, int prev_response, struct slot_list *sl)
01653 {
01654
01655
01656
01657 int rc;
01658 int unique;
01659 struct slot *s;
01660 struct get_ready_slot_condition_param cond_p1;
01661 struct two_slot_state_not_condition_param cond_p2;
01662
01663 begin:
01664
01665
01666
01667
01668 s = NULL;
01669
01670
01671 cond_p1.slotlist = sl;
01672 cond_p1.slot = s;
01673 if (call_xp_wait_until_condition(&(sl->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count), get_ready_slot_condition, &cond_p1, 0) != 0)
01674 {
01675
01676
01677
01678
01679 DPRINT(("dazuko: kernel process %d killed while waiting for free slot\n", event_p != NULL ? event_p->pid : 0));
01680
01681 return -1;
01682 }
01683
01684
01685
01686
01687
01688 s = cond_p1.slot;
01689
01690 if (s == NULL)
01691 {
01692
01693
01694
01695
01696 return 0;
01697 }
01698
01699
01700
01701
01702
01703
01704 unique = s->did.unique;
01705
01706
01707
01708
01709
01710
01711 s->filename = filename;
01712 s->event = event;
01713 s->response = prev_response;
01714 s->filenamelength = filenamelength;
01715
01716 if (event_p == NULL)
01717 dazuko_bzero(&(s->event_p), sizeof(struct event_properties));
01718 else
01719 memcpy(&(s->event_p), event_p, sizeof(struct event_properties));
01720
01721 if (file_p == NULL)
01722 dazuko_bzero(&(s->file_p), sizeof(struct file_properties));
01723 else
01724 memcpy(&(s->file_p), file_p, sizeof(struct file_properties));
01725
01726
01727 call_xp_up(&(s->mutex));
01728
01729
01730
01731 call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_READY));
01732
01733
01734 cond_p2.slot1 = s;
01735 cond_p2.state1 = DAZUKO_WAITING;
01736 cond_p2.slot2 = s;
01737 cond_p2.state2 = DAZUKO_WORKING;
01738 if (call_xp_wait_until_condition(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING), two_slot_state_not_condition, &cond_p2, 0) != 0)
01739 {
01740
01741
01742
01743
01744 DPRINT(("dazuko: kernel process %d killed while waiting for daemon response\n", event_p->pid));
01745
01746
01747
01748
01749 dazuko_change_slot_state(s, DAZUKO_FREE, DAZUKO_FREE, 1);
01750
01751
01752 call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE));
01753
01754 return -1;
01755 }
01756
01757
01758
01759
01760 call_xp_down(&(s->mutex));
01761
01762
01763 if (s->did.unique != unique)
01764 {
01765
01766
01767
01768 call_xp_up(&(s->mutex));
01769
01770 goto begin;
01771 }
01772
01773
01774 if (!__dazuko_change_slot_state(s, DAZUKO_DONE, DAZUKO_FREE))
01775 {
01776
01777
01778
01779 call_xp_up(&(s->mutex));
01780
01781 goto begin;
01782 }
01783
01784
01785 rc = s->response;
01786
01787 call_xp_up(&(s->mutex));
01788
01789
01790
01791 call_xp_notify(&(s->wait_daemon_waiting_until_this_slot_not_DONE));
01792
01793
01794
01795 return rc;
01796 }
01797
01798 static int dazuko_is_selected(struct dazuko_file_struct *kfs, struct slot_list *slist)
01799 {
01800
01801
01802
01803
01804 struct dazuko_file_listnode *cur;
01805 struct path *path;
01806 int selected = 0;
01807 int use_aliases = 1;
01808
01809 if (kfs == NULL || slist == NULL)
01810 return 0;
01811
01812
01813 call_xp_read_lock(&(slist->lock_lists));
01814
01815 if (kfs->aliases == NULL && kfs->filename != NULL)
01816 {
01817
01818
01819 use_aliases = 0;
01820
01821 kfs->aliases = (struct dazuko_file_listnode *)xp_malloc(sizeof(struct dazuko_file_listnode));
01822 if (kfs->aliases == NULL)
01823 {
01824 call_xp_print("dazuko: warning: access not controlled (%s)\n", kfs->filename);
01825 return 0;
01826 }
01827
01828 dazuko_bzero(kfs->aliases, sizeof(struct dazuko_file_listnode));
01829
01830 kfs->aliases->filename = kfs->filename;
01831 kfs->aliases->filename_length = kfs->filename_length;
01832 }
01833
01834 for (cur=kfs->aliases ; cur ; cur=cur->next)
01835 {
01836 if (cur->filename != NULL && cur->filename_length > 0)
01837 {
01838
01839 for (path=slist->incl_paths ; path ; path=path->next)
01840 {
01841
01842 if (path->len <= cur->filename_length)
01843 {
01844
01845 if (memcmp(path->path, cur->filename, path->len) == 0)
01846 {
01847 kfs->filename = cur->filename;
01848 kfs->filename_length = cur->filename_length;
01849
01850 selected = 1;
01851 break;
01852 }
01853 }
01854 }
01855
01856
01857
01858
01859 if (!selected)
01860 {
01861 continue;
01862 }
01863
01864
01865 for (path=slist->excl_paths ; path ; path=path->next)
01866 {
01867
01868 if (path->len <= cur->filename_length)
01869 {
01870
01871 if (memcmp(path->path, cur->filename, path->len) == 0)
01872 {
01873 kfs->filename = NULL;
01874 kfs->filename_length = 0;
01875
01876 selected = 0;
01877 break;
01878 }
01879 }
01880 }
01881
01882
01883 if (selected)
01884 break;
01885 }
01886 }
01887
01888 call_xp_read_unlock(&(slist->lock_lists));
01889
01890
01891 if (!use_aliases)
01892 {
01893 call_xp_free(kfs->aliases);
01894 kfs->aliases = NULL;
01895 }
01896
01897 return selected;
01898 }
01899
01900 static inline int dazuko_should_scan(struct dazuko_file_struct *kfs, struct slot_list *slist)
01901 {
01902
01903
01904
01905
01906
01907 int result = 0;
01908
01909
01910 if (call_xp_fill_file_struct(kfs) == 0)
01911 {
01912 if (dazuko_is_selected(kfs, slist))
01913 result = 1;
01914 }
01915
01916 return result;
01917 }
01918
01919 static inline int dazuko_run_daemon(unsigned long event, struct dazuko_file_struct *dfs, struct event_properties *event_p, struct slot_list *skip_slotlist)
01920 {
01921 struct slot_list *sl;
01922 int i;
01923 int index;
01924 int j;
01925 int rc = 0;
01926 int error;
01927
01928 i = dazuko_event2index(event);
01929 if (i < 0 || i >= NUM_EVENTS)
01930 {
01931 call_xp_print("dazuko: unknown event:%d, allowing access (possible bug)\n", event);
01932 return 0;
01933 }
01934
01935 for (index=0 ; index<NUM_SLOT_LISTS ; index++)
01936 {
01937
01938 call_xp_down(&mutex_amc);
01939
01940 j = access_mask_cache[i][index];
01941
01942 call_xp_up(&mutex_amc);
01943
01944
01945 if (j == AMC_UNSET)
01946 break;
01947
01948 if (j < 0 || j >= NUM_SLOT_LISTS)
01949 {
01950 call_xp_print("dazuko: illegal value:%d in access_mask_cache (possible bug)\n", j);
01951 break;
01952 }
01953
01954
01955 call_xp_down(&(slot_lists[j].mutex));
01956
01957 sl = slot_lists[j].slot_list;
01958
01959 call_xp_up(&(slot_lists[j].mutex));
01960
01961
01962 if (sl == NULL)
01963 continue;
01964
01965 if (sl == skip_slotlist)
01966 continue;
01967
01968 if (!dazuko_should_scan(dfs, sl)) {
01969 return 2;
01970 }
01971
01972 error = dazuko_run_daemon_on_slotlist(event, dfs->filename, dfs->filename_length, event_p, &(dfs->file_p), rc, sl);
01973
01974 if (error < 0)
01975 {
01976
01977 rc = error;
01978 break;
01979 }
01980 else if (error > 0)
01981 {
01982
01983 rc = 1;
01984 }
01985 }
01986
01987 return rc;
01988 }
01989
01990 inline int dazuko_get_filename_length(const char *filename)
01991 {
01992 int len;
01993
01994 for (len=0 ; filename[len] ; len++);
01995
01996 return len;
01997 }
01998
01999 static inline char* dazuko_strdup(const char *string, int *newlength)
02000 {
02001 int length;
02002 char *newstring;
02003
02004 if (string == NULL)
02005 return NULL;
02006
02007 length = dazuko_get_filename_length(string);
02008
02009 newstring = (char *)call_xp_malloc(length + 1);
02010
02011 if (newstring == NULL)
02012 return NULL;
02013
02014 memcpy(newstring, string, length);
02015 newstring[length] = 0;
02016
02017 if (newlength != NULL)
02018 *newlength = length;
02019
02020 return newstring;
02021 }
02022
02023 #ifdef TRUSTED_APPLICATION_SUPPORT
02024 static inline int dazuko_add_trusted_daemon(struct xp_daemon_id *xp_id, const char *token, int trust_children, struct slot_list *sl)
02025 {
02026 int error = 0;
02027 struct trusted_container *tc;
02028 char *temp;
02029
02030
02031 call_xp_read_lock(&(sl->lock_trusted_list));
02032
02033 tc = sl->trusted_list;
02034 while (tc != NULL)
02035 {
02036 if (call_xp_id_compare(tc->xp_id, xp_id, 0) == DAZUKO_SAME)
02037 {
02038
02039
02040
02041 temp = dazuko_strdup(token, &(tc->token_length));
02042
02043 if (temp != NULL)
02044 {
02045
02046
02047
02048 call_xp_free(tc->token);
02049 tc->token = temp;
02050 }
02051
02052 tc->trust_children = trust_children;
02053
02054 break;
02055 }
02056 tc = tc->next;
02057 }
02058
02059 if (tc == NULL)
02060 {
02061
02062
02063 tc = (struct trusted_container *)call_xp_malloc(sizeof(struct trusted_container));
02064 if (tc == NULL)
02065 {
02066 error = -1;
02067 }
02068 else
02069 {
02070 tc->token = dazuko_strdup(token, &(tc->token_length));
02071
02072 if (tc->token == NULL)
02073 {
02074 error = -1;
02075 call_xp_free(tc);
02076 }
02077 else
02078 {
02079 tc->xp_id = call_xp_id_copy(xp_id);
02080 tc->next = sl->trusted_list;
02081 tc->trust_children = trust_children;
02082 sl->trusted_list = tc;
02083
02084
02085 if (!(sl->set_trusted_list))
02086 sl->set_trusted_list = 1;
02087 }
02088 }
02089 }
02090
02091 call_xp_read_unlock(&(sl->lock_trusted_list));
02092
02093
02094 return error;
02095 }
02096
02097 static inline int dazuko_register_trusted_daemon(struct xp_daemon_id *xp_id, const char *group_name, char *token, char *trust_flags)
02098 {
02099 struct event_properties event_p;
02100 struct slot_list *sl;
02101 int rc;
02102 int trust_children = 0;
02103
02104 if (xp_id == NULL || group_name == NULL || token == NULL)
02105 return -1;
02106
02107 sl = find_slot_list_from_groupname(group_name);
02108
02109 if (sl == NULL)
02110 return -1;
02111
02112
02113 if ((DAZUKO_TRUST_REQUEST & sl->access_mask) == 0)
02114 return -1;
02115
02116 memset(&event_p, 0, sizeof(event_p));
02117
02118
02119 call_xp_set_event_properties(&event_p, xp_id);
02120
02121 if (trust_flags != NULL)
02122 {
02123 if (dazuko_strchr(trust_flags, 'C') != NULL)
02124 {
02125 event_p.flags = DAZUKO_TRUST_CHILDREN;
02126 trust_children = 1;
02127 }
02128 }
02129
02130
02131
02132
02133 rc = dazuko_run_daemon_on_slotlist(DAZUKO_TRUST_REQUEST, token, dazuko_strlen(token), &event_p, NULL, 1, sl);
02134
02135 if (rc == 0)
02136 {
02137
02138
02139 rc = dazuko_add_trusted_daemon(xp_id, token, trust_children, sl);
02140 }
02141
02142 return rc;
02143 }
02144
02145 static inline struct trusted_container * _remove_trusted_node(struct trusted_container *prev, struct trusted_container *cur, struct slot_list *sl)
02146 {
02147 struct trusted_container *next;
02148
02149 if (cur == NULL || sl == NULL)
02150 return NULL;
02151
02152 next = cur->next;
02153
02154 if (prev != NULL)
02155 prev->next = next;
02156 else
02157 sl->trusted_list = next;
02158
02159
02160 call_xp_id_free(cur->xp_id);
02161 call_xp_free(cur);
02162
02163 return next;
02164 }
02165
02166 static inline int dazuko_unregister_trusted_daemon(struct xp_daemon_id *xp_id)
02167 {
02168 struct trusted_container *prev;
02169 struct trusted_container *cur;
02170 int error = -1;
02171 int i;
02172 struct slot_list *sl;
02173
02174 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
02175 {
02176
02177 call_xp_down(&(slot_lists[i].mutex));
02178
02179 sl = slot_lists[i].slot_list;
02180
02181 call_xp_up(&(slot_lists[i].mutex));
02182
02183
02184 if (sl == NULL)
02185 continue;
02186
02187
02188
02189
02190 if (!(sl->set_trusted_list))
02191 continue;
02192
02193
02194 call_xp_read_lock(&(sl->lock_trusted_list));
02195
02196 prev = NULL;
02197 cur = sl->trusted_list;
02198 while (cur != NULL)
02199 {
02200 if (call_xp_id_compare(cur->xp_id, xp_id, 0) == DAZUKO_SAME)
02201 {
02202 _remove_trusted_node(prev, cur, sl);
02203
02204
02205 error = 0;
02206
02207 break;
02208 }
02209 prev = cur;
02210 cur = cur->next;
02211 }
02212
02213
02214 if (sl->trusted_list == NULL)
02215 sl->set_trusted_list = 0;
02216
02217 call_xp_read_unlock(&(sl->lock_trusted_list));
02218
02219 }
02220
02221 return error;
02222 }
02223 #endif
02224
02225 static int dazuko_handle_request_register(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02226 {
02227 char *value1;
02228 char *value2;
02229 int error = 0;
02230 struct daemon_id did;
02231
02232
02233
02234
02235 if (request->buffer_size <= 0)
02236 return -1;
02237
02238 if (request->reply_buffer_size <= 0)
02239 return -1;
02240
02241 if (dazuko_get_value("\nGN=", request->buffer, &value1) != 0)
02242 return -1;
02243
02244 if (dazuko_get_value("\nRM=", request->buffer, &value2) != 0)
02245 {
02246 call_xp_free(value1);
02247 return -1;
02248 }
02249
02250 did.xp_id = call_xp_id_copy(xp_id);
02251 did.unique = 0;
02252
02253 error = dazuko_register_daemon(&did, value1, dazuko_strlen(value1), dazuko_strchr(value2, 'W') != NULL);
02254
02255 dazuko_clear_replybuffer(request);
02256 dazuko_add_keyvalue_to_replybuffer(request, "\nID=", &(did.unique), 'd');
02257 dazuko_add_keyvalue_to_replybuffer(request, "\nVN=", &VERSION_NUMBER, 's');
02258 dazuko_add_keyvalue_to_replybuffer(request, "\nVS=", &VERSION_STRING, 's');
02259 dazuko_close_replybuffer(request);
02260
02261 call_xp_free(value1);
02262 call_xp_free(value2);
02263 call_xp_id_free(did.xp_id);
02264
02265 return error;
02266 }
02267
02268 static int dazuko_handle_request_basic(struct dazuko_request *request, struct xp_daemon_id *xp_id, int basic_option)
02269 {
02270 char *value1;
02271 int error = 0;
02272 struct daemon_id did;
02273
02274
02275
02276 if (request->buffer_size <= 0)
02277 return -1;
02278
02279 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02280 return -1;
02281
02282 did.xp_id = call_xp_id_copy(xp_id);
02283 did.unique = dazuko_strtol(value1);
02284
02285 error = dazuko_set_option(&did, basic_option, NULL, 0);
02286
02287 call_xp_free(value1);
02288 call_xp_id_free(did.xp_id);
02289
02290 return error;
02291 }
02292
02293 static int dazuko_handle_request_set_access_mask(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02294 {
02295 char *value1;
02296 char *value2;
02297 int error = 0;
02298 struct daemon_id did;
02299
02300
02301
02302 if (request->buffer_size <= 0)
02303 return -1;
02304
02305 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02306 return -1;
02307
02308 if (dazuko_get_value("\nAM=", request->buffer, &value2) != 0)
02309 {
02310 call_xp_free(value1);
02311 return -1;
02312 }
02313
02314 did.xp_id = call_xp_id_copy(xp_id);
02315 did.unique = dazuko_strtol(value1);
02316
02317 error = dazuko_set_option(&did, SET_ACCESS_MASK, value2, dazuko_strlen(value2));
02318
02319 call_xp_free(value1);
02320 call_xp_free(value2);
02321
02322 return error;
02323 }
02324
02325 static int dazuko_handle_request_add_path(struct dazuko_request *request, struct xp_daemon_id *xp_id, int add_path_option)
02326 {
02327 char *value1;
02328 char *value2;
02329 int error = 0;
02330 struct daemon_id did;
02331
02332
02333
02334 if (request->buffer_size <= 0)
02335 return -1;
02336
02337 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02338 return -1;
02339
02340 if (dazuko_get_value("\nPT=", request->buffer, &value2) != 0)
02341 {
02342 call_xp_free(value1);
02343 return -1;
02344 }
02345
02346 did.xp_id = call_xp_id_copy(xp_id);
02347 did.unique = dazuko_strtol(value1);
02348
02349 error = dazuko_set_option(&did, add_path_option, value2, dazuko_strlen(value2));
02350
02351 call_xp_free(value1);
02352 call_xp_free(value2);
02353 call_xp_id_free(did.xp_id);
02354
02355 return error;
02356 }
02357
02358 static inline int handle_event_as_readonly(struct slot *s)
02359 {
02360
02361 if (!(s->write_mode))
02362 return 1;
02363
02364
02365
02366
02367 if (s->event == DAZUKO_ON_CLOSE || s->event == DAZUKO_ON_CLOSE_MODIFIED)
02368 return 1;
02369
02370 return 0;
02371 }
02372
02373 static int dazuko_handle_request_get_an_access(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02374 {
02375 char *value1;
02376 int error = 0;
02377 struct slot *s;
02378 struct daemon_id did;
02379
02380
02381
02382
02383 if (request->buffer_size <= 0)
02384 return -1;
02385
02386 if (request->reply_buffer_size <= 0)
02387 return -1;
02388
02389 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02390 return -1;
02391
02392 did.xp_id = call_xp_id_copy(xp_id);
02393 did.unique = dazuko_strtol(value1);
02394
02395 call_xp_free(value1);
02396
02397
02398 s = dazuko_get_an_access(&did);
02399
02400 if (s == NULL)
02401 {
02402 call_xp_id_free(did.xp_id);
02403 return XP_ERROR_INTERRUPT;
02404 }
02405
02406
02407
02408
02409
02410 dazuko_clear_replybuffer(request);
02411 dazuko_add_keyvalue_to_replybuffer(request, "\nEV=", &(s->event), 'd');
02412 dazuko_add_esc_to_replybuffer(request, "\nFN=", &(s->filename));
02413
02414 if (s->event_p.set_uid)
02415 dazuko_add_keyvalue_to_replybuffer(request, "\nUI=", &(s->event_p.uid), 'd');
02416
02417 if (s->event_p.set_pid)
02418 dazuko_add_keyvalue_to_replybuffer(request, "\nPI=", &(s->event_p.pid), 'd');
02419
02420 if (s->event_p.set_flags)
02421 dazuko_add_keyvalue_to_replybuffer(request, "\nFL=", &(s->event_p.flags), 'd');
02422
02423 if (s->event_p.set_mode)
02424 dazuko_add_keyvalue_to_replybuffer(request, "\nMD=", &(s->event_p.mode), 'd');
02425
02426 if (s->file_p.set_size)
02427 dazuko_add_keyvalue_to_replybuffer(request, "\nFS=", &(s->file_p.size), 'l');
02428
02429 if (s->file_p.set_uid)
02430 dazuko_add_keyvalue_to_replybuffer(request, "\nFU=", &(s->file_p.uid), 'd');
02431
02432 if (s->file_p.set_gid)
02433 dazuko_add_keyvalue_to_replybuffer(request, "\nFG=", &(s->file_p.gid), 'd');
02434
02435 if (s->file_p.set_mode)
02436 dazuko_add_keyvalue_to_replybuffer(request, "\nFM=", &(s->file_p.mode), 'd');
02437
02438 if (s->file_p.set_device_type)
02439 dazuko_add_keyvalue_to_replybuffer(request, "\nDT=", &(s->file_p.device_type), 'd');
02440
02441 dazuko_close_replybuffer(request);
02442
02443
02444
02445 if (handle_event_as_readonly(s))
02446 {
02447
02448
02449
02450 call_xp_up(&(s->mutex));
02451
02452
02453 dazuko_return_access(&did, 0, s);
02454 }
02455 else
02456 {
02457 call_xp_up(&(s->mutex));
02458
02459 }
02460
02461 call_xp_id_free(did.xp_id);
02462
02463 return error;
02464 }
02465
02466 static int dazuko_handle_request_return_an_access(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02467 {
02468 char *value1;
02469 char *value2;
02470 int error = 0;
02471 struct daemon_id did;
02472 struct slot *s;
02473
02474
02475
02476 if (request->buffer_size <= 0)
02477 return -1;
02478
02479 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02480 return -1;
02481
02482 if (dazuko_get_value("\nDN=", request->buffer, &value2) != 0)
02483 {
02484 call_xp_free(value1);
02485 return -1;
02486 }
02487
02488 did.xp_id = call_xp_id_copy(xp_id);
02489 did.unique = dazuko_strtol(value1);
02490
02491
02492 s = dazuko_find_slot(&did, 1, NULL);
02493
02494 if (s == NULL)
02495 {
02496
02497
02498
02499 DPRINT(("dazuko: daemon %d unexpectedly lost slot (by return access)\n", did.unique));
02500
02501 return -1;
02502 }
02503
02504 if (!handle_event_as_readonly(s))
02505 error = dazuko_return_access(&did, dazuko_strtoul(value2), s);
02506
02507 call_xp_free(value1);
02508 call_xp_free(value2);
02509 call_xp_id_free(did.xp_id);
02510
02511 return error;
02512 }
02513
02514 static int dazuko_handle_request_initialize_cache(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02515 {
02516 char *value1;
02517 char *value2;
02518 int error = 0;
02519 int i;
02520 struct daemon_id did;
02521
02522
02523
02524 if (request->buffer_size <= 0)
02525 return -1;
02526
02527 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02528 return -1;
02529
02530 if (dazuko_get_value("\nCT=", request->buffer, &value2) != 0)
02531 {
02532 call_xp_free(value1);
02533 return -1;
02534 }
02535
02536 did.xp_id = call_xp_id_copy(xp_id);
02537 did.unique = dazuko_strtol(value1);
02538
02539 error = dazuko_initialize_cache(&did, dazuko_strtoul(value2));
02540
02541 call_xp_free(value1);
02542 call_xp_free(value2);
02543
02544 if (error)
02545 i = 0;
02546 else
02547 i = 1;
02548
02549 dazuko_clear_replybuffer(request);
02550 dazuko_add_keyvalue_to_replybuffer(request, "\nCA=", &i, 'd');
02551 dazuko_close_replybuffer(request);
02552
02553 call_xp_id_free(did.xp_id);
02554
02555
02556
02557 return 0;
02558 }
02559
02560 #ifdef TRUSTED_APPLICATION_SUPPORT
02561 static int dazuko_handle_request_register_trusted(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02562 {
02563 char *value1;
02564 char *value2;
02565 char *value3 = NULL;
02566 int error = 0;
02567 int i;
02568
02569
02570
02571
02572 if (request->buffer_size <= 0)
02573 return -1;
02574
02575 if (request->reply_buffer_size <= 0)
02576 return -1;
02577
02578 if (dazuko_get_value("\nGN=", request->buffer, &value1) != 0)
02579 return -1;
02580
02581 if (dazuko_get_value("\nTT=", request->buffer, &value2) != 0)
02582 {
02583 call_xp_free(value1);
02584 return -1;
02585 }
02586
02587 dazuko_get_value("\nTF=", request->buffer, &value3);
02588
02589 error = dazuko_register_trusted_daemon(xp_id, value1, value2, value3);
02590
02591 if (error)
02592 i = 1;
02593 else
02594 i = 0;
02595
02596 dazuko_clear_replybuffer(request);
02597 dazuko_add_keyvalue_to_replybuffer(request, "\nDN=", &i, 'd');
02598 dazuko_close_replybuffer(request);
02599
02600 call_xp_free(value1);
02601 call_xp_free(value2);
02602 if (value3 != NULL)
02603 call_xp_free(value3);
02604
02605
02606
02607 return 0;
02608 }
02609
02610 static int dazuko_handle_request_remove_trusted(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02611 {
02612 char *value1;
02613 char *value2;
02614 int error = 0;
02615 struct daemon_id did;
02616
02617
02618
02619 if (request->buffer_size <= 0)
02620 return -1;
02621
02622 if (dazuko_get_value("\nID=", request->buffer, &value1) != 0)
02623 return -1;
02624
02625 if (dazuko_get_value("\nTT=", request->buffer, &value2) != 0)
02626 {
02627 call_xp_free(value1);
02628 return -1;
02629 }
02630
02631 did.xp_id = call_xp_id_copy(xp_id);
02632 did.unique = dazuko_strtol(value1);
02633
02634 error = dazuko_set_option(&did, REMOVE_TRUSTED, value2, dazuko_strlen(value2));
02635
02636 call_xp_free(value1);
02637 call_xp_free(value2);
02638 call_xp_id_free(did.xp_id);
02639
02640 return error;
02641 }
02642
02643 #endif
02644
02645 static int dazuko_handle_request(struct dazuko_request *request, struct xp_daemon_id *xp_id)
02646 {
02647 int error = 0;
02648 int type;
02649
02650 if (request == NULL || xp_id == NULL)
02651 return -1;
02652
02653 type = request->type[0] + (256 * request->type[1]);
02654
02655 switch (type)
02656 {
02657 case REGISTER:
02658 return dazuko_handle_request_register(request, xp_id);
02659
02660 case UNREGISTER:
02661 return dazuko_handle_request_basic(request, xp_id, type);
02662
02663 case SET_ACCESS_MASK:
02664 return dazuko_handle_request_set_access_mask(request, xp_id);
02665
02666 case ADD_INCLUDE_PATH:
02667 return dazuko_handle_request_add_path(request, xp_id, type);
02668
02669 case ADD_EXCLUDE_PATH:
02670 return dazuko_handle_request_add_path(request, xp_id, type);
02671
02672 case REMOVE_ALL_PATHS:
02673 return dazuko_handle_request_basic(request, xp_id, type);
02674
02675 case GET_AN_ACCESS:
02676 return dazuko_handle_request_get_an_access(request, xp_id);
02677
02678 case RETURN_AN_ACCESS:
02679 return dazuko_handle_request_return_an_access(request, xp_id);
02680
02681 case INITIALIZE_CACHE:
02682 return dazuko_handle_request_initialize_cache(request, xp_id);
02683
02684 #ifdef TRUSTED_APPLICATION_SUPPORT
02685 case REGISTER_TRUSTED:
02686 return dazuko_handle_request_register_trusted(request, xp_id);
02687
02688 case UNREGISTER_TRUSTED:
02689
02690
02691 error = dazuko_unregister_trusted_daemon(xp_id);
02692
02693 break;
02694
02695 case REMOVE_ALL_TRUSTED:
02696 return dazuko_handle_request_basic(request, xp_id, type);
02697
02698 case REMOVE_TRUSTED:
02699 return dazuko_handle_request_remove_trusted(request, xp_id);
02700 #endif
02701
02702 default:
02703 error = XP_ERROR_INVALID;
02704
02705 break;
02706 }
02707
02708 return error;
02709 }
02710
02711 int dazuko_handle_user_request(const char *request_buffer, struct xp_daemon_id *xp_id)
02712 {
02713 int error = 0;
02714 struct dazuko_request *user_request = NULL;
02715 unsigned char *ll_request = NULL;
02716 unsigned char *ll_stream = NULL;
02717 struct dazuko_request *request = NULL;
02718 struct dazuko_request *temp_request = NULL;
02719 char *value;
02720 unsigned char tempslen[4];
02721 int streamlen = 0;
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733 if (request_buffer == NULL || xp_id == NULL)
02734 return XP_ERROR_FAULT;
02735
02736 if (dazuko_get_value("\nra=", request_buffer, &value) == 0)
02737 {
02738 ll_request = (unsigned char *)dazuko_strtoul(value);
02739 xp_free(value);
02740 }
02741 else if (dazuko_get_value("\nRA=", request_buffer, &value) == 0)
02742 {
02743 user_request = (struct dazuko_request *)dazuko_strtoul(value);
02744 xp_free(value);
02745 }
02746
02747
02748
02749
02750
02751
02752 if (ll_request == NULL && user_request == NULL)
02753 return XP_ERROR_FAULT;
02754
02755
02756 temp_request = (struct dazuko_request *)call_xp_malloc(sizeof(struct dazuko_request));
02757 if (temp_request == NULL)
02758 return XP_ERROR_FAULT;
02759
02760
02761 request = (struct dazuko_request *)call_xp_malloc(sizeof(struct dazuko_request));
02762 if (request == NULL)
02763 {
02764 error = XP_ERROR_FAULT;
02765 goto dazuko_handle_user_request_out;
02766 }
02767
02768
02769
02770 dazuko_bzero(request, sizeof(struct dazuko_request));
02771
02772 if (ll_request != NULL)
02773 {
02774
02775
02776
02777
02778
02779
02780
02781 if (call_xp_copyin(ll_request, tempslen, 4) != 0)
02782 {
02783 error = XP_ERROR_FAULT;
02784 goto dazuko_handle_user_request_out;
02785 }
02786
02787 if (dazuko_reqstream_chunksize(tempslen, &streamlen) != 0)
02788 {
02789 error = XP_ERROR_FAULT;
02790 goto dazuko_handle_user_request_out;
02791 }
02792
02793
02794 ll_stream = (unsigned char *)call_xp_malloc(streamlen);
02795 if (ll_stream == NULL)
02796 {
02797 error = XP_ERROR_FAULT;
02798 goto dazuko_handle_user_request_out;
02799 }
02800
02801 if (call_xp_copyin(ll_request, ll_stream, streamlen) != 0)
02802 {
02803 error = XP_ERROR_FAULT;
02804 goto dazuko_handle_user_request_out;
02805 }
02806
02807
02808 if (dazuko_reqstream_ll2hl(ll_stream, temp_request, 0) != 0)
02809 {
02810 error = XP_ERROR_FAULT;
02811 goto dazuko_handle_user_request_out;
02812 }
02813
02814
02815 }
02816 else if (user_request != NULL)
02817 {
02818
02819
02820
02821
02822
02823
02824
02825
02826 if (call_xp_copyin(user_request, temp_request, sizeof(struct dazuko_request)) != 0)
02827 {
02828 error = XP_ERROR_FAULT;
02829 goto dazuko_handle_user_request_out;
02830 }
02831 }
02832
02833
02834
02835
02836
02837
02838 memcpy(request->type, temp_request->type, sizeof(char[2]));
02839
02840
02841 request->buffer_size = temp_request->buffer_size;
02842 if (request->buffer_size < 0 || request->buffer_size > 8192)
02843 {
02844 error = XP_ERROR_FAULT;
02845 goto dazuko_handle_user_request_out;
02846 }
02847
02848
02849 request->reply_buffer_size = temp_request->reply_buffer_size;
02850 if (request->reply_buffer_size < 0 || request->reply_buffer_size > 8192)
02851 {
02852 error = XP_ERROR_PERMISSION;
02853 goto dazuko_handle_user_request_out;
02854 }
02855
02856 if (request->buffer_size > 0)
02857 {
02858
02859 request->buffer = (char *)call_xp_malloc(request->buffer_size + 1);
02860 if (request->buffer == NULL)
02861 {
02862 error = XP_ERROR_FAULT;
02863 goto dazuko_handle_user_request_out;
02864 }
02865
02866 }
02867
02868 if (request->reply_buffer_size > 0)
02869 {
02870
02871 request->reply_buffer = (char *)call_xp_malloc(request->reply_buffer_size + 1);
02872 if (request->reply_buffer == NULL)
02873 {
02874 error = XP_ERROR_FAULT;
02875 goto dazuko_handle_user_request_out;
02876 }
02877
02878 request->reply_buffer_size_used = 0;
02879 }
02880
02881 if (request->buffer_size > 0)
02882 {
02883
02884 if (call_xp_copyin(temp_request->buffer, request->buffer, request->buffer_size) != 0)
02885 {
02886 error = XP_ERROR_FAULT;
02887 goto dazuko_handle_user_request_out;
02888 }
02889
02890 request->buffer[request->buffer_size] = 0;
02891 }
02892
02893
02894 error = dazuko_handle_request(request, xp_id);
02895
02896
02897 if (error == 0 && request->reply_buffer_size > 0)
02898 {
02899 request->reply_buffer[request->reply_buffer_size] = 0;
02900
02901 temp_request->reply_buffer_size_used = request->reply_buffer_size_used;
02902
02903 if (ll_request != NULL)
02904 {
02905
02906
02907
02908 if (dazuko_reqstream_updll(temp_request, ll_stream) != 0)
02909 {
02910 error = XP_ERROR_FAULT;
02911 goto dazuko_handle_user_request_out;
02912 }
02913
02914
02915 if (call_xp_copyout(ll_stream, ll_request, streamlen) != 0)
02916 {
02917 error = XP_ERROR_FAULT;
02918 goto dazuko_handle_user_request_out;
02919 }
02920 }
02921 else if (user_request != NULL)
02922 {
02923
02924
02925
02926 if (call_xp_copyout(temp_request, user_request, sizeof(struct dazuko_request)) != 0)
02927 {
02928 error = XP_ERROR_FAULT;
02929 goto dazuko_handle_user_request_out;
02930 }
02931 }
02932
02933
02934 if (request->reply_buffer_size_used > 0)
02935 {
02936
02937 if (call_xp_copyout(request->reply_buffer, temp_request->reply_buffer, request->reply_buffer_size_used) != 0)
02938 {
02939 error = XP_ERROR_FAULT;
02940 goto dazuko_handle_user_request_out;
02941 }
02942 }
02943 }
02944
02945 dazuko_handle_user_request_out:
02946
02947 if (request != NULL)
02948 {
02949 if (request->buffer != NULL)
02950 call_xp_free(request->buffer);
02951
02952 if (request->reply_buffer != NULL)
02953 call_xp_free(request->reply_buffer);
02954
02955 call_xp_free(request);
02956 }
02957
02958 if (temp_request != NULL)
02959 call_xp_free(temp_request);
02960
02961 if (ll_stream != NULL)
02962 call_xp_free(ll_stream);
02963
02964 return error;
02965 }
02966
02967 int dazuko_handle_user_request_compat1(void *ptr, int cmd, struct xp_daemon_id *xp_id)
02968 {
02969 struct access_compat1 *user_request_1;
02970 struct access_compat1 *temp_request_1;
02971 struct slot_list *sl;
02972 int error = 0;
02973 struct slot *s;
02974 char *k_param;
02975 struct daemon_id did;
02976 int temp_length;
02977 int temp_int;
02978
02979 if (ptr == NULL || xp_id == NULL)
02980 return XP_ERROR_FAULT;
02981
02982 did.xp_id = call_xp_id_copy(xp_id);
02983 did.unique = -1;
02984
02985 switch (cmd)
02986 {
02987 case IOCTL_GET_AN_ACCESS:
02988
02989
02990
02991
02992
02993
02994 user_request_1 = (struct access_compat1 *)ptr;
02995
02996 error = call_xp_verify_user_writable(user_request_1, sizeof(struct access_compat1));
02997 if (error)
02998 {
02999 error = XP_ERROR_FAULT;
03000 break;
03001 }
03002
03003
03004 s = dazuko_get_an_access(&did);
03005
03006 if (s == NULL)
03007 {
03008 error = XP_ERROR_INTERRUPT;
03009 break;
03010 }
03011
03012
03013
03014
03015
03016
03017 if (s->filenamelength >= DAZUKO_FILENAME_MAX_LENGTH_COMPAT1)
03018 {
03019
03020
03021 s->filename[DAZUKO_FILENAME_MAX_LENGTH_COMPAT1 - 1] = 0;
03022 temp_length = DAZUKO_FILENAME_MAX_LENGTH_COMPAT1;
03023 }
03024 else
03025 {
03026 temp_length = s->filenamelength + 1;
03027 }
03028
03029 temp_request_1 = (struct access_compat1 *)call_xp_malloc(sizeof(struct access_compat1));
03030 if (temp_request_1 == NULL)
03031 {
03032 error = XP_ERROR_FAULT;
03033 }
03034 else if (call_xp_copyin(user_request_1, temp_request_1, sizeof(struct access_compat1)) != 0)
03035 {
03036 error = XP_ERROR_FAULT;
03037 }
03038
03039 if (error == 0)
03040 {
03041 temp_request_1->event = s->event;
03042 temp_request_1->o_flags = s->event_p.flags;
03043 temp_request_1->o_mode = s->event_p.mode;
03044 temp_request_1->uid = s->event_p.uid;
03045 temp_request_1->pid = s->event_p.pid;
03046 memcpy(temp_request_1->filename, s->filename, temp_length);
03047
03048 if (call_xp_copyout(temp_request_1, user_request_1, sizeof(struct access_compat1)) != 0)
03049 {
03050 error = XP_ERROR_FAULT;
03051 }
03052 }
03053
03054 call_xp_up(&(s->mutex));
03055
03056
03057 if (error)
03058 {
03059 if (dazuko_change_slot_state(s, DAZUKO_WORKING, DAZUKO_BROKEN, 1))
03060 {
03061
03062 call_xp_notify(&(s->wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
03063 }
03064 }
03065
03066 if (temp_request_1 != NULL)
03067 {
03068 call_xp_free(temp_request_1);
03069 }
03070
03071 break;
03072
03073 case IOCTL_RETURN_ACCESS:
03074
03075
03076
03077
03078 user_request_1 = (struct access_compat1 *)ptr;
03079
03080 error = call_xp_verify_user_readable(user_request_1, sizeof(struct access_compat1));
03081 if (error)
03082 {
03083 error = XP_ERROR_FAULT;
03084 break;
03085 }
03086
03087 temp_request_1 = (struct access_compat1 *)call_xp_malloc(sizeof(struct access_compat1));
03088 if (temp_request_1 == NULL)
03089 {
03090 error = XP_ERROR_FAULT;
03091 break;
03092 }
03093
03094 if (call_xp_copyin(user_request_1, temp_request_1, sizeof(struct access_compat1)) != 0)
03095 {
03096 error = XP_ERROR_FAULT;
03097 }
03098
03099 temp_int = temp_request_1->deny;
03100
03101 call_xp_free(temp_request_1);
03102
03103
03104 s = dazuko_find_slot(&did, 1, NULL);
03105
03106 if (s == NULL)
03107 {
03108
03109
03110
03111 DPRINT(("dazuko: daemon %d unexpectedly lost slot (by return access compat1)\n", did.unique));
03112
03113 error = XP_ERROR_FAULT;
03114 }
03115 else if (!handle_event_as_readonly(s))
03116 {
03117 error = dazuko_return_access(&did, temp_int, s);
03118 }
03119
03120 break;
03121
03122 case IOCTL_SET_OPTION:
03123
03124
03125
03126 error = call_xp_verify_user_readable(ptr, 2*sizeof(int));
03127 if (error)
03128 {
03129 error = XP_ERROR_FAULT;
03130 break;
03131 }
03132
03133
03134 if (call_xp_copyin(ptr, &temp_int, sizeof(int)) != 0)
03135 {
03136 error = XP_ERROR_FAULT;
03137 break;
03138 }
03139
03140 ptr = ((char *)ptr + sizeof(int));
03141
03142
03143 if (call_xp_copyin(ptr, &temp_length, sizeof(int)) != 0)
03144 {
03145 error = XP_ERROR_FAULT;
03146 break;
03147 }
03148
03149
03150 if (temp_length < 0 || temp_length > 4096)
03151 {
03152 error = XP_ERROR_INVALID;
03153 break;
03154 }
03155
03156 ptr = ((char *)ptr + sizeof(int));
03157
03158 error = call_xp_verify_user_readable(ptr, temp_length);
03159 if (error)
03160 {
03161 error = XP_ERROR_FAULT;
03162 break;
03163 }
03164
03165 k_param = (char *)call_xp_malloc(temp_length + 1);
03166 if (k_param == NULL)
03167 {
03168 error = XP_ERROR_FAULT;
03169 break;
03170 }
03171
03172
03173
03174 if (call_xp_copyin(ptr, k_param, temp_length) != 0)
03175 {
03176 call_xp_free(k_param);
03177 error = XP_ERROR_FAULT;
03178 break;
03179 }
03180
03181 k_param[temp_length] = 0;
03182
03183 switch (temp_int)
03184 {
03185 case REGISTER:
03186 error = dazuko_register_daemon(&did, k_param, temp_length, 1);
03187 break;
03188
03189 case SET_ACCESS_MASK:
03190
03191 if (dazuko_find_slot_and_slotlist(&did, 1, NULL, &sl) == NULL)
03192 {
03193 error = XP_ERROR_PERMISSION;
03194 }
03195 else if (sl == NULL)
03196 {
03197 error = XP_ERROR_PERMISSION;
03198 }
03199 else
03200 {
03201 sl->access_mask = k_param[0];
03202
03203
03204 dazuko_setup_amc_cache();
03205 }
03206 break;
03207
03208 default:
03209 error = dazuko_set_option(&did, temp_int, k_param, temp_length);
03210 break;
03211 }
03212
03213 call_xp_free(k_param);
03214
03215 break;
03216
03217 default:
03218 error = XP_ERROR_INVALID;
03219
03220 break;
03221 }
03222
03223 call_xp_id_free(did.xp_id);
03224
03225 return error;
03226 }
03227
03228 inline int dazuko_is_our_daemon(struct xp_daemon_id *xp_id, struct slot_list **slotlist)
03229 {
03230
03231
03232
03233 int ret = 0;
03234 struct daemon_id did;
03235 struct slot *s;
03236 int i;
03237 struct slot_list *sl;
03238 #ifdef TRUSTED_APPLICATION_SUPPORT
03239 int cmp;
03240 struct trusted_container *tc;
03241 struct trusted_container *prev;
03242 #endif
03243
03244 did.xp_id = call_xp_id_copy(xp_id);
03245 did.unique = -1;
03246
03247 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
03248 {
03249
03250 call_xp_down(&(slot_lists[i].mutex));
03251
03252 sl = slot_lists[i].slot_list;
03253
03254 call_xp_up(&(slot_lists[i].mutex));
03255
03256
03257 if (sl == NULL)
03258 continue;
03259
03260 s = _dazuko_find_slot(&did, 1, sl);
03261 if (s != NULL)
03262 {
03263 ret = 1;
03264
03265 if (slotlist != NULL)
03266 *slotlist = sl;
03267
03268 break;
03269 }
03270
03271 if (did.xp_id == NULL)
03272 continue;
03273
03274 #ifdef TRUSTED_APPLICATION_SUPPORT
03275
03276
03277
03278 if (!(sl->set_trusted_list))
03279 continue;
03280
03281
03282 call_xp_read_lock(&(sl->lock_trusted_list));
03283
03284 tc = sl->trusted_list;
03285 prev = NULL;
03286 while (tc != NULL)
03287 {
03288 cmp = call_xp_id_compare(tc->xp_id, did.xp_id, 1);
03289
03290 if (cmp == DAZUKO_SAME || (cmp == DAZUKO_CHILD && tc->trust_children))
03291 {
03292 ret = 1;
03293
03294 if (slotlist != NULL)
03295 *slotlist = sl;
03296
03297 break;
03298 }
03299 else if (cmp == DAZUKO_SUSPICIOUS)
03300 {
03301 DPRINT(("dazuko: detected suspicios activity, removing trusted daemon [%d]\n", did.unique));
03302
03303
03304 tc = _remove_trusted_node(prev, tc, sl);
03305 break;
03306 }
03307 else
03308 {
03309 prev = tc;
03310 tc = tc->next;
03311 }
03312 }
03313
03314 call_xp_read_unlock(&(sl->lock_trusted_list));
03315
03316
03317 if (ret)
03318 break;
03319 #endif
03320 }
03321
03322 call_xp_id_free(did.xp_id);
03323
03324 return ret;
03325 }
03326
03327 int dazuko_check_access(unsigned long event, int daemon_is_allowed, struct xp_daemon_id *xp_id, struct slot_list **cached_lookup)
03328 {
03329 int i;
03330 struct slot_list *sl = NULL;
03331
03332
03333 if (call_xp_atomic_read(&active) <= 0)
03334 return -1;
03335
03336
03337
03338 i = dazuko_event2index(event);
03339 if (i < 0 || i >= NUM_EVENTS)
03340 return -1;
03341
03342
03343 call_xp_down(&mutex_amc);
03344
03345 i = access_mask_cache[i][0];
03346
03347 call_xp_up(&mutex_amc);
03348
03349
03350 if (i == AMC_UNSET)
03351 return -1;
03352
03353 if (dazuko_is_our_daemon(xp_id, &sl))
03354 {
03355
03356 if (daemon_is_allowed)
03357 {
03358
03359
03360
03361 return -1;
03362 }
03363 else
03364 {
03365
03366
03367
03368
03369 if (call_xp_atomic_read(&groupcount) == 1)
03370 return -1;
03371
03372 if (cached_lookup != NULL)
03373 {
03374
03375 *cached_lookup = sl;
03376 }
03377 }
03378 }
03379
03380
03381
03382
03383 return 0;
03384 }
03385
03386 int dazuko_process_access(unsigned long event, struct dazuko_file_struct *kfs, struct event_properties *event_p, struct slot_list *cached_lookup)
03387 {
03388
03389
03390
03391
03392
03393
03394
03395 int error = 0;
03396
03397 if (kfs == NULL)
03398 {
03399
03400
03401 call_xp_print("dazuko: kfs=NULL (possible bug)\n");
03402
03403 return XP_ERROR_PERMISSION;
03404 }
03405
03406
03407 error = dazuko_run_daemon(event, kfs, event_p, cached_lookup);
03408
03409 if (error == 2)
03410 {
03411
03412 return 2;
03413 }
03414 else if (error > 0)
03415 {
03416
03417
03418 return XP_ERROR_PERMISSION;
03419 }
03420 else if (error < 0)
03421 {
03422
03423
03424 return XP_ERROR_INTERRUPT;
03425 }
03426
03427
03428
03429 return 0;
03430 }
03431
03432 int dazuko_init(void)
03433 {
03434 int i;
03435 int error;
03436
03437 call_xp_init_mutex(&mutex_unique_count);
03438 call_xp_init_mutex(&mutex_amc);
03439
03440 dazuko_bzero(&slot_lists, sizeof(slot_lists));
03441
03442 memset(&access_mask_cache, AMC_UNSET, sizeof(access_mask_cache));
03443
03444 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
03445 call_xp_init_mutex(&(slot_lists[i].mutex));
03446
03447 call_xp_atomic_set(&active, 0);
03448 call_xp_atomic_set(&groupcount, 0);
03449
03450 error = call_xp_sys_hook();
03451
03452 if (error == 0)
03453 call_xp_print("dazuko: loaded, version=%s\n", VERSION_STRING);
03454
03455 return error;
03456 }
03457
03458 int dazuko_exit(void)
03459 {
03460 int error;
03461 int i;
03462 int j;
03463
03464 i = call_xp_atomic_read(&active);
03465
03466 if (i != 0)
03467 {
03468 call_xp_print("dazuko: warning: trying to remove Dazuko with %d process%s still registered\n", i, i==1 ? "" : "es");
03469 return -1;
03470 }
03471
03472 error = call_xp_sys_unhook();
03473
03474 if (error == 0)
03475 {
03476 call_xp_destroy_mutex(&mutex_unique_count);
03477 call_xp_destroy_mutex(&mutex_amc);
03478
03479 for (i=0 ; i<NUM_SLOT_LISTS ; i++)
03480 {
03481 if (slot_lists[i].slot_list != NULL)
03482 {
03483 dazuko_remove_all_paths(slot_lists[i].slot_list);
03484
03485 if (call_xp_atomic_read(&(slot_lists[i].slot_list->use_count)) != 0)
03486 call_xp_print("dazuko: slot_list count was not 0 (possible bug)\n");
03487
03488 for (j=0 ; j<NUM_SLOTS ; j++)
03489 {
03490 call_xp_destroy_mutex(&(slot_lists[i].slot_list->slots[j].mutex));
03491 call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_daemon_waiting_until_this_slot_not_READY));
03492 call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_kernel_waiting_until_this_slot_not_WAITING_and_not_WORKING));
03493 call_xp_destroy_queue(&(slot_lists[i].slot_list->slots[j].wait_daemon_waiting_until_this_slot_not_DONE));
03494 }
03495
03496 call_xp_destroy_rwlock(&(slot_lists[i].slot_list->lock_lists));
03497
03498 #ifdef TRUSTED_APPLICATION_SUPPORT
03499 dazuko_remove_all_trusted(slot_lists[i].slot_list);
03500 call_xp_destroy_rwlock(&(slot_lists[i].slot_list->lock_trusted_list));
03501 #endif
03502
03503 call_xp_destroy_queue(&(slot_lists[i].slot_list->wait_kernel_waiting_for_any_READY_slot_or_zero_use_count));
03504
03505 if (slot_lists[i].slot_list->reg_name != NULL)
03506 call_xp_free(slot_lists[i].slot_list->reg_name);
03507 slot_lists[i].slot_list->reg_name = NULL;
03508
03509 call_xp_free(slot_lists[i].slot_list);
03510 slot_lists[i].slot_list = NULL;
03511 }
03512
03513 call_xp_destroy_mutex(&(slot_lists[i].mutex));
03514 }
03515
03516 call_xp_print("dazuko: unloaded, version=%s\n", VERSION_STRING);
03517 }
03518
03519 return error;
03520 }