-
Notifications
You must be signed in to change notification settings - Fork 0
/
getifaddrs_bridge_server.c
222 lines (211 loc) · 8.16 KB
/
getifaddrs_bridge_server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// 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 <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 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 <socket_path>\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;
}