=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tftp/tftp.c,v retrieving revision 1.22 retrieving revision 1.23 diff -c -r1.22 -r1.23 *** src/usr.bin/tftp/tftp.c 2009/10/27 23:59:44 1.22 --- src/usr.bin/tftp/tftp.c 2012/05/01 04:23:21 1.23 *************** *** 1,4 **** ! /* $OpenBSD: tftp.c,v 1.22 2009/10/27 23:59:44 deraadt Exp $ */ /* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */ /* --- 1,4 ---- ! /* $OpenBSD: tftp.c,v 1.23 2012/05/01 04:23:21 gsoares Exp $ */ /* $NetBSD: tftp.c,v 1.5 1995/04/29 05:55:25 cgd Exp $ */ /* *************** *** 53,64 **** #include #include #include #include "extern.h" #include "tftpsubs.h" static int makerequest(int, const char *, struct tftphdr *, const char *); ! static void nak(int); static void tpacket(const char *, struct tftphdr *, int); static void startclock(void); static void stopclock(void); --- 53,66 ---- #include #include #include + #include #include "extern.h" #include "tftpsubs.h" + static int cmpport(struct sockaddr *, struct sockaddr *); static int makerequest(int, const char *, struct tftphdr *, const char *); ! static void nak(int, struct sockaddr *); static void tpacket(const char *, struct tftphdr *, int); static void startclock(void); static void stopclock(void); *************** *** 67,73 **** static void oack(struct tftphdr *, int, int); static int oack_set(const char *, const char *); ! extern struct sockaddr_in peeraddr; /* filled in by main */ extern int f; /* the opened socket */ extern int trace; extern int verbose; --- 69,75 ---- static void oack(struct tftphdr *, int, int); static int oack_set(const char *, const char *); ! extern struct sockaddr_storage peeraddr; /* filled in by main */ extern int f; /* the opened socket */ extern int trace; extern int verbose; *************** *** 124,130 **** sendfile(int fd, char *name, char *mode) { struct tftphdr *dp, *ap; /* data and ack packets */ ! struct sockaddr_in from; struct pollfd pfd[1]; unsigned long amount; socklen_t fromlen; --- 126,133 ---- sendfile(int fd, char *name, char *mode) { struct tftphdr *dp, *ap; /* data and ack packets */ ! struct sockaddr_storage from, peer; ! struct sockaddr_storage serv; /* valid server port number */ struct pollfd pfd[1]; unsigned long amount; socklen_t fromlen; *************** *** 138,143 **** --- 141,148 ---- convert = !strcmp(mode, "netascii"); block = 0; amount = 0; + memcpy(&peer, &peeraddr, peeraddr.ss_len); + memset(&serv, 0, sizeof(serv)); do { /* read data from file */ *************** *** 146,152 **** else { size = readit(file, &dp, convert, segment_size); if (size < 0) { ! nak(errno + 100); break; } dp->th_opcode = htons((u_short)DATA); --- 151,157 ---- else { size = readit(file, &dp, convert, segment_size); if (size < 0) { ! nak(errno + 100, (struct sockaddr *)&peer); break; } dp->th_opcode = htons((u_short)DATA); *************** *** 164,171 **** if (trace) tpacket("sent", dp, size + 4); if (sendto(f, dp, size + 4, 0, ! (struct sockaddr *)&peeraddr, ! sizeof(peeraddr)) != size + 4) { warn("sendto"); goto abort; } --- 169,176 ---- if (trace) tpacket("sent", dp, size + 4); if (sendto(f, dp, size + 4, 0, ! (struct sockaddr *)&peer, ! peer.ss_len) != size + 4) { warn("sendto"); goto abort; } *************** *** 202,208 **** warn("recvfrom"); goto abort; } ! peeraddr.sin_port = from.sin_port; /* added */ if (trace) tpacket("received", ap, n); --- 207,220 ---- warn("recvfrom"); goto abort; } ! if (!serv.ss_family) ! serv = from; ! else if (!cmpport((struct sockaddr *)&serv, ! (struct sockaddr *)&from)) { ! warn("server port mismatch"); ! goto abort; ! } ! peer = from; if (trace) tpacket("received", ap, n); *************** *** 256,262 **** recvfile(int fd, char *name, char *mode) { struct tftphdr *dp, *ap; /* data and ack packets */ ! struct sockaddr_in from; struct pollfd pfd[1]; unsigned long amount; socklen_t fromlen; --- 268,275 ---- recvfile(int fd, char *name, char *mode) { struct tftphdr *dp, *ap; /* data and ack packets */ ! struct sockaddr_storage from, peer; ! struct sockaddr_storage serv; /* valid server port number */ struct pollfd pfd[1]; unsigned long amount; socklen_t fromlen; *************** *** 273,278 **** --- 286,293 ---- block = 1; amount = 0; firsttrip = 1; + memcpy(&peer, &peeraddr, peeraddr.ss_len); + memset(&serv, 0, sizeof(serv)); options: do { *************** *** 298,305 **** if (trace) tpacket("sent", ap, size); if (sendto(f, ackbuf, size, 0, ! (struct sockaddr *)&peeraddr, ! sizeof(peeraddr)) != size) { warn("sendto"); goto abort; } --- 313,320 ---- if (trace) tpacket("sent", ap, size); if (sendto(f, ackbuf, size, 0, ! (struct sockaddr *)&peer, ! peer.ss_len) != size) { warn("sendto"); goto abort; } *************** *** 335,341 **** warn("recvfrom"); goto abort; } ! peeraddr.sin_port = from.sin_port; /* added */ if (trace) tpacket("received", dp, n); --- 350,363 ---- warn("recvfrom"); goto abort; } ! if (!serv.ss_family) ! serv = from; ! else if (!cmpport((struct sockaddr *)&serv, ! (struct sockaddr *)&from)) { ! warn("server port mismatch"); ! goto abort; ! } ! peer = from; if (trace) tpacket("received", dp, n); *************** *** 371,377 **** /* write data to file */ size = writeit(file, &dp, n - 4, convert); if (size < 0) { ! nak(errno + 100); break; } amount += size; --- 393,399 ---- /* write data to file */ size = writeit(file, &dp, n - 4, convert); if (size < 0) { ! nak(errno + 100, (struct sockaddr *)&peer); break; } amount += size; *************** *** 381,388 **** /* ok to ack, since user has seen err msg */ ap->th_opcode = htons((u_short)ACK); ap->th_block = htons((u_short)block); ! (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr, ! sizeof(peeraddr)); write_behind(file, convert); /* flush last buffer */ fclose(file); --- 403,410 ---- /* ok to ack, since user has seen err msg */ ap->th_opcode = htons((u_short)ACK); ap->th_block = htons((u_short)block); ! (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peer, ! peer.ss_len); write_behind(file, convert); /* flush last buffer */ fclose(file); *************** *** 395,400 **** --- 417,436 ---- } static int + cmpport(struct sockaddr *sa, struct sockaddr *sb) + { + char a[NI_MAXSERV], b[NI_MAXSERV]; + if (getnameinfo(sa, sa->sa_len, NULL, 0, a, sizeof(a), NI_NUMERICSERV)) + return (0); + if (getnameinfo(sb, sb->sa_len, NULL, 0, b, sizeof(b), NI_NUMERICSERV)) + return (0); + if (strcmp(a, b) != 0) + return (0); + + return (1); + } + + static int makerequest(int request, const char *name, struct tftphdr *tp, const char *mode) { *************** *** 436,442 **** * offset by 100. */ static void ! nak(int error) { struct errmsg *pe; struct tftphdr *tp; --- 472,478 ---- * offset by 100. */ static void ! nak(int error, struct sockaddr *peer) { struct errmsg *pe; struct tftphdr *tp; *************** *** 457,464 **** length = packet_size; if (trace) tpacket("sent", tp, length); ! if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr, ! sizeof(peeraddr)) != length) warn("nak"); } --- 493,500 ---- length = packet_size; if (trace) tpacket("sent", tp, length); ! if (sendto(f, ackbuf, length, 0, peer, ! peer->sa_len) != length) warn("nak"); } *************** *** 588,593 **** --- 624,631 ---- { int i, n; const char *errstr; + struct sockaddr_storage peer; + memcpy(&peer, &peeraddr, peeraddr.ss_len); for (i = 0; options[i].o_type != NULL; i++) { if (!strcasecmp(options[i].o_type, option)) { *************** *** 600,606 **** &errstr); if (errstr || rexmtval != n || opt_tout == 0) { ! nak(EOPTNEG); intrflag = 1; return (-1); } --- 638,644 ---- &errstr); if (errstr || rexmtval != n || opt_tout == 0) { ! nak(EOPTNEG, (struct sockaddr *)&peer); intrflag = 1; return (-1); } *************** *** 612,618 **** &errstr); if (errstr || opt_blksize != n || opt_blksize == 0) { ! nak(EOPTNEG); intrflag = 1; return (-1); } --- 650,656 ---- &errstr); if (errstr || opt_blksize != n || opt_blksize == 0) { ! nak(EOPTNEG, (struct sockaddr *)&peer); intrflag = 1; return (-1); }