~ubuntu-branches/debian/sid/kismet/sid

« back to all changes in this revision

Viewing changes to cygwin_utils.cc

  • Committer: Bazaar Package Importer
  • Author(s): Francois Gurin
  • Date: 2008-07-04 15:36:20 UTC
  • mfrom: (3.1.10 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080704153620-e7ng9ccvd020sdhf
Tags: 2008-05-R1-4
* updated the copyright file 
* changed extra/manuf_update.sh to update the files in /etc/kismet (closes: #416105)
* updated the readme.debian (closes: #416107)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file was written by Loris Degioanni, and is part of Kismet
 
3
 
 
4
    Kismet is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    Kismet is distributed in the hope that it will be useful,
 
10
      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with Kismet; if not, write to the Free Software
 
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
17
*/
 
18
 
 
19
#include "config.h"
 
20
 
 
21
#ifdef SYS_CYGWIN
 
22
 
 
23
#include <windows.h>
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <unistd.h>
 
27
 
 
28
#define HANDLE2FD_INTERNAL
 
29
#include "cygwin_utils.h"
 
30
 
 
31
//
 
32
// There are two main parameters that can be used to tune the WinPcap performance:
 
33
// mintocopy and the read event timeout.
 
34
//
 
35
// Mintocopy is the minimum amount of data in the kernel buffer that causes the read event to
 
36
// be set by the driver. A small mintocopy means good responisiveness but high CPU load. A big
 
37
// mintocopy forces bigger kernel buffering, at the cost of low responsiveness
 
38
//
 
39
// The read event timeout can be used to check the availability of data once in a while. When the
 
40
// timeout expires, the application will unblock and perform a read, even if the driver doesn't 
 
41
// have mintocopy bytes in the buffer.
 
42
//
 
43
// Using the timeout prevents kismet from sitting forver before processing the packets when traffic 
 
44
// is low, but can cause empty reads. Therefore, we set it to a large enough interval that the 
 
45
// performace hit is neglibile.
 
46
//
 
47
#define THREAD_WAIT_INTERVAL 500
 
48
 
 
49
Handle2Fd::Handle2Fd() {
 
50
    NHandles = 1;
 
51
    ThreadAlive = 1;
 
52
    PipeSignalled = 0;
 
53
    WaitThreadHandle = NULL;
 
54
    FirstFdSet = 1;
 
55
    InitializeCriticalSection(&PipeCs);
 
56
}
 
57
 
 
58
Handle2Fd::~Handle2Fd() {
 
59
    // Kill the thread and wait until he's returned
 
60
    ThreadAlive = 0;
 
61
    SetEvent(WinHandles[0]);
 
62
    WaitForSingleObject(WaitThreadHandle, INFINITE);
 
63
}
 
64
 
 
65
// Set the pipe fd so that it unblocks select
 
66
void Handle2Fd::SetPipe() {
 
67
    int val;
 
68
 
 
69
    EnterCriticalSection(&PipeCs);
 
70
 
 
71
    if (!PipeSignalled) {
 
72
        write(PipeFds[1], &val, sizeof(val));
 
73
        fdatasync(PipeFds[1]);
 
74
        PipeSignalled = 1;
 
75
    }
 
76
 
 
77
   LeaveCriticalSection(&PipeCs);
 
78
}
 
79
 
 
80
// Reset the pipe fd so that it blocks select
 
81
void Handle2Fd::ResetPipe()
 
82
{
 
83
    int val;
 
84
 
 
85
    EnterCriticalSection(&PipeCs);
 
86
 
 
87
    // First, write something to be sure the read will not block
 
88
    write(PipeFds[1], &val, sizeof(val));
 
89
    fdatasync(PipeFds[1]);
 
90
 
 
91
    // Second, we drain the pipe
 
92
    while(read(PipeFds[0], ResetBuf, sizeof(ResetBuf)) == sizeof(ResetBuf));
 
93
 
 
94
    // Third, we clear the signalled flag
 
95
    PipeSignalled = 0;
 
96
 
 
97
    LeaveCriticalSection(&PipeCs);
 
98
}
 
99
 
 
100
// This thread handles asynchronously waiting on the Windows events.
 
101
// It signals the pipe if one or more events are set.
 
102
DWORD WINAPI Handle2Fd::WaitThread(LPVOID lpParameter) { 
 
103
        DWORD WaitRes; 
 
104
        Handle2Fd* This = (Handle2Fd*)lpParameter; 
 
105
 
 
106
        while (This->ThreadAlive) { 
 
107
                WaitRes = WaitForMultipleObjects(This->NHandles,
 
108
                                                                                 This->WinHandles,
 
109
                                                                                 FALSE,
 
110
                                                                                 THREAD_WAIT_INTERVAL);
 
111
 
 
112
                // Event number 0 is the service event used to kill the thread 
 
113
                if (WaitRes != WAIT_OBJECT_0) { 
 
114
                        ResetEvent(This->ReadEvent);
 
115
                        This->SetPipe();
 
116
                        WaitForSingleObject(This->ReadEvent, INFINITE);
 
117
                } 
 
118
        } 
 
119
 
 
120
        return 1; 
 
121
}
 
122
 
 
123
// Mark a signal as read
 
124
void Handle2Fd::Signalread() {
 
125
        SetEvent(ReadEvent);
 
126
}
 
127
 
 
128
// Activate this instance of the Handle2Fd class.
 
129
// This involves creating the pipe, the service event and the support thread
 
130
int Handle2Fd::Activate() {
 
131
 
 
132
    // Create the pipe
 
133
    if (pipe(PipeFds) != 0) {
 
134
        return -1;
 
135
    }
 
136
 
 
137
    // The fd stars in non-signaled state
 
138
    ResetPipe();
 
139
 
 
140
    // Create the event for pipe control, and put it in our list
 
141
        WinHandles[0] = CreateEvent(NULL, TRUE, FALSE, NULL);
 
142
        if (!WinHandles[0]) {
 
143
        close(PipeFds[0]);
 
144
        close(PipeFds[1]);
 
145
        return -1;
 
146
    }
 
147
 
 
148
        // Create the event that will syncronize us with the read loop
 
149
        ReadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 
150
        if (!ReadEvent) {
 
151
                close(PipeFds[0]);
 
152
                close(PipeFds[1]);
 
153
                CloseHandle(WinHandles[0]);
 
154
                return -1;
 
155
        }
 
156
 
 
157
    // Start the thread that does the handle checking
 
158
    if ((WaitThreadHandle = CreateThread(
 
159
        NULL,
 
160
        0,
 
161
        Handle2Fd::WaitThread,
 
162
        this,
 
163
        0,
 
164
        NULL)) == NULL) {
 
165
            close(PipeFds[0]);
 
166
            close(PipeFds[1]);
 
167
                        CloseHandle(WinHandles[0]);
 
168
                        CloseHandle(ReadEvent);
 
169
            return -1;
 
170
                }
 
171
 
 
172
    return 1;
 
173
}
 
174
 
 
175
// The pipe exported by the Handle2Fd class requires manual reset.
 
176
void Handle2Fd::Reset() {
 
177
        ResetPipe();
 
178
}
 
179
 
 
180
// Add a new handle to the class
 
181
int Handle2Fd::AddHandle(HANDLE h) {
 
182
    // If the thread is running, we don't accept new handles. This reduces the syncronization requirements
 
183
    if (!WaitThreadHandle) {
 
184
        if (NHandles < sizeof(WinHandles) / sizeof(WinHandles[0]) - 1) {
 
185
            WinHandles[NHandles++] = h;
 
186
            return 1;
 
187
        }
 
188
    }
 
189
 
 
190
    return -1;
 
191
}
 
192
 
 
193
// Get the pipe file descriptor.
 
194
int Handle2Fd::GetFd() {
 
195
    return PipeFds[0];
 
196
}
 
197
 
 
198
// Kismet-like MergeSet function
 
199
unsigned int Handle2Fd::MergeSet(fd_set *set, unsigned int max) {
 
200
    Reset();    // Manual reset
 
201
 
 
202
    if (!FD_ISSET(GetFd(), set)) {
 
203
        FD_SET(PipeFds[0], set);
 
204
        if (FirstFdSet) {
 
205
            max++;
 
206
            FirstFdSet = 0;
 
207
        }
 
208
    }
 
209
 
 
210
    return max;
 
211
}
 
212
 
 
213
// Nonzero if the HandleNumber event is set
 
214
int Handle2Fd::IsEventSet(unsigned int HandleNumber) {
 
215
    if (WaitForSingleObject(WinHandles[HandleNumber + 1], 0) == WAIT_OBJECT_0) {
 
216
        return 1;
 
217
    }
 
218
    else {
 
219
        return 0;
 
220
    }
 
221
}
 
222
 
 
223
#endif
 
224