Annotation of 42BSD/ucb/tftp/tftp.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.