L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
name_space_svr
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4 * Alexander Warg <warg@os.inf.tu-dresden.de>
5 * economic rights: Technische Universität Dresden (Germany)
6 *
7 * License: see LICENSE.spdx (in this directory or the directories above)
8 */
9#pragma once
10
11#include <l4/cxx/avl_tree>
12#include <l4/cxx/std_ops>
13#include <l4/sys/cxx/ipc_epiface>
14#include <l4/cxx/string>
15#include <l4/re/util/debug>
16
17#include <l4/sys/capability>
18#include <l4/re/namespace>
19
20#include <stddef.h>
21#include <string.h>
22
23namespace L4Re { namespace Util { namespace Names {
24
28class Name : public cxx::String
29{
30public:
31
32 Name(const char *name = "") : String(name, __builtin_strlen(name)) {}
33 Name(const char *name, unsigned long len) : String(name, len) {}
34 Name(cxx::String const &n) : String(n) {}
35 char const *name() const { return start(); }
36 bool operator < (Name const &r) const
37 {
38 unsigned long l = cxx::min(len(), r.len());
39 int v = memcmp(start(), r.start(), l);
40 return v < 0 || (v == 0 && len() < r.len());
41 }
42};
43
44
48class Obj
49{
50protected:
51 unsigned _f;
52 union
53 {
54 l4_cap_idx_t _cap;
55 L4::Epiface *_obj;
56 };
57
58
59public:
60 enum Flags
61 {
63 F_strong = L4Re::Namespace::Strong,
64
65 F_trusted = L4Re::Namespace::Trusted,
66
67 F_rights_mask = F_rw | F_strong | F_trusted,
68
69 F_cap = 0x100,
70 F_local = 0x200,
71 F_replacable = 0x400,
72 F_base_mask = 0xf00,
73 };
74
75
76 unsigned flags() const { return _f; }
77 void restrict_flags(unsigned max_rights)
78 { _f &= (~F_rights_mask | (max_rights & F_rights_mask)); }
79
80 bool is_rw() const { return (_f & F_rw) == F_rw; }
81 bool is_strong() const { return _f & F_strong; }
82
83 bool is_valid() const { return _f & F_cap; }
84 bool is_complete() const { return is_valid(); }
85 bool is_local() const { return _f & F_local; }
86 bool is_replacable() const { return _f & F_replacable; }
87 bool is_trusted() const { return _f & F_trusted; }
88
89 L4::Epiface *obj() const { if (is_local()) return _obj; return 0; }
90 L4::Cap<void> cap() const
91 {
92 if (!is_local())
93 return L4::Cap<void>(_cap);
94 if (!_obj)
96 return _obj->obj_cap();
97 }
98
99
100 void set(Obj const &o, unsigned flags)
101 {
102 *this = o;
103 restrict_flags(flags);
104 }
105
106 explicit Obj(unsigned flags = 0)
107 : _f(flags), _cap(L4_INVALID_CAP)
108 {}
109
110 Obj(unsigned f, L4::Cap<void> const &cap)
111 : _f((f & ~F_base_mask) | F_cap), _cap(cap.cap())
112 {}
113
114 Obj(unsigned f, L4::Epiface *o)
115 : _f((f & ~F_base_mask) | F_cap | F_local), _obj(o)
116 {}
117
118 void reset(unsigned flags)
119 {
120 _f = (_f & F_replacable) | (flags & ~(F_cap | F_local));
121 _cap = L4_INVALID_CAP;
122 }
123
124
125};
126
127
131class Entry : public cxx::Avl_tree_node
132{
133private:
134 friend class Name_space;
135 Name _n;
136 Obj _o;
137
138 bool _dynamic;
139
140public:
141 Entry(Name const &n, Obj const &o, bool dynamic = false)
142 : _n(n), _o(o), _dynamic(dynamic) {}
143
144 Name const &name() const { return _n; }
145 Obj const *obj() const { return &_o; }
146 Obj *obj() { return &_o; }
147 void obj(Obj const &o) { _o = o; }
148
149 bool is_placeholder() const
150 { return !obj()->is_complete(); }
151
152 bool is_dynamic() const { return _dynamic; }
153
154 void set(Obj const &o)
155 {
156 obj()->set(o, obj()->flags());
157 }
158
159private:
160 void * operator new (size_t s);
161 void operator delete(void *b);
162
163};
164
165struct Names_get_key
166{
167 typedef Name Key_type;
168 static Key_type const &key_of(Entry const *e)
169 { return e->name(); }
170};
171
172
180class Name_space
181{
182 friend class Entry;
183
184private:
186 Tree _tree;
187
188protected:
189 L4Re::Util::Dbg const &_dbg;
190 L4Re::Util::Err const &_err;
191
192public:
193
194 typedef Tree::Const_iterator Const_iterator;
195
196 Const_iterator begin() const { return _tree.begin(); }
197 Const_iterator end() const { return _tree.end(); }
198
199 Name_space(L4Re::Util::Dbg const &dbg, L4Re::Util::Err const &err)
200 : _dbg(dbg), _err(err)
201 {}
202
206 virtual ~Name_space() {}
207
208 Entry *find(Name const &name) const { return _tree.find_node(name); }
209 Entry *remove(Name const &name) { return _tree.remove(name); }
210 Entry *find_iter(Name const &pname) const
211 {
212 Name name = pname;
213 _dbg.printf("resolve '%.*s': ", name.len(), name.start());
214 Name_space const *ns = this;
215 while (ns)
216 {
217 cxx::String::Index sep = name.find("/");
218 cxx::String part;
219 if (!name.eof(sep))
220 part = name.head(sep);
221 else
222 part = name;
223
224 _dbg.cprintf(" '%.*s'", part.len(), part.start());
225 Entry *o = ns->find(Name(part.start(), part.len()));
226
227 if (!o)
228 {
229 _dbg.cprintf(": resolution failed: '%.*s' remaining\n",
230 name.len(), name.start());
231 return 0;
232 }
233
234 auto const *obj = o->obj()->obj();
235 ns = dynamic_cast<Name_space const *>(obj);
236 if (ns)
237 {
238 if (!name.eof(sep))
239 {
240 name = name.substr(sep + 1);
241 continue;
242 }
243 }
244
245 _dbg.cprintf(": found object: %p (%s)\n",
246 obj, obj ? typeid(*obj).name() : "");
247
248 return o;
249 }
250
251 return 0;
252 }
253
254 bool insert(Entry *e) { return _tree.insert(e).second; }
255
256 void dump(bool rec = false, int indent = 0) const;
257
258protected:
259 // server support --------------------------------------------
272 virtual Entry *alloc_dynamic_entry(Name const &n, unsigned flags) = 0;
273
279 virtual void free_dynamic_entry(Entry *e) = 0;
280
303 virtual l4_ret_t get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo) = 0;
304
318
327 virtual void free_capability(L4::Cap<void> cap) = 0;
328
337 virtual void free_epiface(L4::Epiface *epiface) = 0;
338
339 l4_ret_t insert_entry(Name const &name, unsigned flags, Entry **e)
340 {
341 Entry *n = find(name);
342 if (n && n->obj()->is_valid())
343 {
344 if (!(flags & L4Re::Namespace::Overwrite)
345 && n->obj()->cap().validate(L4_BASE_TASK_CAP).label() > 0)
346 return -L4_EEXIST;
347
348 if (!n->is_dynamic() && !n->obj()->is_replacable())
349 return -L4_EEXIST;
350
351 if (n->obj()->is_local())
352 free_epiface(n->obj()->obj());
353 else
354 free_capability(n->obj()->cap());
355
356 if (n->is_dynamic())
357 {
358 remove(n->name());
360 n = 0;
361 }
362 else
363 n->obj()->reset(Obj::F_rw);
364 }
365
366 flags &= L4Re::Namespace::Cap_flags;
367 if (!n)
368 {
369 if (!(n = alloc_dynamic_entry(name, flags)))
370 return -L4_ENOMEM;
371 else
372 {
373 if (!insert(n))
374 {
376 return -L4_EEXIST;
377 }
378 }
379 }
380
381 *e = n;
382 return 0;
383 }
384
385public:
386 // server interface ------------------------------------------
387 l4_ret_t op_query(L4Re::Namespace::Rights,
391 {
392#if 1
393 _dbg.printf("query: [%ld] '%.*s'\n", name.length,
394 static_cast<int>(name.length), name.data);
395#endif
396
397 char const *sep
398 = static_cast<char const*>(memchr(name.data, '/', name.length));
399 unsigned long part;
400 if (sep)
401 part = sep - name.data;
402 else
403 part = name.length;
404
405 Entry *n = find(Name(name.data, part));
406 if (!n)
407 return -L4_ENOENT;
408 else if (!n->obj()->is_valid())
409 return -L4_EAGAIN;
410 else
411 {
412 if (n->obj()->cap().validate(L4_BASE_TASK_CAP).label() <= 0)
413 {
414 if (n->obj()->is_local())
415 free_epiface(n->obj()->obj());
416 else
417 free_capability(n->obj()->cap());
418
419 if (n->is_dynamic())
420 {
421 remove(n->name());
423 }
424 return -L4_ENOENT;
425 }
426
427 // make picky clients happy
428 dummy.set_valid();
429 // prevent warning about writing uninitialized data in IPC framework
430 dummy = 0;
431
432 l4_ret_t result = 0;
433
434 out_name.set_valid();
435 if (part < name.length)
436 {
438 memcpy(out_name->data, name.data + part + 1, name.length - part - 1);
439 out_name->length = name.length - part - 1;
440 }
441 else
442 out_name->length = 0;
443
444 unsigned flags = L4_CAP_FPAGE_R;
445 if (n->obj()->is_rw()) flags |= L4_CAP_FPAGE_W;
446 if (n->obj()->is_strong()) flags |= L4_CAP_FPAGE_S;
447
448 snd_cap = L4::Ipc::Snd_fpage(n->obj()->cap(), flags);
449 _dbg.printf(" result = %x flgs=%x strg=%d\n",
450 result, flags, static_cast<int>(n->obj()->is_strong()));
451 return result;
452 }
453 }
454
455 l4_ret_t op_register_obj(L4Re::Namespace::Rights, unsigned flags,
456 L4::Ipc::Array_in_buf<char, unsigned long> const &name,
457 L4::Ipc::Snd_fpage &cap)
458 {
459 if (name.length == 0 || memchr(name.data, '/', name.length))
460 return -L4_EINVAL;
461
462 L4::Cap<void> reg_cap(L4_INVALID_CAP);
463 L4::Epiface *src_o = 0;
464
465 // Did we receive something we have handed out ourselves? If yes,
466 // register the object under the given name but do not allocate
467 // anything more.
468 if (cap.id_received() || cap.local_id_received())
469 {
470 if (l4_ret_t ret = get_epiface(cap.data(), cap.local_id_received(), &src_o))
471 return ret;
472
473 // Make sure rights are restricted to the mapped rights.
474 flags &= (cap.data() & 0x3UL) | ~0x3UL;
475 }
476 else if (cap.cap_received())
477 {
478 if (l4_ret_t ret = copy_receive_cap(&reg_cap))
479 return ret;
480 }
481 else if (!cap.is_valid())
482 {
483 reg_cap = L4::Cap<void>::Invalid;
484 }
485 else
486 return -L4_EINVAL;
487
488 // got a valid entry to register
489 _dbg.printf("register: '%.*s' flags=%x\n", static_cast<int>(name.length),
490 name.data, flags);
491
492 Name _name(name.data, name.length);
493
494 Entry *n;
495 if (l4_ret_t r = insert_entry(_name, flags, &n))
496 {
497 if (cap.cap_received())
498 free_capability(reg_cap);
499 if (src_o)
500 free_epiface(src_o);
501
502 return r;
503 }
504
505 if (src_o)
506 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, src_o));
507 else if (reg_cap.is_valid())
508 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, reg_cap));
509
510 return 0;
511 }
512
513 l4_ret_t op_unlink(L4Re::Namespace::Rights,
514 L4::Ipc::Array_in_buf<char, unsigned long> const &name)
515
516 {
517#if 1
518 _dbg.printf("unlink: [%ld] '%.*s'\n", name.length,
519 static_cast<int>(name.length), name.data);
520#endif
521
522 char const *sep
523 = static_cast<char const*>(memchr(name.data, '/', name.length));
524 unsigned long part;
525 if (sep)
526 part = sep - name.data;
527 else
528 part = name.length;
529
530 Entry *n = find(Name(name.data, part));
531 if (!n || !n->obj()->is_valid())
532 return -L4_ENOENT;
533
534 if (!n->is_dynamic())
535 return -L4_EACCESS;
536
537 if (n->obj()->is_local())
538 free_epiface(n->obj()->obj());
539 else
540 free_capability(n->obj()->cap());
541
542 remove(n->name());
544
545 return 0;
546 }
547};
548
549}}}
550
AVL tree.
L4::Cap related definitions.
@ Partly_resolved
Name was only partly resolved.
Definition namespace:79
@ Trusted
Obsolete, do not use.
Definition namespace:64
@ Overwrite
If entry already exists, overwrite it.
Definition namespace:69
@ Strong
Strong.
Definition namespace:63
@ Rw
Read-write.
Definition namespace:60
virtual l4_ret_t get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo)=0
Return a pointer to the epiface assigned to a given label.
virtual void free_dynamic_entry(Entry *e)=0
Free an entry previously allocated with alloc_dynamic_entry().
virtual l4_ret_t copy_receive_cap(L4::Cap< void > *cap)=0
Return the receive capability for permanent use.
virtual Entry * alloc_dynamic_entry(Name const &n, unsigned flags)=0
Allocate a new entry for the given name.
virtual ~Name_space()
The destructor of the derived class is responsible for freeing resources.
virtual void free_capability(L4::Cap< void > cap)=0
Free a capability previously acquired with copy_receive_cap().
virtual void free_epiface(L4::Epiface *epiface)=0
Free epiface previously acquired with get_epiface().
@ Invalid
Invalid capability selector.
Definition capability.h:42
C++ interface for capabilities.
Definition capability.h:249
l4_umword_t data() const noexcept
Return the raw flexpage descriptor.
Definition ipc_types:280
Send item or return item.
Definition ipc_types:300
bool id_received() const noexcept
(Defined for return items only.) Check if an IPC gate label has been received instead of a mapping.
Definition ipc_types:488
bool local_id_received() const noexcept
(Defined for return items only.) Check if a raw object flexpage has been received instead of a mappin...
Definition ipc_types:504
bool is_valid() const noexcept
Check if the capability is valid.
Definition ipc_types:456
bool cap_received() const noexcept
(Defined for return items only.) Check if at least one object capability has been mapped for this ite...
Definition ipc_types:472
A generic AVL tree.
Definition avl_tree:101
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition avl_tree:282
Bst::Const_iterator Const_iterator
Definition avl_tree:132
Node * find_node(Key_param_type key) const
find the node with the given key.
Definition bst.h:278
Allocation free string class with explicit length field.
Definition string:33
Index start() const
Pointer to first character.
Definition string:56
String head(Index end) const
Return prefix up to index.
Definition string:70
char const * Index
Character index type.
Definition string:37
int len() const
Length.
Definition string:60
String()
Zero-initialize. Create an invalid string.
Definition string:53
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:374
#define L4_INVALID_CAP
Invalid capability selector; see l4_cap_idx_t.
Definition consts.h:165
@ L4_BASE_TASK_CAP
Capability index for the current task.
Definition consts.h:344
@ L4_EEXIST
Already exists.
Definition err.h:44
@ L4_ENOENT
No such entity.
Definition err.h:35
@ L4_EACCESS
Permission denied.
Definition err.h:41
@ L4_EINVAL
Invalid argument.
Definition err.h:47
@ L4_EAGAIN
Try again.
Definition err.h:39
@ L4_ENOMEM
No memory.
Definition err.h:40
@ L4_CAP_FPAGE_R
Read right for capability flexpages.
Definition __l4_fpage.h:175
@ L4_CAP_FPAGE_W
Interface specific 'W' right for capability flexpages.
Definition __l4_fpage.h:157
@ L4_CAP_FPAGE_S
Interface specific 'S' right for capability flexpages.
Definition __l4_fpage.h:169
l4_int16_t l4_ret_t
Return value of an IPC call as well as an RPC call.
Definition types.h:29
Documentation of the L4 Runtime Environment utility functionality in C++.
Definition l4re.dox:21
L4Re C++ Interfaces.
Definition cmd_control:14
Namespace interface.
String.
Base class for interface implementations.
Definition ipc_epiface:264
Server-side copy in buffer for Array.
Definition ipc_array:127
LEN_TYPE length
The length of the array.
Definition ipc_array:134
ELEM_TYPE data[MAX]
The data elements.
Definition ipc_array:132
Array reference data type for arrays located in the message.
Definition ipc_array:29
Attribute for defining an optional RPC argument.
Definition ipc_types:81
void set_valid(bool valid=true) noexcept
Set the argument to present or absent.
Definition ipc_types:100