File: prism2source.cc

package info (click to toggle)
kismet 1.4.2-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 504 kB
  • ctags: 435
  • sloc: cpp: 2,741; makefile: 126; sh: 29
file content (125 lines) | stat: -rw-r--r-- 3,185 bytes parent folder | download
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;
}