I shot multi-episode video series on sample libpcap user-space C code, which you can refer (below). And long ago I shot multi-episode video series on sending custom packets via raw-sockets which you can refer (below). So here is my multi-episode video series where I demonstrate how you can port the same libpcap sample code, discussed in the earlier episode(s) to raw-socket. This code should further help you to design and architect your own user-space Network stack on top of this fundamental framework.
Refer my other video series on:
Linux (user-space) RAW Socket Programming – Generate Google’s QUIC Protocol UDP Packets ↗
Linux (user-space) RAW Socket Programming – Generate VOIP SIP UDP Packets ↗
Linux (user-space) RAW Socket Programming – Generate Layer-2 multicast STP Packets ↗
Linux (user-space) RAW Socket Programming – Generate Layer-3 IP multicast OSPF Packets ↗
Linux TUN/TAP virtual network interfaces ↗
libpcap Library | Linux User-space Network Stack Development ↗
Layer-2 (L2) Multicast Frame Deep Analysis ↗
Linux Kernel net_device data-structure ↗
Also refer:
Wiki Multicast Address ↗
tcpdump and libpcap project ↗
libpcap github ↗
Here is the source code discussed in this video episode
/* raw_socket_sniffer.c - The Linux Channel */
#include <pcap.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netpacket/packet.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <getopt.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <malloc.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#define PROMISCUOUS 1
#define NONPROMISCUOUS 0
typedef unsigned char BYTE; /* 8-bit */
enum _Boolean_ { FALSE=0, TRUE=1};
int sock_fd=0;
#define MAX_PKT_BUF 2000
unsigned char pkt_buf[MAX_PKT_BUF];
unsigned int pkt_buf_len=0;
void parse_pkt(unsigned char *buf, unsigned int buf_len)
{
struct ether_header *ep;
struct ip *iph;
unsigned short ether_type;
int chcnt = 0;
int len = buf_len;
int i;
for(i=0;i<buf_len;i++)
{
printf("%02x ", buf[i]);
}
printf("\n");
printf("dest mac: %02x %02x %02x %02x %02x %02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
printf("src mac: %02x %02x %02x %02x %02x %02x \n", buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
printf("type: %02x %02x \n", buf[12], buf[13]);
printf("src ip: %d.%d.%d.%d \n", buf[26], buf[27], buf[28], buf[29]);
printf("dst ip: %d.%d.%d.%d \n", buf[30], buf[31], buf[32], buf[33]);
printf("protocol: %d \n", buf[23]);
// Get Ethernet header.
ep = (struct ether_header *)buf;
// Get upper protocol type.
ether_type = ntohs(ep->ether_type);
if (ether_type == ETHERTYPE_IP) {
printf("ETHER Source Address = ");
for (i=0; i<ETH_ALEN; ++i)
printf("%.2X ", ep->ether_shost[i]);
printf("\n");
printf("ETHER Dest Address = ");
for (i=0; i<ETH_ALEN; ++i)
printf("%.2X ", ep->ether_dhost[i]);
printf("\n");
// Move packet pointer for upper protocol header.
//packet += sizeof(struct ether_header);
iph = (struct ip *)(buf+sizeof(struct ether_header));
printf("IP Ver = %d\n", iph->ip_v);
printf("IP Header len = %d\n", iph->ip_hl<<2);
printf("IP Source Address = %s\n", inet_ntoa(iph->ip_src));
printf("IP Dest Address = %s\n", inet_ntoa(iph->ip_dst));
printf("IP Packet size = %d\n", len-16);
}
printf("-----------------------------------\n\n");
}
int create_socket(char *device)
{ int sock_fd;
struct ifreq ifr;
struct sockaddr_ll sll;
memset(&ifr, 0, sizeof(ifr));
memset(&sll, 0, sizeof(sll));
sock_fd = socket (PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if(sock_fd == 0) { printf("ERR: socket creation for device: %s\n", device); return FALSE; }
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if(ioctl(sock_fd, SIOCGIFINDEX, &ifr) == -1) { printf(" ERR: ioctl failed for device: %s\n", device); return FALSE; }
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_protocol = htons(ETH_P_ALL);
if(bind(sock_fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { printf("ERR: bind failed for device: %s\n", device); return FALSE; }
return sock_fd;
}
int main(int argc, char **argv)
{
sock_fd = create_socket("wlp1s0");
if( !(sock_fd) ) { printf("no sock_fd found\n"); return 0; }
while(1)
{ pkt_buf_len=0;
pkt_buf_len = read(sock_fd, pkt_buf, MAX_PKT_BUF);
if(pkt_buf_len>0) { parse_pkt(pkt_buf, pkt_buf_len); }
}
return 0;
}