1433d6423SLionel Sambuc #include "inc.h"
2433d6423SLionel Sambuc #include "store.h"
3433d6423SLionel Sambuc
4433d6423SLionel Sambuc /* Allocate space for the data store. */
5433d6423SLionel Sambuc static struct data_store ds_store[NR_DS_KEYS];
6433d6423SLionel Sambuc static struct subscription ds_subs[NR_DS_SUBS];
7433d6423SLionel Sambuc
8433d6423SLionel Sambuc /*===========================================================================*
9433d6423SLionel Sambuc * alloc_data_slot *
10433d6423SLionel Sambuc *===========================================================================*/
alloc_data_slot(void)11433d6423SLionel Sambuc static struct data_store *alloc_data_slot(void)
12433d6423SLionel Sambuc {
13433d6423SLionel Sambuc /* Allocate a new data slot. */
14433d6423SLionel Sambuc int i;
15433d6423SLionel Sambuc
16433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) {
17433d6423SLionel Sambuc if (!(ds_store[i].flags & DSF_IN_USE))
18433d6423SLionel Sambuc return &ds_store[i];
19433d6423SLionel Sambuc }
20433d6423SLionel Sambuc
21433d6423SLionel Sambuc return NULL;
22433d6423SLionel Sambuc }
23433d6423SLionel Sambuc
24433d6423SLionel Sambuc /*===========================================================================*
25433d6423SLionel Sambuc * alloc_sub_slot *
26433d6423SLionel Sambuc *===========================================================================*/
alloc_sub_slot(void)27433d6423SLionel Sambuc static struct subscription *alloc_sub_slot(void)
28433d6423SLionel Sambuc {
29*736b88cfSDavid van Moolenbroek /* Return a free subscription slot. */
30433d6423SLionel Sambuc int i;
31433d6423SLionel Sambuc
32433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) {
33433d6423SLionel Sambuc if (!(ds_subs[i].flags & DSF_IN_USE))
34433d6423SLionel Sambuc return &ds_subs[i];
35433d6423SLionel Sambuc }
36433d6423SLionel Sambuc
37433d6423SLionel Sambuc return NULL;
38433d6423SLionel Sambuc }
39433d6423SLionel Sambuc
40433d6423SLionel Sambuc /*===========================================================================*
41*736b88cfSDavid van Moolenbroek * free_sub_slot *
42*736b88cfSDavid van Moolenbroek *===========================================================================*/
free_sub_slot(struct subscription * subp)43*736b88cfSDavid van Moolenbroek static void free_sub_slot(struct subscription *subp)
44*736b88cfSDavid van Moolenbroek {
45*736b88cfSDavid van Moolenbroek /* Clean up a previously successfully) allocated subscription slot. */
46*736b88cfSDavid van Moolenbroek assert(subp->flags & DSF_IN_USE);
47*736b88cfSDavid van Moolenbroek
48*736b88cfSDavid van Moolenbroek regfree(&subp->regex);
49*736b88cfSDavid van Moolenbroek memset(&subp->regex, 0, sizeof(subp->regex));
50*736b88cfSDavid van Moolenbroek
51*736b88cfSDavid van Moolenbroek subp->flags = 0;
52*736b88cfSDavid van Moolenbroek }
53*736b88cfSDavid van Moolenbroek
54*736b88cfSDavid van Moolenbroek /*===========================================================================*
55433d6423SLionel Sambuc * lookup_entry *
56433d6423SLionel Sambuc *===========================================================================*/
lookup_entry(const char * key_name,int type)57433d6423SLionel Sambuc static struct data_store *lookup_entry(const char *key_name, int type)
58433d6423SLionel Sambuc {
59433d6423SLionel Sambuc /* Lookup an existing entry by key and type. */
60433d6423SLionel Sambuc int i;
61433d6423SLionel Sambuc
62433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) {
63433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE) /* used */
64433d6423SLionel Sambuc && (ds_store[i].flags & type) /* same type*/
65433d6423SLionel Sambuc && !strcmp(ds_store[i].key, key_name)) /* same key*/
66433d6423SLionel Sambuc return &ds_store[i];
67433d6423SLionel Sambuc }
68433d6423SLionel Sambuc
69433d6423SLionel Sambuc return NULL;
70433d6423SLionel Sambuc }
71433d6423SLionel Sambuc
72433d6423SLionel Sambuc /*===========================================================================*
73433d6423SLionel Sambuc * lookup_label_entry *
74433d6423SLionel Sambuc *===========================================================================*/
lookup_label_entry(unsigned num)75433d6423SLionel Sambuc static struct data_store *lookup_label_entry(unsigned num)
76433d6423SLionel Sambuc {
77433d6423SLionel Sambuc /* Lookup an existing label entry by num. */
78433d6423SLionel Sambuc int i;
79433d6423SLionel Sambuc
80433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) {
81433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE)
82433d6423SLionel Sambuc && (ds_store[i].flags & DSF_TYPE_LABEL)
83433d6423SLionel Sambuc && (ds_store[i].u.u32 == num))
84433d6423SLionel Sambuc return &ds_store[i];
85433d6423SLionel Sambuc }
86433d6423SLionel Sambuc
87433d6423SLionel Sambuc return NULL;
88433d6423SLionel Sambuc }
89433d6423SLionel Sambuc
90433d6423SLionel Sambuc /*===========================================================================*
91433d6423SLionel Sambuc * lookup_sub *
92433d6423SLionel Sambuc *===========================================================================*/
lookup_sub(const char * owner)93433d6423SLionel Sambuc static struct subscription *lookup_sub(const char *owner)
94433d6423SLionel Sambuc {
95433d6423SLionel Sambuc /* Lookup an existing subscription given its owner. */
96433d6423SLionel Sambuc int i;
97433d6423SLionel Sambuc
98433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) {
99433d6423SLionel Sambuc if ((ds_subs[i].flags & DSF_IN_USE) /* used */
100433d6423SLionel Sambuc && !strcmp(ds_subs[i].owner, owner)) /* same key*/
101433d6423SLionel Sambuc return &ds_subs[i];
102433d6423SLionel Sambuc }
103433d6423SLionel Sambuc
104433d6423SLionel Sambuc return NULL;
105433d6423SLionel Sambuc }
106433d6423SLionel Sambuc
107433d6423SLionel Sambuc /*===========================================================================*
108433d6423SLionel Sambuc * ds_getprocname *
109433d6423SLionel Sambuc *===========================================================================*/
ds_getprocname(endpoint_t e)110433d6423SLionel Sambuc static char *ds_getprocname(endpoint_t e)
111433d6423SLionel Sambuc {
112433d6423SLionel Sambuc /* Get a process name given its endpoint. */
113433d6423SLionel Sambuc struct data_store *dsp;
114433d6423SLionel Sambuc
115433d6423SLionel Sambuc static char *first_proc_name = "ds";
116433d6423SLionel Sambuc endpoint_t first_proc_ep = DS_PROC_NR;
117433d6423SLionel Sambuc
118433d6423SLionel Sambuc if(e == first_proc_ep)
119433d6423SLionel Sambuc return first_proc_name;
120433d6423SLionel Sambuc
121433d6423SLionel Sambuc if((dsp = lookup_label_entry(e)) != NULL)
122433d6423SLionel Sambuc return dsp->key;
123433d6423SLionel Sambuc
124433d6423SLionel Sambuc return NULL;
125433d6423SLionel Sambuc }
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc /*===========================================================================*
128433d6423SLionel Sambuc * ds_getprocep *
129433d6423SLionel Sambuc *===========================================================================*/
ds_getprocep(const char * s)130433d6423SLionel Sambuc static endpoint_t ds_getprocep(const char *s)
131433d6423SLionel Sambuc {
132433d6423SLionel Sambuc /* Get a process endpoint given its name. */
133433d6423SLionel Sambuc struct data_store *dsp;
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc if((dsp = lookup_entry(s, DSF_TYPE_LABEL)) != NULL)
136433d6423SLionel Sambuc return dsp->u.u32;
137433d6423SLionel Sambuc panic("ds_getprocep: process endpoint not found");
138433d6423SLionel Sambuc }
139433d6423SLionel Sambuc
140433d6423SLionel Sambuc /*===========================================================================*
141433d6423SLionel Sambuc * check_auth *
142433d6423SLionel Sambuc *===========================================================================*/
check_auth(const struct data_store * p,endpoint_t ep,int perm)143433d6423SLionel Sambuc static int check_auth(const struct data_store *p, endpoint_t ep, int perm)
144433d6423SLionel Sambuc {
145433d6423SLionel Sambuc /* Check authorization for a given type of permission. */
146433d6423SLionel Sambuc char *source;
147433d6423SLionel Sambuc
148433d6423SLionel Sambuc if(!(p->flags & perm))
149433d6423SLionel Sambuc return 1;
150433d6423SLionel Sambuc
151433d6423SLionel Sambuc source = ds_getprocname(ep);
152433d6423SLionel Sambuc return source && !strcmp(p->owner, source);
153433d6423SLionel Sambuc }
154433d6423SLionel Sambuc
155433d6423SLionel Sambuc /*===========================================================================*
156433d6423SLionel Sambuc * get_key_name *
157433d6423SLionel Sambuc *===========================================================================*/
get_key_name(const message * m_ptr,char * key_name)158433d6423SLionel Sambuc static int get_key_name(const message *m_ptr, char *key_name)
159433d6423SLionel Sambuc {
160433d6423SLionel Sambuc /* Get key name given an input message. */
161433d6423SLionel Sambuc int r;
162433d6423SLionel Sambuc
163433d6423SLionel Sambuc if (m_ptr->m_ds_req.key_len > DS_MAX_KEYLEN || m_ptr->m_ds_req.key_len < 2) {
164433d6423SLionel Sambuc printf("DS: bogus key length (%d) from %d\n", m_ptr->m_ds_req.key_len,
165433d6423SLionel Sambuc m_ptr->m_source);
166433d6423SLionel Sambuc return EINVAL;
167433d6423SLionel Sambuc }
168433d6423SLionel Sambuc
169433d6423SLionel Sambuc /* Copy name from caller. */
170433d6423SLionel Sambuc r = sys_safecopyfrom(m_ptr->m_source,
171433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, 0,
172433d6423SLionel Sambuc (vir_bytes) key_name, m_ptr->m_ds_req.key_len);
173433d6423SLionel Sambuc if(r != OK) {
174433d6423SLionel Sambuc printf("DS: publish: copy failed from %d: %d\n", m_ptr->m_source, r);
175433d6423SLionel Sambuc return r;
176433d6423SLionel Sambuc }
177433d6423SLionel Sambuc
178433d6423SLionel Sambuc key_name[DS_MAX_KEYLEN-1] = '\0';
179433d6423SLionel Sambuc
180433d6423SLionel Sambuc return OK;
181433d6423SLionel Sambuc }
182433d6423SLionel Sambuc
183433d6423SLionel Sambuc /*===========================================================================*
184433d6423SLionel Sambuc * check_sub_match *
185433d6423SLionel Sambuc *===========================================================================*/
check_sub_match(const struct subscription * subp,struct data_store * dsp,endpoint_t ep)186433d6423SLionel Sambuc static int check_sub_match(const struct subscription *subp,
187433d6423SLionel Sambuc struct data_store *dsp, endpoint_t ep)
188433d6423SLionel Sambuc {
189433d6423SLionel Sambuc /* Check if an entry matches a subscription. Return 1 in case of match. */
190433d6423SLionel Sambuc return (check_auth(dsp, ep, DSF_PRIV_SUBSCRIBE)
191433d6423SLionel Sambuc && regexec(&subp->regex, dsp->key, 0, NULL, 0) == 0)
192433d6423SLionel Sambuc ? 1 : 0;
193433d6423SLionel Sambuc }
194433d6423SLionel Sambuc
195433d6423SLionel Sambuc /*===========================================================================*
196433d6423SLionel Sambuc * update_subscribers *
197433d6423SLionel Sambuc *===========================================================================*/
update_subscribers(struct data_store * dsp,int set)198433d6423SLionel Sambuc static void update_subscribers(struct data_store *dsp, int set)
199433d6423SLionel Sambuc {
200433d6423SLionel Sambuc /* If set = 1, set bit in the sub bitmap of any subscription matching the given
201433d6423SLionel Sambuc * entry, otherwise clear it. In both cases, notify the subscriber.
202433d6423SLionel Sambuc */
203433d6423SLionel Sambuc int i;
204433d6423SLionel Sambuc int nr = dsp - ds_store;
205433d6423SLionel Sambuc endpoint_t ep;
206433d6423SLionel Sambuc
207433d6423SLionel Sambuc for(i = 0; i < NR_DS_SUBS; i++) {
208433d6423SLionel Sambuc if(!(ds_subs[i].flags & DSF_IN_USE))
209433d6423SLionel Sambuc continue;
210433d6423SLionel Sambuc if(!(ds_subs[i].flags & dsp->flags & DSF_MASK_TYPE))
211433d6423SLionel Sambuc continue;
212433d6423SLionel Sambuc
213433d6423SLionel Sambuc ep = ds_getprocep(ds_subs[i].owner);
214433d6423SLionel Sambuc if(!check_sub_match(&ds_subs[i], dsp, ep))
215433d6423SLionel Sambuc continue;
216433d6423SLionel Sambuc
217433d6423SLionel Sambuc if(set == 1) {
218433d6423SLionel Sambuc SET_BIT(ds_subs[i].old_subs, nr);
219433d6423SLionel Sambuc } else {
220433d6423SLionel Sambuc UNSET_BIT(ds_subs[i].old_subs, nr);
221433d6423SLionel Sambuc }
222433d6423SLionel Sambuc ipc_notify(ep);
223433d6423SLionel Sambuc }
224433d6423SLionel Sambuc }
225433d6423SLionel Sambuc
226433d6423SLionel Sambuc /*===========================================================================*
227433d6423SLionel Sambuc * map_service *
228433d6423SLionel Sambuc *===========================================================================*/
map_service(const struct rprocpub * rpub)229433d6423SLionel Sambuc static int map_service(const struct rprocpub *rpub)
230433d6423SLionel Sambuc {
231433d6423SLionel Sambuc /* Map a new service by registering its label. */
232433d6423SLionel Sambuc struct data_store *dsp;
233433d6423SLionel Sambuc
234433d6423SLionel Sambuc /* Allocate a new data slot. */
235433d6423SLionel Sambuc if((dsp = alloc_data_slot()) == NULL) {
236433d6423SLionel Sambuc return ENOMEM;
237433d6423SLionel Sambuc }
238433d6423SLionel Sambuc
239433d6423SLionel Sambuc /* Set attributes. */
240433d6423SLionel Sambuc strcpy(dsp->key, rpub->label);
241433d6423SLionel Sambuc dsp->u.u32 = (u32_t) rpub->endpoint;
242433d6423SLionel Sambuc strcpy(dsp->owner, "rs");
243433d6423SLionel Sambuc dsp->flags = DSF_IN_USE | DSF_TYPE_LABEL;
244433d6423SLionel Sambuc
245433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */
246433d6423SLionel Sambuc update_subscribers(dsp, 1);
247433d6423SLionel Sambuc
248433d6423SLionel Sambuc return(OK);
249433d6423SLionel Sambuc }
250433d6423SLionel Sambuc
251433d6423SLionel Sambuc /*===========================================================================*
252433d6423SLionel Sambuc * sef_cb_init_fresh *
253433d6423SLionel Sambuc *===========================================================================*/
sef_cb_init_fresh(int UNUSED (type),sef_init_info_t * info)254433d6423SLionel Sambuc int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
255433d6423SLionel Sambuc {
256433d6423SLionel Sambuc /* Initialize the data store server. */
257433d6423SLionel Sambuc int i, r;
258433d6423SLionel Sambuc struct rprocpub rprocpub[NR_BOOT_PROCS];
259433d6423SLionel Sambuc
260433d6423SLionel Sambuc /* Reset data store: data and subscriptions. */
261433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) {
262433d6423SLionel Sambuc ds_store[i].flags = 0;
263433d6423SLionel Sambuc }
264433d6423SLionel Sambuc for(i = 0; i < NR_DS_SUBS; i++) {
265433d6423SLionel Sambuc ds_subs[i].flags = 0;
266433d6423SLionel Sambuc }
267433d6423SLionel Sambuc
268433d6423SLionel Sambuc /* Map all the services in the boot image. */
269433d6423SLionel Sambuc if((r = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
270433d6423SLionel Sambuc (vir_bytes) rprocpub, sizeof(rprocpub))) != OK) {
271433d6423SLionel Sambuc panic("sys_safecopyfrom failed: %d", r);
272433d6423SLionel Sambuc }
273433d6423SLionel Sambuc for(i=0;i < NR_BOOT_PROCS;i++) {
274433d6423SLionel Sambuc if(rprocpub[i].in_use) {
275433d6423SLionel Sambuc if((r = map_service(&rprocpub[i])) != OK) {
276433d6423SLionel Sambuc panic("unable to map service: %d", r);
277433d6423SLionel Sambuc }
278433d6423SLionel Sambuc }
279433d6423SLionel Sambuc }
280433d6423SLionel Sambuc
281433d6423SLionel Sambuc return(OK);
282433d6423SLionel Sambuc }
283433d6423SLionel Sambuc
284433d6423SLionel Sambuc /*===========================================================================*
285433d6423SLionel Sambuc * do_publish *
286433d6423SLionel Sambuc *===========================================================================*/
do_publish(message * m_ptr)287433d6423SLionel Sambuc int do_publish(message *m_ptr)
288433d6423SLionel Sambuc {
289433d6423SLionel Sambuc struct data_store *dsp;
290433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN];
291433d6423SLionel Sambuc char *source;
292433d6423SLionel Sambuc int flags = m_ptr->m_ds_req.flags;
293433d6423SLionel Sambuc size_t length;
294433d6423SLionel Sambuc int r;
295433d6423SLionel Sambuc
296433d6423SLionel Sambuc /* Lookup the source. */
297433d6423SLionel Sambuc source = ds_getprocname(m_ptr->m_source);
298433d6423SLionel Sambuc if(source == NULL)
299433d6423SLionel Sambuc return EPERM;
300433d6423SLionel Sambuc
301433d6423SLionel Sambuc /* Only RS can publish labels. */
302433d6423SLionel Sambuc if((flags & DSF_TYPE_LABEL) && m_ptr->m_source != RS_PROC_NR)
303433d6423SLionel Sambuc return EPERM;
304433d6423SLionel Sambuc
305433d6423SLionel Sambuc /* Get key name. */
306433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK)
307433d6423SLionel Sambuc return r;
308433d6423SLionel Sambuc
309433d6423SLionel Sambuc /* Lookup the entry. */
310433d6423SLionel Sambuc dsp = lookup_entry(key_name, flags & DSF_MASK_TYPE);
311433d6423SLionel Sambuc /* If type is LABEL, also try to lookup the entry by num. */
312433d6423SLionel Sambuc if((flags & DSF_TYPE_LABEL) && (dsp == NULL))
313433d6423SLionel Sambuc dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep);
314433d6423SLionel Sambuc
315433d6423SLionel Sambuc if(dsp == NULL) {
316433d6423SLionel Sambuc /* The entry doesn't exist, allocate a new data slot. */
317433d6423SLionel Sambuc if((dsp = alloc_data_slot()) == NULL)
318433d6423SLionel Sambuc return ENOMEM;
319433d6423SLionel Sambuc } else if (flags & DSF_OVERWRITE) {
320433d6423SLionel Sambuc /* Overwrite. */
321433d6423SLionel Sambuc if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_OVERWRITE))
322433d6423SLionel Sambuc return EPERM;
323433d6423SLionel Sambuc } else {
324433d6423SLionel Sambuc /* Don't overwrite and return error. */
325433d6423SLionel Sambuc return EEXIST;
326433d6423SLionel Sambuc }
327433d6423SLionel Sambuc
328433d6423SLionel Sambuc /* Store! */
329433d6423SLionel Sambuc switch(flags & DSF_MASK_TYPE) {
330433d6423SLionel Sambuc case DSF_TYPE_U32:
331433d6423SLionel Sambuc dsp->u.u32 = m_ptr->m_ds_req.val_in.u32;
332433d6423SLionel Sambuc break;
333433d6423SLionel Sambuc case DSF_TYPE_LABEL:
334433d6423SLionel Sambuc dsp->u.u32 = m_ptr->m_ds_req.val_in.ep;
335433d6423SLionel Sambuc break;
336433d6423SLionel Sambuc case DSF_TYPE_STR:
337433d6423SLionel Sambuc case DSF_TYPE_MEM:
338433d6423SLionel Sambuc length = m_ptr->m_ds_req.val_len;
339433d6423SLionel Sambuc /* Allocate a new data buffer if necessary. */
340433d6423SLionel Sambuc if(!(dsp->flags & DSF_IN_USE)) {
341433d6423SLionel Sambuc if((dsp->u.mem.data = malloc(length)) == NULL)
342433d6423SLionel Sambuc return ENOMEM;
343433d6423SLionel Sambuc dsp->u.mem.reallen = length;
344433d6423SLionel Sambuc } else if(length > dsp->u.mem.reallen) {
345433d6423SLionel Sambuc free(dsp->u.mem.data);
346433d6423SLionel Sambuc if((dsp->u.mem.data = malloc(length)) == NULL)
347433d6423SLionel Sambuc return ENOMEM;
348433d6423SLionel Sambuc dsp->u.mem.reallen = length;
349433d6423SLionel Sambuc }
350433d6423SLionel Sambuc
351433d6423SLionel Sambuc /* Copy the memory range. */
352433d6423SLionel Sambuc r = sys_safecopyfrom(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant,
353433d6423SLionel Sambuc 0, (vir_bytes) dsp->u.mem.data, length);
354433d6423SLionel Sambuc if(r != OK) {
355433d6423SLionel Sambuc printf("DS: publish: memory map/copy failed from %d: %d\n",
356433d6423SLionel Sambuc m_ptr->m_source, r);
357433d6423SLionel Sambuc free(dsp->u.mem.data);
358433d6423SLionel Sambuc return r;
359433d6423SLionel Sambuc }
360433d6423SLionel Sambuc dsp->u.mem.length = length;
361433d6423SLionel Sambuc if(flags & DSF_TYPE_STR) {
362433d6423SLionel Sambuc ((char*)dsp->u.mem.data)[length-1] = '\0';
363433d6423SLionel Sambuc }
364433d6423SLionel Sambuc break;
365433d6423SLionel Sambuc default:
366433d6423SLionel Sambuc return EINVAL;
367433d6423SLionel Sambuc }
368433d6423SLionel Sambuc
369433d6423SLionel Sambuc /* Set attributes. */
370433d6423SLionel Sambuc strcpy(dsp->key, key_name);
371433d6423SLionel Sambuc strcpy(dsp->owner, source);
372433d6423SLionel Sambuc dsp->flags = DSF_IN_USE | (flags & DSF_MASK_INTERNAL);
373433d6423SLionel Sambuc
374433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */
375433d6423SLionel Sambuc update_subscribers(dsp, 1);
376433d6423SLionel Sambuc
377433d6423SLionel Sambuc return(OK);
378433d6423SLionel Sambuc }
379433d6423SLionel Sambuc
380433d6423SLionel Sambuc /*===========================================================================*
381433d6423SLionel Sambuc * do_retrieve *
382433d6423SLionel Sambuc *===========================================================================*/
do_retrieve(message * m_ptr)383433d6423SLionel Sambuc int do_retrieve(message *m_ptr)
384433d6423SLionel Sambuc {
385433d6423SLionel Sambuc struct data_store *dsp;
386433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN];
387433d6423SLionel Sambuc int flags = m_ptr->m_ds_req.flags;
388433d6423SLionel Sambuc int type = flags & DSF_MASK_TYPE;
389433d6423SLionel Sambuc size_t length;
390433d6423SLionel Sambuc int r;
391433d6423SLionel Sambuc
392433d6423SLionel Sambuc /* Get key name. */
393433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK)
394433d6423SLionel Sambuc return r;
395433d6423SLionel Sambuc
396433d6423SLionel Sambuc /* Lookup the entry. */
397433d6423SLionel Sambuc if((dsp = lookup_entry(key_name, type)) == NULL)
398433d6423SLionel Sambuc return ESRCH;
399433d6423SLionel Sambuc if(!check_auth(dsp, m_ptr->m_source, DSF_PRIV_RETRIEVE))
400433d6423SLionel Sambuc return EPERM;
401433d6423SLionel Sambuc
402433d6423SLionel Sambuc /* Copy the requested data. */
403433d6423SLionel Sambuc switch(type) {
404433d6423SLionel Sambuc case DSF_TYPE_U32:
405433d6423SLionel Sambuc m_ptr->m_ds_reply.val_out.u32 = dsp->u.u32;
406433d6423SLionel Sambuc break;
407433d6423SLionel Sambuc case DSF_TYPE_LABEL:
408433d6423SLionel Sambuc m_ptr->m_ds_reply.val_out.ep = dsp->u.u32;
409433d6423SLionel Sambuc break;
410433d6423SLionel Sambuc case DSF_TYPE_STR:
411433d6423SLionel Sambuc case DSF_TYPE_MEM:
412433d6423SLionel Sambuc length = MIN(m_ptr->m_ds_req.val_len, dsp->u.mem.length);
413433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source, m_ptr->m_ds_req.val_in.grant, 0,
414433d6423SLionel Sambuc (vir_bytes) dsp->u.mem.data, length);
415433d6423SLionel Sambuc if(r != OK) {
416433d6423SLionel Sambuc printf("DS: retrieve: copy failed to %d: %d\n",
417433d6423SLionel Sambuc m_ptr->m_source, r);
418433d6423SLionel Sambuc return r;
419433d6423SLionel Sambuc }
420433d6423SLionel Sambuc m_ptr->m_ds_reply.val_len = length;
421433d6423SLionel Sambuc break;
422433d6423SLionel Sambuc default:
423433d6423SLionel Sambuc return EINVAL;
424433d6423SLionel Sambuc }
425433d6423SLionel Sambuc
426433d6423SLionel Sambuc return OK;
427433d6423SLionel Sambuc }
428433d6423SLionel Sambuc
429433d6423SLionel Sambuc /*===========================================================================*
430433d6423SLionel Sambuc * do_retrieve_label *
431433d6423SLionel Sambuc *===========================================================================*/
do_retrieve_label(const message * m_ptr)432433d6423SLionel Sambuc int do_retrieve_label(const message *m_ptr)
433433d6423SLionel Sambuc {
434433d6423SLionel Sambuc struct data_store *dsp;
435433d6423SLionel Sambuc int r;
436433d6423SLionel Sambuc
437433d6423SLionel Sambuc /* Lookup the label entry. */
438433d6423SLionel Sambuc if((dsp = lookup_label_entry(m_ptr->m_ds_req.val_in.ep)) == NULL)
439433d6423SLionel Sambuc return ESRCH;
440433d6423SLionel Sambuc
441433d6423SLionel Sambuc /* Copy the key name. */
442433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source,
443433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
444433d6423SLionel Sambuc (vir_bytes) dsp->key, strlen(dsp->key) + 1);
445433d6423SLionel Sambuc if(r != OK) {
446433d6423SLionel Sambuc printf("DS: copy failed from %d: %d\n", m_ptr->m_source, r);
447433d6423SLionel Sambuc return r;
448433d6423SLionel Sambuc }
449433d6423SLionel Sambuc
450433d6423SLionel Sambuc return OK;
451433d6423SLionel Sambuc }
452433d6423SLionel Sambuc
453433d6423SLionel Sambuc /*===========================================================================*
454433d6423SLionel Sambuc * do_subscribe *
455433d6423SLionel Sambuc *===========================================================================*/
do_subscribe(message * m_ptr)456433d6423SLionel Sambuc int do_subscribe(message *m_ptr)
457433d6423SLionel Sambuc {
458433d6423SLionel Sambuc char regex[DS_MAX_KEYLEN+2];
459433d6423SLionel Sambuc struct subscription *subp;
460433d6423SLionel Sambuc char errbuf[80];
461433d6423SLionel Sambuc char *owner;
462433d6423SLionel Sambuc int type_set;
463433d6423SLionel Sambuc int r, e, b;
464433d6423SLionel Sambuc
465433d6423SLionel Sambuc /* Find the owner. */
466433d6423SLionel Sambuc owner = ds_getprocname(m_ptr->m_source);
467433d6423SLionel Sambuc if(owner == NULL)
468433d6423SLionel Sambuc return ESRCH;
469433d6423SLionel Sambuc
470433d6423SLionel Sambuc /* See if the owner already has an existing subscription. */
471*736b88cfSDavid van Moolenbroek if ((subp = lookup_sub(owner)) != NULL) {
472*736b88cfSDavid van Moolenbroek /* If a subscription exists but we can't overwrite, return error. */
473*736b88cfSDavid van Moolenbroek if (!(m_ptr->m_ds_req.flags & DSF_OVERWRITE))
474*736b88cfSDavid van Moolenbroek return EEXIST;
475*736b88cfSDavid van Moolenbroek /* Otherwise just free the old one. */
476*736b88cfSDavid van Moolenbroek free_sub_slot(subp);
477*736b88cfSDavid van Moolenbroek }
478*736b88cfSDavid van Moolenbroek
479*736b88cfSDavid van Moolenbroek /* Find a free subscription slot. */
480433d6423SLionel Sambuc if ((subp = alloc_sub_slot()) == NULL)
481433d6423SLionel Sambuc return EAGAIN;
482433d6423SLionel Sambuc
483433d6423SLionel Sambuc /* Copy key name from the caller. Anchor the subscription with "^regexp$" so
484433d6423SLionel Sambuc * substrings don't match. The caller will probably not expect this,
485433d6423SLionel Sambuc * and the usual case is for a complete match.
486433d6423SLionel Sambuc */
487433d6423SLionel Sambuc regex[0] = '^';
488433d6423SLionel Sambuc if((r = get_key_name(m_ptr, regex+1)) != OK)
489433d6423SLionel Sambuc return r;
490433d6423SLionel Sambuc strcat(regex, "$");
491433d6423SLionel Sambuc
492433d6423SLionel Sambuc /* Compile regular expression. */
493433d6423SLionel Sambuc if((e=regcomp(&subp->regex, regex, REG_EXTENDED)) != 0) {
494433d6423SLionel Sambuc regerror(e, &subp->regex, errbuf, sizeof(errbuf));
495433d6423SLionel Sambuc printf("DS: subscribe: regerror: %s\n", errbuf);
496*736b88cfSDavid van Moolenbroek memset(&subp->regex, 0, sizeof(subp->regex));
497433d6423SLionel Sambuc return EINVAL;
498433d6423SLionel Sambuc }
499433d6423SLionel Sambuc
500433d6423SLionel Sambuc /* If type_set = 0, then subscribe all types. */
501433d6423SLionel Sambuc type_set = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
502433d6423SLionel Sambuc if(type_set == 0)
503433d6423SLionel Sambuc type_set = DSF_MASK_TYPE;
504433d6423SLionel Sambuc
505433d6423SLionel Sambuc subp->flags = DSF_IN_USE | type_set;
506433d6423SLionel Sambuc strcpy(subp->owner, owner);
507433d6423SLionel Sambuc for(b = 0; b < BITMAP_CHUNKS(NR_DS_KEYS); b++)
508433d6423SLionel Sambuc subp->old_subs[b] = 0;
509433d6423SLionel Sambuc
510433d6423SLionel Sambuc /* See if caller requested an instant initial list. */
511433d6423SLionel Sambuc if(m_ptr->m_ds_req.flags & DSF_INITIAL) {
512433d6423SLionel Sambuc int i, match_found = FALSE;
513433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) {
514433d6423SLionel Sambuc if(!(ds_store[i].flags & DSF_IN_USE))
515433d6423SLionel Sambuc continue;
516433d6423SLionel Sambuc if(!(ds_store[i].flags & type_set))
517433d6423SLionel Sambuc continue;
518433d6423SLionel Sambuc if(!check_sub_match(subp, &ds_store[i], m_ptr->m_source))
519433d6423SLionel Sambuc continue;
520433d6423SLionel Sambuc
521433d6423SLionel Sambuc SET_BIT(subp->old_subs, i);
522433d6423SLionel Sambuc match_found = TRUE;
523433d6423SLionel Sambuc }
524433d6423SLionel Sambuc
525433d6423SLionel Sambuc /* Notify in case of match. */
526433d6423SLionel Sambuc if(match_found)
527433d6423SLionel Sambuc ipc_notify(m_ptr->m_source);
528433d6423SLionel Sambuc }
529433d6423SLionel Sambuc
530433d6423SLionel Sambuc return OK;
531433d6423SLionel Sambuc }
532433d6423SLionel Sambuc
533433d6423SLionel Sambuc /*===========================================================================*
534433d6423SLionel Sambuc * do_check *
535433d6423SLionel Sambuc *===========================================================================*/
do_check(message * m_ptr)536433d6423SLionel Sambuc int do_check(message *m_ptr)
537433d6423SLionel Sambuc {
538433d6423SLionel Sambuc struct subscription *subp;
539433d6423SLionel Sambuc char *owner;
540433d6423SLionel Sambuc endpoint_t entry_owner_e;
541433d6423SLionel Sambuc int r, i;
542433d6423SLionel Sambuc
543433d6423SLionel Sambuc /* Find the subscription owner. */
544433d6423SLionel Sambuc owner = ds_getprocname(m_ptr->m_source);
545433d6423SLionel Sambuc if(owner == NULL)
546433d6423SLionel Sambuc return ESRCH;
547433d6423SLionel Sambuc
548433d6423SLionel Sambuc /* Lookup the owner's subscription. */
549433d6423SLionel Sambuc if((subp = lookup_sub(owner)) == NULL)
550433d6423SLionel Sambuc return ESRCH;
551433d6423SLionel Sambuc
552433d6423SLionel Sambuc /* Look for an updated entry the subscriber is interested in. */
553433d6423SLionel Sambuc for(i = 0; i < NR_DS_KEYS; i++) {
554433d6423SLionel Sambuc if(GET_BIT(subp->old_subs, i))
555433d6423SLionel Sambuc break;
556433d6423SLionel Sambuc }
557433d6423SLionel Sambuc if(i == NR_DS_KEYS)
558433d6423SLionel Sambuc return ENOENT;
559433d6423SLionel Sambuc
560433d6423SLionel Sambuc /* Copy the key name. */
561433d6423SLionel Sambuc r = sys_safecopyto(m_ptr->m_source,
562433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_ds_req.key_grant, (vir_bytes) 0,
563433d6423SLionel Sambuc (vir_bytes) ds_store[i].key, strlen(ds_store[i].key) + 1);
564433d6423SLionel Sambuc if(r != OK) {
565433d6423SLionel Sambuc printf("DS: check: copy failed from %d: %d\n", m_ptr->m_source, r);
566433d6423SLionel Sambuc return r;
567433d6423SLionel Sambuc }
568433d6423SLionel Sambuc
569433d6423SLionel Sambuc /* Copy the type and the owner of the original entry. */
570433d6423SLionel Sambuc entry_owner_e = ds_getprocep(ds_store[i].owner);
571433d6423SLionel Sambuc m_ptr->m_ds_req.flags = ds_store[i].flags & DSF_MASK_TYPE;
572433d6423SLionel Sambuc m_ptr->m_ds_req.owner = entry_owner_e;
573433d6423SLionel Sambuc
574433d6423SLionel Sambuc /* Mark the entry as no longer updated for the subscriber. */
575433d6423SLionel Sambuc UNSET_BIT(subp->old_subs, i);
576433d6423SLionel Sambuc
577433d6423SLionel Sambuc return OK;
578433d6423SLionel Sambuc }
579433d6423SLionel Sambuc
580433d6423SLionel Sambuc /*===========================================================================*
581433d6423SLionel Sambuc * do_delete *
582433d6423SLionel Sambuc *===========================================================================*/
do_delete(message * m_ptr)583433d6423SLionel Sambuc int do_delete(message *m_ptr)
584433d6423SLionel Sambuc {
585433d6423SLionel Sambuc struct data_store *dsp;
586433d6423SLionel Sambuc char key_name[DS_MAX_KEYLEN];
587433d6423SLionel Sambuc char *source;
588433d6423SLionel Sambuc char *label;
589433d6423SLionel Sambuc int type = m_ptr->m_ds_req.flags & DSF_MASK_TYPE;
590433d6423SLionel Sambuc int i, r;
591433d6423SLionel Sambuc
592433d6423SLionel Sambuc /* Lookup the source. */
593433d6423SLionel Sambuc source = ds_getprocname(m_ptr->m_source);
594433d6423SLionel Sambuc if(source == NULL)
595433d6423SLionel Sambuc return EPERM;
596433d6423SLionel Sambuc
597433d6423SLionel Sambuc /* Get key name. */
598433d6423SLionel Sambuc if((r = get_key_name(m_ptr, key_name)) != OK)
599433d6423SLionel Sambuc return r;
600433d6423SLionel Sambuc
601433d6423SLionel Sambuc /* Lookup the entry. */
602433d6423SLionel Sambuc if((dsp = lookup_entry(key_name, type)) == NULL)
603433d6423SLionel Sambuc return ESRCH;
604433d6423SLionel Sambuc
605433d6423SLionel Sambuc /* Only the owner can delete. */
606433d6423SLionel Sambuc if(strcmp(dsp->owner, source))
607433d6423SLionel Sambuc return EPERM;
608433d6423SLionel Sambuc
609433d6423SLionel Sambuc switch(type) {
610433d6423SLionel Sambuc case DSF_TYPE_U32:
611433d6423SLionel Sambuc break;
612433d6423SLionel Sambuc case DSF_TYPE_LABEL:
613433d6423SLionel Sambuc label = dsp->key;
614433d6423SLionel Sambuc
615433d6423SLionel Sambuc /* Clean up subscriptions. */
616433d6423SLionel Sambuc for (i = 0; i < NR_DS_SUBS; i++) {
617433d6423SLionel Sambuc if ((ds_subs[i].flags & DSF_IN_USE)
618433d6423SLionel Sambuc && !strcmp(ds_subs[i].owner, label)) {
619*736b88cfSDavid van Moolenbroek free_sub_slot(&ds_subs[i]);
620433d6423SLionel Sambuc }
621433d6423SLionel Sambuc }
622433d6423SLionel Sambuc
623433d6423SLionel Sambuc /* Clean up data entries. */
624433d6423SLionel Sambuc for (i = 0; i < NR_DS_KEYS; i++) {
625433d6423SLionel Sambuc if ((ds_store[i].flags & DSF_IN_USE)
626433d6423SLionel Sambuc && !strcmp(ds_store[i].owner, label)) {
627433d6423SLionel Sambuc update_subscribers(&ds_store[i], 0);
628433d6423SLionel Sambuc
629433d6423SLionel Sambuc ds_store[i].flags = 0;
630433d6423SLionel Sambuc }
631433d6423SLionel Sambuc }
632433d6423SLionel Sambuc break;
633433d6423SLionel Sambuc case DSF_TYPE_STR:
634433d6423SLionel Sambuc case DSF_TYPE_MEM:
635433d6423SLionel Sambuc free(dsp->u.mem.data);
636433d6423SLionel Sambuc break;
637433d6423SLionel Sambuc default:
638433d6423SLionel Sambuc return EINVAL;
639433d6423SLionel Sambuc }
640433d6423SLionel Sambuc
641433d6423SLionel Sambuc /* Update subscribers having a matching subscription. */
642433d6423SLionel Sambuc update_subscribers(dsp, 0);
643433d6423SLionel Sambuc
644433d6423SLionel Sambuc /* Clear the entry. */
645433d6423SLionel Sambuc dsp->flags = 0;
646433d6423SLionel Sambuc
647433d6423SLionel Sambuc return OK;
648433d6423SLionel Sambuc }
649433d6423SLionel Sambuc
650433d6423SLionel Sambuc /*===========================================================================*
651433d6423SLionel Sambuc * do_getsysinfo *
652433d6423SLionel Sambuc *===========================================================================*/
do_getsysinfo(const message * m_ptr)653433d6423SLionel Sambuc int do_getsysinfo(const message *m_ptr)
654433d6423SLionel Sambuc {
655433d6423SLionel Sambuc vir_bytes src_addr;
656433d6423SLionel Sambuc size_t length;
657433d6423SLionel Sambuc int s;
658433d6423SLionel Sambuc
659433d6423SLionel Sambuc switch(m_ptr->m_lsys_getsysinfo.what) {
660433d6423SLionel Sambuc case SI_DATA_STORE:
661433d6423SLionel Sambuc src_addr = (vir_bytes)ds_store;
662433d6423SLionel Sambuc length = sizeof(struct data_store) * NR_DS_KEYS;
663433d6423SLionel Sambuc break;
664433d6423SLionel Sambuc default:
665433d6423SLionel Sambuc return EINVAL;
666433d6423SLionel Sambuc }
667433d6423SLionel Sambuc
668433d6423SLionel Sambuc if (length != m_ptr->m_lsys_getsysinfo.size)
669433d6423SLionel Sambuc return EINVAL;
670433d6423SLionel Sambuc
671433d6423SLionel Sambuc if (OK != (s=sys_datacopy(SELF, src_addr,
672433d6423SLionel Sambuc m_ptr->m_source, m_ptr->m_lsys_getsysinfo.where, length))) {
673433d6423SLionel Sambuc printf("DS: copy failed: %d\n", s);
674433d6423SLionel Sambuc return s;
675433d6423SLionel Sambuc }
676433d6423SLionel Sambuc
677433d6423SLionel Sambuc return OK;
678433d6423SLionel Sambuc }
679433d6423SLionel Sambuc
680