ebuild for ypd-3
[ypd.git] / src / session.c
blob092f5458cfbf8d7bbc6ff64aef85200b7d82ca27
1 //
2 // C Implementation: session
3 //
4 // Description:
5 //
6 //
7 // Author: Felix Bechstein <f@ub0r.de>, (C) 2007
8 //
9 // Copyright: See COPYING file that comes with this distribution
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
19 #include <netdb.h>
20 #include <unistd.h>
21 #include <sys/wait.h>
23 #include "config.h"
24 #include "session.h"
26 char* host;
27 int port;
29 int port_https;
30 int port_ssh;
31 int port_hstop3g;
33 void session_get_type(int sockd, int *port, char* buffer, int buflen, int *l)
35 *port = 0; // initial value
37 int traffic_type = TYPE_UNDEFINED;
38 *l = recv(sockd, buffer, buflen, MSG_DONTWAIT); // MSG_PEEK does not work here! -> return buffer and send it to client later
40 if (*l < 0) // error occured (no data in queue)
42 // try again after a little while
43 unsigned int s = CONNECTION_TIMEOUT;
44 sleep(s);
45 *l = recv(sockd, buffer, buflen, MSG_DONTWAIT);
48 if (*l == 0) // socket is closed
49 return;
51 if (*l > 0) // data in there. so let's analyse it
53 traffic_type = DEFAULT_TRAFFIC;
55 // test for hstop3g traffic -- start
56 char HSTOP3G_PATTERN[] = {0x13,0x01,0x00,0x00,0x27};
57 int HSTOP3G_PATTERN_LEN = 5;
59 int minl = *l;
60 if (*l > HSTOP3G_PATTERN_LEN)
61 minl = HSTOP3G_PATTERN_LEN;
62 traffic_type = TYPE_HSTOP3G;
63 int i;
64 for (i = 0; i < minl; i++) {
65 if (buffer[i] != HSTOP3G_PATTERN[i])
66 traffic_type = DEFAULT_TRAFFIC;
68 // test for hstop3g traffic -- end
69 } else {
70 traffic_type = DEFAULT_NOTRAFFIC;
73 switch (traffic_type)
75 case TYPE_HTTPS:
76 printf("%d:\ttype https\n", sockd);
77 *port = port_https;
78 break;
79 case TYPE_SSH:
80 printf("%d:\ttype ssh\n", sockd);
81 *port = port_ssh;
82 break;
83 case TYPE_HSTOP3G:
84 printf("%d:\ttype hsopt-3g\n", sockd);
85 *port = port_hstop3g;
86 break;
87 default:
88 printf("%d:\ttype error!\n", sockd);
89 *port = 0;
90 break;
92 printf("%d:\tredirect to %s:%d\n", sockd, host, *port);
95 void session_forward(int sock_read, int sock_write)
97 size_t l;
98 char* buffer=(char*) malloc (BUFFSIZE);
99 while ((l = recv(sock_read, buffer, BUFFSIZE, 0)))
101 send(sock_write, buffer, l, 0);
103 free(buffer);
106 void session_start(int sockd)
108 int port;
109 int l;
110 char* buffer=(char*) malloc (BUFFSIZE);
111 session_get_type(sockd, &port, buffer, BUFFSIZE, &l);
112 int sockc = socket(AF_INET, SOCK_STREAM, 0);
113 struct sockaddr_in clientaddr;
114 clientaddr.sin_family = AF_INET;
115 clientaddr.sin_addr.s_addr = inet_addr(host);
116 clientaddr.sin_port = htons(port);
117 if (connect(sockc,(struct sockaddr *) &clientaddr, sizeof(struct sockaddr_in)) < 0)
119 perror("\nerror connecting to target\n");
120 close(sockd);
121 return;
123 if (l > 0)
124 send(sockc, buffer, l, 0);
125 int cpid;
126 if ((cpid = fork()) == 0) // child: read
128 session_forward(sockd, sockc);
129 } else {
130 session_forward(sockc, sockd);
132 shutdown(sockc, SHUT_RDWR);
133 shutdown(sockd, SHUT_RDWR);
134 wait(NULL); // wait for child above
135 close(sockc); // close sockets
136 close(sockd);
137 if (cpid)
138 printf("connection closed: %d\n", sockd);
139 free(buffer);
140 exit(EXIT_SUCCESS); // exit forked process