diff options
author | Maksym Kryzhanovskyy <xmaks@email.cz> | 2010-07-22 02:18:05 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-07-22 02:18:05 +0200 |
commit | 4f0279bd930d02db2d5df51ce878b9b9b940f069 (patch) | |
tree | b7aaa81f6c767faff90518321cf36eb83a75c18f | |
parent | c5fb0ada9b9efe65ceef3f2b5171573463e07b4f (diff) | |
download | busybox-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.c | 333 |
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 | ||
74 | enum { // 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 | }; | ||
82 | static const char api_modes[] ALIGN1 = "aempwi"; | ||
83 | |||
84 | enum { // interface status | 74 | enum { // 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 | ||
126 | static 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 | ||
133 | static int run_script(const char *action) | 116 | static 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 | ||
164 | static int network_ioctl(int request, void* data, const char *errmsg) | 122 | static 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 | ||
172 | static 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 | |||
178 | static 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 | |||
211 | static 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 | ||
247 | static smallint detect_link_mii(void) | 132 | static 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 | ||
237 | enum { // 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 | |||
246 | static const char api_modes[] ALIGN1 = "empwia"; | ||
247 | |||
248 | static 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 | |||
261 | static const char *strstatus(int status) | ||
262 | { | ||
263 | if (status == IFSTATUS_ERR) | ||
264 | return "error"; | ||
265 | return "down\0up" + (status * 5); | ||
266 | } | ||
267 | |||
268 | static 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 | |||
299 | static 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 | |||
332 | static 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 | |||
352 | static smallint detect_link(void) | 368 | static 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 | ||
478 | static 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 |
496 | static NOINLINE pid_t read_pid(const char *filename) | 481 | static 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); |