summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Anvin <hpa@tazenda.sc.orionmulti.com>2005-10-13 11:41:37 -0700
committerPeter Anvin <hpa@tazenda.sc.orionmulti.com>2005-10-13 11:41:37 -0700
commit4187af0e6f0c79e3892bc55ea1bf7b594f00381e (patch)
tree69fc07177d73a71161037ebf8276785b35d6ecfb
parentae1305e2d56d0a90d6e25f04006412f73cea8ba2 (diff)
downloadtftp-hpa-4187af0e6f0c79e3892bc55ea1bf7b594f00381e.tar.gz
Cleaner version implementing port range
-rw-r--r--tftpd/tftpd.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index f859afd..30d20a3 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -273,6 +273,37 @@ static int recv_time(int s, void *rbuf, int len, unsigned int flags,
}
}
+static int
+pick_port_bind(int sockfd, struct sockaddr_in *myaddr)
+{
+ unsigned int port, firstport;
+
+ firstport = portrange
+ ? portrange_from + rand() % (portrange_to-portrange_from+1)
+ : 0;
+
+ port = firstport;
+
+ do {
+ myaddr->sin_port = htons(port);
+
+ if (bind(sockfd, (struct sockaddr *)myaddr, sizeof *myaddr) < 0) {
+ if ( portrange && (errno == EINVAL || errno == EADDRINUSE) )
+ continue; /* Should not happen in normal operation, but try again */
+
+ return -1;
+ } else {
+ return 0;
+ }
+
+ port++;
+ if ( port > portrange_to )
+ port = portrange_from;
+ } while ( port != firstport );
+
+ return -1;
+}
+
int
main(int argc, char **argv)
{
@@ -717,32 +748,11 @@ main(int argc, char **argv)
from.sin_family = AF_INET;
/* Process the request... */
-
- while(1) {
- unsigned int port;
-
- if ( portrange ) {
- /* Pick a (pseudo)random port in the relevant range */
- port = portrange_from + rand() % (portrange_to-portrange_from+1);
- } else {
- port = 0; /* Let the kernel pick a port */
- }
-
-
- myaddr.sin_port = htons(port);
-
- if (bind(peer, (struct sockaddr *)&myaddr, sizeof myaddr) < 0) {
- if ( (errno == EINVAL || errno == EADDRINUSE) && portrange )
- continue; /* Should not happen in normal operation, but try again */
-
- syslog(LOG_ERR, "bind: %m");
- exit(EX_IOERR);
- } else {
- break;
- }
+ if (pick_port_bind(peer, &myaddr) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ exit(EX_IOERR);
}
-
-
+
if (connect(peer, (struct sockaddr *)&from, sizeof from) < 0) {
syslog(LOG_ERR, "connect: %m");
exit(EX_IOERR);