拾起去年扔下的UNIX高级环境编程看了下网络编程章节,对着写了点,废话少说.
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#define iip2cip(...) inet_ntoa((struct in_addr){__VA_ARGS__})
#define BUFFER_MAX_SZ 2048
typedef struct mac_frm_hdr { //按照以太网帧格式定义,长度必须一致
unsigned char dest_addr[6];
unsigned char src_addr[6];
unsigned short type;
}__attribute__((packed)) MAC_FRM_HDR;//取消编译器自动优化对齐结构体,保证与帧中的结构一致.
typedef struct ip_hdr{ //只支持IPV4
unsigned char ver:4, len:4;
unsigned char tos;
unsigned short total_len;
unsigned short id;
unsigned short flags;
unsigned char ttl;
unsigned char protocol;
unsigned short chksum;
uint32_t src;
uint32_t dest;
}__attribute__((packed)) IP_HDR;
int main(int argc,char *argv[])
{
int sock_raw_fd = 0,rf_fd = 0,AND_LOGIC = 0xFF;
unsigned char buf[BUFFER_MAX_SZ] = {0};
if((sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0){
perror("create socket failed.\n");
return -1;
}
printf("sock: %d\n",sock_raw_fd);
MAC_FRM_HDR *mac_hdr;
IP_HDR *ip_hdr;
char *tmp1, *tmp2;
while(1)
{
rf_fd = recvfrom(sock_raw_fd,buf,BUFFER_MAX_SZ,0,NULL,NULL);
mac_hdr = (MAC_FRM_HDR *) buf;
ip_hdr = (IP_HDR *)(buf + sizeof(MAC_FRM_HDR));
tmp1 = mac_hdr->src_addr;
tmp2 = mac_hdr->dest_addr;
printf("MAC:%.2X:%.2X:%.2X:%.2X:%.2X:%.2X" " -> " "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X Protocol:",
tmp1[0]&AND_LOGIC, tmp1[1]&AND_LOGIC, tmp1[2]&AND_LOGIC,tmp1[3]&AND_LOGIC,
tmp1[4]&AND_LOGIC, tmp1[5]&AND_LOGIC,
tmp2[0]&AND_LOGIC, tmp2[1]&AND_LOGIC, tmp2[2]&AND_LOGIC,tmp2[3]&AND_LOGIC,
tmp2[4]&AND_LOGIC, tmp2[5]&AND_LOGIC);
switch (ip_hdr->protocol)
{
case IPPROTO_ICMP: printf("ICMP\n");break;
case IPPROTO_IGMP: printf("IGMP\n");break;
case IPPROTO_GRE: printf("GRE\n");break;
case IPPROTO_IPIP: printf("IPIP\n");break;
case IPPROTO_TCP:
case IPPROTO_UDP:
printf("%s ",ip_hdr->protocol == IPPROTO_TCP? "TCP":"UDP");
printf("IP: %s -> %s\n",iip2cip((in_addr_t)(ip_hdr->src)),iip2cip((in_addr_t)(ip_hdr->dest)));
//这儿可以放某些功能的函数,比如过滤某些关键的IP数据包.
break;
case IPPROTO_RAW: printf("RAW");break;
default:
printf("Other\n");
break;
}
}
return 0;
}
发现在Ubuntu下需要root权限才可运行,而CentOS下则可以直接运行.