下面我将介绍几个在Linux下使用C语言操作网卡的实用代码示例,涵盖常见的网络接口操作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
void get_interface_info(const char *ifname) {
int fd;
struct ifreq ifr;
struct sockaddr_in *sin;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return;
}
// 获取IP地址
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
sin = (struct sockaddr_in *)&ifr.ifr_addr;
printf("IP Address: %s\n", inet_ntoa(sin->sin_addr));
} else {
perror("SIOCGIFADDR");
}
// 获取网络掩码
if (ioctl(fd, SIOCGIFNETMASK, &ifr) == 0) {
sin = (struct sockaddr_in *)&ifr.ifr_netmask;
printf("Netmask: %s\n", inet_ntoa(sin->sin_addr));
} else {
perror("SIOCGIFNETMASK");
}
// 获取MAC地址
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
unsigned char *mac = (unsigned char *)ifr.ifr_hwaddr.sa_data;
printf("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
} else {
perror("SIOCGIFHWADDR");
}
close(fd);
}
int main() {
get_interface_info("eth0"); // 替换为你的网卡名称
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
int set_interface_ip(const char *ifname, const char *ip_addr) {
int fd;
struct ifreq ifr;
struct sockaddr_in *sin;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
// 设置IP地址
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
sin = (struct sockaddr_in *)&ifr.ifr_addr;
sin->sin_family = AF_INET;
if (inet_pton(AF_INET, ip_addr, &sin->sin_addr) <= 0) {
perror("inet_pton");
close(fd);
return -1;
}
if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) {
perror("SIOCSIFADDR");
close(fd);
return -1;
}
close(fd);
return 0;
}
int main() {
if (set_interface_ip("eth0", "192.168.1.100") == 0) {
printf("IP address set successfully\n");
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
int set_interface_state(const char *ifname, int state) {
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
// 获取当前标志
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
perror("SIOCGIFFLAGS");
close(fd);
return -1;
}
// 设置新标志
if (state) {
ifr.ifr_flags |= IFF_UP; // 启用接口
} else {
ifr.ifr_flags &= ~IFF_UP; // 禁用接口
}
if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
perror("SIOCSIFFLAGS");
close(fd);
return -1;
}
close(fd);
return 0;
}
int main() {
// 启用接口
if (set_interface_state("eth0", 1) == 0) {
printf("Interface enabled\n");
}
// 禁用接口
// set_interface_state("eth0", 0);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
void packet_sniffer(const char *ifname) {
int sockfd;
struct sockaddr_ll saddr;
unsigned char buffer[ETH_FRAME_LEN];
ssize_t n;
// 创建原始套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("socket");
return;
}
// 绑定到特定接口
memset(&saddr, 0, sizeof(saddr));
saddr.sll_family = AF_PACKET;
saddr.sll_protocol = htons(ETH_P_ALL);
saddr.sll_ifindex = if_nametoindex(ifname);
if (saddr.sll_ifindex == 0) {
perror("if_nametoindex");
close(sockfd);
return;
}
if (bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
perror("bind");
close(sockfd);
return;
}
printf("Starting packet capture on %s...\n", ifname);
while (1) {
n = recvfrom(sockfd, buffer, sizeof(buffer), 0, NULL, NULL);
if (n < 0) {
perror("recvfrom");
break;
}
// 这里简单打印接收到的包长度
printf("Received packet of length %zd\n", n);
// 实际应用中,这里可以解析包内容
}
close(sockfd);
}
int main() {
packet_sniffer("eth0"); // 替换为你的网卡名称
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
int send_raw_frame(const char *ifname, const unsigned char *dest_mac,
const unsigned char *src_mac, const unsigned char *data,
size_t data_len) {
int sockfd;
struct sockaddr_ll saddr;
unsigned char frame[ETH_FRAME_LEN];
int ifindex;
// 创建原始套接字
sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sockfd < 0) {
perror("socket");
return -1;
}
// 获取接口索引
ifindex = if_nametoindex(ifname);
if (ifindex == 0) {
perror("if_nametoindex");
close(sockfd);
return -1;
}
// 准备以太网帧
memset(frame, 0, sizeof(frame));
// 设置目标MAC
memcpy(frame, dest_mac, ETH_ALEN);
// 设置源MAC
memcpy(frame + ETH_ALEN, src_mac, ETH_ALEN);
// 设置以太网类型 (这里使用0x0800表示IP协议)
frame[12] = 0x08;
frame[13] = 0x00;
// 复制数据
if (data_len > ETH_DATA_LEN) {
fprintf(stderr, "Data too large for Ethernet frame\n");
close(sockfd);
return -1;
}
memcpy(frame + ETH_HLEN, data, data_len);
// 准备目标地址结构
memset(&saddr, 0, sizeof(saddr));
saddr.sll_family = AF_PACKET;
saddr.sll_ifindex = ifindex;
saddr.sll_halen = ETH_ALEN;
memcpy(saddr.sll_addr, dest_mac, ETH_ALEN);
// 发送帧
if (sendto(sockfd, frame, ETH_HLEN + data_len, 0,
(struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
perror("sendto");
close(sockfd);
return -1;
}
close(sockfd);
return 0;
}
int main() {
// 示例MAC地址和数据
unsigned char dest_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 广播地址
unsigned char src_mac[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}; // 源MAC(替换为你的)
unsigned char data[] = "Hello, Ethernet!";
if (send_raw_frame("eth0", dest_mac, src_mac, data, sizeof(data)) == 0) {
printf("Frame sent successfully\n");
}
return 0;
}
这些代码示例涵盖了常见的网卡操作场景,可以根据实际需求进行修改和扩展。