--- /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