概述
对于两台建立通讯的主机,数据传输都是从本地主机的应用层的协议出发,经过从上至下的协议处理发送给另一台主机;另一台主机物理层接收到数据后,从下至上层层通过协议处理上传至应用层。
这个过程有点像栈的FILO,故把这些层级协议的组合叫做协议栈(也称为协议族,family)。
这里结合netmap实现一个简单的协议栈:
#include <stdio.h>
#include <sys/poll.h>
#include <arpa/inet.h>
#define NETMAP_WITH_LIBS
#include <net/netmap_user.h>
#pragma pack(1) //使结构体按照1字节对齐;
#define ETH_ADDR_LENGTH 6//地址长度
#define PROTO_IP 0x0800
#define PROTO_ARP 0x0806
#define PROTO_UDP 17
#define PROTO_TCP 6
#define PROTO_ICMP 1
/*arp的作用:
1、发送请求
2、收到了回复的arp响应之后,记录到arp表里面
*/
struct ethhdr { //以太网协议头
unsigned char h_dst[ETH_ADDR_LENGTH];//不对内部数据进行计算,用unsigned_char;目的地址
unsigned char h_src[ETH_ADDR_LENGTH];//源地址;
unsigned short h_proto;
};//14
struct iphdr{
unsigned char hdrlen:4,//注意这俩的顺序,version是高位(协议头是前面的是高位)
version:4;//方便将不同功能的位进行分配
unsigned char tos;
unsigned short totlen;//2byte
unsigned short id;//最多65535
unsigned short flag_offset;
unsigned char ttl;//time to live,没经过一个网关-1,为0丢弃,回复TTL不可达
unsigned char type;//协议的类型
unsigned short check;
unsigned int sip;//源ip
unsigned int dip;//目的ip
};//20
struct udphdr{
unsigned short sport;
unsigned short dport;
unsigned short length;
unsigned short check;//校验码
};//8
struct udppkt{
struct ethhdr eh;//14
struct iphdr ip;//20
struct udphdr udp;//8
unsigned char data[0];//1、提前分配好的,不会越界 2、不需要确定,因为本身是变化的-------这是柔性数组或者称0长数组
};//一字节对齐:42
struct arphdr{
unsigned short h_type;
unsigned short h_proto;
unsigned char h_addrlen;
unsigned char h_protolen;
unsigned short oper;
unsigned char smac[ETH_ADDR_LENGTH];//源mac地址
unsigned int sip;
unsigned char dmac[ETH_ADDR_LENGTH];
unsigned int dip;
};
struct arppkt{
struct ethhdr eh;
struct arphdr arp;
};
struct icmphdr{
unsigned char type;
unsigned char code;
unsigned short check;
unsigned int other;
};
struct icmppkt{
struct ethhdr eh;
struct iphdr ip;
struct icmphdr icmp;
unsigned char data[0];
};
struct tcphdr{
unsigned short sport;
unsigned short dport;
unsigned int seqnum;//开始是个随机值,可以从0开始,也可以从5开始,保证递增就行;越界之后从0开始//这个值是指的字节的数量
unsigned int acknum;
unsigned char hdrlen_resv;//高4位为TCP头部长度
unsigned char flag;
unsigned short window;//初始化为1460(以太网头+ip头对齐之后是40字节???)
unsigned short checksum;
unsigned short urgent_pointer;
unsigned int options[0];
};
struct tcppkt{
struct ethhdr eh;
struct iphdr ip;
struct tcphdr tcp;
unsigned char data[0];
};
typedef enum _tcp_status{
TCP_STATUS_CLOSED,
TCP_STATUS_LISTEN,
TCP_STATUS_SYN_REVD,
TCP_STATUS_SYN_SENT,
TCP_STATUS_ESTABLISHED,
TCP_STATUS_FIN_WAIT_1,
TCP_STATUS_FIN_WAIT_2,
TCP_STATUS_CLOSING,
TCP_STATUS_TIME_WAIT,
TCP_STATUS_CLOSE_WAIT,
TCP_STATUS_LAST_ACK
}cp;//控制状态机
#define TCP_CWR_FLAG 0x80
#define TCP_ECE_FLAG 0x40
#define TCP_URG_FLAG 0x20
#define TCP_ACK_FLAG 0x10
#define TCP_PSH_FLAG 0x08//通知应用程序赶紧接受
#define TCP_RST_FLAG 0x04//
#define TCP_SYN_FLAG 0x02
#define TCP_FIN_FLAG 0x01
struct ntcb{
unsigned int sip;
unsigned int dip;
unsigned short sport;
unsigned short dport;
//这里没有写具体协议
unsigned char smac[ETH_ADDR_LENGTH];
unsigned char dmac[ETH_ADDR_LENGTH];//一般放在arp表里面的
unsigned char status;
//没有定义sendbuffer;
};
int str2mac(unsigned char *mac,char *str) {
char *p = str;
unsigned char value = 0x0;
int i = 0;
while (*p != '