-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclient.c
More file actions
160 lines (131 loc) · 4.97 KB
/
Copy pathclient.c
File metadata and controls
160 lines (131 loc) · 4.97 KB
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
/**
* client.c
* Function: VPN Client implementation. Communicates with the virtual switch and handles packet forwarding.
* Author: Cyans from Chang'an University
*/
#include "tap.h"
#include "debug.h"
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <pthread.h>
/*
* Virtual Port Structure
* Function: Packages variables required by the threads
*/
struct Vport {
int tap_fd;
int vport_sockfd;
struct sockaddr_in vswitch_addr;
};
/*
* Initialize Virtual Port: Setup TAP interface and UDP Socket
*/
void init_vport(struct Vport *vport, const char *_server_ip, int _server_port) {
char ifname[IFNAMSIZ] = "qwq";
int tapfd = tap_alloc(ifname);
if (tapfd < 0) {
DEBUG_ERROR("fail to tap_alloc");
}
int vport_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (vport_sockfd < 0) {
DEBUG_ERROR("fail to socket");
}
struct sockaddr_in vswitch_addr;
memset(&vswitch_addr, 0, sizeof(vswitch_addr));
vswitch_addr.sin_family = AF_INET;
vswitch_addr.sin_port = htons(_server_port);
if (inet_pton(AF_INET, _server_ip, &vswitch_addr.sin_addr) <= 0) {
DEBUG_ERROR("Invalid server IP address");
}
vport->tap_fd = tapfd;
vport->vport_sockfd = vport_sockfd;
vport->vswitch_addr = vswitch_addr;
DEBUG_LOG("Client Initialized. TAP device: %s, Server: %s:%d", ifname, _server_ip, _server_port);
}
/*
* Upstream Thread Function
* Logic: Read from TAP -> Encapsulate in UDP -> Send to Server
*/
void* upstream_thread(void* arg) {
struct Vport* vport = (struct Vport*)arg;
char buffer[ETHER_MAX_LEN];
while (true) {
ssize_t nread = read(vport->tap_fd, buffer, sizeof(buffer));
if (nread < 0) {
fprintf(stderr, "[WARN] Error reading from TAP device: %s\n", strerror(errno));
continue;
}
ssize_t nsent = sendto(vport->vport_sockfd, buffer, nread, 0, (struct sockaddr*)&vport->vswitch_addr, sizeof(vport->vswitch_addr));
if (nsent < 0) {
fprintf(stderr, "[WARN] Error sending packet to server: %s\n", strerror(errno));
continue;
}
if (nread >= 14) {
const struct ether_header *hdr = (const struct ether_header *)buffer;
DEBUG_LOG("Upstream: Sent %ld bytes. Src<%02x:%02x:%02x:%02x:%02x:%02x> -> Dst<%02x:%02x:%02x:%02x:%02x:%02x>",
nsent,
hdr->ether_shost[0], hdr->ether_shost[1], hdr->ether_shost[2], hdr->ether_shost[3], hdr->ether_shost[4], hdr->ether_shost[5],
hdr->ether_dhost[0], hdr->ether_dhost[1], hdr->ether_dhost[2], hdr->ether_dhost[3], hdr->ether_dhost[4], hdr->ether_dhost[5]
);
}
}
return NULL;
}
/*
* Downstream Thread Function
* Logic: Read UDP from Server -> Decapsulate -> Write to TAP -> Inject into Kernel
*/
void* downstream_thread(void* arg) {
struct Vport* vport = (struct Vport*)arg;
char buffer[ETHER_MAX_LEN];
struct sockaddr_in src_addr;
socklen_t addrlen = sizeof(src_addr);
while (true) {
ssize_t nrecv = recvfrom(vport->vport_sockfd, buffer, sizeof(buffer), 0,
(struct sockaddr*)&src_addr, &addrlen);
if (nrecv < 0) {
fprintf(stderr, "[WARN] Error receiving packet from server: %s\n", strerror(errno));
continue;
}
ssize_t nwrite = write(vport->tap_fd, buffer, nrecv);
if (nwrite < 0) {
fprintf(stderr, "[WARN] Error writing to TAP device: %s\n", strerror(errno));
continue;
}
if (nrecv >= 14) {
const struct ether_header *hdr = (const struct ether_header *)buffer;
DEBUG_LOG("Downstream: Recv %ld bytes. Src<%02x:%02x:%02x:%02x:%02x:%02x> -> Dst<%02x:%02x:%02x:%02x:%02x:%02x>",
nrecv,
hdr->ether_shost[0], hdr->ether_shost[1], hdr->ether_shost[2], hdr->ether_shost[3], hdr->ether_shost[4], hdr->ether_shost[5],
hdr->ether_dhost[0], hdr->ether_dhost[1], hdr->ether_dhost[2], hdr->ether_dhost[3], hdr->ether_dhost[4], hdr->ether_dhost[5]
);
}
}
return NULL;
}
/*
* Main Function
*/
int main(int argc, char const*argv[]) {
if (argc != 3) {
fprintf(stderr, "Usage: client {server_ip} {server_port}\n");
exit(1);
}
const char* _server_ip = argv[1];
int _server_port = atoi(argv[2]);
struct Vport vport;
init_vport(&vport, _server_ip, _server_port);
pthread_t up_thread, down_thread;
if (pthread_create(&up_thread, NULL, upstream_thread, (void*)&vport) != 0) {
DEBUG_ERROR("Failed to create upstream thread");
}
if (pthread_create(&down_thread, NULL, downstream_thread, (void*)&vport) != 0) {
DEBUG_ERROR("Failed to create downstream thread");
}
pthread_join(up_thread, NULL);
pthread_join(down_thread, NULL);
return 0;
}