NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/49868: tftpd(8) doesn't play well with clients that return acknowledgements to the broadcast address
Hello. Here are patches which implement Christos request, as well as
documenting the change. Any reason I shouldn't commit these?
-thanks
-Brian
Index: tftpd.8
===================================================================
RCS file: /cvsroot/src/libexec/tftpd/tftpd.8,v
retrieving revision 1.28
diff -u -r1.28 tftpd.8
--- tftpd.8 29 Apr 2010 21:34:04 -0000 1.28
+++ tftpd.8 30 Apr 2015 18:57:10 -0000
@@ -1,4 +1,4 @@
-.\" $NetBSD$
+.\" $NetBSD: tftpd.8,v 1.28 2010/04/29 21:34:04 wiz Exp $
.\"
.\" Copyright (c) 1983, 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -39,7 +39,7 @@
Internet Trivial File Transfer Protocol server
.Sh SYNOPSIS
.Nm
-.Op Fl cdln
+.Op Fl bcdln
.Op Fl g Ar group
.Op Fl p Ar pathsep
.Op Fl s Ar directory
@@ -95,6 +95,12 @@
.Pp
The options are:
.Bl -tag -width "XsXdirectoryX"
+.It Fl b
+Allow clients which return acknowledgements to the broadcast address to
+communicate with the tftp server.
+Some tftp clients, notably ones resident in the ROMs of older Cisco
+equipment, return their acknowledgements to the broadcast address rather
+than the server's unicast address.
.It Fl c
Allow unrestricted creation of new files.
Without this flag, only existing publicly writable files can be overwritten.
Index: tftpd.c
===================================================================
RCS file: /cvsroot/src/libexec/tftpd/tftpd.c,v
retrieving revision 1.43
diff -u -r1.43 tftpd.c
--- tftpd.c 4 Oct 2013 07:51:48 -0000 1.43
+++ tftpd.c 30 Apr 2015 18:57:30 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD$ */
+/* $NetBSD: tftpd.c,v 1.31.4.1 2011/11/02 19:58:23 riz Exp $ */
/*
* Copyright (c) 1983, 1993
@@ -36,7 +36,7 @@
#if 0
static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD$");
+__RCSID("$NetBSD: tftpd.c,v 1.43 2013/10/04 07:51:48 jnemeth Exp $");
#endif
#endif /* not lint */
@@ -110,6 +110,7 @@
static char pathsep = '\0';
static char *securedir;
static int unrestricted_writes; /* uploaded files don't have to exist */
+static int broadcast_client = 0; /* Some clients ack to the broadcast address */
struct formats;
@@ -142,7 +143,7 @@
{
syslog(LOG_ERR,
- "Usage: %s [-cdln] [-g group] [-p pathsep] [-s directory] [-u user] [directory ...]",
+ "Usage: %s [-bcdln] [-g group] [-p pathsep] [-s directory] [-u user] [directory ...]",
getprogname());
exit(1);
}
@@ -172,8 +173,11 @@
curuid = getuid();
curgid = getgid();
- while ((ch = getopt(argc, argv, "cdg:lnp:s:u:")) != -1)
+ while ((ch = getopt(argc, argv, "bcdg:lnp:s:u:")) != -1)
switch (ch) {
+ case 'b':
+ broadcast_client = 1;
+ break;
case 'c':
unrestricted_writes = 1;
break;
@@ -393,14 +397,17 @@
syslog(LOG_ERR, "socket: %m");
exit(1);
}
+ if (broadcast_client) {
+ soopt = 1;
+ if (setsockopt(peer, SOL_SOCKET, SO_BROADCAST, (void *) &soopt, sizeof(soopt)) < 0) {
+ syslog(LOG_ERR, "set SO_BROADCAST: %m");
+ exit(1);
+ }
+ }
if (bind(peer, (struct sockaddr *)&me, me.ss_len) < 0) {
syslog(LOG_ERR, "bind: %m");
exit(1);
}
- if (connect(peer, (struct sockaddr *)&from, from.ss_len) < 0) {
- syslog(LOG_ERR, "connect: %m");
- exit(1);
- }
soopt = 65536; /* larger than we'll ever need */
if (setsockopt(peer, SOL_SOCKET, SO_SNDBUF, (void *) &soopt, sizeof(soopt)) < 0) {
syslog(LOG_ERR, "set SNDBUF: %m");
@@ -955,7 +962,7 @@
send_data:
if (!etftp && debug)
syslog(LOG_DEBUG, "Send DATA %u", block);
- if ((n = send(peer, dp, size + 4, 0)) != size + 4) {
+ if ((n = sendto(peer, dp, size + 4, 0, (struct sockaddr *)&from, fromlen)) != size + 4) {
syslog(LOG_ERR, "tftpd: write: %m");
goto abort;
}
@@ -963,7 +970,8 @@
read_ahead(file, tftp_blksize, pf->f_convert);
for ( ; ; ) {
alarm(rexmtval); /* read the ack */
- n = recv(peer, ackbuf, tftp_blksize, 0);
+ n = recvfrom(peer, ackbuf, tftp_blksize, 0,(struct sockaddr
+ *)&from, &fromlen );
alarm(0);
if (n < 0) {
syslog(LOG_ERR, "tftpd: read: %m");
@@ -1049,14 +1057,15 @@
(void) setjmp(timeoutbuf);
send_ack:
ap = (struct tftphdr *) (etftp ? oackbuf : ackbuf);
- if (send(peer, ap, acklength, 0) != acklength) {
+ if (sendto(peer, ap, acklength, 0, (struct sockaddr *)&from, fromlen) != acklength) {
syslog(LOG_ERR, "tftpd: write: %m");
goto abort;
}
write_behind(file, pf->f_convert);
for ( ; ; ) {
alarm(rexmtval);
- n = recv(peer, dp, tftp_blksize + 4, 0);
+ n = recvfrom(peer, dp, tftp_blksize + 4, 0, (struct sockaddr
+ *)&from, &fromlen);
alarm(0);
if (n < 0) { /* really? */
syslog(LOG_ERR, "tftpd: read: %m");
@@ -1108,16 +1117,16 @@
ap->th_block = htons((u_short)(block));
if (debug)
syslog(LOG_DEBUG, "Send final ACK %u", block);
- (void) send(peer, ackbuf, 4, 0);
+ (void) sendto(peer, ackbuf, 4, 0, (struct sockaddr *)&from, fromlen);
signal(SIGALRM, justquit); /* just quit on timeout */
alarm(rexmtval);
- n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
+ n = recvfrom(peer, buf, sizeof (buf), 0, (struct sockaddr *)&from, &fromlen); /* normally times out and quits */
alarm(0);
if (n >= 4 && /* if read some data */
dp->th_opcode == DATA && /* and got a data block */
block == dp->th_block) { /* then my last ack was lost */
- (void) send(peer, ackbuf, 4, 0); /* resend final ack */
+ (void) sendto(peer, ackbuf, 4, 0, (struct sockaddr *)&from, fromlen); /* resend final ack */
}
abort:
return;
@@ -1185,7 +1194,7 @@
syslog(LOG_DEBUG, "Send NACK %s", tp->th_msg);
length = strlen(tp->th_msg);
msglen = &tp->th_msg[length + 1] - buf;
- if (send(peer, buf, msglen, 0) != (ssize_t)msglen)
+ if (sendto(peer, buf, msglen, 0, (struct sockaddr *)&from, fromlen) != (ssize_t)msglen)
syslog(LOG_ERR, "nak: %m");
}
Home |
Main Index |
Thread Index |
Old Index