Mercurial > hg > toybox
comparison toys/pending/tftpd.c @ 1383:350655f8fe53 draft
Minor cleanup pass.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 06 Jul 2014 23:17:55 -0500 |
parents | faf7117c4489 |
children |
comparison
equal
deleted
inserted
replaced
1382:50484a5a1798 | 1383:350655f8fe53 |
---|---|
13 help | 13 help |
14 usage: tftpd [-cr] [-u USER] [DIR] | 14 usage: tftpd [-cr] [-u USER] [DIR] |
15 | 15 |
16 Transfer file from/to tftp server. | 16 Transfer file from/to tftp server. |
17 | 17 |
18 -r Prohibit upload | 18 -r read only |
19 -c Allow file creation via upload | 19 -c Allow file creation via upload |
20 -u Access files as USER | 20 -u run as USER |
21 -l Log to syslog (inetd mode requires this) | 21 -l Log to syslog (inetd mode requires this) |
22 */ | 22 */ |
23 | 23 |
24 #define FOR_tftpd | 24 #define FOR_tftpd |
25 #include "toys.h" | 25 #include "toys.h" |
234 } | 234 } |
235 } | 235 } |
236 | 236 |
237 void tftpd_main(void) | 237 void tftpd_main(void) |
238 { | 238 { |
239 int recvmsg_len, rbuflen, opcode, blksize = TFTPD_BLKSIZE, tsize = 0, set =1; | 239 int fd = 0, recvmsg_len, rbuflen, opcode, blksize = TFTPD_BLKSIZE, tsize = 0, set =1; |
240 struct sockaddr_storage srcaddr, dstaddr; | 240 struct sockaddr_storage srcaddr, dstaddr; |
241 socklen_t socklen = sizeof(struct sockaddr_storage); | 241 socklen_t socklen = sizeof(struct sockaddr_storage); |
242 char *buf = toybuf; | 242 char *buf = toybuf; |
243 | 243 |
244 memset(&srcaddr, 0, sizeof(srcaddr)); | 244 memset(&srcaddr, 0, sizeof(srcaddr)); |
248 } | 248 } |
249 | 249 |
250 if (TT.user) TT.pw = xgetpwnam(TT.user); | 250 if (TT.user) TT.pw = xgetpwnam(TT.user); |
251 if (*toys.optargs) xchroot(*toys.optargs); | 251 if (*toys.optargs) xchroot(*toys.optargs); |
252 | 252 |
253 recvmsg_len = recvfrom(STDIN_FILENO, toybuf, TFTPD_BLKSIZE, 0, | 253 recvmsg_len = recvfrom(fd, toybuf, blksize, 0, (void *)&dstaddr, &socklen); |
254 (struct sockaddr*)&dstaddr, &socklen); | 254 |
255 | 255 TT.sfd = xsocket(dstaddr.ss_family, SOCK_DGRAM, 0); |
256 TT.sfd = xsocket(((struct sockaddr*)&dstaddr)->sa_family, SOCK_DGRAM, 0); | |
257 if (setsockopt(TT.sfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&set, | 256 if (setsockopt(TT.sfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&set, |
258 sizeof(set)) < 0) perror_exit("setsockopt failed"); | 257 sizeof(set)) < 0) perror_exit("setsockopt failed"); |
259 if (bind(TT.sfd, (struct sockaddr*)&srcaddr, socklen)) perror_exit("bind"); | 258 if (bind(TT.sfd, (void *)&srcaddr, socklen)) perror_exit("bind"); |
260 if (connect(TT.sfd, (struct sockaddr*)&dstaddr, socklen) < 0) | 259 if (connect(TT.sfd, (void *)&dstaddr, socklen) < 0) |
261 perror_exit("can't connect to remote host"); | 260 perror_exit("can't connect to remote host"); |
262 // Error condition. | 261 // Error condition. |
263 if (recvmsg_len < 4 || recvmsg_len > TFTPD_BLKSIZE | 262 if (recvmsg_len<4 || recvmsg_len>TFTPD_BLKSIZE || toybuf[recvmsg_len-1]) { |
264 || toybuf[recvmsg_len-1] != '\0') { | |
265 send_errpkt((struct sockaddr*)&dstaddr, socklen, "packet format error"); | 263 send_errpkt((struct sockaddr*)&dstaddr, socklen, "packet format error"); |
266 return; | 264 return; |
267 } | 265 } |
268 | 266 |
269 // request is either upload or Download. | 267 // request is either upload or Download. |
270 opcode = ntohs(*(uint16_t*)buf); | 268 opcode = buf[1]; |
271 if (((opcode != TFTPD_OP_RRQ) && (opcode != TFTPD_OP_WRQ)) | 269 if (((opcode != TFTPD_OP_RRQ) && (opcode != TFTPD_OP_WRQ)) |
272 || ((opcode == TFTPD_OP_WRQ) && (toys.optflags & FLAG_r))) { | 270 || ((opcode == TFTPD_OP_WRQ) && (toys.optflags & FLAG_r))) { |
273 send_errpkt((struct sockaddr*)&dstaddr, socklen, | 271 send_errpkt((struct sockaddr*)&dstaddr, socklen, |
274 ((opcode == TFTPD_OP_WRQ) ? "write error" : "packet format error")); | 272 (opcode == TFTPD_OP_WRQ) ? "write error" : "packet format error"); |
275 return; | 273 return; |
276 } | 274 } |
277 | 275 |
278 buf += 2; | 276 buf += 2; |
279 if (*buf == '.' || strstr(buf, "/.")) { | 277 if (*buf == '.' || strstr(buf, "/.")) { |
281 return; | 279 return; |
282 } | 280 } |
283 | 281 |
284 buf += strlen(buf) + 1; //1 '\0'. | 282 buf += strlen(buf) + 1; //1 '\0'. |
285 // As per RFC 1350, mode is case in-sensitive. | 283 // As per RFC 1350, mode is case in-sensitive. |
286 if ((buf >= (toybuf + recvmsg_len)) || (strcasecmp(buf, "octet"))) { | 284 if (buf >= toybuf+recvmsg_len || strcasecmp(buf, "octet")) { |
287 send_errpkt((struct sockaddr*)&dstaddr, socklen, "packet format error"); | 285 send_errpkt((struct sockaddr*)&dstaddr, socklen, "packet format error"); |
288 return; | 286 return; |
289 } | 287 } |
290 | 288 |
291 //RFC2348. e.g. of size type: "ttype1\0ttype1_val\0...ttypeN\0ttypeN_val\0" | 289 //RFC2348. e.g. of size type: "ttype1\0ttype1_val\0...ttypeN\0ttypeN_val\0" |