链路层原始套接字
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/ethernet.h>
#define MTU 1500
int main()
{
/* 定义变量 */
int sockfd, len;
uint8_t buf[MTU]={};
uint16_t ether_type;
struct iphdr *iph; //IP包头
struct tcphdr *tcph;//TCP包头
struct ether_header *eth;
/* 创建一个链路层原始套接字 */
if( (sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) ) < 0){
perror("socket");
return 0;
}
printf("sockfd = %d\n", sockfd);
/* 接收(只接收TCP数据协议)并处理IP数据报 */
while(1)
{
/* 接收包含TCP协议的IP数据报 */
len = recvfrom(sockfd, buf, sizeof(buf),0,NULL,NULL);
eth = (struct ether_header *)buf;
ether_type = htons(eth->ether_type);
switch(ether_type){
case ETHERTYPE_IP:
printf("IP协议\n");
break;
case ETHERTYPE_ARP:
printf("ARP协议\n");
break;
case ETHERTYPE_LOOPBACK:
printf("loop back\n");
break;
default:
printf("其他协议 %x\n",eth->ether_type);
}
if(ether_type != ETHERTYPE_IP)
continue;
/* 打印源IP和目的IP */
iph = (struct iphdr *)(buf+14);
if(iph->protocol != IPPROTO_TCP)
continue;
printf("源IP:%s\n",inet_ntoa(*(struct in_addr *)&iph->saddr) );
printf("目的IP%s\n",inet_ntoa(*(struct in_addr *)&iph->daddr) );
/* 打印TCP包头的源端口号和目的端口号 */
tcph = (struct tcphdr *)(buf+14+iph->ihl*4);
printf("%hu--->", ntohs(tcph->source));
printf("%hu\n", ntohs(tcph->dest));
/* 打印TCP数据段的长度 */
printf("TCP首部长度:%d\n", tcph->doff*4);
}
//关闭套接字
close(sockfd);
return 0;
}
网络层原始套接字
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <sys/ioctl.h>
#define MTU 1500
int main()
{
/* 定义变量 */
int sockfd = -1, len, datalen, i;
uint8_t buf[MTU]={}, *data;
struct iphdr *iph; //IP包头
struct tcphdr *tcph;//TCP包头
struct winsize size;
/* 创建一个原始套接字 */
if( (sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP) ) < 0)
{
perror("socket");
return 0;
}
printf("sockfd = %d\n", sockfd);
/* 接收(只接收TCP数据协议)并处理IP数据报 */
while(1)
{
/* 接收包含TCP协议的IP数据报 */
len = recvfrom(sockfd, buf, sizeof(buf),0,NULL,NULL);
printf("IP数据报长度 = %d\n", len);
/* 打印源IP和目的IP */
iph = (struct iphdr *)buf;
printf("源IP:%s",inet_ntoa(*(struct in_addr *)&iph->saddr) );
printf("目的IP%s\n",inet_ntoa(*(struct in_addr *)&iph->daddr) );
/* 打印TCP包头的源端口号和目的端口号 */
tcph = (struct tcphdr *)(buf+iph->ihl*4);
printf("%hu--->", ntohs(tcph->source));
printf("%hu\n", ntohs(tcph->dest));
/* 打印TCP数据段的长度 */
printf("TCP首部长度:%d\n", tcph->doff*4);
if(iph->ihl*4+tcph->doff*4 < len) {
data = buf + iph->ihl*4 + tcph->doff*4;
datalen = len - iph->ihl*4 + tcph->doff*4;
ioctl(STDIN_FILENO,TIOCGWINSZ,&size); //terminal 结构体
for(i = 0; i < size.ws_col; i++) //显示一行 =
putchar('=');
putchar('\n');
printf("TCP数据字符:\n");
for(i = 0; i < size.ws_col; i++)
putchar('=');
putchar('\n');
for(i = 0; i < datalen-1; i++) {
printf("%c", data[i]);
}
for(i = 0; i < size.ws_col; i++)
putchar('=');
putchar('\n');
printf("TCP数据16进制:\n");
for(i = 0; i < size.ws_col; i++)
putchar('=');
putchar('\n');
for(i = 0; i < datalen-1; i++){
printf("%x ", data[i]);
}
putchar('\n');
for(i = 0; i < size.ws_col; i++)
putchar('=');
putchar('\n');
}
}
//关闭套接字
close(sockfd);
return 0;
}