GNS3 Docker Images
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

152 lines
4.7 KiB

/*
* ethloop loops back all received frames.
*
* ethloop is the virtual equivalence of a RJ45 loopback plug.
* It's main objective is to see, how a network behaves with a
* loop in it's topology.
*
* This program is put into the public domain, use it as you like.
*/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <pcap.h>
pcap_t *pcap = NULL; /* pcap handle */
/* print pcap error/warning and exit on error */
void handle_pcap_err(char *prefix, int err) {
char *msg = NULL;
switch(err) {
case 0: /* no error */
break;
case PCAP_ERROR:
fprintf(stderr, "%s: error: %s\n", prefix, pcap_geterr(pcap));
break;
case PCAP_ERROR_BREAK:
msg = "pcap_loop terminated by pcap_break";
break;
case PCAP_ERROR_NOT_ACTIVATED:
msg = "pcap not activated";
break;
case PCAP_ERROR_ACTIVATED:
msg = "pcap is already activated";
break;
case PCAP_ERROR_NO_SUCH_DEVICE:
msg = "no such device";
break;
case PCAP_ERROR_RFMON_NOTSUP:
msg = "rfmon mode not supported";
break;
case PCAP_ERROR_NOT_RFMON:
msg = "rfmon mode not activated";
break;
case PCAP_ERROR_PERM_DENIED:
msg = "permission denied";
break;
case PCAP_ERROR_IFACE_NOT_UP:
msg = "interface isn't up";
break;
case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
msg = "device can't set the time stamp type";
break;
case PCAP_ERROR_PROMISC_PERM_DENIED:
msg = "no permission to capture in promiscuous mode";
break;
case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
msg = "requested time stamp precision not supported";
break;
case PCAP_WARNING:
fprintf(stderr, "%s: warning: %s\n", prefix, pcap_geterr(pcap));
break;
case PCAP_WARNING_PROMISC_NOTSUP:
msg = "warning: promiscuous mode not supported";
break;
case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
msg = "warning: requested time stamp type not supported";
break;
default:
if (err > 0)
fprintf(stderr, "%s: unknown warning, err = %d\n", prefix, err);
else
fprintf(stderr, "%s: unknown error, err = %d\n", prefix, err);
break;
}
if (msg != NULL)
fprintf(stderr, "%s: %s\n", prefix, msg);
if (err < 0)
exit(1);
}
/* break pcap loop by a signal */
void break_pcap_loop(int signum) {
if (pcap != NULL) pcap_breakloop(pcap);
}
/* print packet counter */
void print_counter(int counter) {
printf("\r%6d", counter); fflush(stdout);
}
/* callback on received packet */
void echo_packet(u_char *user, const struct pcap_pkthdr *pkthdr,
const u_char *packet) {
static int counter = 0;
int ret;
ret = pcap_inject(pcap, packet, pkthdr->len);
if (ret < 0) {
printf("\n");
handle_pcap_err("pcap_inject", ret);
}
print_counter(++counter);
}
int main(int argc, char *argv[]) {
char errbuf[PCAP_ERRBUF_SIZE];
sig_t old_sighup, old_sigint, old_sigquit, old_sigterm;
char *device;
int ret;
/* first (and only) argument is device name */
if (argc != 2 || argv[1][0] == '-') {
fprintf(stderr, "ethloop loops back all received frames.\n\n"
"Usage: ethloop <network device>\n");
exit(1);
}
device = argv[1];
/* open capture device */
if ((pcap = pcap_create(device, errbuf)) == NULL) {
fprintf(stderr, "pcap_create: can't open network device: %s\n", errbuf);
exit(1);
}
/* set capture options */
handle_pcap_err("pcap_set_snaplen", pcap_set_snaplen(pcap, 65535));
handle_pcap_err("pcap_set_promisc", pcap_set_promisc(pcap, 1));
/* activate capture */
handle_pcap_err("pcap_activate", pcap_activate(pcap));
handle_pcap_err("pcap_setdirection", pcap_setdirection(pcap, PCAP_D_IN));
/* receive packets until HUP, INT, QUIT or TERM signal */
old_sighup = signal(SIGHUP, break_pcap_loop);
old_sigint = signal(SIGINT, break_pcap_loop);
old_sigquit = signal(SIGQUIT, break_pcap_loop);
old_sigterm = signal(SIGTERM, break_pcap_loop);
print_counter(0);
ret = pcap_loop(pcap, -1, echo_packet, NULL);
printf("\n");
if (ret != PCAP_ERROR_BREAK)
handle_pcap_err("pcap_loop", ret);
signal(SIGHUP, old_sighup);
signal(SIGINT, old_sigint);
signal(SIGQUIT, old_sigquit);
signal(SIGTERM, old_sigterm);
pcap_close(pcap);
return 0;
}