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