]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/tools/lxc_device.c
tools: unify exit() calls outside of main()
[mirror_lxc.git] / src / lxc / tools / lxc_device.c
1 /*
2 * lxc: linux Container library
3 *
4 * Authors:
5 * Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <libgen.h>
25 #include <string.h>
26 #include <limits.h>
27
28 #include <lxc/lxccontainer.h>
29
30 #include "utils.h"
31 #include "lxc.h"
32 #include "log.h"
33
34 #include "arguments.h"
35
36 #if HAVE_IFADDRS_H
37 #include <ifaddrs.h>
38 #else
39 #include <../include/ifaddrs.h>
40 #endif
41
42 lxc_log_define(lxc_device, lxc);
43
44 static const struct option my_longopts[] = {
45 LXC_COMMON_OPTIONS
46 };
47
48 static struct lxc_arguments my_args = {
49 .progname = "lxc-device",
50 .help = "\
51 --name=NAME -- add|del DEV\n\
52 \n\
53 lxc-device attach or detach DEV to or from container.\n\
54 \n\
55 Options :\n\
56 -n, --name=NAME NAME of the container\n\
57 --rcfile=FILE Load configuration file FILE\n",
58 .options = my_longopts,
59 .parser = NULL,
60 .checker = NULL,
61 };
62
63 static bool is_interface(const char* dev_name, pid_t pid)
64 {
65 pid_t p = fork();
66
67 if (p < 0) {
68 SYSERROR("failed to fork task.");
69 exit(EXIT_FAILURE);
70 }
71
72 if (p == 0) {
73 struct ifaddrs *interfaceArray = NULL, *tempIfAddr = NULL;
74
75 if (!switch_to_ns(pid, "net")) {
76 ERROR("failed to enter netns of container.");
77 exit(-1);
78 }
79
80 /* Grab the list of interfaces */
81 if (getifaddrs(&interfaceArray)) {
82 ERROR("failed to get interfaces list");
83 exit(-1);
84 }
85
86 /* Iterate through the interfaces */
87 for (tempIfAddr = interfaceArray; tempIfAddr != NULL; tempIfAddr = tempIfAddr->ifa_next) {
88 if (strcmp(tempIfAddr->ifa_name, dev_name) == 0) {
89 exit(EXIT_SUCCESS);
90 }
91 }
92 exit(EXIT_FAILURE);
93 }
94
95 if (wait_for_pid(p) == 0) {
96 return true;
97 }
98 return false;
99 }
100
101 int main(int argc, char *argv[])
102 {
103 struct lxc_container *c;
104 char *cmd, *dev_name, *dst_name;
105 int ret = 1;
106
107 if (geteuid() != 0) {
108 ERROR("%s must be run as root", argv[0]);
109 exit(EXIT_FAILURE);
110 }
111
112 if (lxc_arguments_parse(&my_args, argc, argv))
113 goto err;
114
115 if (!my_args.log_file)
116 my_args.log_file = "none";
117
118 if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority,
119 my_args.progname, my_args.quiet, my_args.lxcpath[0]))
120 goto err;
121 lxc_log_options_no_override();
122
123 c = lxc_container_new(my_args.name, my_args.lxcpath[0]);
124 if (!c) {
125 ERROR("%s doesn't exist", my_args.name);
126 goto err;
127 }
128
129 if (my_args.rcfile) {
130 c->clear_config(c);
131 if (!c->load_config(c, my_args.rcfile)) {
132 ERROR("Failed to load rcfile");
133 goto err1;
134 }
135 c->configfile = strdup(my_args.rcfile);
136 if (!c->configfile) {
137 ERROR("Out of memory setting new config filename");
138 goto err1;
139 }
140 }
141
142 if (!c->is_running(c)) {
143 ERROR("Container %s is not running.", c->name);
144 goto err1;
145 }
146
147 if (my_args.argc < 2) {
148 ERROR("Error: no command given (Please see --help output)");
149 goto err1;
150 }
151
152 cmd = my_args.argv[0];
153 dev_name = my_args.argv[1];
154 if (my_args.argc < 3)
155 dst_name = dev_name;
156 else
157 dst_name = my_args.argv[2];
158
159 if (strcmp(cmd, "add") == 0) {
160 if (is_interface(dev_name, 1)) {
161 ret = c->attach_interface(c, dev_name, dst_name);
162 } else {
163 ret = c->add_device_node(c, dev_name, dst_name);
164 }
165 if (ret != true) {
166 ERROR("Failed to add %s to %s.", dev_name, c->name);
167 ret = 1;
168 goto err1;
169 }
170 INFO("Add %s to %s.", dev_name, c->name);
171 } else if (strcmp(cmd, "del") == 0) {
172 if (is_interface(dev_name, c->init_pid(c))) {
173 ret = c->detach_interface(c, dev_name, dst_name);
174 } else {
175 ret = c->remove_device_node(c, dev_name, dst_name);
176 }
177 if (ret != true) {
178 ERROR("Failed to del %s from %s.", dev_name, c->name);
179 ret = 1;
180 goto err1;
181 }
182 INFO("Delete %s from %s.", dev_name, c->name);
183 } else {
184 ERROR("Error: Please use add or del (Please see --help output)");
185 goto err1;
186 }
187 exit(EXIT_SUCCESS);
188 err1:
189 lxc_container_put(c);
190 err:
191 exit(EXIT_FAILURE);
192 }