I'm currently working on a packet sniffer in C using the pcap library, and I'm running into an issue. My program is supposed to capture live network packets and process them, displaying some basic information such as timestamp, captured length, and printable text data. However, I'm encountering some problems. What My Code Does:
It takes a network interface as a command-line argument.
It retrieves a list of available devices using pcap_findalldevs(), then checks if the provided device name exists.
If the device is found, it opens a live capture session with pcap_open_live().
It sets up a filter (though for now, I’ve left it empty to capture all packets).
It enters pcap_loop() to continuously capture packets and process them in the packet_handler() function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <pcap.h>
#define STARTING_INDEX 0
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata);
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "argc must be 2 or more (in later versions)\n");
return 1;
}
char ERRBUF[PCAP_ERRBUF_SIZE];
memset(ERRBUF, 0, sizeof(ERRBUF));
pcap_if_t* devices;
if (pcap_findalldevs(&devices, ERRBUF) == -1) {
fprintf(stderr, "Failed to look up devices.\n");
return 1;
}
char device[BUFSIZ];
while (devices->next != NULL) {
if (strcmp(argv[1], devices->name) == 0) {
strcpy(device, devices->name);
break;
}
devices = devices->next;
}
struct bpf_program fp;
char filter_exp[] = "";
bpf_u_int32 net;
bpf_u_int32 mask;
if (pcap_lookupnet(device, &net, &mask, ERRBUF) == -1) {
fprintf(stderr, "Failed to get netmask of device.\n");
net = 0;
}
pcap_t* handle;
handle = pcap_open_live(device, BUFSIZ, 1, 1000, ERRBUF);
if (handle == NULL) {
fprintf(stderr, "Failed to start a sniffing session on device: %s due to error: %s.\n", device, ERRBUF);
return 1;
}
int datalink_type = pcap_datalink(handle);
printf("%i\n", datalink_type);
if (pcap_compile(handle, &fp, filter_exp, 1, net) == -1) {
fprintf(stderr, "Failed to compile filter expression.\n");
return 1;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Failed to set up a filter.\n");
return 1;
}
struct pcap_pkthdr header;
if (pcap_loop(handle, 0, packet_handler, NULL) == -1) {
fprintf(stderr, "Failed to start a packet_capturing session using loop.\n");
return 1;
}
pcap_close(handle);
}
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata) {
fprintf(stdout, "timestamp: %s seconds\n", ctime(&header->ts.tv_sec));
fprintf(stdout, "caplen: %i\n", header->caplen);
fprintf(stdout, "len: %i\n", header->len);
if (header->caplen == 0) {
return;
}
char* buffer = malloc(sizeof(u_char) * header->caplen);
if (buffer == NULL) {
fprintf(stderr, "Failed to allocate enough memory.\n");
return;
}
memset(buffer, 0, sizeof(u_char) * header->caplen);
int BUFFER_LEN = STARTING_INDEX;
for (int i = STARTING_INDEX; i < header->caplen; i++) {
if (BUFFER_LEN < header->caplen)
if (isprint(rawdata[i])) {
buffer[BUFFER_LEN] = (char)(rawdata[i]);
BUFFER_LEN++;
}
}
buffer[BUFFER_LEN] = '\0';
fprintf(stdout, "text data: %s\n", buffer);
free(buffer);
}
This issue is that when I run using sudo ./[PROGRAM_NAME] [DEVICE_NAME]
, nothing's getting printed to the terminal (its empty).
I'm on a Mac if that's useful to know.
I'm currently working on a packet sniffer in C using the pcap library, and I'm running into an issue. My program is supposed to capture live network packets and process them, displaying some basic information such as timestamp, captured length, and printable text data. However, I'm encountering some problems. What My Code Does:
It takes a network interface as a command-line argument.
It retrieves a list of available devices using pcap_findalldevs(), then checks if the provided device name exists.
If the device is found, it opens a live capture session with pcap_open_live().
It sets up a filter (though for now, I’ve left it empty to capture all packets).
It enters pcap_loop() to continuously capture packets and process them in the packet_handler() function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <pcap.h>
#define STARTING_INDEX 0
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata);
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "argc must be 2 or more (in later versions)\n");
return 1;
}
char ERRBUF[PCAP_ERRBUF_SIZE];
memset(ERRBUF, 0, sizeof(ERRBUF));
pcap_if_t* devices;
if (pcap_findalldevs(&devices, ERRBUF) == -1) {
fprintf(stderr, "Failed to look up devices.\n");
return 1;
}
char device[BUFSIZ];
while (devices->next != NULL) {
if (strcmp(argv[1], devices->name) == 0) {
strcpy(device, devices->name);
break;
}
devices = devices->next;
}
struct bpf_program fp;
char filter_exp[] = "";
bpf_u_int32 net;
bpf_u_int32 mask;
if (pcap_lookupnet(device, &net, &mask, ERRBUF) == -1) {
fprintf(stderr, "Failed to get netmask of device.\n");
net = 0;
}
pcap_t* handle;
handle = pcap_open_live(device, BUFSIZ, 1, 1000, ERRBUF);
if (handle == NULL) {
fprintf(stderr, "Failed to start a sniffing session on device: %s due to error: %s.\n", device, ERRBUF);
return 1;
}
int datalink_type = pcap_datalink(handle);
printf("%i\n", datalink_type);
if (pcap_compile(handle, &fp, filter_exp, 1, net) == -1) {
fprintf(stderr, "Failed to compile filter expression.\n");
return 1;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Failed to set up a filter.\n");
return 1;
}
struct pcap_pkthdr header;
if (pcap_loop(handle, 0, packet_handler, NULL) == -1) {
fprintf(stderr, "Failed to start a packet_capturing session using loop.\n");
return 1;
}
pcap_close(handle);
}
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata) {
fprintf(stdout, "timestamp: %s seconds\n", ctime(&header->ts.tv_sec));
fprintf(stdout, "caplen: %i\n", header->caplen);
fprintf(stdout, "len: %i\n", header->len);
if (header->caplen == 0) {
return;
}
char* buffer = malloc(sizeof(u_char) * header->caplen);
if (buffer == NULL) {
fprintf(stderr, "Failed to allocate enough memory.\n");
return;
}
memset(buffer, 0, sizeof(u_char) * header->caplen);
int BUFFER_LEN = STARTING_INDEX;
for (int i = STARTING_INDEX; i < header->caplen; i++) {
if (BUFFER_LEN < header->caplen)
if (isprint(rawdata[i])) {
buffer[BUFFER_LEN] = (char)(rawdata[i]);
BUFFER_LEN++;
}
}
buffer[BUFFER_LEN] = '\0';
fprintf(stdout, "text data: %s\n", buffer);
free(buffer);
}
This issue is that when I run using sudo ./[PROGRAM_NAME] [DEVICE_NAME]
, nothing's getting printed to the terminal (its empty).
I'm on a Mac if that's useful to know.
Share Improve this question edited Mar 27 at 5:47 C Enjoyer asked Mar 27 at 5:20 C EnjoyerC Enjoyer 112 bronze badges 1- 1 Nothing gets printed? – robertklep Commented Mar 27 at 5:34
1 Answer
Reset to default 1macOS restricts direct access to network interfaces for security reasons. Packet sniffing on interfaces like en0 (Wi-Fi) often requires additional permissions. Try running your program on lo0 (loopback interface) instead of en0. To list available interfaces, run:
ifconfig
then test:
sudo ./[PROGRAM_NAME] lo0
Try this updated code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/ip_icmp.h>
#include <pcap.h>
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata);
int main(int argc, char** argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
return 1;
}
char ERRBUF[PCAP_ERRBUF_SIZE] = {0};
pcap_if_t* devices, *dev;
if (pcap_findalldevs(&devices, ERRBUF) == -1) {
fprintf(stderr, "Failed to look up devices: %s\n", ERRBUF);
return 1;
}
char device[BUFSIZ] = {0};
for (dev = devices; dev != NULL; dev = dev->next) {
if (strcmp(argv[1], dev->name) == 0) {
strcpy(device, dev->name);
break;
}
}
if (strlen(device) == 0) {
fprintf(stderr, "Device not found: %s\n", argv[1]);
pcap_freealldevs(devices);
return 1;
}
pcap_freealldevs(devices);
bpf_u_int32 net, mask;
if (pcap_lookupnet(device, &net, &mask, ERRBUF) == -1) {
fprintf(stderr, "Failed to get netmask of device.\n");
net = 0;
mask = 0;
}
pcap_t* handle = pcap_open_live(device, BUFSIZ, 1, 1000, ERRBUF);
if (handle == NULL) {
fprintf(stderr, "Failed to start a sniffing session on %s: %s\n", device, ERRBUF);
return 1;
}
pcap_set_immediate_mode(handle, 1);
struct bpf_program fp;
char filter_exp[] = "tcp or udp or icmp";
if (pcap_compile(handle, &fp, filter_exp, 1, net) == -1) {
fprintf(stderr, "Failed to compile filter expression.\n");
pcap_close(handle);
return 1;
}
if (pcap_setfilter(handle, &fp) == -1) {
fprintf(stderr, "Failed to set up filter.\n");
pcap_close(handle);
return 1;
}
printf("Sniffing on interface: %s\n", device);
if (pcap_loop(handle, 0, packet_handler, NULL) == -1) {
fprintf(stderr, "Failed to start packet capture.\n");
pcap_close(handle);
return 1;
}
pcap_close(handle);
return 0;
}
void packet_handler(u_char* args, const struct pcap_pkthdr* header, const u_char* rawdata) {
printf("\nTimestamp: %s", ctime(&header->ts.tv_sec));
printf("Captured Length: %u bytes\n", header->caplen);
printf("Packet Length: %u bytes\n", header->len);
printf("Text Data: ");
for (int i = 0; i < header->caplen; i++) {
if (isprint(rawdata[i])) {
putchar(rawdata[i]);
} else {
putchar('.');
}
}
putchar('\n');
}