Date: Wed, 16 Aug 2006 21:33:13 GMT From: Aaron Gifford <agifford@infowest.com> To: freebsd-gnats-submit@FreeBSD.org Subject: misc/102162: New Feature (Patch Included): Limit port range for tftpd Message-ID: <200608162133.k7GLXDlS081594@www.freebsd.org> Resent-Message-ID: <200608162140.k7GLeCBG017385@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 102162 >Category: misc >Synopsis: New Feature (Patch Included): Limit port range for tftpd >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: update >Submitter-Id: current-users >Arrival-Date: Wed Aug 16 21:40:12 GMT 2006 >Closed-Date: >Last-Modified: >Originator: Aaron Gifford >Release: 6.1-RELEASE >Organization: >Environment: Not applicable >Description: NEW FEATURE FOR tftpd: This patch the TFTP daemon adds a new command line option -p that permits the user to specify what port or port range the tftpd daemon will bind to during transfers. This is useful in cases where one must limit tftpd (perhaps for firewall reasons) to a small subset of ports. The patch applies cleanly to 5.x as well as 6.x up to 6.1-STABLE as of 16 Aug. 2006. While this has been tested on IPv4 networks, it has not been tested on IPv6. The code is so simple, however, that severe bugs under IPv6 are unlikely (but it would be nice for someone with an IPv6 net to give it a good walloping test). -Aaron out. (The patch is included in the "Fix to the problem" section.) >How-To-Repeat: >Fix: PATCH FOLLOWS: --- /usr/src/libexec/tftpd/tftpd.c.orig Tue May 31 11:22:53 2005 +++ /usr/src/libexec/tftpd/tftpd.c Fri May 12 07:28:28 2006 @@ -130,11 +130,13 @@ char *chroot_dir = NULL; struct passwd *nobody; const char *chuser = "nobody"; + char *pp; + u_short startport = 0, endport = 0; tzset(); /* syslog in localtime */ openlog("tftpd", LOG_PID | LOG_NDELAY, LOG_FTP); - while ((ch = getopt(argc, argv, "cClns:u:U:w")) != -1) { + while ((ch = getopt(argc, argv, "cClnp:s:u:U:w")) != -1) { switch (ch) { case 'c': ipchroot = 1; @@ -148,6 +150,17 @@ case 'n': suppress_naks = 1; break; + case 'p': + pp = strchr(optarg, (int)'-'); + if (pp == NULL) { + startport = atoi(optarg); + endport = startport; + } else { + *pp++ = (char)0; + startport = atoi(optarg); + endport = atoi(pp); + } + break; case 's': chroot_dir = optarg; break; @@ -289,19 +302,7 @@ } len = sizeof(me); - if (getsockname(0, (struct sockaddr *)&me, &len) == 0) { - switch (me.ss_family) { - case AF_INET: - ((struct sockaddr_in *)&me)->sin_port = 0; - break; - case AF_INET6: - ((struct sockaddr_in6 *)&me)->sin6_port = 0; - break; - default: - /* unsupported */ - break; - } - } else { + if (getsockname(0, (struct sockaddr *)&me, &len) != 0) { memset(&me, 0, sizeof(me)); me.ss_family = from.ss_family; me.ss_len = from.ss_len; @@ -314,9 +315,27 @@ syslog(LOG_ERR, "socket: %m"); exit(1); } - if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) { - syslog(LOG_ERR, "bind: %m"); - exit(1); + while (1) { + switch (me.ss_family) { + case AF_INET: + ((struct sockaddr_in *)&me)->sin_port = htons(startport); + break; + case AF_INET6: + ((struct sockaddr_in6 *)&me)->sin6_port = htons(startport); + break; + default: + /* unsupported */ + break; + } + if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) { + if (errno == EADDRINUSE && startport < endport) { + startport++; + continue; + } + syslog(LOG_ERR, "bind: %m"); + exit(1); + } + break; } if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { syslog(LOG_ERR, "connect: %m"); --- /usr/src/libexec/tftpd/tftpd.8.orig Wed Jul 7 13:57:14 2004 +++ /usr/src/libexec/tftpd/tftpd.8 Wed May 10 16:36:10 2006 @@ -147,6 +147,21 @@ .It Fl n Suppress negative acknowledgement of requests for nonexistent relative filenames. +.It Fl p Ar port-range +Force +.Nm +to bind to a local udp port within the specified +.Pa port-range . +.Nm +This is useful when the server is behind a firewall because it +limits the size of hole that must be opened in the firewall for +to function. You can specify either a single port number, or +a port range (two numbers separated by the '-' dash character). +If you only use a single port, your tftp server will only be +able to handle a single tftp session at a time. If you use +this option, it is recommended that you choose a large enough +range to support as many concurrent tftp sessions as you +ever expect to encounter. .It Fl s Ar directory Cause .Nm >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608162133.k7GLXDlS081594>