?? tftpd.c
字號:
/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintchar copyright[] ="@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)tftpd.c 5.8 (Berkeley) 6/18/88";#endif /* not lint *//* * Trivial file transfer protocol server. * * This version includes many modifications by Jim Guyton <guyton@rand-unix> */#include <sys/types.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/wait.h>#include <sys/stat.h>#include <netinet/in.h>#include "tftp.h"#include <signal.h>#include <stdio.h>#include <errno.h>#include <ctype.h>#include <netdb.h>#include <setjmp.h>#include <syslog.h>#ifdef EMBED#include <unistd.h>#endif#define TIMEOUT 5extern int errno;struct sockaddr_in mysin = { AF_INET };int peer;int rexmtval = TIMEOUT;int maxtimeout = 5*TIMEOUT;#define PKTSIZE SEGSIZE+4char buf[PKTSIZE];char ackbuf[PKTSIZE];struct sockaddr_in from;socklen_t fromlen;#ifdef EMBEDvoid openlog(const char *ident, int option, int facility) { return; }//syslog removed because of already defined as fprintf in syslog.h//void syslog(int priority, const char *format, ...) { return; }/*{ FILE *fp; fp = fopen("/dev/ttyS0", "rw"); fprintf(fp, format); }*/#ifndef fork#define fork vfork#endif#endifmain(){ //unsigned char *tp; register int n; int on = 1; short th_opcode;#ifdef NAOSI_ABS32 naosi_tftpd();#endif openlog("tftpd", LOG_PID, LOG_DAEMON); ioctl(0, FIONBIO, &on);/* if (ioctl(0, FIONBIO, &on) < 0) { syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); exit(1); }*/ fromlen = sizeof (from); n = recvfrom(0, buf, sizeof (buf), 0, (struct sockaddr *)&from, &fromlen); //printf(" retrun n = %d\n",n); if (n < 0) { // syslog(LOG_ERR, "recvfrom: %m\n"); // exit(1); _exit(1); } /* * Now that we have read the message out of the UDP * socket, we fork and exit. Thus, inetd will go back * to listening to the tftp port, and the next request * to come in will start up a new instance of tftpd. * * We do this so that inetd can run tftpd in "wait" mode. * The problem with tftpd running in "nowait" mode is that * inetd may get one or more successful "selects" on the * tftp port before we do our receive, so more than one * instance of tftpd may be started up. Worse, if tftpd * break before doing the above "recvfrom", inetd would * spawn endless instances, clogging the system. */#if 0#if 0315 * 0 { int pid; int i, j; for (i = 1; i < 20; i++) { //pid = fork(); pid = vfork(); //fork not availble if (pid < 0) { sleep(i); /* * flush out to most recently sent request. * * This may drop some request, but those * will be resent by the clients when * they timeout. The positive effect of * this flush is to (try to) prevent more * than one tftpd being started up to service * a single request from a single client. */ j = sizeof from; i = recvfrom(0, buf, sizeof (buf), 0, (struct sockaddr *)&from, &j); if (i > 0) { n = i; fromlen = j; } } else { break; } } if (pid < 0) { //syslog(LOG_ERR, "fork: %m\n"); //exit(1); _exit(1); } else if (pid != 0) { //exit(0); _exit(0); } }#else /* 0315 */ { int pid; pid = vfork(); if(pid < 0){ printf("tftpd - fork error\n"); _exit(1); } else if (pid != 0){ _exit(0); } }#endif /* 0315 */#endif from.sin_family = AF_INET;// alarm(0);// close(0);// close(1); peer = socket(AF_INET, SOCK_DGRAM, 0); if (peer < 0) { //syslog(LOG_ERR, "socket: %m\n"); //exit(1); _exit(1); } if (bind(peer, (struct sockaddr *)&mysin, sizeof (mysin)) < 0) { //syslog(LOG_ERR, "bind: %m\n"); //exit(1); _exit(1); } if (connect(peer, ( struct sockaddr *)&from, sizeof(from)) < 0) { //syslog(LOG_ERR, "connect: %m\n"); //exit(1); _exit(1); } //tp = (unsigned char *)buf; th_opcode = (buf[0] << 8 | buf[1]); //th_opcode = ntohs(th_opcode);//printf(" th_opcode %d ========\n",th_opcode); if (th_opcode == RRQ || th_opcode == WRQ){//printf(" buf %p ========\n",buf); tftp(buf, n); } _exit(0);}int validate_access();int sendfile(), recvfile();struct formats {// char *f_mode; char f_mode[16]; int (*f_validate)(); int (*f_send)(); int (*f_recv)(); int f_convert;} formats[] = { { "netascii", validate_access, sendfile, recvfile, 1 }, { "octet", validate_access, sendfile, recvfile, 0 },#ifdef notdef { "mail", validate_user, sendmail, recvmail, 1 },#endif#if 0326 & 0 { 0 }#endif};/* * Handle initial connection protocol. */tftp(tp, size) unsigned char *tp; int size;{ char *cp, *filename, *mode; int i, ecode; struct formats *pf; short th_opcode;//printf(" tp %p ========\n",tp); tp = buf; mode = NULL; filename = cp = &tp[2];//printf(" filename %s ========\n",filename);again: while (cp < (char *)tp + size) { if (*cp == '\0') break; cp++; }//printf(" *********** 1\n"); if (*cp != '\0') {printf("EBADOP 1\n"); nak(EBADOP); _exit(1); }//printf(" *********** 2\n");//printf("mode = %p\n",mode); if (mode == NULL) {//printf(" *********** 3\n"); mode = ++cp; goto again; }//printf(" *********** 3\n"); for (cp = mode; *cp; cp++){ if (isupper(*cp)) *cp = tolower(*cp); }//printf(" *********** 4\n");#if 0326 for (pf = formats, i = sizeof(formats)/sizeof(formats[0]);; pf++){ if (--i < 0){printf("EBADOP 2\n"); nak(EBADOP); _exit(1); } if (strcmp(pf->f_mode, mode) == 0){ break; } }#else for (pf = formats; pf->f_mode; pf++){ if (strcmp(pf->f_mode, mode) == 0) break; }//printf(" *********** 5\n"); if (pf->f_mode == 0) {printf("EBADOP 3\n"); nak(EBADOP); _exit(1); }#endif//printf(" *********** 6\n"); th_opcode = (tp[0] << 8 | tp[1]); ecode = validate_access(filename, th_opcode);//printf(" **** ecode = %x\n",ecode);// ecode = (*pf->f_validate)(filename, tp->th_opcode); if (ecode) {//printf(" ===== tftp 3\n"); nak(ecode); _exit(1); }//printf(" **** tp->th_opcode %d\n",th_opcode); if (th_opcode == WRQ) recvfile(pf);// (*pf->f_recv)(pf); else sendfile(pf);// (*pf->f_send)(pf);printf(" ------ ftfpd END -------------\n"); _exit(0);}FILE *file;/* * Validate file access. Since we * have no uid or gid, for now require * file to exist and be publicly * readable/writable. * Note also, full path name must be * given as we have no login directory. */validate_access(filename, mode) char *filename; int mode;{ struct stat stbuf; int fd;printf(" validate_access filename = %s\n",filename); if (*filename != '/') return (EACCESS); if (stat(filename, &stbuf) < 0){printf(" ------- validate_access errno %d\n",errno); return (errno == ENOENT ? ENOTFOUND : EACCESS); }//printf(" ------- validate_access 1\n"); if (mode == RRQ) { if ((stbuf.st_mode&(S_IREAD >> 6)) == 0) return (EACCESS);//printf(" ------- validate_access 2\n"); } else { if ((stbuf.st_mode&(S_IWRITE >> 6)) == 0) return (EACCESS);//printf(" ------- validate_access 3\n"); }//printf("mode = %d ============= \n",mode); fd = open(filename, mode == RRQ ? 0 : 1); if (fd < 0) return (errno + 100);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -