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>
35 time_t last_dns_expire = 0;
36 extern HASH_TABLE *dns_cache;
37 extern char username[];
38 SOCKLIST socklist[MAXLISTENPORTS];
39 pthread_mutex_t dns_cache_lock = PTHREAD_MUTEX_INITIALIZER;
42 initialize the socket list
48 for (i = 0; i < MAXLISTENPORTS; i++) {
49 socklist[i].status = NET_UNUSED;
50 socklist[i].ip = NULL;
56 open a listening socket on a specific port and ip
58 int net_listen(int port, char *ip)
60 int i, x = -1, on = 1;
61 struct sockaddr_in saddr;
63 for (i = 0; i < MAXLISTENPORTS; i++) {
64 if (socklist[i].status == NET_UNUSED) {
73 socklist[x].fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
74 if (socklist[x].fd == -1)
77 /* this allows the proxy to successfully bind to the socket again when the server is restarted,
78 otherwise it would have to wait for all connections is TIME_WAIT to be cleaned up */
79 setsockopt(socklist[x].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
81 /* TCP_NODELAY prevents the kernel from buffering the socket, which is only useful for interactive
82 connections such as telnet or ssh */
83 setsockopt(socklist[x].fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
85 fcntl(socklist[x].fd, F_SETFL, FD_CLOEXEC);
87 memset(&saddr, 0, sizeof(struct sockaddr_in));
89 saddr.sin_family = AF_INET;
90 saddr.sin_port = htons(port);
93 saddr.sin_addr.s_addr = INADDR_ANY;
95 saddr.sin_addr.s_addr = inet_addr(ip);
97 i = bind(socklist[x].fd, (struct sockaddr *) &saddr, sizeof(saddr));
99 close(socklist[x].fd);
103 i = listen(socklist[x].fd, 25);
105 close(socklist[x].fd);
110 socklist[x].ip = xstrdup(ip);
112 socklist[x].ip = NULL;
114 socklist[x].port = port;
115 socklist[x].status = NET_LISTEN;
121 poll on every open listening socket in socklist until timeout is reached (or forever if
122 timeout is -1), accept then return a pointer to a CONNECTION struct
124 CONNECTION *net_accept(int timeout)
126 int i, x = 0, j, newfd;
127 struct sockaddr_in saddr;
128 unsigned int sl = sizeof(struct sockaddr);
129 CONNECTION *connection;
130 struct pollfd pfd[MAXLISTENPORTS];
132 for (i = 0; i < MAXLISTENPORTS; i++) {
133 if (socklist[i].status == NET_LISTEN) {
134 pfd[x].fd = socklist[i].fd;
135 pfd[x].events = POLLIN;
141 j = p_poll(pfd, x, (timeout != -1) ? timeout * 1000 : -1);
144 for (i = 0; i < MAXLISTENPORTS; i++) {
145 if (pfd[i].revents & POLLIN) {
146 newfd = accept(socklist[i].fd, (struct sockaddr *) &saddr, &sl);
151 connection = xmalloc(sizeof(CONNECTION));
153 connection->client = sock_new(newfd);
154 connection->server = NULL;
155 connection->port = socklist[i].port;
156 connection->ip = xstrdup(inet_ntoa(saddr.sin_addr));
157 connection->buffer = FALSE;
158 connection->site_host = NULL;
159 connection->site_port = -1;
160 connection->bypass = connection->obypass = 0;
161 connection->header = NULL;
162 connection->rheader = NULL;
163 connection->keepalive_client = FALSE;
164 connection->keepalive_server = FALSE;
165 connection->request = FALSE;
166 connection->proxy_host = NULL;
167 connection->proxy_type = PROXY_DIRECT;
168 connection->proxy_username = NULL;
169 connection->proxy_password = NULL;
170 connection->proxy_domain = NULL;
171 connection->proxy_auth = NULL;
172 connection->authenticate = FALSE;
183 open a connection to somewhere and return file descriptor
185 int net_connect(char *host, int port)
187 int fd, ret, on = TRUE;
189 struct sockaddr_in saddr;
191 if (!host || port <= 0)
192 return ERROR_UNKNOWN;
194 memset(&saddr, 0, sizeof(saddr));
196 hostent = net_dns(host);
200 saddr.sin_addr = *(struct in_addr *)hostent->addr;
202 hostent_free(hostent);
204 saddr.sin_family = AF_INET;
205 saddr.sin_port = htons(port);
207 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
209 return ERROR_CONNECT;
211 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
212 fcntl(fd, F_SETFL, FD_CLOEXEC);
214 ret = connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
218 return ERROR_CONNECT;
225 close a connection and free used memory from structure
227 void net_close(CONNECTION * connection)
232 sock_close(connection->client);
234 FREE_AND_NULL(connection->ip);
235 FREE_AND_NULL(connection->proxy_host);
236 FREE_AND_NULL(connection->proxy_username);
237 FREE_AND_NULL(connection->proxy_password);
238 FREE_AND_NULL(connection->proxy_domain);
239 FREE_AND_NULL(connection->proxy_auth);
240 FREE_AND_NULL(connection->site_host);
246 close all open listening sockets
248 void net_listen_closeall()
252 for (i = 0; i < MAXLISTENPORTS; i++) {
253 if (socklist[i].status == NET_LISTEN) {
254 close(socklist[i].fd);
255 if (socklist[i].ip != NULL)
256 xfree(socklist[i].ip);
257 socklist[i].status = NET_UNUSED;
263 load <network> section from XML_LIST
265 NETWORK *network_load(NETWORK * network, XML_LIST * xml_list)
267 NETWORK *network_tmp = network;
268 struct LISTEN_LIST *listen_list = NULL;
270 if (network_tmp == NULL) {
271 network_tmp = xmalloc(sizeof(NETWORK));
272 network_tmp->listen_list = NULL;
275 network = network_tmp;
277 pthread_rwlock_init(&network_tmp->lock, NULL);
279 listen_list = network->listen_list;
281 while ((xml_list = xml_section(xml_list, "<network>"))) {
282 XML_LIST_LOOP(xml_list, "<network>") {
283 XML_LIST_CMP(xml_list, "<listen>") {
284 listen_list = listen_list_new(listen_list);
285 listen_list->id = network->id++;
287 if (network_tmp->listen_list == NULL)
288 network_tmp->listen_list = listen_list;
289 XML_LIST_LOOP(xml_list, "<listen>") {
290 XML_LIST_CMP(xml_list, "<ip>") {
291 xml_list = xml_list->next;
292 if (xml_list->type == XML_VALUE)
293 listen_list_insert(listen_list, xml_list->item, NULL);
295 XML_LIST_CMP(xml_list, "<port>") {
296 xml_list = xml_list->next;
297 if (xml_list->type == XML_VALUE)
298 listen_list_insert(listen_list, NULL, xml_list->item);
308 XML_LIST *network_xml(NETWORK * network, XML_LIST * xml_list)
311 struct LISTEN_LIST *ll;
316 pthread_rwlock_rdlock(&network->lock);
318 xml_list = xml_list_add(xml_list, "<network>", XML_TAG);
320 ll = network->listen_list;
322 for (ll = network->listen_list; ll; ll = ll->next) {
323 xml_list = xml_list_add(xml_list, "<listen>", XML_TAG);
325 xml_list = xml_list_add(xml_list, "<port>", XML_TAG);
326 snprintf(buf, sizeof(buf), "%d", ll->port);
327 xml_list = xml_list_add(xml_list, buf, XML_VALUE);
328 xml_list = xml_list_add(xml_list, "</port>", XML_TAG);
330 if (ll->ip != NULL) {
331 xml_list = xml_list_add(xml_list, "<ip>", XML_TAG);
332 ptr = string_to_xml(ll->ip);
333 xml_list = xml_list_add(xml_list, ptr, XML_VALUE);
335 xml_list = xml_list_add(xml_list, "</ip>", XML_TAG);
338 xml_list = xml_list_add(xml_list, "</listen>", XML_TAG);
341 xml_list = xml_list_add(xml_list, "</network>", XML_TAG);
343 pthread_rwlock_unlock(&network->lock);
347 void listen_list_insert(struct LISTEN_LIST *x, char *a, char *b)
350 FREE_AND_NULL(x->ip);
359 struct LISTEN_LIST *listen_list_delete(struct LISTEN_LIST *x)
361 struct LISTEN_LIST *start = x;
363 while (start->prev != NULL)
367 x->next->prev = x->prev;
369 x->prev->next = x->next;
373 FREE_AND_NULL(x->ip);
374 FREE_AND_NULL(x->proxy);
381 struct LISTEN_LIST *listen_list_new(struct LISTEN_LIST *x)
384 x = xmalloc(sizeof(struct LISTEN_LIST));
387 while (x->next != NULL)
389 x->next = xmalloc(sizeof(struct LISTEN_LIST));
401 free memory allocated by network_load
403 void network_free(NETWORK * network)
405 struct LISTEN_LIST *listen_list, *tmp_list;
410 listen_list = network->listen_list;
412 while (listen_list != NULL) {
413 tmp_list = listen_list->next;
414 if (listen_list->ip != NULL)
415 xfree(listen_list->ip);
416 if (listen_list->proxy != NULL)
417 xfree(listen_list->proxy);
419 listen_list = tmp_list;
422 pthread_rwlock_destroy(&network->lock);
428 look through network->listen_list linked list and bind to listening ports
430 void network_check(NETWORK * network)
433 struct LISTEN_LIST *listen_list;
438 listen_list = network->listen_list;
440 pthread_rwlock_rdlock(&network->lock);
442 while (listen_list != NULL) {
443 if (listen_list->port != -1) {
444 ret = net_listen(listen_list->port, listen_list->ip);
447 putlog(MMLOG_NETWORK, "listening on %s:%d", (listen_list->ip != NULL) ? listen_list->ip : "0.0.0.0", listen_list->port);
449 putlog(MMLOG_NETWORK, "failed to bind to %s:%d", (listen_list->ip != NULL) ? listen_list->ip : "0.0.0.0", listen_list->port);
452 listen_list = listen_list->next;
455 pthread_rwlock_unlock(&network->lock);
459 relay anything from one socket to another, and vice versa
461 int net_proxy(CONNECTION * connection, int len)
465 struct pollfd pfd[2];
466 SOCKET *sock1, *sock2;
468 sock1 = connection->client;
469 sock2 = connection->server;
471 pfd[0].fd = sock1->fd;
472 pfd[0].events = POLLIN;
473 pfd[1].fd = sock2->fd;
474 pfd[1].events = POLLIN;
477 x = p_poll(pfd, 2, (sock1->inbuf_len != 0 || sock2->inbuf_len != 0) ? 0 : -1);
478 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
479 x = sock_read(sock1, buf, (len != -1) ? (len - bytes < sizeof(buf)) ? len - bytes : sizeof(buf) : sizeof(buf));
481 sock_write(sock2, buf, x);
486 } else if (pfd[0].revents & (POLLHUP | POLLERR))
489 if (sock1->inbuf_len != 0 || pfd[1].revents & POLLIN) {
490 x = sock_read(sock2, buf, (len != -1) ? (len - bytes < sizeof(buf)) ? len - bytes : sizeof(buf) : sizeof(buf));
492 sock_write(sock1, buf, x);
497 } else if (pfd[1].revents & (POLLHUP | POLLERR))
500 if (len != -1 && bytes == len)
508 tranfer data one way between two sockets
510 int net_transfer(CONNECTION * connection, int flags, int bytes)
514 struct pollfd pfd[2];
515 SOCKET *sock1, *sock2;
517 sock1 = (flags == SERVER) ? connection->server : connection->client;
518 sock2 = (flags == SERVER) ? connection->client : connection->server;
520 pfd[0].fd = sock1->fd;
521 pfd[0].events = POLLIN;
522 pfd[1].fd = sock2->fd;
523 pfd[1].events = POLLIN;
525 while (bytes == -1 || bytes > 0) {
526 x = p_poll(pfd, 2, (sock1->inbuf_len != 0) ? 0 : -1);
527 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
528 x = sock_read(sock1, buf, (bytes != -1) ? (bytes < sizeof(buf)) ? bytes : sizeof(buf) : sizeof(buf));
534 x = sock_write(sock2, buf, x);
539 } else if (pfd[0].revents & (POLLHUP | POLLERR))
542 if (pfd[1].revents & POLLIN) {
543 x = sock_read(sock2, NULL, -1);
546 } else if (pfd[1].revents & (POLLHUP | POLLERR))
553 int putsock(SOCKET * sock, char *format, ...)
558 va_start(va, format);
559 vsnprintf(buf, sizeof(buf), format, va);
562 return sock_write(sock, buf, strlen(buf));
565 void net_filebuf_read(FILEBUF * filebuf, CONNECTION * connection, int flags, int bytes)
569 struct pollfd pfd[2];
570 SOCKET *sock1, *sock2;
572 sock1 = (flags == SERVER) ? connection->server : connection->client;
573 sock2 = (flags == SERVER) ? connection->client : connection->server;
575 pfd[0].fd = sock1->fd;
576 pfd[0].events = POLLIN;
579 pfd[1].fd = sock2->fd;
580 pfd[1].events = POLLIN;
581 } else pfd[1].revents = 0;
583 while (bytes == -1 || bytes > 0) {
584 x = p_poll(pfd, (sock2 != NULL) ? 2 : 1, (sock1->inbuf_len != 0) ? 0 : -1);
585 if (sock1->inbuf_len != 0 || pfd[0].revents & POLLIN) {
586 x = sock_read(sock1, buf, (bytes != -1) ? (bytes < sizeof(buf)) ? bytes : sizeof(buf) : sizeof(buf));
588 if (filebuf != NULL) filebuf_add(filebuf, buf, x);
594 } else if (pfd[0].revents & (POLLHUP | POLLERR))
597 if (pfd[1].revents & POLLIN) {
598 x = sock_read(sock2, NULL, -1);
601 } else if (pfd[1].revents & (POLLHUP | POLLERR))
606 int net_filebuf_send(FILEBUF * filebuf, CONNECTION * connection, int flags)
610 sock = (flags == SERVER) ? connection->server : connection->client;
612 return sock_write(sock, filebuf->data, filebuf->size);
616 perform a dns lookup, using cached response from a previous lookup if possible
618 HOSTENT *net_dns(char *host)
621 char *string, hst[128], buf[24];
624 pthread_mutex_lock(&dns_cache_lock);
628 s_strncpy(hst, host, 128);
631 if (last_dns_expire == 0)
634 if (t - last_dns_expire >= DNS_EXPIRE) {
635 putlog(MMLOG_DEBUG, "dns cache expire: entry > %d seconds", DNS_EXPIRE);
637 hash_expire(dns_cache, DNS_EXPIRE);
642 hostent = xmalloc(sizeof(HOSTENT));
643 hostent->addr = xmalloc(sizeof(struct in_addr));
644 hostent->len = sizeof(struct in_addr);
646 inet_aton(host, hostent->addr);
648 string = hash_search(dns_cache, hst);
649 if (string == NULL) {
650 pthread_mutex_unlock(&dns_cache_lock);
652 hostent = p_gethostbyname(host);
656 pthread_mutex_lock(&dns_cache_lock);
658 s_strncpy(buf, inet_ntoa(*hostent->addr), sizeof(buf));
660 hash_insert(dns_cache, hst, xstrdup(buf));
662 putlog(MMLOG_DEBUG, "dns cache insert: %s -> %s", hst, buf);
664 putlog(MMLOG_DEBUG, "dns cache hit: %s -> %s", hst, string);
666 hostent = xmalloc(sizeof(HOSTENT));
667 hostent->addr = xmalloc(sizeof(struct in_addr));
668 hostent->len = sizeof(struct in_addr);
670 inet_aton(string, hostent->addr);
674 pthread_mutex_unlock(&dns_cache_lock);
680 connect through socks4 server
682 int net_socks4(CONNECTION * connection, char *host, int port)
688 hostent = net_dns(host);
692 ret = snprintf(buf, sizeof(buf), "\004\001%c%c%c%c%c%c%s", (port >> 8) % 256, port % 256, '0', '0', '0', '0', username);
693 memcpy(&buf[4], hostent->addr, hostent->len);
695 hostent_free(hostent);
697 sock_write(connection->server, buf, ret + 1);
699 /* come on.. what are the changes we won't get the packet in one read() ? :) */
700 sock_read(connection->server, buf, 8);