From 219b9b062b40f0f5a4edd982164d170633dc7433 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sun, 16 Nov 2003 22:45:25 +0000 Subject: many changes including host roaming support git-svn-id: file:///home/lennart/svn/public/waproamd/trunk@46 022f378f-78c4-0310-b860-d162c87e6274 --- conf/default.in | 2 +- configure.ac | 9 ----- src/Makefile.am | 3 +- src/iwapi.c | 39 +++++++-------------- src/iwapi.h | 3 +- src/iwhostroam.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/iwhostroam.h | 28 +++++++++++++++ src/waproamd.c | 89 ++++++++++++++++++++++++++---------------------- src/wireless.h | 1 + 9 files changed, 197 insertions(+), 79 deletions(-) create mode 100644 src/iwhostroam.c create mode 100644 src/iwhostroam.h diff --git a/conf/default.in b/conf/default.in index 77f6b6b..b1888b9 100755 --- a/conf/default.in +++ b/conf/default.in @@ -20,7 +20,7 @@ KEYDIR="@sysconfdir@/waproamd/keys" -if [ -z "$AP" -o -z "$IFACE" -o -z "$ESSID" -o -z "$ESSID_ESCAPED" -o -z "$ADHOC" ] ; then +if [ -z "$AP" -o -z "$IFACE" -o -z "$ESSID" -o -z "$ESSID_ESCAPED" ] ; then echo "Corrupt environment" > /dev/stderr exit 1 fi diff --git a/configure.ac b/configure.ac index bbbcc66..d01fa1e 100644 --- a/configure.ac +++ b/configure.ac @@ -101,14 +101,5 @@ fi AM_CONDITIONAL([USE_XMLTOMAN], [test "x$xmltoman" = xyes]) -# Build waproamd? -AC_ARG_ENABLE(waproamd, - AC_HELP_STRING([--disable-waproamd], [Disable building of waproamd]), -[case "${enableval}" in - yes) waproamd=yes ;; - no) waproamd=no ;; - *) AC_MSG_ERROR([bad value ${enableval} for --disable-waproamd]) ;; -esac], [waproamd=yes]) - AC_CONFIG_FILES([src/Makefile Makefile conf/Makefile doc/Makefile man/Makefile doc/README.html]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index 5d92e5e..9176e15 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,8 @@ waproamd_SOURCES = waproamd.c waproamd.h \ assocwatch.c assocwatch.h \ ifmonitor.c ifmonitor.h \ wireless.h wireless.15.h \ - netlink.h rtnetlink.h + netlink.h rtnetlink.h \ + iwhostroam.h iwhostroam.c svnkeywords: svn propset svn:keywords Id *.c *.h Makefile.am diff --git a/src/iwapi.c b/src/iwapi.c index 5fbb305..3202f9e 100644 --- a/src/iwapi.c +++ b/src/iwapi.c @@ -18,7 +18,6 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include #include #include #include @@ -195,13 +194,10 @@ int iw_scan_result(struct interface *i, int (*callback)(struct ap_info* ap)) { } if ((e->u.mode != IW_MODE_INFRA) && - (e->u.mode != IW_MODE_MASTER) && - (e->u.mode != IW_MODE_ADHOC)) - f = 0; // Ignore non-APs, non-adhocs - else { + (e->u.mode != IW_MODE_MASTER)) + f = 0; // Ignore non-APs + else f |= 4; - ap.adhoc = e->u.mode == IW_MODE_ADHOC; - } break; @@ -235,12 +231,10 @@ int iw_tune(struct interface *i, struct ap_info *ap) { assert(i && ap); /* We are not interested in the return values of these functions due to driver issues */ - iw_set_mode(i, ap->adhoc ? IW_MODE_ADHOC : IW_MODE_INFRA); + iw_set_mode(i, IW_MODE_INFRA); iw_set_essid(i, ap->essid); iw_set_freq(i, &ap->freq); - - if (!ap->adhoc) - iw_set_ap(i, &ap->ap); + iw_set_ap(i, &ap->ap); return 0; } @@ -320,9 +314,16 @@ int iw_assoc(struct interface *i, struct ap_info *ap) { struct hw_addr hw; struct iwreq req; struct iw_statistics q; + int m; assert(i); + if (iw_get_mode(i, &m) < 0) + return -1; + + if (m != IW_MODE_INFRA) + return 0; + if (iw_get_ap(i, &hw) < 0) return -1; @@ -345,7 +346,6 @@ int iw_assoc(struct interface *i, struct ap_info *ap) { return 0; if (ap) { - int m; memset(ap, 0, sizeof(struct ap_info)); memcpy(ap->ap.addr, hw.addr, ETH_ALEN); @@ -355,16 +355,6 @@ int iw_assoc(struct interface *i, struct ap_info *ap) { if (iw_get_freq(i, &ap->freq) < 0) return -1; - - if (iw_get_mode(i, &m) < 0) - return -1; - - if (m != IW_MODE_INFRA && m != IW_MODE_ADHOC) { - daemon_log(LOG_ERR, "Bad interface mode\n"); - return -1; - } - - ap->adhoc = m == IW_MODE_ADHOC; } return 1; @@ -373,8 +363,5 @@ int iw_assoc(struct interface *i, struct ap_info *ap) { int iw_ap_info_equal(const struct ap_info *a, const struct ap_info *b) { assert(a && b); - return !strcmp(a->essid, b->essid) && - !!a->adhoc == !!b->adhoc && - !memcmp(&a->freq, &b->freq, sizeof(a->freq)) && - (a->adhoc || hw_addr_equal(&a->ap, &b->ap)); + return !strcmp(a->essid, b->essid) && !memcmp(&a->freq, &b->freq, sizeof(a->freq)); } diff --git a/src/iwapi.h b/src/iwapi.h index 06c46a1..b81b2dd 100644 --- a/src/iwapi.h +++ b/src/iwapi.h @@ -22,11 +22,10 @@ */ #include "interface.h" -#include "wireless.h" #include "util.h" +#include "wireless.h" struct ap_info { - int adhoc; /* 0: master; 1: ad hoc */ struct hw_addr ap; struct iw_freq freq; char essid[IW_ESSID_MAX_SIZE + 1]; diff --git a/src/iwhostroam.c b/src/iwhostroam.c new file mode 100644 index 0000000..33d5d9c --- /dev/null +++ b/src/iwhostroam.c @@ -0,0 +1,102 @@ +/* $Id: iwapi.c 45 2003-11-15 10:30:30Z lennart $ */ + +/* + * 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. + */ + +#include +#include +#include +#include +#include + +#include "iwapi.h" +#include "wireless.h" + +#define IW_MAX_PRIV_DEF 128 + +int iw_set_hostroam(struct interface *i, int h) { + struct iwreq req; + struct iw_priv_args pa[IW_MAX_PRIV_DEF]; + int j, subcmd = 0, b_subcmd = 0; + + assert(i); + + memset(&req, 0, sizeof(req)); + strncpy(req.ifr_ifrn.ifrn_name, i->name, IFNAMSIZ); + + req.u.data.pointer = (caddr_t) pa; + req.u.data.length = IW_MAX_PRIV_DEF; + req.u.data.flags = 0; + + if(ioctl(i->fd, SIOCGIWPRIV, &req) < 0) + return -1; + + if (req.u.data.length <= 0) + return -1; + + for (j = 0; j < req.u.data.length; j++) + if (!strcmp(pa[j].name, "host_roaming")) + break; + + if (j >= req.u.data.length) + return -1; + + if ((pa[j].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT || + (pa[j].set_args & IW_PRIV_SIZE_MASK) != 1) { + daemon_log(LOG_WARNING, "Private ioctl host_roaming with bogus arguments found!"); + return -1; + } + + /* Look for sub ioctls */ + if(pa[j].cmd < SIOCDEVPRIVATE) { + int k; + + for (k = 0; k < req.u.data.length; k++) { + if (pa[k].name[0] == 0 && + pa[j].set_args == pa[k].set_args && + pa[j].get_args == pa[k].get_args) + break; + } + + if (k >= req.u.data.length) { + daemon_log(LOG_WARNING, "Invalid private ioctl definition!"); + return -1; + } + + subcmd = pa[j].cmd; + b_subcmd = 1; + j = k; + } + + if (h < 0) h = 0; + if (h > 2) h = 2; + + memset(&req, 0, sizeof(req)); + strncpy(req.ifr_ifrn.ifrn_name, i->name, IFNAMSIZ); + req.u.data.length = 1; + req.u.mode = b_subcmd ? subcmd : 0; + memcpy(req.u.name+4, &h, sizeof(h)); + + if (ioctl(i->fd, pa[j].cmd, &req) < 0) { + daemon_log(LOG_WARNING, "Private ioctl host_roaming (%x) failed: %s", pa[j].cmd, strerror(errno)); + return -1; + } + + daemon_log(LOG_INFO, "Successfully set host roaming of driver to <%s>", !h ? "hardware" : (h == 1 ? "host" : "user space")); + return 0; +} diff --git a/src/iwhostroam.h b/src/iwhostroam.h new file mode 100644 index 0000000..745d528 --- /dev/null +++ b/src/iwhostroam.h @@ -0,0 +1,28 @@ +#ifndef fooiwhostroamhfoo +#define fooiwhostroamhfoo + +/* $Id: iwapi.c 45 2003-11-15 10:30:30Z lennart $ */ + +/* + * 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. + */ + +#include "interface.h" + +int iw_set_hostroam(struct interface *i, int h); + +#endif diff --git a/src/waproamd.c b/src/waproamd.c index 98cec2c..13e391c 100644 --- a/src/waproamd.c +++ b/src/waproamd.c @@ -41,6 +41,7 @@ #include "ifmonitor.h" #include "assocwatch.h" #include "waproamd.h" +#include "iwhostroam.h" #ifdef HAVE_CONFIG_H #include @@ -65,7 +66,8 @@ int use_assocwatch = 1, #ifdef DAEMON_PID_FILE_KILL_WAIT_AVAILABLE wait_on_kill = 0, #endif - use_syslog = 1; + use_syslog = 1, + use_userspace_roaming = 1; int poll_interval = 5, scan_interval = 10; @@ -172,15 +174,10 @@ int run_script(struct ap_info *ai, const char *arg) { 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); - + snprint_hw_addr(t, sizeof(t), &ai->ap); + setenv("AP", t, 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); }; @@ -200,14 +197,9 @@ int set_current_ap(struct ap_info *a) { memcpy(¤t_ap, a, sizeof(struct ap_info)); 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 '%s'", t, escape_essid(a->essid)); - } + char t[20]; + snprint_hw_addr(t, sizeof(t), ¤t_ap.ap); + daemon_log(LOG_INFO, "Selected new AP %s with ESSID '%s'", t, escape_essid(a->essid)); if (run_script(¤t_ap, "start") < 0) return -1; @@ -237,8 +229,6 @@ int assocwatch_cb(int index, struct hw_addr *a) { if (strcmp(name, interface_name)) return 0; - do_status_check = 1; - return 0; } @@ -265,6 +255,7 @@ int go(struct interface *i) { if (nlapi_open(RTMGRP_LINK) < 0) goto finish; + /* Check whether interface is available */ if (use_ifmonitor) { int b; @@ -275,16 +266,28 @@ int go(struct interface *i) { } else disabled = 0; + /* Try to enable userspace roaming in the driver */ + if (!disabled && use_userspace_roaming) { + + if (iw_set_hostroam(i, 2) < 0) { + daemon_log(LOG_WARNING, "Enabling user space roaming failed, doing without."); + use_userspace_roaming = 0; + } + } + memset(¤t_ap, 0, sizeof(current_ap)); current_ap_valid = 0; - if ((associated = iw_assoc(i, &associated_ap)) < 0) { - if (!use_ifmonitor) - goto finish; - - associated = 0; + /* Check association status */ + if (!disabled) { + if ((associated = iw_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) @@ -311,7 +314,7 @@ int go(struct interface *i) { for (;;) { fd_set qfds; - struct timeval tv, *ptv = NULL; + struct timeval tv; time_t now = time(NULL); int a, d; @@ -328,15 +331,12 @@ int go(struct interface *i) { if (do_status_check) { tv.tv_sec = 0; tv.tv_usec = 0; - ptv = &tv; } if (scanning) { tv.tv_sec = 0; tv.tv_usec = 100000; - ptv = &tv; - } else if (!use_assocwatch) { + } else { tv.tv_sec = poll_interval; tv.tv_usec = 0; - ptv = &tv; } if (next_scan != (time_t) -1) { @@ -345,16 +345,13 @@ int go(struct interface *i) { 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; - } + if (tv2.tv_sec < tv.tv_sec) + tv = tv2; } qfds = fds; - - if (select(FD_SETSIZE, &qfds, NULL, NULL, ptv) < 0) { + + if (select(FD_SETSIZE, &qfds, NULL, NULL, &tv) < 0) { if (errno == EINTR) continue; @@ -369,7 +366,7 @@ int go(struct interface *i) { if (nlapi_work(0) < 0) goto finish; - if (do_status_check || (!use_assocwatch && !disabled && !paused)) { + if (!disabled && !paused) { if ((associated = iw_assoc(i, &associated_ap)) < 0) { if (!use_ifmonitor) @@ -378,10 +375,9 @@ int go(struct interface *i) { associated = 0; } + do_status_check = 0; } - do_status_check = 0; - if (paused) { /* If paused ignore new data */ @@ -510,7 +506,13 @@ int go(struct interface *i) { finish: + daemon_log(LOG_INFO, "Shutdown"); + + set_current_ap(NULL); + + if (use_userspace_roaming) + iw_set_hostroam(i, 0); if (send_retval && daemonize && wait_on_fork) daemon_retval_send(1); @@ -541,6 +543,7 @@ void usage(char *p) { #endif " -M --monitor Use interface monitoring (%s)\n" " -e --no-event Don't use wireless event API (%s)\n" + " -U --no-userspace-roaming Don't enable user space roaming via private ioctl (%s)\n" " -t --scan-interval=SECS Specify scan interval (%i)\n" " -p --poll-interval=SECS Specify association poll interval, unless using -e (%i)\n" " -h --help Show this help\n" @@ -560,6 +563,7 @@ void usage(char *p) { #endif use_ifmonitor ? "on" : "off", use_assocwatch ? "off" : "on", + use_userspace_roaming ? "off" : "on", scan_interval, poll_interval); } @@ -575,6 +579,7 @@ void parse_args(int argc, char *argv[]) { #endif {"monitor", no_argument, 0, 'M'}, {"no-event", no_argument, 0, 'e'}, + {"no-userspace-roaming", no_argument, 0, 'U'}, {"scan-interval", required_argument, 0, 't'}, {"poll-interval", required_argument, 0, 'p'}, {"help", no_argument, 0, 'h'}, @@ -592,7 +597,7 @@ void parse_args(int argc, char *argv[]) { for (;;) { int c; - if ((c = getopt_long(argc, argv, "nsi:whkcvMet:p:SRrWr", long_options, &option_index)) < 0) + if ((c = getopt_long(argc, argv, "nsi:whkcvMet:p:SRrWrU", long_options, &option_index)) < 0) break; switch (c) { @@ -639,6 +644,10 @@ void parse_args(int argc, char *argv[]) { use_assocwatch = !use_assocwatch; break; + case 'U': + use_userspace_roaming = !use_userspace_roaming; + break; + case 't': if ((scan_interval = atoi(optarg)) < 0) { daemon_log(LOG_ERR, "Scan interval must be a positive, nonzero integer."); diff --git a/src/wireless.h b/src/wireless.h index 0a4ef2e..f654dff 100644 --- a/src/wireless.h +++ b/src/wireless.h @@ -22,6 +22,7 @@ */ #include +#include #include "wireless.15.h" #endif -- cgit