// getifaddrs_bridge_server.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 #include #include #include #include #include #include #include #include #include #include #define BUFSIZE 1024 // 定义缓冲区大小 // 定义一个序列化函数,将ifaddrs结构体转换为字节数组 int serialize_ifaddrs(struct ifaddrs *ifa, char *buf, int size) { int len = 0; // 记录已经写入的字节数 while (ifa != NULL && len < size) { // 写入接口名称 int namelen = strlen(ifa->ifa_name) + 1; // 包括结束符 if (len + namelen > size) break; // 缓冲区不足 memcpy(buf + len, ifa->ifa_name, namelen); len += namelen; // 写入接口标志 if (len + sizeof(unsigned int) > size) break; // 缓冲区不足 memcpy(buf + len, &ifa->ifa_flags, sizeof(unsigned int)); len += sizeof(unsigned int); // 写入接口地址 if (ifa->ifa_addr != NULL) { int addrlen = sizeof(struct sockaddr); // 地址结构体长度 if (len + addrlen > size) break; // 缓冲区不足 memcpy(buf + len, ifa->ifa_addr, addrlen); len += addrlen; } else { // 如果没有地址,写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } // 写入接口掩码 if (ifa->ifa_netmask != NULL) { int masklen = sizeof(struct sockaddr); // 掩码结构体长度 if (len + masklen > size) break; // 缓冲区不足 memcpy(buf + len, ifa->ifa_netmask, masklen); len += masklen; } else { // 如果没有掩码,写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } // 写入接口广播地址或点对点地址 if (ifa->ifa_flags & IFF_BROADCAST) { // 如果有广播地址 if (ifa->ifa_broadaddr != NULL) { int broadlen = sizeof(struct sockaddr); // 广播地址结构体长度 if (len + broadlen > size) break; // 缓冲区不足 memcpy(buf + len, ifa->ifa_broadaddr, broadlen); len += broadlen; } else { // 如果没有广播地址,写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } } else if (ifa->ifa_flags & IFF_POINTOPOINT) { // 如果有点对点地址 if (ifa->ifa_dstaddr != NULL) { int dstlen = sizeof(struct sockaddr); // 点对点地址结构体长度 if (len + dstlen > size) break; // 缓冲区不足 memcpy(buf + len, ifa->ifa_dstaddr, dstlen); len += dstlen; } else { // 如果没有点对点地址,写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } } else { // 如果没有广播地址或点对点地址,写入两个空字节 if (len + 2 > size) break; // 缓冲区不足 buf[len] = '\0'; buf[len + 1] = '\0'; len += 2; } // 写入接口数据 if (ifa->ifa_data != NULL) { // TODO: 根据不同的地址族,写入不同的数据 // 这里暂时省略,只写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } else { // 如果没有数据,写入一个空字节 if (len + 1 > size) break; // 缓冲区不足 buf[len] = '\0'; len += 1; } // 跳到下一个接口 ifa = ifa->ifa_next; } return len; // 返回写入的总字节数 } // 定义一个接收信号的函数,从客户端接收一个信号 int receive_signal(int sockfd) { char sig; // 定义信号变量 int n = read(sockfd, &sig, 1); // 从套接字读取一个字节 if (n < 0) { perror("read"); return -1; // 返回错误 } if (sig == 'S') { // 如果收到信号S,表示客户端需要数据 return 0; // 返回成功 } else { // 如果收到其他信号,表示无效信号 fprintf(stderr, "invalid signal: %c\n", sig); return -1; // 返回错误 } } // 定义一个发送数据的函数,向客户端发送数据并序列化 int send_data(int sockfd) { struct ifaddrs *ifap = NULL; // 定义ifaddrs结构体指针 // 调用getifaddrs函数,获取本地接口信息 if (getifaddrs(&ifap) < 0) { perror("getifaddrs"); return -1; // 返回错误 } char buf[BUFSIZE]; // 定义缓冲区 // 调用序列化函数,将ifaddrs结构体转换为字节数组 int len = serialize_ifaddrs(ifap, buf, BUFSIZE); if (len < 0) { fprintf(stderr, "serialize_ifaddrs failed\n"); return -1; // 返回错误 } // 向套接字写入数据 int n = write(sockfd, buf, len); if (n < 0) { perror("write"); return -1; // 返回错误 } // 释放ifaddrs结构体 freeifaddrs(ifap); return 0; // 返回成功 } // 主函数 int main(int argc, char *argv[]) { if (argc != 2) { printf("usage: %s \n", argv[0]); return 0; } // 创建一个套接字 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", argv[1]); unlink(un.sun_path); // 绑定套接字到服务器地址 if (bind(sockfd, (struct sockaddr *)&un, sizeof(un)) < 0) { perror("bind"); exit(1); } // 监听套接字 if (listen(sockfd, 5) < 0) { perror("listen"); exit(1); } // 循环接受客户端连接 while (1) { int connfd = accept(sockfd, NULL, NULL); if (connfd < 0) { perror("accept"); continue; // 如果接受失败,继续循环 } // 循环接收和发送数据 while (1) { // 接收信号 if (receive_signal(connfd) < 0) { fprintf(stderr, "receive_signal failed\n"); close(connfd); // 如果接收失败,关闭连接套接字 break; // 跳出循环 } // 发送数据 if (send_data(connfd) < 0) { fprintf(stderr, "send_data failed\n"); close(connfd); // 如果发送失败,关闭连接套接字 break; // 跳出循环 } } } // 关闭监听套接字 close(sockfd); return 0; }