source: MondoRescue/branches/stable/mindi-busybox/networking/ifconfig.c

Last change on this file was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 15.5 KB
Line 
1/* vi: set sw=4 ts=4: */
2/* ifconfig
3 *
4 * Similar to the standard Unix ifconfig, but with only the necessary
5 * parts for AF_INET, and without any printing of if info (for now).
6 *
7 * Bjorn Wesen, Axis Communications AB
8 *
9 *
10 * Authors of the original ifconfig was:
11 * Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
12 *
13 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
14 */
15
16/*
17 * Heavily modified by Manuel Novoa III Mar 6, 2001
18 *
19 * From initial port to busybox, removed most of the redundancy by
20 * converting to a table-driven approach. Added several (optional)
21 * args missing from initial port.
22 *
23 * Still missing: media, tunnel.
24 *
25 * 2002-04-20
26 * IPV6 support added by Bart Visscher <magick@linux-fan.com>
27 */
28
29#include <net/if.h>
30#include <net/if_arp.h>
31#include <netinet/in.h>
32#if defined(__GLIBC__) && __GLIBC__ >=2 && __GLIBC_MINOR__ >= 1
33#include <netpacket/packet.h>
34#include <net/ethernet.h>
35#else
36#include <sys/types.h>
37#include <netinet/if_ether.h>
38#endif
39#include "inet_common.h"
40#include "libbb.h"
41
42#if ENABLE_FEATURE_IFCONFIG_SLIP
43# include <net/if_slip.h>
44#endif
45
46/* I don't know if this is needed for busybox or not. Anyone? */
47#define QUESTIONABLE_ALIAS_CASE
48
49
50/* Defines for glibc2.0 users. */
51#ifndef SIOCSIFTXQLEN
52# define SIOCSIFTXQLEN 0x8943
53# define SIOCGIFTXQLEN 0x8942
54#endif
55
56/* ifr_qlen is ifru_ivalue, but it isn't present in 2.0 kernel headers */
57#ifndef ifr_qlen
58# define ifr_qlen ifr_ifru.ifru_mtu
59#endif
60
61#ifndef IFF_DYNAMIC
62# define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses */
63#endif
64
65#if ENABLE_FEATURE_IPV6
66struct in6_ifreq {
67 struct in6_addr ifr6_addr;
68 uint32_t ifr6_prefixlen;
69 int ifr6_ifindex;
70};
71#endif
72
73/*
74 * Here are the bit masks for the "flags" member of struct options below.
75 * N_ signifies no arg prefix; M_ signifies arg prefixed by '-'.
76 * CLR clears the flag; SET sets the flag; ARG signifies (optional) arg.
77 */
78#define N_CLR 0x01
79#define M_CLR 0x02
80#define N_SET 0x04
81#define M_SET 0x08
82#define N_ARG 0x10
83#define M_ARG 0x20
84
85#define M_MASK (M_CLR | M_SET | M_ARG)
86#define N_MASK (N_CLR | N_SET | N_ARG)
87#define SET_MASK (N_SET | M_SET)
88#define CLR_MASK (N_CLR | M_CLR)
89#define SET_CLR_MASK (SET_MASK | CLR_MASK)
90#define ARG_MASK (M_ARG | N_ARG)
91
92/*
93 * Here are the bit masks for the "arg_flags" member of struct options below.
94 */
95
96/*
97 * cast type:
98 * 00 int
99 * 01 char *
100 * 02 HOST_COPY in_ether
101 * 03 HOST_COPY INET_resolve
102 */
103#define A_CAST_TYPE 0x03
104/*
105 * map type:
106 * 00 not a map type (mem_start, io_addr, irq)
107 * 04 memstart (unsigned long)
108 * 08 io_addr (unsigned short)
109 * 0C irq (unsigned char)
110 */
111#define A_MAP_TYPE 0x0C
112#define A_ARG_REQ 0x10 /* Set if an arg is required. */
113#define A_NETMASK 0x20 /* Set if netmask (check for multiple sets). */
114#define A_SET_AFTER 0x40 /* Set a flag at the end. */
115#define A_COLON_CHK 0x80 /* Is this needed? See below. */
116#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
117#define A_HOSTNAME 0x100 /* Set if it is ip addr. */
118#define A_BROADCAST 0x200 /* Set if it is broadcast addr. */
119#else
120#define A_HOSTNAME 0
121#define A_BROADCAST 0
122#endif
123
124/*
125 * These defines are for dealing with the A_CAST_TYPE field.
126 */
127#define A_CAST_CHAR_PTR 0x01
128#define A_CAST_RESOLVE 0x01
129#define A_CAST_HOST_COPY 0x02
130#define A_CAST_HOST_COPY_IN_ETHER A_CAST_HOST_COPY
131#define A_CAST_HOST_COPY_RESOLVE (A_CAST_HOST_COPY | A_CAST_RESOLVE)
132
133/*
134 * These defines are for dealing with the A_MAP_TYPE field.
135 */
136#define A_MAP_ULONG 0x04 /* memstart */
137#define A_MAP_USHORT 0x08 /* io_addr */
138#define A_MAP_UCHAR 0x0C /* irq */
139
140/*
141 * Define the bit masks signifying which operations to perform for each arg.
142 */
143
144#define ARG_METRIC (A_ARG_REQ /*| A_CAST_INT*/)
145#define ARG_MTU (A_ARG_REQ /*| A_CAST_INT*/)
146#define ARG_TXQUEUELEN (A_ARG_REQ /*| A_CAST_INT*/)
147#define ARG_MEM_START (A_ARG_REQ | A_MAP_ULONG)
148#define ARG_IO_ADDR (A_ARG_REQ | A_MAP_ULONG)
149#define ARG_IRQ (A_ARG_REQ | A_MAP_UCHAR)
150#define ARG_DSTADDR (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE)
151#define ARG_NETMASK (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_NETMASK)
152#define ARG_BROADCAST (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_BROADCAST)
153#define ARG_HW (A_ARG_REQ | A_CAST_HOST_COPY_IN_ETHER)
154#define ARG_POINTOPOINT (A_ARG_REQ | A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
155#define ARG_KEEPALIVE (A_ARG_REQ | A_CAST_CHAR_PTR)
156#define ARG_OUTFILL (A_ARG_REQ | A_CAST_CHAR_PTR)
157#define ARG_HOSTNAME (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER | A_COLON_CHK | A_HOSTNAME)
158#define ARG_ADD_DEL (A_CAST_HOST_COPY_RESOLVE | A_SET_AFTER)
159
160
161/*
162 * Set up the tables. Warning! They must have corresponding order!
163 */
164
165struct arg1opt {
166 const char *name;
167 int selector;
168 unsigned short ifr_offset;
169};
170
171struct options {
172 const char *name;
173#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
174 const unsigned int flags:6;
175 const unsigned int arg_flags:10;
176#else
177 const unsigned char flags;
178 const unsigned char arg_flags;
179#endif
180 const unsigned short selector;
181};
182
183#define ifreq_offsetof(x) offsetof(struct ifreq, x)
184
185static const struct arg1opt Arg1Opt[] = {
186 {"SIOCSIFMETRIC", SIOCSIFMETRIC, ifreq_offsetof(ifr_metric)},
187 {"SIOCSIFMTU", SIOCSIFMTU, ifreq_offsetof(ifr_mtu)},
188 {"SIOCSIFTXQLEN", SIOCSIFTXQLEN, ifreq_offsetof(ifr_qlen)},
189 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
190 {"SIOCSIFNETMASK", SIOCSIFNETMASK, ifreq_offsetof(ifr_netmask)},
191 {"SIOCSIFBRDADDR", SIOCSIFBRDADDR, ifreq_offsetof(ifr_broadaddr)},
192#if ENABLE_FEATURE_IFCONFIG_HW
193 {"SIOCSIFHWADDR", SIOCSIFHWADDR, ifreq_offsetof(ifr_hwaddr)},
194#endif
195 {"SIOCSIFDSTADDR", SIOCSIFDSTADDR, ifreq_offsetof(ifr_dstaddr)},
196#ifdef SIOCSKEEPALIVE
197 {"SIOCSKEEPALIVE", SIOCSKEEPALIVE, ifreq_offsetof(ifr_data)},
198#endif
199#ifdef SIOCSOUTFILL
200 {"SIOCSOUTFILL", SIOCSOUTFILL, ifreq_offsetof(ifr_data)},
201#endif
202#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
203 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.mem_start)},
204 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.base_addr)},
205 {"SIOCSIFMAP", SIOCSIFMAP, ifreq_offsetof(ifr_map.irq)},
206#endif
207 /* Last entry if for unmatched (possibly hostname) arg. */
208#if ENABLE_FEATURE_IPV6
209 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
210 {"SIOCDIFADDR", SIOCDIFADDR, ifreq_offsetof(ifr_addr)}, /* IPv6 version ignores the offset */
211#endif
212 {"SIOCSIFADDR", SIOCSIFADDR, ifreq_offsetof(ifr_addr)},
213};
214
215static const struct options OptArray[] = {
216 {"metric", N_ARG, ARG_METRIC, 0},
217 {"mtu", N_ARG, ARG_MTU, 0},
218 {"txqueuelen", N_ARG, ARG_TXQUEUELEN, 0},
219 {"dstaddr", N_ARG, ARG_DSTADDR, 0},
220 {"netmask", N_ARG, ARG_NETMASK, 0},
221 {"broadcast", N_ARG | M_CLR, ARG_BROADCAST, IFF_BROADCAST},
222#if ENABLE_FEATURE_IFCONFIG_HW
223 {"hw", N_ARG, ARG_HW, 0},
224#endif
225 {"pointopoint", N_ARG | M_CLR, ARG_POINTOPOINT, IFF_POINTOPOINT},
226#ifdef SIOCSKEEPALIVE
227 {"keepalive", N_ARG, ARG_KEEPALIVE, 0},
228#endif
229#ifdef SIOCSOUTFILL
230 {"outfill", N_ARG, ARG_OUTFILL, 0},
231#endif
232#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
233 {"mem_start", N_ARG, ARG_MEM_START, 0},
234 {"io_addr", N_ARG, ARG_IO_ADDR, 0},
235 {"irq", N_ARG, ARG_IRQ, 0},
236#endif
237#if ENABLE_FEATURE_IPV6
238 {"add", N_ARG, ARG_ADD_DEL, 0},
239 {"del", N_ARG, ARG_ADD_DEL, 0},
240#endif
241 {"arp", N_CLR | M_SET, 0, IFF_NOARP},
242 {"trailers", N_CLR | M_SET, 0, IFF_NOTRAILERS},
243 {"promisc", N_SET | M_CLR, 0, IFF_PROMISC},
244 {"multicast", N_SET | M_CLR, 0, IFF_MULTICAST},
245 {"allmulti", N_SET | M_CLR, 0, IFF_ALLMULTI},
246 {"dynamic", N_SET | M_CLR, 0, IFF_DYNAMIC},
247 {"up", N_SET, 0, (IFF_UP | IFF_RUNNING)},
248 {"down", N_CLR, 0, IFF_UP},
249 {NULL, 0, ARG_HOSTNAME, (IFF_UP | IFF_RUNNING)}
250};
251
252/*
253 * A couple of prototypes.
254 */
255
256#if ENABLE_FEATURE_IFCONFIG_HW
257static int in_ether(const char *bufp, struct sockaddr *sap);
258#endif
259
260/*
261 * Our main function.
262 */
263
264int ifconfig_main(int argc, char **argv);
265int ifconfig_main(int argc, char **argv)
266{
267 struct ifreq ifr;
268 struct sockaddr_in sai;
269#if ENABLE_FEATURE_IFCONFIG_HW
270 struct sockaddr sa;
271#endif
272 const struct arg1opt *a1op;
273 const struct options *op;
274 int sockfd; /* socket fd we use to manipulate stuff with */
275 int selector;
276#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
277 unsigned int mask;
278 unsigned int did_flags;
279 unsigned int sai_hostname, sai_netmask;
280#else
281 unsigned char mask;
282 unsigned char did_flags;
283#endif
284 char *p;
285 /*char host[128];*/
286 const char *host = NULL; /* make gcc happy */
287
288 did_flags = 0;
289#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
290 sai_hostname = 0;
291 sai_netmask = 0;
292#endif
293
294 /* skip argv[0] */
295 ++argv;
296 --argc;
297
298#if ENABLE_FEATURE_IFCONFIG_STATUS
299 if (argc > 0 && (argv[0][0] == '-' && argv[0][1] == 'a' && !argv[0][2])) {
300 interface_opt_a = 1;
301 --argc;
302 ++argv;
303 }
304#endif
305
306 if (argc <= 1) {
307#if ENABLE_FEATURE_IFCONFIG_STATUS
308 return display_interfaces(argc ? *argv : NULL);
309#else
310 bb_error_msg_and_die("no support for status display");
311#endif
312 }
313
314 /* Create a channel to the NET kernel. */
315 sockfd = xsocket(AF_INET, SOCK_DGRAM, 0);
316
317 /* get interface name */
318 safe_strncpy(ifr.ifr_name, *argv, IFNAMSIZ);
319
320 /* Process the remaining arguments. */
321 while (*++argv != (char *) NULL) {
322 p = *argv;
323 mask = N_MASK;
324 if (*p == '-') { /* If the arg starts with '-'... */
325 ++p; /* advance past it and */
326 mask = M_MASK; /* set the appropriate mask. */
327 }
328 for (op = OptArray; op->name; op++) { /* Find table entry. */
329 if (strcmp(p, op->name) == 0) { /* If name matches... */
330 mask &= op->flags;
331 if (mask) /* set the mask and go. */
332 goto FOUND_ARG;
333 /* If we get here, there was a valid arg with an */
334 /* invalid '-' prefix. */
335 bb_error_msg_and_die("bad: '%s'", p-1);
336 }
337 }
338
339 /* We fell through, so treat as possible hostname. */
340 a1op = Arg1Opt + ARRAY_SIZE(Arg1Opt) - 1;
341 mask = op->arg_flags;
342 goto HOSTNAME;
343
344 FOUND_ARG:
345 if (mask & ARG_MASK) {
346 mask = op->arg_flags;
347 a1op = Arg1Opt + (op - OptArray);
348 if (mask & A_NETMASK & did_flags)
349 bb_show_usage();
350 if (*++argv == NULL) {
351 if (mask & A_ARG_REQ)
352 bb_show_usage();
353 --argv;
354 mask &= A_SET_AFTER; /* just for broadcast */
355 } else { /* got an arg so process it */
356 HOSTNAME:
357 did_flags |= (mask & (A_NETMASK|A_HOSTNAME));
358 if (mask & A_CAST_HOST_COPY) {
359#if ENABLE_FEATURE_IFCONFIG_HW
360 if (mask & A_CAST_RESOLVE) {
361#endif
362#if ENABLE_FEATURE_IPV6
363 char *prefix;
364 int prefix_len = 0;
365#endif
366 /*safe_strncpy(host, *argv, (sizeof host));*/
367 host = *argv;
368#if ENABLE_FEATURE_IPV6
369 prefix = strchr(host, '/');
370 if (prefix) {
371 prefix_len = xatou_range(prefix + 1, 0, 128);
372 *prefix = '\0';
373 }
374#endif
375 sai.sin_family = AF_INET;
376 sai.sin_port = 0;
377 if (!strcmp(host, bb_str_default)) {
378 /* Default is special, meaning 0.0.0.0. */
379 sai.sin_addr.s_addr = INADDR_ANY;
380 }
381#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
382 else if ((host[0] == '+' && !host[1]) && (mask & A_BROADCAST)
383 && (did_flags & (A_NETMASK|A_HOSTNAME)) == (A_NETMASK|A_HOSTNAME)
384 ) {
385 /* + is special, meaning broadcast is derived. */
386 sai.sin_addr.s_addr = (~sai_netmask) | (sai_hostname & sai_netmask);
387 }
388#endif
389 else {
390 len_and_sockaddr *lsa;
391 if (strcmp(host, "inet") == 0)
392 continue; /* compat stuff */
393 lsa = xhost2sockaddr(host, 0);
394#if ENABLE_FEATURE_IPV6
395 if (lsa->sa.sa_family == AF_INET6) {
396 int sockfd6;
397 struct in6_ifreq ifr6;
398
399 memcpy((char *) &ifr6.ifr6_addr,
400 (char *) &(lsa->sin6.sin6_addr),
401 sizeof(struct in6_addr));
402
403 /* Create a channel to the NET kernel. */
404 sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0);
405 xioctl(sockfd6, SIOGIFINDEX, &ifr);
406 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
407 ifr6.ifr6_prefixlen = prefix_len;
408 ioctl_or_perror_and_die(sockfd6, a1op->selector, &ifr6, "%s", a1op->name);
409 if (ENABLE_FEATURE_CLEAN_UP)
410 free(lsa);
411 continue;
412 }
413#endif
414 sai.sin_addr = lsa->sin.sin_addr;
415 if (ENABLE_FEATURE_CLEAN_UP)
416 free(lsa);
417 }
418#if ENABLE_FEATURE_IFCONFIG_BROADCAST_PLUS
419 if (mask & A_HOSTNAME)
420 sai_hostname = sai.sin_addr.s_addr;
421 if (mask & A_NETMASK)
422 sai_netmask = sai.sin_addr.s_addr;
423#endif
424 p = (char *) &sai;
425#if ENABLE_FEATURE_IFCONFIG_HW
426 } else { /* A_CAST_HOST_COPY_IN_ETHER */
427 /* This is the "hw" arg case. */
428 if (strcmp("ether", *argv) || !*++argv)
429 bb_show_usage();
430 /*safe_strncpy(host, *argv, sizeof(host));*/
431 host = *argv;
432 if (in_ether(host, &sa))
433 bb_error_msg_and_die("invalid hw-addr %s", host);
434 p = (char *) &sa;
435 }
436#endif
437 memcpy( (((char *)&ifr) + a1op->ifr_offset),
438 p, sizeof(struct sockaddr));
439 } else {
440 /* FIXME: error check?? */
441 unsigned long i = strtoul(*argv, NULL, 0);
442 p = ((char *)&ifr) + a1op->ifr_offset;
443#if ENABLE_FEATURE_IFCONFIG_MEMSTART_IOADDR_IRQ
444 if (mask & A_MAP_TYPE) {
445 xioctl(sockfd, SIOCGIFMAP, &ifr);
446 if ((mask & A_MAP_UCHAR) == A_MAP_UCHAR)
447 *((unsigned char *) p) = i;
448 else if (mask & A_MAP_USHORT)
449 *((unsigned short *) p) = i;
450 else
451 *((unsigned long *) p) = i;
452 } else
453#endif
454 if (mask & A_CAST_CHAR_PTR)
455 *((caddr_t *) p) = (caddr_t) i;
456 else /* A_CAST_INT */
457 *((int *) p) = i;
458 }
459
460 ioctl_or_perror_and_die(sockfd, a1op->selector, &ifr, "%s", a1op->name);
461#ifdef QUESTIONABLE_ALIAS_CASE
462 if (mask & A_COLON_CHK) {
463 /*
464 * Don't do the set_flag() if the address is an alias with
465 * a '-' at the end, since it's deleted already! - Roman
466 *
467 * Should really use regex.h here, not sure though how well
468 * it'll go with the cross-platform support etc.
469 */
470 char *ptr;
471 short int found_colon = 0;
472 for (ptr = ifr.ifr_name; *ptr; ptr++)
473 if (*ptr == ':')
474 found_colon++;
475 if (found_colon && ptr[-1] == '-')
476 continue;
477 }
478#endif
479 }
480 if (!(mask & A_SET_AFTER))
481 continue;
482 mask = N_SET;
483 }
484
485 xioctl(sockfd, SIOCGIFFLAGS, &ifr);
486 selector = op->selector;
487 if (mask & SET_MASK)
488 ifr.ifr_flags |= selector;
489 else
490 ifr.ifr_flags &= ~selector;
491 xioctl(sockfd, SIOCSIFFLAGS, &ifr);
492 } /* while () */
493
494 if (ENABLE_FEATURE_CLEAN_UP)
495 close(sockfd);
496 return 0;
497}
498
499#if ENABLE_FEATURE_IFCONFIG_HW
500/* Input an Ethernet address and convert to binary. */
501static int in_ether(const char *bufp, struct sockaddr *sap)
502{
503 char *ptr;
504 int i, j;
505 unsigned char val;
506 unsigned char c;
507
508 sap->sa_family = ARPHRD_ETHER;
509 ptr = sap->sa_data;
510
511 i = 0;
512 do {
513 j = val = 0;
514
515 /* We might get a semicolon here - not required. */
516 if (i && (*bufp == ':')) {
517 bufp++;
518 }
519
520 do {
521 c = *bufp;
522 if (((unsigned char)(c - '0')) <= 9) {
523 c -= '0';
524 } else if (((unsigned char)((c|0x20) - 'a')) <= 5) {
525 c = (c|0x20) - ('a'-10);
526 } else if (j && (c == ':' || c == 0)) {
527 break;
528 } else {
529 return -1;
530 }
531 ++bufp;
532 val <<= 4;
533 val += c;
534 } while (++j < 2);
535 *ptr++ = val;
536 } while (++i < ETH_ALEN);
537
538 return *bufp; /* Error if we don't end at end of string. */
539}
540#endif
Note: See TracBrowser for help on using the repository browser.