nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /*
|
2 | * Copyright (c) 1993,1994
|
||
3 | * Texas A&M University. All rights reserved.
|
||
4 | *
|
||
5 | * Redistribution and use in source and binary forms, with or without
|
||
6 | * modification, are permitted provided that the following conditions
|
||
7 | * are met:
|
||
8 | * 1. Redistributions of source code must retain the above copyright
|
||
9 | * notice, this list of conditions and the following disclaimer.
|
||
10 | * 2. Redistributions in binary form must reproduce the above copyright
|
||
11 | * notice, this list of conditions and the following disclaimer in the
|
||
12 | * documentation and/or other materials provided with the distribution.
|
||
13 | * 3. All advertising materials mentioning features or use of this software
|
||
14 | * must display the following acknowledgement:
|
||
15 | * This product includes software developed by Texas A&M University
|
||
16 | * and its contributors.
|
||
17 | * 4. Neither the name of the University nor the names of its contributors
|
||
18 | * may be used to endorse or promote products derived from this software
|
||
19 | * without specific prior written permission.
|
||
20 | *
|
||
21 | * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
|
||
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
|
||
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
31 | * SUCH DAMAGE.
|
||
32 | *
|
||
33 | * Developers:
|
||
34 | * David K. Hess, Douglas Lee Schales, David R. Safford
|
||
35 | *
|
||
36 | * Heavily modified for Metaware HighC + GNU C 2.8+
|
||
37 | * Gisle Vanem 1998
|
||
38 | */ |
||
39 | |||
40 | #include <stdio.h> |
||
41 | #include <stdlib.h> |
||
42 | #include <dos.h> |
||
43 | #include <io.h> |
||
44 | #include <fcntl.h> |
||
45 | #include <malloc.h> |
||
46 | #include <string.h> |
||
47 | |||
48 | #include "pcap-dos.h" |
||
49 | #include "pcap-int.h" |
||
50 | #include "msdos/ndis2.h" |
||
51 | |||
52 | #if defined(USE_NDIS2) |
||
53 | |||
54 | /*
|
||
55 | * Packet buffer handling
|
||
56 | */ |
||
57 | extern int FreePktBuf (PktBuf *buf); |
||
58 | extern int EnquePktBuf (PktBuf *buf); |
||
59 | extern PktBuf* AllocPktBuf (void); |
||
60 | |||
61 | /*
|
||
62 | * Various defines
|
||
63 | */ |
||
64 | #define MAX_NUM_DEBUG_STRINGS 90 |
||
65 | #define DEBUG_STRING_LENGTH 80 |
||
66 | #define STACK_POOL_SIZE 6 |
||
67 | #define STACK_SIZE 256 |
||
68 | |||
69 | #define MEDIA_FDDI 1 |
||
70 | #define MEDIA_ETHERNET 2 |
||
71 | #define MEDIA_TOKEN 3 |
||
72 | |||
73 | static int startDebug = 0; |
||
74 | static int stopDebug = 0; |
||
75 | |||
76 | static DWORD droppedPackets = 0L; |
||
77 | static WORD frameSize = 0; |
||
78 | static WORD headerSize = 0; |
||
79 | static int mediaType = 0; |
||
80 | static char *lastErr = NULL; |
||
81 | |||
82 | static BYTE debugStrings [MAX_NUM_DEBUG_STRINGS][DEBUG_STRING_LENGTH]; |
||
83 | static BYTE *freeStacks [STACK_POOL_SIZE]; |
||
84 | static int freeStackPtr = STACK_POOL_SIZE - 1; |
||
85 | |||
86 | static ProtMan protManEntry = NULL; |
||
87 | static WORD protManDS = 0; |
||
88 | static volatile int xmitPending; |
||
89 | |||
90 | static struct _PktBuf *txBufPending; |
||
91 | static struct _CardHandle *handle; |
||
92 | static struct _CommonChars common; |
||
93 | static struct _ProtocolChars protChars; |
||
94 | static struct _ProtDispatch lowerTable; |
||
95 | |||
96 | static struct _FailingModules failingModules; |
||
97 | static struct _BindingsList bindings; |
||
98 | |||
99 | static struct { |
||
100 | WORD err_num; |
||
101 | char *err_text; |
||
102 | } ndis_errlist[] = { |
||
103 | |||
104 | { ERR_SUCCESS, |
||
105 | "The function completed successfully.\n" }, |
||
106 | |||
107 | { ERR_WAIT_FOR_RELEASE, |
||
108 | "The ReceiveChain completed successfully but the protocol has\n" |
||
109 | "retained control of the buffer.\n" }, |
||
110 | |||
111 | { ERR_REQUEST_QUEUED, |
||
112 | "The current request has been queued.\n" }, |
||
113 | |||
114 | { ERR_FRAME_NOT_RECOGNIZED, |
||
115 | "Frame not recognized.\n" }, |
||
116 | |||
117 | { ERR_FRAME_REJECTED, |
||
118 | "Frame was discarded.\n" }, |
||
119 | |||
120 | { ERR_FORWARD_FRAME, |
||
121 | "Protocol wishes to forward frame to another protocol.\n" }, |
||
122 | |||
123 | { ERR_OUT_OF_RESOURCE, |
||
124 | "Out of resource.\n" }, |
||
125 | |||
126 | { ERR_INVALID_PARAMETER, |
||
127 | "Invalid parameter.\n" }, |
||
128 | |||
129 | { ERR_INVALID_FUNCTION, |
||
130 | "Invalid function.\n" }, |
||
131 | |||
132 | { ERR_NOT_SUPPORTED, |
||
133 | "Not supported.\n" }, |
||
134 | |||
135 | { ERR_HARDWARE_ERROR, |
||
136 | "Hardware error.\n" }, |
||
137 | |||
138 | { ERR_TRANSMIT_ERROR, |
||
139 | "The packet was not transmitted due to an error.\n" }, |
||
140 | |||
141 | { ERR_NO_SUCH_DESTINATION, |
||
142 | "Token ring packet was not recognized when transmitted.\n" }, |
||
143 | |||
144 | { ERR_BUFFER_TOO_SMALL, |
||
145 | "Provided buffer was too small.\n" }, |
||
146 | |||
147 | { ERR_ALREADY_STARTED, |
||
148 | "Network drivers already started.\n" }, |
||
149 | |||
150 | { ERR_INCOMPLETE_BINDING, |
||
151 | "Protocol driver could not complete its bindings.\n" }, |
||
152 | |||
153 | { ERR_DRIVER_NOT_INITIALIZED, |
||
154 | "MAC did not initialize properly.\n" }, |
||
155 | |||
156 | { ERR_HARDWARE_NOT_FOUND, |
||
157 | "Hardware not found.\n" }, |
||
158 | |||
159 | { ERR_HARDWARE_FAILURE, |
||
160 | "Hardware failure.\n" }, |
||
161 | |||
162 | { ERR_CONFIGURATION_FAILURE, |
||
163 | "Configuration failure.\n" }, |
||
164 | |||
165 | { ERR_INTERRUPT_CONFLICT, |
||
166 | "Interrupt conflict.\n" }, |
||
167 | |||
168 | { ERR_INCOMPATIBLE_MAC, |
||
169 | "The MAC is not compatible with the protocol.\n" }, |
||
170 | |||
171 | { ERR_INITIALIZATION_FAILED, |
||
172 | "Initialization failed.\n" }, |
||
173 | |||
174 | { ERR_NO_BINDING, |
||
175 | "Binding did not occur.\n" }, |
||
176 | |||
177 | { ERR_NETWORK_MAY_NOT_BE_CONNECTED, |
||
178 | "The network may not be connected to the adapter.\n" }, |
||
179 | |||
180 | { ERR_INCOMPATIBLE_OS_VERSION, |
||
181 | "The version of the operating system is incompatible with the protocol.\n" }, |
||
182 | |||
183 | { ERR_ALREADY_REGISTERED, |
||
184 | "The protocol is already registered.\n" }, |
||
185 | |||
186 | { ERR_PATH_NOT_FOUND, |
||
187 | "PROTMAN.EXE could not be found.\n" }, |
||
188 | |||
189 | { ERR_INSUFFICIENT_MEMORY, |
||
190 | "Insufficient memory.\n" }, |
||
191 | |||
192 | { ERR_INFO_NOT_FOUND, |
||
193 | "Protocol Mananger info structure is lost or corrupted.\n" }, |
||
194 | |||
195 | { ERR_GENERAL_FAILURE, |
||
196 | "General failure.\n" } |
||
197 | }; |
||
198 | |||
199 | /*
|
||
200 | * Some handy macros
|
||
201 | */ |
||
202 | #define PERROR(str) printf("%s (%d): %s\n", __FILE__,__LINE__,str) |
||
203 | #define DEBUG_RING() (debugStrings[stopDebug+1 == MAX_NUM_DEBUG_STRINGS ? \ |
||
204 | stopDebug = 0 : ++stopDebug]) |
||
205 | |||
206 | /*
|
||
207 | * needs rewrite for DOSX
|
||
208 | */ |
||
209 | #define MAC_DISPATCH(hnd) ((struct _MacUpperDispatch*)(hnd)->common->upperDispatchTable) |
||
210 | #define MAC_STATUS(hnd) ((struct _MacStatusTable*) (hnd)->common->serviceStatus) |
||
211 | #define MAC_CHAR(hnd) ((struct _MacChars*) (hnd)->common->serviceChars) |
||
212 | |||
213 | #ifdef NDIS_DEBUG |
||
214 | #define DEBUG0(str) printf (str) |
||
215 | #define DEBUG1(fmt,a) printf (fmt,a) |
||
216 | #define DEBUG2(fmt,a,b) printf (fmt,a,b) |
||
217 | #define TRACE0(str) sprintf (DEBUG_RING(),str) |
||
218 | #define TRACE1(fmt,a) sprintf (DEBUG_RING(),fmt,a) |
||
219 | #else
|
||
220 | #define DEBUG0(str) ((void)0) |
||
221 | #define DEBUG1(fmt,a) ((void)0) |
||
222 | #define DEBUG2(fmt,a,b) ((void)0) |
||
223 | #define TRACE0(str) ((void)0) |
||
224 | #define TRACE1(fmt,a) ((void)0) |
||
225 | #endif
|
||
226 | |||
227 | /*
|
||
228 | * This routine is called from both threads
|
||
229 | */ |
||
230 | void NdisFreeStack (BYTE *aStack) |
||
231 | { |
||
232 | GUARD(); |
||
233 | |||
234 | if (freeStackPtr == STACK_POOL_SIZE - 1) |
||
235 | PERROR ("tried to free too many stacks"); |
||
236 | |||
237 | freeStacks[++freeStackPtr] = aStack; |
||
238 | |||
239 | if (freeStackPtr == 0) |
||
240 | TRACE0 ("freeStackPtr went positive\n"); |
||
241 | |||
242 | UNGUARD(); |
||
243 | } |
||
244 | |||
245 | /*
|
||
246 | * This routine is called from callbacks to allocate local data
|
||
247 | */ |
||
248 | BYTE *NdisAllocStack (void) |
||
249 | { |
||
250 | BYTE *stack; |
||
251 | |||
252 | GUARD(); |
||
253 | |||
254 | if (freeStackPtr < 0) |
||
255 | { |
||
256 | /* Ran out of stack buffers. Return NULL which will start
|
||
257 | * dropping packets
|
||
258 | */ |
||
259 | TRACE0 ("freeStackPtr went negative\n"); |
||
260 | stack = 0; |
||
261 | } |
||
262 | else |
||
263 | stack = freeStacks[freeStackPtr--]; |
||
264 | |||
265 | UNGUARD(); |
||
266 | return (stack); |
||
267 | } |
||
268 | |||
269 | CALLBACK (NdisSystemRequest (DWORD param1, DWORD param2, WORD param3, |
||
270 | WORD opcode, WORD targetDS)) |
||
271 | { |
||
272 | static int bindEntry = 0; |
||
273 | struct _CommonChars *macCommon; |
||
274 | volatile WORD result; |
||
275 | |||
276 | switch (opcode) |
||
277 | { |
||
278 | case REQ_INITIATE_BIND: |
||
279 | macCommon = (struct _CommonChars*) param2; |
||
280 | if (macCommon == NULL) |
||
281 | { |
||
282 | printf ("There is an NDIS misconfiguration.\n"); |
||
283 | result = ERR_GENERAL_FAILURE; |
||
284 | break; |
||
285 | } |
||
286 | DEBUG2 ("module name %s\n" |
||
287 | "module type %s\n", |
||
288 | macCommon->moduleName, |
||
289 | ((MacChars*) macCommon->serviceChars)->macName); |
||
290 | |||
291 | /* Binding to the MAC */ |
||
292 | result = macCommon->systemRequest ((DWORD)&common, (DWORD)&macCommon, |
||
293 | 0, REQ_BIND, |
||
294 | macCommon->moduleDS); |
||
295 | |||
296 | if (!strcmp(bindings.moduleName[bindEntry], handle->moduleName)) |
||
297 | handle->common = macCommon; |
||
298 | else PERROR ("unknown module"); |
||
299 | ++bindEntry; |
||
300 | break; |
||
301 | |||
302 | case REQ_INITIATE_UNBIND: |
||
303 | macCommon = (struct _CommonChars*) param2; |
||
304 | result = macCommon->systemRequest ((DWORD)&common, 0, |
||
305 | 0, REQ_UNBIND, |
||
306 | macCommon->moduleDS); |
||
307 | break; |
||
308 | |||
309 | default: |
||
310 | result = ERR_GENERAL_FAILURE; |
||
311 | break; |
||
312 | } |
||
313 | ARGSUSED (param1); |
||
314 | ARGSUSED (param3); |
||
315 | ARGSUSED (targetDS); |
||
316 | return (result); |
||
317 | } |
||
318 | |||
319 | CALLBACK (NdisRequestConfirm (WORD protId, WORD macId, WORD reqHandle, |
||
320 | WORD status, WORD request, WORD protDS)) |
||
321 | { |
||
322 | ARGSUSED (protId); ARGSUSED (macId); |
||
323 | ARGSUSED (reqHandle); ARGSUSED (status); |
||
324 | ARGSUSED (request); ARGSUSED (protDS); |
||
325 | return (ERR_SUCCESS); |
||
326 | } |
||
327 | |||
328 | CALLBACK (NdisTransmitConfirm (WORD protId, WORD macId, WORD reqHandle, |
||
329 | WORD status, WORD protDS)) |
||
330 | { |
||
331 | xmitPending--; |
||
332 | FreePktBuf (txBufPending); /* Add passed ECB back to the free list */ |
||
333 | |||
334 | ARGSUSED (reqHandle); |
||
335 | ARGSUSED (status); |
||
336 | ARGSUSED (protDS); |
||
337 | return (ERR_SUCCESS); |
||
338 | } |
||
339 | |||
340 | |||
341 | /*
|
||
342 | * The primary function for receiving packets
|
||
343 | */ |
||
344 | CALLBACK (NdisReceiveLookahead (WORD macId, WORD frameSize, |
||
345 | WORD bytesAvail, BYTE *buffer, |
||
346 | BYTE *indicate, WORD protDS)) |
||
347 | { |
||
348 | int result; |
||
349 | PktBuf *pktBuf; |
||
350 | WORD bytesCopied; |
||
351 | struct _TDBufDescr tDBufDescr; |
||
352 | |||
353 | #if 0 |
||
354 | TRACE1 ("lookahead length = %d, ", bytesAvail); |
||
355 | TRACE1 ("ecb = %08lX, ", *ecb); |
||
356 | TRACE1 ("count = %08lX\n", count); |
||
357 | TRACE1 ("offset = %08lX, ", offset); |
||
358 | TRACE1 ("timesAllowed = %d, ", timesAllowed); |
||
359 | TRACE1 ("packet size = %d\n", look->dataLookAheadLen); |
||
360 | #endif
|
||
361 | |||
362 | /* Allocate a buffer for the packet
|
||
363 | */ |
||
364 | if ((pktBuf = AllocPktBuf()) == NULL) |
||
365 | { |
||
366 | droppedPackets++; |
||
367 | return (ERR_FRAME_REJECTED); |
||
368 | } |
||
369 | |||
370 | /*
|
||
371 | * Now kludge things. Note we will have to undo this later. This will
|
||
372 | * make the packet contiguous after the MLID has done the requested copy.
|
||
373 | */ |
||
374 | |||
375 | tDBufDescr.tDDataCount = 1; |
||
376 | tDBufDescr.tDBufDescrRec[0].tDPtrType = NDIS_PTR_PHYSICAL; |
||
377 | tDBufDescr.tDBufDescrRec[0].tDDataPtr = pktBuf->buffer; |
||
378 | tDBufDescr.tDBufDescrRec[0].tDDataLen = pktBuf->length; |
||
379 | tDBufDescr.tDBufDescrRec[0].dummy = 0; |
||
380 | |||
381 | result = MAC_DISPATCH(handle)->transferData (&bytesCopied, 0, &tDBufDescr, |
||
382 | handle->common->moduleDS); |
||
383 | pktBuf->packetLength = bytesCopied; |
||
384 | |||
385 | if (result == ERR_SUCCESS) |
||
386 | EnquePktBuf(pktBuf); |
||
387 | else FreePktBuf (pktBuf); |
||
388 | |||
389 | ARGSUSED (frameSize); |
||
390 | ARGSUSED (bytesAvail); |
||
391 | ARGSUSED (indicate); |
||
392 | ARGSUSED (protDS); |
||
393 | |||
394 | return (ERR_SUCCESS); |
||
395 | } |
||
396 | |||
397 | CALLBACK (NdisIndicationComplete (WORD macId, WORD protDS)) |
||
398 | { |
||
399 | ARGSUSED (macId); |
||
400 | ARGSUSED (protDS); |
||
401 | |||
402 | /* We don't give a hoot about these. Just return
|
||
403 | */ |
||
404 | return (ERR_SUCCESS); |
||
405 | } |
||
406 | |||
407 | /*
|
||
408 | * This is the OTHER way we may receive packets
|
||
409 | */ |
||
410 | CALLBACK (NdisReceiveChain (WORD macId, WORD frameSize, WORD reqHandle, |
||
411 | struct _RxBufDescr *rxBufDescr, |
||
412 | BYTE *indicate, WORD protDS)) |
||
413 | { |
||
414 | struct _PktBuf *pktBuf; |
||
415 | int i; |
||
416 | |||
417 | /*
|
||
418 | * For now we copy the entire packet over to a PktBuf structure. This may be
|
||
419 | * a performance hit but this routine probably isn't called very much, and
|
||
420 | * it is a lot of work to do it otherwise. Also if it is a filter protocol
|
||
421 | * packet we could end up sucking up MAC buffes.
|
||
422 | */ |
||
423 | |||
424 | if ((pktBuf = AllocPktBuf()) == NULL) |
||
425 | { |
||
426 | droppedPackets++; |
||
427 | return (ERR_FRAME_REJECTED); |
||
428 | } |
||
429 | pktBuf->packetLength = 0; |
||
430 | |||
431 | /* Copy the packet to the buffer
|
||
432 | */ |
||
433 | for (i = 0; i < rxBufDescr->rxDataCount; ++i) |
||
434 | { |
||
435 | struct _RxBufDescrRec *rxDescr = &rxBufDescr->rxBufDescrRec[i]; |
||
436 | |||
437 | memcpy (pktBuf->buffer + pktBuf->packetLength, |
||
438 | rxDescr->rxDataPtr, rxDescr->rxDataLen); |
||
439 | pktBuf->packetLength += rxDescr->rxDataLen; |
||
440 | } |
||
441 | |||
442 | EnquePktBuf (pktBuf); |
||
443 | |||
444 | ARGSUSED (frameSize); |
||
445 | ARGSUSED (reqHandle); |
||
446 | ARGSUSED (indicate); |
||
447 | ARGSUSED (protDS); |
||
448 | |||
449 | /* This frees up the buffer for the MAC to use
|
||
450 | */ |
||
451 | return (ERR_SUCCESS); |
||
452 | } |
||
453 | |||
454 | CALLBACK (NdisStatusProc (WORD macId, WORD param1, BYTE *indicate, |
||
455 | WORD opcode, WORD protDS)) |
||
456 | { |
||
457 | switch (opcode) |
||
458 | { |
||
459 | case STATUS_RING_STATUS: |
||
460 | break; |
||
461 | case STATUS_ADAPTER_CHECK: |
||
462 | break; |
||
463 | case STATUS_START_RESET: |
||
464 | break; |
||
465 | case STATUS_INTERRUPT: |
||
466 | break; |
||
467 | case STATUS_END_RESET: |
||
468 | break; |
||
469 | default: |
||
470 | break; |
||
471 | } |
||
472 | ARGSUSED (macId); |
||
473 | ARGSUSED (param1); |
||
474 | ARGSUSED (indicate); |
||
475 | ARGSUSED (opcode); |
||
476 | ARGSUSED (protDS); |
||
477 | |||
478 | /* We don't need to do anything about this stuff yet
|
||
479 | */ |
||
480 | return (ERR_SUCCESS); |
||
481 | } |
||
482 | |||
483 | /*
|
||
484 | * Tell the NDIS driver to start the delivery of the packet
|
||
485 | */ |
||
486 | int NdisSendPacket (struct _PktBuf *pktBuf, int macId) |
||
487 | { |
||
488 | struct _TxBufDescr txBufDescr; |
||
489 | int result; |
||
490 | |||
491 | xmitPending++; |
||
492 | txBufPending = pktBuf; /* we only have 1 pending Tx at a time */ |
||
493 | |||
494 | txBufDescr.txImmedLen = 0; |
||
495 | txBufDescr.txImmedPtr = NULL; |
||
496 | txBufDescr.txDataCount = 1; |
||
497 | txBufDescr.txBufDescrRec[0].txPtrType = NDIS_PTR_PHYSICAL; |
||
498 | txBufDescr.txBufDescrRec[0].dummy = 0; |
||
499 | txBufDescr.txBufDescrRec[0].txDataLen = pktBuf->packetLength; |
||
500 | txBufDescr.txBufDescrRec[0].txDataPtr = pktBuf->buffer; |
||
501 | |||
502 | result = MAC_DISPATCH(handle)->transmitChain (common.moduleId, |
||
503 | pktBuf->handle, |
||
504 | &txBufDescr, |
||
505 | handle->common->moduleDS); |
||
506 | switch (result) |
||
507 | { |
||
508 | case ERR_OUT_OF_RESOURCE: |
||
509 | /* Note that this should not happen but if it does there is not
|
||
510 | * much we can do about it
|
||
511 | */ |
||
512 | printf ("ERROR: transmit queue overflowed\n"); |
||
513 | return (0); |
||
514 | |||
515 | case ERR_SUCCESS: |
||
516 | /* Everything was hunky dory and synchronous. Free up the
|
||
517 | * packet buffer
|
||
518 | */ |
||
519 | xmitPending--; |
||
520 | FreePktBuf (pktBuf); |
||
521 | return (1); |
||
522 | |||
523 | case ERR_REQUEST_QUEUED: |
||
524 | /* Everything was hunky dory and asynchronous. Do nothing
|
||
525 | */ |
||
526 | return (1); |
||
527 | |||
528 | default: |
||
529 | printf ("Tx fail, code = %04X\n", result); |
||
530 | return (0); |
||
531 | } |
||
532 | } |
||
533 | |||
534 | |||
535 | |||
536 | static int ndis_nerr = sizeof(ndis_errlist) / sizeof(ndis_errlist[0]); |
||
537 | |||
538 | static char *Ndis_strerror (WORD errorCode) |
||
539 | { |
||
540 | static char buf[30]; |
||
541 | int i; |
||
542 | |||
543 | for (i = 0; i < ndis_nerr; i++) |
||
544 | if (errorCode == ndis_errlist[i].err_num) |
||
545 | return (ndis_errlist[i].err_text); |
||
546 | |||
547 | sprintf (buf,"unknown error %d",errorCode); |
||
548 | return (buf); |
||
549 | } |
||
550 | |||
551 | |||
552 | char *NdisLastError (void) |
||
553 | { |
||
554 | char *errStr = lastErr; |
||
555 | lastErr = NULL; |
||
556 | return (errStr); |
||
557 | } |
||
558 | |||
559 | int NdisOpen (void) |
||
560 | { |
||
561 | struct _ReqBlock reqBlock; |
||
562 | int result; |
||
563 | int ndisFd = open (NDIS_PATH, O_RDONLY); |
||
564 | |||
565 | if (ndisFd < 0) |
||
566 | { |
||
567 | printf ("Could not open NDIS Protocol Manager device.\n"); |
||
568 | return (0); |
||
569 | } |
||
570 | |||
571 | memset (&reqBlock, 0, sizeof(ReqBlock)); |
||
572 | |||
573 | reqBlock.opcode = PM_GET_PROTOCOL_MANAGER_LINKAGE; |
||
574 | |||
575 | result = NdisGetLinkage (ndisFd, (char*)&reqBlock, sizeof(ReqBlock)); |
||
576 | if (result != 0) |
||
577 | { |
||
578 | printf ("Could not get Protocol Manager linkage.\n"); |
||
579 | close (ndisFd); |
||
580 | return (0); |
||
581 | } |
||
582 | |||
583 | close (ndisFd); |
||
584 | protManEntry = (ProtMan) reqBlock.pointer1; |
||
585 | protManDS = reqBlock.word1; |
||
586 | |||
587 | DEBUG2 ("Entry Point = %04X:%04X\n", FP_SEG(protManEntry),FP_OFF(protManEntry)); |
||
588 | DEBUG1 ("ProtMan DS = %04X\n", protManDS); |
||
589 | return (1); |
||
590 | } |
||
591 | |||
592 | |||
593 | int NdisRegisterAndBind (int promis) |
||
594 | { |
||
595 | struct _ReqBlock reqBlock; |
||
596 | WORD result; |
||
597 | |||
598 | memset (&common,0,sizeof(common)); |
||
599 | |||
600 | common.tableSize = sizeof (common); |
||
601 | |||
602 | common.majorNdisVersion = 2; |
||
603 | common.minorNdisVersion = 0; |
||
604 | common.majorModuleVersion = 2; |
||
605 | common.minorModuleVersion = 0; |
||
606 | |||
607 | /* Indicates binding from below and dynamically loaded
|
||
608 | */ |
||
609 | common.moduleFlags = 0x00000006L; |
||
610 | |||
611 | strcpy (common.moduleName, "PCAP"); |
||
612 | |||
613 | common.protocolLevelUpper = 0xFF; |
||
614 | common.protocolLevelLower = 1; |
||
615 | common.interfaceLower = 1; |
||
616 | #ifdef __DJGPP__ |
||
617 | common.moduleDS = _dos_ds; /* the callback data segment */ |
||
618 | #else
|
||
619 | common.moduleDS = _DS; |
||
620 | #endif
|
||
621 | |||
622 | common.systemRequest = (SystemRequest) systemRequestGlue; |
||
623 | common.serviceChars = (BYTE*) &protChars; |
||
624 | common.serviceStatus = NULL; |
||
625 | common.upperDispatchTable = NULL; |
||
626 | common.lowerDispatchTable = (BYTE*) &lowerTable; |
||
627 | |||
628 | protChars.length = sizeof (protChars); |
||
629 | protChars.name[0] = 0; |
||
630 | protChars.type = 0; |
||
631 | |||
632 | lowerTable.backPointer = &common; |
||
633 | lowerTable.requestConfirm = requestConfirmGlue; |
||
634 | lowerTable.transmitConfirm = transmitConfirmGlue; |
||
635 | lowerTable.receiveLookahead = receiveLookaheadGlue; |
||
636 | lowerTable.indicationComplete = indicationCompleteGlue; |
||
637 | lowerTable.receiveChain = receiveChainGlue; |
||
638 | lowerTable.status = statusGlue; |
||
639 | lowerTable.flags = 3; |
||
640 | if (promis) |
||
641 | lowerTable.flags |= 4; /* promiscous mode (receive everything) */ |
||
642 | |||
643 | bindings.numBindings = 1; |
||
644 | strcpy (bindings.moduleName[0], handle->moduleName); |
||
645 | |||
646 | /* Register ourselves with NDIS
|
||
647 | */ |
||
648 | reqBlock.opcode = PM_REGISTER_MODULE; |
||
649 | reqBlock.pointer1 = (BYTE FAR*) &common; |
||
650 | reqBlock.pointer2 = (BYTE FAR*) &bindings; |
||
651 | |||
652 | result = (*protManEntry) (&reqBlock, protManDS); |
||
653 | if (result) |
||
654 | { |
||
655 | printf ("Protman registering failed: %s\n", Ndis_strerror(result)); |
||
656 | return (0); |
||
657 | } |
||
658 | |||
659 | /* Start the binding process
|
||
660 | */ |
||
661 | reqBlock.opcode = PM_BIND_AND_START; |
||
662 | reqBlock.pointer1 = (BYTE FAR*) &failingModules; |
||
663 | |||
664 | result = (*protManEntry) (&reqBlock, protManDS); |
||
665 | if (result) |
||
666 | { |
||
667 | printf ("Start binding failed: %s\n", Ndis_strerror(result)); |
||
668 | return (0); |
||
669 | } |
||
670 | return (1); |
||
671 | } |
||
672 | |||
673 | static int CheckMacFeatures (CardHandle *card) |
||
674 | { |
||
675 | DWORD serviceFlags; |
||
676 | BYTE _far *mediaString; |
||
677 | BYTE _far *mac_addr; |
||
678 | |||
679 | DEBUG2 ("checking card features\n" |
||
680 | "common table address = %08lX, macId = %d\n", |
||
681 | card->common, card->common->moduleId); |
||
682 | |||
683 | serviceFlags = MAC_CHAR (handle)->serviceFlags; |
||
684 | |||
685 | if ((serviceFlags & SF_PROMISCUOUS) == 0) |
||
686 | { |
||
687 | printf ("The MAC %s does not support promiscuous mode.\n", |
||
688 | card->moduleName); |
||
689 | return (0); |
||
690 | } |
||
691 | |||
692 | mediaString = MAC_CHAR (handle)->macName; |
||
693 | |||
694 | DEBUG1 ("media type = %s\n",mediaString); |
||
695 | |||
696 | /* Get the media type. And set the header size
|
||
697 | */ |
||
698 | if (!strncmp(mediaString,"802.3",5) || |
||
699 | !strncmp(mediaString,"DIX",3) || |
||
700 | !strncmp(mediaString,"DIX+802.3",9)) |
||
701 | headerSize = sizeof (EthernetIIHeader); |
||
702 | |||
703 | else if (!strncmp(mediaString,"FDDI",4)) |
||
704 | headerSize = sizeof (FddiHeader) + |
||
705 | sizeof (Ieee802Dot2SnapHeader); |
||
706 | else |
||
707 | { |
||
708 | printf ("Unsupported MAC type: `%s'\n", mediaString); |
||
709 | return (0); |
||
710 | } |
||
711 | |||
712 | frameSize = MAC_CHAR (handle)->maxFrameSize; |
||
713 | mac_addr = MAC_CHAR (handle)->currentAddress; |
||
714 | |||
715 | printf ("Hardware address: %02X:%02X:%02X:%02X:%02X:%02X\n", |
||
716 | mac_addr[0], mac_addr[1], mac_addr[2], |
||
717 | mac_addr[3], mac_addr[4], mac_addr[5]); |
||
718 | return (1); |
||
719 | } |
||
720 | |||
721 | static int NdisStartMac (CardHandle *card) |
||
722 | { |
||
723 | WORD result; |
||
724 | |||
725 | /* Set the lookahead length
|
||
726 | */ |
||
727 | result = MAC_DISPATCH(handle)->request (common.moduleId, 0, |
||
728 | headerSize, 0, |
||
729 | REQ_SET_LOOKAHEAD, |
||
730 | card->common->moduleDS); |
||
731 | |||
732 | /* We assume that if we got INVALID PARAMETER then either this
|
||
733 | * is not supported or will work anyway. NE2000 does this.
|
||
734 | */ |
||
735 | if (result != ERR_SUCCESS && result != ERR_INVALID_PARAMETER) |
||
736 | { |
||
737 | DEBUG1 ("Set lookahead failed: %s\n", Ndis_strerror(result)); |
||
738 | return (0); |
||
739 | } |
||
740 | |||
741 | /* Set the packet filter. Note that for some medias and drivers we
|
||
742 | * must specify all three flags or the card(s) will not operate correctly.
|
||
743 | */ |
||
744 | result = MAC_DISPATCH(handle)->request (common.moduleId, 0, |
||
745 | /* all packets */ FILTER_PROMISCUOUS | |
||
746 | /* packets to us */ FILTER_DIRECTED | |
||
747 | /* broadcasts */ FILTER_BROADCAST, |
||
748 | 0, REQ_SET_PACKET_FILTER, |
||
749 | card->common->moduleDS); |
||
750 | if (result != ERR_SUCCESS) |
||
751 | { |
||
752 | DEBUG1 ("Set packet filter failed: %s\n", Ndis_strerror(result)); |
||
753 | return (0); |
||
754 | } |
||
755 | |||
756 | /* If OPEN/CLOSE supported then open the adapter
|
||
757 | */ |
||
758 | if (MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) |
||
759 | { |
||
760 | result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, NULL, |
||
761 | REQ_OPEN_ADAPTER, |
||
762 | card->common->moduleDS); |
||
763 | if (result != ERR_SUCCESS) |
||
764 | { |
||
765 | DEBUG1 ("Opening the MAC failed: %s\n", Ndis_strerror(result)); |
||
766 | return (0); |
||
767 | } |
||
768 | } |
||
769 | return (1); |
||
770 | } |
||
771 | |||
772 | void NdisShutdown (void) |
||
773 | { |
||
774 | struct _ReqBlock reqBlock; |
||
775 | int result, i; |
||
776 | |||
777 | if (!handle) |
||
778 | return; |
||
779 | |||
780 | /* If the adapters support open and are open then close them
|
||
781 | */ |
||
782 | if ((MAC_CHAR(handle)->serviceFlags & SF_OPEN_CLOSE) && |
||
783 | (MAC_STATUS(handle)->macStatus & MAC_OPEN)) |
||
784 | { |
||
785 | result = MAC_DISPATCH(handle)->request (common.moduleId, 0, 0, 0, |
||
786 | REQ_CLOSE_ADAPTER, |
||
787 | handle->common->moduleDS); |
||
788 | if (result != ERR_SUCCESS) |
||
789 | { |
||
790 | printf ("Closing the MAC failed: %s\n", Ndis_strerror(result)); |
||
791 | return; |
||
792 | } |
||
793 | } |
||
794 | |||
795 | /* Tell the Protocol Manager to unbind and stop
|
||
796 | */ |
||
797 | reqBlock.opcode = PM_UNBIND_AND_STOP; |
||
798 | reqBlock.pointer1 = (BYTE FAR*) &failingModules; |
||
799 | reqBlock.pointer2 = NULL; |
||
800 | |||
801 | result = (*protManEntry) (&reqBlock, protManDS); |
||
802 | if (result) |
||
803 | printf ("Unbind failed: %s\n", Ndis_strerror(result)); |
||
804 | |||
805 | for (i = 0; i < STACK_POOL_SIZE; ++i) |
||
806 | free (freeStacks[i] - STACK_SIZE); |
||
807 | |||
808 | handle = NULL; |
||
809 | } |
||
810 | |||
811 | int NdisInit (int promis) |
||
812 | { |
||
813 | int i, result; |
||
814 | |||
815 | /* Allocate the real mode stacks used for NDIS callbacks
|
||
816 | */ |
||
817 | for (i = 0; i < STACK_POOL_SIZE; ++i) |
||
818 | { |
||
819 | freeStacks[i] = malloc (STACK_SIZE); |
||
820 | if (!freeStacks[i]) |
||
821 | return (0); |
||
822 | freeStacks[i] += STACK_SIZE; |
||
823 | } |
||
824 | |||
825 | if (!NdisOpen()) |
||
826 | return (0); |
||
827 | |||
828 | if (!NdisRegisterAndBind(promis)) |
||
829 | return (0); |
||
830 | |||
831 | DEBUG1 ("My module id: %d\n", common.moduleId); |
||
832 | DEBUG1 ("Handle id; %d\n", handle->common->moduleId); |
||
833 | DEBUG1 ("MAC card: %-16s - ", handle->moduleName); |
||
834 | |||
835 | atexit (NdisShutdown); |
||
836 | |||
837 | if (!CheckMacFeatures(&handle)) |
||
838 | return (0); |
||
839 | |||
840 | switch (mediaType) |
||
841 | { |
||
842 | case MEDIA_FDDI: |
||
843 | DEBUG0 ("Media type: FDDI"); |
||
844 | break; |
||
845 | case MEDIA_ETHERNET: |
||
846 | DEBUG0 ("Media type: ETHERNET"); |
||
847 | break; |
||
848 | default: |
||
849 | DEBUG0 ("Unsupported media.\n"); |
||
850 | return (0); |
||
851 | } |
||
852 | |||
853 | DEBUG1 (" - Frame size: %d\n", frameSize); |
||
854 | |||
855 | if (!NdisStartMac(&handle)) |
||
856 | return (0); |
||
857 | return (1); |
||
858 | } |
||
859 | #endif /* USE_NDIS2 */ |
||
860 |