openbsd-ports/net/tircproxy/patches/patch-tircproxy_c
2002-04-25 07:56:00 +00:00

386 lines
10 KiB
Plaintext

--- tircproxy.c.orig Fri May 5 06:53:30 2000
+++ tircproxy.c Thu Apr 25 13:35:39 2002
@@ -119,6 +119,8 @@
#endif
#undef TRANS
+#undef RANGEDPORTS
+
#if IPF
# if HAVE_NETINET_IP_NAT_H
# include <sys/ioctl.h>
@@ -142,6 +144,15 @@
# endif
#endif
+#ifdef PF
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+#define TRANS 1
+#define RANGEDPORTS 1
+#endif
+
#ifndef LINUX
# define LINUX 0
#endif
@@ -187,6 +198,11 @@
#endif
+#ifdef RANGEDPORTS
+int min_port = IPPORT_HIFIRSTAUTO;
+int max_port = IPPORT_HILASTAUTO;
+#endif
+
/* Typedefs.
*/
@@ -213,6 +229,10 @@
static uid_t get_group_id (uid_t uid);
static int bind_to_port (ipaddr_t bind_ip, short bind_port,
int backlog, int dlev);
+#ifdef RANGEDPORTS
+static int bind_to_ranged_port (ipaddr_t bind_ip, short min_port,
+ short max_port, int backlog, int dlev);
+#endif
static int connect_to_server (struct sockaddr_in addr);
static void lookup_hostname (struct sockaddr_in *addr, char *hostname,
int hostlen, int needed);
@@ -350,8 +370,14 @@
/* Parse the command line arguments.
*/
- while ((arg = getopt(argc, argv, "ab:d:h?i:o:pq:r:s:t:CDHIKLMNOQRSU")) != EOF)
+#ifdef RANGEDPORTS
+ while ((arg = getopt(argc, argv, "ab:d:h?i:m:o:pq:r:s:t:x:CDHIKLMNOQRSU")) != EOF)
{
+ char *p;
+#else
+ while ((arg = getopt(argc, argv, "ab:d:h?i:o:pq:r:s:t:CDHIKLMNOQRSU")) != EOF)
+ {
+#endif
switch (arg)
{
@@ -375,6 +401,15 @@
case 'i':
visible_ip_i = get_ip_addr(optarg);
break;
+#ifdef RANGEDPORTS
+ case 'm':
+ min_port = strtol(optarg, &p, 10);
+ if (!*optarg || *p)
+ usage(argv[0], "Missing min port.");
+ if (min_port < 0 || min_port > USHRT_MAX)
+ usage(argv[0], "Invalid min port.");
+ break;
+#endif
case 'o':
visible_ip_o = get_ip_addr(optarg);
break;
@@ -408,6 +443,16 @@
case 't':
throttle_seconds = atoi(optarg);
break;
+
+#ifdef RANGEDPORTS
+ case 'x':
+ max_port = strtol(optarg, &p, 10);
+ if (!*optarg || *p)
+ usage(argv[0], "Missing max port.");
+ if (max_port < 0 || max_port > USHRT_MAX)
+ usage(argv[0], "Invalid max port.");
+ break;
+#endif
case 'C':
allow_dcc_chat = 0;
@@ -467,6 +512,11 @@
break;
}
}
+
+#ifdef RANGEDPORTS
+ if (max_port < min_port)
+ usage(argv[0], "max port can not be smaller than min port.");
+#endif
/* Set a few variables to 'default' values.
*/
@@ -684,6 +734,11 @@
-p Require a valid Unix password for access.\n\
-q file Read a list of 'quizzes' from the named file.\n");
#endif
+#ifdef RANGEDPORTS
+ fprintf(stderr,"\
+ -m minport Specify the minimum port to bind incoming DCC connects to.\n\
+ -x maxport Specify the maxmium port to bind incoming DCC connects to.\n");
+#endif
fprintf(stderr,"\
-a Anonymous mode, hide as much info about the user as possible.\n\
-r user Run as the specified user in server mode.\n\
@@ -853,58 +908,146 @@
return (gid);
}
-
/* Bind to the specified ip and port.
*/
static int bind_to_port(ipaddr_t bind_ip, short bind_port, int backlog, int dlev)
{
+ struct sockaddr_in addr;
+ int sock;
+
+ /* Allocate a socket.
+ */
+ if ((sock = socket(AF_INET, SOCK_STREAM,
+ getprotobyname("tcp")->p_proto)) < 0)
+ {
+ debug_msg(dlev, LOG_WARNING, "socket(): %d - %.256s", errno, strerror(errno));
+ return(-1);
+ }
+
+#ifdef TIRC_DEBUG
+ /* Set the SO_REUSEADDR option for debugging.
+ */
+ if (debug_level >= DEBUG_NOFORK) {
+ int on = 1;
+
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
+ }
+#endif
+
+ /* Set the address to listen to.
+ */
+ memset(&addr, '\0', sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(bind_port);
+ addr.sin_addr.s_addr = bind_ip;
+
+ /* Bind our socket to the above address.
+ */
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ debug_msg(dlev, LOG_WARNING, "bind(): %d - %.256s", errno, strerror(errno));
+ return(-1);
+ }
+
+ /* Establish a large listen backlog.
+ */
+ if (listen(sock, backlog) < 0)
+ {
+ debug_msg(dlev, LOG_WARNING, "listen(): %d - %.256s", errno, strerror(errno));
+ return(-1);
+ }
+
+ return (sock);
+}
+
+#ifdef RANGEDPORTS
+/* Bind to the specified ip and choose a port in the range of min_port and max_port.
+*/
+static int bind_to_ranged_port(ipaddr_t bind_ip, short min_port, short max_port, int backlog, int dlev)
+
+{
struct sockaddr_in addr;
int sock;
- /* Allocate a socket.
- */
- if ((sock = socket(AF_INET, SOCK_STREAM,
- getprotobyname("tcp")->p_proto)) < 0)
+ int direction = 1;
+ int count;
+ short start_port;
+
+ if (min_port > max_port)
{
- debug_msg(dlev, LOG_WARNING, "socket(): %d - %.256s", errno, strerror(errno));
- return(-1);
+ debug_msg(dlev, LOG_WARNING, "min_port > max_port");
+ return(-1);
}
+
+ count = 1 + max_port - min_port;
+
+ start_port = (arc4random() % count) + min_port;
+
+ while (count-- > 0) {
+
+ /* Allocate a socket.
+ */
+ if ((sock = socket(AF_INET, SOCK_STREAM,
+ getprotobyname("tcp")->p_proto)) < 0)
+ {
+ debug_msg(dlev, LOG_WARNING, "socket(): %d - %.256s", errno, strerror(errno));
+ return(-1);
+ }
#ifdef TIRC_DEBUG
- /* Set the SO_REUSEADDR option for debugging.
- */
- if (debug_level >= DEBUG_NOFORK) {
- int on = 1;
+ /* Set the SO_REUSEADDR option for debugging.
+ */
+ if (debug_level >= DEBUG_NOFORK) {
+ int on = 1;
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
- }
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
+ }
#endif
- /* Set the address to listen to.
- */
- memset(&addr, '\0', sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_port = htons(bind_port);
- addr.sin_addr.s_addr = bind_ip;
+ /* Set the address to listen to.
+ */
+ memset(&addr, '\0', sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(start_port);
+ addr.sin_addr.s_addr = bind_ip;
- /* Bind our socket to the above address.
- */
- if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- {
- debug_msg(dlev, LOG_WARNING, "bind(): %d - %.256s", errno, strerror(errno));
- return(-1);
- }
+ /* Bind our socket to the above address.
+ */
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
+ {
+ if (errno != EADDRINUSE)
+ {
+ debug_msg(dlev, LOG_WARNING, "bind(): %d - %.256s", errno, strerror(errno));
+ close(sock);
+ return(-1);
+ }
+ /* It's in use, try the next port */
+ close(sock);
- /* Establish a large listen backlog.
- */
- if (listen(sock, backlog) < 0)
- {
- debug_msg(dlev, LOG_WARNING, "listen(): %d - %.256s", errno, strerror(errno));
- return(-1);
- }
+ start_port += direction;
- return (sock);
+ if (start_port < min_port)
+ start_port = max_port;
+ else if (start_port > max_port)
+ start_port = min_port;
+ continue;
+ }
+
+ /* Establish a large listen backlog.
+ */
+ if (listen(sock, backlog) < 0)
+ {
+ debug_msg(dlev, LOG_WARNING, "listen(): %d - %.256s", errno, strerror(errno));
+ close(sock);
+ return(-1);
+ }
+
+ return (sock);
+ }
+ errno = EAGAIN;
+ return(-1);
}
+#endif
/* Connect to the a server.
@@ -1070,6 +1213,11 @@
natlookup_t natlook;
int fd;
#endif
+#ifdef PF
+ struct sockaddr_in ext, gwy;
+ struct pfioc_natlook natlook;
+ int fd;
+#endif
/* Give this thing 10 minutes to get started (paranoia).
*/
@@ -1166,6 +1314,50 @@
to_addr.sin_family = AF_INET;
to_addr.sin_port = htons(ntohs(natlook.nl_realport));
to_addr.sin_addr.s_addr = get_ip_addr(inet_ntoa(natlook.nl_realip));
+# else
+# ifdef PF
+ to_len = sizeof(ext);
+ if (getpeername(sock, (struct sockaddr *)&ext, &to_len) == -1)
+ {
+ perror("getpeername");
+ exit(-1);
+ }
+
+ to_len = sizeof(gwy);
+ if (getsockname(sock, (struct sockaddr *)&gwy, &to_len) == -1)
+ {
+ perror("getsockname");
+ exit(-1);
+ }
+
+ if ((fd = open("/dev/pf", O_RDWR)) == -1) {
+ perror("open(\"/dev/pf\")");
+ exit(-1);
+ }
+
+ memset(&natlook, 0, sizeof(struct pfioc_natlook));
+ natlook.af = AF_INET;
+ natlook.proto = IPPROTO_TCP;
+ natlook.direction = PF_OUT; /* s = ext, d = gwy, r = svr */
+ natlook.saddr.v4.s_addr = ext.sin_addr.s_addr;
+ natlook.sport = ext.sin_port;
+ natlook.daddr.v4.s_addr = gwy.sin_addr.s_addr;
+ natlook.dport = gwy.sin_port;
+
+ if (ioctl(fd, DIOCNATLOOK, &natlook) == -1)
+ {
+ perror("ioctl");
+ close(fd);
+ exit(-1);
+ }
+
+ close(fd);
+
+ memset(&to_addr, 0, sizeof(to_addr));
+ to_addr.sin_family = AF_INET;
+ to_addr.sin_port = natlook.rdport;
+ to_addr.sin_addr.s_addr = natlook.rdaddr.v4.s_addr;
+# endif /* PF */
# endif /* IFP */
#endif /* LINUX */
}
@@ -2047,9 +2239,15 @@
** (re: BUGTRAQ, 1998, December 22 & 23)
*/
len = 10;
- while ((listen_sock = bind_to_port((incoming) ? visible_ip_o : visible_ip_i,
- ((rand() + getpid()) % PPOOL) + 1025,
+#ifdef RANGEDPORTS
+ while ((listen_sock = bind_to_ranged_port((incoming) ? visible_ip_o : visible_ip_i,
+ min_port, max_port,
1, DEBUG_TRIVIA)) < 0)
+#else
+ while ((listen_sock = bind_to_port((incoming) ? visible_ip_o : visible_ip_i,
+ ((rand() + getpid()) % PPOOL) + 1025,
+ 1, DEBUG_TRIVIA)) < 0)
+#endif
{
if (--len < 1) {
debug_msg(0, LOG_ERR, "Failed to bind to port, dropping DCC!");