1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
|
#include <errno.h>
#include <string.h>
#include "prism2source.h"
int Prism2Source::OpenSource(const char *dev) {
snprintf(type, 64, "Prism/2");
int fds[2], r;
fd = -1;
struct sockaddr_nl addr;
r = pipe(fds);
if (r < 0) {
snprintf(errstr, 1024, "Prism2 open pipe() failed. (%s)", strerror(errno));
return(-1);
}
read_sock = fds[0];
write_sock = fds[1];
fd = socket(PF_NETLINK, SOCK_RAW, MCAST_GRP_SNIFF);
if (fd < 0) {
snprintf(errstr, 1024, "Prism2 open socket() failed. (%s)", strerror(errno));
return(-1);
}
addr.nl_family = PF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = MCAST_GRP_SNIFF;
if (bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_nl)) < 0) {
snprintf(errstr, 1024, "Prism2 open bind() failed. (%s)", strerror(errno));
return(-1);
}
snprintf(errstr, 1024, "Prism2 capture source opened.");
return(1);
}
int Prism2Source::CloseSource() {
return 1;
}
int Prism2Source::FetchPacket(pkthdr *in_header, u_char *in_data) {
fd_set rs;
int r;
struct timeval tm;
struct timeval *ptm;
if (read_sock < 0 || fd < 0) {
snprintf(errstr, 1024, "Prism2 fetch failed. (source not open)");
return(-1);
}
FD_ZERO(&rs);
FD_SET(fd, &rs);
FD_SET(read_sock, &rs);
if (PRISM2_READ_TIMEOUT >= 0) {
tm.tv_sec = PRISM2_READ_TIMEOUT / 1000;
tm.tv_usec = (PRISM2_READ_TIMEOUT % 1000) * 1000;
ptm = &tm;
} else {
ptm = NULL;
}
r = select((read_sock > fd) ? read_sock + 1 : fd + 1,
&rs, NULL, NULL, ptm);
if (r < 0) {
snprintf(errstr, 1024, "Prism2 fetch select() failed. (%s)", strerror(errno));
return(-1);
}
if (r == 0) {
if (PRISM2_READ_TIMEOUT >= 0)
return(0);
}
if (FD_ISSET(read_sock, &rs)) {
char a;
read(read_sock, &a, 1);
}
// u_char buf[MAX_PACKET_LEN];
if (FD_ISSET(fd, &rs)) {
r = recv(fd, buffer, MAX_PACKET_LEN, 0);
if (r < 0) {
// We ignore ENOBUFS since it seems to happen fairly often and is really
// annoying.
if (errno == ENOBUFS)
return 0;
snprintf(errstr, 1024, "Prism2 fetch recv() failed. (%s)", strerror(errno));
return -1;
}
}
Prism2Common(in_header, in_data);
return(in_header->len);
}
int Prism2Source::Prism2Common(pkthdr *in_header, u_char *in_data) {
sniff_packet_t *sniff_info = (sniff_packet_t *) buffer;
// For some reason prism2 returns 4 bytes longer than it needs to. I don't
// entirely know why this is, but they're all 0xFF so we just drop them entirely.
gettimeofday(&in_header->ts, NULL);
in_header->caplen = sniff_info->frmlen.data - 4;
if (sniff_info->frmlen.data > MAX_PACKET_LEN)
in_header->len = MAX_PACKET_LEN;
else
in_header->len = sniff_info->frmlen.data - 4;
// in_header->pkt_encap = WTAP_ENCAP_IEEE_802_11;
int offset = sizeof(sniff_packet_t);
memcpy(in_data, &buffer[offset], in_header->len);
return 1;
}
|