aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaksym Kryzhanovskyy <xmaks@email.cz>2010-07-22 02:18:05 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-07-22 02:18:05 +0200
commit4f0279bd930d02db2d5df51ce878b9b9b940f069 (patch)
treeb7aaa81f6c767faff90518321cf36eb83a75c18f
parentc5fb0ada9b9efe65ceef3f2b5171573463e07b4f (diff)
downloadbusybox-w32-4f0279bd930d02db2d5df51ce878b9b9b940f069.tar.gz
busybox-w32-4f0279bd930d02db2d5df51ce878b9b9b940f069.tar.bz2
busybox-w32-4f0279bd930d02db2d5df51ce878b9b9b940f069.zip
ifplugd: code shrink
function old new delta ifplugd_main 1089 1161 +72 method_table - 40 +40 detect_link 221 207 -14 static.method 40 - -40 netlink_open 79 - -79 ------------------------------------------------------------------------------ (add/remove: 1/2 grow/shrink: 1/1 up/down: 112/-133) Total: -21 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--networking/ifplugd.c333
1 files changed, 164 insertions, 169 deletions
diff --git a/networking/ifplugd.c b/networking/ifplugd.c
index eb7442881..2f8c90ffc 100644
--- a/networking/ifplugd.c
+++ b/networking/ifplugd.c
@@ -71,16 +71,6 @@ enum {
71# define OPTION_STR "+ansfFi:r:It:u:d:m:pqlx:M" 71# define OPTION_STR "+ansfFi:r:It:u:d:m:pqlx:M"
72#endif 72#endif
73 73
74enum { // api mode
75 API_AUTO = 'a',
76 API_ETHTOOL = 'e',
77 API_MII = 'm',
78 API_PRIVATE = 'p',
79 API_WLAN = 'w',
80 API_IFF = 'i',
81};
82static const char api_modes[] ALIGN1 = "aempwi";
83
84enum { // interface status 74enum { // interface status
85 IFSTATUS_ERR = -1, 75 IFSTATUS_ERR = -1,
86 IFSTATUS_DOWN = 0, 76 IFSTATUS_DOWN = 0,
@@ -107,8 +97,6 @@ struct globals {
107 const char *api_mode; 97 const char *api_mode;
108 const char *script_name; 98 const char *script_name;
109 const char *extra_arg; 99 const char *extra_arg;
110
111 smallint (*detect_link_func)(void);
112}; 100};
113#define G (*ptr_to_globals) 101#define G (*ptr_to_globals)
114#define INIT_G() do { \ 102#define INIT_G() do { \
@@ -123,42 +111,12 @@ struct globals {
123} while (0) 111} while (0)
124 112
125 113
126static const char *strstatus(int status) 114/* Utility routines */
127{
128 if (status == IFSTATUS_ERR)
129 return "error";
130 return "down\0up" + (status * 5);
131}
132 115
133static int run_script(const char *action) 116static void set_ifreq_to_ifname(struct ifreq *ifreq)
134{ 117{
135 char *env_PREVIOUS, *env_CURRENT; 118 memset(ifreq, 0, sizeof(struct ifreq));
136 char *argv[5]; 119 strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface);
137 int r;
138
139 bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action);
140
141 argv[0] = (char*) G.script_name;
142 argv[1] = (char*) G.iface;
143 argv[2] = (char*) action;
144 argv[3] = (char*) G.extra_arg;
145 argv[4] = NULL;
146
147 env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status));
148 putenv(env_PREVIOUS);
149 env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_CURRENT, strstatus(G.iface_last_status));
150 putenv(env_CURRENT);
151
152 /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */
153 r = spawn_and_wait(argv);
154
155 unsetenv(IFPLUGD_ENV_PREVIOUS);
156 unsetenv(IFPLUGD_ENV_CURRENT);
157 free(env_PREVIOUS);
158 free(env_CURRENT);
159
160 bb_error_msg("exit code: %d", r & 0xff);
161 return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r;
162} 120}
163 121
164static int network_ioctl(int request, void* data, const char *errmsg) 122static int network_ioctl(int request, void* data, const char *errmsg)
@@ -169,80 +127,7 @@ static int network_ioctl(int request, void* data, const char *errmsg)
169 return r; 127 return r;
170} 128}
171 129
172static void set_ifreq_to_ifname(struct ifreq *ifreq) 130/* Link detection routines and table */
173{
174 memset(ifreq, 0, sizeof(struct ifreq));
175 strncpy_IFNAMSIZ(ifreq->ifr_name, G.iface);
176}
177
178static void up_iface(void)
179{
180 struct ifreq ifrequest;
181
182 if (!G.iface_exists)
183 return;
184
185 set_ifreq_to_ifname(&ifrequest);
186 if (network_ioctl(SIOCGIFFLAGS, &ifrequest, "getting interface flags") < 0) {
187 G.iface_exists = 0;
188 return;
189 }
190
191 if (!(ifrequest.ifr_flags & IFF_UP)) {
192 ifrequest.ifr_flags |= IFF_UP;
193 /* Let user know we mess up with interface */
194 bb_error_msg("upping interface");
195 if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0)
196 xfunc_die();
197 }
198
199#if 0 /* why do we mess with IP addr? It's not our business */
200 if (network_ioctl(SIOCGIFADDR, &ifrequest, "can't get interface address") < 0) {
201 } else if (ifrequest.ifr_addr.sa_family != AF_INET) {
202 bb_perror_msg("the interface is not IP-based");
203 } else {
204 ((struct sockaddr_in*)(&ifrequest.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
205 network_ioctl(SIOCSIFADDR, &ifrequest, "can't set interface address");
206 }
207 network_ioctl(SIOCGIFFLAGS, &ifrequest, "can't get interface flags");
208#endif
209}
210
211static void maybe_up_new_iface(void)
212{
213 if (!(option_mask32 & FLAG_NO_AUTO))
214 up_iface();
215
216#if 0 /* bloat */
217 struct ifreq ifrequest;
218 struct ethtool_drvinfo driver_info;
219
220 set_ifreq_to_ifname(&ifrequest);
221 driver_info.cmd = ETHTOOL_GDRVINFO;
222 ifrequest.ifr_data = &driver_info;
223 if (network_ioctl(SIOCETHTOOL, &ifrequest, NULL) == 0) {
224 char buf[sizeof("/xx:xx:xx:xx:xx:xx")];
225
226 /* Get MAC */
227 buf[0] = '\0';
228 set_ifreq_to_ifname(&ifrequest);
229 if (network_ioctl(SIOCGIFHWADDR, &ifrequest, NULL) == 0) {
230 sprintf(buf, "/%02X:%02X:%02X:%02X:%02X:%02X",
231 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[0]),
232 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[1]),
233 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[2]),
234 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[3]),
235 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[4]),
236 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[5]));
237 }
238
239 bb_error_msg("using interface %s%s with driver<%s> (version: %s)",
240 G.iface, buf, driver_info.driver, driver_info.version);
241 }
242#endif
243 if (G.api_method_num == 0)
244 G.detect_link_func = NULL;
245}
246 131
247static smallint detect_link_mii(void) 132static smallint detect_link_mii(void)
248{ 133{
@@ -349,18 +234,139 @@ static smallint detect_link_wlan(void)
349 return IFSTATUS_UP; 234 return IFSTATUS_UP;
350} 235}
351 236
237enum { // api mode
238 API_ETHTOOL, // 'e'
239 API_MII, // 'm'
240 API_PRIVATE, // 'p'
241 API_WLAN, // 'w'
242 API_IFF, // 'i'
243 API_AUTO, // 'a'
244};
245
246static const char api_modes[] ALIGN1 = "empwia";
247
248static const struct {
249 const char *name;
250 smallint (*func)(void);
251} method_table[] = {
252 { "SIOCETHTOOL" , &detect_link_ethtool },
253 { "SIOCGMIIPHY" , &detect_link_mii },
254 { "SIOCDEVPRIVATE" , &detect_link_priv },
255 { "wireless extension", &detect_link_wlan },
256 { "IFF_RUNNING" , &detect_link_iff },
257};
258
259
260
261static const char *strstatus(int status)
262{
263 if (status == IFSTATUS_ERR)
264 return "error";
265 return "down\0up" + (status * 5);
266}
267
268static int run_script(const char *action)
269{
270 char *env_PREVIOUS, *env_CURRENT;
271 char *argv[5];
272 int r;
273
274 bb_error_msg("executing '%s %s %s'", G.script_name, G.iface, action);
275
276 argv[0] = (char*) G.script_name;
277 argv[1] = (char*) G.iface;
278 argv[2] = (char*) action;
279 argv[3] = (char*) G.extra_arg;
280 argv[4] = NULL;
281
282 env_PREVIOUS = xasprintf("%s=%s", IFPLUGD_ENV_PREVIOUS, strstatus(G.iface_prev_status));
283 putenv(env_PREVIOUS);
284 env_CURRENT = xasprintf("%s=%s", IFPLUGD_ENV_CURRENT, strstatus(G.iface_last_status));
285 putenv(env_CURRENT);
286
287 /* r < 0 - can't exec, 0 <= r < 0x180 - exited, >=0x180 - killed by sig (r-0x180) */
288 r = spawn_and_wait(argv);
289
290 unsetenv(IFPLUGD_ENV_PREVIOUS);
291 unsetenv(IFPLUGD_ENV_CURRENT);
292 free(env_PREVIOUS);
293 free(env_CURRENT);
294
295 bb_error_msg("exit code: %d", r & 0xff);
296 return (option_mask32 & FLAG_IGNORE_RETVAL) ? 0 : r;
297}
298
299static void up_iface(void)
300{
301 struct ifreq ifrequest;
302
303 if (!G.iface_exists)
304 return;
305
306 set_ifreq_to_ifname(&ifrequest);
307 if (network_ioctl(SIOCGIFFLAGS, &ifrequest, "getting interface flags") < 0) {
308 G.iface_exists = 0;
309 return;
310 }
311
312 if (!(ifrequest.ifr_flags & IFF_UP)) {
313 ifrequest.ifr_flags |= IFF_UP;
314 /* Let user know we mess up with interface */
315 bb_error_msg("upping interface");
316 if (network_ioctl(SIOCSIFFLAGS, &ifrequest, "setting interface flags") < 0)
317 xfunc_die();
318 }
319
320#if 0 /* why do we mess with IP addr? It's not our business */
321 if (network_ioctl(SIOCGIFADDR, &ifrequest, "can't get interface address") < 0) {
322 } else if (ifrequest.ifr_addr.sa_family != AF_INET) {
323 bb_perror_msg("the interface is not IP-based");
324 } else {
325 ((struct sockaddr_in*)(&ifrequest.ifr_addr))->sin_addr.s_addr = INADDR_ANY;
326 network_ioctl(SIOCSIFADDR, &ifrequest, "can't set interface address");
327 }
328 network_ioctl(SIOCGIFFLAGS, &ifrequest, "can't get interface flags");
329#endif
330}
331
332static void maybe_up_new_iface(void)
333{
334 if (!(option_mask32 & FLAG_NO_AUTO))
335 up_iface();
336
337#if 0 /* bloat */
338 struct ifreq ifrequest;
339 struct ethtool_drvinfo driver_info;
340
341 set_ifreq_to_ifname(&ifrequest);
342 driver_info.cmd = ETHTOOL_GDRVINFO;
343 ifrequest.ifr_data = &driver_info;
344 if (network_ioctl(SIOCETHTOOL, &ifrequest, NULL) == 0) {
345 char buf[sizeof("/xx:xx:xx:xx:xx:xx")];
346
347 /* Get MAC */
348 buf[0] = '\0';
349 set_ifreq_to_ifname(&ifrequest);
350 if (network_ioctl(SIOCGIFHWADDR, &ifrequest, NULL) == 0) {
351 sprintf(buf, "/%02X:%02X:%02X:%02X:%02X:%02X",
352 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[0]),
353 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[1]),
354 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[2]),
355 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[3]),
356 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[4]),
357 (uint8_t)(ifrequest.ifr_hwaddr.sa_data[5]));
358 }
359
360 bb_error_msg("using interface %s%s with driver<%s> (version: %s)",
361 G.iface, buf, driver_info.driver, driver_info.version);
362 }
363#endif
364 if (G.api_mode[0] == 'a')
365 G.api_method_num = API_AUTO;
366}
367
352static smallint detect_link(void) 368static smallint detect_link(void)
353{ 369{
354 static const struct {
355 const char *name;
356 smallint (*func)(void);
357 } method[] = {
358 { "SIOCETHTOOL" , &detect_link_ethtool },
359 { "SIOCGMIIPHY" , &detect_link_mii },
360 { "SIOCDEVPRIVATE" , &detect_link_priv },
361 { "wireless extension", &detect_link_wlan },
362 { "IFF_RUNNING" , &detect_link_iff },
363 };
364 smallint status; 370 smallint status;
365 371
366 if (!G.iface_exists) 372 if (!G.iface_exists)
@@ -373,38 +379,34 @@ static smallint detect_link(void)
373 if (!(option_mask32 & FLAG_NO_AUTO)) 379 if (!(option_mask32 & FLAG_NO_AUTO))
374 up_iface(); 380 up_iface();
375 381
376 if (!G.detect_link_func) { 382 if (G.api_method_num == API_AUTO) {
377 if (G.api_method_num == 0) { 383 int i;
378 int i; 384 smallint sv_logmode;
379 smallint sv_logmode; 385
380 386 sv_logmode = logmode;
381 sv_logmode = logmode; 387 for (i = 0; i < ARRAY_SIZE(method_table); i++) {
382 for (i = 0; i < ARRAY_SIZE(method); i++) { 388 logmode = LOGMODE_NONE;
383 logmode = LOGMODE_NONE; 389 status = method_table[i].func();
384 status = method[i].func(); 390 logmode = sv_logmode;
385 logmode = sv_logmode; 391 if (status != IFSTATUS_ERR) {
386 if (status != IFSTATUS_ERR) { 392 G.api_method_num = i;
387 G.detect_link_func = method[i].func; 393 bb_error_msg("using %s detection mode", method_table[i].name);
388 bb_error_msg("using %s detection mode", method[i].name); 394 break;
389 goto _2;
390 }
391 } 395 }
392 goto _1;
393 } 396 }
394 G.detect_link_func = method[G.api_method_num - 1].func; 397 } else {
398 status = method_table[G.api_method_num].func();
395 } 399 }
396 400
397 status = G.detect_link_func();
398 _1:
399 if (status == IFSTATUS_ERR) { 401 if (status == IFSTATUS_ERR) {
400 if (option_mask32 & FLAG_IGNORE_FAIL) 402 if (option_mask32 & FLAG_IGNORE_FAIL)
401 status = IFSTATUS_DOWN; 403 status = IFSTATUS_DOWN;
402 else if (option_mask32 & FLAG_IGNORE_FAIL_POSITIVE) 404 else if (option_mask32 & FLAG_IGNORE_FAIL_POSITIVE)
403 status = IFSTATUS_UP; 405 status = IFSTATUS_UP;
404 else if (G.api_method_num == 0) 406 else if (G.api_mode[0] == 'a')
405 bb_error_msg("can't detect link status"); 407 bb_error_msg("can't detect link status");
406 } 408 }
407 _2: 409
408 if (status != G.iface_last_status) { 410 if (status != G.iface_last_status) {
409 G.iface_prev_status = G.iface_last_status; 411 G.iface_prev_status = G.iface_last_status;
410 G.iface_last_status = status; 412 G.iface_last_status = status;
@@ -475,23 +477,6 @@ static NOINLINE int check_existence_through_netlink(void)
475 return G.iface_exists; 477 return G.iface_exists;
476} 478}
477 479
478static NOINLINE int netlink_open(void)
479{
480 int fd;
481 struct sockaddr_nl addr;
482
483 fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
484
485 memset(&addr, 0, sizeof(addr));
486 addr.nl_family = AF_NETLINK;
487 addr.nl_groups = RTMGRP_LINK;
488 addr.nl_pid = getpid();
489
490 xbind(fd, (struct sockaddr*)&addr, sizeof(addr));
491
492 return fd;
493}
494
495#if ENABLE_FEATURE_PIDFILE 480#if ENABLE_FEATURE_PIDFILE
496static NOINLINE pid_t read_pid(const char *filename) 481static NOINLINE pid_t read_pid(const char *filename)
497{ 482{
@@ -545,6 +530,7 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
545 if (pid_from_pidfile > 0 && kill(pid_from_pidfile, 0) == 0) 530 if (pid_from_pidfile > 0 && kill(pid_from_pidfile, 0) == 0)
546 bb_error_msg_and_die("daemon already running"); 531 bb_error_msg_and_die("daemon already running");
547#endif 532#endif
533
548 api_mode_found = strchr(api_modes, G.api_mode[0]); 534 api_mode_found = strchr(api_modes, G.api_mode[0]);
549 if (!api_mode_found) 535 if (!api_mode_found)
550 bb_error_msg_and_die("unknown API mode '%s'", G.api_mode); 536 bb_error_msg_and_die("unknown API mode '%s'", G.api_mode);
@@ -555,7 +541,16 @@ int ifplugd_main(int argc UNUSED_PARAM, char **argv)
555 541
556 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd); 542 xmove_fd(xsocket(AF_INET, SOCK_DGRAM, 0), ioctl_fd);
557 if (opts & FLAG_MONITOR) { 543 if (opts & FLAG_MONITOR) {
558 xmove_fd(netlink_open(), netlink_fd); 544 struct sockaddr_nl addr;
545 int fd = xsocket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
546
547 memset(&addr, 0, sizeof(addr));
548 addr.nl_family = AF_NETLINK;
549 addr.nl_groups = RTMGRP_LINK;
550 addr.nl_pid = getpid();
551
552 xbind(fd, (struct sockaddr*)&addr, sizeof(addr));
553 xmove_fd(fd, netlink_fd);
559 } 554 }
560 555
561 write_pidfile(pidfile_name); 556 write_pidfile(pidfile_name);