?? tftpd.c
字號:
/**********************************************************Date: OCT 28th, 2006Project : NET4900 Project: tftpd.c TFTP ServerProgramers: Craig HolmesReza Rahmanian File: TFTP Server (main)Purpose: A TFTP server that will accept a connections from a client and transefet files.Notes: Here we are using the sendto and recvfrom functions so the server and client can exchange data.***********************************************************************//* Include our header which contains libaries and defines */#include "tftp.h"/* Function prototypes */void tsend (char *, struct sockaddr_in, char *, int);void tget (char *, struct sockaddr_in, char *, int);int isnotvaliddir (char *);void usage (void);/* default values which can be controlled by command line */int debug = 0;char path[64] = "/tmp/";int port = 69;unsigned short int ackfreq = 1;int datasize = 512;intmain (int argc, char **argv){ /*local variables */ extern char *optarg; int sock, n, client_len, pid, status, opt, tid; char opcode, *bufindex, filename[196], mode[12]; struct sockaddr_in server, client; /*the address structure for both the server and client */ /* All of the following deals with command line switches */ while ((opt = getopt (argc, argv, "dh:p:P:a:s:")) != -1) /* this function is handy */ { switch (opt) { case 'p': /* path (opt required) */ if (!isnotvaliddir (optarg)) { printf ("Sorry, you specified an invalid/non-existant directory. Make sure the directory exists.\n"); return 0; } strncpy (path, optarg, sizeof (path) - 1); break; case 'd': /* debug mode (no opts) */ debug = 1; break; case 'P': /* Port (opt required) */ port = atoi (optarg); break; case 'a': /* ack frequency (opt required) */ ackfreq = atoi (optarg); if (ackfreq > MAXACKFREQ) { printf ("Sorry, you specified an ack frequency higher than the maximum allowed (Requested: %d Max: %d)\n", ackfreq, MAXACKFREQ); return 0; } else if (ackfreq == 0) { printf ("Sorry, you have to ack sometime.\n"); return 0; } break; case 's': /* File chunk size (opt required) */ datasize = atoi (optarg); if (datasize > MAXDATASIZE) { printf ("Sorry, you specified a data size higher than the maximum allowed (Requested: %d Max: %d)\n", datasize, MAXDATASIZE); return 0; } break; case 'h': /* Help (no opts) */ usage (); return (0); break; default: /* everything else */ usage (); return (0); break; } } /* Done dealing with switches */ /*Create the socket, a -1 will show us an error */ if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { printf ("Server Socket could not be created"); return 0; } /*set the address values for the server */ server.sin_family = AF_INET; /*address family for TCP and UDP */ server.sin_addr.s_addr = htonl (INADDR_ANY); /*use any address */ server.sin_port = htons (port); /*pick a free port */ /*Bind the socket */ if (bind (sock, (struct sockaddr *) &server, sizeof (server)) < 0) { printf ("Server bind failed. Server already running? Proper permissions?\n"); return (2); } if (!debug) { pid = fork (); if (pid != 0) /* if pid != 0 then we are the parent */ { if (pid == -1) { printf ("Error: Fork failed!\n"); return 0; } else { printf ("Daemon Successfully forked (pid: %d)\n", pid); return 1; } } } else { printf ("tftpd server is running in debug mode and will not fork. \nMulti-threaded mode disabled.\nServer is bound to port %d and awaiting connections\nfile path: %s\n", ntohs (server.sin_port), path); } /*endless loop to get connections from the client */ while (1) { client_len = sizeof (client); /*get the length of the client */ memset (buf, 0, BUFSIZ); /*clear the buffer */ /*the fs message */ n = 0; while (errno == EAGAIN || n == 0) /* This loop is required because on linux we have to acknowledge complete children with waitpid. Ugh. */ { waitpid (-1, &status, WNOHANG); n = recvfrom (sock, buf, BUFSIZ, MSG_DONTWAIT, (struct sockaddr *) &client, (socklen_t *) & client_len); if (n < 0 && errno != EAGAIN) { printf ("The server could not receive from the client"); return 0; } usleep (1000); } if (debug) printf ("Connection from %s, port %d\n", inet_ntoa (client.sin_addr), ntohs (client.sin_port)); bufindex = buf; //start our pointer going if (bufindex++[0] != 0x00) { //first TFTP packet byte needs to be null. Once the value is taken increment it. if (debug) printf ("Malformed tftp packet.\n"); return 0; } tid = ntohs (client.sin_port); /* record the tid */ opcode = *bufindex++; //opcode is in the second byte. if (opcode == 1 || opcode == 2) // RRQ or WRQ. The only two really valid packets on port 69 { strncpy (filename, bufindex, sizeof (filename) - 1); /* Our pointer has been nudged along the recieved string so the first char is the beginning of the filename. This filename is null deliimited so we can use the str family of functions */ bufindex += strlen (filename) + 1; /* move the pointer to after the filename + null byte in the string */ strncpy (mode, bufindex, sizeof (mode) - 1); /* like the filename, we are at the beginning of the null delimited mode */ bufindex += strlen (mode) + 1; /* move pointer... */ if (debug) printf ("opcode: %x filename: %s packet size: %d mode: %s\n", opcode, filename, n, mode); /*show the message to the server */ } else { if (debug) printf ("opcode: %x size: %d \n", opcode, sizeof (n)); /*show the message to the server */ } switch (opcode) /* case one and two are valid on port 69 or server port... no other codes are */ { case 1: if (debug) { printf ("Opcode indicates file read request\n"); tsend (filename, client, mode, tid); } else { pid = fork (); if (pid == 0) { /* if we are pid != 0 then we are the parent */ tsend (filename, client, mode, tid); exit (1); } } break; case 2: if (debug) { printf ("Opcode indicates file write request\n"); tget (filename, client, mode, tid); } else { pid = fork (); if (pid == 0) /* if we are pid != 0 then we are the parent */ { tget (filename, client, mode, tid); exit (1); } } break; default: if (debug) printf ("Invalid opcode detected. Ignoring packet."); break; } //end of while }}voidtget (char *pFilename, struct sockaddr_in client, char *pMode, int tid){ /* local variables */ int sock, len, client_len, opcode, i, j, n, flag = 1; unsigned short int count = 0, rcount = 0; unsigned char filebuf[MAXDATASIZE + 1]; unsigned char packetbuf[MAXDATASIZE + 12]; extern int errno; char filename[128], mode[12], fullpath[196], *bufindex, ackbuf[512]; struct sockaddr_in data; FILE *fp; /* pointer to the file we will be getting */ strcpy (filename, pFilename); //copy the pointer to the filename into a real array strcpy (mode, pMode); //same as above if (debug) printf ("branched to file receive function\n"); if ((sock = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) //startup a socket { printf ("Server reconnect for getting did not work correctly\n"); return; } if (!strncasecmp (mode, "octet", 5) && !strncasecmp (mode, "netascii", 8)) /* these two are the only modes we accept */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -