Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (12 years ago)
Author:
Bruno Cornec
Message:
  • 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:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/networking/ifupdown.c

    r821 r1770  
    1111 *  Remove checks for kernel version, assume kernel version 2.2.0 or better.
    1212 *  Lines in the interfaces file cannot wrap.
    13  *  To adhere to the FHS, the default state file is /var/run/ifstate.
     13 *  To adhere to the FHS, the default state file is /var/run/ifstate
     14 *  (defined via CONFIG_IFUPDOWN_IFSTATE_PATH) and can be overridden by build
     15 *  configuration.
    1416 *
    1517 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
    1618 */
    1719
    18 /* TODO: standardise execute() return codes to return 0 for success and 1 for failure */
    19 
    20 #include <sys/stat.h>
    2120#include <sys/utsname.h>
    22 #include <sys/wait.h>
    23 
    24 #include <ctype.h>
    25 #include <errno.h>
    26 #include <fcntl.h>
    2721#include <fnmatch.h>
    2822#include <getopt.h>
    29 #include <stdarg.h>
    30 #include <stdio.h>
    31 #include <stdlib.h>
    32 #include <string.h>
    33 #include <unistd.h>
    34 
    35 #include "busybox.h"
     23
     24#include "libbb.h"
    3625
    3726#define MAX_OPT_DEPTH 10
     
    4029#define EUNBALPER   10000
    4130
    42 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
     31#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    4332#define MAX_INTERFACE_LENGTH 10
    4433#endif
    4534
    46 #if 0
    47 #define debug_noise(fmt, args...) printf(fmt, ## args)
    48 #else
    49 #define debug_noise(fmt, args...)
    50 #endif
     35#define debug_noise(args...) /*fprintf(stderr, args)*/
    5136
    5237/* Forward declaration */
    5338struct interface_defn_t;
    5439
    55 typedef int (execfn)(char *command);
    56 
    57 struct method_t
    58 {
    59     char *name;
     40typedef int execfn(char *command);
     41
     42struct method_t {
     43    const char *name;
    6044    int (*up)(struct interface_defn_t *ifd, execfn *e);
    6145    int (*down)(struct interface_defn_t *ifd, execfn *e);
    6246};
    6347
    64 struct address_family_t
    65 {
    66     char *name;
     48struct address_family_t {
     49    const char *name;
    6750    int n_methods;
    68     struct method_t *method;
     51    const struct method_t *method;
    6952};
    7053
    71 struct mapping_defn_t
    72 {
     54struct mapping_defn_t {
    7355    struct mapping_defn_t *next;
    7456
     
    8466};
    8567
    86 struct variable_t
    87 {
     68struct variable_t {
    8869    char *name;
    8970    char *value;
    9071};
    9172
    92 struct interface_defn_t
    93 {
    94     struct address_family_t *address_family;
    95     struct method_t *method;
     73struct interface_defn_t {
     74    const struct address_family_t *address_family;
     75    const struct method_t *method;
    9676
    9777    char *iface;
     
    10181};
    10282
    103 struct interfaces_file_t
    104 {
     83struct interfaces_file_t {
    10584    llist_t *autointerfaces;
    10685    llist_t *ifaces;
     
    10887};
    10988
    110 static char no_act = 0;
    111 static char verbose = 0;
    112 static char **__myenviron = NULL;
     89#define OPTION_STR "anvf" USE_FEATURE_IFUPDOWN_MAPPING("m") "i:"
     90enum {
     91    OPT_do_all = 0x1,
     92    OPT_no_act = 0x2,
     93    OPT_verbose = 0x4,
     94    OPT_force = 0x8,
     95    OPT_no_mappings = 0x10,
     96};
     97#define DO_ALL (option_mask32 & OPT_do_all)
     98#define NO_ACT (option_mask32 & OPT_no_act)
     99#define VERBOSE (option_mask32 & OPT_verbose)
     100#define FORCE (option_mask32 & OPT_force)
     101#define NO_MAPPINGS (option_mask32 & OPT_no_mappings)
     102
     103static char **my_environ;
     104
     105static const char *startup_PATH;
    113106
    114107#if ENABLE_FEATURE_IFUPDOWN_IPV4 || ENABLE_FEATURE_IFUPDOWN_IPV6
    115108
    116 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    117 
    118 static unsigned int count_bits(unsigned int a)
    119 {
    120     unsigned int result;
    121     result = (a & 0x55) + ((a >> 1) & 0x55);
    122     result = (result & 0x33) + ((result >> 2) & 0x33);
    123     return((result & 0x0F) + ((result >> 4) & 0x0F));
    124 }
    125 
    126 static int count_netmask_bits(char *dotted_quad)
    127 {
    128     unsigned int result, a, b, c, d;
    129     /* Found a netmask...  Check if it is dotted quad */
    130     if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
    131         return -1;
    132     result = count_bits(a);
    133     result += count_bits(b);
    134     result += count_bits(c);
    135     result += count_bits(d);
    136     return ((int)result);
    137 }
    138 #endif
    139 
    140 static void addstr(char **buf, size_t *len, size_t *pos, char *str, size_t str_length)
    141 {
    142     if (*pos + str_length >= *len) {
    143         char *newbuf;
    144 
    145         newbuf = xrealloc(*buf, *len * 2 + str_length + 1);
    146         *buf = newbuf;
    147         *len = *len * 2 + str_length + 1;
    148     }
    149 
    150     while (str_length-- >= 1) {
    151         (*buf)[(*pos)++] = *str;
    152         str++;
    153     }
    154     (*buf)[*pos] = '\0';
    155 }
    156 
    157 static int strncmpz(char *l, char *r, size_t llen)
     109static void addstr(char **bufp, const char *str, size_t str_length)
     110{
     111    /* xasprintf trick will be smaller, but we are often
     112     * called with str_length == 1 - don't want to have
     113     * THAT much of malloc/freeing! */
     114    char *buf = *bufp;
     115    int len = (buf ? strlen(buf) : 0);
     116    str_length++;
     117    buf = xrealloc(buf, len + str_length);
     118    /* copies at most str_length-1 chars! */
     119    safe_strncpy(buf + len, str, str_length);
     120    *bufp = buf;
     121}
     122
     123static int strncmpz(const char *l, const char *r, size_t llen)
    158124{
    159125    int i = strncmp(l, r, llen);
    160126
    161     if (i == 0) {
    162         return(-r[llen]);
    163     } else {
    164         return(i);
    165     }
    166 }
    167 
    168 static char *get_var(char *id, size_t idlen, struct interface_defn_t *ifd)
     127    if (i == 0)
     128        return -r[llen];
     129    return i;
     130}
     131
     132static char *get_var(const char *id, size_t idlen, struct interface_defn_t *ifd)
    169133{
    170134    int i;
     
    173137        char *result;
    174138        static char label_buf[20];
    175         strncpy(label_buf, ifd->iface, 19);
    176         label_buf[19]=0;
     139        safe_strncpy(label_buf, ifd->iface, sizeof(label_buf));
    177140        result = strchr(label_buf, ':');
    178141        if (result) {
    179             *result=0;
    180         }
    181         return( label_buf);
    182     } else if (strncmpz(id, "label", idlen) == 0) {
    183         return (ifd->iface);
    184     } else {
    185         for (i = 0; i < ifd->n_options; i++) {
    186             if (strncmpz(id, ifd->option[i].name, idlen) == 0) {
    187                 return (ifd->option[i].value);
    188             }
    189         }
    190     }
    191 
    192     return(NULL);
    193 }
    194 
    195 static char *parse(char *command, struct interface_defn_t *ifd)
    196 {
    197 
    198     char *result = NULL;
    199     size_t pos = 0, len = 0;
     142            *result = '\0';
     143        }
     144        return label_buf;
     145    }
     146    if (strncmpz(id, "label", idlen) == 0) {
     147        return ifd->iface;
     148    }
     149    for (i = 0; i < ifd->n_options; i++) {
     150        if (strncmpz(id, ifd->option[i].name, idlen) == 0) {
     151            return ifd->option[i].value;
     152        }
     153    }
     154    return NULL;
     155}
     156
     157#if ENABLE_FEATURE_IFUPDOWN_IP
     158static int count_netmask_bits(const char *dotted_quad)
     159{
     160//  int result;
     161//  unsigned a, b, c, d;
     162//  /* Found a netmask...  Check if it is dotted quad */
     163//  if (sscanf(dotted_quad, "%u.%u.%u.%u", &a, &b, &c, &d) != 4)
     164//      return -1;
     165//  if ((a|b|c|d) >> 8)
     166//      return -1; /* one of numbers is >= 256 */
     167//  d |= (a << 24) | (b << 16) | (c << 8); /* IP */
     168//  d = ~d; /* 11110000 -> 00001111 */
     169
     170    /* Shorter version */
     171    int result;
     172    struct in_addr ip;
     173    unsigned d;
     174
     175    if (inet_aton(dotted_quad, &ip) == 0)
     176        return -1; /* malformed dotted IP */
     177    d = ntohl(ip.s_addr); /* IP in host order */
     178    d = ~d; /* 11110000 -> 00001111 */
     179    if (d & (d+1)) /* check that it is in 00001111 form */
     180        return -1; /* no it is not */
     181    result = 32;
     182    while (d) {
     183        d >>= 1;
     184        result--;
     185    }
     186    return result;
     187}
     188#endif
     189
     190static char *parse(const char *command, struct interface_defn_t *ifd)
     191{
    200192    size_t old_pos[MAX_OPT_DEPTH] = { 0 };
    201193    int okay[MAX_OPT_DEPTH] = { 1 };
    202194    int opt_depth = 1;
     195    char *result = NULL;
    203196
    204197    while (*command) {
    205198        switch (*command) {
    206 
    207             default:
    208                 addstr(&result, &len, &pos, command, 1);
     199        default:
     200            addstr(&result, command, 1);
     201            command++;
     202            break;
     203        case '\\':
     204            if (command[1]) {
     205                addstr(&result, command + 1, 1);
     206                command += 2;
     207            } else {
     208                addstr(&result, command, 1);
    209209                command++;
    210                 break;
    211             case '\\':
    212                 if (command[1]) {
    213                     addstr(&result, &len, &pos, command + 1, 1);
    214                     command += 2;
     210            }
     211            break;
     212        case '[':
     213            if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
     214                old_pos[opt_depth] = result ? strlen(result) : 0;
     215                okay[opt_depth] = 1;
     216                opt_depth++;
     217                command += 2;
     218            } else {
     219                addstr(&result, "[", 1);
     220                command++;
     221            }
     222            break;
     223        case ']':
     224            if (command[1] == ']' && opt_depth > 1) {
     225                opt_depth--;
     226                if (!okay[opt_depth]) {
     227                    result[old_pos[opt_depth]] = '\0';
     228                }
     229                command += 2;
     230            } else {
     231                addstr(&result, "]", 1);
     232                command++;
     233            }
     234            break;
     235        case '%':
     236            {
     237                char *nextpercent;
     238                char *varvalue;
     239
     240                command++;
     241                nextpercent = strchr(command, '%');
     242                if (!nextpercent) {
     243                    errno = EUNBALPER;
     244                    free(result);
     245                    return NULL;
     246                }
     247
     248                varvalue = get_var(command, nextpercent - command, ifd);
     249
     250                if (varvalue) {
     251                    addstr(&result, varvalue, strlen(varvalue));
    215252                } else {
    216                     addstr(&result, &len, &pos, command, 1);
    217                     command++;
    218                 }
    219                 break;
    220             case '[':
    221                 if (command[1] == '[' && opt_depth < MAX_OPT_DEPTH) {
    222                     old_pos[opt_depth] = pos;
    223                     okay[opt_depth] = 1;
    224                     opt_depth++;
    225                     command += 2;
    226                 } else {
    227                     addstr(&result, &len, &pos, "[", 1);
    228                     command++;
    229                 }
    230                 break;
    231             case ']':
    232                 if (command[1] == ']' && opt_depth > 1) {
    233                     opt_depth--;
    234                     if (!okay[opt_depth]) {
    235                         pos = old_pos[opt_depth];
    236                         result[pos] = '\0';
    237                     }
    238                     command += 2;
    239                 } else {
    240                     addstr(&result, &len, &pos, "]", 1);
    241                     command++;
    242                 }
    243                 break;
    244             case '%':
    245                 {
    246                     char *nextpercent;
    247                     char *varvalue;
    248 
    249                     command++;
    250                     nextpercent = strchr(command, '%');
    251                     if (!nextpercent) {
    252                         errno = EUNBALPER;
    253                         free(result);
    254                         return (NULL);
    255                     }
    256 
    257                     varvalue = get_var(command, nextpercent - command, ifd);
    258 
    259                     if (varvalue) {
    260                         addstr(&result, &len, &pos, varvalue, strlen(varvalue));
    261                     } else {
    262 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    263                         /* Sigh...  Add a special case for 'ip' to convert from
    264                          * dotted quad to bit count style netmasks.  */
    265                         if (strncmp(command, "bnmask", 6)==0) {
    266                             int res;
    267                             varvalue = get_var("netmask", 7, ifd);
    268                             if (varvalue && (res=count_netmask_bits(varvalue)) > 0) {
    269                                 char argument[255];
    270                                 sprintf(argument, "%d", res);
    271                                 addstr(&result, &len, &pos, argument, strlen(argument));
     253#if ENABLE_FEATURE_IFUPDOWN_IP
     254                    /* Sigh...  Add a special case for 'ip' to convert from
     255                     * dotted quad to bit count style netmasks.  */
     256                    if (strncmp(command, "bnmask", 6) == 0) {
     257                        unsigned res;
     258                        varvalue = get_var("netmask", 7, ifd);
     259                        if (varvalue) {
     260                            res = count_netmask_bits(varvalue);
     261                            if (res > 0) {
     262                                const char *argument = utoa(res);
     263                                addstr(&result, argument, strlen(argument));
    272264                                command = nextpercent + 1;
    273265                                break;
    274266                            }
    275267                        }
    276 #endif
    277                         okay[opt_depth - 1] = 0;
    278268                    }
    279 
    280                     command = nextpercent + 1;
    281                 }
    282                 break;
     269#endif
     270                    okay[opt_depth - 1] = 0;
     271                }
     272
     273                command = nextpercent + 1;
     274            }
     275            break;
    283276        }
    284277    }
     
    287280        errno = EUNBALBRACK;
    288281        free(result);
    289         return(NULL);
     282        return NULL;
    290283    }
    291284
     
    293286        errno = EUNDEFVAR;
    294287        free(result);
    295         return(NULL);
    296     }
    297 
    298     return(result);
    299 }
    300 
    301 static int execute(char *command, struct interface_defn_t *ifd, execfn *exec)
     288        return NULL;
     289    }
     290
     291    return result;
     292}
     293
     294/* execute() returns 1 for success and 0 for failure */
     295static int execute(const char *command, struct interface_defn_t *ifd, execfn *exec)
    302296{
    303297    char *out;
     
    306300    out = parse(command, ifd);
    307301    if (!out) {
    308         return(0);
    309     }
    310     ret = (*exec) (out);
     302        /* parse error? */
     303        return 0;
     304    }
     305    /* out == "": parsed ok but not all needed variables known, skip */
     306    ret = out[0] ? (*exec)(out) : 1;
    311307
    312308    free(out);
    313309    if (ret != 1) {
    314         return(0);
    315     }
    316     return(1);
    317 }
    318 #endif
    319 
    320 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
     310        return 0;
     311    }
     312    return 1;
     313}
     314#endif
     315
     316#if ENABLE_FEATURE_IFUPDOWN_IPV6
    321317static int loopback_up6(struct interface_defn_t *ifd, execfn *exec)
    322318{
    323 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     319#if ENABLE_FEATURE_IFUPDOWN_IP
    324320    int result;
    325     result =execute("ip addr add ::1 dev %iface%", ifd, exec);
     321    result = execute("ip addr add ::1 dev %iface%", ifd, exec);
    326322    result += execute("ip link set %iface% up", ifd, exec);
    327323    return ((result == 2) ? 2 : 0);
    328324#else
    329     return( execute("ifconfig %iface% add ::1", ifd, exec));
     325    return execute("ifconfig %iface% add ::1", ifd, exec);
    330326#endif
    331327}
     
    333329static int loopback_down6(struct interface_defn_t *ifd, execfn *exec)
    334330{
    335 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    336     return(execute("ip link set %iface% down", ifd, exec));
     331#if ENABLE_FEATURE_IFUPDOWN_IP
     332    return execute("ip link set %iface% down", ifd, exec);
    337333#else
    338     return(execute("ifconfig %iface% del ::1", ifd, exec));
     334    return execute("ifconfig %iface% del ::1", ifd, exec);
    339335#endif
    340336}
     
    343339{
    344340    int result;
    345 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    346     result = execute("ip addr add %address%/%netmask% dev %iface% [[label %label%]]", ifd, exec);
    347     result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
    348     result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
     341#if ENABLE_FEATURE_IFUPDOWN_IP
     342    result = execute("ip addr add %address%/%netmask% dev %iface%[[ label %label%]]", ifd, exec);
     343    result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec);
     344    /* Was: "[[ ip ....%gateway% ]]". Removed extra spaces w/o checking */
     345    result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
    349346#else
    350     result = execute("ifconfig %iface% [[media %media%]] [[hw %hwaddress%]] [[mtu %mtu%]] up", ifd, exec);
     347    result = execute("ifconfig %iface%[[ media %media%]][[ hw %hwaddress%]][[ mtu %mtu%]] up", ifd, exec);
    351348    result += execute("ifconfig %iface% add %address%/%netmask%", ifd, exec);
    352     result += execute("[[ route -A inet6 add ::/0 gw %gateway% ]]", ifd, exec);
     349    result += execute("[[route -A inet6 add ::/0 gw %gateway%]]", ifd, exec);
    353350#endif
    354351    return ((result == 3) ? 3 : 0);
     
    357354static int static_down6(struct interface_defn_t *ifd, execfn *exec)
    358355{
    359 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    360     return(execute("ip link set %iface% down", ifd, exec));
     356#if ENABLE_FEATURE_IFUPDOWN_IP
     357    return execute("ip link set %iface% down", ifd, exec);
    361358#else
    362     return(execute("ifconfig %iface% down", ifd, exec));
    363 #endif
    364 }
    365 
    366 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     359    return execute("ifconfig %iface% down", ifd, exec);
     360#endif
     361}
     362
     363#if ENABLE_FEATURE_IFUPDOWN_IP
    367364static int v4tunnel_up(struct interface_defn_t *ifd, execfn *exec)
    368365{
    369366    int result;
    370367    result = execute("ip tunnel add %iface% mode sit remote "
    371                 "%endpoint% [[local %local%]] [[ttl %ttl%]]", ifd, exec);
     368            "%endpoint%[[ local %local%]][[ ttl %ttl%]]", ifd, exec);
    372369    result += execute("ip link set %iface% up", ifd, exec);
    373370    result += execute("ip addr add %address%/%netmask% dev %iface%", ifd, exec);
    374     result += execute("[[ ip route add ::/0 via %gateway% ]]", ifd, exec);
     371    result += execute("[[ip route add ::/0 via %gateway%]]", ifd, exec);
    375372    return ((result == 4) ? 4 : 0);
    376373}
     
    378375static int v4tunnel_down(struct interface_defn_t * ifd, execfn * exec)
    379376{
    380     return( execute("ip tunnel del %iface%", ifd, exec));
    381 }
    382 #endif
    383 
    384 static struct method_t methods6[] = {
    385 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     377    return execute("ip tunnel del %iface%", ifd, exec);
     378}
     379#endif
     380
     381static const struct method_t methods6[] = {
     382#if ENABLE_FEATURE_IFUPDOWN_IP
    386383    { "v4tunnel", v4tunnel_up, v4tunnel_down, },
    387384#endif
     
    390387};
    391388
    392 static struct address_family_t addr_inet6 = {
     389static const struct address_family_t addr_inet6 = {
    393390    "inet6",
    394     sizeof(methods6) / sizeof(struct method_t),
     391    ARRAY_SIZE(methods6),
    395392    methods6
    396393};
    397 #endif /* CONFIG_FEATURE_IFUPDOWN_IPV6 */
    398 
    399 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
     394#endif /* FEATURE_IFUPDOWN_IPV6 */
     395
     396#if ENABLE_FEATURE_IFUPDOWN_IPV4
    400397static int loopback_up(struct interface_defn_t *ifd, execfn *exec)
    401398{
    402 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     399#if ENABLE_FEATURE_IFUPDOWN_IP
    403400    int result;
    404401    result = execute("ip addr add 127.0.0.1/8 dev %iface%", ifd, exec);
     
    406403    return ((result == 2) ? 2 : 0);
    407404#else
    408     return( execute("ifconfig %iface% 127.0.0.1 up", ifd, exec));
     405    return execute("ifconfig %iface% 127.0.0.1 up", ifd, exec);
    409406#endif
    410407}
     
    412409static int loopback_down(struct interface_defn_t *ifd, execfn *exec)
    413410{
    414 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     411#if ENABLE_FEATURE_IFUPDOWN_IP
    415412    int result;
    416413    result = execute("ip addr flush dev %iface%", ifd, exec);
     
    418415    return ((result == 2) ? 2 : 0);
    419416#else
    420     return( execute("ifconfig %iface% 127.0.0.1 down", ifd, exec));
     417    return execute("ifconfig %iface% 127.0.0.1 down", ifd, exec);
    421418#endif
    422419}
     
    425422{
    426423    int result;
    427 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
    428     result = execute("ip addr add %address%/%bnmask% [[broadcast %broadcast%]] "
    429             "dev %iface% [[peer %pointopoint%]] [[label %label%]]", ifd, exec);
    430     result += execute("ip link set [[mtu %mtu%]] [[address %hwaddress%]] %iface% up", ifd, exec);
    431     result += execute("[[ ip route add default via %gateway% dev %iface% ]]", ifd, exec);
     424#if ENABLE_FEATURE_IFUPDOWN_IP
     425    result = execute("ip addr add %address%/%bnmask%[[ broadcast %broadcast%]] "
     426            "dev %iface%[[ peer %pointopoint%]][[ label %label%]]", ifd, exec);
     427    result += execute("ip link set[[ mtu %mtu%]][[ address %hwaddress%]] %iface% up", ifd, exec);
     428    result += execute("[[ip route add default via %gateway% dev %iface%]]", ifd, exec);
    432429    return ((result == 3) ? 3 : 0);
    433430#else
    434     result = execute("ifconfig %iface% %address% netmask %netmask% "
    435                 "[[broadcast %broadcast%]] [[pointopoint %pointopoint%]] "
    436                 "[[media %media%]] [[mtu %mtu%]] [[hw %hwaddress%]] up",
     431    /* ifconfig said to set iface up before it processes hw %hwaddress%,
     432     * which then of course fails. Thus we run two separate ifconfig */
     433    result = execute("ifconfig %iface%[[ hw %hwaddress%]][[ media %media%]][[ mtu %mtu%]] up",
    437434                ifd, exec);
    438     result += execute("[[ route add default gw %gateway% %iface% ]]", ifd, exec);
    439     return ((result == 2) ? 2 : 0);
     435    result += execute("ifconfig %iface% %address% netmask %netmask%"
     436                "[[ broadcast %broadcast%]][[ pointopoint %pointopoint%]] ",
     437                ifd, exec);
     438    result += execute("[[route add default gw %gateway% %iface%]]", ifd, exec);
     439    return ((result == 3) ? 3 : 0);
    440440#endif
    441441}
     
    444444{
    445445    int result;
    446 #ifdef CONFIG_FEATURE_IFUPDOWN_IP
     446#if ENABLE_FEATURE_IFUPDOWN_IP
    447447    result = execute("ip addr flush dev %iface%", ifd, exec);
    448448    result += execute("ip link set %iface% down", ifd, exec);
    449449#else
    450     result = execute("[[ route del default gw %gateway% %iface% ]]", ifd, exec);
     450    result = execute("[[route del default gw %gateway% %iface%]]", ifd, exec);
    451451    result += execute("ifconfig %iface% down", ifd, exec);
    452452#endif
     
    454454}
    455455
    456 static int execable(char *program)
    457 {
    458     struct stat buf;
    459     if (0 == stat(program, &buf)) {
    460         if (S_ISREG(buf.st_mode) && (S_IXUSR & buf.st_mode)) {
    461             return(1);
    462         }
    463     }
    464     return(0);
    465 }
     456#if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     457struct dhcp_client_t
     458{
     459    const char *name;
     460    const char *startcmd;
     461    const char *stopcmd;
     462};
     463
     464static const struct dhcp_client_t ext_dhcp_clients[] = {
     465    { "dhcpcd",
     466        "dhcpcd[[ -h %hostname%]][[ -i %vendor%]][[ -I %clientid%]][[ -l %leasetime%]] %iface%",
     467        "dhcpcd -k %iface%",
     468    },
     469    { "dhclient",
     470        "dhclient -pf /var/run/dhclient.%iface%.pid %iface%",
     471        "kill -9 `cat /var/run/dhclient.%iface%.pid` 2>/dev/null",
     472    },
     473    { "pump",
     474        "pump -i %iface%[[ -h %hostname%]][[ -l %leasehours%]]",
     475        "pump -i %iface% -k",
     476    },
     477    { "udhcpc",
     478        "udhcpc -R -n -p /var/run/udhcpc.%iface%.pid -i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]",
     479        "kill `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null",
     480    },
     481};
     482#endif /* ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCPC */
    466483
    467484static int dhcp_up(struct interface_defn_t *ifd, execfn *exec)
    468485{
    469     if (execable("/sbin/udhcpc")) {
    470         return( execute("udhcpc -n -p /var/run/udhcpc.%iface%.pid -i "
    471                     "%iface% [[-H %hostname%]] [[-c %clientid%]]", ifd, exec));
    472     } else if (execable("/sbin/pump")) {
    473         return( execute("pump -i %iface% [[-h %hostname%]] [[-l %leasehours%]]", ifd, exec));
    474     } else if (execable("/sbin/dhclient")) {
    475         return( execute("dhclient -pf /var/run/dhclient.%iface%.pid %iface%", ifd, exec));
    476     } else if (execable("/sbin/dhcpcd")) {
    477         return( execute("dhcpcd [[-h %hostname%]] [[-i %vendor%]] [[-I %clientid%]] "
    478                     "[[-l %leasetime%]] %iface%", ifd, exec));
    479     }
    480     return(0);
     486#if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     487    int i;
     488#if ENABLE_FEATURE_IFUPDOWN_IP
     489    /* ip doesn't up iface when it configures it (unlike ifconfig) */
     490    if (!execute("ip link set %iface% up", ifd, exec))
     491        return 0;
     492#endif
     493    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
     494        if (exists_execable(ext_dhcp_clients[i].name))
     495            return execute(ext_dhcp_clients[i].startcmd, ifd, exec);
     496    }
     497    bb_error_msg("no dhcp clients found");
     498    return 0;
     499#elif ENABLE_APP_UDHCPC
     500#if ENABLE_FEATURE_IFUPDOWN_IP
     501    /* ip doesn't up iface when it configures it (unlike ifconfig) */
     502    if (!execute("ip link set %iface% up", ifd, exec))
     503        return 0;
     504#endif
     505    return execute("udhcpc -R -n -p /var/run/udhcpc.%iface%.pid "
     506            "-i %iface%[[ -H %hostname%]][[ -c %clientid%]][[ -s %script%]]",
     507            ifd, exec);
     508#else
     509    return 0; /* no dhcp support */
     510#endif
    481511}
    482512
    483513static int dhcp_down(struct interface_defn_t *ifd, execfn *exec)
    484514{
    485     int result = 0;
    486     if (execable("/sbin/udhcpc")) {
    487         /* SIGUSR2 forces udhcpc to release the current lease and go inactive,
    488          * and SIGTERM causes udhcpc to exit.  Signals are queued and processed
    489          * sequentially so we don't need to sleep */
    490         result = execute("kill -USR2 `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
    491         result += execute("kill -TERM `cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
    492     } else if (execable("/sbin/pump")) {
    493         result = execute("pump -i %iface% -k", ifd, exec);
    494     } else if (execable("/sbin/dhclient")) {
    495         result = execute("kill -9 `cat /var/run/dhclient.%iface%.pid` 2>/dev/null", ifd, exec);
    496     } else if (execable("/sbin/dhcpcd")) {
    497         result = execute("dhcpcd -k %iface%", ifd, exec);
    498     }
    499     return (result || static_down(ifd, exec));
     515#if ENABLE_FEATURE_IFUPDOWN_EXTERNAL_DHCP
     516    int i;
     517    for (i = 0; i < ARRAY_SIZE(ext_dhcp_clients); i++) {
     518        if (exists_execable(ext_dhcp_clients[i].name))
     519            return execute(ext_dhcp_clients[i].stopcmd, ifd, exec);
     520    }
     521    bb_error_msg("no dhcp clients found, using static interface shutdown");
     522    return static_down(ifd, exec);
     523#elif ENABLE_APP_UDHCPC
     524    return execute("kill "
     525                   "`cat /var/run/udhcpc.%iface%.pid` 2>/dev/null", ifd, exec);
     526#else
     527    return 0; /* no dhcp support */
     528#endif
     529}
     530
     531static int manual_up_down(struct interface_defn_t *ifd, execfn *exec)
     532{
     533    return 1;
    500534}
    501535
    502536static int bootp_up(struct interface_defn_t *ifd, execfn *exec)
    503537{
    504     return( execute("bootpc [[--bootfile %bootfile%]] --dev %iface% "
    505                 "[[--server %server%]] [[--hwaddr %hwaddr%]] "
    506                 "--returniffail --serverbcast", ifd, exec));
     538    return execute("bootpc[[ --bootfile %bootfile%]] --dev %iface%"
     539            "[[ --server %server%]][[ --hwaddr %hwaddr%]]"
     540            " --returniffail --serverbcast", ifd, exec);
    507541}
    508542
    509543static int ppp_up(struct interface_defn_t *ifd, execfn *exec)
    510544{
    511     return( execute("pon [[%provider%]]", ifd, exec));
     545    return execute("pon[[ %provider%]]", ifd, exec);
    512546}
    513547
    514548static int ppp_down(struct interface_defn_t *ifd, execfn *exec)
    515549{
    516     return( execute("poff [[%provider%]]", ifd, exec));
     550    return execute("poff[[ %provider%]]", ifd, exec);
    517551}
    518552
    519553static int wvdial_up(struct interface_defn_t *ifd, execfn *exec)
    520554{
    521     return( execute("/sbin/start-stop-daemon --start -x /usr/bin/wvdial "
    522                 "-p /var/run/wvdial.%iface% -b -m -- [[ %provider% ]]", ifd, exec));
     555    return execute("start-stop-daemon --start -x wvdial "
     556        "-p /var/run/wvdial.%iface% -b -m --[[ %provider%]]", ifd, exec);
    523557}
    524558
    525559static int wvdial_down(struct interface_defn_t *ifd, execfn *exec)
    526560{
    527     return( execute("/sbin/start-stop-daemon --stop -x /usr/bin/wvdial "
    528                 "-p /var/run/wvdial.%iface% -s 2", ifd, exec));
    529 }
    530 
    531 static struct method_t methods[] =
    532 {
     561    return execute("start-stop-daemon --stop -x wvdial "
     562            "-p /var/run/wvdial.%iface% -s 2", ifd, exec);
     563}
     564
     565static const struct method_t methods[] = {
     566    { "manual", manual_up_down, manual_up_down, },
    533567    { "wvdial", wvdial_up, wvdial_down, },
    534568    { "ppp", ppp_up, ppp_down, },
     
    539573};
    540574
    541 static struct address_family_t addr_inet =
    542 {
     575static const struct address_family_t addr_inet = {
    543576    "inet",
    544     sizeof(methods) / sizeof(struct method_t),
     577    ARRAY_SIZE(methods),
    545578    methods
    546579};
    547580
    548 #endif  /* ifdef CONFIG_FEATURE_IFUPDOWN_IPV4 */
     581#endif  /* if ENABLE_FEATURE_IFUPDOWN_IPV4 */
    549582
    550583static char *next_word(char **buf)
     
    553586    char *word;
    554587
    555     if ((buf == NULL) || (*buf == NULL) || (**buf == '\0')) {
     588    if (!buf || !*buf || !**buf) {
    556589        return NULL;
    557590    }
    558591
    559592    /* Skip over leading whitespace */
    560     word = *buf;
    561     while (isspace(*word)) {
    562         ++word;
    563     }
     593    word = skip_whitespace(*buf);
    564594
    565595    /* Skip over comments */
    566596    if (*word == '#') {
    567         return(NULL);
     597        return NULL;
    568598    }
    569599
     
    571601    length = strcspn(word, " \t\n");
    572602    if (length == 0) {
    573         return(NULL);
     603        return NULL;
    574604    }
    575605    *buf = word + length;
     
    583613}
    584614
    585 static struct address_family_t *get_address_family(struct address_family_t *af[], char *name)
     615static const struct address_family_t *get_address_family(const struct address_family_t *const af[], char *name)
    586616{
    587617    int i;
     618
     619    if (!name)
     620        return NULL;
    588621
    589622    for (i = 0; af[i]; i++) {
     
    595628}
    596629
    597 static struct method_t *get_method(struct address_family_t *af, char *name)
     630static const struct method_t *get_method(const struct address_family_t *af, char *name)
    598631{
    599632    int i;
     633
     634    if (!name)
     635        return NULL;
    600636
    601637    for (i = 0; i < af->n_methods; i++) {
     
    604640        }
    605641    }
    606     return(NULL);
     642    return NULL;
    607643}
    608644
    609645static const llist_t *find_list_string(const llist_t *list, const char *string)
    610646{
     647    if (string == NULL)
     648        return NULL;
     649
    611650    while (list) {
    612651        if (strcmp(list->data, string) == 0) {
    613             return(list);
     652            return list;
    614653        }
    615654        list = list->link;
    616655    }
    617     return(NULL);
     656    return NULL;
    618657}
    619658
    620659static struct interfaces_file_t *read_interfaces(const char *filename)
    621660{
    622 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
     661#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    623662    struct mapping_defn_t *currmap = NULL;
    624663#endif
     
    633672    defn = xzalloc(sizeof(struct interfaces_file_t));
    634673
    635     f = bb_xfopen(filename, "r");
    636 
    637     while ((buf = bb_get_chomped_line_from_file(f)) != NULL) {
     674    f = xfopen(filename, "r");
     675
     676    while ((buf = xmalloc_getline(f)) != NULL) {
    638677        char *buf_ptr = buf;
    639678
     
    645684
    646685        if (strcmp(firstword, "mapping") == 0) {
    647 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
     686#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    648687            currmap = xzalloc(sizeof(struct mapping_defn_t));
    649688
     
    654693                }
    655694
    656                 currmap->match[currmap->n_matches++] = bb_xstrdup(firstword);
     695                currmap->match[currmap->n_matches++] = xstrdup(firstword);
    657696            }
    658697            currmap->max_mappings = 0;
     
    672711            currently_processing = MAPPING;
    673712        } else if (strcmp(firstword, "iface") == 0) {
    674             {
    675                 char *iface_name;
    676                 char *address_family_name;
    677                 char *method_name;
    678                 struct address_family_t *addr_fams[] = {
    679 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV4
    680                     &addr_inet,
    681 #endif
    682 #ifdef CONFIG_FEATURE_IFUPDOWN_IPV6
    683                     &addr_inet6,
    684 #endif
    685                     NULL
    686                 };
    687 
    688                 currif = xzalloc(sizeof(struct interface_defn_t));
    689                 iface_name = next_word(&buf_ptr);
    690                 address_family_name = next_word(&buf_ptr);
    691                 method_name = next_word(&buf_ptr);
    692 
    693                 if (buf_ptr == NULL) {
    694                     bb_error_msg("too few parameters for line \"%s\"", buf);
     713            static const struct address_family_t *const addr_fams[] = {
     714#if ENABLE_FEATURE_IFUPDOWN_IPV4
     715                &addr_inet,
     716#endif
     717#if ENABLE_FEATURE_IFUPDOWN_IPV6
     718                &addr_inet6,
     719#endif
     720                NULL
     721            };
     722
     723            char *iface_name;
     724            char *address_family_name;
     725            char *method_name;
     726            llist_t *iface_list;
     727
     728            currif = xzalloc(sizeof(struct interface_defn_t));
     729            iface_name = next_word(&buf_ptr);
     730            address_family_name = next_word(&buf_ptr);
     731            method_name = next_word(&buf_ptr);
     732
     733            if (buf_ptr == NULL) {
     734                bb_error_msg("too few parameters for line \"%s\"", buf);
     735                return NULL;
     736            }
     737
     738            /* ship any trailing whitespace */
     739            buf_ptr = skip_whitespace(buf_ptr);
     740
     741            if (buf_ptr[0] != '\0') {
     742                bb_error_msg("too many parameters \"%s\"", buf);
     743                return NULL;
     744            }
     745
     746            currif->iface = xstrdup(iface_name);
     747
     748            currif->address_family = get_address_family(addr_fams, address_family_name);
     749            if (!currif->address_family) {
     750                bb_error_msg("unknown address type \"%s\"", address_family_name);
     751                return NULL;
     752            }
     753
     754            currif->method = get_method(currif->address_family, method_name);
     755            if (!currif->method) {
     756                bb_error_msg("unknown method \"%s\"", method_name);
     757                return NULL;
     758            }
     759
     760            for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
     761                struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
     762                if ((strcmp(tmp->iface, currif->iface) == 0) &&
     763                    (tmp->address_family == currif->address_family)) {
     764                    bb_error_msg("duplicate interface \"%s\"", tmp->iface);
    695765                    return NULL;
    696766                }
    697 
    698                 /* ship any trailing whitespace */
    699                 while (isspace(*buf_ptr)) {
    700                     ++buf_ptr;
    701                 }
    702 
    703                 if (buf_ptr[0] != '\0') {
    704                     bb_error_msg("too many parameters \"%s\"", buf);
    705                     return NULL;
    706                 }
    707 
    708                 currif->iface = bb_xstrdup(iface_name);
    709 
    710                 currif->address_family = get_address_family(addr_fams, address_family_name);
    711                 if (!currif->address_family) {
    712                     bb_error_msg("unknown address type \"%s\"", address_family_name);
    713                     return NULL;
    714                 }
    715 
    716                 currif->method = get_method(currif->address_family, method_name);
    717                 if (!currif->method) {
    718                     bb_error_msg("unknown method \"%s\"", method_name);
    719                     return NULL;
    720                 }
    721 
    722 
    723                 {
    724                     llist_t *iface_list;
    725                     for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
    726                         struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
    727                         if ((strcmp(tmp->iface, currif->iface) == 0) &&
    728                             (tmp->address_family == currif->address_family)) {
    729                             bb_error_msg("duplicate interface \"%s\"", tmp->iface);
    730                             return NULL;
    731                         }
    732                     }
    733 
    734                     llist_add_to_end(&(defn->ifaces), (char*)currif);
    735                 }
    736                 debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
    737             }
     767            }
     768            llist_add_to_end(&(defn->ifaces), (char*)currif);
     769
     770            debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
    738771            currently_processing = IFACE;
    739772        } else if (strcmp(firstword, "auto") == 0) {
     
    746779
    747780                /* Add the interface to the list */
    748                 llist_add_to_end(&(defn->autointerfaces), bb_xstrdup(firstword));
     781                llist_add_to_end(&(defn->autointerfaces), xstrdup(firstword));
    749782                debug_noise("\nauto %s\n", firstword);
    750783            }
     
    752785        } else {
    753786            switch (currently_processing) {
    754                 case IFACE:
    755                     {
    756                         int i;
    757 
    758                         if (strlen(buf_ptr) == 0) {
    759                             bb_error_msg("option with empty value \"%s\"", buf);
    760                             return NULL;
    761                         }
    762 
    763                         if (strcmp(firstword, "up") != 0
    764                                 && strcmp(firstword, "down") != 0
    765                                 && strcmp(firstword, "pre-up") != 0
    766                                 && strcmp(firstword, "post-down") != 0) {
    767                             for (i = 0; i < currif->n_options; i++) {
    768                                 if (strcmp(currif->option[i].name, firstword) == 0) {
    769                                     bb_error_msg("duplicate option \"%s\"", buf);
    770                                     return NULL;
    771                                 }
     787            case IFACE:
     788                {
     789                    int i;
     790
     791                    if (strlen(buf_ptr) == 0) {
     792                        bb_error_msg("option with empty value \"%s\"", buf);
     793                        return NULL;
     794                    }
     795
     796                    if (strcmp(firstword, "up") != 0
     797                            && strcmp(firstword, "down") != 0
     798                            && strcmp(firstword, "pre-up") != 0
     799                            && strcmp(firstword, "post-down") != 0) {
     800                        for (i = 0; i < currif->n_options; i++) {
     801                            if (strcmp(currif->option[i].name, firstword) == 0) {
     802                                bb_error_msg("duplicate option \"%s\"", buf);
     803                                return NULL;
    772804                            }
    773805                        }
    774806                    }
    775                     if (currif->n_options >= currif->max_options) {
    776                         struct variable_t *opt;
    777 
    778                         currif->max_options = currif->max_options + 10;
    779                         opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options);
    780                         currif->option = opt;
     807                }
     808                if (currif->n_options >= currif->max_options) {
     809                    struct variable_t *opt;
     810
     811                    currif->max_options = currif->max_options + 10;
     812                    opt = xrealloc(currif->option, sizeof(*opt) * currif->max_options);
     813                    currif->option = opt;
     814                }
     815                currif->option[currif->n_options].name = xstrdup(firstword);
     816                currif->option[currif->n_options].value = xstrdup(buf_ptr);
     817                if (!currif->option[currif->n_options].name) {
     818                    perror(filename);
     819                    return NULL;
     820                }
     821                if (!currif->option[currif->n_options].value) {
     822                    perror(filename);
     823                    return NULL;
     824                }
     825                debug_noise("\t%s=%s\n", currif->option[currif->n_options].name,
     826                        currif->option[currif->n_options].value);
     827                currif->n_options++;
     828                break;
     829            case MAPPING:
     830#if ENABLE_FEATURE_IFUPDOWN_MAPPING
     831                if (strcmp(firstword, "script") == 0) {
     832                    if (currmap->script != NULL) {
     833                        bb_error_msg("duplicate script in mapping \"%s\"", buf);
     834                        return NULL;
     835                    } else {
     836                        currmap->script = xstrdup(next_word(&buf_ptr));
    781837                    }
    782                     currif->option[currif->n_options].name = bb_xstrdup(firstword);
    783                     currif->option[currif->n_options].value = bb_xstrdup(buf_ptr);
    784                     if (!currif->option[currif->n_options].name) {
    785                         perror(filename);
    786                         return NULL;
     838                } else if (strcmp(firstword, "map") == 0) {
     839                    if (currmap->max_mappings == currmap->n_mappings) {
     840                        currmap->max_mappings = currmap->max_mappings * 2 + 1;
     841                        currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings);
    787842                    }
    788                     if (!currif->option[currif->n_options].value) {
    789                         perror(filename);
    790                         return NULL;
    791                     }
    792                     debug_noise("\t%s=%s\n", currif->option[currif->n_options].name,
    793                             currif->option[currif->n_options].value);
    794                     currif->n_options++;
    795                     break;
    796                 case MAPPING:
    797 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
    798                     if (strcmp(firstword, "script") == 0) {
    799                         if (currmap->script != NULL) {
    800                             bb_error_msg("duplicate script in mapping \"%s\"", buf);
    801                             return NULL;
    802                         } else {
    803                             currmap->script = bb_xstrdup(next_word(&buf_ptr));
    804                         }
    805                     } else if (strcmp(firstword, "map") == 0) {
    806                         if (currmap->max_mappings == currmap->n_mappings) {
    807                             currmap->max_mappings = currmap->max_mappings * 2 + 1;
    808                             currmap->mapping = xrealloc(currmap->mapping, sizeof(char *) * currmap->max_mappings);
    809                         }
    810                         currmap->mapping[currmap->n_mappings] = bb_xstrdup(next_word(&buf_ptr));
    811                         currmap->n_mappings++;
    812                     } else {
    813                         bb_error_msg("misplaced option \"%s\"", buf);
    814                         return NULL;
    815                     }
    816 #endif
    817                     break;
    818                 case NONE:
    819                 default:
     843                    currmap->mapping[currmap->n_mappings] = xstrdup(next_word(&buf_ptr));
     844                    currmap->n_mappings++;
     845                } else {
    820846                    bb_error_msg("misplaced option \"%s\"", buf);
    821847                    return NULL;
     848                }
     849#endif
     850                break;
     851            case NONE:
     852            default:
     853                bb_error_msg("misplaced option \"%s\"", buf);
     854                return NULL;
    822855            }
    823856        }
     
    825858    }
    826859    if (ferror(f) != 0) {
    827         bb_perror_msg_and_die("%s", filename);
     860        /* ferror does NOT set errno! */
     861        bb_error_msg_and_die("%s: I/O error", filename);
    828862    }
    829863    fclose(f);
     
    832866}
    833867
    834 static char *setlocalenv(char *format, const char *name, const char *value)
     868static char *setlocalenv(const char *format, const char *name, const char *value)
    835869{
    836870    char *result;
     
    838872    char *there;
    839873
    840     result = bb_xasprintf(format, name, value);
     874    result = xasprintf(format, name, value);
    841875
    842876    for (here = there = result; *there != '=' && *there; there++) {
     
    863897    char **ppch;
    864898
    865     if (__myenviron != NULL) {
    866         for (ppch = __myenviron; *ppch; ppch++) {
     899    if (my_environ != NULL) {
     900        for (ppch = my_environ; *ppch; ppch++) {
    867901            free(*ppch);
    868902            *ppch = NULL;
    869903        }
    870         free(__myenviron);
    871     }
    872     __myenviron = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));
    873     environend = __myenviron;
     904        free(my_environ);
     905    }
     906    my_environ = xzalloc(sizeof(char *) * (n_env_entries + 1 /* for final NULL */ ));
     907    environend = my_environ;
    874908
    875909    for (i = 0; i < iface->n_options; i++) {
    876910        if (strcmp(iface->option[i].name, "up") == 0
    877                 || strcmp(iface->option[i].name, "down") == 0
    878                 || strcmp(iface->option[i].name, "pre-up") == 0
    879                 || strcmp(iface->option[i].name, "post-down") == 0) {
     911         || strcmp(iface->option[i].name, "down") == 0
     912         || strcmp(iface->option[i].name, "pre-up") == 0
     913         || strcmp(iface->option[i].name, "post-down") == 0
     914        ) {
    880915            continue;
    881916        }
     
    887922    *(environend++) = setlocalenv("%s=%s", "METHOD", iface->method->name);
    888923    *(environend++) = setlocalenv("%s=%s", "MODE", mode);
    889     *(environend++) = setlocalenv("%s=%s", "PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin");
     924    *(environend++) = setlocalenv("%s=%s", "PATH", startup_PATH);
    890925}
    891926
    892927static int doit(char *str)
    893928{
    894     if (verbose || no_act) {
    895         printf("%s\n", str);
    896     }
    897     if (!no_act) {
     929    if (option_mask32 & (OPT_no_act|OPT_verbose)) {
     930        puts(str);
     931    }
     932    if (!(option_mask32 & OPT_no_act)) {
    898933        pid_t child;
    899934        int status;
    900935
    901936        fflush(NULL);
    902         switch (child = fork()) {
    903             case -1:        /* failure */
    904                 return 0;
    905             case 0:     /* child */
    906                 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, __myenviron);
    907                 exit(127);
     937        child = fork();
     938        switch (child) {
     939        case -1: /* failure */
     940            return 0;
     941        case 0: /* child */
     942            execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ);
     943            exit(127);
    908944        }
    909945        waitpid(child, &status, 0);
     
    912948        }
    913949    }
    914     return (1);
     950    return 1;
    915951}
    916952
     
    927963    }
    928964
    929     buf = bb_xasprintf("run-parts /etc/network/if-%s.d", opt);
    930     if (doit(buf) != 1) {
    931         return 0;
    932     }
    933     return 1;
    934 }
    935 
    936 static int check(char *str) {
     965    buf = xasprintf("run-parts /etc/network/if-%s.d", opt);
     966    /* heh, we don't bother free'ing it */
     967    return doit(buf);
     968}
     969
     970static int check(char *str)
     971{
    937972    return str != NULL;
    938973}
     
    940975static int iface_up(struct interface_defn_t *iface)
    941976{
    942     if (!iface->method->up(iface,check)) return -1;
     977    if (!iface->method->up(iface, check)) return -1;
    943978    set_environ(iface, "start");
    944979    if (!execute_all(iface, "pre-up")) return 0;
     
    958993}
    959994
    960 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
     995#if ENABLE_FEATURE_IFUPDOWN_MAPPING
    961996static int popen2(FILE **in, FILE **out, char *command, ...)
    962997{
     
    9871022    fflush(NULL);
    9881023    switch (pid = fork()) {
    989         case -1:            /* failure */
    990             close(infd[0]);
    991             close(infd[1]);
    992             close(outfd[0]);
    993             close(outfd[1]);
    994             return 0;
    995         case 0:         /* child */
    996             dup2(infd[0], 0);
    997             dup2(outfd[1], 1);
    998             close(infd[0]);
    999             close(infd[1]);
    1000             close(outfd[0]);
    1001             close(outfd[1]);
    1002             execvp(command, argv);
    1003             exit(127);
    1004         default:            /* parent */
    1005             *in = fdopen(infd[1], "w");
    1006             *out = fdopen(outfd[0], "r");
    1007             close(infd[0]);
    1008             close(outfd[1]);
    1009             return pid;
     1024    case -1:            /* failure */
     1025        close(infd[0]);
     1026        close(infd[1]);
     1027        close(outfd[0]);
     1028        close(outfd[1]);
     1029        return 0;
     1030    case 0:         /* child */
     1031        dup2(infd[0], 0);
     1032        dup2(outfd[1], 1);
     1033        close(infd[0]);
     1034        close(infd[1]);
     1035        close(outfd[0]);
     1036        close(outfd[1]);
     1037        BB_EXECVP(command, argv);
     1038        exit(127);
     1039    default:            /* parent */
     1040        *in = fdopen(infd[1], "w");
     1041        *out = fdopen(outfd[0], "r");
     1042        close(infd[0]);
     1043        close(outfd[1]);
     1044        return pid;
    10101045    }
    10111046    /* unreached */
     
    10181053    pid_t pid;
    10191054
    1020     char *logical = bb_xstrdup(physical);
     1055    char *logical = xstrdup(physical);
    10211056
    10221057    /* Run the mapping script. */
     
    10381073         * grab a line of output and use that as the name of the
    10391074         * logical interface. */
    1040         char *new_logical = (char *)xmalloc(MAX_INTERFACE_LENGTH);
     1075        char *new_logical = xmalloc(MAX_INTERFACE_LENGTH);
    10411076
    10421077        if (fgets(new_logical, MAX_INTERFACE_LENGTH, out)) {
     
    10621097    return logical;
    10631098}
    1064 #endif /* CONFIG_FEATURE_IFUPDOWN_MAPPING */
     1099#endif /* FEATURE_IFUPDOWN_MAPPING */
    10651100
    10661101static llist_t *find_iface_state(llist_t *state_list, const char *iface)
     
    10701105
    10711106    while (search) {
    1072         if ((strncmp(search->data, iface, iface_len) == 0) &&
    1073                 (search->data[iface_len] == '=')) {
    1074             return(search);
     1107        if ((strncmp(search->data, iface, iface_len) == 0)
     1108         && (search->data[iface_len] == '=')) {
     1109            return search;
    10751110        }
    10761111        search = search->link;
    10771112    }
    1078     return(NULL);
    1079 }
    1080 
     1113    return NULL;
     1114}
     1115
     1116/* read the previous state from the state file */
     1117static llist_t *read_iface_state(void)
     1118{
     1119    llist_t *state_list = NULL;
     1120    FILE *state_fp = fopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "r");
     1121
     1122    if (state_fp) {
     1123        char *start, *end_ptr;
     1124        while ((start = xmalloc_fgets(state_fp)) != NULL) {
     1125            /* We should only need to check for a single character */
     1126            end_ptr = start + strcspn(start, " \t\n");
     1127            *end_ptr = '\0';
     1128            llist_add_to(&state_list, start);
     1129        }
     1130        fclose(state_fp);
     1131    }
     1132    return state_list;
     1133}
     1134
     1135
     1136int ifupdown_main(int argc, char **argv);
    10811137int ifupdown_main(int argc, char **argv)
    10821138{
    1083     int (*cmds) (struct interface_defn_t *) = NULL;
     1139    int (*cmds)(struct interface_defn_t *) = NULL;
    10841140    struct interfaces_file_t *defn;
    1085     llist_t *state_list = NULL;
    10861141    llist_t *target_list = NULL;
    10871142    const char *interfaces = "/etc/network/interfaces";
    1088     const char *statefile = "/var/run/ifstate";
    1089 
    1090 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
    1091     int run_mappings = 1;
    1092 #endif
    1093     int do_all = 0;
    1094     int force = 0;
    1095     int any_failures = 0;
    1096     int i;
    1097 
    1098     if (bb_applet_name[2] == 'u') {
     1143    bool any_failures = 0;
     1144
     1145    cmds = iface_down;
     1146    if (applet_name[2] == 'u') {
    10991147        /* ifup command */
    11001148        cmds = iface_up;
     1149    }
     1150
     1151    getopt32(argv, OPTION_STR, &interfaces);
     1152    if (argc - optind > 0) {
     1153        if (DO_ALL) bb_show_usage();
    11011154    } else {
    1102         /* ifdown command */
    1103         cmds = iface_down;
    1104     }
    1105 
    1106 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
    1107     while ((i = getopt(argc, argv, "i:hvnamf")) != -1)
    1108 #else
    1109         while ((i = getopt(argc, argv, "i:hvnaf")) != -1)
    1110 #endif
    1111         {
    1112             switch (i) {
    1113                 case 'i':   /* interfaces */
    1114                     interfaces = optarg;
    1115                     break;
    1116                 case 'v':   /* verbose */
    1117                     verbose = 1;
    1118                     break;
    1119                 case 'a':   /* all */
    1120                     do_all = 1;
    1121                     break;
    1122                 case 'n':   /* no-act */
    1123                     no_act = 1;
    1124                     break;
    1125 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
    1126                 case 'm':   /* no-mappings */
    1127                     run_mappings = 0;
    1128                     break;
    1129 #endif
    1130                 case 'f':   /* force */
    1131                     force = 1;
    1132                     break;
    1133                 default:
    1134                     bb_show_usage();
    1135                     break;
    1136             }
    1137         }
    1138 
    1139     if (argc - optind > 0) {
    1140         if (do_all) {
    1141             bb_show_usage();
    1142         }
    1143     } else {
    1144         if (!do_all) {
    1145             bb_show_usage();
    1146         }
     1155        if (!DO_ALL) bb_show_usage();
    11471156    }
    11481157
     
    11521161
    11531162    if (!defn) {
    1154         exit(EXIT_FAILURE);
    1155     }
     1163        return EXIT_FAILURE;
     1164    }
     1165
     1166    startup_PATH = getenv("PATH");
     1167    if (!startup_PATH) startup_PATH = "";
    11561168
    11571169    /* Create a list of interfaces to work on */
    1158     if (do_all) {
    1159         if (cmds == iface_up) {
    1160             target_list = defn->autointerfaces;
    1161         } else {
    1162             /* iface_down */
    1163             const llist_t *list = state_list;
    1164             while (list) {
    1165                 llist_add_to_end(&target_list, bb_xstrdup(list->data));
    1166                 list = list->link;
    1167             }
    1168             target_list = defn->autointerfaces;
    1169         }
     1170    if (DO_ALL) {
     1171        target_list = defn->autointerfaces;
    11701172    } else {
    11711173        llist_add_to_end(&target_list, argv[optind]);
    11721174    }
    1173 
    11741175
    11751176    /* Update the interfaces */
     
    11801181        char *liface;
    11811182        char *pch;
    1182         int okay = 0;
    1183         int cmds_ret;
    1184 
    1185         iface = bb_xstrdup(target_list->data);
     1183        bool okay = 0;
     1184        unsigned cmds_ret;
     1185
     1186        iface = xstrdup(target_list->data);
    11861187        target_list = target_list->link;
    11871188
     
    11891190        if (pch) {
    11901191            *pch = '\0';
    1191             liface = bb_xstrdup(pch + 1);
     1192            liface = xstrdup(pch + 1);
    11921193        } else {
    1193             liface = bb_xstrdup(iface);
    1194         }
    1195 
    1196         if (!force) {
     1194            liface = xstrdup(iface);
     1195        }
     1196
     1197        if (!FORCE) {
     1198            llist_t *state_list = read_iface_state();
    11971199            const llist_t *iface_state = find_iface_state(state_list, iface);
    11981200
     
    12051207            } else {
    12061208                /* ifdown */
    1207                 if (iface_state) {
     1209                if (!iface_state) {
    12081210                    bb_error_msg("interface %s not configured", iface);
    12091211                    continue;
    12101212                }
    12111213            }
    1212         }
    1213 
    1214 #ifdef CONFIG_FEATURE_IFUPDOWN_MAPPING
    1215         if ((cmds == iface_up) && run_mappings) {
     1214            llist_free(state_list, free);
     1215        }
     1216
     1217#if ENABLE_FEATURE_IFUPDOWN_MAPPING
     1218        if ((cmds == iface_up) && !NO_MAPPINGS) {
    12161219            struct mapping_defn_t *currmap;
    12171220
    12181221            for (currmap = defn->mappings; currmap; currmap = currmap->next) {
    1219 
     1222                int i;
    12201223                for (i = 0; i < currmap->n_matches; i++) {
    12211224                    if (fnmatch(currmap->match[i], liface, 0) != 0)
    12221225                        continue;
    1223                     if (verbose) {
     1226                    if (VERBOSE) {
    12241227                        printf("Running mapping script %s on %s\n", currmap->script, liface);
    12251228                    }
     
    12301233        }
    12311234#endif
    1232 
    12331235
    12341236        iface_list = defn->ifaces;
     
    12461248                cmds_ret = cmds(currif);
    12471249                if (cmds_ret == -1) {
    1248                     bb_error_msg("Don't seem to have all the variables for %s/%s.",
     1250                    bb_error_msg("don't seem to have all the variables for %s/%s",
    12491251                            liface, currif->address_family->name);
    1250                     any_failures += 1;
     1252                    any_failures = 1;
    12511253                } else if (cmds_ret == 0) {
    1252                     any_failures += 1;
     1254                    any_failures = 1;
    12531255                }
    12541256
     
    12571259            iface_list = iface_list->link;
    12581260        }
    1259         if (verbose) {
    1260             printf("\n");
    1261         }
    1262 
    1263         if (!okay && !force) {
    1264             bb_error_msg("Ignoring unknown interface %s", liface);
    1265             any_failures += 1;
    1266         } else {
     1261        if (VERBOSE) {
     1262            puts("");
     1263        }
     1264
     1265        if (!okay && !FORCE) {
     1266            bb_error_msg("ignoring unknown interface %s", liface);
     1267            any_failures = 1;
     1268        } else if (!NO_ACT) {
     1269            /* update the state file */
     1270            FILE *state_fp;
     1271            llist_t *state;
     1272            llist_t *state_list = read_iface_state();
    12671273            llist_t *iface_state = find_iface_state(state_list, iface);
    12681274
    12691275            if (cmds == iface_up) {
    1270                 char *newiface = bb_xasprintf("%s=%s", iface, liface);
     1276                char * const newiface = xasprintf("%s=%s", iface, liface);
    12711277                if (iface_state == NULL) {
    12721278                    llist_add_to_end(&state_list, newiface);
     
    12761282                }
    12771283            } else {
    1278                 /* Remove an interface from the linked list */
     1284                /* Remove an interface from state_list */
     1285                llist_unlink(&state_list, iface_state);
    12791286                free(llist_pop(&iface_state));
    12801287            }
    1281         }
    1282     }
    1283 
    1284     /* Actually write the new state */
    1285     if (!no_act) {
    1286         FILE *state_fp = NULL;
    1287 
    1288         state_fp = bb_xfopen(statefile, "w");
    1289         while (state_list) {
    1290             if (state_list->data) {
    1291                 fputs(state_list->data, state_fp);
    1292                 fputc('\n', state_fp);
    1293             }
    1294             state_list = state_list->link;
    1295         }
    1296         fclose(state_fp);
    1297     }
    1298 
    1299     if (any_failures)
    1300         return 1;
    1301     return 0;
    1302 }
     1288
     1289            /* Actually write the new state */
     1290            state_fp = xfopen(CONFIG_IFUPDOWN_IFSTATE_PATH, "w");
     1291            state = state_list;
     1292            while (state) {
     1293                if (state->data) {
     1294                    fprintf(state_fp, "%s\n", state->data);
     1295                }
     1296                state = state->link;
     1297            }
     1298            fclose(state_fp);
     1299            llist_free(state_list, free);
     1300        }
     1301    }
     1302
     1303    return any_failures;
     1304}
Note: See TracChangeset for help on using the changeset viewer.