关于Busybox对interfaces文件的解析过程

写了那么多,最后保存时却只剩这一点。。。 这博客真难用。。。

网络的启动是通过执行脚本:
/etc/init.d/networking start
脚本中调用了命令 ifup -a;

ls -l /sbin/ifup
lrwxrwxrwx 1 admin sysadmin 14 Jan 1 1970 /sbin/ifup -> ../bin/busybox

可见,该命令被集成到busbox中去了,如果要看详细的过程那只能看源码了.
找到busbox中的 ifupdown_main 函数,该函数用来执行ifup ifdown命令。

int ifupdown_main(int argc, char **argv)
{
    int (*cmds)(struct interface_defn_t *);
    struct interfaces_file_t *defn;
    llist_t *target_list = NULL;
    const char *interfaces = "/etc/network/interfaces";
    bool any_failures = 0;

    cmds = iface_down;
    if (applet_name[2] == 'u') {
        /* ifup command */
        cmds = iface_up;
    }
...
    defn = read_interfaces(interfaces);
    debug_noise("\ndone reading %s\n\n", interfaces);

    startup_PATH = getenv("PATH");
    if (!startup_PATH) startup_PATH = "";

    /* Create a list of interfaces to work on */
    if (DO_ALL) {
        target_list = defn->autointerfaces;
    } else {
        llist_add_to_end(&target_list, argv[optind]);
    }

    /* Update the interfaces */
    while (target_list) {
        llist_t *iface_list;
        struct interface_defn_t *currif;
        char *iface;
        char *liface;
        char *pch;
        bool okay = 0;
        int cmds_ret;

        iface = xstrdup(target_list->data);
        target_list = target_list->link;

        pch = strchr(iface, '=');
        if (pch) {
            *pch = '\0';
            liface = xstrdup(pch + 1);
        } else {
            liface = xstrdup(iface);
        }

        if (!FORCE) {
            llist_t *state_list = read_iface_state();
            const llist_t *iface_state = find_iface_state(state_list, iface);

            if (cmds == iface_up) {
                /* ifup */
                if (iface_state) {
                    bb_error_msg("interface %s already configured", iface);
                    goto next;
                }
            } else {
                /* ifdown */
                if (!iface_state) {
                    bb_error_msg("interface %s not configured", iface);
                    goto next;
                }
            }
            llist_free(state_list, free);
        }
....

        iface_list = defn->ifaces;
        while (iface_list) {
            currif = (struct interface_defn_t *) iface_list->data;
            if (strcmp(liface, currif->iface) == 0) {
                char *oldiface = currif->iface;

                okay = 1;
                currif->iface = iface;

                debug_noise("\nConfiguring interface %s (%s)\n", liface, currif->address_family->name);

                /* Call the cmds function pointer, does either iface_up() or iface_down() */
                cmds_ret = cmds(currif);
                if (cmds_ret == -1) {
                    bb_error_msg("don't seem to have all the variables for %s/%s",
                            liface, currif->address_family->name);
                    any_failures = 1;
                } else if (cmds_ret == 0) {
                    any_failures = 1;
                }

                currif->iface = oldiface;
            }
            iface_list = iface_list->link;
        }
        if (VERBOSE) {
            bb_putchar('\n');
        }

        if (!okay && !FORCE) {
            bb_error_msg("ignoring unknown interface %s", liface);
            any_failures = 1;
        } else if (!NO_ACT) {
            /* update the state file */
            FILE *state_fp;
            llist_t *state;
            llist_t *state_list = read_iface_state();
            llist_t *iface_state = find_iface_state(state_list, iface);

            if (cmds == iface_up) {
                char * const newiface = xasprintf("%s=%s", iface, liface);
                if (iface_state == NULL) {
                    llist_add_to_end(&state_list, newiface);
                } else {
                    free(iface_state->data);
                    iface_state->data = newiface;
                }
            } else {
                /* Remove an interface from state_list */
                llist_unlink(&state_list, iface_state);
                free(llist_pop(&iface_state));
            }

            /* Actually write the new state */
            state_fp = xfopen_for_write(CONFIG_IFUPDOWN_IFSTATE_PATH);
            state = state_list;
            while (state) {
                if (state->data) {
                    fprintf(state_fp, "%s\n", state->data);
                }
                state = state->link;
            }
            ....
        }
 next:
....
    }
    return any_failures;
}

主函数中的读取interfaces文件的函数是read_interfaces,他将解析文件,把所需要的信息放在结构体 defn 中。


static struct interfaces_file_t *read_interfaces(const char *filename)
{
    /* Let's try to be compatible.
     *
     * "man 5 interfaces" says:
     * Lines starting with "#" are ignored. Note that end-of-line
     * comments are NOT supported, comments must be on a line of their own.
     * A line may be extended across multiple lines by making
     * the last character a backslash.
     *
     * Seen elsewhere in example config file:
     * A first non-blank "#" character makes the rest of the line
     * be ignored. Blank lines are ignored. Lines may be indented freely.
     * A "\" character at the very end of the line indicates the next line
     * should be treated as a continuation of the current one.
     */
....
    struct interface_defn_t *currif = NULL;
    struct interfaces_file_t *defn;
    FILE *f;
    char *buf;
    char *first_word;
    char *rest_of_line;
    enum { NONE, IFACE, MAPPING } currently_processing = NONE;

