diff options
Diffstat (limited to 'src/waproamd.c')
-rw-r--r-- | src/waproamd.c | 180 |
1 files changed, 102 insertions, 78 deletions
diff --git a/src/waproamd.c b/src/waproamd.c index 0e2c719..23884bf 100644 --- a/src/waproamd.c +++ b/src/waproamd.c @@ -50,10 +50,13 @@ char *interface_name = NULL; int interface_index = -1; int disabled = 0, - associated = 0; + associated = 0, + do_status_check = 0; -struct hw_addr associated_ap; -struct hw_addr current_ap; +struct ap_info associated_ap; + +struct ap_info current_ap; +int current_ap_valid = 0; int use_assocwatch = 1, use_ifmonitor = 0, @@ -85,51 +88,70 @@ int issue_scan(struct interface *i) { return 0; } -void get_script_path(char *path, int l, struct hw_addr *ap, int uc) { +int get_script_path(char *path, int l, struct ap_info *ai) { assert(path && l); - if (!ap) { + if (!ai) { snprintf(path, l, "%s/default", SCRIPTDIR); - return; + return 0; } - snprintf(path, l, uc ? "%s/%02X:%02X:%02X:%02X:%02X:%02X": "%s/%02x:%02x:%02x:%02x:%02x:%02x", + snprintf(path, l, "%s/%02X:%02X:%02X:%02X:%02X:%02X", + SCRIPTDIR, + ai->ap.addr[0], ai->ap.addr[1], ai->ap.addr[2], + ai->ap.addr[3], ai->ap.addr[4], ai->ap.addr[5]); + + if (!access(path, X_OK)) + return 0; + + snprintf(path, l, "%s/%02x:%02x:%02x:%02x:%02x:%02x", SCRIPTDIR, - ap->addr[0], ap->addr[1], ap->addr[2], - ap->addr[3], ap->addr[4], ap->addr[5]); + ai->ap.addr[0], ai->ap.addr[1], ai->ap.addr[2], + ai->ap.addr[3], ai->ap.addr[4], ai->ap.addr[5]); + + if (!access(path, X_OK)) + return 0; + + if (ai->essid[0]) { + snprintf(path, l, "%s/essid:%s", + SCRIPTDIR, + escape_essid(ai->essid)); + + if (!access(path, X_OK)) + return 0; + } + + return -1; } -struct ap_info selected_ap; -int selected_ap_has_script; -int selected_ap_valid; +struct ap_info scan_ap; +int scan_ap_has_script; +int scan_ap_valid; -static int scan_result_cb(struct ap_info*ap) { - int b; +static int scan_result_cb(struct ap_info*ai) { + int f; char path[PATH_MAX]; - assert(ap); - get_script_path(path, sizeof(path), &ap->ap, 0); - if (!(b = !access(path, X_OK))) { - get_script_path(path, sizeof(path), &ap->ap, 1); - b = !access(path, X_OK); - } - - if (selected_ap_valid) { + assert(ai); - if (!b || selected_ap_has_script) - return 0; - } - - memcpy(&selected_ap, ap, sizeof(struct ap_info)); - selected_ap_valid = 1; - selected_ap_has_script = 1; + /* Found something suitable earlier */ + if (scan_ap_valid && scan_ap_has_script) + return 0; + + f = get_script_path(path, sizeof(path), ai); + if (scan_ap_valid && !f) + return 0; + + memcpy(&scan_ap, ai, sizeof(struct ap_info)); + scan_ap_valid = 1; + scan_ap_has_script = !f; return 0; } int read_scan(struct interface *i, struct ap_info **ap) { int r; - selected_ap_valid = 0; - selected_ap_has_script = 0; + scan_ap_valid = 0; + scan_ap_has_script = 0; if ((r = iw_scan_result(i, scan_result_cb)) < 0) return -1; @@ -137,48 +159,55 @@ int read_scan(struct interface *i, struct ap_info **ap) { if (r == 1) return 1; - *ap = selected_ap_valid ? &selected_ap : NULL; + *ap = scan_ap_valid ? &scan_ap : NULL; return 0; } -int run_script(struct hw_addr *ap, const char *arg) { +int run_script(struct ap_info *ai, const char *arg) { + char t[32]; char path[PATH_MAX]; - get_script_path(path, sizeof(path), ap, 0); - - if (access(path, X_OK) < 0) { - get_script_path(path, sizeof(path), ap, 1); - - if (access(path, X_OK) < 0) - get_script_path(path, sizeof(path), NULL, 0); - } + if (get_script_path(path, sizeof(path), ai) < 0) + get_script_path(path, sizeof(path), NULL); + setenv("IFACE", interface_name, 1); + if (!ai->adhoc) { + snprint_hw_addr(t, sizeof(t), &ai->ap); + setenv("AP", t, 1); + } else + setenv("AP", "n.a.", 1); + + setenv("ESSID", ai->essid, 1); + setenv("ESSID_ESCAPED", escape_essid(ai->essid), 1); + setenv("ADHOC", ai->adhoc ? "YES" : "NO", 1); + return log_exec(SCRIPTDIR, path, arg); }; -int set_current_ap(struct hw_addr *a) { - char t[32]; +int set_current_ap(struct ap_info *a) { - if (!a) - a = &null_ap; - - if (!hw_addr_equal(a, ¤t_ap)) { + if ((a && current_ap_valid && !iw_ap_info_equal(a, ¤t_ap)) || + (!!a != !!current_ap_valid)) { - if (!hw_addr_equal(¤t_ap, &null_ap)) { + if (current_ap_valid) { if (run_script(¤t_ap, "stop") < 0) return -1; } - - memcpy(¤t_ap, a, sizeof(struct hw_addr)); - snprint_hw_addr(t, sizeof(t), ¤t_ap); - setenv("AP", t, 1); - setenv("IFACE", interface_name, 1); + if ((current_ap_valid = !!a)) + memcpy(¤t_ap, a, sizeof(struct ap_info)); - if (!hw_addr_equal(¤t_ap, &null_ap)) { - daemon_log(LOG_INFO, "Selected new AP %s", t); + if (current_ap_valid) { + + if (current_ap.adhoc) + daemon_log(LOG_INFO, "Selected new ad hoc network with ESSID '%s'", escape_essid(a->essid)); + else { + char t[20]; + snprint_hw_addr(t, sizeof(t), ¤t_ap.ap); + daemon_log(LOG_INFO, "Selected new AP %s with ESSID", t, escape_essid(a->essid)); + } if (run_script(¤t_ap, "start") < 0) return -1; @@ -205,13 +234,11 @@ int assocwatch_cb(int index, struct hw_addr *a) { if (get_ifname(index, name, sizeof(name)) < 0) return -1; - if (!strcmp(name, interface_name)) { - interface_index = index; - disabled = 0; - if ((associated = !!a)) - memcpy(&associated_ap, a, sizeof(struct hw_addr)); - } + if (strcmp(name, interface_name)) + return 0; + do_status_check = 1; + return 0; } @@ -221,7 +248,6 @@ int go(struct interface *i) { int send_retval = 1; int r = -1, sigfd; int paused = 0; - int force_assoc_check = 0; fd_set fds; daemon_log(LOG_INFO, "waproamd "VERSION" initializing%s%s.", use_ifmonitor ? ", using NETLINK device monitoring" : "", use_assocwatch ? ", using wireless event notifications" : ""); @@ -250,8 +276,9 @@ int go(struct interface *i) { disabled = 0; memset(¤t_ap, 0, sizeof(current_ap)); + current_ap_valid = 0; - if ((associated = interface_is_assoc(i, &associated_ap)) < 0) { + if ((associated = iw_assoc(i, &associated_ap)) < 0) { if (!use_ifmonitor) goto finish; @@ -270,7 +297,7 @@ int go(struct interface *i) { daemon_log(LOG_INFO, "Initialization complete."); - set_current_ap(&associated_ap); + set_current_ap(associated ? &associated_ap : NULL); next_scan = associated || disabled ? (time_t) -1 : 0; if (daemonize && wait_on_fork) { @@ -298,7 +325,7 @@ int go(struct interface *i) { next_scan = (time_t) -1; } - if (force_assoc_check) { + if (do_status_check) { tv.tv_sec = 0; tv.tv_usec = 0; ptv = &tv; @@ -342,19 +369,20 @@ int go(struct interface *i) { if (nlapi_work(0) < 0) goto finish; - if (force_assoc_check || (!disabled && !use_assocwatch && !paused)) { + if (do_status_check || (!use_assocwatch && !disabled && !paused)) { daemon_log(LOG_INFO, "Querying association status"); - if ((associated = interface_is_assoc(i, &associated_ap)) < 0) { + if ((associated = iw_assoc(i, &associated_ap)) < 0) { if (!use_ifmonitor) goto finish; associated = 0; } + } - force_assoc_check = 0; + do_status_check = 0; if (paused) { @@ -413,16 +441,11 @@ int go(struct interface *i) { if (!associated) { - if (ai) { - if (iw_tune(i, ai) < 0) - goto finish; + if (ai && iw_tune(i, ai) < 0) + goto finish; - if (set_current_ap(&ai->ap) < 0) - goto finish; - } else { - if (set_current_ap(NULL) < 0) - goto finish; - } + if (set_current_ap(ai) < 0) + goto finish; } } } @@ -465,7 +488,8 @@ int go(struct interface *i) { case SIGUSR2: if (paused > 0) { daemon_log(LOG_INFO, "SIGUSR2: Daemon resumed (#%i)", paused--); - force_assoc_check = !paused; + if (!paused) + do_status_check = 1; } break; |