Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * Copyright (c) 1983 Regents of the University of California.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms are permitted
  6. * provided that the above copyright notice and this paragraph are
  7. * duplicated in all such forms and that any documentation,
  8. * advertising materials, and other materials related to such
  9. * distribution and use acknowledge that the software was developed
  10. * by the University of California, Berkeley. The name of the
  11. * University may not be used to endorse or promote products derived
  12. * from this software without specific prior written permission.
  13. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15. * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16. */
  17. #ifndef lint
  18. static char sccsid[] = "@(#)tftp.c 5.7 (Berkeley) 6/29/88";
  19. #endif /* not lint */
  20. /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
  21. /*
  22. * TFTP User Program -- Protocol Machines
  23. */
  24. #include <sys/types.h>
  25. #include <sys/socket.h>
  26. #include <sys/time.h>
  27. #include <netinet/in.h>
  28. #include <arpa/tftp.h>
  29. #include <signal.h>
  30. #include <stdio.h>
  31. #include <errno.h>
  32. #include <setjmp.h>
  33. extern int errno;
  34. extern struct sockaddr_in sin; /* filled in by main */
  35. extern int f; /* the opened socket */
  36. extern int trace;
  37. extern int verbose;
  38. extern int rexmtval;
  39. extern int maxtimeout;
  40. extern int segsize;
  41. #define PKTSIZE (1432+4) /* SEGSIZE+4 */
  42. char ackbuf[PKTSIZE];
  43. int timeout;
  44. jmp_buf toplevel;
  45. jmp_buf timeoutbuf;
  46. #ifndef OACK
  47. #define OACK 6
  48. #endif
  49. void timer(int sig)
  50. {
  51. signal(SIGALRM, timer);
  52. timeout += rexmtval;
  53. if (timeout >= maxtimeout) {
  54. printf("Transfer timed out.\n");
  55. longjmp(toplevel, -1);
  56. }
  57. longjmp(timeoutbuf, 1);
  58. }
  59. strnlen(s, n)
  60. char *s;
  61. int n;
  62. {
  63. int i = 0;
  64. while (n-- > 0 && *s++) i++;
  65. return(i);
  66. }
  67. /*
  68. * Parse an OACK package and set blocksize accordingly
  69. */
  70. parseoack(cp, sz)
  71. char *cp;
  72. int sz;
  73. {
  74. int n;
  75. segsize = 512;
  76. while (sz > 0 && *cp) {
  77. n = strnlen(cp, sz);
  78. if (n == 7 && !strncmp("blksize", cp, 7)) {
  79. cp += 8;
  80. sz -= 8;
  81. if (sz <= 0)
  82. break;
  83. for (segsize = 0, n = strnlen(cp, sz); n > 0;
  84. n--, cp++, sz--) {
  85. if (*cp < '0' || *cp > '9')
  86. break;
  87. segsize = 10*segsize + *cp - '0'; }
  88. }
  89. cp += n + 1;
  90. sz -= n + 1;
  91. }
  92. if (segsize < 8 || segsize > 1432) {
  93. printf("Remote host negotiated illegal blocksize %d\n",
  94. segsize);
  95. segsize = 512;
  96. longjmp(timeoutbuf, -1);
  97. }
  98. }
  99. /*
  100. * Send the requested file.
  101. */
  102. sendfile(fd, name, mode)
  103. int fd;
  104. char *name;
  105. char *mode;
  106. {
  107. register struct tftphdr *ap; /* data and ack packets */
  108. struct tftphdr *r_init(), *dp;
  109. register int size, n;
  110. u_short block = 0;
  111. register unsigned long amount = 0;
  112. struct sockaddr_in from;
  113. int fromlen;
  114. int convert; /* true if doing nl->crlf conversion */
  115. FILE *file;
  116. startclock(); /* start stat's clock */
  117. dp = r_init(); /* reset fillbuf/read-ahead code */
  118. ap = (struct tftphdr *)ackbuf;
  119. file = fdopen(fd, "r");
  120. convert = !strcmp(mode, "netascii");
  121. signal(SIGALRM, timer);
  122. do {
  123. if (block == 0)
  124. size = makerequest(WRQ, name, dp, mode) - 4;
  125. else {
  126. /* size = read(fd, dp->th_data, SEGSIZE); */
  127. size = readit(file, &dp, convert);
  128. if (size < 0) {
  129. nak(errno + 100);
  130. break;
  131. }
  132. dp->th_opcode = htons((u_short)DATA);
  133. dp->th_block = htons(block);
  134. }
  135. timeout = 0;
  136. (void) setjmp(timeoutbuf);
  137. send_data:
  138. if (trace)
  139. tpacket("sent", dp, size + 4);
  140. n = sendto(f, dp, size + 4, 0, (struct sockaddr *)&sin,
  141. sizeof (sin));
  142. if (n != size + 4) {
  143. perror("tftp: sendto");
  144. goto abort;
  145. }
  146. if (block) /* do not start reading until the blocksize
  147. has been negotiated */
  148. read_ahead(file, convert);
  149. for ( ; ; ) {
  150. alarm(rexmtval);
  151. do {
  152. fromlen = sizeof (from);
  153. n = recvfrom(f, ackbuf, sizeof (ackbuf), 0,
  154. (struct sockaddr *)&from,
  155. &fromlen);
  156. } while (n <= 0);
  157. alarm(0);
  158. if (n < 0) {
  159. perror("tftp: recvfrom");
  160. goto abort;
  161. }
  162. sin.sin_port = from.sin_port; /* added */
  163. if (trace)
  164. tpacket("received", ap, n);
  165. /* should verify packet came from server */
  166. ap->th_opcode = ntohs(ap->th_opcode);
  167. if (ap->th_opcode == ERROR) {
  168. printf("Error code %d: %s\n", ap->th_code,
  169. ap->th_msg);
  170. goto abort;
  171. }
  172. if (ap->th_opcode == ACK) {
  173. int j;
  174. ap->th_block = ntohs(ap->th_block);
  175. if (block == 0) {
  176. if (trace)
  177. printf("server does not know "
  178. "about RFC1782; reset"
  179. "ting blocksize\n");
  180. segsize = 512;
  181. }
  182. if (ap->th_block == block) {
  183. break;
  184. }
  185. /* On an error, try to synchronize
  186. * both sides.
  187. */
  188. j = synchnet(f);
  189. if (j && trace) {
  190. printf("discarded %d packets\n",
  191. j);
  192. }
  193. if (ap->th_block == (block-1)) {
  194. goto send_data;
  195. }
  196. }
  197. else if (ap->th_opcode == OACK) {
  198. if (block) {
  199. printf("protocol violation\n");
  200. longjmp(toplevel, -1);
  201. }
  202. parseoack(&ap->th_stuff, n - 2);
  203. break;
  204. }
  205. }
  206. if (block > 0)
  207. amount += size;
  208. else
  209. read_ahead(file, convert);
  210. block++;
  211. } while (size == segsize || block == 1);
  212. abort:
  213. fclose(file);
  214. stopclock();
  215. if (amount > 0)
  216. printstats("Sent", amount);
  217. }
  218. /*
  219. * Receive a file.
  220. */
  221. recvfile(fd, name, mode)
  222. int fd;
  223. char *name;
  224. char *mode;
  225. {
  226. register struct tftphdr *ap;
  227. struct tftphdr *dp, *w_init();
  228. register int n, size;
  229. u_short block = 1;
  230. unsigned long amount = 0;
  231. struct sockaddr_in from;
  232. int fromlen, firsttrip = 1;
  233. FILE *file;
  234. int convert; /* true if converting crlf -> lf */
  235. int waitforoack = 1;
  236. startclock();
  237. dp = w_init();
  238. ap = (struct tftphdr *)ackbuf;
  239. file = fdopen(fd, "w");
  240. convert = !strcmp(mode, "netascii");
  241. signal(SIGALRM, timer);
  242. do {
  243. if (firsttrip) {
  244. size = makerequest(RRQ, name, ap, mode);
  245. firsttrip = 0;
  246. } else {
  247. ap->th_opcode = htons((u_short)ACK);
  248. ap->th_block = htons(block);
  249. size = 4;
  250. block++;
  251. }
  252. timeout = 0;
  253. (void) setjmp(timeoutbuf);
  254. send_ack:
  255. if (trace)
  256. tpacket("sent", ap, size);
  257. if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&sin,
  258. sizeof (sin)) != size) {
  259. alarm(0);
  260. perror("tftp: sendto");
  261. goto abort;
  262. }
  263. if (!waitforoack)
  264. write_behind(file, convert);
  265. for ( ; ; ) {
  266. alarm(rexmtval);
  267. do {
  268. fromlen = sizeof (from);
  269. n = recvfrom(f, dp, PKTSIZE, 0,
  270. (struct sockaddr *)&from, &fromlen);
  271. } while (n <= 0);
  272. alarm(0);
  273. if (n < 0) {
  274. perror("tftp: recvfrom");
  275. goto abort;
  276. }
  277. sin.sin_port = from.sin_port; /* added */
  278. if (trace)
  279. tpacket("received", dp, n);
  280. /* should verify client address */
  281. dp->th_opcode = ntohs(dp->th_opcode);
  282. if (dp->th_opcode == ERROR) {
  283. printf("Error code %d: %s\n", dp->th_code,
  284. dp->th_msg);
  285. goto abort;
  286. }
  287. if (dp->th_opcode == DATA) {
  288. int j;
  289. if (waitforoack) {
  290. if (trace)
  291. printf("server does not know "
  292. "about RFC1782; reset"
  293. "ting blocksize\n");
  294. waitforoack = 0;
  295. segsize = 512;
  296. }
  297. dp->th_block = ntohs(dp->th_block);
  298. if (dp->th_block == block) {
  299. break; /* have next packet */
  300. }
  301. /* On an error, try to synchronize
  302. * both sides.
  303. */
  304. j = synchnet(f);
  305. if (j && trace) {
  306. printf("discarded %d packets\n", j);
  307. }
  308. if (dp->th_block == (block-1)) {
  309. goto send_ack; /* resend ack */
  310. }
  311. }
  312. else if (dp->th_opcode == OACK) {
  313. if (block != 1 || !waitforoack) {
  314. printf("protocol violation\n");
  315. longjmp(toplevel, -1);
  316. }
  317. waitforoack = 0;
  318. parseoack(&dp->th_stuff, n - 2);
  319. ap->th_opcode = htons((u_short)ACK);
  320. ap->th_block = htons(0);
  321. size = 4;
  322. goto send_ack;
  323. }
  324. }
  325. /* size = write(fd, dp->th_data, n - 4); */
  326. size = writeit(file, &dp, n - 4, convert);
  327. if (size < 0) {
  328. nak(errno + 100);
  329. break;
  330. }
  331. amount += size;
  332. } while (size == segsize);
  333. abort: /* ok to ack, since user */
  334. ap->th_opcode = htons((u_short)ACK); /* has seen err msg */
  335. ap->th_block = htons(block);
  336. (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&sin, sizeof (sin));
  337. write_behind(file, convert); /* flush last buffer */
  338. fclose(file);
  339. stopclock();
  340. if (amount > 0)
  341. printstats("Received", amount);
  342. }
  343. makerequest(request, name, tp, mode)
  344. int request;
  345. char *name, *mode;
  346. struct tftphdr *tp;
  347. {
  348. register char *cp;
  349. tp->th_opcode = htons((u_short)request);
  350. cp = tp->th_stuff;
  351. strcpy(cp, name);
  352. cp += strlen(name);
  353. *cp++ = '\0';
  354. strcpy(cp, mode);
  355. cp += strlen(mode);
  356. *cp++ = '\0';
  357. strcpy(cp, "blksize");
  358. cp += 7;
  359. *cp++ = '\0';
  360. sprintf(cp, "%d", segsize);
  361. cp += strlen(cp) + 1;
  362. return (cp - (char *)tp);
  363. }
  364. struct errmsg {
  365. int e_code;
  366. const char *e_msg;
  367. } errmsgs[] = {
  368. { EUNDEF, "Undefined error code" },
  369. { ENOTFOUND, "File not found" },
  370. { EACCESS, "Access violation" },
  371. { ENOSPACE, "Disk full or allocation exceeded" },
  372. { EBADOP, "Illegal TFTP operation" },
  373. { EBADID, "Unknown transfer ID" },
  374. { EEXISTS, "File already exists" },
  375. { ENOUSER, "No such user" },
  376. { -1, 0 }
  377. };
  378. /*
  379. * Send a nak packet (error message).
  380. * Error code passed in is one of the
  381. * standard TFTP codes, or a UNIX errno
  382. * offset by 100.
  383. */
  384. nak(error)
  385. int error;
  386. {
  387. register struct tftphdr *tp;
  388. int length;
  389. register struct errmsg *pe;
  390. /* extern char *sys_errlist[]; */
  391. tp = (struct tftphdr *)ackbuf;
  392. tp->th_opcode = htons((u_short)ERROR);
  393. tp->th_code = htons((u_short)error);
  394. for (pe = errmsgs; pe->e_code >= 0; pe++)
  395. if (pe->e_code == error)
  396. break;
  397. if (pe->e_code < 0) {
  398. pe->e_msg = sys_errlist[error - 100];
  399. tp->th_code = EUNDEF;
  400. }
  401. strcpy(tp->th_msg, pe->e_msg);
  402. length = strlen(pe->e_msg) + 4;
  403. if (trace)
  404. tpacket("sent", tp, length);
  405. if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&sin, sizeof (sin))
  406. != length)
  407. perror("nak");
  408. }
  409. topts(cp, sz)
  410. char *cp;
  411. int sz;
  412. {
  413. int n, i = 0;
  414. while (sz > 0 && *cp) {
  415. n = strnlen(cp, sz);
  416. if (n > 0) {
  417. printf("%s%s=", i++ ? ", " : "", cp);
  418. cp += n + 1;
  419. sz -= n + 1;
  420. if (sz <= 0)
  421. break;
  422. n = strnlen(cp, sz);
  423. if (n > 0)
  424. printf("%s", cp);
  425. }
  426. cp += n + 1;
  427. sz -= n + 1;
  428. }
  429. }
  430. tpacket(s, tp, n)
  431. char *s;
  432. struct tftphdr *tp;
  433. int n;
  434. {
  435. static char *opcodes[] =
  436. { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR", "OACK" };
  437. register char *cp, *file;
  438. u_short op = ntohs(tp->th_opcode);
  439. char *index();
  440. if (op < RRQ || op > OACK)
  441. printf("%s opcode=%x ", s, op);
  442. else
  443. printf("%s %s ", s, opcodes[op]);
  444. switch (op) {
  445. case RRQ:
  446. case WRQ:
  447. n -= 2;
  448. file = cp = tp->th_stuff;
  449. cp = index(cp, '\0');
  450. printf("<file=%s, mode=%s, opts: ", file, cp + 1);
  451. topts(index(cp + 1, '\000') + 1, n - strlen(file)
  452. - strlen(cp + 1) - 2);
  453. printf(">\n");
  454. break;
  455. case DATA:
  456. printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4);
  457. break;
  458. case ACK:
  459. printf("<block=%d>\n", ntohs(tp->th_block));
  460. break;
  461. case ERROR:
  462. printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg);
  463. break;
  464. case OACK:
  465. printf("<");
  466. topts(tp->th_stuff, n - 2);
  467. printf(">\n");
  468. break;
  469. }
  470. }
  471. struct timeval tstart;
  472. struct timeval tstop;
  473. struct timezone zone;
  474. startclock() {
  475. gettimeofday(&tstart, &zone);
  476. }
  477. stopclock() {
  478. gettimeofday(&tstop, &zone);
  479. }
  480. printstats(direction, amount)
  481. char *direction;
  482. unsigned long amount;
  483. {
  484. double delta;
  485. /* compute delta in 1/10's second units */
  486. delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) -
  487. ((tstart.tv_sec*10.)+(tstart.tv_usec/100000));
  488. delta = delta/10.; /* back to seconds */
  489. printf("%s %ld bytes in %.1f seconds", direction, amount, delta);
  490. if ((verbose) && (delta >= 0.1))
  491. printf(" [%.0f bits/sec]", (amount*8.)/delta);
  492. putchar('\n');
  493. }