2 MiddleMan filtering proxy server
3 Copyright (C) 2002 Jason McLaughlin
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netinet/tcp.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
36 time_t last_dns_expire = 0;
37 extern HASH_TABLE *dns_cache;
38 extern char username[];
39 SOCKLIST socklist[MAXLISTENPORTS];
40 pthread_mutex_t dns_cache_lock = PTHREAD_MUTEX_INITIALIZER;
43 initialize the socket list
49 for (i = 0; i < MAXLISTENPORTS; i++) {
50 socklist[i].status = NET_UNUSED;
51 socklist[i].ip = NULL;
57 open a listening socket on a specific port and ip
59 int net_listen(int port, char *ip)
61 int i, x = -1, on = 1;
62 struct sockaddr_in saddr;
64 for (i = 0; i < MAXLISTENPORTS; i++) {
65 if (socklist[i].status == NET_UNUSED) {
74 socklist[x].fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
75 if (socklist[x].fd == -1)
78 /* this allows the proxy to successfully bind to the socket again when the server is restarted,
79 otherwise it would have to wait for all connections is TIME_WAIT to be cleaned up */
80 setsockopt(socklist[x].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
82 /* TCP_NODELAY prevents the kernel from buffering the socket, which is only useful for interactive
83 connections such as telnet or ssh */
84 setsockopt(socklist[x].fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
86 fcntl(socklist[x].fd, F_SETFL, FD_CLOEXEC);
88 memset(&saddr, 0, sizeof(struct sockaddr_in));
90 saddr.sin_family = AF_INET;
91 saddr.sin_port = htons(port);
94 saddr.sin_addr.s_addr = INADDR_ANY;
96 saddr.sin_addr.s_addr = inet_addr(ip);
98 i = bind(socklist[x].fd, (struct sockaddr *) &saddr, sizeof(saddr));
100 close(socklist[x].fd);
104 i = listen(socklist[x].fd, 25);
106 close(socklist[x].fd);
111 socklist[x].ip = xstrdup(ip);
113 socklist[x].ip = NULL;
115 socklist[x].port = port;
116 socklist[x].status = NET_LISTEN;
122 poll on every open listening socket in socklist until timeout is reached (or forever if
123 timeout is -1), accept then return a pointer to a CONNECTION struct
125 CONNECTION *net_accept(int timeout)
127 int i, x = 0, j, newfd;
128 struct sockaddr_in saddr;
129 unsigned int sl = sizeof(struct sockaddr);
130 CONNECTION *connection;
131 struct pollfd pfd[MAXLISTENPORTS];
133 for (i = 0; i < MAXLISTENPORTS; i++) {
134 if (socklist[i].status == NET_LISTEN) {
135 pfd[x].fd = socklist[i].fd;
136 pfd[x].events = POLLIN;
142 j = p_poll(pfd, x, (timeout != -1) ? timeout * 1000 : -1);
145 for (i = 0; i < MAXLISTENPORTS; i++) {
146 if (pfd[i].revents & POLLIN) {
147 newfd = accept(socklist[i].fd, (struct sockaddr *) &saddr, &sl);
152 connection = xmalloc(sizeof(CONNECTION));
154 connection->client = sock_new(newfd);
155 connection->server = NULL;
156 connection->port = socklist[i].port;
157 connection->ip = xstrdup(inet_ntoa(saddr.sin_addr));
158 connection->buffer = FALSE;
159 connection->site_host = NULL;
160 connection->site_port = -1;
161 connection->bypass = connection->obypass = 0;
162 connection->header = NULL;
163 connection->rheader = NULL;
164 connection->keepalive_client = FALSE;
165 connection->keepalive_server = FALSE;
166 connection->request = FALSE;
167 connection->proxy_host = NULL;
168 connection->proxy_type = PROXY_DIRECT;
169 connection->proxy_username = NULL;
170 connection->proxy_password = NULL;
171 connection->proxy_domain = NULL;
172 connection->proxy_auth = NULL;
173 connection->authenticate = FALSE;
184 open a connection to somewhere and return file descriptor
186 int net_connect(char *host, int port)
188 int fd, ret, on = TRUE;
190 struct sockaddr_in saddr;
192 if (!host || port <= 0)
193 return ERROR_UNKNOWN;
195 memset(&saddr, 0, sizeof(saddr));
197 hostent = net_dns(host);
201 saddr.sin_addr = *(struct in_addr *)hostent->addr;
203 hostent_free(hostent);
205 saddr.sin_family = AF_INET;
206 saddr.sin_port = htons(port);
208 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
210 return ERROR_CONNECT;
212 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
213 fcntl(fd, F_SETFL, FD_CLOEXEC);
215 ret = connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
219 return ERROR_CONNECT;
226 close a connection and free used memory from structure
228 void net_close(CONNECTION * connection)
233 sock_close(connection->client);
235 FREE_AND_NULL(connection->ip);
236 FREE_AND_NULL(connection->proxy_host);
237 FREE_AND_NULL(connection->proxy_username);
238 FREE_AND_NULL(connection->proxy_password);
239 FREE_AND_NULL(connection->proxy_domain);
240 FREE_AND_NULL(connection->proxy_auth);
241 FREE_AND_NULL(connection->site_host);
247 close all open listening sockets
249 void net_listen_closeall()
253 for (i = 0; i < MAXLISTENPORTS; i++) {
254 if (socklist[i].status == NET_LISTEN) {
255 close(socklist[i].fd);
256 if (socklist[i].ip != NULL)
257 xfree(socklist[i].ip);
258 socklist[i].status = NET_UNUSED;
264 load <network> section from XML_LIST
266 NETWORK *network_load(NETWORK * network, XML_LIST * xml_list)
268 NETWORK *network_tmp = network;
269 struct LISTEN_LIST *listen_list = NULL;
271 if (network_tmp == NULL) {
272 network_tmp = xmalloc(sizeof(NETWORK));
273 network_tmp->listen_list = NULL;
276 network = network_tmp;
278 pthread_rwlock_init(&network_tmp->lock, NULL);
280 listen_list = network->listen_list;
282 while ((xml_list = xml_section(xml_list, "<network>"))) {
283 XML_LIST_LOOP(xml_list, "<network>") {
284 XML_LIST_CMP(xml_list, "<listen>") {
285 listen_list = listen_list_new(listen_list);
286 listen_list->id = network->id++;
288 if (network_tmp->listen_list == NULL)
289 network_tmp->listen_list = listen_list;
290 XML_LIST_LOOP(xml_list, "<listen>") {
291 XML_LIST_CMP(xml_list, "<ip>") {
292 xml_list = xml_list->next;
293 if (xml_list->type == XML_VALUE)
294 listen_list_insert(listen_list, xml_list->item, NULL);
296 XML_LIST_CMP(xml_list, "<port>") {
297 xml_list = xml_list->next;
298 if (xml_list->type == XML_VALUE)
299 listen_list_insert(listen_list, NULL, xml_list->item);
309 XML_LIST *network_xml(NETWORK * network, XML_LIST * xml_list)
312 struct LISTEN_LIST *ll;
317 pthread_rwlock_rdlock(&network->lock);
319 xml_list = xml_list_add(xml_list, "<network>", XML_TAG);
321 ll = network->listen_list;
323 for (ll = network->listen_list; ll; ll = ll->next) {
324 xml_list = xml_list_add(xml_list, "<listen>", XML_TAG);
326 xml_list = xml_list_add(xml_list, "<port>", XML_TAG);
327 snprintf(buf, sizeof(buf), "%d", ll->port);
328 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
329 xml_list = xml_list_add(xml_list, "</port>", XML_TAG);
331 if (ll->ip != NULL) {
332 xml_list = xml_list_add(xml_list, "<ip>", XML_TAG);
333 ptr = string_to_xml(ll->ip);
334 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
336 xml_list = xml_list_add(xml_list, "</ip>", XML_TAG);
339 xml_list = xml_list_add(xml_list, "</listen>", XML_TAG);
342 xml_list = xml_list_add(xml_list, "</network>", XML_TAG);
344 pthread_rwlock_unlock(&network->lock);
348 void listen_list_insert(struct LISTEN_LIST *x, char *a, char *b)
351 FREE_AND_NULL(x->ip);
360 struct LISTEN_LIST *listen_list_delete(struct LISTEN_LIST *x)
362 struct LISTEN_LIST *start = x;
364 while (start->prev != NULL)
368 x->next->prev = x->prev;
370 x->prev->next = x->next;
374 FREE_AND_NULL(x->ip);
375 FREE_AND_NULL(x->proxy);
382 struct LISTEN_LIST *listen_list_new(struct LISTEN_LIST *x)
385 x = xmalloc(sizeof(struct LISTEN_LIST));
388 while (x->next != NULL)
390 x->next = xmalloc(sizeof(struct LISTEN_LIST));
402 free memory allocated by network_load
404 void network_free(NETWORK * network)
406 struct LISTEN_LIST *listen_list, *tmp_list;
411 listen_list = network->listen_list;
413 while (listen_list != NULL) {
414 tmp_list = listen_list->next;
415 if (listen_list->ip != NULL)
416 xfree(listen_list->ip);
417 if (listen_list->proxy != NULL)
418 xfree(listen_list->proxy);
420 listen_list = tmp_list;
423 pthread_rwlock_destroy(&network->lock);
429 look through network->listen_list linked list and bind to listening ports
431 void network_check(NETWORK * network)
434 struct LISTEN_LIST *listen_list;
439 listen_list = network->listen_list;
441 pthread_rwlock_rdlock(&network->lock);
443 while (listen_list != NULL) {
444 if (listen_list->port != -1) {
445 ret = net_listen(listen_list->port, listen_list->ip);
448 putlog(MMLOG_NETWORK, "listening on %s:%d", (listen_list->ip != NULL) ? listen_list->ip : "0.0.0.0", listen_list->port);
450 putlog(MMLOG_NETWORK, "failed to bind to %s:%d", (listen_list->ip != NULL) ? listen_list->ip : "0.0.0.0", listen_list->port);
453 listen_list = listen_list->next;
456 pthread_rwlock_unlock(&network->lock);
460 relay anything from one socket to another, and vice versa
462 int net_proxy(CONNECTION * connection, int len)
466 struct pollfd pfd[2];
467 SOCKET *sock1, *sock2;
469 sock1 = connection->client;
470 sock2 = connection->server;
472 pfd[0].fd = sock1->fd;
473 pfd[0].events = POLLIN;
474 pfd[1].fd = sock2->fd;
475 pfd[1].events = POLLIN;
478 x = p_poll(pfd, 2, (sock1->inbuf_len != 0 || sock2->inbuf_len != 0) ? 0 : -1);
479 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
480 x = sock_read(sock1, buf, (len != -1) ? (len - bytes < sizeof(buf)) ? len - bytes : sizeof(buf) : sizeof(buf));
482 sock_write(sock2, buf, x);
487 } else if (pfd[0].revents & (POLLHUP | POLLERR))
490 if (sock1->inbuf_len != 0 || pfd[1].revents & POLLIN) {
491 x = sock_read(sock2, buf, (len != -1) ? (len - bytes < sizeof(buf)) ? len - bytes : sizeof(buf) : sizeof(buf));
493 sock_write(sock1, buf, x);
498 } else if (pfd[1].revents & (POLLHUP | POLLERR))
501 if (len != -1 && bytes == len)
509 tranfer data one way between two sockets
511 int net_transfer(CONNECTION * connection, int flags, int bytes)
515 struct pollfd pfd[2];
516 SOCKET *sock1, *sock2;
518 sock1 = (flags == SERVER) ? connection->server : connection->client;
519 sock2 = (flags == SERVER) ? connection->client : connection->server;
521 pfd[0].fd = sock1->fd;
522 pfd[0].events = POLLIN;
523 pfd[1].fd = sock2->fd;
524 pfd[1].events = POLLIN;
526 while (bytes == -1 || bytes > 0) {
527 x = p_poll(pfd, 2, (sock1->inbuf_len != 0) ? 0 : -1);
528 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
529 x = sock_read(sock1, buf, (bytes != -1) ? (bytes < sizeof(buf)) ? bytes : sizeof(buf) : sizeof(buf));
535 x = sock_write(sock2, buf, x);
540 } else if (pfd[0].revents & (POLLHUP | POLLERR))
543 if (pfd[1].revents & POLLIN) {
544 x = sock_read(sock2, NULL, -1);
547 } else if (pfd[1].revents & (POLLHUP | POLLERR))
554 int putsock(SOCKET * sock, char *format, ...)
559 va_start(va, format);
560 vsnprintf(buf, sizeof(buf), format, va);
563 return sock_write(sock, buf, strlen(buf));
566 void net_filebuf_read(FILEBUF * filebuf, CONNECTION * connection, int flags, int bytes)
570 struct pollfd pfd[2];
571 SOCKET *sock1, *sock2;
573 sock1 = (flags == SERVER) ? connection->server : connection->client;
574 sock2 = (flags == SERVER) ? connection->client : connection->server;
576 pfd[0].fd = sock1->fd;
577 pfd[0].events = POLLIN;
580 pfd[1].fd = sock2->fd;
581 pfd[1].events = POLLIN;
582 } else pfd[1].revents = 0;
584 while (bytes == -1 || bytes > 0) {
585 x = p_poll(pfd, (sock2 != NULL) ? 2 : 1, (sock1->inbuf_len != 0) ? 0 : -1);
586 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
587 x = sock_read(sock1, buf, (bytes != -1) ? (bytes < sizeof(buf)) ? bytes : sizeof(buf) : sizeof(buf));
589 if (filebuf != NULL) filebuf_add(filebuf, buf, x);
595 } else if (pfd[0].revents & (POLLHUP | POLLERR))
598 if (pfd[1].revents & POLLIN) {
599 x = sock_read(sock2, NULL, -1);
602 } else if (pfd[1].revents & (POLLHUP | POLLERR))
607 int net_filebuf_send(FILEBUF * filebuf, CONNECTION * connection, int flags)
611 sock = (flags == SERVER) ? connection->server : connection->client;
613 return sock_write(sock, filebuf->data, filebuf->size);
617 perform a dns lookup, using cached response from a previous lookup if possible
619 HOSTENT *net_dns(char *host)
622 char *string, hst[128], buf[24];
625 pthread_mutex_lock(&dns_cache_lock);
629 s_strncpy(hst, host, 128);
632 if (last_dns_expire == 0)
635 if (t - last_dns_expire >= DNS_EXPIRE) {
636 putlog(MMLOG_DEBUG, "dns cache expire: entry > %d seconds", DNS_EXPIRE);
638 hash_expire(dns_cache, DNS_EXPIRE);
643 hostent = xmalloc(sizeof(HOSTENT));
644 hostent->addr = xmalloc(sizeof(struct in_addr));
645 hostent->len = sizeof(struct in_addr);
647 inet_aton(host, hostent->addr);
649 string = hash_search(dns_cache, hst);
650 if (string == NULL) {
651 pthread_mutex_unlock(&dns_cache_lock);
653 hostent = p_gethostbyname(host);
657 pthread_mutex_lock(&dns_cache_lock);
659 s_strncpy(buf, inet_ntoa(*hostent->addr), sizeof(buf));
661 hash_insert(dns_cache, hst, xstrdup(buf));
663 putlog(MMLOG_DEBUG, "dns cache insert: %s -> %s", hst, buf);
665 putlog(MMLOG_DEBUG, "dns cache hit: %s -> %s", hst, string);
667 hostent = xmalloc(sizeof(HOSTENT));
668 hostent->addr = xmalloc(sizeof(struct in_addr));
669 hostent->len = sizeof(struct in_addr);
671 inet_aton(string, hostent->addr);
675 pthread_mutex_unlock(&dns_cache_lock);
681 connect through socks4 server
683 int net_socks4(CONNECTION * connection, char *host, int port)
689 hostent = net_dns(host);
693 ret = snprintf(buf, sizeof(buf), "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, port % 256, '0', '0', '0', '0', username);
694 memcpy(&buf[4], hostent->addr, hostent->len);
696 hostent_free(hostent);
698 sock_write(connection->server, buf, ret + 1);
700 /* come on.. what are the changes we won't get the packet in one read() ? :) */
701 sock_read(connection->server, buf, 8);