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 * This file is part of TUD:OS and distributed under the terms of the
8 * GNU General Public License 2.
9 * Please see the COPYING-GPL-2 file for details.
10 *
11 * As a special exception, you may use this file as part of a free software
12 * library without restriction. Specifically, if other files instantiate
13 * templates or use macros or inline functions from this file, or you compile
14 * this file and link it with other files to produce an executable, this
15 * file does not by itself cause the resulting executable to be covered by
16 * the GNU General Public License. This exception does not however
17 * invalidate any other reasons why the executable file might be covered by
18 * the GNU General Public License.
19 */
20#pragma once
21
22#include <l4/cxx/avl_tree>
23#include <l4/cxx/std_ops>
24#include <l4/sys/cxx/ipc_epiface>
25#include <l4/cxx/string>
26#include <l4/re/util/debug>
27
28#include <l4/sys/capability>
29#include <l4/re/namespace>
30
31#include <cstddef>
32#include <cstring>
33
34namespace L4Re { namespace Util { namespace Names {
35
39class Name : public cxx::String
40{
41public:
42
43 Name(const char *name = "") : String(name, __builtin_strlen(name)) {}
44 Name(const char *name, unsigned long len) : String(name, len) {}
45 Name(cxx::String const &n) : String(n) {}
46 char const *name() const { return start(); }
47 bool operator < (Name const &r) const
48 {
49 unsigned long l = cxx::min(len(), r.len());
50 int v = memcmp(start(), r.start(), l);
51 return v < 0 || (v == 0 && len() < r.len());
52 }
53};
54
55
59class Obj
60{
61protected:
62 unsigned _f;
63 union
64 {
65 l4_cap_idx_t _cap;
66 L4::Epiface *_obj;
67 };
68
69
70public:
71 enum Flags
72 {
74 F_strong = L4Re::Namespace::Strong,
75
76 F_trusted = L4Re::Namespace::Trusted,
77
78 F_rights_mask = F_rw | F_strong | F_trusted,
79
80 F_cap = 0x100,
81 F_local = 0x200,
82 F_replacable = 0x400,
83 F_base_mask = 0xf00,
84 };
85
86
87 unsigned flags() const { return _f; }
88 void restrict_flags(unsigned max_rights)
89 { _f &= (~F_rights_mask | (max_rights & F_rights_mask)); }
90
91 bool is_rw() const { return (_f & F_rw) == F_rw; }
92 bool is_strong() const { return _f & F_strong; }
93
94 bool is_valid() const { return _f & F_cap; }
95 bool is_complete() const { return is_valid(); }
96 bool is_local() const { return _f & F_local; }
97 bool is_replacable() const { return _f & F_replacable; }
98 bool is_trusted() const { return _f & F_trusted; }
99
100 L4::Epiface *obj() const { if (is_local()) return _obj; return 0; }
101 L4::Cap<void> cap() const
102 {
103 if (!is_local())
104 return L4::Cap<void>(_cap);
105 if (!_obj)
107 return _obj->obj_cap();
108 }
109
110
111 void set(Obj const &o, unsigned flags)
112 {
113 *this = o;
114 restrict_flags(flags);
115 }
116
117 explicit Obj(unsigned flags = 0)
118 : _f(flags), _cap(L4_INVALID_CAP)
119 {}
120
121 Obj(unsigned f, L4::Cap<void> const &cap)
122 : _f((f & ~F_base_mask) | F_cap), _cap(cap.cap())
123 {}
124
125 Obj(unsigned f, L4::Epiface *o)
126 : _f((f & ~F_base_mask) | F_cap | F_local), _obj(o)
127 {}
128
129 void reset(unsigned flags)
130 {
131 _f = (_f & F_replacable) | (flags & ~(F_cap | F_local));
132 _cap = L4_INVALID_CAP;
133 }
134
135
136};
137
138
142class Entry : public cxx::Avl_tree_node
143{
144private:
145 friend class Name_space;
146 Name _n;
147 Obj _o;
148
149 bool _dynamic;
150
151public:
152 Entry(Name const &n, Obj const &o, bool dynamic = false)
153 : _n(n), _o(o), _dynamic(dynamic) {}
154
155 Name const &name() const { return _n; }
156 Obj const *obj() const { return &_o; }
157 Obj *obj() { return &_o; }
158 void obj(Obj const &o) { _o = o; }
159
160 bool is_placeholder() const
161 { return !obj()->is_complete(); }
162
163 bool is_dynamic() const { return _dynamic; }
164
165 void set(Obj const &o)
166 {
167 obj()->set(o, obj()->flags());
168 }
169
170private:
171 void * operator new (size_t s);
172 void operator delete(void *b);
173
174};
175
176struct Names_get_key
177{
178 typedef Name Key_type;
179 static Key_type const &key_of(Entry const *e)
180 { return e->name(); }
181};
182
183
192{
193 friend class Entry;
194
195private:
197 Tree _tree;
198
199protected:
200 L4Re::Util::Dbg const &_dbg;
201 L4Re::Util::Err const &_err;
202
203public:
204
205 typedef Tree::Const_iterator Const_iterator;
206
207 Const_iterator begin() const { return _tree.begin(); }
208 Const_iterator end() const { return _tree.end(); }
209
210 Name_space(L4Re::Util::Dbg const &dbg, L4Re::Util::Err const &err)
211 : _dbg(dbg), _err(err)
212 {}
213
217 virtual ~Name_space() {}
218
219 Entry *find(Name const &name) const { return _tree.find_node(name); }
220 Entry *remove(Name const &name) { return _tree.remove(name); }
221 Entry *find_iter(Name const &pname) const
222 {
223 Name name = pname;
224 _dbg.printf("resolve '%.*s': ", name.len(), name.start());
225 Name_space const *ns = this;
226 while (ns)
227 {
228 cxx::String::Index sep = name.find("/");
229 cxx::String part;
230 if (!name.eof(sep))
231 part = name.head(sep);
232 else
233 part = name;
234
235 _dbg.cprintf(" '%.*s'", part.len(), part.start());
236 Entry *o = ns->find(Name(part.start(), part.len()));
237
238 if (!o)
239 {
240 _dbg.cprintf(": resolution failed: '%.*s' remaining\n",
241 name.len(), name.start());
242 return 0;
243 }
244
245 auto const *obj = o->obj()->obj();
246 ns = dynamic_cast<Name_space const *>(obj);
247 if (ns)
248 {
249 if (!name.eof(sep))
250 {
251 name = name.substr(sep + 1);
252 continue;
253 }
254 }
255
256 _dbg.cprintf(": found object: %p (%s)\n",
257 obj, obj ? typeid(*obj).name() : "");
258
259 return o;
260 }
261
262 return 0;
263 }
264
265 bool insert(Entry *e) { return _tree.insert(e).second; }
266
267 void dump(bool rec = false, int indent = 0) const;
268
269protected:
270 // server support --------------------------------------------
283 virtual Entry *alloc_dynamic_entry(Name const &n, unsigned flags) = 0;
284
290 virtual void free_dynamic_entry(Entry *e) = 0;
291
314 virtual int get_epiface(l4_umword_t data, bool is_local, L4::Epiface **lo) = 0;
315
328 virtual int copy_receive_cap(L4::Cap<void> *cap) = 0;
329
338 virtual void free_capability(L4::Cap<void> cap) = 0;
339
348 virtual void free_epiface(L4::Epiface *epiface) = 0;
349
350 int insert_entry(Name const &name, unsigned flags, Entry **e)
351 {
352 Entry *n = find(name);
353 if (n && n->obj()->is_valid())
354 {
355 if (!(flags & L4Re::Namespace::Overwrite)
356 && n->obj()->cap().validate(L4_BASE_TASK_CAP).label() > 0)
357 return -L4_EEXIST;
358
359 if (n->obj()->is_local())
360 free_epiface(n->obj()->obj());
361 else
362 free_capability(n->obj()->cap());
363
364 if (n->is_dynamic())
365 {
366 remove(n->name());
368 n = 0;
369 }
370 else
371 {
372 if (!n->obj()->is_replacable())
373 return -L4_EEXIST;
374 n->obj()->reset(Obj::F_rw);
375 }
376 }
377
378 flags &= L4Re::Namespace::Cap_flags;
379 if (!n)
380 {
381 if (!(n = alloc_dynamic_entry(name, flags)))
382 return -L4_ENOMEM;
383 else
384 {
385 if (!insert(n))
386 {
388 return -L4_EEXIST;
389 }
390 }
391 }
392
393 *e = n;
394 return 0;
395 }
396
397public:
398 // server interface ------------------------------------------
399 int op_query(L4Re::Namespace::Rights,
403 {
404#if 1
405 _dbg.printf("query: [%ld] '%.*s'\n", name.length,
406 static_cast<int>(name.length), name.data);
407#endif
408
409 char const *sep
410 = static_cast<char const*>(memchr(name.data, '/', name.length));
411 unsigned long part;
412 if (sep)
413 part = sep - name.data;
414 else
415 part = name.length;
416
417 Entry *n = find(Name(name.data, part));
418 if (!n)
419 return -L4_ENOENT;
420 else if (!n->obj()->is_valid())
421 return -L4_EAGAIN;
422 else
423 {
424 if (n->obj()->cap().validate(L4_BASE_TASK_CAP).label() <= 0)
425 {
426 if (n->obj()->is_local())
427 free_epiface(n->obj()->obj());
428 else
429 free_capability(n->obj()->cap());
430
431 if (n->is_dynamic())
432 {
433 remove(n->name());
435 }
436 return -L4_ENOENT;
437 }
438
439 // make picky clients happy
440 dummy.set_valid();
441
442 l4_umword_t result = 0;
443
444 out_name.set_valid();
445 if (part < name.length)
446 {
448 memcpy(out_name->data, name.data + part + 1, name.length - part - 1);
449 out_name->length = name.length - part - 1;
450 }
451 else
452 out_name->length = 0;
453
454 unsigned flags = L4_CAP_FPAGE_R;
455 if (n->obj()->is_rw()) flags |= L4_CAP_FPAGE_W;
456 if (n->obj()->is_strong()) flags |= L4_CAP_FPAGE_S;
457
458 snd_cap = L4::Ipc::Snd_fpage(n->obj()->cap(), flags);
459 _dbg.printf(" result = %lx flgs=%x strg=%d\n",
460 result, flags, static_cast<int>(n->obj()->is_strong()));
461 return result;
462 }
463 }
464
465 int op_register_obj(L4Re::Namespace::Rights, unsigned flags,
468 {
469 if (name.length == 0 || memchr(name.data, '/', name.length))
470 return -L4_EINVAL;
471
473 L4::Epiface *src_o = 0;
474
475 // Did we receive something we have handed out ourselves? If yes,
476 // register the object under the given name but do not allocate
477 // anything more.
478 if (cap.id_received() || cap.local_id_received())
479 {
480 if (int ret = get_epiface(cap.data(), cap.local_id_received(), &src_o))
481 return ret;
482
483 // Make sure rights are restricted to the mapped rights.
484 flags &= (cap.data() & 0x3UL) | ~0x3UL;
485 }
486 else if (cap.cap_received())
487 {
488 if (int ret = copy_receive_cap(&reg_cap))
489 return ret;
490 }
491 else if (!cap.is_valid())
492 {
493 reg_cap = L4::Cap<void>::Invalid;
494 }
495 else
496 return -L4_EINVAL;
497
498 // got a valid entry to register
499 _dbg.printf("register: '%.*s' flags=%x\n", static_cast<int>(name.length),
500 name.data, flags);
501
502 Name _name(name.data, name.length);
503
504 Entry *n;
505 if (int r = insert_entry(_name, flags, &n))
506 {
507 if (cap.cap_received())
508 free_capability(reg_cap);
509 if (src_o)
510 free_epiface(src_o);
511
512 return r;
513 }
514
515 if (src_o)
516 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, src_o));
517 else if (reg_cap.is_valid())
518 n->set(Names::Obj(flags & L4Re::Namespace::Cap_flags, reg_cap));
519
520 return 0;
521 }
522
523 int op_unlink(L4Re::Namespace::Rights,
525
526 {
527#if 1
528 _dbg.printf("unlink: [%ld] '%.*s'\n", name.length,
529 static_cast<int>(name.length), name.data);
530#endif
531
532 char const *sep
533 = static_cast<char const*>(memchr(name.data, '/', name.length));
534 unsigned long part;
535 if (sep)
536 part = sep - name.data;
537 else
538 part = name.length;
539
540 Entry *n = find(Name(name.data, part));
541 if (!n || !n->obj()->is_valid())
542 return -L4_ENOENT;
543
544 if (n->obj()->is_local())
545 free_epiface(n->obj()->obj());
546 else
547 free_capability(n->obj()->cap());
548
549 if (n->is_dynamic())
550 {
551 remove(n->name());
553 }
554 else
555 return -L4_EACCESS;
556
557 return 0;
558 }
559};
560
561}}}
562
AVL tree.
L4::Cap related definitions.
@ Partly_resolved
Name was only partly resolved.
Definition namespace:90
@ Trusted
Obsolete, do not use.
Definition namespace:75
@ Overwrite
If entry already exists, overwrite it.
Definition namespace:80
@ Strong
Strong.
Definition namespace:74
@ Rw
Read-write.
Definition namespace:71
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
bool is_valid() const noexcept
Check if the capability is valid.
Definition ipc_types:354
bool id_received() const noexcept
Check if a label was received instead of a mapping.
Definition ipc_types:377
bool cap_received() const noexcept
Check if at least one capability has been mapped.
Definition ipc_types:365
bool local_id_received() const noexcept
Check if a local capability id has been received.
Definition ipc_types:387
l4_umword_t data() const noexcept
Return the raw flex page descriptor.
Definition ipc_types:397
Send flex-page.
Definition ipc_types:408
Node of an AVL tree.
Definition avl_tree:41
A generic AVL tree.
Definition avl_tree:112
Pair< Node *, bool > insert(Node *new_node)
Insert a new node into this AVL tree.
Definition avl_tree:231
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition avl_tree:293
Bst::Const_iterator Const_iterator
Constant forward iterator for the tree.
Definition avl_tree:143
Node * find_node(Key_param_type key) const
find the node with the given key.
Definition bst.h:280
Const_iterator end() const
Get the end marker for the constant forward iterator.
Definition bst.h:188
Const_iterator begin() const
Get the constant forward iterator for the first element in the set.
Definition bst.h:183
Allocation free string class with explicit length field.
Definition string:42
Index start() const
Pointer to first character.
Definition string:65
String head(Index end) const
Return prefix up to index.
Definition string:79
char const * Index
Character index type.
Definition string:46
int len() const
Length.
Definition string:69
String()
Zero-initialize. Create an invalid string.
Definition string:62
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:359
@ L4_BASE_TASK_CAP
Capability selector for the current task.
Definition consts.h:316
@ L4_INVALID_CAP
Invalid capability selector.
Definition consts.h:168
@ L4_EEXIST
Already exists.
Definition err.h:54
@ L4_ENOENT
No such entity.
Definition err.h:45
@ L4_EACCESS
Permission denied.
Definition err.h:51
@ L4_EINVAL
Invalid argument.
Definition err.h:57
@ L4_EAGAIN
Try again.
Definition err.h:49
@ L4_ENOMEM
No memory.
Definition err.h:50
@ L4_CAP_FPAGE_R
Read right for capability flex-pages.
Definition __l4_fpage.h:178
@ L4_CAP_FPAGE_W
Interface specific 'W' right for capability flex-pages.
Definition __l4_fpage.h:160
@ L4_CAP_FPAGE_S
Interface specific 'S' right for capability flex-pages.
Definition __l4_fpage.h:172
L4Re C++ Interfaces.
Definition l4re.dox:17
Namespace interface.
Base class for interface implementations.
Definition ipc_epiface:157
Server-side copy in buffer for Array.
Definition ipc_array:138
LEN_TYPE length
The length of the array.
Definition ipc_array:145
ELEM_TYPE data[MAX]
The data elements.
Definition ipc_array:143
Array reference data type for arrays located in the message.
Definition ipc_array:40
Attribute for defining an optional RPC argument.
Definition ipc_types:148
void set_valid(bool valid=true) noexcept
Set the argument to present or absent.
Definition ipc_types:167