]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_device.c
tree-wide: fix lxc header inclusion
[mirror_lxc.git] / src / lxc / tools / lxc_device.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <libgen.h>
7 #include <limits.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <unistd.h>
12
13 #include "lxc.h"
14
15 #include "netns_ifaddrs.h"
16 #include "arguments.h"
17 #include "config.h"
18 #include "log.h"
19 #include "utils.h"
20
21 lxc_log_define(lxc_device, lxc);
22
23 static bool is_interface(const char *dev_name, pid_t pid);
24
25 static const struct option my_longopts[] = {
26 LXC_COMMON_OPTIONS
27 };
28
29 static struct lxc_arguments my_args = {
30 .progname = "lxc-device",
31 .help = "\
32 --name=NAME -- add|del DEV\n\
33 \n\
34 lxc-device attach or detach DEV to or from container.\n\
35 \n\
36 Options :\n\
37 -n, --name=NAME NAME of the container\n\
38 --rcfile=FILE Load configuration file FILE\n",
39 .options = my_longopts,
40 .parser = NULL,
41 .checker = NULL,
42 .log_priority = "ERROR",
43 .log_file = "none",
44 };
45
46 static bool is_interface(const char *dev_name, pid_t pid)
47 {
48 pid_t p = fork();
49 if (p < 0) {
50 ERROR("Failed to fork task");
51 exit(EXIT_FAILURE);
52 }
53
54 if (p == 0) {
55 struct netns_ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
56
57 if (!switch_to_ns(pid, "net")) {
58 ERROR("Failed to enter netns of container");
59 _exit(-1);
60 }
61
62 /* Grab the list of interfaces */
63 if (netns_getifaddrs(&interfaceArray, -1, &(bool){false})) {
64 ERROR("Failed to get interfaces list");
65 _exit(-1);
66 }
67
68 /* Iterate through the interfaces */
69 for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
70 if (strncmp(tempIfAddr->ifa_name, dev_name, strlen(tempIfAddr->ifa_name)) == 0)
71 _exit(EXIT_SUCCESS);
72 }
73
74 _exit(EXIT_FAILURE);
75 }
76
77 if (wait_for_pid(p) == 0)
78 return true;
79
80 return false;
81 }
82
83 int main(int argc, char *argv[])
84 {
85 struct lxc_container *c;
86 struct lxc_log log;
87 char *cmd, *dev_name, *dst_name;
88 bool ret = false;
89
90 if (geteuid() != 0) {
91 ERROR("%s must be run as root", argv[0]);
92 exit(EXIT_FAILURE);
93 }
94
95 if (lxc_arguments_parse(&my_args, argc, argv))
96 exit(EXIT_FAILURE);
97
98 log.name = my_args.name;
99 log.file = my_args.log_file;
100 log.level = my_args.log_priority;
101 log.prefix = my_args.progname;
102 log.quiet = my_args.quiet;
103 log.lxcpath = my_args.lxcpath[0];
104
105 if (lxc_log_init(&log))
106 exit(EXIT_FAILURE);
107
108 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
109 if (!c) {
110 ERROR("%s doesn't exist", my_args.name);
111 exit(EXIT_FAILURE);
112 }
113
114 if (my_args.rcfile) {
115 c->clear_config(c);
116
117 if (!c->load_config(c, my_args.rcfile)) {
118 ERROR("Failed to load rcfile");
119 goto err;
120 }
121
122 c->configfile = strdup(my_args.rcfile);
123 if (!c->configfile) {
124 ERROR("Out of memory setting new config filename");
125 goto err;
126 }
127 }
128
129 if (!c->is_running(c)) {
130 ERROR("Container %s is not running", c->name);
131 goto err;
132 }
133
134 if (my_args.argc < 2) {
135 ERROR("Error: no command given (Please see --help output)");
136 goto err;
137 }
138
139 cmd = my_args.argv[0];
140 dev_name = my_args.argv[1];
141
142 if (my_args.argc < 3)
143 dst_name = dev_name;
144 else
145 dst_name = my_args.argv[2];
146
147 if (strncmp(cmd, "add", strlen(cmd)) == 0) {
148 if (is_interface(dev_name, 1))
149 ret = c->attach_interface(c, dev_name, dst_name);
150 else
151 ret = c->add_device_node(c, dev_name, dst_name);
152 if (ret != true) {
153 ERROR("Failed to add %s to %s", dev_name, c->name);
154 goto err;
155 }
156 } else if (strncmp(cmd, "del", strlen(cmd)) == 0) {
157 if (is_interface(dev_name, c->init_pid(c)))
158 ret = c->detach_interface(c, dev_name, dst_name);
159 else
160 ret = c->remove_device_node(c, dev_name, dst_name);
161 if (ret != true) {
162 ERROR("Failed to del %s from %s", dev_name, c->name);
163 goto err;
164 }
165 } else {
166 ERROR("Error: Please use add or del (Please see --help output)");
167 goto err;
168 }
169
170 exit(EXIT_SUCCESS);
171
172 err:
173 lxc_container_put(c);
174 exit(EXIT_FAILURE);
175 }