From c42407335a7ca00d58d860d42a3fe62bb8f0b2f1 Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 5 Oct 2004 19:51:34 +0000 Subject: simple program to watch 802.11 events through a routing socket --- tools/tools/ath/80211watch.c | 381 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 tools/tools/ath/80211watch.c diff --git a/tools/tools/ath/80211watch.c b/tools/tools/ath/80211watch.c new file mode 100644 index 0000000..a9315f2 --- /dev/null +++ b/tools/tools/ath/80211watch.c @@ -0,0 +1,381 @@ +/*- + * Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGES. + * + * $FreeBSD$ + */ + +/* + * Monitor 802.11 events using a routing socket. + * Code liberaly swiped from route(8). + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void print_rtmsg(struct rt_msghdr *rtm, int msglen); + +int nflag = 0; + +int +main(int argc, char *argv[]) +{ + int n, s; + char msg[2048]; + + s = socket(PF_ROUTE, SOCK_RAW, 0); + if (s < 0) + err(EX_OSERR, "socket"); + for(;;) { + n = read(s, msg, 2048); + print_rtmsg((struct rt_msghdr *)msg, n); + } + return 0; +} + +static void +bprintf(fp, b, s) + FILE *fp; + int b; + u_char *s; +{ + int i; + int gotsome = 0; + + if (b == 0) + return; + while ((i = *s++) != 0) { + if (b & (1 << (i-1))) { + if (gotsome == 0) + i = '<'; + else + i = ','; + (void) putc(i, fp); + gotsome = 1; + for (; (i = *s) > 32; s++) + (void) putc(i, fp); + } else + while (*s > 32) + s++; + } + if (gotsome) + putc('>', fp); +} + +char metricnames[] = +"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount" +"\1mtu"; +char routeflags[] = +"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT" +"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016" +"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE" +"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST"; +char ifnetflags[] = +"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" +"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" +"\017LINK2\020MULTICAST"; +char addrnames[] = +"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; + +const char * +routename(sa) + struct sockaddr *sa; +{ + char *cp; + static char line[MAXHOSTNAMELEN + 1]; + struct hostent *hp; + static char domain[MAXHOSTNAMELEN + 1]; + static int first = 1, n; + + if (first) { + first = 0; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = strchr(domain, '.'))) { + domain[MAXHOSTNAMELEN] = '\0'; + (void) strcpy(domain, cp + 1); + } else + domain[0] = 0; + } + + if (sa->sa_len == 0) + strcpy(line, "default"); + else switch (sa->sa_family) { + + case AF_INET: + { struct in_addr in; + in = ((struct sockaddr_in *)sa)->sin_addr; + + cp = 0; + if (in.s_addr == INADDR_ANY || sa->sa_len < 4) + cp = "default"; + if (cp == 0 && !nflag) { + hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), + AF_INET); + if (hp) { + if ((cp = strchr(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = 0; + cp = hp->h_name; + } + } + if (cp) { + strncpy(line, cp, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; + } else + (void) sprintf(line, "%s", inet_ntoa(in)); + break; + } + +#ifdef INET6 + case AF_INET6: + { + struct sockaddr_in6 sin6; /* use static var for safety */ + int niflags = 0; +#ifdef NI_WITHSCOPEID + niflags = NI_WITHSCOPEID; +#endif + + memset(&sin6, 0, sizeof(sin6)); + memcpy(&sin6, sa, sa->sa_len); + sin6.sin6_len = sizeof(struct sockaddr_in6); + sin6.sin6_family = AF_INET6; +#ifdef __KAME__ + if (sa->sa_len == sizeof(struct sockaddr_in6) && + (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) && + sin6.sin6_scope_id == 0) { + sin6.sin6_scope_id = + ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); + sin6.sin6_addr.s6_addr[2] = 0; + sin6.sin6_addr.s6_addr[3] = 0; + } +#endif + if (nflag) + niflags |= NI_NUMERICHOST; + if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, + line, sizeof(line), NULL, 0, niflags) != 0) + strncpy(line, "invalid", sizeof(line)); + + return(line); + } +#endif + + case AF_LINK: + return (link_ntoa((struct sockaddr_dl *)sa)); + + default: + { u_short *s = (u_short *)sa; + u_short *slim = s + ((sa->sa_len + 1) >> 1); + char *cp = line + sprintf(line, "(%d)", sa->sa_family); + char *cpe = line + sizeof(line); + + while (++s < slim && cp < cpe) /* start with sa->sa_data */ + if ((n = snprintf(cp, cpe - cp, " %x", *s)) > 0) + cp += n; + else + *cp = '\0'; + break; + } + } + return (line); +} + + +static void +pmsg_addrs(char *cp, int addrs) +{ + struct sockaddr *sa; + int i; + + if (addrs == 0) { + (void) putchar('\n'); + return; + } + printf("\nsockaddrs: "); + bprintf(stdout, addrs, addrnames); + putchar('\n'); + for (i = 1; i; i <<= 1) + if (i & addrs) { + sa = (struct sockaddr *)cp; + printf(" %s", routename(sa)); + cp += SA_SIZE(sa); + } + putchar('\n'); + fflush(stdout); +} + +static const char * +ether_sprintf(const uint8_t mac[6]) +{ + static char buf[32]; + + snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + return buf; +} + +static void +print_rtmsg(struct rt_msghdr *rtm, int msglen) +{ + struct if_msghdr *ifm; + struct if_announcemsghdr *ifan; + char *state; + time_t now = time(NULL); + char *cnow = ctime(&now); + + if (rtm->rtm_version != RTM_VERSION) { + (void) printf("routing message version %d not understood\n", + rtm->rtm_version); + return; + } + switch (rtm->rtm_type) { + case RTM_IFINFO: + ifm = (struct if_msghdr *)rtm; + printf("%.19s RTM_IFINFO: if# %d, ", + cnow, ifm->ifm_index); + switch (ifm->ifm_data.ifi_link_state) { + case LINK_STATE_DOWN: + state = "down"; + break; + case LINK_STATE_UP: + state = "up"; + break; + default: + state = "unknown"; + break; + } + printf("link: %s, flags:", state); + bprintf(stdout, ifm->ifm_flags, ifnetflags); + pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); + break; + case RTM_IFANNOUNCE: + ifan = (struct if_announcemsghdr *)rtm; + printf("%.19s RTM_IFANNOUNCE: if# %d, what: ", + cnow, ifan->ifan_index); + switch (ifan->ifan_what) { + case IFAN_ARRIVAL: + printf("arrival"); + break; + case IFAN_DEPARTURE: + printf("departure"); + break; + default: + printf("#%d", ifan->ifan_what); + break; + } + printf("\n"); + break; + case RTM_IEEE80211: +#define V(type) ((struct type *)(&ifan[1])) + ifan = (struct if_announcemsghdr *)rtm; + printf("%.19s RTM_IEEE80211: ", cnow); + switch (ifan->ifan_what) { + case RTM_IEEE80211_ASSOC: + printf("associate with %s", + ether_sprintf(V(ieee80211_join_event)->iev_addr)); + break; + case RTM_IEEE80211_REASSOC: + printf("reassociate with %s", + ether_sprintf(V(ieee80211_join_event)->iev_addr)); + break; + case RTM_IEEE80211_DISASSOC: + printf("disassociate"); + break; + case RTM_IEEE80211_JOIN: + printf("%s station join", + ether_sprintf(V(ieee80211_join_event)->iev_addr)); + break; + case RTM_IEEE80211_LEAVE: + printf("%s station leave", + ether_sprintf(V(ieee80211_leave_event)->iev_addr)); + break; + case RTM_IEEE80211_SCAN: + printf("scan complete"); + break; + case RTM_IEEE80211_REPLAY: + printf("replay failure: src %s " + , ether_sprintf(V(ieee80211_replay_event)->iev_src) + ); + printf("dst %s cipher %u keyix %u keyrsc %llu rsc %llu" + , ether_sprintf(V(ieee80211_replay_event)->iev_dst) + , V(ieee80211_replay_event)->iev_cipher + , V(ieee80211_replay_event)->iev_keyix + , V(ieee80211_replay_event)->iev_keyrsc + , V(ieee80211_replay_event)->iev_rsc + ); + break; + case RTM_IEEE80211_MICHAEL: + printf("michael failure: src %s " + , ether_sprintf(V(ieee80211_michael_event)->iev_src) + ); + printf("dst %s cipher %u keyix %u" + , ether_sprintf(V(ieee80211_michael_event)->iev_dst) + , V(ieee80211_michael_event)->iev_cipher + , V(ieee80211_michael_event)->iev_keyix + ); + break; + default: + printf("if# %d, what: #%d", + ifan->ifan_index, ifan->ifan_what); + break; + } + printf("\n"); + break; +#undef V + } +} -- cgit v1.1