간단한 패킷 분석기를 만들었다. 리눅스에서 작동하는 코드다.
// packetCapture.cpp
// g++ -o packetCapture.out packetCapture.cpp; sudo ./packetCapture.out
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <linux/if_packet.h>
using namespace std;
// The packet length
#define PCKT_LEN 8192
typedef struct {
unsigned short htype;
unsigned short ptype;
unsigned char hlen;
unsigned char plen;
unsigned short opcode;
unsigned char sender_mac[6];
unsigned char sender_ip[4];
unsigned char target_mac[6];
unsigned char target_ip[4];
}arp_packet;
void error(char* msg);
void arpReceived(arp_packet* recv_arp_pkt);
void ipReceived(struct iphdr* iphdr);
int main() {
int sock;
struct ifreq if_idx;
struct sockaddr_ll dest_addr;
struct ether_header ethhdr;
char buffer[1600];
if((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)))==-1)
error((char*)"socket");
strncpy(if_idx.ifr_name, "eno1", IFNAMSIZ);
if(ioctl(sock, SIOCGIFINDEX, &if_idx)<0)
error((char*)"ioctl");
struct ether_header* recv_ethhdr = (struct ether_header*)buffer;
arp_packet* recv_arp_pkt = (arp_packet*)(buffer+sizeof(struct ether_header));
struct iphdr* iphdr = (struct iphdr*)(buffer+sizeof(struct ether_header));
while (true) {
if(recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL)<0)
error((char*)"recvfrom");
switch(ntohs(recv_ethhdr->ether_type)) {
case ETH_P_ARP:
arpReceived(recv_arp_pkt);
break;
case ETH_P_IP:
ipReceived(iphdr);
break;
default:
cout << "unknown packet received" << endl;
}
}
return 0;
}
void arpReceived(arp_packet* recv_arp_pkt) {
switch(ntohs(recv_arp_pkt->opcode)) {
case 0x0001:
cout << "arp request capture" << endl;
break;
case 0x0002:
cout << "arp reply received" << endl;
}
}
void ipReceived(struct iphdr* iphdr) {
cout.width(3); cout << (iphdr->saddr & 0xff) << ".";
cout.width(3); cout << ((iphdr->saddr & 0xff00) >> 8) << ".";
cout.width(3); cout << ((iphdr->saddr & 0xff0000) >> 16) << ".";
cout.width(3); cout << ((iphdr->saddr & 0xff000000) >> 24) << " to ";
cout.width(3); cout << (iphdr->daddr & 0xff) << ".";
cout.width(3); cout << ((iphdr->daddr & 0xff00) >> 8) << ".";
cout.width(3); cout << ((iphdr->daddr & 0xff0000) >> 16) << ".";
cout.width(3); cout << ((iphdr->daddr & 0xff000000) >> 24) << " ";
switch(iphdr->protocol) {
case 0x06: {
struct tcphdr* tcphdr = (struct tcphdr*)((char*)iphdr + sizeof(struct iphdr));
cout << "TCP " << ntohs(tcphdr->source) << " -> " << ntohs(tcphdr->dest) <<endl;
}
break;
case 0x11: {
struct udphdr* udphdr = (struct udphdr*)((char*)iphdr + sizeof(struct iphdr));
cout << "UDP " << ntohs(udphdr->source) << " -> " << ntohs(udphdr->dest) << endl;
}
break;
case 0x01:
cout << "ICMP " << endl;
break;
case 0x02:
cout << "IGMP " << endl;
break;
default:
cout << "unknown IP protocol" << endl;
break;
}
}
void error(char* msg)
{
perror(msg);
exit(1);
}
'소켓프로그래밍' 카테고리의 다른 글
linux arp 요청 & 응답 받기 (1) | 2024.03.06 |
---|---|
리눅스 udp패킷 전송 (0) | 2024.02.03 |
java 간단한 web Server 한글전송 깨짐. (0) | 2020.09.25 |
chrome http web프로그래밍 에러 (failed) net::ERR_CONTENT_LENGTH_MISMATCH (0) | 2020.09.24 |
cpp 간단한 web서버 (0) | 2020.09.23 |