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

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 13 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.