L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
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 int get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo) = 0;
304
317 virtual int copy_receive_cap(L4::Cap<void> *cap) = 0;
318
327 virtual void free_capability(L4::Cap<void> cap) = 0;
328
337 virtual void free_epiface(L4::Epiface *epiface) = 0;
338
339 int 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->obj()->is_local())
349 free_epiface(n->obj()->obj());
350 else
351 free_capability(n->obj()->cap());
352
353 if (n->is_dynamic())
354 {
355 remove(n->name());
357 n = 0;
358 }
359 else
360 {
361 if (!n->obj()->is_replacable())
362 return -L4_EEXIST;
363 n->obj()->reset(Obj::F_rw);
364 }
365 }
366
367 flags &= L4Re::Namespace::Cap_flags;
368 if (!n)
369 {
370 if (!(n = alloc_dynamic_entry(name, flags)))
371 return -L4_ENOMEM;
372 else
373 {
374 if (!insert(n))
375 {
377 return -L4_EEXIST;
378 }
379 }
380 }
381
382 *e = n;
383 return 0;
384 }
385
386public:
387 // server interface ------------------------------------------
388 int op_query(L4Re::Namespace::Rights,
392 {
393#if 1
394 _dbg.printf("query: [%ld] '%.*s'\n", name.length,
395 static_cast<int>(name.length), name.data);
396#endif
397
398 char const *sep
399 = static_cast<char const*>(memchr(name.data, '/', name.length));
400 unsigned long part;
401 if (sep)
402 part = sep - name.data;
403 else
404 part = name.length;
405
406 Entry *n = find(Name(name.data, part));
407 if (!n)
408 return -L4_ENOENT;
409 else if (!n->obj()->is_valid())
410 return -L4_EAGAIN;
411 else
412 {
413 if (n->obj()->cap().validate(L4_BASE_TASK_CAP).label() <= 0)
414 {
415 if (n->obj()->is_local())
416 free_epiface(n->obj()->obj());
417 else
418 free_capability(n->obj()->cap());
419
420 if (n->is_dynamic())
421 {
422 remove(n->name());
424 }
425 return -L4_ENOENT;
426 }
427
428 // make picky clients happy
429 dummy.set_valid();
430 // prevent warning about writing uninitialized data in IPC framework
431 dummy = 0;
432
433 l4_umword_t result = 0;
434
435 out_name.set_valid();
436 if (part < name.length)
437 {
439 memcpy(out_name->data, name.data + part + 1, name.length - part - 1);
440 out_name->length = name.length - part - 1;
441 }
442 else
443 out_name->length = 0;
444
445 unsigned flags = L4_CAP_FPAGE_R;
446 if (n->obj()->is_rw()) flags |= L4_CAP_FPAGE_W;
447 if (n->obj()->is_strong()) flags |= L4_CAP_FPAGE_S;
448
449 snd_cap = L4::Ipc::Snd_fpage(n->obj()->cap(), flags);
450 _dbg.printf(" result = %lx flgs=%x strg=%d\n",
451 result, flags, static_cast<int>(n->obj()->is_strong()));
452 return result;
453 }
454 }
455
456 int op_register_obj(L4Re::Namespace::Rights, unsigned flags,
459 {
460 if (name.length == 0 || memchr(name.data, '/', name.length))
461 return -L4_EINVAL;
462
464 L4::Epiface *src_o = 0;
465
466 // Did we receive something we have handed out ourselves? If yes,
467 // register the object under the given name but do not allocate
468 // anything more.
469 if (cap.id_received() || cap.local_id_received())
470 {
471 if (int ret = get_epiface(cap.data(), cap.local_id_received(), &src_o))
472 return ret;
473
474 // Make sure rights are restricted to the mapped rights.
475 flags &= (cap.data() & 0x3UL) | ~0x3UL;
476 }
477 else if (cap.cap_received())
478 {
479 if (int ret = copy_receive_cap(&reg_cap))
480 return ret;
481 }
482 else if (!cap.is_valid())
483 {
484 reg_cap = L4::Cap<void>::Invalid;
485 }
486 else
487 return -L4_EINVAL;
488
489 // got a valid entry to register
490 _dbg.printf("register: '%.*s' flags=%x\n", static_cast<int>(name.length),
491 name.data, flags);
492
493 Name _name(name.data, name.length);
494
495 Entry *n;
496 if (int r = insert_entry(_name, flags, &n))
497 {
498 if (cap.cap_received())
499 free_capability(reg_cap);
500 if (src_o)
501 free_epiface(src_o);
502
503 return r;
504 }
505
506 if (src_o)
507 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, src_o));
508 else if (reg_cap.is_valid())
509 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, reg_cap));
510
511 return 0;
512 }
513
514 int op_unlink(L4Re::Namespace::Rights,
516
517 {
518#if 1
519 _dbg.printf("unlink: [%ld] '%.*s'\n", name.length,
520 static_cast<int>(name.length), name.data);
521#endif
522
523 char const *sep
524 = static_cast<char const*>(memchr(name.data, '/', name.length));
525 unsigned long part;
526 if (sep)
527 part = sep - name.data;
528 else
529 part = name.length;
530
531 Entry *n = find(Name(name.data, part));
532 if (!n || !n->obj()->is_valid())
533 return -L4_ENOENT;
534
535 if (n->obj()->is_local())
536 free_epiface(n->obj()->obj());
537 else
538 free_capability(n->obj()->cap());
539
540 if (n->is_dynamic())
541 {
542 remove(n->name());
544 }
545 else
546 return -L4_EACCESS;
547
548 return 0;
549 }
550};
551
552}}}
553
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
Abstract server-side implementation of the L4::Namespace interface.
virtual void free_dynamic_entry(Entry *e)=0
Free an entry previously allocated with alloc_dynamic_entry().
virtual int 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 Entry * alloc_dynamic_entry(Name const &n, unsigned flags)=0
Allocate a new entry for the given name.
virtual int copy_receive_cap(L4::Cap< void > *cap)=0
Return the receive capability for permanent use.
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().
C++ interface for capabilities.
Definition capability.h:219
l4_umword_t data() const noexcept
Return the raw flexpage descriptor.
Definition ipc_types:304
Send item or return item.
Definition ipc_types:324
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:512
bool local_id_received() const noexcept
*(Defined for return items only.)* Check if a raw object flexpage has been received instead of a mapp...
Definition ipc_types:528
bool is_valid() const noexcept
Check if the capability is valid.
Definition ipc_types:480
bool cap_received() const noexcept
*(Defined for return items only.)* Check if at least one object capability has been mapped for this i...
Definition ipc_types:496
Node of an AVL tree.
Definition avl_tree:30
A generic AVL tree.
Definition avl_tree:101
Pair< Node *, bool > insert(Node *new_node)
Insert a new node into this AVL tree.
Definition avl_tree:220
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition avl_tree:282
Bst::Const_iterator Const_iterator
Constant forward iterator for the tree.
Definition avl_tree:132
Node * find_node(Key_param_type key) const
find the node with the given key.
Definition bst.h:269
Const_iterator end() const
Get the end marker for the constant forward iterator.
Definition bst.h:177
Const_iterator begin() const
Get the constant forward iterator for the first element in the set.
Definition bst.h:172
Allocation free string class with explicit length field.
Definition string:31
Index start() const
Pointer to first character.
Definition string:54
String head(Index end) const
Return prefix up to index.
Definition string:68
char const * Index
Character index type.
Definition string:35
int len() const
Length.
Definition string:58
String()
Zero-initialize. Create an invalid string.
Definition string:51
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:335
@ L4_BASE_TASK_CAP
Capability selector for the current task.
Definition consts.h:331
@ L4_INVALID_CAP
Invalid capability selector.
Definition consts.h:157
@ L4_EEXIST
Already exists.
Definition err.h:43
@ L4_ENOENT
No such entity.
Definition err.h:34
@ L4_EACCESS
Permission denied.
Definition err.h:40
@ L4_EINVAL
Invalid argument.
Definition err.h:46
@ L4_EAGAIN
Try again.
Definition err.h:38
@ L4_ENOMEM
No memory.
Definition err.h:39
@ 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
L4Re C++ Interfaces.
Definition cmd_control:14
Namespace interface.
String.
Base class for interface implementations.
Definition ipc_epiface:146
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:137
void set_valid(bool valid=true) noexcept
Set the argument to present or absent.
Definition ipc_types:156