|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)tftp.c 4.7 (Berkeley) 8/11/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * TFTP User Program -- Protocol Machines ! 7: */ ! 8: #include <sys/types.h> ! 9: #include <sys/socket.h> ! 10: ! 11: #include <netinet/in.h> ! 12: ! 13: #include <arpa/tftp.h> ! 14: ! 15: #include <signal.h> ! 16: #include <stdio.h> ! 17: #include <errno.h> ! 18: #include <setjmp.h> ! 19: ! 20: extern int errno; ! 21: extern struct sockaddr_in sin; ! 22: extern char mode[]; ! 23: int f; ! 24: int trace; ! 25: int verbose; ! 26: int connected; ! 27: char buf[BUFSIZ]; ! 28: int rexmtval; ! 29: int maxtimeout; ! 30: int timeout; ! 31: jmp_buf toplevel; ! 32: jmp_buf timeoutbuf; ! 33: ! 34: timer() ! 35: { ! 36: ! 37: timeout += rexmtval; ! 38: if (timeout >= maxtimeout) { ! 39: printf("Transfer timed out.\n"); ! 40: longjmp(toplevel, -1); ! 41: } ! 42: longjmp(timeoutbuf, 1); ! 43: } ! 44: ! 45: /* ! 46: * Send the requested file. ! 47: */ ! 48: sendfile(fd, name) ! 49: int fd; ! 50: char *name; ! 51: { ! 52: register struct tftphdr *tp = (struct tftphdr *)buf; ! 53: register int block = 0, size, n, amount = 0; ! 54: struct sockaddr_in from; ! 55: time_t start = time(0), delta; ! 56: int fromlen; ! 57: ! 58: signal(SIGALRM, timer); ! 59: do { ! 60: if (block == 0) ! 61: size = makerequest(WRQ, name) - 4; ! 62: else { ! 63: size = read(fd, tp->th_data, SEGSIZE); ! 64: if (size < 0) { ! 65: nak(errno + 100); ! 66: break; ! 67: } ! 68: tp->th_opcode = htons((u_short)DATA); ! 69: tp->th_block = htons((u_short)block); ! 70: } ! 71: timeout = 0; ! 72: (void) setjmp(timeoutbuf); ! 73: if (trace) ! 74: tpacket("sent", tp, size + 4); ! 75: n = sendto(f, buf, size + 4, 0, (caddr_t)&sin, sizeof (sin)); ! 76: if (n != size + 4) { ! 77: perror("tftp: sendto"); ! 78: goto abort; ! 79: } ! 80: do { ! 81: alarm(rexmtval); ! 82: do { ! 83: fromlen = sizeof (from); ! 84: n = recvfrom(f, buf, sizeof (buf), 0, ! 85: (caddr_t)&from, &fromlen); ! 86: } while (n <= 0); ! 87: alarm(0); ! 88: if (n < 0) { ! 89: perror("tftp: recvfrom"); ! 90: goto abort; ! 91: } ! 92: if (trace) ! 93: tpacket("received", tp, n); ! 94: /* should verify packet came from server */ ! 95: tp->th_opcode = ntohs(tp->th_opcode); ! 96: tp->th_block = ntohs(tp->th_block); ! 97: if (tp->th_opcode == ERROR) { ! 98: printf("Error code %d: %s\n", tp->th_code, ! 99: tp->th_msg); ! 100: goto abort; ! 101: } ! 102: } while (tp->th_opcode != ACK && block != tp->th_block); ! 103: if (block > 0) ! 104: amount += size; ! 105: block++; ! 106: } while (size == SEGSIZE || block == 1); ! 107: abort: ! 108: (void) close(fd); ! 109: if (amount > 0) { ! 110: delta = time(0) - start; ! 111: printf("Sent %d bytes in %d seconds.\n", amount, delta); ! 112: } ! 113: } ! 114: ! 115: /* ! 116: * Receive a file. ! 117: */ ! 118: recvfile(fd, name) ! 119: int fd; ! 120: char *name; ! 121: { ! 122: register struct tftphdr *tp = (struct tftphdr *)buf; ! 123: register int block = 1, n, size, amount = 0; ! 124: struct sockaddr_in from; ! 125: time_t start = time(0), delta; ! 126: int fromlen, firsttrip = 1; ! 127: ! 128: signal(SIGALRM, timer); ! 129: do { ! 130: if (firsttrip) { ! 131: size = makerequest(RRQ, name); ! 132: firsttrip = 0; ! 133: } else { ! 134: tp->th_opcode = htons((u_short)ACK); ! 135: tp->th_block = htons((u_short)(block)); ! 136: size = 4; ! 137: block++; ! 138: } ! 139: timeout = 0; ! 140: (void) setjmp(timeoutbuf); ! 141: if (trace) ! 142: tpacket("sent", tp, size); ! 143: if (sendto(f, buf, size, 0, (caddr_t)&sin, ! 144: sizeof (sin)) != size) { ! 145: alarm(0); ! 146: perror("tftp: sendto"); ! 147: goto abort; ! 148: } ! 149: do { ! 150: alarm(rexmtval); ! 151: do ! 152: n = recvfrom(f, buf, sizeof (buf), 0, ! 153: (caddr_t)&from, &fromlen); ! 154: while (n <= 0); ! 155: alarm(0); ! 156: if (n < 0) { ! 157: perror("tftp: recvfrom"); ! 158: goto abort; ! 159: } ! 160: if (trace) ! 161: tpacket("received", tp, n); ! 162: /* should verify client address */ ! 163: tp->th_opcode = ntohs(tp->th_opcode); ! 164: tp->th_block = ntohs(tp->th_block); ! 165: if (tp->th_opcode == ERROR) { ! 166: printf("Error code %d: %s\n", tp->th_code, ! 167: tp->th_msg); ! 168: goto abort; ! 169: } ! 170: } while (tp->th_opcode != DATA && block != tp->th_block); ! 171: size = write(fd, tp->th_data, n - 4); ! 172: if (size < 0) { ! 173: nak(errno + 100); ! 174: break; ! 175: } ! 176: amount += size; ! 177: } while (size == SEGSIZE); ! 178: abort: ! 179: tp->th_opcode = htons((u_short)ACK); ! 180: tp->th_block = htons((u_short)block); ! 181: (void) sendto(f, buf, 4, 0, &sin, sizeof (sin)); ! 182: (void) close(fd); ! 183: if (amount > 0) { ! 184: delta = time(0) - start; ! 185: printf("Received %d bytes in %d seconds.\n", amount, delta); ! 186: } ! 187: } ! 188: ! 189: makerequest(request, name) ! 190: int request; ! 191: char *name; ! 192: { ! 193: register struct tftphdr *tp; ! 194: int size; ! 195: register char *cp; ! 196: ! 197: tp = (struct tftphdr *)buf; ! 198: tp->th_opcode = htons((u_short)request); ! 199: strcpy(tp->th_stuff, name); ! 200: size = strlen(name); ! 201: cp = tp->th_stuff + strlen(name); ! 202: *cp++ = '\0'; ! 203: strcpy(cp, mode); ! 204: cp += sizeof ("netascii") - 1; ! 205: *cp++ = '\0'; ! 206: return (cp - buf); ! 207: } ! 208: ! 209: struct errmsg { ! 210: int e_code; ! 211: char *e_msg; ! 212: } errmsgs[] = { ! 213: { EUNDEF, "Undefined error code" }, ! 214: { ENOTFOUND, "File not found" }, ! 215: { EACCESS, "Access violation" }, ! 216: { ENOSPACE, "Disk full or allocation exceeded" }, ! 217: { EBADOP, "Illegal TFTP operation" }, ! 218: { EBADID, "Unknown transfer ID" }, ! 219: { EEXISTS, "File already exists" }, ! 220: { ENOUSER, "No such user" }, ! 221: { -1, 0 } ! 222: }; ! 223: ! 224: /* ! 225: * Send a nak packet (error message). ! 226: * Error code passed in is one of the ! 227: * standard TFTP codes, or a UNIX errno ! 228: * offset by 100. ! 229: */ ! 230: nak(error) ! 231: int error; ! 232: { ! 233: register struct tftphdr *tp; ! 234: int length; ! 235: register struct errmsg *pe; ! 236: extern char *sys_errlist[]; ! 237: ! 238: tp = (struct tftphdr *)buf; ! 239: tp->th_opcode = htons((u_short)ERROR); ! 240: tp->th_code = htons((u_short)error); ! 241: for (pe = errmsgs; pe->e_code >= 0; pe++) ! 242: if (pe->e_code == error) ! 243: break; ! 244: if (pe->e_code < 0) ! 245: pe->e_msg = sys_errlist[error - 100]; ! 246: strcpy(tp->th_msg, pe->e_msg); ! 247: length = strlen(pe->e_msg) + 4; ! 248: if (trace) ! 249: tpacket("sent", tp, length); ! 250: if (send(f, &sin, buf, length) != length) ! 251: perror("nak"); ! 252: } ! 253: ! 254: tpacket(s, tp, n) ! 255: struct tftphdr *tp; ! 256: int n; ! 257: { ! 258: static char *opcodes[] = ! 259: { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" }; ! 260: register char *cp, *file; ! 261: u_short op = ntohs(tp->th_opcode); ! 262: char *index(); ! 263: ! 264: if (op < RRQ || op > ERROR) ! 265: printf("%s opcode=%x ", s, op); ! 266: else ! 267: printf("%s %s ", s, opcodes[op]); ! 268: switch (op) { ! 269: ! 270: case RRQ: ! 271: case WRQ: ! 272: n -= 2; ! 273: file = cp = tp->th_stuff; ! 274: cp = index(cp, '\0'); ! 275: printf("<file=%s, mode=%s>\n", file, cp + 1); ! 276: break; ! 277: ! 278: case DATA: ! 279: printf("<block=%d, %d bytes>\n", ntohs(tp->th_block), n - 4); ! 280: break; ! 281: ! 282: case ACK: ! 283: printf("<block=%d>\n", ntohs(tp->th_block)); ! 284: break; ! 285: ! 286: case ERROR: ! 287: printf("<code=%d, msg=%s>\n", ntohs(tp->th_code), tp->th_msg); ! 288: break; ! 289: } ! 290: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.