Skip to content

Instantly share code, notes, and snippets.

@mmitou
Created November 9, 2014 17:38
Show Gist options
  • Select an option

  • Save mmitou/fddb12e671711acda376 to your computer and use it in GitHub Desktop.

Select an option

Save mmitou/fddb12e671711acda376 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
// #include <arpa/inet.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <net/ethernet.h>
#include <netpacket/packet.h>
#include <netinet/if_ether.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <inttypes.h>
int init_raw_socket(const char* const device_name,
const bool is_promiscuous_mode,
const bool is_ip_packet_only) {
const uint16_t protocol = is_ip_packet_only ? htons(ETH_P_IP) : htons(ETH_P_ALL);
// make raw socket
const int sockfd = socket(PF_PACKET, SOCK_RAW, protocol);
if(sockfd < 0) { goto FAIL_SOCKET; };
// get interface index
struct ifreq ifreq;
memset(&ifreq,0,sizeof(struct ifreq));
strncpy(ifreq.ifr_name, device_name, sizeof(ifreq.ifr_name) -1);
if(ioctl(sockfd, SIOCGIFINDEX, &ifreq) < 0) { goto FAIL_IOCTL; };
struct sockaddr_ll sa = {
.sll_family = PF_PACKET,
.sll_protocol = protocol,
.sll_ifindex = ifreq.ifr_ifindex
};
if(bind(sockfd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { goto FAIL_BIND; };
// add promisc flag
if(is_promiscuous_mode) {
// get interface flags
if(ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) { goto FAIL_IOCTL; };
ifreq.ifr_flags = ifreq.ifr_flags | IFF_PROMISC;
// set promisc flag
if(ioctl(sockfd, SIOCSIFFLAGS, &ifreq) < 0) { goto FAIL_IOCTL; };
}
return sockfd;
FAIL_BIND:
perror("bind");
close(sockfd);
return -1;
FAIL_IOCTL:
perror("ioctl");
close(sockfd);
return -1;
FAIL_SOCKET:
perror("socket");
return -1;
}
void print_ether_header(const struct ether_header* const p) {
const char buf[2] = {(((char*)&(p->ether_type)) [1]), (((char*)&(p->ether_type))[0])};
const short ether_type = *((short *)buf);
printf("dst: %02x:%02x:%02x:%02x:%02x:%02x\n",
p->ether_dhost[0],
p->ether_dhost[1],
p->ether_dhost[2],
p->ether_dhost[3],
p->ether_dhost[4],
p->ether_dhost[5]);
printf("src: %02x:%02x:%02x:%02x:%02x:%02x\n",
p->ether_shost[0],
p->ether_shost[1],
p->ether_shost[2],
p->ether_shost[3],
p->ether_shost[4],
p->ether_shost[5]);
printf("type: %04x\n", ether_type);
switch(ether_type) {
case ETHERTYPE_PUP : printf("ETHERTYPE_PUP\n"); break;
case ETHERTYPE_IP : printf("ETHERTYPE_IP\n"); break;
case ETHERTYPE_ARP : printf("ETHERTYPE_ARP\n"); break;
default: printf("UNKNOWN TYPE\n");
}
}
int main(int argc, char **argv) {
char buf[2000];
struct ether_header ether_header;
const int sockfd = init_raw_socket(argv[1], true, true);
while(sockfd >= 0) {
const ssize_t size = read(sockfd, buf, sizeof(buf));
if(size < 0) {
perror("read");
} else {
if(size >= (long)sizeof(struct ether_header)) {
memcpy(&ether_header, buf, sizeof(struct ether_header));
print_ether_header(&ether_header);
} else {
fprintf(stderr, "read size(%zd) < %ld\n", size, sizeof(struct ether_header));
}
}
}
return 0;
}
TARGET := ltest
SRCS := ltest.c
OBJS := $(SRCS:.c=.o)
CFLAGS := -Wall -pedantic -std=c11
CC := gcc
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $< -o $@
%.o: %.c
$(CC) $(CFLAGS) $< -c -o $@
.PHONY: clean
clean:
find ./ \( -name '*.o' -o -name $(TARGET) \) -exec rm {} /dev/null \; 2> /dev/null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment