diff options
Diffstat (limited to 'libexec/tftpd')
-rw-r--r-- | libexec/tftpd/tftpd.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/libexec/tftpd/tftpd.c b/libexec/tftpd/tftpd.c index d971cdd5f35..c6a71400d77 100644 --- a/libexec/tftpd/tftpd.c +++ b/libexec/tftpd/tftpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tftpd.c,v 1.54 2006/12/15 05:52:06 itojun Exp $ */ +/* $OpenBSD: tftpd.c,v 1.55 2007/04/02 20:13:17 deraadt Exp $ */ /* * Copyright (c) 1983 Regents of the University of California. @@ -37,7 +37,7 @@ char copyright[] = #ifndef lint /*static char sccsid[] = "from: @(#)tftpd.c 5.13 (Berkeley) 2/26/91";*/ -static char rcsid[] = "$OpenBSD: tftpd.c,v 1.54 2006/12/15 05:52:06 itojun Exp $"; +static char rcsid[] = "$OpenBSD: tftpd.c,v 1.55 2007/04/02 20:13:17 deraadt Exp $"; #endif /* not lint */ /* @@ -160,7 +160,7 @@ usage(void) int main(int argc, char *argv[]) { - int n = 0, on = 1, fd = 0, i, c; + int n = 0, on = 1, fd = 0, i, c, dobind = 1; struct tftphdr *tp; struct passwd *pw; char cbuf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; @@ -354,6 +354,9 @@ main(int argc, char *argv[]) cmsg->cmsg_type == IP_RECVDSTADDR) { memcpy(&((struct sockaddr_in *)&s_in)->sin_addr, CMSG_DATA(cmsg), sizeof(struct in_addr)); + if (((struct sockaddr_in *)&s_in)->sin_addr.s_addr == + INADDR_BROADCAST) + dobind = 0; break; } if (cmsg->cmsg_level == IPPROTO_IPV6 && @@ -372,8 +375,14 @@ main(int argc, char *argv[]) } } - if (bind(peer, (struct sockaddr *)&s_in, s_in.ss_len) < 0) { - syslog(LOG_ERR, "bind: %m"); + (void) setsockopt(peer, SOL_SOCKET, SO_REUSEADDR, &on, + sizeof(on)); + (void) setsockopt(peer, SOL_SOCKET, SO_REUSEPORT, &on, + sizeof(on)); + + if (dobind && bind(peer, (struct sockaddr *)&s_in, s_in.ss_len) < 0) { + syslog(LOG_ERR, "bind to %s: %m", + inet_ntoa(((struct sockaddr_in *)&s_in)->sin_addr)); exit(1); } if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) { |