Files
tiny_computer/extra/getifaddrs_bridge/getifaddrs_bridge_client_lib.c
2023-11-10 21:29:07 +08:00

244 lines
9.4 KiB
C
Raw 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.
// getifaddrs_bridge_client_lib.c -- This file is part of tiny_computer.
// Copyright (C) 2023 Caten Hu
// Tiny Computer is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License,
// or any later version.
// Tiny Computer is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
/* this file is mainly generated by Bing */
#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 <ifaddrs.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/un.h>
#define BUFSIZE 1024 // 定义缓冲区大小
// 定义一个反序列化函数将字节数组转换为ifaddrs结构体
int TINY_deserialize_ifaddrs(char *buf, int size, struct ifaddrs **ifap) {
int len = 0; // 记录已经读取的字节数
struct ifaddrs *head = NULL; // 链表头指针
struct ifaddrs *tail = NULL; // 链表尾指针
while (len < size) {
// 为当前接口分配内存
struct ifaddrs *ifa = (struct ifaddrs *)malloc(sizeof(struct ifaddrs));
if (ifa == NULL) {
// 分配失败,释放已分配的内存
freeifaddrs(head);
return -1; // 返回错误
}
// 读取接口名称
int namelen = strlen(buf + len) + 1; // 包括结束符
if (len + namelen > size) break; // 缓冲区不足
ifa->ifa_name = (char *)malloc(namelen); // 为名称分配内存
if (ifa->ifa_name == NULL) {
// 分配失败,释放已分配的内存
free(ifa);
freeifaddrs(head);
return -1; // 返回错误
}
memcpy(ifa->ifa_name, buf + len, namelen); // 复制名称
len += namelen;
// 读取接口标志
if (len + sizeof(unsigned int) > size) break; // 缓冲区不足
memcpy(&ifa->ifa_flags, buf + len, sizeof(unsigned int)); // 复制标志
len += sizeof(unsigned int);
// 读取接口地址
if (buf[len] != '\0') {
// 如果有地址
int addrlen = sizeof(struct sockaddr); // 地址结构体长度
if (len + addrlen > size) break; // 缓冲区不足
ifa->ifa_addr = (struct sockaddr *)malloc(addrlen); // 为地址分配内存
if (ifa->ifa_addr == NULL) {
// 分配失败,释放已分配的内存
free(ifa->ifa_name);
free(ifa);
freeifaddrs(head);
return -1; // 返回错误
}
memcpy(ifa->ifa_addr, buf + len, addrlen); // 复制地址
len += addrlen;
} else {
// 如果没有地址,跳过一个空字节
ifa->ifa_addr = NULL;
len += 1;
}
// 读取接口掩码
if (buf[len] != '\0') {
// 如果有掩码
int masklen = sizeof(struct sockaddr); // 掩码结构体长度
if (len + masklen > size) break; // 缓冲区不足
ifa->ifa_netmask = (struct sockaddr *)malloc(masklen); // 为掩码分配内存
if (ifa->ifa_netmask == NULL) {
// 分配失败,释放已分配的内存
free(ifa->ifa_addr);
free(ifa->ifa_name);
free(ifa);
freeifaddrs(head);
return -1; // 返回错误
}
memcpy(ifa->ifa_netmask, buf + len, masklen); // 复制
len += masklen;
} else {
// 如果没有掩码,跳过一个空字节
ifa->ifa_netmask = NULL;
len += 1;
}
// 读取接口广播地址或点对点地址
if (ifa->ifa_flags & IFF_BROADCAST) {
// 如果有广播地址
if (buf[len] != '\0') {
// 如果有广播地址
int broadlen = sizeof(struct sockaddr); // 广播地址结构体长度
if (len + broadlen > size) break; // 缓冲区不足
ifa->ifa_broadaddr = (struct sockaddr *)malloc(broadlen); // 为广播地址分配内存
if (ifa->ifa_broadaddr == NULL) {
// 分配失败,释放已分配的内存
free(ifa->ifa_netmask);
free(ifa->ifa_addr);
free(ifa->ifa_name);
free(ifa);
freeifaddrs(head);
return -1; // 返回错误
}
memcpy(ifa->ifa_broadaddr, buf + len, broadlen); // 复制广播地址
len += broadlen;
} else {
// 如果没有广播地址,跳过一个空字节
ifa->ifa_broadaddr = NULL;
len += 1;
}
} else if (ifa->ifa_flags & IFF_POINTOPOINT) {
// 如果有点对点地址
if (buf[len] != '\0') {
// 如果有点对点地址
int dstlen = sizeof(struct sockaddr); // 点对点地址结构体长度
if (len + dstlen > size) break; // 缓冲区不足
ifa->ifa_dstaddr = (struct sockaddr *)malloc(dstlen); // 为点对点地址分配内存
if (ifa->ifa_dstaddr == NULL) {
// 分配失败,释放已分配的内存
free(ifa->ifa_netmask);
free(ifa->ifa_addr);
free(ifa->ifa_name);
free(ifa);
freeifaddrs(head);
return -1; // 返回错误
}
memcpy(ifa->ifa_dstaddr, buf + len, dstlen); // 复制点对点地址
len += dstlen;
} else {
// 如果没有点对点地址,跳过一个空字节
ifa->ifa_dstaddr = NULL;
len += 1;
}
} else {
// 如果没有广播地址或点对点地址,跳过两个空字节
ifa->ifa_broadaddr = NULL;
ifa->ifa_dstaddr = NULL;
len += 2;
}
// 读取接口数据
if (buf[len] != '\0') {
// 如果有数据
// TODO: 根据不同的地址族,读取不同的数据
// 这里暂时省略,只跳过一个空字节
ifa->ifa_data = NULL;
len += 1;
} else {
// 如果没有数据,跳过一个空字节
ifa->ifa_data = NULL;
len += 1;
}
// 将当前接口插入链表
ifa->ifa_next = NULL;
if (head == NULL) {
// 如果是第一个接口,设置头指针
head = ifa;
} else {
// 如果不是第一个接口,设置尾指针的下一个指针
tail->ifa_next = ifa;
}
// 更新尾指针
tail = ifa;
}
*ifap = head; // 返回链表头指针
return len; // 返回读取的总字节数
}
// 定义一个发送信号的函数,向服务器发送一个信号
int TINY_send_signal(int sockfd) {
char sig = 'S'; // 定义信号为一个字符S
int n = write(sockfd, &sig, 1); // 向套接字写入一个字节
if (n < 0) {
perror("write");
return -1; // 返回错误
}
return 0; // 返回成功
}
// 定义一个接收数据的函数,从服务器接收数据并反序列化
int TINY_receive_data(int sockfd, struct ifaddrs **ifap) {
char buf[BUFSIZE]; // 定义缓冲区
int n = read(sockfd, buf, BUFSIZE); // 从套接字读取数据
if (n < 0) {
perror("read");
return -1; // 返回错误
}
int len = TINY_deserialize_ifaddrs(buf, n, ifap); // 反序列化数据
if (len < 0) {
fprintf(stderr, "deserialize_ifaddrs failed\n");
return -1; // 返回错误
}
return 0; // 返回成功
}
// 主函数
int getifaddrs(struct ifaddrs **ifap) {
// 创建一个套接字
int sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
// 定义服务器地址结构体
struct sockaddr_un un;
memset(&un, 0, sizeof(un));
un.sun_family = AF_UNIX;
snprintf(un.sun_path, sizeof(un.sun_path), "%s", "/tmp/.getifaddrs-bridge");
// 连接到服务器
if (connect(sockfd, (struct sockaddr *)&un, sizeof(un)) < 0) {
perror("connect");
exit(1);
}
// 发送信号给服务器
if (TINY_send_signal(sockfd) < 0) {
fprintf(stderr, "send_signal failed\n");
exit(1);
}
// 接收数据并反序列化
if (TINY_receive_data(sockfd, ifap) < 0) {
fprintf(stderr, "receive_data failed\n");
exit(1);
}
// 关闭套接字
close(sockfd);
return 0;
}