diff options
Diffstat (limited to 'src/waproamd.c')
-rw-r--r-- | src/waproamd.c | 675 |
1 files changed, 0 insertions, 675 deletions
diff --git a/src/waproamd.c b/src/waproamd.c deleted file mode 100644 index f96288a..0000000 --- a/src/waproamd.c +++ /dev/null @@ -1,675 +0,0 @@ -/* $Id$ */ - -/* - * This file is part of waproamd. - * - * waproamd is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * waproamd is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with waproamd; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define _GNU_SOURCE - -#include <assert.h> -#include <string.h> -#include <time.h> -#include <errno.h> -#include <unistd.h> -#include <signal.h> -#include <stdlib.h> -#include <getopt.h> - -#include <libdaemon/dpid.h> -#include <libdaemon/dlog.h> -#include <libdaemon/dfork.h> -#include <libdaemon/dsignal.h> - -#include "iwapi.h" -#include "interface.h" -#include "exec.h" -#include "nlapi.h" -#include "ifmonitor.h" -#include "assocwatch.h" -#include "waproamd.h" - -char *interface_name = NULL; -int interface_index = -1; - -int disabled = 0, - associated = 0; - -struct hw_addr associated_ap; -struct hw_addr current_ap; - -int use_assocwatch = 1, - use_ifmonitor = 0, - daemonize = 1, - wait_on_fork = 0, - use_syslog = 1; - -int poll_interval = 5, - scan_interval = 10; - -char log_ident[32], pid_ident[32]; - -int issue_scan(struct interface *i) { - - //daemon_log(LOG_ERR, "Scanning...\n"); - - if (iw_set_mode(i, IW_MODE_INFRA) < 0) - return -1; - -/* if (iw_set_ap(i, &null_ap) < 0) */ -/* return -1; */ - - if (iw_set_essid(i, NULL) < 0) - return -1; - - if (iw_scan(i) < 0) - return -1; - - return 0; -} - -void get_script_path(char *path, int l, struct hw_addr *ap) { - assert(path && l); - - if (!ap) { - snprintf(path, l, "%s/default", SCRIPTDIR); - return; - } - - 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]); -} - -struct ap_info selected_ap; -int selected_ap_has_script; -int selected_ap_valid; - -static int scan_result_cb(struct ap_info*ap) { - int b; - char path[PATH_MAX]; - - assert(ap); - get_script_path(path, sizeof(path), &ap->ap); - b = access(path, X_OK) == 0; - - if (selected_ap_valid) { - - 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; - return 0; -} - -int read_scan(struct interface *i, struct ap_info **ap) { - int r; - selected_ap_valid = 0; - selected_ap_has_script = 0; - - if ((r = iw_scan_result(i, scan_result_cb)) < 0) - return -1; - - if (r == 1) - return 1; - - *ap = selected_ap_valid ? &selected_ap : NULL; - - return 0; -} - -int run_script(struct hw_addr *ap, const char *arg) { - char path[PATH_MAX]; - - get_script_path(path, sizeof(path), ap); - - if (access(path, X_OK) < 0) - get_script_path(path, sizeof(path), NULL); - - return log_exec(SCRIPTDIR, path, arg); -}; - - -int set_current_ap(struct hw_addr *a) { - char t[32]; - - if (!a) - a = &null_ap; - - if (!hw_addr_equal(a, ¤t_ap)) { - - if (!hw_addr_equal(¤t_ap, &null_ap)) { - 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 (!hw_addr_equal(¤t_ap, &null_ap)) { - daemon_log(LOG_INFO, "Selected new AP %s", t); - - if (run_script(¤t_ap, "start") < 0) - return -1; - } - } - - return 0; -} - -int ifmonitor_cb(int b, int index, unsigned short type, const char *name) { - if (!name) - return 0; - - if (!strcmp(name, interface_name)) { - interface_index = index; - disabled = !b; - } - return 0; -} - -int assocwatch_cb(int index, struct hw_addr *a) { - char name[IFNAMSIZ+1]; - - 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)); - } - - return 0; -} - -int go(struct interface *i) { - time_t next_scan; - int scanning = 0; - int send_retval = 1; - int r = -1, sigfd; - fd_set fds; - - daemon_log(LOG_INFO, "waproamd "VERSION" initializing%s%s.", use_ifmonitor ? ", using NETLINK device monitoring" : "", use_assocwatch ? ", using wireless event notifications" : ""); - - if (daemon_pid_file_create() < 0) { - daemon_log(LOG_ERR, "Could not create PID file %s.", daemon_pid_file_proc()); - goto finish; - } - - if (daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, -1) < 0) { - daemon_log(LOG_ERR, "Could not register signal handler: %s", strerror(errno)); - goto finish; - } - - if (nlapi_open(RTMGRP_LINK) < 0) - goto finish; - - if (use_ifmonitor) { - int b; - - if ((b = is_iface_available(interface_name)) < 0) - goto finish; - - disabled = !b; - } else - disabled = 0; - - memset(¤t_ap, 0, sizeof(current_ap)); - - if ((associated = interface_is_assoc(i, &associated_ap)) < 0) { - if (!use_ifmonitor) - goto finish; - - associated = 0; - } - - daemon_log(LOG_INFO, "Currently %sassociated, interface %s.", associated ? "" : "not ", disabled ? "disabled" : "enabled"); - - if (use_assocwatch) - if (assocwatch_init(assocwatch_cb) < 0) - goto finish; - - if (use_ifmonitor) - if (ifmonitor_init(ifmonitor_cb) < 0) - goto finish; - - daemon_log(LOG_INFO, "Initialization complete."); - - set_current_ap(&associated_ap); - next_scan = associated || disabled ? (time_t) -1 : 0; - - if (daemonize && wait_on_fork) { - daemon_retval_send(0); - send_retval = 0; - } - - FD_ZERO(&fds); - FD_SET(sigfd = daemon_signal_fd(), &fds); - FD_SET(nlapi_fd, &fds); - - for (;;) { - fd_set qfds; - struct timeval tv, *ptv; - time_t now = time(NULL); - int a, d; - - if (next_scan != (time_t) -1 && next_scan <= now) { - if (issue_scan(i) < 0) { - if (!use_ifmonitor) - goto finish; - } else - scanning = 1; - - next_scan = (time_t) -1; - } - - ptv = NULL; - - if (scanning) { - tv.tv_sec = 0; - tv.tv_usec = 100000; - ptv = &tv; - } else if (!use_assocwatch) { - tv.tv_sec = poll_interval; - tv.tv_usec = 0; - ptv = &tv; - } - - if (next_scan != (time_t) -1) { - struct timeval tv2; - now = time(NULL); - tv2.tv_sec = next_scan > now ? next_scan - now : 0; - tv2.tv_usec = 0; - - if (!ptv || tv2.tv_sec < tv.tv_sec) { - tv.tv_sec = tv2.tv_sec; - tv.tv_usec = tv2.tv_usec; - ptv = &tv; - } - } - - qfds = fds; - - if (select(FD_SETSIZE, &qfds, NULL, NULL, ptv) < 0) { - if (errno == EINTR) - continue; - - daemon_log(LOG_ERR, "select() failed: %s\n", strerror(errno)); - goto finish; - } - - a = associated; - d = disabled; - - if (FD_ISSET(nlapi_fd, &qfds)) - if (nlapi_work(0) < 0) - goto finish; - - if (!disabled && !use_assocwatch) { - if ((associated = interface_is_assoc(i, &associated_ap)) < 0) { - if (!use_ifmonitor) - goto finish; - - associated = 0; - } - } - - /* Changed: enabled -> disabled */ - if (!d && disabled) { - daemon_log(LOG_INFO, "Interface disabled\n"); - - if (associated) - if (set_current_ap(NULL) < 0) - goto finish; - - associated = scanning = 0; - } - - /* Changed: disabled -> enabled */ - if (d && !disabled) { - daemon_log(LOG_INFO, "Interface enabled\n"); - associated = scanning = 0; - } - - /* Changed: associated -> not associated */ - if (a && !associated) { - daemon_log(LOG_INFO, "No longer associated.\n"); - scanning = 0; - } - - /* Changed: not associated -> associated */ - if (!a && associated) { - if (set_current_ap(&associated_ap) < 0) - goto finish; - - daemon_log(LOG_INFO, "Associated.\n"); - scanning = 0; - } - - if (scanning) { - int r; - struct ap_info *ai = NULL; - - if ((r = read_scan(i, &ai)) < 0) { - if (!use_ifmonitor) - goto finish; - - scanning = 0; - - } else if (!r) { - - scanning = 0; - - if (!associated) { - - if (set_current_ap(ai ? &ai->ap : NULL) < 0) - goto finish; - } - } - } - - if (FD_ISSET(sigfd, &qfds)) { - int sig; - - if ((sig = daemon_signal_next()) < 0) { - daemon_log(LOG_ERR, "daemon_signal_next(): %s", strerror(errno)); - goto finish; - } - - - switch (sig) { - - case SIGINT: - case SIGTERM: - case SIGQUIT: - r = 0; - goto finish; - - case SIGHUP: - next_scan = 0; - break; - - default: - daemon_log(LOG_INFO, "Ignoring unknown signal %s", strsignal(sig)); - break; - - } - } - - if (next_scan == (time_t) -1 && !scanning) - if (!disabled && !associated) - next_scan = time(NULL) + scan_interval; - - if (disabled || associated) { - scanning = 0; - next_scan = (time_t) -1; - } - } - - r = 0; - -finish: - - set_current_ap(NULL); - - if (send_retval && daemonize && wait_on_fork) - daemon_retval_send(1); - - nlapi_close(); - - daemon_pid_file_remove(); - daemon_signal_done(); - - daemon_log(LOG_INFO, "Exiting."); - - return r; -} - -void usage(char *p) { - if (strrchr(p, '/')) - p = strchr(p, '/')+1; - - printf("%s -- Wireless Access Point Roaming Daemon for 802.11b\n\n" - "Usage: %s [options]\n\n" - "Options:\n" - " -n --no-daemon Do not daemonize (for debugging) (%s)\n" - " -s --no-syslog Do not use syslog, use stderr instead (for debugging) (%s)\n" - " -i --iface=IFACE Specify network interface (%s)\n" - " -w --wait-on-fork Wait until daemon fork finished (%s)\n" - " -M --monitor Use interface monitoring (%s)\n" - " -e --no-event Don't use wireless event API (%s)\n" - " -t --scan-interval Specify scan interval (%i)\n" - " -p --poll-interval Specify association poll interval, unless using -e (%i)\n" - " -h --help Show this help\n" - " -k --kill Kill a running daemon\n" - " -c --check-running Check if a daemon is currently running\n" - " -v --version Show version\n", - p, p, - !daemonize ? "on" : "off", - !use_syslog ? "on" : "off", - interface_name, - wait_on_fork ? "on" : "off", - use_ifmonitor ? "on" : "off", - use_assocwatch ? "off" : "on", - scan_interval, - poll_interval); -} - -void parse_args(int argc, char *argv[]) { - static struct option long_options[] = { - {"no-daemon", no_argument, 0, 'n'}, - {"no-syslog", no_argument, 0, 's'}, - {"iface", required_argument, 0, 'i'}, - {"wait-on-fork", no_argument, 0, 'w'}, - {"monitor", no_argument, 0, 'M'}, - {"no-event", no_argument, 0, 'e'}, - {"scan-interval", required_argument, 0, 't'}, - {"poll-interval", required_argument, 0, 'p'}, - {"help", no_argument, 0, 'h'}, - {"kill", no_argument, 0, 'k'}, - {"check-running", no_argument, 0, 'c'}, - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - int option_index = 0; - int _help = 0, _kill = 0, _check = 0, _version = 0; - - for (;;) { - int c; - - if ((c = getopt_long(argc, argv, "nsi:whkcvMet:p:", long_options, &option_index)) < 0) - break; - - switch (c) { - case 'n' : - daemonize = !daemonize; - break; - - case 's' : - use_syslog = !use_syslog; - break; - - case 'i' : - if (interface_name) - free(interface_name); - interface_name = strdup(optarg); - break; - - case 'w': - wait_on_fork = !wait_on_fork; - break; - - case 'M': - use_ifmonitor = !use_ifmonitor; - break; - - case 'e': - use_assocwatch = !use_assocwatch; - break; - - case 't': - if ((scan_interval = atoi(optarg)) < 0) { - daemon_log(LOG_ERR, "Scan interval must be a positive, nonzero integer."); - exit(1); - } - - case 'p': - if ((poll_interval = atoi(optarg)) < 0) { - daemon_log(LOG_ERR, "Poll interval must be a positive, nonzero integer."); - exit(1); - } - - case 'h': - _help = 1; - break; - - case 'k': - _kill = 1; - break; - - case 'c': - _check = 1; - break; - - case 'v': - _version = 1; - break; - - default: - daemon_log(LOG_ERR, "Unknown parameter.\n"); - exit(1); - } - } - - if (!interface_name) - interface_name = strdup("wlan0"); - - snprintf(pid_ident, sizeof(pid_ident), "waproamd.%s", interface_name); - daemon_pid_file_ident = pid_ident; - snprintf(log_ident, sizeof(log_ident), "waproamd(%s)", interface_name); - daemon_log_ident = log_ident; - - - if (_help) { - usage(argv[0]); - exit(0); - } - - if (_kill) { - if (daemon_pid_file_kill(SIGINT) < 0) { - daemon_log(LOG_ERR, "Failed to kill daemon. (%s)", strerror(errno)); - exit(6); - } - - exit(0); - } - - if (_version) { - printf("waproamd "VERSION"\n"); - exit(0); - } - - if (_check) { - pid_t pid = daemon_pid_file_is_running(); - - if (pid == (pid_t) -1) - printf("waproamd not running.\n"); - else - printf("waproamd process for device %s running as pid %u.\n", interface_name, pid); - - exit(pid == 0 ? 255 : 0); - } - - if (!use_syslog) - daemon_log_use = DAEMON_LOG_STDERR; - -} - -int main(int argc, char *argv[]) { - struct interface *i = NULL; - int r = 1; - pid_t pid; - - daemon_pid_file_ident = daemon_log_ident = daemon_ident_from_argv0(argv[0]); - - parse_args(argc, argv); - - if (geteuid() != 0) { - daemon_log(LOG_ERR, "Sorry, you need to be root to run this binary."); - goto finish; - } - - if ((pid = daemon_pid_file_is_running()) >= 0) { - daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); - goto finish; - - } - - if (daemonize) { - pid_t pid; - - if (wait_on_fork) - if (daemon_retval_init() < 0) { - daemon_log(LOG_ERR, "Sorry, could not create pipe: %s", strerror(errno)); - goto finish; - } - - if ((pid = daemon_fork()) < 0) - goto finish; - - if (pid) { - int c = 0; - - // Parent process - - if (wait_on_fork) - if ((c = daemon_retval_wait(60)) < 0) { - daemon_log(LOG_WARNING, "Killing background process."); - kill(pid, SIGTERM); - } - - r = c; - goto finish; - } - } - - if (!(i = interface_open(interface_name)) < 0) - goto finish; - - if (go(i) < 0) - goto finish; - - r = 0; - -finish: - - if (i) - interface_close(i); - - if (interface_name) - free(interface_name); - - return r; -} |