This patch replaces the for_each_iface nested funtion with a macro so that we don't have an executable stack and work correctly on NX capable hardware. See http://www.gentoo.org/proj/en/hardened/gnu-stack.xml for more information. Patch by Diego Pettenò (flameeyes@gentoo.org) Index: netplug-1.2.9/if_info.c =================================================================== --- netplug-1.2.9.orig/if_info.c +++ netplug-1.2.9/if_info.c @@ -29,8 +29,7 @@ #include "netplug.h" -#define INFOHASHSZ 16 /* must be a power of 2 */ -static struct if_info *if_info[INFOHASHSZ]; +struct if_info *if_info[INFOHASHSZ]; static const char * statename(enum ifstate s) @@ -95,17 +94,6 @@ flags_str(char *buf, unsigned int fl) return buf; } -void -for_each_iface(int (*func)(struct if_info *)) -{ - for(int i = 0; i < INFOHASHSZ; i++) { - for(struct if_info *info = if_info[i]; info != NULL; info = info->next) { - if ((*func)(info)) - return; - } - } -} - /* Reevaluate the state machine based on the current state and flag settings */ void ifsm_flagpoll(struct if_info *info) @@ -284,6 +272,14 @@ ifsm_flagchange(struct if_info *info, un info->lastchange = time(0); } +int find_pid(struct if_info *i, pid_t pid, struct if_info **info) { + if (i->worker == pid) { + *info = i; + return 1; + } + return 0; +} + /* handle a script termination and update the state accordingly */ void ifsm_scriptdone(pid_t pid, int exitstatus) { @@ -291,16 +287,8 @@ void ifsm_scriptdone(pid_t pid, int exit struct if_info *info; assert(WIFEXITED(exitstatus) || WIFSIGNALED(exitstatus)); - int find_pid(struct if_info *i) { - if (i->worker == pid) { - info = i; - return 1; - } - return 0; - } - info = NULL; - for_each_iface(find_pid); + for_each_iface(find_pid, pid, &info); if (info == NULL) { do_log(LOG_INFO, "Unexpected child %d exited with status %d", Index: netplug-1.2.9/main.c =================================================================== --- netplug-1.2.9.orig/main.c +++ netplug-1.2.9/main.c @@ -164,6 +164,23 @@ child_handler(int sig, siginfo_t *info, write(child_handler_pipe[1], &ce, sizeof(ce)); } +int pollflags_state(struct if_info *info, int sockfd) { + struct ifreq ifr; + + if (!if_match(info->name)) + return 0; + + memcpy(ifr.ifr_name, info->name, sizeof(ifr.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) + do_log(LOG_ERR, "%s: can't get flags: %m", info->name); + else { + ifsm_flagchange(info, ifr.ifr_flags); + ifsm_flagpoll(info); + } + + return 0; +} + /* Poll the existing interface state, so we can catch any state changes for which we may not have neen a netlink message. */ static void @@ -180,28 +197,20 @@ poll_interfaces(void) close_on_exec(sockfd); } - int pollflags(struct if_info *info) { - struct ifreq ifr; - - if (!if_match(info->name)) - return 0; - - memcpy(ifr.ifr_name, info->name, sizeof(ifr.ifr_name)); - if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) - do_log(LOG_ERR, "%s: can't get flags: %m", info->name); - else { - ifsm_flagchange(info, ifr.ifr_flags); - ifsm_flagpoll(info); - } - - return 0; - } - - for_each_iface(pollflags); + for_each_iface(pollflags_state, sockfd); } int debug = 0; +/* Run over each of the interfaces we know and care about, and + make sure the state machine has done the appropriate thing + for their current state. */ +int poll_flags_check(struct if_info *i) { + if (if_match(i->name)) + ifsm_flagpoll(i); + return 0; +} + int main(int argc, char *argv[]) { @@ -331,17 +340,7 @@ main(int argc, char *argv[]) { child_handler_pipe[0], POLLIN, 0 }, }; - { - /* Run over each of the interfaces we know and care about, and - make sure the state machine has done the appropriate thing - for their current state. */ - int poll_flags(struct if_info *i) { - if (if_match(i->name)) - ifsm_flagpoll(i); - return 0; - } - for_each_iface(poll_flags); - } + for_each_iface(poll_flags_check); for(;;) { int ret; Index: netplug-1.2.9/netplug.h =================================================================== --- netplug-1.2.9.orig/netplug.h +++ netplug-1.2.9/netplug.h @@ -28,6 +28,9 @@ #define NP_SCRIPT NP_SCRIPT_DIR "/netplug" +#define INFOHASHSZ 16 /* must be a power of 2 */ +extern struct if_info *if_info[INFOHASHSZ]; + /* configuration */ void read_config(char *filename); @@ -83,7 +86,14 @@ struct if_info *if_info_update_interface struct rtattr *attrs[]); int if_info_save_interface(struct nlmsghdr *hdr, void *arg); void parse_rtattrs(struct rtattr *tb[], int max, struct rtattr *rta, int len); -void for_each_iface(int (*func)(struct if_info *)); + +#define for_each_iface(func, ...) \ + for(int i = 0; i < INFOHASHSZ; i++) { \ + for(struct if_info *each_iface = if_info[i]; each_iface != NULL; each_iface = each_iface->next) { \ + if (func (each_iface, ##__VA_ARGS__)) \ + break; \ + } \ + } void ifsm_flagpoll(struct if_info *info); void ifsm_flagchange(struct if_info *info, unsigned int newflags);