summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2003-11-16 22:45:25 +0000
committerLennart Poettering <lennart@poettering.net>2003-11-16 22:45:25 +0000
commit219b9b062b40f0f5a4edd982164d170633dc7433 (patch)
treec72309fc476e2188c9d3399e3662c8d9bf5831a5
parent909f82a22883e3f45ec64d8206802bbce5bad9bf (diff)
many changes including host roaming support
git-svn-id: file:///home/lennart/svn/public/waproamd/trunk@46 022f378f-78c4-0310-b860-d162c87e6274
-rwxr-xr-xconf/default.in2
-rw-r--r--configure.ac9
-rw-r--r--src/Makefile.am3
-rw-r--r--src/iwapi.c39
-rw-r--r--src/iwapi.h3
-rw-r--r--src/iwhostroam.c102
-rw-r--r--src/iwhostroam.h28
-rw-r--r--src/waproamd.c89
-rw-r--r--src/wireless.h1
9 files changed, 197 insertions, 79 deletions
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 <net/if_arp.h>
#include <errno.h>
#include <assert.h>
#include <string.h>
@@ -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 <assert.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <libdaemon/dlog.h>
+#include <errno.h>
+
+#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 <config.h>
@@ -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(&current_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), &current_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), &current_ap.ap);
+ daemon_log(LOG_INFO, "Selected new AP %s with ESSID '%s'", t, escape_essid(a->essid));
if (run_script(&current_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(&current_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 <linux/if.h>
+#include <net/if_arp.h>
#include "wireless.15.h"
#endif