    defn = xzalloc(sizeof(*defn));
    f = xfopen_for_read(filename);

    while ((buf = xmalloc_fgetline(f)) != NULL) {
#if ENABLE_DESKTOP
        /* Trailing "\" concatenates lines */
        char *p;
        while ((p = last_char_is(buf, '\\')) != NULL) {
            *p = '\0';
            rest_of_line = xmalloc_fgetline(f);
            if (!rest_of_line)
                break;
            p = xasprintf("%s%s", buf, rest_of_line);
            free(buf);
            free(rest_of_line);
            buf = p;
        }
#endif
        rest_of_line = buf;
        first_word = next_word(&rest_of_line);
        if (!first_word || *first_word == '#') {
            free(buf);
            continue; /* blank/comment line */
        }

        if (strcmp(first_word, "mapping") == 0) {
....
            currently_processing = MAPPING;
        } else if (strcmp(first_word, "iface") == 0) {
            static const struct address_family_t *const addr_fams[] = {
#if ENABLE_FEATURE_IFUPDOWN_IPV4
                &addr_inet,
#endif
#if ENABLE_FEATURE_IFUPDOWN_IPV6
                &addr_inet6,
#endif
                NULL
            };
            char *iface_name;
            char *address_family_name;
            char *method_name;
            llist_t *iface_list;

            currif = xzalloc(sizeof(*currif));
            iface_name = next_word(&rest_of_line);
            address_family_name = next_word(&rest_of_line);
            method_name = next_word(&rest_of_line);

            if (method_name == NULL)
                bb_error_msg_and_die("too few parameters for line \"%s\"", buf);

            /* ship any trailing whitespace */
            rest_of_line = skip_whitespace(rest_of_line);

            if (rest_of_line[0] != '\0' /* && rest_of_line[0] != '#' */)
                bb_error_msg_and_die("too many parameters \"%s\"", buf);

            currif->iface = xstrdup(iface_name);

            currif->address_family = get_address_family(addr_fams, address_family_name);
            if (!currif->address_family)
                bb_error_msg_and_die("unknown address type \"%s\"", address_family_name);

            currif->method = get_method(currif->address_family, method_name);
            if (!currif->method)
                bb_error_msg_and_die("unknown method \"%s\"", method_name);

            for (iface_list = defn->ifaces; iface_list; iface_list = iface_list->link) {
                struct interface_defn_t *tmp = (struct interface_defn_t *) iface_list->data;
                if ((strcmp(tmp->iface, currif->iface) == 0)
                 && (tmp->address_family == currif->address_family)
                ) {
                    bb_error_msg_and_die("duplicate interface \"%s\"", tmp->iface);
                }
            }
            llist_add_to_end(&(defn->ifaces), (char*)currif);

            debug_noise("iface %s %s %s\n", currif->iface, address_family_name, method_name);
            currently_processing = IFACE;
        } else if (strcmp(first_word, "auto") == 0) {
            while ((first_word = next_word(&rest_of_line)) != NULL) {

                /* Check the interface isnt already listed */
                if (find_list_string(defn->autointerfaces, first_word)) {
                    bb_perror_msg_and_die("interface declared auto twice \"%s\"", buf);
                }

                /* Add the interface to the list */
                llist_add_to_end(&(defn->autointerfaces), xstrdup(first_word));
                debug_noise("\nauto %s\n", first_word);
            }
            currently_processing = NONE;
        } else {
            switch (currently_processing) {
            case IFACE:
                if (rest_of_line[0] == '\0')
                    bb_error_msg_and_die("option with empty value \"%s\"", buf);

                if (strcmp(first_word, "up") != 0
                 && strcmp(first_word, "down") != 0
                 && strcmp(first_word, "pre-up") != 0
                 && strcmp(first_word, "post-down") != 0
                ) {
                    int i;
                    for (i = 0; i < currif->n_options; i++) {
                        if (strcmp(currif->option[i].name, first_word) == 0)
                            bb_error_msg_and_die("duplicate option \"%s\"", buf);
                    }
                }
                if (currif->n_options >= currif->max_options) {
                    currif->max_options += 10;
                    currif->option = xrealloc(currif->option,
                        sizeof(*currif->option) * currif->max_options);
                }
                debug_noise("\t%s=%s\n", first_word, rest_of_line);
                currif->option[currif->n_options].name = xstrdup(first_word);
                currif->option[currif->n_options].value = xstrdup(rest_of_line);
                currif->n_options++;
                break;
            case MAPPING:
 ....
                break;
            case NONE:
            default:
                bb_error_msg_and_die("misplaced option \"%s\"", buf);
            }
        }
        free(buf);
    } /* while (fgets) */

    if (ferror(f) != 0) {
        /* ferror does NOT set errno! */
        bb_error_msg_and_die("%s: I/O error", filename);
    }
    fclose(f);

    return defn;
}
static const struct method_t methods[] = {
    { "manual", manual_up_down, manual_up_down, },
    { "wvdial", wvdial_up, wvdial_down, },
    { "ppp", ppp_up, ppp_down, },
    { "static", static_up, static_down, },
    { "bootp", bootp_up, static_down, },
    { "dhcp", dhcp_up, dhcp_down, },
    { "loopback", loopback_up, loopback_down, },
};

你可能感兴趣的:(ARM)