写了那么多,最后保存时却只剩这一点。。。 这博客真难用。。。
网络的启动是通过执行脚本:
/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, },
};