/*
*
* the tcp client cases
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <netinet/in.h>
#include <net/if.h>
#include <net/ethernet.h>
#include <netinet/if_ether.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netpacket/packet.h>
#define SRC_MAC "11:00:00:11:00:11"
#define DST_MAC "11:00:00:11:00:11"
#define IFACE "eth0"
#define BUFFER_SIZE 2048
// 定义长选项
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"src", required_argument, 0, 's'},
{"dec", required_argument, 0, 'd'},
{"if", required_argument, 0, 'i'},
{0, 0, 0, 0}
};
typedef struct st_user_param {
char src_mac[20];
char des_mac[20];
char net_if[20];
} user_param;
int param_parse(user_param *param, int argc, char * argv[])
{
int opt;
while ((opt = getopt_long(argc, argv, "hs:d:i:", long_options, NULL)) != -1) {
switch (opt) {
case 's':
memset(param->src_mac, 0x00, sizeof(param->src_mac));
strncpy(param->src_mac, optarg, sizeof(param->src_mac));
printf("src_mac : %s\n", param->src_mac);
break;
case 'd':
memset(param->des_mac, 0x00, sizeof(param->des_mac));
strncpy(param->des_mac, optarg, sizeof(param->des_mac));
printf("des_mac : %s\n", param->des_mac);
break;
case 'i':
memset(param->net_if, 0x00, sizeof(param->net_if));
strncpy(param->net_if, optarg, sizeof(param->net_if));
printf("net interface : %s\n", param->net_if);
break;
default:
exit(0);
}
}
}
// 将MAC地址字符串转换为二进制格式
void mac_str_to_bin(char *mac_str, unsigned char *mac_bin) {
int a, b, c, d, e, f;
sscanf(mac_str, "%x:%x:%x:%x:%x:%x", &a, &b, &c, &d, &e, &f);
mac_bin[0] = a;
mac_bin[1] = b;
mac_bin[2] = c;
mac_bin[3] = d;
mac_bin[4] = e;
mac_bin[5] = f;
}
int main(int argc, char *argv[]) {
int sockfd;
unsigned char buffer[BUFFER_SIZE];
unsigned char src_mac[6], dst_mac[6];
struct sockaddr_ll sll;
struct ifreq ifr;
user_param params = {0};
param_parse(¶ms, argc, argv);
// 转换MAC地址
if (params.src_mac[0]){
mac_str_to_bin(params.src_mac, src_mac);
} else {
mac_str_to_bin(SRC_MAC, src_mac);
}
if (params.des_mac[0]){
mac_str_to_bin(params.des_mac, dst_mac);
} else {
mac_str_to_bin(DST_MAC, dst_mac);
}
// 创建原始套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 获取接口索引
memset(&ifr, 0, sizeof(ifr));
if (params.net_if[0]){
strncpy(ifr.ifr_name, params.net_if, IFNAMSIZ);
} else {
strncpy(ifr.ifr_name, IFACE, IFNAMSIZ);
}
if (ioctl(sockfd, SIOCGIFINDEX, &ifr) < 0) {
perror("ioctl");
close(sockfd);
exit(EXIT_FAILURE);
}
// 准备发送数据
unsigned char data_to_send[] = "This is a test message to verify MAC layer data consistency.";
unsigned char packet[BUFFER_SIZE];
memset(packet, 0, BUFFER_SIZE);
// 构造以太网帧
memcpy(packet, dst_mac, 6);
memcpy(packet + 6, src_mac, 6);
packet[12] = 0x08; // Type: IP
packet[13] = 0x00;
memcpy(packet + 14, data_to_send, strlen((char *)data_to_send));
// 设置发送地址
memset(&sll, 0, sizeof(sll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifr.ifr_ifindex;
sll.sll_halen = ETH_ALEN;
memcpy(sll.sll_addr, dst_mac, ETH_ALEN);
// 发送数据包
if (sendto(sockfd, packet, 14 + strlen((char *)data_to_send), 0, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
perror("sendto");
close(sockfd);
exit(EXIT_FAILURE);
}
printf("Packet sent successfully.\n");
// 接收数据包
int packet_size;
while ((packet_size = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, NULL, NULL)) < 0) {
perror("recvfrom");
close(sockfd);
exit(EXIT_FAILURE);
}
// 解析接收到的数据包
if (packet_size >= 14) {
unsigned char *received_data = buffer + 14;
printf("Received data: %s\n", received_data);
if (strcmp((char *)received_data, (char *)data_to_send) == 0) {
printf("Data consistency verified successfully!\n");
} else {
printf("Data inconsistency detected!\n");
}
}
close(sockfd);
return 0;
}
case 2
/*
*
* the tcp client cases
*/
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <pcap.h>
#define PORT 8080
#define SERVER_IP "127.0.0.1"
#define BUFFER_SIZE 1024
// 定义长选项
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"ip", required_argument, 0, 'a'},
{"port", required_argument, 0, 'p'},
{"data", required_argument, 0, 'd'},
{"leng", required_argument, 0, 'l'},
{"vlan", required_argument, 0, 'v'},
{"PRIO", required_argument, 0, 'P'},
{0, 0, 0, 0}
};
int main(int argc, char * argv[]) {
int sockfd;
struct sockaddr_in servaddr;
struct ifreq ifr;
int tos_value = 0x10; // 例如,设置TOS为0x10(十进制16),这对应于IP_PRECEDENCE_INTERNETCONTROL(网络控制)
char*vlan_name = NULL;
unsigned char tbuffer[BUFFER_SIZE] = {0};
unsigned char rbuffer[BUFFER_SIZE] = {0};
int opt;
char *ip = SERVER_IP;
uint16_t port = PORT;
int data = 0x5A;
int data_len = 8;
char *pdata;
// 使用getopt_long函数解析命令行选项
while ((opt = getopt_long(argc, argv, "ha:p:d:l:v:P:", long_options, NULL)) != -1) {
switch (opt) {
case 'a':
ip = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 'd':
data = strtoul(optarg, &pdata ,16);
break;
case 'l':
data_len = atoi(optarg);
if ((data_len > BUFFER_SIZE) || (data_len < 1)){
printf("Data leng = %d, out of range [1,%d]\n", data_len, BUFFER_SIZE);
exit(0);
}
break;
case 'v':
vlan_name = optarg;
break;
case 'P':
tos_value = atoi(optarg);
break;
case '?':
case 'h':
default:
printf("Usage: %s [options]\n", argv[0]);
printf(" -h, --help Display this help message\n");
printf(" -a, --IP IP Adress\n");
printf(" -p, --port port number\n");
printf(" -d, --data data (Hex)\n");
printf(" -v, --vlan vlan name\n");
printf(" -P, --PRIO priority\n");
exit(0);
}
}
printf("udp client :\n");
printf("ip = %s, port = %d\n", ip, port);
printf("data = 0x%X, data length = %d\n", data, data_len);
// 创建套接字
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
} else {
printf("\n Socket OK, return %d\n", sockfd);
}
// 设置要绑定的网络接口名称
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, vlan_name, IFNAMSIZ);
// 将套接字绑定到指定的网络接口
if (setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(ifr)) < 0) {
perror("setsockopt SO_BINDTODEVICE error");
close(sockfd);
return 1;
}
// 设置IP_TOS选项
if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, &tos_value, sizeof(tos_value)) < 0) {
perror("setsockopt(IP_TOS)");
close(sockfd);
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
// 填充服务器信息
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(port);
servaddr.sin_addr.s_addr = inet_addr(ip);
memset(tbuffer, data, data_len);
data_len = sendto(sockfd, (const char *)tbuffer, data_len, MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("udp client sent %d Byte\n", data_len);
unsigned int len;
len = sizeof(servaddr);
data_len = recvfrom(sockfd, (char *)rbuffer, BUFFER_SIZE, MSG_WAITALL, (struct sockaddr *)&servaddr, &len);
printf("udp client recv %d Byte: \n", data_len);
for(int i = 0; i < data_len; ){
printf("%X ", rbuffer[i++]);
if((0 == (i & 0x1F)) || (data_len == i)){
printf("\n");
}
}
pcap_sendpacket();
close(sockfd);
return 0;
}
#endif
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <getopt.h>
#include <net/if.h>
#define BUF_SIZE 4096
#define VLAN_ID 100
#define VLAN_PCP 3 // Priority Code Point (0-7)
struct vlanhdr {
unsigned short h_vlan_TCI; /* destination eth addr */
unsigned short h_vlan_Frame_Type; /* packet type ID field */
} __attribute__((packed));
// 定义长选项
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"data", required_argument, 0, 'd'},
{"name", required_argument, 0, 'n'},
{"PRIO", required_argument, 0, 'p'},
{0, 0, 0, 0}
};
int main(int argc, char * argv[]) {
int sock;
struct sockaddr_ll sa;
struct ifreq ifr;
char buf[BUF_SIZE];
struct ethhdr *eth = (struct ethhdr *)buf;
struct vlanhdr *vlan = (struct vlanhdr *)(buf + sizeof(struct ethhdr));
char *data = buf + sizeof(struct ethhdr) + sizeof(struct vlanhdr);
int opt;
unsigned char data_value = 0x5A;
char *eth_name = "eth0";
char priority = 0;
char *pdata = NULL;
// 使用getopt_long函数解析命令行选项
while ((opt = getopt_long(argc, argv, "hd:n:p:", long_options, NULL)) != -1) {
switch (opt) {
case 'd':
data_value = strtoul(optarg, &pdata ,16);
break;
case 'n':
eth_name = optarg;
break;
case 'p':
priority = atoi(optarg);
break;
case '?':
case 'h':
default:
printf("Usage: %s [options]\n", argv[0]);
printf(" -h, --help Display this help message\n");
printf(" -d, --data data (Hex)\n");
printf(" -n, --name eth name\n");
printf(" -p, --PRIO priority\n");
exit(0);
}
}
printf("eth name : %s\n", eth_name);
printf("data : 0x%X\n", data_value);
printf("priority : %d\n", priority);
// 创建 PF_PACKET 套接字
if ((sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
perror("socket");
exit(EXIT_FAILURE);
}
// 获取网络接口索引
strncpy(ifr.ifr_name, eth_name, IFNAMSIZ-1); // 替换为您的网络接口名
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
perror("ioctl SIOCGIFINDEX");
close(sock);
exit(EXIT_FAILURE);
}
// 设置 sockaddr_ll 结构
memset(&sa, 0, sizeof(sa));
sa.sll_ifindex = ifr.ifr_ifindex;
sa.sll_halen = ETH_ALEN;
// 设置目的 MAC 地址(这里使用广播地址作为示例)
memset(sa.sll_addr, 0xff, ETH_ALEN);
// 构建以太网帧头
memcpy(eth->h_source, ifr.ifr_hwaddr.sa_data, ETH_ALEN); // 源 MAC 地址
eth->h_proto = htons(ETH_P_8021Q); // 以太网类型:VLAN 标签
// 构建 VLAN 标签头
vlan->h_vlan_TCI = htons((priority << 13) | (VLAN_ID & 0xFFF)); // TCI 字段:PCP 和 VID
vlan->h_vlan_Frame_Type = eth->h_proto; // 在这里应该是原始以太网类型,但因为我们是在模拟,所以复用
// 注意:在实际应用中,您应该设置正确的原始以太网类型(如 IP、ARP 等)在 vlan->h_vlan_Frame_Type 中
// 并且确保在数据部分构建相应的协议头
// 在这里,我们只是填充一些示例数据
memset(data, data_value, BUF_SIZE - sizeof(struct ethhdr) - sizeof(struct vlanhdr));
// 发送数据包
if (sendto(sock, buf, sizeof(struct ethhdr) + sizeof(struct vlanhdr) + (BUF_SIZE - sizeof(struct ethhdr) - sizeof(struct vlanhdr)), 0,
(struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("sendto");
close(sock);
exit(EXIT_FAILURE);
}
printf("Packet sent successfully!\n");
close(sock);
return 0;
}
#endif
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <netinet/ip.h>
#include <errno.h>
#include <net/ethernet.h>
// 自定义的以太网头部结构体(简化版)
struct ethhdr_custom {
unsigned char h_dest[ETH_ALEN];
unsigned char h_source[ETH_ALEN];
unsigned short h_proto;
};
int main() {
int sockfd;
struct sockaddr_ll sa_ll;
char buffer[ETH_FRAME_LEN]; // 通常以太网帧的最大长度为1518字节
struct ethhdr_custom *eth_header = (struct ethhdr_custom *)buffer;
struct iphdr *ip_header = (struct iphdr *)(buffer + sizeof(struct ethhdr_custom));
struct sockaddr_in server_addr; // 尽管我们不会使用它,但保留以供参考
// 创建PF_PACKET套接字
if ((sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP))) < 0) {
perror("socket() error");
exit(EXIT_FAILURE);
}
// 设置目标MAC地址(这里使用广播地址作为示例)
memset(eth_header->h_dest, 0xff, ETH_ALEN);
// 设置源MAC地址(这里需要替换为实际网卡的MAC地址)
//if (if_gethwaddr(sockfd, "eth0", eth_header->h_source) == -1) {
// perror("if_gethwaddr() error");
// close(sockfd);
// exit(EXIT_FAILURE);
//}
eth_header->h_source[0] = 0x02;
eth_header->h_source[1] = 0x00;
eth_header->h_source[2] = 0x00;
eth_header->h_source[3] = 0x0a;
eth_header->h_source[4] = 0x00;
eth_header->h_source[5] = 0x11;
eth_header->h_proto = htons(ETH_P_IP); // 设置协议类型为IP
// 填充IP头部
ip_header->ihl = sizeof(struct iphdr) / 4;
ip_header->version = 4;
ip_header->tot_len = htons(sizeof(struct iphdr)); // 这里只包含IP头部,没有数据部分
ip_header->id = htons(54321); // 任意ID
ip_header->frag_off = 0;
ip_header->ttl = 64;
ip_header->protocol = IPPROTO_TCP; // 假设是TCP协议(尽管没有填充TCP头部)
ip_header->check = 0; // 稍后计算校验和,但在这个例子中我们省略了它
ip_header->saddr = inet_addr("192.168.1.100"); // 源IP地址
ip_header->daddr = inet_addr("192.168.1.200"); // 目标IP地址
// 注意:在这个例子中,我们没有填充任何TCP头部或数据,只是构造了一个空的IP数据包。
// 在实际应用中,你需要根据需要在IP数据包后面添加TCP头部和数据。
// 设置套接字地址结构
memset(&sa_ll, 0, sizeof(sa_ll));
sa_ll.sll_ifindex = if_nametoindex("eth0.30"); // 替换为实际的网络接口名
sa_ll.sll_halen = ETH_ALEN;
memcpy(sa_ll.sll_addr, eth_header->h_source, ETH_ALEN); // 设置源MAC地址(虽然这在这里是多余的,因为我们已经设置了)
// 发送数据包
if (sendto(sockfd, buffer, sizeof(struct ethhdr_custom) + sizeof(struct iphdr), 0, (struct sockaddr *)&sa_ll, sizeof(sa_ll)) < 0) {
perror("sendto() error");
close(sockfd);
exit(EXIT_FAILURE);
}
// 关闭套接字
close(sockfd);
return 0;
}
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <net/if.h>
#include <linux/sockios.h>
#define BUF_SIZE 1518 // 以太网帧最大长度
#define VLAN_ID 10 // VLAN ID 示例值
int main() {
int sockfd;
struct sockaddr_ll sa;
char buf[BUF_SIZE];
struct ether_header *eh;
struct vlan_header {
__be16 h_vlan_TCI; // VLAN信息
__be16 h_vlan_proto; // 总是0x8100
} *vh;
struct iphdr *ip;
char src_mac[] = {0x02, 0x00, 0x00, 0x0a, 0x00, 0x11}; // 源MAC地址示例
char dst_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 目的MAC地址示例(广播)
char src_ip[] = "192.168.30.17"; // 源IP地址示例
char dst_ip[] = "192.168.30.15"; // 目的IP地址示例
int data_leng = 0;
// 创建PF_PACKET套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("socket");
exit(1);
}
// 设置套接字选项以绑定到特定接口(这里假设接口名为"eth0")
struct ifreq ifr;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
if (ioctl(sockfd, (int)SIOCGIFINDEX, &ifr) < 0) {
perror("ioctl - SIOCGIFINDEX");
close(sockfd);
exit(1);
}
sa.sll_ifindex = ifr.ifr_ifindex;
sa.sll_halen = ETH_ALEN;
memcpy(sa.sll_addr, dst_mac, ETH_ALEN);
// 构造以太网帧头部
eh = (struct ether_header *)buf;
memcpy(eh->ether_shost, src_mac, ETH_ALEN);
memcpy(eh->ether_dhost, dst_mac, ETH_ALEN);
eh->ether_type = htons(ETH_P_8021Q); // 设置类型为802.1Q VLAN
// 构造VLAN头部
vh = (struct vlan_header *)(buf + sizeof(struct ether_header));
vh->h_vlan_proto = htons(0x0800);
vh->h_vlan_TCI = htons((VLAN_ID & 0x0FFF) | (5 << 13) | (0 << 12)); // 设置VLAN ID和优先级
// 构造IPv4头部
ip = (struct iphdr *)(buf + sizeof(struct ether_header) + sizeof(struct vlan_header));
ip->version = 4;
ip->ihl = sizeof(struct iphdr) / 4;
ip->tos = 0;
ip->tot_len = htons(sizeof(struct iphdr) + /* 数据长度,这里假设为0 */ 0);
ip->id = 0;
ip->frag_off = 0;
ip->ttl = 64;
ip->protocol = IPPROTO_RAW; // IPPROTO_TCP; // 这里假设为TCP,你可以根据需要更改为UDP等
ip->check = 0; // 由内核在发送时计算
inet_pton(AF_INET, src_ip, &(ip->saddr));
inet_pton(AF_INET, dst_ip, &(ip->daddr));
// 这里应该填充IPv4选项(如果有),为了简化示例,我们省略了这些步骤
// 数据部分
data_leng = sizeof(struct ether_header) + sizeof(struct vlan_header) + sizeof(struct iphdr);
memset(buf + data_leng, 0x5A, BUF_SIZE - data_leng);
// 发送报文
if (sendto(sockfd, buf, BUF_SIZE, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
perror("sendto");
close(sockfd);
exit(1);
}
close(sockfd);
return 0;
}
290

被折叠的 条评论
为什么被折叠?



