00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00041
00082
00086
00090
00091
00092 #include <stdio.h>
00093 #include <unistd.h>
00094 #include <sys/types.h>
00095 #include <sys/socket.h>
00096 #include <sys/select.h>
00097 #include <sys/wait.h>
00098 #include <netinet/in.h>
00099 #include <arpa/inet.h>
00100 #include <netdb.h>
00101 #include <fcntl.h>
00102 #include <string.h>
00103 #include <errno.h>
00104 #include <ctype.h>
00105 #include <stdlib.h>
00106 #include <signal.h>
00107 #include <netdb.h>
00108 #include <time.h>
00109
00110 #ifdef __linux__
00114 #define LINUX_NETFILTER
00115 #endif
00116
00117 #ifdef LINUX_NETFILTER
00118 #include <limits.h>
00119 #include <linux/netfilter_ipv4.h>
00120 #endif
00121
00123 #define PARSE_LONG_OPT
00124 #ifdef PARSE_LONG_OPT
00125 #include <getopt.h>
00126 #endif
00127
00129 #define VERSION "1.2"
00131 #define MAX_BUF 100000
00132
00134 #define ERR(x...) fprintf(stderr,x)
00135
00136
00137
00138 #ifdef DEBUG
00140 #define DBG(x...) printf(x)
00141 #else
00143 #define DBG(x...)
00144 #endif
00145
00147 #define UDP_TIMEOUT 30
00148
00150 struct rule_s {
00152 char *from;
00154 char *to;
00156 const char *forig;
00158 const char *torig;
00160 int fs;
00162 int ts;
00164 int dir;
00165 };
00166
00168 enum {
00169 ALL = 0,
00170 IN = 1,
00171 OUT = 2,
00172 };
00173
00175 enum state_e {
00177 UNREPLIED,
00179 ESTABLISHED,
00183 DISCONNECTED,
00185 TIMEOUT
00186 };
00187
00189 struct tracker_s {
00191 struct sockaddr* csa;
00193 socklen_t csl;
00195 int csock;
00197 int fsock;
00199 time_t time;
00201 enum state_e state;
00203 int* live;
00204
00206 struct tracker_s * n;
00207 };
00208
00210 time_t now;
00211
00213 int lsock;
00214
00215
00216
00218 int family = AF_UNSPEC;
00219
00221 int tcp;
00222
00224 char* lport;
00225
00227 char* rhost;
00229 char* rport;
00230
00232 int rules;
00234 struct rule_s *rule;
00237 int *rule_live;
00238
00240 struct tracker_s * connections = NULL;
00241
00243 volatile int stop=0;
00244
00247 void short_usage_hints(const char* why) {
00248 if (why) ERR("Error: %s\n\n",why);
00249 ERR("Usage: netsed [option] proto lport rhost rport rule1 [ rule2 ... ]\n\n");
00250 ERR(" use netsed -h for more information on usage.\n");
00251 exit(1);
00252 }
00253
00254
00257 void usage_hints(const char* why) {
00258 if (why) ERR("Error: %s\n\n",why);
00259 ERR("Usage: netsed [option] proto lport rhost rport rule1 [ rule2 ... ]\n\n");
00260 #ifdef PARSE_LONG_OPT
00261 ERR(" options - can be --ipv4 or -4 to force address resolution in IPv4,\n");
00262 ERR(" --ipv6 or -6 to force address resolution in IPv6,\n");
00263 ERR(" --ipany to resolve the address in either IPv4 or IPv6.\n");
00264 ERR(" - --help or -h to display this usage information.\n");
00265 #else
00266 ERR(" options - can be nothing, -4 to force address resolution in IPv4\n");
00267 ERR(" or -6 to force address resolution in IPv6.\n");
00268 ERR(" - -h to display this usage information.\n");
00269 #endif
00270 ERR(" proto - protocol specification (tcp or udp)\n");
00271 ERR(" lport - local port to listen on (see README for transparent\n");
00272 ERR(" traffic intercepting on some systems)\n");
00273 ERR(" rhost - where connection should be forwarded (0 = use destination\n");
00274 ERR(" address of incoming connection, see README)\n");
00275 ERR(" rport - destination port (0 = dst port of incoming connection)\n");
00276 ERR(" ruleN - replacement rules (see below)\n\n");
00277 ERR("General syntax of replacement rules: s/pat1/pat2[/expire]\n\n");
00278 ERR("This will replace all occurrences of pat1 with pat2 in any matching packet.\n");
00279 ERR("An additional parameter, 'expire' of the form [CHAR][NUM], can be used to\n");
00280 ERR("expire a rule after NUM successful substitutions during a given connection.\n");
00281 ERR("The character CHAR is one of \"iIoO\", with the effect of restricting the rule\n");
00282 ERR("to apply to incoming (\"iI\") or to outgoing (\"oO\") packets only, as seen from\n");
00283 ERR("the client's perspective. Both of CHAR and NUM are optional.\n\n");
00284 ERR("Eight-bit characters, including NULL and '/', can be applied using HTTP-like\n");
00285 ERR("hex escape sequences (e.g. CRLF as %%0a%%0d).\n");
00286 ERR("A match on '%%' can be achieved by specifying '%%%%'.\n\nExamples:\n");
00287 ERR(" 's/andrew/mike/1' - replace 'andrew' with 'mike' (only first time)\n");
00288 ERR(" 's/andrew/mike' - replace all occurrences of 'andrew' with 'mike'\n");
00289 ERR(" 's/andrew/mike%%00%%00' - replace 'andrew' with 'mike\\x00\\x00'\n");
00290 ERR(" (manually padding to keep original size)\n");
00291 ERR(" 's/%%%%/%%2f/20' - replace the 20 first occurrence of '%%' with '/'\n");
00292 ERR(" 's/andrew/mike/o' - the server will always see 'mike', never 'andrew'\n\n");
00293 ERR(" 's/Rilke/Proust/o s/Proust/Rilke/i'\n");
00294 ERR(" - let Rilke travel incognito as Proust\n\n");
00295 ERR("Rules are not active across packet boundaries, and they are evaluated\n");
00296 ERR("from first to last, not yet expired rule, as stated on the command line.\n");
00297 exit(1);
00298 }
00299
00300
00304 void freetracker (struct tracker_s * conn)
00305 {
00306 if(conn->csa != NULL) {
00307 free(conn->csa);
00308 } else {
00309 close(conn->csock);
00310 }
00311 close(conn->fsock);
00312 free(conn);
00313 }
00314
00317 void clean_socks(void)
00318 {
00319 close(lsock);
00320
00321 while(connections != NULL) {
00322 struct tracker_s * conn = connections;
00323 connections = conn->n;
00324 freetracker(conn);
00325 }
00326 }
00327
00328 #ifdef __GNUC__
00329
00330
00331 in_port_t get_port(struct sockaddr *sa) __attribute__ ((noinline));
00332 void set_port(struct sockaddr *sa, in_port_t port) __attribute__ ((noinline));
00333 #endif
00334
00337 in_port_t get_port(struct sockaddr *sa) {
00338 switch (sa->sa_family) {
00339 case AF_INET:
00340 return ntohs(((struct sockaddr_in *) sa)->sin_port);
00341 case AF_INET6:
00342 return ntohs(((struct sockaddr_in6 *) sa)->sin6_port);
00343 default:
00344 return 0;
00345 }
00346 }
00347
00351 void set_port(struct sockaddr *sa, in_port_t port) {
00352 switch (sa->sa_family) {
00353 case AF_INET:
00354 ((struct sockaddr_in *) sa)->sin_port = htons(port);
00355 break;
00356 case AF_INET6:
00357 ((struct sockaddr_in6 *) sa)->sin6_port = htons(port);
00358 default:
00359 break;
00360 }
00361 }
00362
00366 int is_addr_any(struct sockaddr *sa) {
00367 switch (sa->sa_family) {
00368 case AF_INET:
00369 return (((struct sockaddr_in *) sa)->sin_addr.s_addr == htonl(INADDR_ANY));
00370 case AF_INET6:
00371 return !memcmp(&((struct sockaddr_in6 *) sa)->sin6_addr, &in6addr_any, sizeof(in6addr_any));
00372 default:
00373 return 0;
00374 }
00375 }
00376
00377
00379 void error(const char* reason) {
00380 ERR("[-] Error: %s\n",reason);
00381 ERR("netsed: exiting.\n");
00382 clean_socks();
00383 exit(2);
00384 }
00385
00387 char hex[]="0123456789ABCDEF";
00388
00391 void shrink_to_binary(struct rule_s* r) {
00392 int i;
00393
00394 r->from=malloc(strlen(r->forig));
00395 r->to=malloc(strlen(r->torig));
00396 if ((!r->from) || (!r->to)) error("shrink_to_binary: unable to malloc() buffers");
00397
00398 for (i=0;i<strlen(r->forig);i++) {
00399 if (r->forig[i]=='%') {
00400
00401 i++;
00402 if (r->forig[i]=='%') {
00403
00404 r->from[r->fs]='%';
00405 r->fs++;
00406 } else {
00407 int hexval;
00408 char* x;
00409 if (!r->forig[i]) error("shrink_to_binary: src pattern: unexpected end.");
00410 if (!r->forig[i+1]) error("shrink_to_binary: src pattern: unexpected end.");
00411 x=strchr(hex,toupper(r->forig[i]));
00412 if (!x) error("shrink_to_binary: src pattern: non-hex sequence.");
00413 hexval=(x-hex)*16;
00414 x=strchr(hex,toupper(r->forig[i+1]));
00415 if (!x) error("shrink_to_binary: src pattern: non-hex sequence.");
00416 hexval+=(x-hex);
00417 r->from[r->fs]=hexval;
00418 r->fs++; i++;
00419 }
00420 } else {
00421
00422 r->from[r->fs]=r->forig[i];
00423 r->fs++;
00424 }
00425 }
00426
00427 for (i=0;i<strlen(r->torig);i++) {
00428 if (r->torig[i]=='%') {
00429
00430 i++;
00431 if (r->torig[i]=='%') {
00432
00433 r->to[r->ts]='%';
00434 r->ts++;
00435 } else {
00436 int hexval;
00437 char* x;
00438 if (!r->torig[i]) error("shrink_to_binary: dst pattern: unexpected end.");
00439 if (!r->torig[i+1]) error("shrink_to_binary: dst pattern: unexpected end.");
00440 x=strchr(hex,toupper(r->torig[i]));
00441 if (!x) error("shrink_to_binary: dst pattern: non-hex sequence.");
00442 hexval=(x-hex)*16;
00443 x=strchr(hex,toupper(r->torig[i+1]));
00444 if (!x) error("shrink_to_binary: dst pattern: non-hex sequence.");
00445 hexval+=(x-hex);
00446 r->to[r->ts]=hexval;
00447 r->ts++; i++;
00448 }
00449 } else {
00450
00451 r->to[r->ts]=r->torig[i];
00452 r->ts++;
00453 }
00454 }
00455 }
00456
00460 void parse_params(int argc,char* argv[]) {
00461 int i;
00462
00463
00464 #ifdef PARSE_LONG_OPT
00465 static struct option long_options[] = {
00466 {"ipv4", 0, 0, '4'},
00467 {"ipv6", 0, 0, '6'},
00468 {"help", 0, 0, 'h'},
00469 {"ipany", 0, &family, AF_UNSPEC},
00470 {0, 0, 0, 0}
00471 };
00472
00473 while ((i = getopt_long(argc, argv, "46h", long_options, NULL)) != -1)
00474 #else
00475 while ((i = getopt(argc, argv, "46h")) != -1)
00476 #endif
00477 {
00478 switch(i) {
00479 case 0:
00480 break;
00481 case '4':
00482 family = AF_INET;
00483 break;
00484 case '6':
00485 family = AF_INET6;
00486 break;
00487 case 'h':
00488 usage_hints(NULL);
00489 default:
00490 usage_hints("unsupported optional parameter");
00491 }
00492 }
00493
00494
00495 if (argc<optind+5) short_usage_hints("not enough parameters");
00496
00497
00498 if (strcasecmp(argv[optind],"tcp")*strcasecmp(argv[optind],"udp")) short_usage_hints("incorrect protocol");
00499 tcp = strncasecmp(argv[optind++], "udp", 3);
00500
00501
00502 lport = argv[optind++];
00503
00504
00505 rhost = argv[optind++];
00506 rport = argv[optind++];
00507
00508
00509 rule=malloc((argc-optind)*sizeof(struct rule_s));
00510 rule_live=malloc((argc-optind)*sizeof(int));
00511
00512 for (i=optind;i<argc;i++) {
00513 char *fs=0, *ts=0, *cs=0;
00514 printf("[*] Parsing rule %s...\n",argv[i]);
00515 fs=strchr(argv[i],'/');
00516 if (!fs) error("missing first '/' in rule");
00517 fs++;
00518 ts=strchr(fs,'/');
00519 if (!ts) error("missing second '/' in rule");
00520 *ts=0;
00521 ts++;
00522 cs=strchr(ts,'/');
00523 if (cs) { *cs=0; cs++; }
00524 rule[rules].forig=fs;
00525 rule[rules].torig=ts;
00526 rule[rules].dir = ALL;
00527
00528 if (cs && *cs && strchr("iIoO", *cs)) {
00529 rule[rules].dir = (*cs=='i'||*cs=='I') ? IN : OUT;
00530 cs++;
00531 }
00532 if (cs && *cs)
00533 rule_live[rules]=atoi(cs); else rule_live[rules]=-1;
00534 shrink_to_binary(&rule[rules]);
00535
00536 rules++;
00537 }
00538
00539 printf("[+] Loaded %d rule%s...\n", rules, (rules > 1) ? "s" : "");
00540
00541 }
00542
00548 void bind_and_listen(int af, int tcp, const char *portstr) {
00549 int ret;
00550 struct addrinfo hints, *res, *reslist;
00551
00552 memset(&hints, '\0', sizeof(hints));
00553 hints.ai_family = af;
00554 hints.ai_flags = AI_PASSIVE;
00555 hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM;
00556
00557 if ((ret = getaddrinfo(NULL, portstr, &hints, &reslist))) {
00558 ERR("getaddrinfo(): %s\n", gai_strerror(ret));
00559 error("Impossible to resolve listening port.");
00560 }
00561
00562 for (res = reslist; res; res = res->ai_next) {
00563 int one = 1;
00564
00565 if ( (lsock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
00566 continue;
00567 setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
00568
00569
00570 one = (family == AF_UNSPEC) ? 0 : 1;
00571 if (res->ai_family == AF_INET6)
00572 if (setsockopt(lsock, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)))
00573 printf(" Failed to unset IPV6_V6ONLY: %s.\n", strerror(errno));
00574 if (bind(lsock, res->ai_addr, res->ai_addrlen) < 0) {
00575 ERR("bind(): %s", strerror(errno));
00576 close(lsock);
00577 continue;
00578 }
00579 if (tcp) {
00580 if (listen(lsock, 16) < 0) {
00581 close(lsock);
00582 continue;
00583 }
00584 } else {
00585 int one=1;
00586 setsockopt(lsock,SOL_SOCKET,SO_OOBINLINE,&one,sizeof(int));
00587 }
00588
00589 break;
00590 }
00591 freeaddrinfo(reslist);
00592 if (res == NULL)
00593 error("Listening socket failed.");
00594 }
00595
00597 char buf[MAX_BUF];
00599 char b2[MAX_BUF];
00600
00605 int sed_the_buffer(int siz, int* live, int dir) {
00606 int i=0,j=0;
00607 int newsize=0;
00608 int changes=0;
00609 int gotchange=0;
00610 for (i=0;i<siz;) {
00611 gotchange=0;
00612 for (j=0;j<rules;j++) {
00613 if (rule[j].dir != ALL && rule[j].dir !=dir) continue;
00614
00615 if ((!memcmp(&buf[i],rule[j].from,rule[j].fs)) && (live[j]!=0)) {
00616 changes++;
00617 gotchange=1;
00618 printf(" Applying rule s/%s/%s...\n",rule[j].forig,rule[j].torig);
00619 live[j]--;
00620 if (live[j]==0) printf(" (rule just expired)\n");
00621 memcpy(&b2[newsize],rule[j].to,rule[j].ts);
00622 newsize+=rule[j].ts;
00623 i+=rule[j].fs;
00624 break;
00625 }
00626 }
00627 if (!gotchange) {
00628 b2[newsize]=buf[i];
00629 newsize++;
00630 i++;
00631 }
00632 }
00633 if (!changes) printf("[*] Forwarding untouched packet of size %d.\n",siz);
00634 else printf("[*] Done %d replacements, forwarding packet of size %d (orig %d).\n",
00635 changes,newsize,siz);
00636 return newsize;
00637 }
00638
00639
00640
00641
00642 void b2server_sed(struct tracker_s * conn, ssize_t rd);
00643
00647 void server2client_sed(struct tracker_s * conn) {
00648 ssize_t rd;
00649 rd=read(conn->fsock,buf,sizeof(buf));
00650 if ((rd<0) && (errno!=EAGAIN))
00651 {
00652 DBG("[!] server disconnected. (rd err) %s\n",strerror(errno));
00653 conn->state = DISCONNECTED;
00654 }
00655 if (rd == 0) {
00656
00657 DBG("[!] server disconnected. (rd)\n");
00658 conn->state = DISCONNECTED;
00659 }
00660 if (rd>0) {
00661 printf("[+] Caught server -> client packet.\n");
00662 rd=sed_the_buffer(rd, conn->live, IN);
00663 conn->time = now;
00664 conn->state = ESTABLISHED;
00665 if (sendto(conn->csock,b2,rd,0,conn->csa, conn->csl)<=0) {
00666 DBG("[!] client disconnected. (wr)\n");
00667 conn->state = DISCONNECTED;
00668 }
00669 }
00670 }
00671
00674 void client2server_sed(struct tracker_s * conn) {
00675 ssize_t rd;
00676 rd=read(conn->csock,buf,sizeof(buf));
00677 if ((rd<0) && (errno!=EAGAIN))
00678 {
00679 DBG("[!] client disconnected. (rd err)\n");
00680 conn->state = DISCONNECTED;
00681 }
00682 if (rd == 0) {
00683
00684 DBG("[!] client disconnected. (rd)\n");
00685 conn->state = DISCONNECTED;
00686 }
00687 b2server_sed(conn, rd);
00688 }
00689
00693 void b2server_sed(struct tracker_s * conn, ssize_t rd) {
00694 if (rd>0) {
00695 printf("[+] Caught client -> server packet.\n");
00696 rd=sed_the_buffer(rd, conn->live, OUT);
00697 conn->time = now;
00698 if (write(conn->fsock,b2,rd)<=0) {
00699 DBG("[!] server disconnected. (wr)\n");
00700 conn->state = DISCONNECTED;
00701 }
00702 }
00703 }
00704
00706 void sig_int(int signo)
00707 {
00708 DBG("[!] user interrupt request (%d)\n",getpid());
00709 stop = 1;
00710 }
00711
00713 int main(int argc,char* argv[]) {
00714 int ret;
00715 in_port_t fixedport = 0;
00716 struct sockaddr_storage fixedhost;
00717 struct addrinfo hints, *res, *reslist;
00718 struct tracker_s * conn;
00719
00720 memset(&fixedhost, '\0', sizeof(fixedhost));
00721 printf("netsed " VERSION " by Julien VdG <julien@silicone.homelinux.org>\n"
00722 " based on 0.01c from Michal Zalewski <lcamtuf@ids.pl>\n");
00723 setbuffer(stdout,NULL,0);
00724
00725 parse_params(argc, argv);
00726
00727 memset(&hints, '\0', sizeof(hints));
00728 hints.ai_family = family;
00729 hints.ai_flags = AI_CANONNAME;
00730 hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM;
00731
00732 if ((ret = getaddrinfo(rhost, rport, &hints, &reslist))) {
00733 ERR("getaddrinfo(): %s\n", gai_strerror(ret));
00734 error("Impossible to resolve remote address or port.");
00735 }
00736
00737 for (res = reslist; res; res = res->ai_next) {
00738 int sd = -1;
00739
00740 if ( (sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
00741 continue;
00742
00743
00744 fixedport = get_port(res->ai_addr);
00745 if (!is_addr_any(res->ai_addr))
00746 memcpy(&fixedhost, res->ai_addr, res->ai_addrlen);
00747 close(sd);
00748 break;
00749 }
00750 freeaddrinfo(reslist);
00751 if (res == NULL)
00752 error("Failed in resolving remote host.");
00753
00754 if (fixedhost.ss_family && fixedport)
00755 printf("[+] Using fixed forwarding to %s,%s.\n",rhost,rport);
00756 else if (fixedport)
00757 printf("[+] Using dynamic (transparent proxy) forwarding with fixed port %s.\n",rport);
00758 else if (fixedhost.ss_family)
00759 printf("[+] Using dynamic (transparent proxy) forwarding with fixed addr %s.\n",rhost);
00760 else
00761 printf("[+] Using dynamic (transparent proxy) forwarding.\n");
00762
00763 bind_and_listen(fixedhost.ss_family, tcp, lport);
00764
00765 printf("[+] Listening on port %s/%s.\n", lport, (tcp)?"tcp":"udp");
00766
00767 signal(SIGPIPE, SIG_IGN);
00768 struct sigaction sa;
00769 sa.sa_flags = 0;
00770 sigemptyset(&sa.sa_mask);
00771 sa.sa_handler = sig_int;
00772 if (sigaction(SIGINT, &sa, NULL) == -1) error("netsed: sigaction() failed");
00773
00774 while (!stop) {
00775 struct sockaddr_storage s;
00776 socklen_t l = sizeof(s);
00777 struct sockaddr_storage conho;
00778 in_port_t conpo;
00779 char ipstr[INET6_ADDRSTRLEN], portstr[12];
00780
00781 int sel;
00782 fd_set rd_set;
00783 struct timeval timeout, *ptimeout;
00784 int nfds = lsock;
00785 FD_ZERO(&rd_set);
00786 FD_SET(lsock,&rd_set);
00787 timeout.tv_sec = UDP_TIMEOUT+1;
00788 timeout.tv_usec = 0;
00789 ptimeout = NULL;
00790
00791 {
00792 conn = connections;
00793 while(conn != NULL) {
00794 if(tcp) {
00795 FD_SET(conn->csock, &rd_set);
00796 if (nfds < conn->csock) nfds = conn->csock;
00797 } else {
00798
00799 int remain = UDP_TIMEOUT - (now - conn->time);
00800 if (remain < 0) remain = 0;
00801 if (timeout.tv_sec > remain) {
00802 timeout.tv_sec = remain;
00803
00804 ptimeout = &timeout;
00805 }
00806 }
00807 FD_SET(conn->fsock, &rd_set);
00808 if (nfds < conn->fsock) nfds = conn->fsock;
00809
00810 conn = conn->n;
00811 }
00812 }
00813
00814 sel=select(nfds+1, &rd_set, (fd_set*)0, (fd_set*)0, ptimeout);
00815 time(&now);
00816 if (stop)
00817 {
00818 break;
00819 }
00820 if (sel < 0) {
00821 DBG("[!] select fail! %s\n", strerror(errno));
00822 break;
00823 }
00824 if (sel == 0) {
00825 DBG("[*] select timeout. now: %d\n", now);
00826
00827
00828
00829 }
00830
00831 if (FD_ISSET(lsock, &rd_set)) {
00832 int csock=-1;
00833 ssize_t rd=-1;
00834 if (tcp) {
00835 csock = accept(lsock,(struct sockaddr*)&s,&l);
00836 } else {
00837
00838
00839
00840 rd = recvfrom(lsock,buf,sizeof(buf),0,(struct sockaddr*)&s,&l);
00841 if(rd >= 0) {
00842 conn = connections;
00843 while(conn != NULL) {
00844
00845 if ((conn->csl == l) && (0 == memcmp(&s, conn->csa, l))) {
00846
00847 break;
00848 }
00849
00850 conn = conn->n;
00851 }
00852
00853 if(conn == NULL) {
00854
00855 csock = lsock;
00856 } else {
00857 DBG("[+] Got incoming datagram from existing connection.\n");
00858 }
00859 } else {
00860 ERR("recvfrom(): %s", strerror(errno));
00861 }
00862 }
00863
00864
00865 if ((csock)>=0) {
00866 int one=1;
00867 getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr),
00868 portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
00869 printf("[+] Got incoming connection from %s,%s", ipstr, portstr);
00870 conn = malloc(sizeof(struct tracker_s));
00871 if(NULL == conn) error("netsed: unable to malloc() connection tracker struct");
00872
00873 if (tcp) {
00874 setsockopt(csock,SOL_SOCKET,SO_OOBINLINE,&one,sizeof(int));
00875 conn->csa = NULL;
00876 conn->csl = 0;
00877 conn->state = ESTABLISHED;
00878 } else {
00879 conn->csa = malloc(l);
00880 if(NULL == conn->csa) error("netsed: unable to malloc() connection tracker sockaddr struct");
00881 memcpy(conn->csa, &s, l);
00882 conn->csl = l;
00883 conn->state = UNREPLIED;
00884 }
00885 conn->csock = csock;
00886 conn->time = now;
00887
00888 conn->live = malloc(rules*sizeof(int));
00889 if(NULL == conn->live) error("netsed: unable to malloc() connection tracker sockaddr struct");
00890 memcpy(conn->live, rule_live, rules*sizeof(int));
00891
00892 l = sizeof(s);
00893 #ifndef LINUX_NETFILTER
00894
00895 getsockname(csock,(struct sockaddr*)&s,&l);
00896 #else
00897
00898 getsockopt(csock, SOL_IP, SO_ORIGINAL_DST,(struct sockaddr*)&s,&l);
00899 #endif
00900 getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr),
00901 portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
00902 printf(" to %s,%s\n", ipstr, portstr);
00903 conpo = get_port((struct sockaddr *) &s);
00904
00905 memcpy(&conho, &s, sizeof(conho));
00906
00907 if (fixedport) conpo=fixedport;
00908 if (fixedhost.ss_family)
00909 memcpy(&conho, &fixedhost, sizeof(conho));
00910
00911
00912 memcpy(&s, &conho, sizeof(s));
00913 set_port((struct sockaddr *) &s, conpo);
00914 getnameinfo((struct sockaddr *) &s, l, ipstr, sizeof(ipstr),
00915 portstr, sizeof(portstr), NI_NUMERICHOST | NI_NUMERICSERV);
00916 printf("[*] Forwarding connection to %s,%s\n", ipstr, portstr);
00917
00918
00919 conn->fsock = socket(s.ss_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
00920
00921 if (connect(conn->fsock,(struct sockaddr*)&s,l)) {
00922 printf("[!] Cannot connect to remote server, dropping connection.\n");
00923 freetracker(conn);
00924 conn = NULL;
00925 } else {
00926 setsockopt(conn->fsock,SOL_SOCKET,SO_OOBINLINE,&one,sizeof(int));
00927 conn->n = connections;
00928 connections = conn;
00929 }
00930 }
00931
00932 if((rd >= 0) && (conn != NULL)) {
00933 b2server_sed(conn, rd);
00934 }
00935 }
00936
00937 conn = connections;
00938 struct tracker_s ** pconn = &connections;
00939 while(conn != NULL) {
00940
00941 if(tcp && FD_ISSET(conn->csock, &rd_set)) {
00942 client2server_sed(conn);
00943 }
00944 if(FD_ISSET(conn->fsock, &rd_set)) {
00945 server2client_sed(conn);
00946 }
00947
00948 DBG("[!] connection last time: %d, now: %d\n", conn->time, now);
00949 if(!tcp && ((now - conn->time) >= UDP_TIMEOUT)) {
00950 DBG("[!] connection timeout.\n");
00951 conn->state = TIMEOUT;
00952 }
00953 if(conn->state >= DISCONNECTED) {
00954
00955 (*pconn)=conn->n;
00956 freetracker(conn);
00957 conn=(*pconn);
00958 } else {
00959
00960 pconn = &(conn->n);
00961 conn = conn->n;
00962 }
00963 }
00964 }
00965
00966 clean_socks();
00967 exit(0);
00968 }
00969
00970