Replace brctl with ip (remove bridge-utils dependency)
[platform/core/security/vasum.git] / wrapper / wrapper.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Krzysztof Dynowski <k.dynowski@samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19
20 /**
21  * @file
22  * @author  Krzysztof Dynowski (k.dynowski@samsung.com)
23  * @brief   Vasum old API wrapper to slp client lib
24  */
25
26 #define __VASUM_WRAPPER_SOURCE__
27 #include <vector>
28 #include <string.h>
29 #include <algorithm>
30
31 #include "config.hpp"
32 #include "vasum-client-impl.hpp"
33 #include "logger/logger.hpp"
34 #include "logger/backend-journal.hpp"
35
36 #include "wrapper-compatibility.h"
37
38 struct WrappedZone
39 {
40     Client *client;
41     VsmZone zone;
42     struct vsm_zone vz;
43     std::vector<vsm_netdev> netdevs;
44 };
45
46 struct WrappedContext
47 {
48     Client *client;
49     vsm_context hq_ctx;
50     struct vsm_zone hq_root;
51     std::vector<WrappedZone> zones;
52 };
53
54 static struct
55 {
56     int done;
57     int glib_stop;
58 }wrap;
59
60 #ifndef offsetof
61 #define offsetof(type, memb) ((size_t)&((type *)0)->memb)
62 #endif
63 #ifdef container_of
64 #undef container_of
65 #endif
66 #ifndef container_of
67 #define container_of(ptr, type, memb) (\
68     (type *)((char *)(ptr) - offsetof(type, memb)))
69 #endif
70
71 #define UNUSED(x) ((void)(x))
72
73 #define vsm_error_t vsm_error_s
74 #define vsm_attach_command_t vsm_attach_command_s
75 #define vsm_attach_options_t vsm_attach_options_s
76 #define vsm_zone_state_cb vsm_zone_state_changed_cb
77
78 void __attribute__ ((constructor)) wrapper_load(void);
79 void __attribute__ ((destructor)) wrapper_unload(void);
80 static void init_wrapper();
81 extern struct vasum_ops dummy_ops;
82
83 using namespace logger;
84 void wrapper_load(void)
85 {
86     Logger::setLogLevel(LogLevel::TRACE);
87     Logger::setLogBackend(new SystemdJournalBackend());
88     init_wrapper();
89 }
90
91 void wrapper_unload(void)
92 {
93     if (wrap.glib_stop) Client::vsm_stop_glib_loop();
94     wrap.glib_stop = 0;
95 }
96
97 static void callcheck()
98 {
99     init_wrapper();
100 }
101
102 void init_wrapper()
103 {
104     if (wrap.done) return ;
105     memset(&wrap,0,sizeof(wrap));
106     wrap.done = 1;
107     LOGS("");
108 }
109
110 static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false)
111 {
112     if (zone == NULL) {
113         return NULL;
114     }
115     for (auto& zw : w->zones) {
116         if (zw.zone == zone) {
117             return &zw.vz;
118         }
119     }
120     if (create) {
121         w->zones.push_back(WrappedZone());
122         WrappedZone& zw = w->zones.back();
123         zw.client = w->client;
124         zw.zone = zone;
125         zw.vz.name = zone->id;
126         zw.vz.type = NULL;
127         zw.vz.user_data = NULL;
128         zw.vz.rootfs_path = zone->rootfs_path;
129         zw.vz.parent = &zw.vz;
130         LOGI("return (create) zone " << zone->id);
131         return &w->zones.back().vz;
132     }
133     LOGE("return zone NULL");
134     return NULL;
135 }
136
137 static int wrap_error(VsmStatus st, const Client *c)
138 {
139     if (st == VSMCLIENT_SUCCESS) LOGI("return success " << st);
140     else LOGE("return error " << st << "m=" << (c ? c->vsm_get_status_message() : "n/a"));
141     switch (st) {
142         case VSMCLIENT_SUCCESS: return VSM_ERROR_NONE;
143         case VSMCLIENT_CUSTOM_ERROR: return -VSM_ERROR_GENERIC;
144         case VSMCLIENT_IO_ERROR: return -VSM_ERROR_IO;
145         case VSMCLIENT_OPERATION_FAILED: return -VSM_ERROR_NOT_PERMITTED;
146         case VSMCLIENT_INVALID_ARGUMENT: return -VSM_ERROR_INVALID;
147         case VSMCLIENT_OTHER_ERROR: return -VSM_ERROR_GENERIC;
148     }
149     return -VSM_ERROR_GENERIC;
150 }
151
152 static void init_context_wrap(WrappedContext *w)
153 {
154     Client::vsm_start_glib_loop();
155     wrap.glib_stop = 1;
156     w->client = new Client();
157     VsmStatus st = w->client->createSystem();
158     wrap_error(st, w->client);
159
160     memset(&w->hq_ctx, 0, sizeof(w->hq_ctx));
161     memset(&w->hq_root, 0, sizeof(w->hq_root));
162
163     vsm_context *ctx = &w->hq_ctx;
164     adt_init_list(&ctx->listeners);
165     //init root_zone
166     ctx->root_zone = &w->hq_root;
167     ctx->root_zone->name = (char*)"";
168     ctx->root_zone->id=0;
169     ctx->root_zone->rootfs_path = (char*)"/";
170
171     ctx->root_zone->terminal = -1;
172     ctx->root_zone->state = VSM_ZONE_STATE_RUNNING;
173     ctx->root_zone->user_data = ctx->root_zone;
174
175     ctx->root_zone->parent = ctx->root_zone;
176     ctx->root_zone->ctx = ctx;
177
178     pthread_rwlock_init(&ctx->root_zone->lock, NULL);
179     adt_init_list(&ctx->root_zone->netdevs);
180     adt_init_list(&ctx->root_zone->devices);
181     adt_init_list(&ctx->root_zone->children);
182
183     pthread_rwlock_init(&ctx->lock, NULL);
184     adt_init_list(&ctx->listeners);
185     adt_init_list(&ctx->sc_listeners);
186     adt_init_list(&ctx->ev_listeners);
187
188     //struct mainloop *mainloop = mainloop_create();
189     //struct mxe_engine *engine = mxe_prepare_engine(mainloop, ctx);
190     //struct mxe_endpoint *ep = mxe_create_client(engine, SERVICEPATH);
191
192     ctx->foreground_zone = ctx->root_zone;
193     ctx->vsm_ops = &dummy_ops;
194     ctx->error = VSM_ERROR_NONE;
195     //ctx->data = ep;
196 }
197
198 API vsm_context_h vsm_create_context(void)
199 {
200     LOGS(""); callcheck();
201     WrappedContext *w = new WrappedContext();
202     init_context_wrap(w);
203
204     vsm_context *ctx = &w->hq_ctx;
205     return ctx;
206 }
207
208 API int vsm_cleanup_context(vsm_context_h ctx)
209 {
210     LOGS(""); callcheck();
211     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
212     if (w->client != NULL) {
213         delete w->client;
214         w->client = NULL;
215     }
216     for (auto& zw : w->zones) {
217         zw.netdevs.clear();
218     }
219     w->zones.clear();
220     delete w;
221     return VSM_ERROR_NONE;
222 }
223
224 static const char *const vsm_error_strtab[] = {
225     "No error",
226     "Undefined error",
227     "Invalid",
228     "Operation cancelled",
229     "Operation aborted",
230     "Connection refused",
231     "Object exists",
232     "Resource busy",
233     "Input/Output error",
234     "Timeout",
235     "Overflow",
236     "Out of memory",
237     "Out of range",
238     "Operation not permitted",
239     "Function not implemented",
240     "Operation not supported",
241     "Access denied",
242     "No object found",
243     "Bad state"
244 };
245
246 API vsm_error_e vsm_last_error(struct vsm_context *ctx)
247 {
248     if (ctx)
249         return ctx->error;
250     return static_cast<vsm_error_e>(-1);
251 }
252
253 API const char *vsm_error_string(vsm_error_e error)
254 {
255     LOGS(""); callcheck();
256     if (error < 0 || error > VSM_MAX_ERROR) {
257         return NULL;
258     }
259     return vsm_error_strtab[error];
260 }
261
262 API int vsm_get_poll_fd(struct vsm_context *ctx)
263 {
264     LOGS(""); callcheck();
265     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
266     UNUSED(w);
267     //FIXME Client should create Dispatcher and pass to IPCConnection
268     //      now: IPCConnection has field ThreadWrapper
269     //return w->client->getEventPoll().getPollFD();
270     return -1;
271 }
272 API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout)
273 {
274     LOGS(""); callcheck();
275     UNUSED(flags);
276     UNUSED(timeout);
277     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
278     UNUSED(w);
279     //FIXME Client should create Dispatcher and pass to IPCConnection
280     //      now: IPCConnection has field ThreadWrapper
281     //TODO Use EventPoll from Dispatcher
282     return 0;
283 }
284
285 API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const char *template_name, int flag)
286 {
287     LOGS("create_zone " << zone_name); callcheck();
288     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
289     UNUSED(flag);
290     //template_name = NULL; //template name not supported by libvasum-client
291     if (!w->client) return VSM_ERROR_GENERIC;
292     VsmStatus st = w->client->vsm_create_zone(zone_name, template_name);
293     if (st != VSMCLIENT_SUCCESS) {
294         LOGE("vsm_create_zone(" << zone_name << ") = " << st);
295     }
296     return wrap_error(st, w->client);
297 }
298
299 API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int force)
300 {
301     LOGS("zone=" << zone_name); callcheck();
302     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
303     UNUSED(force);
304     if (!w->client) return VSM_ERROR_GENERIC;
305     VsmStatus st = w->client->vsm_destroy_zone(zone_name);
306     if (st == VSMCLIENT_SUCCESS) {
307         auto zonebyname = [zone_name](const WrappedZone& v) {return v.zone->id == zone_name;};
308         auto zonelist = std::remove_if(w->zones.begin(), w->zones.end(), zonebyname);
309         w->zones.erase(zonelist);
310     }
311     return wrap_error(st, w->client);
312 }
313
314 API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name)
315 {
316     LOGS("zone=" << zone_name); callcheck();
317     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
318     if (!w->client) return VSM_ERROR_GENERIC;
319     VsmStatus st = w->client->vsm_start_zone(zone_name);
320     return wrap_error(st, w->client);
321 }
322
323 API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force)
324 {
325     LOGS("zone=" << zone_name); callcheck();
326     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
327     UNUSED(force);
328     if (!w->client) return VSM_ERROR_GENERIC;
329     VsmStatus st = w->client->vsm_shutdown_zone(zone_name);
330     return wrap_error(st, w->client);
331 }
332
333 API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown)
334 {
335     LOGS("zone=" << zone_name); callcheck();
336     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
337     UNUSED(shutdown);
338     if (!w->client) return VSM_ERROR_GENERIC;
339     VsmStatus st = w->client->vsm_lock_zone(zone_name);
340     return wrap_error(st, w->client);
341 }
342
343 API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name)
344 {
345     LOGS("zone=" << zone_name); callcheck();
346     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
347     if (!w->client) return VSM_ERROR_GENERIC;
348     VsmStatus st = w->client->vsm_lock_zone(zone_name);
349     return wrap_error(st, w->client);
350 }
351
352 API int vsm_set_foreground(struct vsm_zone *zone)
353 {
354     LOGS(""); callcheck();
355     WrappedZone *w = container_of(zone, WrappedZone, vz);
356     if (!w->client) return VSM_ERROR_GENERIC;
357     VsmStatus st = w->client->vsm_set_active_zone(zone->name);
358     return wrap_error(st, w->client);
359 }
360
361 //execute command in specified zone
362 API int vsm_attach_zone(struct vsm_context *ctx,
363                         const char *zone_name,
364                         vsm_attach_command_t *command,
365                         vsm_attach_options_t *opts,
366                         pid_t *attached_process)
367 {
368     return dummy_ops.attach_zone(ctx, zone_name, command, opts,
369                      attached_process);
370 }
371
372 //execute command in specified zone and wait
373 API int vsm_attach_zone_wait(struct vsm_context *ctx,
374                              const char *zone_name,
375                              vsm_attach_command_t *command,
376                              vsm_attach_options_t *opts)
377 {
378     return dummy_ops.attach_zone_wait(ctx, zone_name, command, opts);
379 }
380
381 API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data)
382 {
383     LOGS(""); callcheck();
384     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
385     if (!w->client) return -VSM_ERROR_GENERIC;
386     callback(ctx->root_zone, user_data);
387     for (auto& z : w->zones) {
388         callback(&z.vz, user_data);
389     }
390     return 0;
391 }
392
393 API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path)
394 {
395     LOGS("name=" << path); callcheck();
396     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
397     VsmZone zone;
398     if (!w->client) return NULL;
399     //CHECK if path is same as zone_name
400     if (w->client->vsm_lookup_zone_by_id(path, &zone) != VSMCLIENT_SUCCESS)
401         return NULL;
402     return wrap_vsm_zone(w, zone, true);
403 }
404
405 API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid)
406 {
407     LOGS("pid=" << pid); callcheck();
408     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
409     VsmZone zone;
410     VsmString id;
411     if (!w->client) return NULL;
412     if (w->client->vsm_lookup_zone_by_pid(pid, &id) != VSMCLIENT_SUCCESS) {
413         LOGE("vsm_lookup_zone_by_pid(" << pid << ") error");
414         return NULL;
415     }
416     if (::strcmp(id, "host") == 0) {
417         return w->hq_ctx.root_zone;
418     }
419     w->client->vsm_lookup_zone_by_id(id, &zone); //zone is malloced
420     return wrap_vsm_zone(w, zone);
421 }
422
423 API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal)
424 {
425     LOGS("terminal=" << terminal); callcheck();
426     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
427     VsmZone zone;
428     VsmString id;
429     if (!w->client) return NULL;
430     if (w->client->vsm_lookup_zone_by_terminal_id(terminal, &id) != VSMCLIENT_SUCCESS)
431         return NULL;
432     w->client->vsm_lookup_zone_by_id(id, &zone);
433     return wrap_vsm_zone(w, zone);
434 }
435 #if 0
436 API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_cb callback, void *user_data)
437 {
438     LOGS(""); callcheck();
439     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
440     VsmSubscriptionId subscriptionId;
441
442     auto dbus_cb = [=](const char* id, const char* dbusAddress, void* data) ->
443     void {
444         VsmZone zone;
445         //TODO what are valid state, event
446         UNUSED(dbusAddress);
447         w->client->vsm_lookup_zone_by_id(id, &zone);
448         callback(wrap_vsm_zone(w, zone), data);
449     };
450     w->client->vsm_add_state_callback(dbus_cb, user_data, &subscriptionId);
451     return (int)subscriptionId;
452 }
453
454 API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle)
455 {
456     LOGS(""); callcheck();
457     WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx);
458     VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle;
459     VsmStatus st = w->client->vsm_del_state_callback(subscriptionId);
460     return wrap_error(st, w->client);
461 }
462 #endif
463 API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags)
464 {
465     LOGS(""); callcheck();
466     WrappedZone *w = container_of(dom, WrappedZone, vz);
467     const char *id = dom->name;
468     VsmZone zone;
469     w->client->vsm_lookup_zone_by_id(id, &zone);
470     VsmStatus st = w->client->vsm_grant_device(id, name, flags);
471     return wrap_error(st, w->client);
472 }
473
474 API int vsm_revoke_device(struct vsm_zone *dom, const char *name)
475 {
476     LOGS(""); callcheck();
477     WrappedZone *w = container_of(dom, WrappedZone, vz);
478     const char *id = dom->name;
479     VsmStatus st = w->client->vsm_revoke_device(id, name);
480     return wrap_error(st, w->client);
481 }
482
483 API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev)
484 {
485     LOGS(""); callcheck();
486     UNUSED(zone);
487     UNUSED(type);
488     UNUSED(target);
489     UNUSED(netdev);
490
491     WrappedZone *w = container_of(zone, WrappedZone, vz);
492     const char *id = zone->name;
493     VsmStatus st;
494     if (type == VSM_NETDEV_VETH)
495         st = w->client->vsm_create_netdev_veth(id, target, netdev);
496     else if (type == VSM_NETDEV_PHYS)
497         st = w->client->vsm_create_netdev_phys(id, netdev);
498     else if (type == VSM_NETDEV_MACVLAN) // macvlan_mode from if_link.h
499         st = w->client->vsm_create_netdev_macvlan(id, target, netdev, MACVLAN_MODE_BRIDGE);
500     else {
501         LOGE("Invalid arguments");
502         //ctx->error = VSM_ERROR_INVALID;
503         return NULL;
504     }
505
506     if (st != VSMCLIENT_SUCCESS) {
507         LOGE("vsm_create_netdev(" << netdev << ") = " << st);
508         return NULL;
509     }
510
511     vsm_netdev vnd;
512     vnd.zone = zone;
513     vnd.name = (char*)netdev; //FIXME? copy content of string
514     vnd.type = type;
515     w->netdevs.push_back(vnd); //copy pushed to vector
516     return &w->netdevs.back(); //pointer to struct on vector
517 }
518
519 API int vsm_destroy_netdev(struct vsm_zone *zone, struct vsm_netdev *netdev)
520 {
521     LOGS(""); callcheck();
522     WrappedZone *w = container_of(zone, WrappedZone, vz);
523
524     VsmStatus st = w->client->vsm_destroy_netdev(zone->name, netdev->name);
525     if (st == VSMCLIENT_SUCCESS) {
526         auto devbyname = [netdev](const vsm_netdev& v) {return ::strcmp(v.name, netdev->name) == 0;};
527         auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
528         if (devlist != w->netdevs.end()) {
529             w->netdevs.erase(devlist);
530         }
531     }
532     return wrap_error(st, w->client);
533 }
534
535 API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data)
536 {
537     LOGS(""); callcheck();
538     WrappedZone *w = container_of(zone, WrappedZone, vz);
539     for (auto nd : w->netdevs) {
540         callback(&nd, user_data);
541     }
542     return 0;
543 }
544
545 API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name)
546 {
547     LOGS(""); callcheck();
548     WrappedZone *w = container_of(zone, WrappedZone, vz);
549     VsmNetdev nd;
550     VsmStatus st = w->client->vsm_lookup_netdev_by_name(zone->name, name, &nd);
551     if (st == VSMCLIENT_SUCCESS) {
552         auto devbyname = [name](const vsm_netdev& v) {return ::strcmp(v.name, name) == 0;};
553         auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname);
554         if (devlist != w->netdevs.end()) {
555             return &devlist[0];
556         }
557     }
558     return NULL;
559 }
560
561 API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode)
562 {
563     LOGS(""); callcheck();
564     UNUSED(ctx);
565     UNUSED(ftype);
566     UNUSED(path);
567     UNUSED(flags);
568     UNUSED(mode);
569     //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
570     return VSM_ERROR_NONE;
571 }
572
573 API int vsm_declare_mount(struct vsm_context *ctx,
574                           const char *source,
575                           const char *target,
576                           const char *fstype,
577                           unsigned long flags,
578                           const void *data)
579 {
580     LOGS(""); callcheck();
581     UNUSED(ctx);
582     UNUSED(source);
583     UNUSED(target);
584     UNUSED(fstype);
585     UNUSED(flags);
586     UNUSED(data);
587     //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
588     return VSM_ERROR_NONE;
589 }
590
591 API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target)
592 {
593     LOGS("src=" << source << "dst=" << target); callcheck();
594     UNUSED(ctx);
595     UNUSED(source);
596     UNUSED(target);
597     //TODO apply declare link for existing zones (and those created in the future, so must store paits source, target)
598     return VSM_ERROR_NONE;
599 }
600
601 API int vsm_add_state_changed_callback(vsm_context_h  /*ctx*/, vsm_zone_state_changed_cb  /*callback*/, void * /*user_data*/)
602 {
603     return VSM_ERROR_NONE;
604 }
605 API int vsm_del_state_changed_callback(vsm_context_h  /*ctx*/, int  /*id*/)
606 {
607     return VSM_ERROR_NONE;
608 }
609 API const char * vsm_get_zone_rootpath(vsm_zone_h  /*zone*/)
610 {
611     return NULL;
612 }
613 API const char * vsm_get_zone_name(vsm_zone_h  /*zone*/)
614 {
615     return NULL;
616 }
617 API int vsm_is_host_zone(vsm_zone_h  /*zone*/)
618 {
619     return VSM_ERROR_NONE;
620 }
621 API vsm_zone_h vsm_join_zone(vsm_zone_h  /*zone*/)
622 {
623     return NULL;
624 }
625 API int vsm_canonicalize_path(const char * /*input_path*/, char ** /*output_path*/)
626 {
627     return VSM_ERROR_NONE;
628 }
629
630