unsigned sqdb_get_bssid_packet(struct SQDB *sqdb, const unsigned char *bssid, unsigned type, struct SquirrelPacket *pkt) { struct SQDB_AccessPoint *ap; unsigned i; pkt->px = (const unsigned char*)""; pkt->length = 1; pkt->secs = time(0); pkt->usecs = 0; pkt->linktype = 0; pixie_enter_critical_section(sqdb->cs); /* Grab the AP record */ ap = sqdb_find_bssid(sqdb, bssid); if (ap == NULL) goto _end; /* Figure out which type of packet we need */ if (type == SQPKT_BEACON) i = 0; else if (type == SQPKT_PROBERESPONSE) i = 1; else goto _end; /* Copy the packet over */ memcpy(pkt, &ap->packets[i], sizeof(*pkt)); _end: pixie_leave_critical_section(sqdb->cs); return 1; }
void regmac_base_crypto(struct SQDB *sqdb, const unsigned char *bssid, unsigned crypto) { struct SQDB_AccessPoint *entry; pixie_enter_critical_section(sqdb->cs); entry = sqdb_create_bssid(sqdb, bssid); switch (crypto) { case ENC_TYPE_WEP : case ENC_TYPE_WEP40 : case ENC_TYPE_WEP128 : case ENC_TYPE_WPA : case ENC_TYPE_WPA2 : if (entry->encryption_type < crypto) entry->encryption_type = crypto; break; case CIPHER_TYPE_WEP : case CIPHER_TYPE_TKIP: case CIPHER_TYPE_AES: if (entry->cipher_type < crypto) entry->cipher_type = crypto; break; case AUTH_TYPE_OPEN : case AUTH_TYPE_SKA : case AUTH_TYPE_EAP : case AUTH_TYPE_PSK : case AUTH_TYPE_MGMT: entry->auth_type = crypto; break; default: ; } pixie_leave_critical_section(sqdb->cs); }
const unsigned char * sqdb_lookup_bssid_by_access_point(struct SQDB *sqdb, const unsigned char *mac_address) { unsigned i; const unsigned char *result = NULL; pixie_enter_critical_section(sqdb->cs); for (i=0; i<sizeof(sqdb->access_points)/sizeof(sqdb->access_points[0]); i++) { struct SQDB_AccessPoint *x; for (x = sqdb->access_points[i]; x; x = x->next) { struct EntryMacAddr *y; if (memcmp(mac_address, x->bssid, 6) == 0) { result = x->bssid; goto _return; } for (y = &x->mac_address; y; y = y->next) { if (memcmp(mac_address, y->addr, 6) == 0) { result = x->bssid; goto _return; } } } } _return: pixie_leave_critical_section(sqdb->cs); return result; }
unsigned regmac_base_resolve_direction(struct SQDB *sqdb, const unsigned char *bssid, const unsigned char *src, const unsigned char *dst) { struct SQDB_AccessPoint *entry; struct EntryMacAddr *mac; unsigned dir = DIR_UNKNOWN; pixie_enter_critical_section(sqdb->cs); if (memcmp(bssid, src, 6) == 0) { regmac_base(sqdb, bssid, bssid); regmac_station(sqdb, bssid, dst, -1); dir = DIR_BASE_TO_STA; } else if (memcmp(bssid, dst, 6) == 0) { regmac_base(sqdb, bssid, bssid); regmac_station(sqdb, bssid, src, -1); dir = DIR_STA_TO_BASE; } else { /* Neither matches, so let's see if this is a different * access-point in the BSS */ entry = sqdb_create_bssid(sqdb, bssid); for (mac = &entry->mac_address; mac; mac = mac->next) { if (memcmp(mac->addr, src, 6) == 0) { regmac_station(sqdb, bssid, dst, -1); dir = DIR_BASE_TO_STA; break; } else if (memcmp(mac->addr, dst, 6) == 0) { regmac_station(sqdb, bssid, src, -1); dir = DIR_STA_TO_BASE; } } } pixie_leave_critical_section(sqdb->cs); return dir; }
void regmac_base_ssid(struct SQDB *sqdb, const unsigned char *bssid, struct SQDB_String *ssid) { struct SQDB_AccessPoint *entry; /* Ignore empty SSIDs */ if (ssid->length == 0) return; if (ssid->length == 1 && ssid->value[0] == '\0') return; pixie_enter_critical_section(sqdb->cs); entry = sqdb_create_bssid(sqdb, bssid); if (!sqdb_string_is_equal(&entry->ssid, ssid)) { if (entry->ssid.length > 0) { SQUIRREL_EVENT("[%02X:%02X:%02X:%02X:%02X:%02X] SSID=\"%.*s\" (was \"%.*s\")\n", PRINTMAC(bssid), PRINTSTR(ssid), PRINTSTR(&entry->ssid)); } sqdb_string_copy(&entry->ssid, ssid); /*FIXME: we should support seeing multiple SSIDs on a BSSID */ } pixie_leave_critical_section(sqdb->cs); }
/** * Lookup access point by BSSID */ static struct SQDB_AccessPoint * sqdb_create_bssid(struct SQDB *sqdb, const unsigned char *bssid) { struct SQDB_AccessPoint **r_entry; unsigned index = bssid_hash(bssid); pixie_enter_critical_section(sqdb->cs); r_entry = &sqdb->access_points[index]; while ((*r_entry) && memcmp((*r_entry)->bssid, bssid, 6) != 0) r_entry = &((*r_entry)->next); if (*r_entry == NULL) { struct XMAC *xmac; *r_entry = (struct SQDB_AccessPoint*)malloc(sizeof(**r_entry)); memset(*r_entry, 0, sizeof(**r_entry)); memcpy((*r_entry)->bssid, bssid, 6); if (sqdb->kludge.channel) { (*r_entry)->channels[0] = sqdb->kludge.channel; (*r_entry)->channel_count = 1; } /* Create a link to this from the master MAC address registery */ xmac = xmac_create(&sqdb->macs, bssid); xmac->type = STATION_TYPE_BASE; xmac->base = *r_entry; (*r_entry)->first = sqdb->kludge.time_stamp; } (*r_entry)->last = sqdb->kludge.time_stamp; pixie_leave_critical_section(sqdb->cs); return *r_entry; }
struct TMP_STATIONS * sqdb_find_station(struct SQDB *sqdb, const unsigned char *mac, unsigned *count) { struct TMP_STATIONS *result = 0; unsigned i; unsigned maxcount = 0; *count = 0; pixie_enter_critical_section(sqdb->cs); memset(&result, 0, sizeof(result)); /* * Look for a "prober" record */ { struct SQDB_Station *entry; unsigned index = bssid_hash(mac); entry = sqdb->stations[index]; while (entry && memcmp(entry->mac_address, mac, 6) != 0) entry = entry->next; if (entry != NULL) { result = alloc_tmp_stations(result, count, &maxcount); result[*count].type = 1; result[*count].sta.unassociated = entry; result[*count].last_update = entry->dbm_last_update; (*count)++; } } /* Look for Associated station */ for (i=0; i<sizeof(sqdb->access_points)/sizeof(sqdb->access_points[0]); i++) { struct SQDB_AccessPoint *ap; ap = sqdb->access_points[i]; while (ap) { struct SQDB_SubStation *sta; sta = ap->substations; while (sta) { if (memcmp(sta->mac_address, mac, 6) == 0) { result = alloc_tmp_stations(result, count, &maxcount); result[*count].type = 2; result[*count].sta.associated = sta; result[*count].last_update = sta->dbm_last_update; result[*count].sta.accesspoint = ap; (*count)++; break; } sta = sta->next; } ap = ap->next; } } pixie_leave_critical_section(sqdb->cs); return result; }
void regmac_station_wired(struct SQDB *sqdb, const unsigned char *bssid, const unsigned char *mac_address, unsigned dir) { struct SQDB_SubStation *sta; struct SQDB_AccessPoint *base; struct SQDB_SubStation multicast; pixie_enter_critical_section(sqdb->cs); /* First, register the fact we have an access-point*/ base = sqdb_create_bssid(sqdb, bssid); /* Second, regisger the fact we have an access-point attached * to that access-point */ if (mac_address[0]&1) sta = &multicast; else sta = sqdb_lookup_substation(sqdb, mac_address, bssid); /* Finally, update the packet counts */ switch (dir) { case DIR_RECEIVED: case DIR_BASE_TO_STA: //base->data_sent++; sta->data_received++; break; case DIR_SENT: case DIR_STA_TO_BASE: //base->data_received++; sta->data_sent++; break; } pixie_leave_critical_section(sqdb->cs); }
void regmac_event(struct SQDB *sqdb, unsigned event_type, const unsigned char *bssid, const unsigned char *mac_address, unsigned frame_type, struct NetFrame *frame) { struct SQDB_SubStation *sta; struct SQDB_AccessPoint *ap; struct SQDB_Event *event; time_t timestamp = sqdb->kludge.time_stamp; pixie_enter_critical_section(sqdb->cs); ap = sqdb_create_bssid(sqdb, bssid); sta = sqdb_lookup_substation(sqdb, mac_address, bssid); /* If the existing event doesn't match this, then we need to close it */ if (sta->current_event && sta->current_event->type != event_type) { event_close(sqdb, sta->current_event); } /* If there is no current event, create one */ if (sta->current_event == NULL) event_new(sqdb, sta, ap, sqdb->kludge.time_stamp, event_type); event = sta->current_event; /* update latest time */ if (event->time_last < timestamp) event->time_last = timestamp; /* Do different logic, depending on the event type */ event_update_packet(event, frame_type, frame); pixie_leave_critical_section(sqdb->cs); }
/** * Create a list pointing to discovered stations */ struct TMP_STATIONS * sqdb_enum_probers(struct SQDB *sqdb, size_t *count) { unsigned i; unsigned total_stations = 0; unsigned n; struct TMP_STATIONS *result; bool still_swapping; pixie_enter_critical_section(sqdb->cs); /* First, count all the station records */ for (i=0; i<sizeof(sqdb->stations)/sizeof(sqdb->stations[0]); i++) { struct SQDB_Station *entry = sqdb->stations[i]; while (entry) { total_stations++; entry = entry->next; } } /* Allocate a list of the stations */ result = (struct TMP_STATIONS*)malloc(sizeof(result[0]) * (total_stations + 1)); n = 0; for (i=0; i<sizeof(sqdb->stations)/sizeof(sqdb->stations[0]); i++) { struct SQDB_Station *entry = sqdb->stations[i]; while (entry) { result[n].sta.unassociated = entry; result[n].last_update = entry->dbm_last_update; result[n].type = 1; n++; entry = entry->next; } } result[n].type = 0; *count = total_stations; /* Sort the list so that most recent are on top */ still_swapping = true; if (total_stations) while (still_swapping) { still_swapping = false; for (i=0; i<total_stations-1; i++) { if (result[i].last_update < result[i+1].last_update) { struct TMP_STATIONS x; memcpy(&x, &result[i], sizeof(x)); memcpy(&result[i], &result[i+1], sizeof(x)); memcpy(&result[i+1], &x, sizeof(x)); still_swapping = true; } } } pixie_leave_critical_section(sqdb->cs); return result; }
/*=========================================================================== *===========================================================================*/ void xml_station_item(struct mg_connection *c, const struct mg_request_info *ri, void *user_data) { struct SQDB *sqdb = (struct SQDB*)user_data; unsigned char mac_address[6]; char mac_address_str[16] = ""; struct TMP_STATIONS *stations=NULL; unsigned station_count = 0; pixie_enter_critical_section(sqdb->cs); if (memcmp(ri->uri, "/station/", 9) != 0) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } /* * Lookup this BSSID entry */ parse_mac_address(mac_address, sizeof(mac_address), ri->uri+strlen("/station/")); stations = sqdb_find_station(sqdb, mac_address, &station_count); if (stations == NULL || station_count == 0) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } sprintf_s(mac_address_str, sizeof(mac_address_str), "%02x%02x%02x%02x%02x%02x", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); mg_headers_ok(c, "text/xml"); X(c, "Connection: close\r\n"); X(c, "\r\n"); X(c, "<?xml version=\"1.0\" ?>\n"); X(c, "<update timestamp=\"%u\">\n", time(0)); X(c, " <station id=\"%02x%02x%02x%02x%02x%02x\">\n", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); X(c, " <mac>[%02x:%02x:%02x:%02x:%02x:%02x]</mac>\n", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); X(c, " </station>\n"); X(c, "</update>\n"); _return: pixie_leave_critical_section(sqdb->cs); if (stations) free(stations); }
/** * Lookup a MAC address in the system and see whether it refers * to an access-point or a normal station */ unsigned sqdb_station_type(struct SQDB *sqdb, const unsigned char *mac_address) { unsigned result = STATION_TYPE_UNKNOWN; pixie_enter_critical_section(sqdb->cs); if ((mac_address[0]&1) == 1) result = STATION_TYPE_MULTICAST; else { struct XMAC *xmac; xmac = xmac_create(&sqdb->macs, mac_address); result = xmac->type; } pixie_leave_critical_section(sqdb->cs); return result; }
/** * Add access-point information for a beacon or probe-response packet * Returns '1' if a new entry was created, or '0' otherwise */ unsigned sqdb_add_beacon( struct SQDB *sqdb, const unsigned char *src_mac, const unsigned char *bssid, struct SQDB_String ssid, unsigned channel, struct SQDB_RateList rates1, struct SQDB_RateList rates2, unsigned is_adhoc, struct SQDB_String cisco_name ) { struct SQDB_AccessPoint *entry; /*unsigned is_new = false;*/ pixie_enter_critical_section(sqdb->cs); /* * Look up the entry in the hash table */ entry = sqdb_create_bssid(sqdb, bssid); entry->flag_is_ibss = is_adhoc; if (memcmp(entry->mac_address.addr, "\0\0\0\0\0\0", 6) == 0) memcpy(entry->mac_address.addr, src_mac, 6); regmac_base(sqdb, bssid, src_mac); regmac_base_ssid(sqdb, bssid, &ssid); sqdb_base_channel(entry, channel); sqdb_string_copy(&entry->cisco_name, &cisco_name); entry->beacon_count++; /* * See if the Rates fields are the same */ if (!sqdb_ratesfield_equal(&entry->rates1, &rates1)) { sqdb_ratesfield_copy(&entry->rates1, &rates1); } if (!sqdb_ratesfield_equal(&entry->rates2, &rates2)) { sqdb_ratesfield_copy(&entry->rates2, &rates2); } pixie_leave_critical_section(sqdb->cs); return 0; }
void sqdb_add_info(struct SQDB *sqdb, const unsigned char *mac_address, const unsigned char *bssid, const char *name, const char *value) { struct SQDB_SubStation *sta; struct NVPair **r_data; struct NVPair *d; unsigned name_length = strlen(name); unsigned value_length = strlen(value); /* Filter out some common names that I see */ if (MATCHESZ(name, "domain")) { if (MATCHESZ(value, "savvis.net")) return; } pixie_enter_critical_section(sqdb->cs); sta = sqdb_lookup_substation(sqdb, mac_address, bssid); if (sta == NULL) goto _return; for (r_data = &sta->data; *r_data; r_data = &(*r_data)->next) { d = *r_data; if (MATCHESZ(d->name, name) && MATCHESZ(d->value, value)) goto _return; } d = (struct NVPair*)malloc(sizeof(*d)); d->name = (char*)malloc(name_length+1); memcpy(d->name, name, name_length+1); d->value = (char*)malloc(value_length+1); memcpy(d->value, value, value_length+1); d->next = 0; *r_data = d; _return: pixie_leave_critical_section(sqdb->cs); }
void regmac_base(struct SQDB *sqdb, const unsigned char *bssid, const unsigned char *mac_address) { struct SQDB_AccessPoint *base; struct XMAC *xmac; pixie_enter_critical_section(sqdb->cs); base = sqdb_create_bssid(sqdb, bssid); if (!sqdb_contains_mac_address(base, mac_address)) { sqdb_ap_add_mac_address(base, mac_address); /* Create a link to this from the master MAC address registery */ xmac = xmac_create(&sqdb->macs, bssid); xmac->type = STATION_TYPE_BASE; xmac->base = base; } pixie_leave_critical_section(sqdb->cs); }
unsigned sqdb_set_bssid_packet(struct SQDB *sqdb, const unsigned char *bssid, unsigned type, const struct SquirrelPacket *pkt) { struct SQDB_AccessPoint *ap; unsigned i; pixie_enter_critical_section(sqdb->cs); ap = sqdb_create_bssid(sqdb, bssid); if (pkt->px[0] == 0x80) i = 0; /* Beacon */ else if (pkt->px[0] == 0x50) i = 1; /* Probe Response */ else return 0; if (ap) { unsigned char *px; if (ap->packets[i].px == NULL) { /* If no existing packets, then allocate a buffer */ px = (unsigned char*)malloc(pkt->length); } else if (ap->packets[i].length < pkt->length) { /* If there was already a buffer, but it's too short, * then allocate a replacement buffer that's long enough */ free((unsigned char*)ap->packets[i].px); px = (unsigned char*)malloc(pkt->length); } else { /* The existing buffer is big enough, so just reusee it */ px = (unsigned char*)ap->packets[i].px; } memcpy(&ap->packets[i], pkt, sizeof(*pkt)); ap->packets[i].px = px; memcpy(px, pkt->px, pkt->length); } pixie_leave_critical_section(sqdb->cs); return 0; }
void regmac_base_rates(struct SQDB *sqdb, const unsigned char *bssid, struct SQDB_RateList *rates1, struct SQDB_RateList *rates2) { struct SQDB_AccessPoint *entry; pixie_enter_critical_section(sqdb->cs); entry = sqdb_create_bssid(sqdb, bssid); if (rates1) { if (!sqdb_ratesfield_equal(&entry->rates1, rates1)) { sqdb_ratesfield_copy(&entry->rates1, rates1); } } if (rates2) { if (!sqdb_ratesfield_equal(&entry->rates2, rates2)) { sqdb_ratesfield_copy(&entry->rates2, rates2); } } pixie_leave_critical_section(sqdb->cs); }
void regmac_station_ctrl(struct SQDB *sqdb, const unsigned char *bssid, const unsigned char *mac_address, unsigned dir) { struct SQDB_SubStation *sta; struct SQDB_AccessPoint *base; pixie_enter_critical_section(sqdb->cs); base = sqdb_create_bssid(sqdb, bssid); sta = sqdb_lookup_substation(sqdb, mac_address, bssid); switch (dir) { case DIR_RECEIVED: case DIR_BASE_TO_STA: base->ctrl_sent++; sta->ctrl_received++; break; case DIR_SENT: case DIR_STA_TO_BASE: base->ctrl_received++; sta->ctrl_sent++; break; } pixie_leave_critical_section(sqdb->cs); }
void regmac_transmit_power(struct SQDB *sqdb, const unsigned char *src, int dbm, time_t timestamp) { struct XMAC *xmac; if (dbm == 0) return; pixie_enter_critical_section(sqdb->cs); xmac = xmac_create(&sqdb->macs, src); switch (xmac->type) { case STATION_TYPE_BASE: { struct SQDB_AccessPoint *entry = xmac->base; entry->dbm = dbm; entry->dbm_last_update = timestamp; } break; case STATION_TYPE_STA: { struct SQDB_SubStation *entry = xmac->sta; entry->dbm = dbm; entry->dbm_last_update = timestamp; } break; case STATION_TYPE_STA_ALONE: { struct SQDB_Station *entry = xmac->sta_alone; entry->dbm = dbm; entry->dbm_last_update = timestamp; } break; } pixie_leave_critical_section(sqdb->cs); }
/*=========================================================================== *===========================================================================*/ void display_station_item(struct mg_connection *c, const struct mg_request_info *ri, void *user_data) { struct SQDB *sqdb = (struct SQDB*)user_data; unsigned char mac_address[6]; char mac_address_str[16]; char buf[64]; struct TMP_STATIONS *stations = NULL; unsigned station_count = 0; unsigned i; if (strstr(ri->uri, ".xml")) { xml_station_item(c, ri, user_data); return; } pixie_enter_critical_section(sqdb->cs); if (memcmp(ri->uri, "/station/", 9) != 0) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } /* * Lookup this BSSID entry */ parse_mac_address(mac_address, sizeof(mac_address), ri->uri+strlen("/station/")); stations = sqdb_find_station(sqdb, mac_address, &station_count); if (stations == 0 || station_count == 0) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } sprintf_s(mac_address_str, sizeof(mac_address_str), "%02x%02x%02x%02x%02x%02x", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); mg_headers_ok(c, "text/html"); X(c, "Connection: close\r\n"); X(c, "\r\n"); //X(c, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\r\n"); X(c,"<html>\n"); X(c,"<head>\n"); X(c," <title>Squirrel WiFi monitor</title>\n"); X(c," <link rel=\"stylesheet\" type=\"text/css\" href=\"../squirrel.css\" />\n"); X(c," <link rel=\"Shortcut Icon\" href=\"../favicon.ico\" type=\"image/x-icon\">\n"); X(c," <script type=\"text/javascript\" src=\"../squirrel.js\"></script>\n"); X(c, "<script type=\"text/javascript\">var bssid_item_address = '%s';</script>\n", mac_address_str); X(c,"</head>\n"); X(c,"<body onLoad=\"setInterval(refresh_station_item,1000)\">\n"); display_topmenu(c, ri, user_data, 1); for (i=0; i<station_count; i++) { struct TMP_STATIONS *tmp = &stations[i]; /* * ASSOCIATED station */ if (tmp->type == 2) { struct SQDB_SubStation *sta = tmp->sta.associated; struct SQDB_AccessPoint *ap = tmp->sta.accesspoint; X(c, "<table id=\"station\" class=\"station\">\n"); X(c, " <tr id=\"0\"><th colspan=\"6\" class=\"title\">ASSOCIATED STATION</th></tr>\n"); X(c, " <tr id=\"1\">\n"); X(c, " <th>MAC:</th><td id=\"mac\" class=\"mac\">[%02x:%02x:%02x:%02x:%02x:%02x]</td>\n", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5], mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); X(c, " <th>Data Sent:</th><td id=\"dataout\" class=\"sent\">%s</td>\n", format_unsigned(sta->data_sent,buf,sizeof(buf))); X(c, " <th>Data Recv:</th><td id=\"datain\" class=\"sent\">%s</td>\n", format_unsigned(sta->data_received,buf,sizeof(buf))); X(c, " </tr>\n"); X(c, " <tr id=\"2\">\n"); X(c, " <th>SSID:</th><td id=\"essid\" class=\"essid\"><a href=\"/bssid/%02x%02x%02x%02x%02x%02x.html\">%.*s</a></td>\n", ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], ap->ssid.length, ap->ssid.value); X(c, " <th>Ctrl Sent:</th><td id=\"ctrlout\" class=\"sent\">%s</td>\n", format_unsigned(sta->ctrl_sent,buf,sizeof(buf))); X(c, " <th>Ctrl Recv:</th><td id=\"ctrlin\" class=\"sent\">%s</td>\n", format_unsigned(sta->ctrl_received,buf,sizeof(buf))); X(c, " </tr>\n"); X(c, " <tr id=\"4\">\n"); X(c, " <th>BSSID:</th><td id=\"bssid\" class=\"bssid\"><a href=\"/bssid/%02x%02x%02x%02x%02x%02x.html\">%02x:%02x:%02x:%02x:%02x:%02x</a></td>\n", ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5], ap->bssid[0], ap->bssid[1], ap->bssid[2], ap->bssid[3], ap->bssid[4], ap->bssid[5] ); X(c, " <th>Power:</th><td id=\"power\" class=\"power\">%s</td>\n", format_signed(sta->dbm,buf,sizeof(buf))); X(c, " <th>Channels:</th><td id=\"channels\" class=\"channels\">"); { unsigned j; for (j=0; j<ap->channel_count; j++) { X(c, "%u%c", ap->channels[j], (j+1<ap->channel_count?',':' ')); } } X(c, "</td>\n"); X(c, " </tr>\n"); X(c, " <tr id=\"6\">\n"); X(c, " <th>MANUF:</th><td id=\"manuf\" class=\"manuf\">%s</td>\n", manuf_from_mac(mac_address)); X(c, " <th>Desc:</th><td id=\"manuf2\" class=\"manuf2\" colspan=\"3\">%s</td>\n", manuf2_from_mac(mac_address)); X(c, " </tr>\n"); X(c, " <tr id=\"7\">\n"); X(c, " <th>Info:</th><td id=\"manuf\" class=\"manuf\" colspan=\"5\">\n"); { struct NVPair *nv = sta->data; while (nv) { X(c, " %s = %s<br/>\n", nv->name, nv->value); nv = nv->next; } } X(c, " </th>\n"); X(c, " </tr>\n"); X(c, "</table><br/>\n"); } if (tmp->type == 1) { struct SQDB_Station *sta = tmp->sta.unassociated; X(c, "<table id=\"station\" class=\"station\">\n"); X(c, " <tr id=\"0\"><th colspan=\"6\" class=\"title\">UNASSOCIATED PROBER</th></tr>\n"); X(c, " <tr id=\"1\">\n"); X(c, " <th>MAC:</th><td id=\"mac\" class=\"mac\">[%02x:%02x:%02x:%02x:%02x:%02x]</td>\n", mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5], mac_address[0],mac_address[1],mac_address[2], mac_address[3],mac_address[4],mac_address[5] ); X(c, " <th>Probes:</th><td id=\"dataout\" class=\"sent\">%s</td>\n", format_unsigned(sta->probe_count,buf,sizeof(buf))); X(c, " <th>Responses:</th><td id=\"datain\" class=\"sent\">%s</td>\n", format_unsigned(0,buf,sizeof(buf))); X(c, " </tr>\n"); X(c, " <tr id=\"7\">\n"); X(c, " <th>SSIDs:</th><td id=\"essid\" class=\"essid\" colspan=\"5\">\n"); { struct EntrySSID *s; for (s=&sta->ssid; s; s = s->next) { char defanged[1024]; defang_ssid(defanged, sizeof(defanged), (const char*)s->ssid.value, s->ssid.length); X(c, "%s<br/>", defanged); } } X(c, " </th>\n"); X(c, " </tr>\n"); X(c, "</table><br/>\n"); } } X(c, "</body>\n" "</html>\n" ); _return: pixie_leave_critical_section(sqdb->cs); if (stations) free(stations); }
/*=========================================================================== *===========================================================================*/ void display_adapters(struct mg_connection *c, const struct mg_request_info *ri, void *user_data) { struct Squirrel *squirrel = (struct Squirrel *)user_data; char errbuf[1024]; unsigned interface_channel = 0; char *action = mg_get_var(c, "action"); pixie_enter_critical_section(squirrel->cs); /* If a CGI request was sent to change an adapter status, then do that change */ if (action) ; //change_adapter_status( mg_headers_ok(c, "text/html"); X(c, "Connection: close\r\n"); X(c, "\r\n"); //X(c, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\r\n"); X(c,"<html>\n"); X(c,"<head>\n"); X(c," <title>Squirrel WiFi monitor / Adapters</title>\n"); X(c," <link rel=\"stylesheet\" type=\"text/css\" href=\"squirrel.css\" />\n"); X(c," <link rel=\"Shortcut Icon\" href=\"favicon.ico\" type=\"image/x-icon\">\n"); X(c,"</head>\n"); X(c,"<body>\n"); display_topmenu(c, ri, user_data, 0); if (!pcap.is_available) { X(c, "<h1>ERROR: no libpcap</h1>\n"); X(c, " On Unix, install libpcap from tcpdump site. On Windows, instal WinPcap from WinDump site.\n"); goto _return; } else if (pcap.findalldevs(&alldevs, errbuf) == -1) { X(c, "<h1>ERROR: no adapters found</h1>\n"); X(c, "<p>%s</p>\n", errbuf); X(c, "<p>Make sure you have root/administrator privileges</p>\n"); goto _return; } else if (alldevs == NULL) { X(c, "<h1>ERROR: no adapters found</h1>\n"); X(c, "<p>Make sure you have root/administrator privileges</p>\n"); goto _return; } else { pcap_if_t *d; unsigned i=0; /* Print the list */ X(c, "<table class=\"bssids\">\n"); X(c, " <tr><th>Index</th><th>Name</th><th>Driver</th><th>Description</th><th>Monitor</th><th>Channel</th></tr>\n"); for(d=alldevs; d; d=d->next) { const char *driver = ""; if (strstr(d->name, "\\airpcap")) { driver = "airpcap"; } else { driver = "airpcap"; } ++i; X(c, " <tr>\n"); X(c, " <td class=\"index\"><a href=\"monitor.php?index=%d\">%d</a></td>\n", i, i); X(c, " <td><a href=\"adapter/%s.html\">%s</td>\n", d->name, d->name); if (strstr(d->name, "\\airpcap")) { X(c, " <td>airpcap</td>\n\n"); } else { X(c, " <td>ndis</td>\n"); } if (d->description) X(c, " <td>%s</td>\n", d->description); else X(c, " <td>%s</td>\n", ""); if (squirrel_get_interface_status(squirrel, d->name, &interface_channel)) { X(c, " <td id=\"status\">" "<form action=\"/adapters.html\">" "<input type=\"hidden\" name=\"adapter\" value=\"%s\">" "<input type=\"submit\" name=\"action\" value=\"Stop\">" "</form></td>\n", d->name); if (interface_channel == 0) X(c, " <td id=\"channel\">%s</td>\n", ""); else if (interface_channel == (unsigned)-1) X(c, " <td id=\"channel\">%s</td>\n", "scan"); else X(c, " <td id=\"channel\">%u</td>\n", interface_channel); } else { X(c, " <td id=\"status\">" "<form action=\"/adapters.html\">" "<input type=\"hidden\" name=\"adapter\" value=\"%s\">" "<input type=\"submit\" name=\"action\" value=\"Start\">" "</form></td>\n", d->name); X(c, " <td id=\"channel\">%s</td>\n", ""); } } X(c, "</table>\n"); } _return: pixie_leave_critical_section(squirrel->cs); }
/*=========================================================================== *===========================================================================*/ void display_adapter(struct mg_connection *c, const struct mg_request_info *ri, void *user_data) { struct Squirrel *squirrel = (struct Squirrel *)user_data; char adapter_name[256]; char description[256]; unsigned exists; const char *driver = ""; unsigned interface_channel = 0; pixie_enter_critical_section(squirrel->cs); if (memcmp(ri->uri, "/adapter/", 9) != 0) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } else sprintf_s(adapter_name, sizeof(adapter_name), "%s", ri->uri+9); if (strlen(adapter_name) > 5 && memcmp(adapter_name+strlen(adapter_name)-5, ".html", 5) == 0) adapter_name[strlen(adapter_name)-5] = '\0'; if (strlen(adapter_name) > 7 && memcmp(adapter_name, "airpcap", 7) == 0 && strlen(adapter_name) < sizeof(adapter_name)-5) { memmove(adapter_name+4, adapter_name, strlen(adapter_name)+1); memcpy(adapter_name, "\\\\.\\", 4); } exists = adapter_description(adapter_name, description, sizeof(description)); if (!exists) { mg_printf(c, "404 Not Found\r\nConnection: closed\r\n\r\n"); goto _return; } if (strstr(adapter_name, "\\airpcap")) { driver = "airpcap"; } else { driver = "ndis"; } mg_headers_ok(c, "text/html"); X(c, "Connection: close\r\n"); X(c, "\r\n"); //X(c, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\r\n"); X(c,"<html>\n"); X(c,"<head>\n"); X(c," <title>Squirrel WiFi monitor / Adapter</title>\n"); X(c," <link rel=\"stylesheet\" type=\"text/css\" href=\"../squirrel.css\" />\n"); X(c," <link rel=\"Shortcut Icon\" href=\"../favicon.ico\" type=\"image/x-icon\">\n"); X(c,"</head>\n"); X(c,"<body>\n"); display_topmenu(c, ri, user_data, 0); /* * Do any necessary changes */ { char *status = mg_get_var(c, "status"); char *channel = mg_get_var(c, "channel"); if (status && channel) { unsigned is_running = squirrel_get_interface_status(squirrel, adapter_name, &interface_channel); unsigned new_channel; if (strcmp(channel, "scan") == 0) new_channel = (unsigned)-1; else if (isdigit(channel[0])) new_channel = atoi(channel); else new_channel = 0; if (is_running && strcmp(status, "monitor") != 0) { /* Turn off the adapter */ squirrel_set_interface_status(squirrel, adapter_name, 0, 0); X(c, "<b>Turned off adapter</b>\n"); } else if (!is_running && strcmp(status, "monitor") == 0) { launch_thread(squirrel, adapter_name); squirrel_set_interface_status(squirrel, adapter_name, 1, new_channel); X(c, "<b>Turned on adapter, channel %u</b>\n", new_channel); } else if (is_running && interface_channel != new_channel) { squirrel_set_interface_status(squirrel, adapter_name, 1, new_channel); X(c, "<b>Changed channel to %u</b>\n", new_channel); } else X(c, "<b>Nothing changed</b>\n"); } if (status) free(status); if (channel) free(channel); } X(c, "<table class=\"adapter\">\n"); X(c, " <tr><th>Adapter:</th><td>%s</td></tr>\n", adapter_name); X(c, " <tr><th>Description:</th><td>%s</td></tr>\n", description); X(c, " <tr><th>Driver:</th><td>%s</td></tr>\n", driver); X(c, " <tr><th>Monitor Mode:</th><td>%s</td></tr>\n", can_monitor_mode(adapter_name)?"yes":"no"); X(c, " <tr><th>Can Transmit:</th><td>%s</td></tr>\n", can_transmit(adapter_name)?"yes":"no"); if (squirrel_get_interface_status(squirrel, adapter_name, &interface_channel)) { X(c, " <tr><th>Status:</th><td>%s</td></tr>\n", "monitoring"); if (interface_channel == 0) X(c, " <tr><th>Channel:</th><td>%s</td></tr>\n", ""); else if (interface_channel == (unsigned)-1) X(c, " <tr><th>Channel:</th><td>%s</td></tr>\n", "scan"); else X(c, " <tr><th>Channel:</th><td>%u</td></tr>\n", interface_channel); } else { X(c, " <tr><th>Status:</th><td>%s</td></tr>\n", "off"); X(c, " <tr><th>Channel:</th><td>%s</td></tr>\n", ""); } X(c, "</table>\n"); X(c, "<hr/>\n"); X(c, "<form action=\"%s.html\">\n", adapter_name); X(c, " <input type=\"radio\" name=\"status\" value=\"monitor\" /> Monitor<br/>\n"); X(c, " <input type=\"radio\" name=\"status\" value=\"off\" /> Off<br/>\n"); X(c, " Channel: <input type=\"text\" name=\"channel\" value=\"scan\"/><br/>\n"); X(c, " <input type=\"submit\" value=\"Submit\">\n"); X(c, "</form>\n"); _return: pixie_leave_critical_section(squirrel->cs); }
unsigned sqdb_add_probe_request( struct SQDB *sqdb, const unsigned char *src_mac, struct SQDB_String ssid, struct SQDB_RateList rates1, struct SQDB_RateList rates2 ) { struct SQDB_Station *entry; unsigned is_new = false; pixie_enter_critical_section(sqdb->cs); /* * Look up the entry in the hash table */ { struct SQDB_Station **r_entry; unsigned index = bssid_hash(src_mac); r_entry = &sqdb->stations[index]; while ((*r_entry) && memcmp((*r_entry)->mac_address, src_mac, 6) != 0) r_entry = &((*r_entry)->next); if (*r_entry == NULL) { struct XMAC *xmac; char myssid[256]; unsigned myssid_length; *r_entry = (struct SQDB_Station*)malloc(sizeof(**r_entry)); memset(*r_entry, 0, sizeof(**r_entry)); memcpy((*r_entry)->mac_address, src_mac, 6); sqdb_string_copy(&(*r_entry)->ssid.ssid, &ssid); is_new = true; /* Create a link to this from the master MAC address registery */ xmac = xmac_create(&sqdb->macs, src_mac); xmac->type = STATION_TYPE_STA_ALONE; xmac->sta_alone = *r_entry; myssid_length = format_ssid(myssid, sizeof(myssid), (const char*)ssid.value, ssid.length); SQUIRREL_EVENT(" %02X:%02X:%02X:%02X:%02X:%02X " "probe=\"%.*s\" " "%.*s" "\n", PRINTMAC(src_mac), myssid_length, myssid, (ssid.length>16)?0:(16-ssid.length), " " ); } entry = *r_entry; } entry->probe_count++; /* * See if the SSID of the network has changed. This should * never really happen. */ if (!sqdb_string_is_equal(&entry->ssid.ssid, &ssid)) { struct EntrySSID **r; unsigned found = 0; for (r=&entry->ssid.next; *r; r = &((*r)->next)) { if (sqdb_string_is_equal(&(*r)->ssid, &ssid)) { found = 1; break; } } if (!found) { char myssid[256]; unsigned myssid_length; myssid_length = format_ssid(myssid, sizeof(myssid), (const char*)ssid.value, ssid.length); *r = (struct EntrySSID*)malloc(sizeof(**r)); memset(*r, 0, sizeof(**r)); sqdb_string_copy(&(*r)->ssid, &ssid); SQUIRREL_EVENT(" %02X:%02X:%02X:%02X:%02X:%02X probe=\"%.*s\"\n", PRINTMAC(src_mac), myssid_length, myssid); } } /* * See if the Rates fields are the same */ if (!sqdb_ratesfield_equal(&entry->rates1, &rates1)) { sqdb_ratesfield_copy(&entry->rates1, &rates1); } if (!sqdb_ratesfield_equal(&entry->rates2, &rates2)) { sqdb_ratesfield_copy(&entry->rates2, &rates2); } pixie_leave_critical_section(sqdb->cs); return 0; }