1 /*
2 VTun - Virtual Tunnel over TCP/IP network.
3
4 Copyright (C) 1998-2016 Maxim Krasnyansky <max_mk@yahoo.com>
5
6 VTun has been derived from VPPP package by Maxim Krasnyansky.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17 */
18
19 /*
20 * $Id: linkfd.c,v 1.13.2.7 2016/10/01 21:27:51 mtbishop Exp $
21 */
22
23 #include "config.h"
24
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <strings.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/time.h>
33 #include <syslog.h>
34 #include <time.h>
35
36 #ifdef HAVE_SYS_RESOURCE_H
37 #include <sys/resource.h>
38 #endif
39
40 #ifdef HAVE_SCHED_H
41 #include <sched.h>
42 #endif
43
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
46 #endif
47
48 #include "vtun.h"
49 #include "linkfd.h"
50 #include "lib.h"
51 #include "driver.h"
52
53 /* used by lfd_encrypt */
54 int send_a_packet = 0;
55
56 /* Host we are working with.
57 * Used by signal handlers that's why it is global.
58 */
59 static struct vtun_host *lfd_host;
60
61 static struct lfd_mod *lfd_mod_head = NULL, *lfd_mod_tail = NULL;
62
63 /* Modules functions*/
64
65 /* Add module to the end of modules list */
lfd_add_mod(struct lfd_mod * mod)66 static void lfd_add_mod(struct lfd_mod *mod)
67 {
68 if( !lfd_mod_head ){
69 lfd_mod_head = lfd_mod_tail = mod;
70 mod->next = mod->prev = NULL;
71 } else {
72 lfd_mod_tail->next = mod;
73 mod->prev = lfd_mod_tail;
74 mod->next = NULL;
75 lfd_mod_tail = mod;
76 }
77 }
78
79 /* Initialize and allocate each module */
lfd_alloc_mod(struct vtun_host * host)80 static int lfd_alloc_mod(struct vtun_host *host)
81 {
82 struct lfd_mod *mod = lfd_mod_head;
83
84 while( mod ){
85 if( mod->alloc && (mod->alloc)(host) )
86 return 1;
87 mod = mod->next;
88 }
89
90 return 0;
91 }
92
93 /* Free all modules */
lfd_free_mod(void)94 static int lfd_free_mod(void)
95 {
96 struct lfd_mod *mod = lfd_mod_head;
97
98 while( mod ){
99 if( mod->free && (mod->free)() )
100 return 1;
101 mod = mod->next;
102 }
103 lfd_mod_head = lfd_mod_tail = NULL;
104 return 0;
105 }
106
107 /* Run modules down (from head to tail) */
lfd_run_down(int len,char * in,char ** out)108 static inline int lfd_run_down(int len, char *in, char **out)
109 {
110 register struct lfd_mod *mod;
111
112 *out = in;
113 for(mod = lfd_mod_head; mod && len > 0; mod = mod->next )
114 if( mod->encode ){
115 len = (mod->encode)(len, in, out);
116 in = *out;
117 }
118 return len;
119 }
120
121 /* Run modules up (from tail to head) */
lfd_run_up(int len,char * in,char ** out)122 static inline int lfd_run_up(int len, char *in, char **out)
123 {
124 register struct lfd_mod *mod;
125
126 *out = in;
127 for(mod = lfd_mod_tail; mod && len > 0; mod = mod->prev )
128 if( mod->decode ){
129 len = (mod->decode)(len, in, out);
130 in = *out;
131 }
132 return len;
133 }
134
135 /* Check if modules are accepting the data(down) */
lfd_check_down(void)136 static inline int lfd_check_down(void)
137 {
138 register struct lfd_mod *mod;
139 int err = 1;
140
141 for(mod = lfd_mod_head; mod && err > 0; mod = mod->next )
142 if( mod->avail_encode )
143 err = (mod->avail_encode)();
144 return err;
145 }
146
147 /* Check if modules are accepting the data(up) */
lfd_check_up(void)148 static inline int lfd_check_up(void)
149 {
150 register struct lfd_mod *mod;
151 int err = 1;
152
153 for(mod = lfd_mod_tail; mod && err > 0; mod = mod->prev)
154 if( mod->avail_decode )
155 err = (mod->avail_decode)();
156
157 return err;
158 }
159
160 /********** Linker *************/
161 /* Termination flag */
162 static volatile sig_atomic_t linker_term;
163
sig_term(int sig)164 static void sig_term(int sig)
165 {
166 vtun_syslog(LOG_INFO, "Closing connection");
167 io_cancel();
168 linker_term = VTUN_SIG_TERM;
169 }
170
sig_hup(int sig)171 static void sig_hup(int sig)
172 {
173 vtun_syslog(LOG_INFO, "Reestablishing connection");
174 io_cancel();
175 linker_term = VTUN_SIG_HUP;
176 }
177
178 /* Statistic dump and keep-alive monitor */
179 static volatile sig_atomic_t ka_need_verify = 0;
180 static time_t stat_timer = 0, ka_timer = 0;
181
sig_alarm(int sig)182 static void sig_alarm(int sig)
183 {
184 static time_t tm_old, tm = 0;
185 static char stm[20];
186
187 tm_old = tm;
188 tm = time(NULL);
189
190 if( (lfd_host->flags & VTUN_KEEP_ALIVE) && (ka_timer -= tm-tm_old) <= 0){
191 ka_need_verify = 1;
192 ka_timer = lfd_host->ka_interval
193 + 1; /* We have to complete select() on idle */
194 }
195
196 if( (lfd_host->flags & VTUN_STAT) && (stat_timer -= tm-tm_old) <= 0){
197 strftime(stm, sizeof(stm)-1, "%b %d %H:%M:%S", localtime(&tm));
198 fprintf(lfd_host->stat.file,"%s %lu %lu %lu %lu\n", stm,
199 lfd_host->stat.byte_in, lfd_host->stat.byte_out,
200 lfd_host->stat.comp_in, lfd_host->stat.comp_out);
201 stat_timer = VTUN_STAT_IVAL;
202 }
203
204 if ( ka_timer*stat_timer ){
205 alarm( (ka_timer < stat_timer) ? ka_timer : stat_timer );
206 } else {
207 alarm( (ka_timer) ? ka_timer : stat_timer );
208 }
209 }
210
sig_usr1(int sig)211 static void sig_usr1(int sig)
212 {
213 /* Reset statistic counters on SIGUSR1 */
214 lfd_host->stat.byte_in = lfd_host->stat.byte_out = 0;
215 lfd_host->stat.comp_in = lfd_host->stat.comp_out = 0;
216 }
217
lfd_linker(void)218 static int lfd_linker(void)
219 {
220 int fd1 = lfd_host->rmt_fd;
221 int fd2 = lfd_host->loc_fd;
222 register int len, fl;
223 struct timeval tv;
224 char *buf, *out;
225 fd_set fdset;
226 int maxfd, idle = 0, tmplen;
227
228 if( !(buf = lfd_alloc(VTUN_FRAME_SIZE + VTUN_FRAME_OVERHEAD)) ){
229 vtun_syslog(LOG_ERR,"Can't allocate buffer for the linker");
230 return 0;
231 }
232
233 /* Delay sending of first UDP packet over broken NAT routers
234 because we will probably be disconnected. Wait for the remote
235 end to send us something first, and use that connection. */
236 if (!VTUN_USE_NAT_HACK(lfd_host))
237 proto_write(fd1, buf, VTUN_ECHO_REQ);
238
239 maxfd = (fd1 > fd2 ? fd1 : fd2) + 1;
240
241 linker_term = 0;
242 while( !linker_term ){
243 errno = 0;
244
245 /* Wait for data */
246 FD_ZERO(&fdset);
247 FD_SET(fd1, &fdset);
248 FD_SET(fd2, &fdset);
249
250 tv.tv_sec = lfd_host->ka_interval;
251 tv.tv_usec = 0;
252
253 if( (len = select(maxfd, &fdset, NULL, NULL, &tv)) < 0 ){
254 if( errno != EAGAIN && errno != EINTR )
255 break;
256 else
257 continue;
258 }
259
260 if( ka_need_verify ){
261 if( idle > lfd_host->ka_maxfail ){
262 vtun_syslog(LOG_INFO,"Session %s network timeout", lfd_host->host);
263 break;
264 }
265 if (idle++ > 0) { /* No input frames, check connection with ECHO */
266 if( proto_write(fd1, buf, VTUN_ECHO_REQ) < 0 ){
267 vtun_syslog(LOG_ERR,"Failed to send ECHO_REQ");
268 break;
269 }
270 }
271 ka_need_verify = 0;
272 }
273
274 if (send_a_packet)
275 {
276 send_a_packet = 0;
277 tmplen = 1;
278 lfd_host->stat.byte_out += tmplen;
279 if( (tmplen=lfd_run_down(tmplen,buf,&out)) == -1 )
280 break;
281 if( tmplen && proto_write(fd1, out, tmplen) < 0 )
282 break;
283 lfd_host->stat.comp_out += tmplen;
284 }
285
286 /* Read frames from network(fd1), decode and pass them to
287 * the local device (fd2) */
288 if( FD_ISSET(fd1, &fdset) && lfd_check_up() ){
289 idle = 0; ka_need_verify = 0;
290 if( (len=proto_read(fd1, buf)) <= 0 )
291 break;
292
293 /* Handle frame flags */
294 fl = len & ~VTUN_FSIZE_MASK;
295 len = len & VTUN_FSIZE_MASK;
296 if( fl ){
297 if( fl==VTUN_BAD_FRAME ){
298 vtun_syslog(LOG_ERR, "Received bad frame");
299 continue;
300 }
301 if( fl==VTUN_ECHO_REQ ){
302 /* Send ECHO reply */
303 if( proto_write(fd1, buf, VTUN_ECHO_REP) < 0 )
304 break;
305 continue;
306 }
307 if( fl==VTUN_ECHO_REP ){
308 /* Just ignore ECHO reply, ka_need_verify==0 already */
309 continue;
310 }
311 if( fl==VTUN_CONN_CLOSE ){
312 vtun_syslog(LOG_INFO,"Connection closed by other side");
313 break;
314 }
315 }
316
317 lfd_host->stat.comp_in += len;
318 if( (len=lfd_run_up(len,buf,&out)) == -1 )
319 break;
320 if( len && dev_write(fd2,out,len) < 0 ){
321 if( errno != EAGAIN && errno != EINTR )
322 break;
323 else
324 continue;
325 }
326 lfd_host->stat.byte_in += len;
327 }
328
329 /* Read data from the local device(fd2), encode and pass it to
330 * the network (fd1) */
331 if( FD_ISSET(fd2, &fdset) && lfd_check_down() ){
332 if( (len = dev_read(fd2, buf, VTUN_FRAME_SIZE)) < 0 ){
333 if( errno != EAGAIN && errno != EINTR )
334 break;
335 else
336 continue;
337 }
338 if( !len ) break;
339
340 lfd_host->stat.byte_out += len;
341 if( (len=lfd_run_down(len,buf,&out)) == -1 )
342 break;
343 if( len && proto_write(fd1, out, len) < 0 )
344 break;
345 lfd_host->stat.comp_out += len;
346 }
347 }
348 if( !linker_term && errno )
349 vtun_syslog(LOG_INFO,"%s (%d)", strerror(errno), errno);
350
351 if (linker_term == VTUN_SIG_TERM) {
352 lfd_host->persist = 0;
353 }
354
355 /* Notify other end about our close */
356 proto_write(fd1, buf, VTUN_CONN_CLOSE);
357 lfd_free(buf);
358
359 return 0;
360 }
361
362 /* Link remote and local file descriptors */
linkfd(struct vtun_host * host)363 int linkfd(struct vtun_host *host)
364 {
365 struct sigaction sa, sa_oldterm, sa_oldint, sa_oldhup;
366 int old_prio;
367
368 lfd_host = host;
369
370 old_prio=getpriority(PRIO_PROCESS,0);
371 setpriority(PRIO_PROCESS,0,LINKFD_PRIO);
372
373 /* Build modules stack */
374 if(host->flags & VTUN_ZLIB)
375 lfd_add_mod(&lfd_zlib);
376
377 if(host->flags & VTUN_LZO)
378 lfd_add_mod(&lfd_lzo);
379
380 if(host->flags & VTUN_ENCRYPT)
381 if(host->cipher == VTUN_LEGACY_ENCRYPT) {
382 lfd_add_mod(&lfd_legacy_encrypt);
383 } else {
384 lfd_add_mod(&lfd_encrypt);
385 }
386
387 if(host->flags & VTUN_SHAPE)
388 lfd_add_mod(&lfd_shaper);
389
390 if(lfd_alloc_mod(host))
391 return 0;
392
393 memset(&sa, 0, sizeof(sa));
394 sa.sa_handler=sig_term;
395 sigaction(SIGTERM,&sa,&sa_oldterm);
396 sigaction(SIGINT,&sa,&sa_oldint);
397 sa.sa_handler=sig_hup;
398 sigaction(SIGHUP,&sa,&sa_oldhup);
399
400 /* Initialize keep-alive timer */
401 if( host->flags & (VTUN_STAT|VTUN_KEEP_ALIVE) ){
402 sa.sa_handler=sig_alarm;
403 sigaction(SIGALRM,&sa,NULL);
404
405 alarm( (host->ka_interval < VTUN_STAT_IVAL) ?
406 host->ka_interval : VTUN_STAT_IVAL );
407 }
408
409 /* Initialize statstic dumps */
410 if( host->flags & VTUN_STAT ){
411 char file[40];
412
413 sa.sa_handler=sig_alarm;
414 sigaction(SIGALRM,&sa,NULL);
415 sa.sa_handler=sig_usr1;
416 sigaction(SIGUSR1,&sa,NULL);
417
418 sprintf(file,"%s/%.20s", VTUN_STAT_DIR, host->host);
419 if( (host->stat.file=fopen(file, "a")) ){
420 setvbuf(host->stat.file, NULL, _IOLBF, 0);
421 } else
422 vtun_syslog(LOG_ERR, "Can't open stats file %s", file);
423 }
424
425 io_init();
426
427 lfd_linker();
428
429 if( host->flags & (VTUN_STAT|VTUN_KEEP_ALIVE) ){
430 alarm(0);
431 if (host->stat.file)
432 fclose(host->stat.file);
433 }
434
435 lfd_free_mod();
436
437 sigaction(SIGTERM,&sa_oldterm,NULL);
438 sigaction(SIGINT,&sa_oldint,NULL);
439 sigaction(SIGHUP,&sa_oldhup,NULL);
440
441 setpriority(PRIO_PROCESS,0,old_prio);
442
443 return linker_term;
444 }
445