qfedu-network-advanced-level/day7/fake_feiq.c

198 lines
6.4 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <stdio.h>
#include <libnet.h>
#include <iconv.h> // iconv 用于转换编码
// 将字符串转换为UTF-8编码
char *convertToUTF8(const char *str)
{
// 输入字符串的长度
size_t inlen = strlen(str);
// 输出缓冲区的长度假设为输入长度的3倍UTF-8编码最多占用3个字节
size_t outlen = inlen * 3;
// 创建转换句柄
iconv_t cd = iconv_open("UTF-8", "GB2312"); // 从 GB2312 转换为 UTF-8
// 分配输出缓冲区
char *outbuf = (char *)malloc(outlen);
if (outbuf == NULL)
{
perror("Memory allocation failed");
return NULL;
}
// 进行转换
char *inbuf = (char *)str;
char *outptr = outbuf;
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
{
perror("Conversion failed");
free(outbuf);
iconv_close(cd);
return NULL;
}
// 关闭转换句柄
iconv_close(cd);
// 添加字符串结束符
*outptr = '\0';
return outbuf;
}
// 将字符串转换为GB2312编码
char *convertToGB2312(const char *str)
{
// 输入字符串的长度
size_t inlen = strlen(str);
// 输出缓冲区的长度假设为输入长度的3倍UTF-8编码最多占用3个字节
size_t outlen = inlen * 3;
// 创建转换句柄
iconv_t cd = iconv_open("GB2312", "UTF-8"); // 从 UTF-8 转换为 GB2312
// 分配输出缓冲区
char *outbuf = (char *)malloc(outlen);
if (outbuf == NULL)
{
perror("Memory allocation failed");
return NULL;
}
// 进行转换
char *inbuf = (char *)str;
char *outptr = outbuf;
if (iconv(cd, &inbuf, &inlen, &outptr, &outlen) == (size_t)-1)
{
perror("Conversion failed");
free(outbuf);
iconv_close(cd);
return NULL;
}
// 关闭转换句柄
iconv_close(cd);
// 添加字符串结束符
*outptr = '\0';
return outbuf;
}
int main(int argc, char const *argv[])
{
if (argc < 2)
{
printf("usage: %s <device>\n", argv[0]);
return -1;
}
while (1)
{
// 1. 初始化libnet
char err_buf[LIBNET_ERRBUF_SIZE] = "";
libnet_t *net = libnet_init(LIBNET_RAW4, argv[1], err_buf);
if (net == NULL)
{
printf("libnet_init error: %s\n", err_buf);
return -2;
}
printf("libnet_init success\n");
// 2. 构建数据
// 2.1 UDP
u_char msg_data[64] = "";
u_char say_what[64] = "";
printf("请输入要发送的内容:");
// scanf("%s", say_what);
fgets(say_what, sizeof(say_what), stdin); // 比 scanf 的优点是可以输入空格
say_what[strlen(say_what) - 1] = '\0'; // 去掉最后的换行符
sprintf(msg_data, "1:%d:%s:%s:%d:%s", 123, convertToGB2312("发送者"), convertToGB2312("匿名PC"), 32, convertToGB2312(say_what));
int msg_data_len = strlen(msg_data) + strlen(msg_data) % 2; // 整数补齐偶数位strlen(msg_data)%2 : 偶数+0奇数+1
printf("msg_data_len = %d ---> %s\n", msg_data_len, convertToUTF8(msg_data));
// 2.1.2 构建UDP数据包
libnet_ptag_t udp_tag = 0;
udp_tag = libnet_build_udp(
2425, // 源端口
2425, // 目的端口
8 + msg_data_len, // UDP数据包长度
0, // 校验和0为自动计算
msg_data, // 数据
msg_data_len, // 数据长度
net, // libnet句柄
0 // 0 表示构造新的报文,>0表示在已有报文基础上追加
);
if (udp_tag != -1)
{
printf("udp tag: %d\n", udp_tag);
}
// 2.2 ip 报
libnet_ptag_t ip_tag = libnet_build_ipv4(
20 + 8 + msg_data_len, // IP数据包总长度
0, // tos
0, // id, 0表示自动计算
0, // 标志位
32, // TTL
17, // 上层协议号17表示UDP
0, // 校验和0表示自动计算
inet_addr("10.12.156.196"), // 源IP地址网络序
inet_addr("10.12.156.178"), // 目的IP地址网络序
NULL, // 负载数据,这里不需要
0, // 负载数据长度
net, // libnet句柄
0 // 协议标记0表示构造新的报文, >0表示在已有报文基础上追加
); // 构造IP数据包返回值是新生成的协议块标记
if (ip_tag != -1)
{
printf("ip tag: %d\n", ip_tag);
}
// 2.3 构建以太网数据包
char sender_mac[128] = "4c:e1:73:47:16:3a"; // 发送者原始 MAC
char recv_mac[128] = "00:d8:61:03:45:65"; // 接收者原始 MAC
unsigned char dst_mac[8] = {}; // 目的 MAC
unsigned char src_mac[8] = {}; // 发送者 MAC
sscanf(sender_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &src_mac[0], &src_mac[1], &src_mac[2], &src_mac[3], &src_mac[4], &src_mac[5]);
sscanf(recv_mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &dst_mac[0], &dst_mac[1], &dst_mac[2], &dst_mac[3], &dst_mac[4], &dst_mac[5]);
printf("src_mac: %s dst_mac: %s\n", src_mac, dst_mac);
libnet_ptag_t eth_tag = libnet_build_ethernet(
dst_mac, // 目的MAC地址
src_mac, // 源MAC地址
0x0800, // 上层协议类型0x0800表示IP
NULL, // 负载数据,这里不需要
0, // 负载数据长度
net, // libnet句柄
0 // 协议标记0表示构造新的报文, >0表示在已有报文基础上追加
);
if (eth_tag != -1)
{
printf("eth tag: %d\n", eth_tag);
}
// 3. 发送数据
int send_len = libnet_write(net);
if (send_len == -1)
{
printf("libnet_write error: %s\n", libnet_geterror(net));
}
else
{
printf("libnet_write success, send bytes: %d\n", send_len);
}
// 释放资源
libnet_destroy(net);
}
return 0;
}