1 #include "common.h"
2 
3 extern struct uwsgi_tuntap utt;
4 
5 // error reporting
uwsgi_tuntap_error_do(struct uwsgi_tuntap_peer * uttp,char * msg,char * file,int line)6 void uwsgi_tuntap_error_do(struct uwsgi_tuntap_peer *uttp, char *msg, char *file, int line) {
7 	if (uttp) {
8 		uwsgi_log_verbose("[tuntap] peer fd: %d ip: %s %s: %s [%s line %d]\n", uttp->fd, uttp->ip, msg, strerror(errno), file, line);
9 	}
10 	else {
11 		uwsgi_log_verbose("[tuntap] %s: %s [%s line %d]\n", msg, strerror(errno), file, line);
12 	}
13 }
14 
15 // create a new peer
uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router * uttr,int fd,int is_router)16 struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_create(struct uwsgi_tuntap_router *uttr, int fd, int is_router) {
17 
18 	struct uwsgi_tuntap_peer *uttp = uwsgi_calloc(sizeof(struct uwsgi_tuntap_peer));
19 	uttp->fd = fd;
20 	// leave space fot he uwsgi header
21 	uttp->buf = uwsgi_malloc(utt.buffer_size + 4);
22 	uttp->write_buf = uwsgi_malloc(utt.buffer_size);
23 
24 	if (uttr->peers_tail) {
25 		uttr->peers_tail->next = uttp;
26 		uttp->prev = uttr->peers_tail;
27 		uttr->peers_tail = uttp;
28 	}
29 	else {
30 		uttr->peers_head = uttp;
31 		uttr->peers_tail = uttp;
32 	}
33 
34 	if (!is_router) {
35 		if (utt.use_credentials) {
36 			uwsgi_log_verbose("[uwsgi-tuntap] waiting for privileges drop...\n");
37 			for(;;) {
38 				if (getuid() > 0) break;
39 				sleep(1);
40 			}
41 			uwsgi_log_verbose("[uwsgi-tuntap] privileges dropped\n");
42 			if (uwsgi_pass_cred(fd, "uwsgi-tuntap", 12)) {
43 				// better to exit
44 				exit(1);
45 			}
46 		}
47 
48 		uwsgi_tuntap_peer_send_rules(fd, uttp);
49 	}
50 
51 	return uttp;
52 }
53 
54 // destroy a peer
uwsgi_tuntap_peer_destroy(struct uwsgi_tuntap_router * uttr,struct uwsgi_tuntap_peer * uttp)55 void uwsgi_tuntap_peer_destroy(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
56 	struct uwsgi_tuntap_peer *prev = uttp->prev;
57 	struct uwsgi_tuntap_peer *next = uttp->next;
58 
59 	if (prev) {
60 		prev->next = next;
61 	}
62 
63 	if (next) {
64 		next->prev = prev;
65 	}
66 
67 	if (uttp == uttr->peers_head) {
68 		uttr->peers_head = next;
69 	}
70 
71 	if (uttp == uttr->peers_tail) {
72 		uttr->peers_tail = prev;
73 	}
74 
75 	free(uttp->buf);
76 	free(uttp->write_buf);
77 	if (uttp->rules) free(uttp->rules);
78 	close(uttp->fd);
79 	free(uttp);
80 }
81 
82 
83 // get a peer by addr
uwsgi_tuntap_peer_get_by_addr(struct uwsgi_tuntap_router * uttr,uint32_t addr)84 struct uwsgi_tuntap_peer *uwsgi_tuntap_peer_get_by_addr(struct uwsgi_tuntap_router *uttr, uint32_t addr) {
85 	struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
86 	while (uttp) {
87 		if (uttp->addr == addr)
88 			return uttp;
89 		uttp = uttp->next;
90 	}
91 
92 	return NULL;
93 }
94 
95 // block all reading peers
uwsgi_tuntap_block_reads(struct uwsgi_tuntap_router * uttr)96 void uwsgi_tuntap_block_reads(struct uwsgi_tuntap_router *uttr) {
97 	struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
98 	while (uttp) {
99 		if (!uttp->blocked_read) {
100 			if (!uttp->wait_for_write) {
101 				if (event_queue_del_fd(uttr->queue, uttp->fd, event_queue_read())) {
102 					struct uwsgi_tuntap_peer *tmp_uttp = uttp;
103 					uttp = uttp->next;
104 					uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
105 					continue;
106 				}
107 			}
108 			else {
109 				if (event_queue_fd_readwrite_to_write(uttr->queue, uttp->fd)) {
110                                         struct uwsgi_tuntap_peer *tmp_uttp = uttp;
111                                         uttp = uttp->next;
112                                         uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
113                                         continue;
114                                 }
115 			}
116 			uttp->blocked_read = 1;
117 		}
118 		uttp = uttp->next;
119 	}
120 }
121 
122 //unblock all reading peers
uwsgi_tuntap_unblock_reads(struct uwsgi_tuntap_router * uttr)123 void uwsgi_tuntap_unblock_reads(struct uwsgi_tuntap_router *uttr) {
124 	struct uwsgi_tuntap_peer *uttp = uttr->peers_head;
125 	while (uttp) {
126 		if (uttp->blocked_read) {
127 			if (!uttp->wait_for_write) {
128 				if (event_queue_add_fd_read(uttr->queue, uttp->fd)) {
129 					struct uwsgi_tuntap_peer *tmp_uttp = uttp;
130 					uttp = uttp->next;
131 					uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
132 					continue;
133 				}
134 			}
135 			else {
136 				if (event_queue_fd_write_to_readwrite(uttr->queue, uttp->fd)) {
137 					struct uwsgi_tuntap_peer *tmp_uttp = uttp;
138 					uttp = uttp->next;
139 					uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
140 					continue;
141 				}
142 			}
143 			uttp->blocked_read = 0;
144 		}
145 		uttp = uttp->next;
146 	}
147 }
148 
149 // enqueue a packet in the tuntap device
uwsgi_tuntap_enqueue(struct uwsgi_tuntap_router * uttr)150 void uwsgi_tuntap_enqueue(struct uwsgi_tuntap_router *uttr) {
151 	ssize_t rlen = write(uttr->fd, uttr->write_buf + uttr->write_pos, uttr->write_pktsize - uttr->write_pos);
152 	// error on the tuntap device, destroy !!!
153 	if (rlen == 0) {
154 		uwsgi_error("uwsgi_tuntap_enqueue()/write()");
155 		exit(1);
156 	}
157 
158 	if (rlen < 0) {
159 		if (uwsgi_is_again())
160 			goto retry;
161 		uwsgi_error("uwsgi_tuntap_enqueue()/write()");
162 		exit(1);
163 	}
164 
165 	uttr->write_pos += rlen;
166 	if (uttr->write_pos >= uttr->write_pktsize) {
167 		uttr->write_pos = 0;
168 		if (uttr->wait_for_write) {
169 			if (event_queue_fd_write_to_read(uttr->queue, uttr->fd)) {
170 				uwsgi_error("uwsgi_tuntap_enqueue()/event_queue_fd_read_to_write()");
171 				exit(1);
172 			}
173 			uttr->wait_for_write = 0;
174 		}
175 		uwsgi_tuntap_unblock_reads(uttr);
176 		return;
177 	}
178 
179 retry:
180 	if (!uttr->wait_for_write) {
181 		uwsgi_tuntap_block_reads(uttr);
182 		if (event_queue_fd_read_to_write(uttr->queue, uttr->fd)) {
183 			uwsgi_error("uwsgi_tuntap_enqueue()/event_queue_fd_read_to_write()");
184 			exit(1);
185 		}
186 		uttr->wait_for_write = 1;
187 	}
188 }
189 
uwsgi_tuntap_register_addr(struct uwsgi_tuntap_router * uttr,struct uwsgi_tuntap_peer * uttp)190 int uwsgi_tuntap_register_addr(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
191 
192 	struct uwsgi_tuntap_peer *tmp_uttp = uwsgi_tuntap_peer_get_by_addr(uttr, uttp->addr);
193         char ip[INET_ADDRSTRLEN + 1];
194         memset(ip, 0, INET_ADDRSTRLEN + 1);
195         if (!inet_ntop(AF_INET, &uttp->addr, ip, INET_ADDRSTRLEN)) {
196         	uwsgi_tuntap_error(uttp, "uwsgi_tuntap_register_addr()/inet_ntop()");
197                 return -1;
198         }
199         if (uttp != tmp_uttp) {
200         	uwsgi_log("[tuntap-router] detected ip collision for %s\n", ip);
201                 uwsgi_tuntap_peer_destroy(uttr, tmp_uttp);
202         }
203         uwsgi_log("[tuntap-router] registered new peer %s (fd: %d)\n", ip, uttp->fd);
204         memcpy(uttp->ip, ip, INET_ADDRSTRLEN + 1);
205 	return 0;
206 }
207 
208 // receive a packet from the client
uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router * uttr,struct uwsgi_tuntap_peer * uttp,int is_router)209 int uwsgi_tuntap_peer_dequeue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp, int is_router) {
210 	// get body
211 	if (uttp->header_pos >= 4) {
212 		ssize_t rlen = read(uttp->fd, uttp->buf + uttp->buf_pos, uttp->buf_pktsize - uttp->buf_pos);
213 		if (rlen == 0)
214 			return -1;
215 		if (rlen < 0) {
216 			if (uwsgi_is_again())
217 				return 0;
218 			uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_dequeue()/read()");
219 			return -1;
220 		}
221 		uttp->buf_pos += rlen;
222 		uttp->rx += rlen;
223 		// a whole pkt has been received
224 		if (uttp->buf_pos >= uttp->buf_pktsize) {
225 
226 			uttp->header_pos = 0;
227 			uttp->buf_pos = 0;
228 
229 			if (!is_router) goto enqueue;
230 
231 			// a rule block
232 			if (uttp->header[3] == 1) {
233 				if (uttp->rules) free(uttp->rules);
234 				uttp->rules = uwsgi_malloc(uttp->buf_pktsize);
235 				memcpy(uttp->rules, uttp->buf, uttp->buf_pktsize);
236 				uttp->rules_cnt = uttp->buf_pktsize / sizeof(struct uwsgi_tuntap_peer_rule);
237 				return 0;
238 			}
239 
240 			if (uwsgi_tuntap_firewall_check(utt.fw_out, uttp->buf, uttp->buf_pktsize)) return 0;
241 
242 			// if there is no associated address store the source
243 			if (!uttp->addr) {
244 				// close on invalid first packet
245 				if (uttp->buf_pktsize < 20) return -1;
246 				uint32_t *src_ip = (uint32_t *) (&uttp->buf[12]);
247 				uttp->addr = *src_ip;
248 				// drop invalid ip addresses
249 				if (!uttp->addr)
250 					return -1;
251 
252 				if (uwsgi_tuntap_register_addr(uttr, uttp)) {
253 					return -1;
254 				}
255 
256 			}
257 
258 			if (uwsgi_tuntap_peer_rules_check(uttr, uttp, uttp->buf, uttp->buf_pktsize, 1)) return 0;
259 
260 			// check four routing rule
261 			if (uttr->gateway_fd > -1) {
262 				if (uwsgi_tuntap_route_check(uttr->gateway_fd, uttp->buf, uttp->buf_pktsize)) return 0;
263 			}
264 enqueue:
265 
266 			memcpy(uttr->write_buf, uttp->buf, uttp->buf_pktsize);
267 			uttr->write_pktsize = uttp->buf_pktsize;
268 			uwsgi_tuntap_enqueue(uttr);
269 		}
270 		return 0;
271 	}
272 	ssize_t rlen = read(uttp->fd, uttp->header + uttp->header_pos, 4 - uttp->header_pos);
273 	if (rlen == 0)
274 		return -1;
275 	if (rlen < 0) {
276 		if (uwsgi_is_again())
277 			return 0;
278 		uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_dequeue()/read()");
279 		return -1;
280 	}
281 	uttp->header_pos += rlen;
282 	if (uttp->header_pos >= 4) {
283 		uint16_t *pktsize = (uint16_t *) &uttp->header[1];
284 		uttp->buf_pktsize = *pktsize;
285 		uttp->rx += 4;
286 	}
287 	return 0;
288 }
289 
290 // enqueue a packet to the client
uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_router * uttr,struct uwsgi_tuntap_peer * uttp)291 int uwsgi_tuntap_peer_enqueue(struct uwsgi_tuntap_router *uttr, struct uwsgi_tuntap_peer *uttp) {
292 
293 	ssize_t rlen = write(uttp->fd, uttp->write_buf + uttp->written, uttp->write_buf_pktsize - uttp->written);
294 	if (rlen == 0) {
295 		uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/write()");
296 		return -1;
297 	}
298 
299 	if (rlen < 0) {
300 		if (uwsgi_is_again())
301 			goto retry;
302 		uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/write()");
303 		return -1;
304 	}
305 
306 	uttp->written += rlen;
307 	uttp->tx += rlen;
308 	if (uttp->written >= uttp->write_buf_pktsize) {
309 		uttp->written = 0;
310 		uttp->write_buf_pktsize = 0;
311 		if (uttp->wait_for_write) {
312 			// if the write ends while we are writing to the tuntap, block the reads
313 			if (uttr->wait_for_write) {
314 				uttp->blocked_read = 1;
315 				if (event_queue_del_fd(uttr->queue, uttp->fd, event_queue_write())) {
316 					uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_del_fd()");
317 					return -1;
318 				}
319 			}
320 			else {
321 				if (event_queue_fd_readwrite_to_read(uttr->queue, uttp->fd)) {
322 					uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_fd_write_to_read()");
323 					return -1;
324 				}
325 			}
326 			uttp->wait_for_write = 0;
327 		}
328 		return 0;
329 	}
330 
331 	memmove(uttp->write_buf, uttp->write_buf + rlen, uttp->write_buf_pktsize - rlen);
332 	uttp->write_buf_pktsize -= rlen;
333 
334 retry:
335 	if (!uttp->wait_for_write) {
336 		if (event_queue_fd_read_to_readwrite(uttr->queue, uttp->fd)) {
337 			uwsgi_tuntap_error(uttp, "uwsgi_tuntap_peer_enqueue()/event_queue_fd_read_to_write()");
338 			return -1;
339 		}
340 		uttp->wait_for_write = 1;
341 	}
342 
343 	return 0;
344 }
345 
uwsgi_tuntap_device(char * name)346 int uwsgi_tuntap_device(char *name) {
347 	struct ifreq ifr;
348         int fd = open(UWSGI_TUNTAP_DEVICE, O_RDWR);
349         if (fd < 0) {
350                 uwsgi_error_open(UWSGI_TUNTAP_DEVICE);
351                 exit(1);
352         }
353 
354         memset(&ifr, 0, sizeof(struct ifreq));
355 
356         ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
357         strncpy(ifr.ifr_name, name, IFNAMSIZ);
358 
359         if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0) {
360                 uwsgi_error("uwsgi_tuntap_device()/ioctl()");
361                 exit(1);
362         }
363 
364 	uwsgi_log("initialized tuntap device %s (fd: %d)\n", ifr.ifr_name, fd);
365 
366 	return fd;
367 }
368 
369