1 /** \file rawnetarch_unix.c
2 * \brief Raw ethernet interface, architecture-dependent stuff
3 *
4 * \author Spiro Trikaliotis <Spiro.Trikaliotis@gmx.de>
5 * \author Bas Wassink <b.wassink@ziggo.nl>
6 *
7 * These functions let the UI enumerate the available interfaces.
8 *
9 * First, rawnet_arch_enumadapter_open() is used to start enumeration.
10 *
11 * rawnet_arch_enumadapter() is then used to gather information for each adapter
12 * present on the system, where:
13 *
14 * ppname points to a pointer which will hold the name of the interface
15 * ppdescription points to a pointer which will hold the description of the
16 * interface
17 *
18 * For each of these parameters, new memory is allocated, so it has to be
19 * freed with lib_free(), except ppdescription, which can be `NULL`, though
20 * calling lib_free() on `NULL` is safe.
21 *
22 * rawnet_arch_enumadapter_close() must be used to stop processing.
23 *
24 * Each function returns 1 on success, and 0 on failure.
25 * rawnet_arch_enumadapter() only fails if there is no more adpater; in this
26 * case, *ppname and *ppdescription are not altered.
27 */
28
29 /*
30 * This file is part of VICE, the Versatile Commodore Emulator.
31 * See README for copyright notice.
32 *
33 * This program is free software; you can redistribute it and/or modify
34 * it under the terms of the GNU General Public License as published by
35 * the Free Software Foundation; either version 2 of the License, or
36 * (at your option) any later version.
37 *
38 * This program is distributed in the hope that it will be useful,
39 * but WITHOUT ANY WARRANTY; without even the implied warranty of
40 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41 * GNU General Public License for more details.
42 *
43 * You should have received a copy of the GNU General Public License
44 * along with this program; if not, write to the Free Software
45 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
46 * 02111-1307 USA.
47 *
48 */
49
50 #include <stdint.h>
51
52 #include "vice.h"
53
54 #ifdef HAVE_RAWNET
55
56 /*
57 * if we have a pcap version with either pcap_sendpacket or pcap_inject,
58 * do not use libnet anymore!
59 */
60 #if defined(HAVE_PCAP_SENDPACKET) || defined(HAVE_PCAP_INJECT)
61 #undef HAVE_LIBNET
62 #endif
63
64 #include "pcap.h"
65
66 #ifdef HAVE_LIBNET
67 #include "libnet.h"
68 #endif
69
70 #include <assert.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74
75 #include "lib.h"
76 #include "log.h"
77 #include "rawnetarch.h"
78
79 /*
80 * FIXME: rename all remaining tfe_ stuff to rawnet_
81 */
82
83 #define RAWNET_DEBUG_WARN 1 /* this should not be deactivated
84 * If this should not be deactived, why is this
85 * here at all? --compyx
86 */
87
88
89 /** \brief Only select devices that are PCAP_IF_UP
90 *
91 * Since on Linux pcap_findalldevs() returns all interfaces, including special
92 * kernal devices such as nfqueue, filtering the list returned by pcap makes
93 * sense. Should this filtering cause trouble on other Unices, this define can
94 * be guarded with #ifdef SOME_UNIX_VERSION to disable the filtering.
95 */
96 #ifdef PCAP_IF_UP
97 #define RAWNET_ONLY_IF_UP
98 #endif
99
100
101 /** #define RAWNET_DEBUG_ARCH 1 **/
102 /** #define RAWNET_DEBUG_PKTDUMP 1 **/
103
104 /* ------------------------------------------------------------------------- */
105 /* variables needed */
106
107 static log_t rawnet_arch_log = LOG_ERR;
108
109
110 /** \brief Iterator for the list returned by pcap_findalldevs()
111 */
112 static pcap_if_t *rawnet_pcap_dev_iter = NULL;
113
114
115 /** \brief Device list returned by pcap_findalldevs()
116 *
117 * Can be `NULL` since pcap_findalldevs() considers not finding any devices a
118 * succesful outcome.
119 */
120 static pcap_if_t *rawnet_pcap_dev_list = NULL;
121
122
123 static pcap_t *rawnet_pcap_fp = NULL;
124
125 #ifdef HAVE_LIBNET
126 #ifdef VICE_USE_LIBNET_1_1
127 static libnet_t *TfeLibnetFP = NULL;
128 #else /* VICE_USE_LIBNET_1_1 */
129 static struct libnet_link_int *TfeLibnetFP = NULL;
130 #endif /* VICE_USE_LIBNET_1_1 */
131
132 static char TfeLibnetErrBuf[LIBNET_ERRBUF_SIZE];
133
134 #endif /* HAVE_LIBNET */
135
136
137 /** \brief Buffer for pcap error messages
138 */
139 static char rawnet_pcap_errbuf[PCAP_ERRBUF_SIZE];
140
141
142 #ifdef RAWNET_DEBUG_PKTDUMP
143
debug_output(const char * text,uint8_t * what,int count)144 static void debug_output( const char *text, uint8_t *what, int count )
145 {
146 char buffer[256];
147 char *p = buffer;
148 char *pbuffer1 = what;
149 int len1 = count;
150 int i;
151
152 sprintf(buffer, "\n%s: length = %u\n", text, len1);
153 fprintf(stderr, "%s", buffer);
154 do {
155 p = buffer;
156 for (i=0; (i<8) && len1>0; len1--, i++) {
157 sprintf(p, "%02x ", (unsigned int)(unsigned char)*pbuffer1++);
158 p += 3;
159 }
160 *(p-1) = '\n'; *p = 0;
161 fprintf(stderr, "%s", buffer);
162 } while (len1>0);
163 }
164 #endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
165
166
rawnet_arch_enumadapter_open(void)167 int rawnet_arch_enumadapter_open(void)
168 {
169 if (pcap_findalldevs(&rawnet_pcap_dev_list, rawnet_pcap_errbuf) == -1) {
170 log_message(rawnet_arch_log,
171 "ERROR in rawnet_arch_enumadapter_open: pcap_findalldevs: '%s'",
172 rawnet_pcap_errbuf);
173 return 0;
174 }
175
176 if (!rawnet_pcap_dev_list) {
177 log_message(rawnet_arch_log,
178 "ERROR in rawnet_arch_enumadapter_open, finding all pcap "
179 "devices - Do we have the necessary privilege rights?");
180 return 0;
181 }
182
183 rawnet_pcap_dev_iter = rawnet_pcap_dev_list;
184 return 1;
185 }
186
187
188 /** \brief Get current pcap device iterator values
189 *
190 * The \a ppname and \a ppdescription are heap-allocated via lib_stralloc()
191 * and should thus be freed after use with lib_free(). Please not that
192 * \a ppdescription can be `NULL` due to pcap_if_t->description being `NULL`,
193 * so check against `NULL` before using it. Calling lib_free() on it is safe
194 * though, free(`NULL`) is guaranteed to just do nothing.
195 *
196 * \param[out] ppname device name
197 * \param[out] ppdescription device description
198 *
199 * \return bool (1 on success, 0 on failure)
200 */
rawnet_arch_enumadapter(char ** ppname,char ** ppdescription)201 int rawnet_arch_enumadapter(char **ppname, char **ppdescription)
202 {
203 #ifdef RAWNET_ONLY_IF_UP
204 /* only select devices that are up */
205 while (rawnet_pcap_dev_iter != NULL
206 && !(rawnet_pcap_dev_iter->flags & PCAP_IF_UP)) {
207 rawnet_pcap_dev_iter = rawnet_pcap_dev_iter->next;
208 }
209 #endif
210
211 if (rawnet_pcap_dev_iter == NULL) {
212 return 0;
213 }
214
215 *ppname = lib_stralloc(rawnet_pcap_dev_iter->name);
216 /* carefull: pcap_if_t->description can be NULL and lib_stralloc() fails on
217 * passing `NULL` */
218 if (rawnet_pcap_dev_iter->description != NULL) {
219 *ppdescription = lib_stralloc(rawnet_pcap_dev_iter->description);
220 } else {
221 *ppdescription = NULL;
222 }
223
224 rawnet_pcap_dev_iter = rawnet_pcap_dev_iter->next;
225
226 return 1;
227 }
228
rawnet_arch_enumadapter_close(void)229 int rawnet_arch_enumadapter_close(void)
230 {
231 if (rawnet_pcap_dev_list) {
232 pcap_freealldevs(rawnet_pcap_dev_list);
233 rawnet_pcap_dev_list = NULL;
234 }
235 return 1;
236 }
237
rawnet_pcap_open_adapter(const char * interface_name)238 static int rawnet_pcap_open_adapter(const char *interface_name)
239 {
240 rawnet_pcap_fp = pcap_open_live((char*)interface_name, 1700, 1, 20, rawnet_pcap_errbuf);
241 if ( rawnet_pcap_fp == NULL) {
242 log_message(rawnet_arch_log, "ERROR opening adapter: '%s'", rawnet_pcap_errbuf);
243 return 0;
244 }
245
246 if (pcap_setnonblock(rawnet_pcap_fp, 1, rawnet_pcap_errbuf) < 0) {
247 log_message(rawnet_arch_log, "WARNING: Setting PCAP to non-blocking failed: '%s'", rawnet_pcap_errbuf);
248 }
249
250 /* Check the link layer. We support only Ethernet for simplicity. */
251 if (pcap_datalink(rawnet_pcap_fp) != DLT_EN10MB) {
252 log_message(rawnet_arch_log, "ERROR: TFE works only on Ethernet networks.");
253 return 0;
254 }
255
256 #ifdef HAVE_LIBNET
257 /* now, open the libnet device to be able to send afterwards */
258 #ifdef VICE_USE_LIBNET_1_1
259 TfeLibnetFP = libnet_init(LIBNET_LINK, (char *)interface_name, TfeLibnetErrBuf);
260 #else /* VICE_USE_LIBNET_1_1 */
261 TfeLibnetFP = libnet_open_link_interface(interface_name, TfeLibnetErrBuf);
262 #endif /* VICE_USE_LIBNET_1_1 */
263
264 if (TfeLibnetFP == NULL) {
265 log_message(rawnet_arch_log, "Libnet interface could not be opened: '%s'", TfeLibnetErrBuf);
266
267 if (rawnet_pcap_fp) {
268 pcap_close(rawnet_pcap_fp);
269 rawnet_pcap_fp = NULL;
270 }
271 return 0;
272 }
273 #endif /* HAVE_LIBNET */
274
275 return 1;
276 }
277
278 /* ------------------------------------------------------------------------- */
279 /* the architecture-dependend functions */
280
rawnet_arch_init(void)281 int rawnet_arch_init(void)
282 {
283 rawnet_arch_log = log_open("TFEARCH");
284
285 return 1;
286 }
287
rawnet_arch_pre_reset(void)288 void rawnet_arch_pre_reset(void)
289 {
290 #ifdef RAWNET_DEBUG_ARCH
291 log_message( rawnet_arch_log, "rawnet_arch_pre_reset()." );
292 #endif
293 }
294
rawnet_arch_post_reset(void)295 void rawnet_arch_post_reset(void)
296 {
297 #ifdef RAWNET_DEBUG_ARCH
298 log_message( rawnet_arch_log, "rawnet_arch_post_reset()." );
299 #endif
300 }
301
rawnet_arch_activate(const char * interface_name)302 int rawnet_arch_activate(const char *interface_name)
303 {
304 #ifdef RAWNET_DEBUG_ARCH
305 log_message( rawnet_arch_log, "rawnet_arch_activate()." );
306 #endif
307 if (!rawnet_pcap_open_adapter(interface_name)) {
308 return 0;
309 }
310 return 1;
311 }
312
rawnet_arch_deactivate(void)313 void rawnet_arch_deactivate( void )
314 {
315 #ifdef RAWNET_DEBUG_ARCH
316 log_message( rawnet_arch_log, "rawnet_arch_deactivate()." );
317 #endif
318 }
319
rawnet_arch_set_mac(const uint8_t mac[6])320 void rawnet_arch_set_mac( const uint8_t mac[6] )
321 {
322 #ifdef RAWNET_DEBUG_ARCH
323 log_message( rawnet_arch_log, "New MAC address set: %02X:%02X:%02X:%02X:%02X:%02X.", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
324 #endif
325 }
326
rawnet_arch_set_hashfilter(const uint32_t hash_mask[2])327 void rawnet_arch_set_hashfilter(const uint32_t hash_mask[2])
328 {
329 #ifdef RAWNET_DEBUG_ARCH
330 log_message( rawnet_arch_log, "New hash filter set: %08X:%08X.", hash_mask[1], hash_mask[0]);
331 #endif
332 }
333
334 /* int bBroadcast - broadcast */
335 /* int bIA - individual address (IA) */
336 /* int bMulticast - multicast if address passes the hash filter */
337 /* int bCorrect - accept correct frames */
338 /* int bPromiscuous - promiscuous mode */
339 /* int bIAHash - accept if IA passes the hash filter */
340
rawnet_arch_recv_ctl(int bBroadcast,int bIA,int bMulticast,int bCorrect,int bPromiscuous,int bIAHash)341 void rawnet_arch_recv_ctl(int bBroadcast, int bIA, int bMulticast, int bCorrect, int bPromiscuous, int bIAHash)
342 {
343 #ifdef RAWNET_DEBUG_ARCH
344 log_message(rawnet_arch_log, "rawnet_arch_recv_ctl() called with the following parameters:" );
345 log_message(rawnet_arch_log, "\tbBroadcast = %s", bBroadcast ? "TRUE" : "FALSE");
346 log_message(rawnet_arch_log, "\tbIA = %s", bIA ? "TRUE" : "FALSE");
347 log_message(rawnet_arch_log, "\tbMulticast = %s", bMulticast ? "TRUE" : "FALSE");
348 log_message(rawnet_arch_log, "\tbCorrect = %s", bCorrect ? "TRUE" : "FALSE");
349 log_message(rawnet_arch_log, "\tbPromiscuous = %s", bPromiscuous ? "TRUE" : "FALSE");
350 log_message(rawnet_arch_log, "\tbIAHash = %s", bIAHash ? "TRUE" : "FALSE");
351 #endif
352 }
353
rawnet_arch_line_ctl(int bEnableTransmitter,int bEnableReceiver)354 void rawnet_arch_line_ctl(int bEnableTransmitter, int bEnableReceiver )
355 {
356 #ifdef RAWNET_DEBUG_ARCH
357 log_message(rawnet_arch_log,
358 "rawnet_arch_line_ctl() called with the following parameters:");
359 log_message(rawnet_arch_log,
360 "\tbEnableTransmitter = %s", bEnableTransmitter ? "TRUE" : "FALSE");
361 log_message(rawnet_arch_log,
362 "\tbEnableReceiver = %s", bEnableReceiver ? "TRUE" : "FALSE");
363 #endif
364 }
365
366
367 /** \brief Raw pcap packet
368 */
369 typedef struct rawnet_pcap_internal_s {
370 unsigned int len; /**< length of packet data */
371 uint8_t *buffer; /**< packet data */
372 } rawnet_pcap_internal_t;
373
374
375 /** \brief Callback function invoked by libpcap for every incoming packet
376 *
377 * \param[in,out] param reference to internal VICE packet struct
378 * \param[in] header pcap header
379 * \param[in] pkt_data packet data
380 */
rawnet_pcap_packet_handler(u_char * param,const struct pcap_pkthdr * header,const u_char * pkt_data)381 static void rawnet_pcap_packet_handler(u_char *param,
382 const struct pcap_pkthdr *header, const u_char *pkt_data)
383 {
384 rawnet_pcap_internal_t *pinternal = (void*)param;
385
386 /* determine the count of bytes which has been returned,
387 * but make sure not to overrun the buffer
388 */
389 if (header->caplen < pinternal->len) {
390 pinternal->len = header->caplen;
391 }
392
393 memcpy(pinternal->buffer, pkt_data, pinternal->len);
394 }
395
396
397 /** \brief Receives a frame
398 *
399 * If there's none, it returns a -1 in \a pinternal->len, if there is one,
400 * it returns the length of the frame in bytes in \a pinternal->len.
401 *
402 * It copies the frame to \a buffer and returns the number of copied bytes as
403 * the return value.
404 *
405 * \param[in,out] pinternal internal VICE packet struct
406 *
407 * \note At most 'len' bytes are copied.
408 *
409 * \return number of bytes copied or -1 on failure
410 */
rawnet_arch_receive_frame(rawnet_pcap_internal_t * pinternal)411 static int rawnet_arch_receive_frame(rawnet_pcap_internal_t *pinternal)
412 {
413 int ret = -1;
414
415 /* check if there is something to receive */
416 if (pcap_dispatch(rawnet_pcap_fp, 1, rawnet_pcap_packet_handler,
417 (void*)pinternal) != 0) {
418 /* Something has been received */
419 ret = pinternal->len;
420 }
421
422 #ifdef RAWNET_DEBUG_ARCH
423 log_message(rawnet_arch_log,
424 "rawnet_arch_receive_frame() called, returns %d.", ret);
425 #endif
426
427 return ret;
428 }
429
430 #ifdef HAVE_LIBNET
431
432 # ifdef VICE_USE_LIBNET_1_1
433
434 # define RAWNET_ARCH_TRANSMIT rawnet_arch_transmit_libnet_1_1
435
rawnet_arch_transmit_libnet_1_1(int force,int onecoll,int inhibit_crc,int tx_pad_dis,int txlength,uint8_t * txframe)436 static void rawnet_arch_transmit_libnet_1_1(int force, int onecoll,
437 int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe)
438 {
439 /* we want to send via libnet */
440
441 do {
442 libnet_pblock_t *p;
443
444 p = libnet_pblock_new(TfeLibnetFP, txlength);
445
446 if (p == NULL) {
447 log_message(rawnet_arch_log,
448 "WARNING! Could not send packet, libnet_pblock_probe() failed!");
449 break;
450 }
451
452 if ( libnet_pblock_append(TfeLibnetFP, p, txframe, txlength) == -1 ) {
453 log_message(rawnet_arch_log,
454 "WARNING! Could not send packet, libnet_pblock_append() failed!");
455 break;
456 }
457
458 libnet_pblock_update(TfeLibnetFP, p, 0, LIBNET_PBLOCK_ETH_H);
459
460 if ( libnet_write(TfeLibnetFP) == -1 ) {
461 log_message(rawnet_arch_log,
462 "WARNING! Could not send packet, libnet_write() failed!");
463 break;
464 }
465
466 libnet_pblock_delete(TfeLibnetFP, p);
467
468 } while (0);
469 }
470
471 # else /* VICE_USE_LIBNET_1_1 */
472
473 # define RAWNET_ARCH_TRANSMIT rawnet_arch_transmit_libnet_1_0
474
rawnet_arch_transmit_libnet_1_0(int force,int onecoll,int inhibit_crc,int tx_pad_dis,int txlength,uint8_t * txframe)475 static void rawnet_arch_transmit_libnet_1_0(int force, int onecoll,
476 int inhibit_crc, int tx_pad_dis, int txlength, uint8_t *txframe)
477 {
478 u_char *plibnet_buffer = NULL;
479
480 /* we want to send via libnet 1.0 */
481
482 if (libnet_init_packet(txlength, &plibnet_buffer)==-1) {
483 log_message(rawnet_arch_log, "WARNING! Could not send packet!");
484 } else {
485 if (plibnet_buffer) {
486 memcpy(plibnet_buffer, txframe, txlength);
487 libnet_write_link_layer(TfeLibnetFP, "eth0", plibnet_buffer, txlength);
488 libnet_destroy_packet(&plibnet_buffer);
489 } else {
490 log_message(rawnet_arch_log,
491 "WARNING! Could not send packet: plibnet_buffer==NULL, "
492 "but libnet_init_packet() did NOT fail!!");
493 }
494 }
495
496 }
497
498 # endif
499
500 #else /* HAVE_LIBNET */
501
502 # define RAWNET_ARCH_TRANSMIT rawnet_arch_transmit_pcap
503
504 #if defined(HAVE_PCAP_INJECT)
505 #define PCAP_INJECT pcap_inject
506 #elif defined(HAVE_PCAP_SENDPACKET)
507 #define PCAP_INJECT pcap_sendpacket
508 #else
509 #error SHOULD NOT HAPPEN: No libnet, but neither HAVE_PCAP_SENDPACKET nor HAVE_PCAP_INJECT are defined!
510 #endif
511
512
513 /** \brief Transmit a packet(?) via pcap
514 *
515 */
rawnet_arch_transmit_pcap(int force,int onecoll,int inhibit_crc,int tx_pad_dis,int txlength,uint8_t * txframe)516 static void rawnet_arch_transmit_pcap(int force, int onecoll, int inhibit_crc,
517 int tx_pad_dis, int txlength, uint8_t *txframe)
518 {
519 /* we want to send via pcap */
520
521 if (PCAP_INJECT(rawnet_pcap_fp, txframe, txlength) < 0) {
522 log_message(rawnet_arch_log, "WARNING! Could not send packet!");
523 }
524 }
525
526 #endif /* HAVE_LIBNET */
527
528
529 /** \brief Transmit a frame
530 *
531 * \param[in] force Delete waiting frames in transmit buffer
532 * \param[in] onecoll Terminate after just one collision
533 * \param[in] inhibit_crc Do not append CRC to the transmission
534 * \param[in] tx_pad_dis Disable padding to 60 Bytes
535 * \param[in] txlength Frame length
536 * \param[in] txframe Pointer to the frame to be transmitted
537 */
rawnet_arch_transmit(int force,int onecoll,int inhibit_crc,int tx_pad_dis,int txlength,uint8_t * txframe)538 void rawnet_arch_transmit(int force, int onecoll, int inhibit_crc,
539 int tx_pad_dis, int txlength, uint8_t *txframe)
540 {
541 #ifdef RAWNET_DEBUG_ARCH
542 log_message(rawnet_arch_log,
543 "rawnet_arch_transmit() called, with: force = %s, onecoll = %s, "
544 "inhibit_crc=%s, tx_pad_dis=%s, txlength=%u",
545 force ? "TRUE" : "FALSE",
546 onecoll ? "TRUE" : "FALSE",
547 inhibit_crc ? "TRUE" : "FALSE",
548 tx_pad_dis ? "TRUE" : "FALSE",
549 txlength);
550 #endif
551
552 #ifdef RAWNET_DEBUG_PKTDUMP
553 debug_output("Transmit frame: ", txframe, txlength);
554 #endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
555
556 RAWNET_ARCH_TRANSMIT(force, onecoll, inhibit_crc, tx_pad_dis, txlength,
557 txframe);
558 }
559
560
561 /**
562 * \brief Check if a frame was received
563 *
564 * This function checks if there was a frame received. If so, it returns 1,
565 * else 0.
566 *
567 * If there was no frame, none of the parameters is changed!
568 *
569 * If there was a frame, the following actions are done:
570 *
571 * - at maximum \a plen byte are transferred into the buffer given by \a pbuffer
572 * - \a plen gets the length of the received frame, EVEN if this is more
573 * than has been copied to \a pbuffer!
574 * - if the dest. address was accepted by the hash filter, \a phashed is set,
575 * else cleared.
576 * - if the dest. address was accepted by the hash filter, \a phash_index is
577 * set to the number of the rule leading to the acceptance
578 * - if the receive was ok (good CRC and valid length), \a *prx_ok is set, else
579 * cleared.
580 * - if the dest. address was accepted because it's exactly our MAC address
581 * (set by rawnet_arch_set_mac()), \a pcorrect_mac is set, else cleared.
582 * - if the dest. address was accepted since it was a broadcast address,
583 * \a pbroadcast is set, else cleared.
584 * - if the received frame had a crc error, \a pcrc_error is set, else cleared
585 *
586 * \param[out] buffer where to store a frame
587 * \param[in,out] plen IN: maximum length of frame to copy;
588 * OUT: length of received frame OUT
589 * can be bigger than IN if received frame was
590 * longer than supplied buffer
591 * \param[out] phashed set if the dest. address is accepted by the
592 * hash filter
593 * \param[out] phash_index hash table index if hashed == TRUE
594 * \param[out] prx_ok set if good CRC and valid length
595 * \param[out] pcorrect_mac set if dest. address is exactly our IA
596 * \param[out[ pbroadcast set if dest. address is a broadcast address
597 * \param[out] pcrc_error set if received frame had a CRC error
598 */
rawnet_arch_receive(uint8_t * pbuffer,int * plen,int * phashed,int * phash_index,int * prx_ok,int * pcorrect_mac,int * pbroadcast,int * pcrc_error)599 int rawnet_arch_receive(uint8_t *pbuffer, int *plen, int *phashed,
600 int *phash_index, int *prx_ok, int *pcorrect_mac, int *pbroadcast,
601 int *pcrc_error)
602 {
603 int len;
604
605 rawnet_pcap_internal_t internal = { *plen, pbuffer };
606
607 #ifdef RAWNET_DEBUG_ARCH
608 log_message(rawnet_arch_log,
609 "rawnet_arch_receive() called, with *plen=%u.",
610 *plen);
611 #endif
612
613 assert((*plen & 1) == 0);
614
615 len = rawnet_arch_receive_frame(&internal);
616
617 if (len != -1) {
618
619 #ifdef RAWNET_DEBUG_PKTDUMP
620 debug_output("Received frame: ", internal.buffer, internal.len);
621 #endif /* #ifdef RAWNET_DEBUG_PKTDUMP */
622
623 if (len & 1) {
624 ++len;
625 }
626
627 *plen = len;
628
629 /* we don't decide if this frame fits the needs;
630 * by setting all zero, we let tfe.c do the work
631 * for us
632 */
633 *phashed =
634 *phash_index =
635 *pbroadcast =
636 *pcorrect_mac =
637 *pcrc_error = 0;
638
639 /* this frame has been received correctly */
640 *prx_ok = 1;
641
642 return 1;
643 }
644
645 return 0;
646 }
647
648
649 /** \brief Find default device on which to capture
650 *
651 * \return name of standard interface
652 *
653 * \note pcap_lookupdev() has been deprecated, so the correct way to get
654 * the default device is to use the first entry returned by
655 * pcap_findalldevs().
656 * See http://www.tcpdump.org/manpages/pcap_lookupdev.3pcap.html
657 *
658 * \return default interface name or `NULL` when not found
659 *
660 * \note free the returned value with lib_free() if not `NULL`
661 */
rawnet_arch_get_standard_interface(void)662 char *rawnet_arch_get_standard_interface(void)
663 {
664 char *dev = NULL;
665 char errbuf[PCAP_ERRBUF_SIZE];
666 pcap_if_t *list;
667
668 if (pcap_findalldevs(&list, errbuf) == 0 && list != NULL) {
669 dev = lib_stralloc(list[0].name);
670 pcap_freealldevs(list);
671 #ifdef HAVE_TUNTAP
672 } else {
673 dev = lib_stralloc("tap0");
674 #endif
675 }
676 return dev;
677 }
678
679 #endif /* #ifdef HAVE_RAWNET */
680