/* $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. */ #include #include #include #include #include #include #include #include #include #include "netlink.h" #include "rtnetlink.h" #include #include "wireless.h" #include #include "util.h" #include "assocwatch.h" #include "nlapi.h" static int handle_wireless_event(int idx, uint8_t *data, int l, int (*cb) (int idx, struct hw_addr *a)) { struct iw_event *e; int hs; struct hw_addr ap; e = (struct iw_event*) data; hs = sizeof(struct iw_event)-sizeof(union iwreq_data); while (l >= sizeof(struct iw_event)) { if (e->len < hs) { daemon_log(LOG_ERR, "ASSOCWATCH: Recieved corrupt wireless event\n"); return -1; } switch (e->cmd) { case SIOCGIWAP: if (e->len < hs + sizeof(struct sockaddr)) { daemon_log(LOG_ERR, "ASSOCWATCH: Recieved corrupt AP wireless event\n"); return -1; } memcpy(ap.addr, e->u.ap_addr.sa_data, ETH_ALEN); if (cb(idx, is_assoc_ap(&ap) ? &ap : NULL) < 0) return -1; return 0; } l -= e->len; e = (struct iw_event*) (((uint8_t*) e) + e->len); } return 0; } static int callback(struct nlmsghdr *n, void *u) { int (*cb) (int idx, struct hw_addr *a) = u; if (n->nlmsg_type == RTM_NEWLINK) { struct ifinfomsg* ifi; struct rtattr *a; int la; if (n->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg))) { daemon_log(LOG_ERR, "ASSOCWATCH: Corrupt NETLINK message\n"); return -1; } ifi = NLMSG_DATA(n); a = (void*) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg)); la = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg)); while (RTA_OK(a, la)) { if(a->rta_type == IFLA_WIRELESS) handle_wireless_event(ifi->ifi_index, RTA_DATA(a), RTA_PAYLOAD(a), cb); a = RTA_NEXT(a, la); } } return 0; } int assocwatch_init(int (*cb) (int idx, struct hw_addr *a)) { return nlapi_register(callback, cb); }