1*433d6423SLionel Sambuc #include "inc.h" 2*433d6423SLionel Sambuc #include "store.h" 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc /* Allocate space for the data store. */ 5*433d6423SLionel Sambuc static struct data_store ds_store[NR_DS_KEYS]; 6*433d6423SLionel Sambuc static struct subscription ds_subs[NR_DS_SUBS]; 7*433d6423SLionel Sambuc 8*433d6423SLionel Sambuc /*===========================================================================* 9*433d6423SLionel Sambuc * alloc_data_slot * 10*433d6423SLionel Sambuc *===========================================================================*/ 11*433d6423SLionel Sambuc static struct data_store *alloc_data_slot(void) 12*433d6423SLionel Sambuc { 13*433d6423SLionel Sambuc /* Allocate a new data slot. */ 14*433d6423SLionel Sambuc int i; 15*433d6423SLionel Sambuc 16*433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) { 17*433d6423SLionel Sambuc if (!(ds_store[i].flags & DSF_IN_USE)) 18*433d6423SLionel Sambuc return &ds_store[i]; 19*433d6423SLionel Sambuc } 20*433d6423SLionel Sambuc 21*433d6423SLionel Sambuc return NULL; 22*433d6423SLionel Sambuc } 23*433d6423SLionel Sambuc 24*433d6423SLionel Sambuc /*===========================================================================* 25*433d6423SLionel Sambuc * alloc_sub_slot * 26*433d6423SLionel Sambuc *===========================================================================*/ 27*433d6423SLionel Sambuc static struct subscription *alloc_sub_slot(void) 28*433d6423SLionel Sambuc { 29*433d6423SLionel Sambuc /* Allocate a new subscription slot. */ 30*433d6423SLionel Sambuc int i; 31*433d6423SLionel Sambuc 32*433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) { 33*433d6423SLionel Sambuc if (!(ds_subs[i].flags & DSF_IN_USE)) 34*433d6423SLionel Sambuc return &ds_subs[i]; 35*433d6423SLionel Sambuc } 36*433d6423SLionel Sambuc 37*433d6423SLionel Sambuc return NULL; 38*433d6423SLionel Sambuc } 39*433d6423SLionel Sambuc 40*433d6423SLionel Sambuc /*===========================================================================* 41*433d6423SLionel Sambuc * lookup_entry * 42*433d6423SLionel Sambuc *===========================================================================*/ 43*433d6423SLionel Sambuc static struct data_store *lookup_entry(const char *key_name, int type) 44*433d6423SLionel Sambuc { 45*433d6423SLionel Sambuc /* Lookup an existing entry by key and type. */ 46*433d6423SLionel Sambuc int i; 47*433d6423SLionel Sambuc 48*433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) { 49*433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE) /* used */ 50*433d6423SLionel Sambuc && (ds_store[i].flags & type) /* same type*/ 51*433d6423SLionel Sambuc && !strcmp(ds_store[i].key, key_name)) /* same key*/ 52*433d6423SLionel Sambuc return &ds_store[i]; 53*433d6423SLionel Sambuc } 54*433d6423SLionel Sambuc 55*433d6423SLionel Sambuc return NULL; 56*433d6423SLionel Sambuc } 57*433d6423SLionel Sambuc 58*433d6423SLionel Sambuc /*===========================================================================* 59*433d6423SLionel Sambuc * lookup_label_entry * 60*433d6423SLionel Sambuc *===========================================================================*/ 61*433d6423SLionel Sambuc static struct data_store *lookup_label_entry(unsigned num) 62*433d6423SLionel Sambuc { 63*433d6423SLionel Sambuc /* Lookup an existing label entry by num. */ 64*433d6423SLionel Sambuc int i; 65*433d6423SLionel Sambuc 66*433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) { 67*433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE) 68*433d6423SLionel Sambuc && (ds_store[i].flags & DSF_TYPE_LABEL) 69*433d6423SLionel Sambuc && (ds_store[i].u.u32 == num)) 70*433d6423SLionel Sambuc return &ds_store[i]; 71*433d6423SLionel Sambuc } 72*433d6423SLionel Sambuc 73*433d6423SLionel Sambuc return NULL; 74*433d6423SLionel Sambuc } 75*433d6423SLionel Sambuc 76*433d6423SLionel Sambuc /*===========================================================================* 77*433d6423SLionel Sambuc * lookup_sub * 78*433d6423SLionel Sambuc *===========================================================================*/ 79*433d6423SLionel Sambuc static struct subscription *lookup_sub(const char *owner) 80*433d6423SLionel Sambuc { 81*433d6423SLionel Sambuc /* Lookup an existing subscription given its owner. */ 82*433d6423SLionel Sambuc int i; 83*433d6423SLionel Sambuc 84*433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) { 85*433d6423SLionel Sambuc if ((ds_subs[i].flags & DSF_IN_USE) /* used */ 86*433d6423SLionel Sambuc && !strcmp(ds_subs[i].owner, owner)) /* same key*/ 87*433d6423SLionel Sambuc return &ds_subs[i]; 88*433d6423SLionel Sambuc } 89*433d6423SLionel Sambuc 90*433d6423SLionel Sambuc return NULL; 91*433d6423SLionel Sambuc } 92*433d6423SLionel Sambuc 93*433d6423SLionel Sambuc /*===========================================================================* 94*433d6423SLionel Sambuc * ds_getprocname * 95*433d6423SLionel Sambuc *===========================================================================*/ 96*433d6423SLionel Sambuc static char *ds_getprocname(endpoint_t e) 97*433d6423SLionel Sambuc { 98*433d6423SLionel Sambuc /* Get a process name given its endpoint. */ 99*433d6423SLionel Sambuc struct data_store *dsp; 100*433d6423SLionel Sambuc 101*433d6423SLionel Sambuc static char *first_proc_name = "ds"; 102*433d6423SLionel Sambuc endpoint_t first_proc_ep = DS_PROC_NR; 103*433d6423SLionel Sambuc 104*433d6423SLionel Sambuc if(e == first_proc_ep) 105*433d6423SLionel Sambuc return first_proc_name; 106*433d6423SLionel Sambuc 107*433d6423SLionel Sambuc if((dsp = lookup_label_entry(e)) != NULL) 108*433d6423SLionel Sambuc return dsp->key; 109*433d6423SLionel Sambuc 110*433d6423SLionel Sambuc return NULL; 111*433d6423SLionel Sambuc } 112*433d6423SLionel Sambuc 113*433d6423SLionel Sambuc /*===========================================================================* 114*433d6423SLionel Sambuc * ds_getprocep * 115*433d6423SLionel Sambuc *===========================================================================*/ 116*433d6423SLionel Sambuc static endpoint_t ds_getprocep(const char *s) 117*433d6423SLionel Sambuc { 118*433d6423SLionel Sambuc /* Get a process endpoint given its name. */ 119*433d6423SLionel Sambuc struct data_store *dsp; 120*433d6423SLionel Sambuc 121*433d6423SLionel Sambuc if((dsp = lookup_entry(s, DSF_TYPE_LABEL)) != NULL) 122*433d6423SLionel Sambuc return dsp->u.u32; 123*433d6423SLionel Sambuc panic("ds_getprocep: process endpoint not found"); 124*433d6423SLionel Sambuc } 125*433d6423SLionel Sambuc 126*433d6423SLionel Sambuc /*===========================================================================* 127*433d6423SLionel Sambuc * check_auth * 128*433d6423SLionel Sambuc *===========================================================================*/ 129*433d6423SLionel Sambuc static int check_auth(const struct data_store *p, endpoint_t ep, int perm) 130*433d6423SLionel Sambuc { 131*433d6423SLionel Sambuc /* Check authorization for a given type of permission. */ 132*433d6423SLionel Sambuc char *source; 133*433d6423SLionel Sambuc 134*433d6423SLionel Sambuc if(!(p->flags & perm)) 135*433d6423SLionel Sambuc return 1; 136*433d6423SLionel Sambuc 137*433d6423SLionel Sambuc source = ds_getprocname(ep); 138*433d6423SLionel Sambuc return source && !strcmp(p->owner, source); 139*433d6423SLionel Sambuc } 140*433d6423SLionel Sambuc 141*433d6423SLionel Sambuc /*===========================================================================* 142*433d6423SLionel Sambuc * get_key_name * 143*433d6423SLionel Sambuc *===========================================================================*/ 144*433d6423SLionel Sambuc static int get_key_name(const message *m_ptr, char *key_name) 145*433d6423SLionel Sambuc { 146*433d6423SLionel Sambuc /* Get key name given an input message. */ 147*433d6423SLionel Sambuc int r; 148*433d6423SLionel Sambuc 149*433d6423SLionel Sambuc if (m_ptr->m_ds_req.key_len > DS_MAX_KEYLEN || m_ptr->m_ds_req.key_len < 2) { 150*433d6423SLionel Sambuc printf("DS: bogus key length (%d) from %d\n", m_ptr->m_ds_req.key_len, 151*433d6423SLionel Sambuc m_ptr->m_source); 152*433d6423SLionel Sambuc return EINVAL; 153*433d6423SLionel Sambuc } 154*433d6423SLionel Sambuc 155*433d6423SLionel Sambuc /* Copy name from caller. */ 156*433d6423SLionel Sambuc r = sys_safecopyfrom(m_ptr->m_source, 157*433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, 0, 158*433d6423SLionel Sambuc (vir_bytes) key_name, m_ptr->m_ds_req.key_len); 159*433d6423SLionel Sambuc if(r != OK) { 160*433d6423SLionel Sambuc printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r); 161*433d6423SLionel Sambuc return r; 162*433d6423SLionel Sambuc } 163*433d6423SLionel Sambuc 164*433d6423SLionel Sambuc key_name[DS_MAX_KEYLEN-1] = '\0'; 165*433d6423SLionel Sambuc 166*433d6423SLionel Sambuc return OK; 167*433d6423SLionel Sambuc } 168*433d6423SLionel Sambuc 169*433d6423SLionel Sambuc /*===========================================================================* 170*433d6423SLionel Sambuc * check_sub_match * 171*433d6423SLionel Sambuc *===========================================================================*/ 172*433d6423SLionel Sambuc static int check_sub_match(const struct subscription *subp, 173*433d6423SLionel Sambuc struct data_store *dsp, endpoint_t ep) 174*433d6423SLionel Sambuc { 175*433d6423SLionel Sambuc /* Check if an entry matches a subscription. Return 1 in case of match. */ 176*433d6423SLionel Sambuc return (check_auth(dsp, ep, DSF_PRIV_SUBSCRIBE) 177*433d6423SLionel Sambuc && regexec(&subp->regex, dsp->key, 0, NULL, 0) == 0) 178*433d6423SLionel Sambuc ? 1 : 0; 179*433d6423SLionel Sambuc } 180*433d6423SLionel Sambuc 181*433d6423SLionel Sambuc /*===========================================================================* 182*433d6423SLionel Sambuc * update_subscribers * 183*433d6423SLionel Sambuc *===========================================================================*/ 184*433d6423SLionel Sambuc static void update_subscribers(struct data_store *dsp, int set) 185*433d6423SLionel Sambuc { 186*433d6423SLionel Sambuc /* If set = 1, set bit in the sub bitmap of any subscription matching the given 187*433d6423SLionel Sambuc * entry, otherwise clear it. In both cases, notify the subscriber. 188*433d6423SLionel Sambuc */ 189*433d6423SLionel Sambuc int i; 190*433d6423SLionel Sambuc int nr = dsp - ds_store; 191*433d6423SLionel Sambuc endpoint_t ep; 192*433d6423SLionel Sambuc 193*433d6423SLionel Sambuc for(i = 0; i < NR_DS_SUBS; i++) { 194*433d6423SLionel Sambuc if(!(ds_subs[i].flags & DSF_IN_USE)) 195*433d6423SLionel Sambuc continue; 196*433d6423SLionel Sambuc if(!(ds_subs[i].flags & dsp->flags & DSF_MASK_TYPE)) 197*433d6423SLionel Sambuc continue; 198*433d6423SLionel Sambuc 199*433d6423SLionel Sambuc ep = ds_getprocep(ds_subs[i].owner); 200*433d6423SLionel Sambuc if(!check_sub_match(&ds_subs[i], dsp, ep)) 201*433d6423SLionel Sambuc continue; 202*433d6423SLionel Sambuc 203*433d6423SLionel Sambuc if(set == 1) { 204*433d6423SLionel Sambuc SET_BIT(ds_subs[i].old_subs, nr); 205*433d6423SLionel Sambuc } else { 206*433d6423SLionel Sambuc UNSET_BIT(ds_subs[i].old_subs, nr); 207*433d6423SLionel Sambuc } 208*433d6423SLionel Sambuc ipc_notify(ep); 209*433d6423SLionel Sambuc } 210*433d6423SLionel Sambuc } 211*433d6423SLionel Sambuc 212*433d6423SLionel Sambuc /*===========================================================================* 213*433d6423SLionel Sambuc * map_service * 214*433d6423SLionel Sambuc *===========================================================================*/ 215*433d6423SLionel Sambuc static int map_service(const struct rprocpub *rpub) 216*433d6423SLionel Sambuc { 217*433d6423SLionel Sambuc /* Map a new service by registering its label. */ 218*433d6423SLionel Sambuc struct data_store *dsp; 219*433d6423SLionel Sambuc 220*433d6423SLionel Sambuc /* Allocate a new data slot. */ 221*433d6423SLionel Sambuc if((dsp = alloc_data_slot()) == NULL) { 222*433d6423SLionel Sambuc return ENOMEM; 223*433d6423SLionel Sambuc } 224*433d6423SLionel Sambuc 225*433d6423SLionel Sambuc /* Set attributes. */ 226*433d6423SLionel Sambuc strcpy(dsp->key, rpub->label); 227*433d6423SLionel Sambuc dsp->u.u32 = (u32_t) rpub->endpoint; 228*433d6423SLionel Sambuc strcpy(dsp->owner, "rs"); 229*433d6423SLionel Sambuc dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL; 230*433d6423SLionel Sambuc 231*433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */ 232*433d6423SLionel Sambuc update_subscribers(dsp, 1); 233*433d6423SLionel Sambuc 234*433d6423SLionel Sambuc return(OK); 235*433d6423SLionel Sambuc } 236*433d6423SLionel Sambuc 237*433d6423SLionel Sambuc /*===========================================================================* 238*433d6423SLionel Sambuc * sef_cb_init_fresh * 239*433d6423SLionel Sambuc *===========================================================================*/ 240*433d6423SLionel Sambuc int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) 241*433d6423SLionel Sambuc { 242*433d6423SLionel Sambuc /* Initialize the data store server. */ 243*433d6423SLionel Sambuc int i, r; 244*433d6423SLionel Sambuc struct rprocpub rprocpub[NR_BOOT_PROCS]; 245*433d6423SLionel Sambuc 246*433d6423SLionel Sambuc /* Reset data store: data and subscriptions. */ 247*433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) { 248*433d6423SLionel Sambuc ds_store[i].flags = 0; 249*433d6423SLionel Sambuc } 250*433d6423SLionel Sambuc for(i = 0; i < NR_DS_SUBS; i++) { 251*433d6423SLionel Sambuc ds_subs[i].flags = 0; 252*433d6423SLionel Sambuc } 253*433d6423SLionel Sambuc 254*433d6423SLionel Sambuc /* Map all the services in the boot image. */ 255*433d6423SLionel Sambuc if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0, 256*433d6423SLionel Sambuc (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) { 257*433d6423SLionel Sambuc panic("sys_safecopyfrom failed: %d", r); 258*433d6423SLionel Sambuc } 259*433d6423SLionel Sambuc for(i=0;i < NR_BOOT_PROCS;i++) { 260*433d6423SLionel Sambuc if(rprocpub[i].in_use) { 261*433d6423SLionel Sambuc if((r = map_service(&rprocpub[i])) != OK) { 262*433d6423SLionel Sambuc panic("unable to map service: %d", r); 263*433d6423SLionel Sambuc } 264*433d6423SLionel Sambuc } 265*433d6423SLionel Sambuc } 266*433d6423SLionel Sambuc 267*433d6423SLionel Sambuc return(OK); 268*433d6423SLionel Sambuc } 269*433d6423SLionel Sambuc 270*433d6423SLionel Sambuc /*===========================================================================* 271*433d6423SLionel Sambuc * do_publish * 272*433d6423SLionel Sambuc *===========================================================================*/ 273*433d6423SLionel Sambuc int do_publish(message *m_ptr) 274*433d6423SLionel Sambuc { 275*433d6423SLionel Sambuc struct data_store *dsp; 276*433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN]; 277*433d6423SLionel Sambuc char *source; 278*433d6423SLionel Sambuc int flags = m_ptr->m_ds_req.flags; 279*433d6423SLionel Sambuc size_t length; 280*433d6423SLionel Sambuc int r; 281*433d6423SLionel Sambuc 282*433d6423SLionel Sambuc /* Lookup the source. */ 283*433d6423SLionel Sambuc source = ds_getprocname(m_ptr->m_source); 284*433d6423SLionel Sambuc if(source == NULL) 285*433d6423SLionel Sambuc return EPERM; 286*433d6423SLionel Sambuc 287*433d6423SLionel Sambuc /* Only RS can publish labels. */ 288*433d6423SLionel Sambuc if((flags & DSF_TYPE_LABEL) && m_ptr->m_source != RS_PROC_NR) 289*433d6423SLionel Sambuc return EPERM; 290*433d6423SLionel Sambuc 291*433d6423SLionel Sambuc /* Get key name. */ 292*433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK) 293*433d6423SLionel Sambuc return r; 294*433d6423SLionel Sambuc 295*433d6423SLionel Sambuc /* Lookup the entry. */ 296*433d6423SLionel Sambuc dsp = lookup_entry(key_name, flags & DSF_MASK_TYPE); 297*433d6423SLionel Sambuc /* If type is LABEL, also try to lookup the entry by num. */ 298*433d6423SLionel Sambuc if((flags & DSF_TYPE_LABEL) && (dsp == NULL)) 299*433d6423SLionel Sambuc dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep); 300*433d6423SLionel Sambuc 301*433d6423SLionel Sambuc if(dsp == NULL) { 302*433d6423SLionel Sambuc /* The entry doesn't exist, allocate a new data slot. */ 303*433d6423SLionel Sambuc if((dsp = alloc_data_slot()) == NULL) 304*433d6423SLionel Sambuc return ENOMEM; 305*433d6423SLionel Sambuc } else if (flags & DSF_OVERWRITE) { 306*433d6423SLionel Sambuc /* Overwrite. */ 307*433d6423SLionel Sambuc if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_OVERWRITE)) 308*433d6423SLionel Sambuc return EPERM; 309*433d6423SLionel Sambuc } else { 310*433d6423SLionel Sambuc /* Don't overwrite and return error. */ 311*433d6423SLionel Sambuc return EEXIST; 312*433d6423SLionel Sambuc } 313*433d6423SLionel Sambuc 314*433d6423SLionel Sambuc /* Store! */ 315*433d6423SLionel Sambuc switch(flags & DSF_MASK_TYPE) { 316*433d6423SLionel Sambuc case DSF_TYPE_U32: 317*433d6423SLionel Sambuc dsp->u.u32 = m_ptr->m_ds_req.val_in.u32; 318*433d6423SLionel Sambuc break; 319*433d6423SLionel Sambuc case DSF_TYPE_LABEL: 320*433d6423SLionel Sambuc dsp->u.u32 = m_ptr->m_ds_req.val_in.ep; 321*433d6423SLionel Sambuc break; 322*433d6423SLionel Sambuc case DSF_TYPE_STR: 323*433d6423SLionel Sambuc case DSF_TYPE_MEM: 324*433d6423SLionel Sambuc length = m_ptr->m_ds_req.val_len; 325*433d6423SLionel Sambuc /* Allocate a new data buffer if necessary. */ 326*433d6423SLionel Sambuc if(!(dsp->flags & DSF_IN_USE)) { 327*433d6423SLionel Sambuc if((dsp->u.mem.data = malloc(length)) == NULL) 328*433d6423SLionel Sambuc return ENOMEM; 329*433d6423SLionel Sambuc dsp->u.mem.reallen = length; 330*433d6423SLionel Sambuc } else if(length > dsp->u.mem.reallen) { 331*433d6423SLionel Sambuc free(dsp->u.mem.data); 332*433d6423SLionel Sambuc if((dsp->u.mem.data = malloc(length)) == NULL) 333*433d6423SLionel Sambuc return ENOMEM; 334*433d6423SLionel Sambuc dsp->u.mem.reallen = length; 335*433d6423SLionel Sambuc } 336*433d6423SLionel Sambuc 337*433d6423SLionel Sambuc /* Copy the memory range. */ 338*433d6423SLionel Sambuc r = sys_safecopyfrom(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant, 339*433d6423SLionel Sambuc 0, (vir_bytes) dsp->u.mem.data, length); 340*433d6423SLionel Sambuc if(r != OK) { 341*433d6423SLionel Sambuc printf("DS: publish: memory map/copy failed from %d: %d\n", 342*433d6423SLionel Sambuc m_ptr->m_source, r); 343*433d6423SLionel Sambuc free(dsp->u.mem.data); 344*433d6423SLionel Sambuc return r; 345*433d6423SLionel Sambuc } 346*433d6423SLionel Sambuc dsp->u.mem.length = length; 347*433d6423SLionel Sambuc if(flags & DSF_TYPE_STR) { 348*433d6423SLionel Sambuc ((char*)dsp->u.mem.data)[length-1] = '\0'; 349*433d6423SLionel Sambuc } 350*433d6423SLionel Sambuc break; 351*433d6423SLionel Sambuc default: 352*433d6423SLionel Sambuc return EINVAL; 353*433d6423SLionel Sambuc } 354*433d6423SLionel Sambuc 355*433d6423SLionel Sambuc /* Set attributes. */ 356*433d6423SLionel Sambuc strcpy(dsp->key, key_name); 357*433d6423SLionel Sambuc strcpy(dsp->owner, source); 358*433d6423SLionel Sambuc dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL); 359*433d6423SLionel Sambuc 360*433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */ 361*433d6423SLionel Sambuc update_subscribers(dsp, 1); 362*433d6423SLionel Sambuc 363*433d6423SLionel Sambuc return(OK); 364*433d6423SLionel Sambuc } 365*433d6423SLionel Sambuc 366*433d6423SLionel Sambuc /*===========================================================================* 367*433d6423SLionel Sambuc * do_retrieve * 368*433d6423SLionel Sambuc *===========================================================================*/ 369*433d6423SLionel Sambuc int do_retrieve(message *m_ptr) 370*433d6423SLionel Sambuc { 371*433d6423SLionel Sambuc struct data_store *dsp; 372*433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN]; 373*433d6423SLionel Sambuc int flags = m_ptr->m_ds_req.flags; 374*433d6423SLionel Sambuc int type = flags & DSF_MASK_TYPE; 375*433d6423SLionel Sambuc size_t length; 376*433d6423SLionel Sambuc int r; 377*433d6423SLionel Sambuc 378*433d6423SLionel Sambuc /* Get key name. */ 379*433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK) 380*433d6423SLionel Sambuc return r; 381*433d6423SLionel Sambuc 382*433d6423SLionel Sambuc /* Lookup the entry. */ 383*433d6423SLionel Sambuc if((dsp = lookup_entry(key_name, type)) == NULL) 384*433d6423SLionel Sambuc return ESRCH; 385*433d6423SLionel Sambuc if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_RETRIEVE)) 386*433d6423SLionel Sambuc return EPERM; 387*433d6423SLionel Sambuc 388*433d6423SLionel Sambuc /* Copy the requested data. */ 389*433d6423SLionel Sambuc switch(type) { 390*433d6423SLionel Sambuc case DSF_TYPE_U32: 391*433d6423SLionel Sambuc m_ptr->m_ds_reply.val_out.u32 = dsp->u.u32; 392*433d6423SLionel Sambuc break; 393*433d6423SLionel Sambuc case DSF_TYPE_LABEL: 394*433d6423SLionel Sambuc m_ptr->m_ds_reply.val_out.ep = dsp->u.u32; 395*433d6423SLionel Sambuc break; 396*433d6423SLionel Sambuc case DSF_TYPE_STR: 397*433d6423SLionel Sambuc case DSF_TYPE_MEM: 398*433d6423SLionel Sambuc length = MIN(m_ptr->m_ds_req.val_len, dsp->u.mem.length); 399*433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant, 0, 400*433d6423SLionel Sambuc (vir_bytes) dsp->u.mem.data, length); 401*433d6423SLionel Sambuc if(r != OK) { 402*433d6423SLionel Sambuc printf("DS: retrieve: copy failed to %d: %d\n", 403*433d6423SLionel Sambuc m_ptr->m_source, r); 404*433d6423SLionel Sambuc return r; 405*433d6423SLionel Sambuc } 406*433d6423SLionel Sambuc m_ptr->m_ds_reply.val_len = length; 407*433d6423SLionel Sambuc break; 408*433d6423SLionel Sambuc default: 409*433d6423SLionel Sambuc return EINVAL; 410*433d6423SLionel Sambuc } 411*433d6423SLionel Sambuc 412*433d6423SLionel Sambuc return OK; 413*433d6423SLionel Sambuc } 414*433d6423SLionel Sambuc 415*433d6423SLionel Sambuc /*===========================================================================* 416*433d6423SLionel Sambuc * do_retrieve_label * 417*433d6423SLionel Sambuc *===========================================================================*/ 418*433d6423SLionel Sambuc int do_retrieve_label(const message *m_ptr) 419*433d6423SLionel Sambuc { 420*433d6423SLionel Sambuc struct data_store *dsp; 421*433d6423SLionel Sambuc int r; 422*433d6423SLionel Sambuc 423*433d6423SLionel Sambuc /* Lookup the label entry. */ 424*433d6423SLionel Sambuc if((dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep)) == NULL) 425*433d6423SLionel Sambuc return ESRCH; 426*433d6423SLionel Sambuc 427*433d6423SLionel Sambuc /* Copy the key name. */ 428*433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source, 429*433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0, 430*433d6423SLionel Sambuc (vir_bytes) dsp->key, strlen(dsp->key) + 1); 431*433d6423SLionel Sambuc if(r != OK) { 432*433d6423SLionel Sambuc printf("DS: copy failed from %d: %d\n", m_ptr->m_source, r); 433*433d6423SLionel Sambuc return r; 434*433d6423SLionel Sambuc } 435*433d6423SLionel Sambuc 436*433d6423SLionel Sambuc return OK; 437*433d6423SLionel Sambuc } 438*433d6423SLionel Sambuc 439*433d6423SLionel Sambuc /*===========================================================================* 440*433d6423SLionel Sambuc * do_subscribe * 441*433d6423SLionel Sambuc *===========================================================================*/ 442*433d6423SLionel Sambuc int do_subscribe(message *m_ptr) 443*433d6423SLionel Sambuc { 444*433d6423SLionel Sambuc char regex[DS_MAX_KEYLEN+2]; 445*433d6423SLionel Sambuc struct subscription *subp; 446*433d6423SLionel Sambuc char errbuf[80]; 447*433d6423SLionel Sambuc char *owner; 448*433d6423SLionel Sambuc int type_set; 449*433d6423SLionel Sambuc int r, e, b; 450*433d6423SLionel Sambuc 451*433d6423SLionel Sambuc /* Find the owner. */ 452*433d6423SLionel Sambuc owner = ds_getprocname(m_ptr->m_source); 453*433d6423SLionel Sambuc if(owner == NULL) 454*433d6423SLionel Sambuc return ESRCH; 455*433d6423SLionel Sambuc 456*433d6423SLionel Sambuc /* See if the owner already has an existing subscription. */ 457*433d6423SLionel Sambuc if((subp = lookup_sub(owner)) == NULL) { 458*433d6423SLionel Sambuc /* The subscription doesn't exist, allocate a new one. */ 459*433d6423SLionel Sambuc if((subp = alloc_sub_slot()) == NULL) 460*433d6423SLionel Sambuc return EAGAIN; 461*433d6423SLionel Sambuc } else if(!(m_ptr->m_ds_req.flags & DSF_OVERWRITE)) { 462*433d6423SLionel Sambuc /* The subscription exists but we can't overwrite, return error. */ 463*433d6423SLionel Sambuc return EEXIST; 464*433d6423SLionel Sambuc } 465*433d6423SLionel Sambuc 466*433d6423SLionel Sambuc /* Copy key name from the caller. Anchor the subscription with "^regexp$" so 467*433d6423SLionel Sambuc * substrings don't match. The caller will probably not expect this, 468*433d6423SLionel Sambuc * and the usual case is for a complete match. 469*433d6423SLionel Sambuc */ 470*433d6423SLionel Sambuc regex[0] = '^'; 471*433d6423SLionel Sambuc if((r = get_key_name(m_ptr, regex+1)) != OK) 472*433d6423SLionel Sambuc return r; 473*433d6423SLionel Sambuc strcat(regex, "$"); 474*433d6423SLionel Sambuc 475*433d6423SLionel Sambuc /* Compile regular expression. */ 476*433d6423SLionel Sambuc if((e=regcomp(&subp->regex, regex, REG_EXTENDED)) != 0) { 477*433d6423SLionel Sambuc regerror(e, &subp->regex, errbuf, sizeof(errbuf)); 478*433d6423SLionel Sambuc printf("DS: subscribe: regerror: %s\n", errbuf); 479*433d6423SLionel Sambuc return EINVAL; 480*433d6423SLionel Sambuc } 481*433d6423SLionel Sambuc 482*433d6423SLionel Sambuc /* If type_set = 0, then subscribe all types. */ 483*433d6423SLionel Sambuc type_set = m_ptr->m_ds_req.flags & DSF_MASK_TYPE; 484*433d6423SLionel Sambuc if(type_set == 0) 485*433d6423SLionel Sambuc type_set = DSF_MASK_TYPE; 486*433d6423SLionel Sambuc 487*433d6423SLionel Sambuc subp->flags = DSF_IN_USE | type_set; 488*433d6423SLionel Sambuc strcpy(subp->owner, owner); 489*433d6423SLionel Sambuc for(b = 0; b < BITMAP_CHUNKS(NR_DS_KEYS); b++) 490*433d6423SLionel Sambuc subp->old_subs[b] = 0; 491*433d6423SLionel Sambuc 492*433d6423SLionel Sambuc /* See if caller requested an instant initial list. */ 493*433d6423SLionel Sambuc if(m_ptr->m_ds_req.flags & DSF_INITIAL) { 494*433d6423SLionel Sambuc int i, match_found = FALSE; 495*433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) { 496*433d6423SLionel Sambuc if(!(ds_store[i].flags & DSF_IN_USE)) 497*433d6423SLionel Sambuc continue; 498*433d6423SLionel Sambuc if(!(ds_store[i].flags & type_set)) 499*433d6423SLionel Sambuc continue; 500*433d6423SLionel Sambuc if(!check_sub_match(subp, &ds_store[i], m_ptr->m_source)) 501*433d6423SLionel Sambuc continue; 502*433d6423SLionel Sambuc 503*433d6423SLionel Sambuc SET_BIT(subp->old_subs, i); 504*433d6423SLionel Sambuc match_found = TRUE; 505*433d6423SLionel Sambuc } 506*433d6423SLionel Sambuc 507*433d6423SLionel Sambuc /* Notify in case of match. */ 508*433d6423SLionel Sambuc if(match_found) 509*433d6423SLionel Sambuc ipc_notify(m_ptr->m_source); 510*433d6423SLionel Sambuc } 511*433d6423SLionel Sambuc 512*433d6423SLionel Sambuc return OK; 513*433d6423SLionel Sambuc } 514*433d6423SLionel Sambuc 515*433d6423SLionel Sambuc /*===========================================================================* 516*433d6423SLionel Sambuc * do_check * 517*433d6423SLionel Sambuc *===========================================================================*/ 518*433d6423SLionel Sambuc int do_check(message *m_ptr) 519*433d6423SLionel Sambuc { 520*433d6423SLionel Sambuc struct subscription *subp; 521*433d6423SLionel Sambuc char *owner; 522*433d6423SLionel Sambuc endpoint_t entry_owner_e; 523*433d6423SLionel Sambuc int r, i; 524*433d6423SLionel Sambuc 525*433d6423SLionel Sambuc /* Find the subscription owner. */ 526*433d6423SLionel Sambuc owner = ds_getprocname(m_ptr->m_source); 527*433d6423SLionel Sambuc if(owner == NULL) 528*433d6423SLionel Sambuc return ESRCH; 529*433d6423SLionel Sambuc 530*433d6423SLionel Sambuc /* Lookup the owner's subscription. */ 531*433d6423SLionel Sambuc if((subp = lookup_sub(owner)) == NULL) 532*433d6423SLionel Sambuc return ESRCH; 533*433d6423SLionel Sambuc 534*433d6423SLionel Sambuc /* Look for an updated entry the subscriber is interested in. */ 535*433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) { 536*433d6423SLionel Sambuc if(GET_BIT(subp->old_subs, i)) 537*433d6423SLionel Sambuc break; 538*433d6423SLionel Sambuc } 539*433d6423SLionel Sambuc if(i == NR_DS_KEYS) 540*433d6423SLionel Sambuc return ENOENT; 541*433d6423SLionel Sambuc 542*433d6423SLionel Sambuc /* Copy the key name. */ 543*433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source, 544*433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0, 545*433d6423SLionel Sambuc (vir_bytes) ds_store[i].key, strlen(ds_store[i].key) + 1); 546*433d6423SLionel Sambuc if(r != OK) { 547*433d6423SLionel Sambuc printf("DS: check: copy failed from %d: %d\n", m_ptr->m_source, r); 548*433d6423SLionel Sambuc return r; 549*433d6423SLionel Sambuc } 550*433d6423SLionel Sambuc 551*433d6423SLionel Sambuc /* Copy the type and the owner of the original entry. */ 552*433d6423SLionel Sambuc entry_owner_e = ds_getprocep(ds_store[i].owner); 553*433d6423SLionel Sambuc m_ptr->m_ds_req.flags = ds_store[i].flags & DSF_MASK_TYPE; 554*433d6423SLionel Sambuc m_ptr->m_ds_req.owner = entry_owner_e; 555*433d6423SLionel Sambuc 556*433d6423SLionel Sambuc /* Mark the entry as no longer updated for the subscriber. */ 557*433d6423SLionel Sambuc UNSET_BIT(subp->old_subs, i); 558*433d6423SLionel Sambuc 559*433d6423SLionel Sambuc return OK; 560*433d6423SLionel Sambuc } 561*433d6423SLionel Sambuc 562*433d6423SLionel Sambuc /*===========================================================================* 563*433d6423SLionel Sambuc * do_delete * 564*433d6423SLionel Sambuc *===========================================================================*/ 565*433d6423SLionel Sambuc int do_delete(message *m_ptr) 566*433d6423SLionel Sambuc { 567*433d6423SLionel Sambuc struct data_store *dsp; 568*433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN]; 569*433d6423SLionel Sambuc char *source; 570*433d6423SLionel Sambuc char *label; 571*433d6423SLionel Sambuc int type = m_ptr->m_ds_req.flags & DSF_MASK_TYPE; 572*433d6423SLionel Sambuc int i, r; 573*433d6423SLionel Sambuc 574*433d6423SLionel Sambuc /* Lookup the source. */ 575*433d6423SLionel Sambuc source = ds_getprocname(m_ptr->m_source); 576*433d6423SLionel Sambuc if(source == NULL) 577*433d6423SLionel Sambuc return EPERM; 578*433d6423SLionel Sambuc 579*433d6423SLionel Sambuc /* Get key name. */ 580*433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK) 581*433d6423SLionel Sambuc return r; 582*433d6423SLionel Sambuc 583*433d6423SLionel Sambuc /* Lookup the entry. */ 584*433d6423SLionel Sambuc if((dsp = lookup_entry(key_name, type)) == NULL) 585*433d6423SLionel Sambuc return ESRCH; 586*433d6423SLionel Sambuc 587*433d6423SLionel Sambuc /* Only the owner can delete. */ 588*433d6423SLionel Sambuc if(strcmp(dsp->owner, source)) 589*433d6423SLionel Sambuc return EPERM; 590*433d6423SLionel Sambuc 591*433d6423SLionel Sambuc switch(type) { 592*433d6423SLionel Sambuc case DSF_TYPE_U32: 593*433d6423SLionel Sambuc break; 594*433d6423SLionel Sambuc case DSF_TYPE_LABEL: 595*433d6423SLionel Sambuc label = dsp->key; 596*433d6423SLionel Sambuc 597*433d6423SLionel Sambuc /* Clean up subscriptions. */ 598*433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) { 599*433d6423SLionel Sambuc if ((ds_subs[i].flags & DSF_IN_USE) 600*433d6423SLionel Sambuc && !strcmp(ds_subs[i].owner, label)) { 601*433d6423SLionel Sambuc ds_subs[i].flags = 0; 602*433d6423SLionel Sambuc } 603*433d6423SLionel Sambuc } 604*433d6423SLionel Sambuc 605*433d6423SLionel Sambuc /* Clean up data entries. */ 606*433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) { 607*433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE) 608*433d6423SLionel Sambuc && !strcmp(ds_store[i].owner, label)) { 609*433d6423SLionel Sambuc update_subscribers(&ds_store[i], 0); 610*433d6423SLionel Sambuc 611*433d6423SLionel Sambuc ds_store[i].flags = 0; 612*433d6423SLionel Sambuc } 613*433d6423SLionel Sambuc } 614*433d6423SLionel Sambuc break; 615*433d6423SLionel Sambuc case DSF_TYPE_STR: 616*433d6423SLionel Sambuc case DSF_TYPE_MEM: 617*433d6423SLionel Sambuc free(dsp->u.mem.data); 618*433d6423SLionel Sambuc break; 619*433d6423SLionel Sambuc default: 620*433d6423SLionel Sambuc return EINVAL; 621*433d6423SLionel Sambuc } 622*433d6423SLionel Sambuc 623*433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */ 624*433d6423SLionel Sambuc update_subscribers(dsp, 0); 625*433d6423SLionel Sambuc 626*433d6423SLionel Sambuc /* Clear the entry. */ 627*433d6423SLionel Sambuc dsp->flags = 0; 628*433d6423SLionel Sambuc 629*433d6423SLionel Sambuc return OK; 630*433d6423SLionel Sambuc } 631*433d6423SLionel Sambuc 632*433d6423SLionel Sambuc /*===========================================================================* 633*433d6423SLionel Sambuc * do_getsysinfo * 634*433d6423SLionel Sambuc *===========================================================================*/ 635*433d6423SLionel Sambuc int do_getsysinfo(const message *m_ptr) 636*433d6423SLionel Sambuc { 637*433d6423SLionel Sambuc vir_bytes src_addr; 638*433d6423SLionel Sambuc size_t length; 639*433d6423SLionel Sambuc int s; 640*433d6423SLionel Sambuc 641*433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) { 642*433d6423SLionel Sambuc case SI_DATA_STORE: 643*433d6423SLionel Sambuc src_addr = (vir_bytes)ds_store; 644*433d6423SLionel Sambuc length = sizeof(struct data_store) * NR_DS_KEYS; 645*433d6423SLionel Sambuc break; 646*433d6423SLionel Sambuc default: 647*433d6423SLionel Sambuc return EINVAL; 648*433d6423SLionel Sambuc } 649*433d6423SLionel Sambuc 650*433d6423SLionel Sambuc if (length != m_ptr->m_lsys_getsysinfo.size) 651*433d6423SLionel Sambuc return EINVAL; 652*433d6423SLionel Sambuc 653*433d6423SLionel Sambuc if (OK != (s=sys_datacopy(SELF, src_addr, 654*433d6423SLionel Sambuc m_ptr->m_source, m_ptr->m_lsys_getsysinfo.where, length))) { 655*433d6423SLionel Sambuc printf("DS: copy failed: %d\n", s); 656*433d6423SLionel Sambuc return s; 657*433d6423SLionel Sambuc } 658*433d6423SLionel Sambuc 659*433d6423SLionel Sambuc return OK; 660*433d6423SLionel Sambuc } 661*433d6423SLionel Sambuc 662