#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ETH_ALEN 6
#define ETH_P_GATE 0x9006
#define ETH_MAX_DATA_LEN 1488
#define ETH_HEAD_LEN 16
#define ETH_BODY_LEN 1496
#define ETH_LEN ETH_HEAD_LEN + ETH_BODY_LEN
struct EtherHead
{
unsigned char dest[ETH_ALEN]; /* destinat ion eth addr */
unsigned char source[ETH_ALEN]; /* source e ther addr */
unsigned int proto; /* packet type ID field */
};
struct EtherBody
{
size_t datalen;
char data[ETH_MAX_DATA_LEN];
};
int Eth_SetHead(const char *destmac, const char *srcmac, int proto, struct EtherHead **head)
{
char machex[6];
int c,i;
*head = (struct EtherHead *)malloc(sizeof(struct EtherHead));
if(!*head)
{
return -1;
}
memset(*head, 0, sizeof(struct EtherHead));
//填写帧头中的类型字段
(*head)->proto=htons(proto);
//填写帧头中的目的mac
for (i=0;i<6;i++)
{
sscanf(destmac+3*i,"%2x",&c);
machex[i]=(char)c;
}
memcpy((*head)->dest, machex, 6);
//填写帧头中的源mac
for (i=0;i<6;i++)
{
sscanf(srcmac+3*i,"%2x",&c);
machex[i]=(char)c;
}
memcpy((*head)->source, machex, 6);
return 0;
}
int Eth_CreatEth(void **eth, const char *data, size_t datalen, struct EtherHead *head)
{
//帧数据部分
struct EtherBody body;
memset(&body, 0, sizeof(body));
memcpy(body.data, data, datalen);
body.datalen = datalen;
//拼接帧(以太网中帧首部16字节,帧数据段最小46字节,FCS4字节,合计最小以太网帧长64字节)
*eth = malloc(ETH_LEN);
if(!*eth)
{
return -1;
}
memcpy(*eth, head, ETH_HEAD_LEN);
memcpy((*eth) + ETH_HEAD_LEN, &body, ETH_BODY_LEN);
return 0;
}
void Eth_Free(void **eth, struct EtherHead **head)
{
free(*eth);
*eth = NULL;
free(*head);
*head = NULL;
}
int main()
{
//创建原始套接字
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_GATE));
if (0 > sock)
{
printf("create_sock err %s", strerror(errno));
return -1;
}
//获取网卡信息
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
memcpy(ifr.ifr_name, "eno16777736", strlen("eno16777736") + 1);
ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
//填写发送信息
struct sockaddr_ll sk_ll;
sk_ll.sll_family = AF_PACKET;
//sk_ll.sll_protocol = htons(ETH_P_GATE);//指定帧协议类型
//sk_ll.sll_hatype = 1;
sk_ll.sll_halen = ETH_ALEN;
//sk_ll.sll_pkttype = PACKET_MULTICAST;//帧类型为链路层组播
sk_ll.sll_ifindex = ifr.ifr_ifindex;//指定从哪个网卡发送帧
//填写帧头
struct EtherHead *head = NULL;
Eth_SetHead("ff-ff-ff-ff-ff-ff", "00:0c:29:b5:15:a9", ETH_P_GATE, &head);
//组装帧
void *buf = NULL;
Eth_CreatEth(&buf, "nihao", 5, head);
//发出帧
while(1)
{
if(-1 == sendto(sock, buf, ETH_LEN, 0, (struct sockaddr *)&sk_ll, sizeof(sk_ll)))
{
printf("sendto err %s", strerror(errno));
exit(-1);
}
sleep(1);
}
//释放资源
Eth_Free(&buf, &head);
}