⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tftpd.c

📁 tftp-1.0源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        return;    }    if (!strncasecmp (mode, "octet", 5) && !strncasecmp (mode, "netascii", 8))	/* these two are the only modes we accept */    {        if (!strncasecmp (mode, "mail", 4))            len = sprintf ((char *) packetbuf[0],                    "%c%c%c%cThis tftp server will not operate as a mail relay%c",                    0x00, 0x05, 0x00, 0x04, 0x00);        else            len = sprintf ((char *) packetbuf[0],                    "%c%c%c%cUnrecognized mode (%s)%c",                    0x00, 0x05, 0x00, 0x04, mode, 0x00);        if (sendto (sock, packetbuf[0], len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */        {            printf                ("Mismatch in number of sent bytes while trying to send mode error packet\n");        }        return;    }    if (strchr (filename, 0x5C) || strchr (filename, 0x2F))	//look for illegal characters in the filename string these are \ and /    {        if (debug)            printf ("Server requested bad file: forbidden name\n");        len =            sprintf ((char *) packetbuf[0],                    "%c%c%c%cIllegal filename.(%s) You may not attempt to descend or ascend directories.%c",                    0x00, 0x05, 0x00, 0x00, filename, 0x00);        if (sendto (sock, packetbuf[0], len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */        {            printf                ("Mismatch in number of sent bytes while trying to send error packet\n");        }        return;    }    strcpy (fullpath, path);    strncat (fullpath, filename, sizeof (fullpath) - 1);	//build the full file path by appending filename to path    fp = fopen (fullpath, "r");    if (fp == NULL)    {				//if the pointer is null then the file can't be opened - Bad perms OR no such file        if (debug)            printf ("Server requested bad file: file not found (%s)\n", fullpath);        len =            sprintf ((char *) packetbuf[0], "%c%c%c%cFile not found (%s)%c", 0x00,                    0x05, 0x00, 0x01, fullpath, 0x00);        if (sendto (sock, packetbuf[0], len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */        {            printf                ("Mismatch in number of sent bytes while trying to send error packet\n");        }        return;    }    else    {        if (debug)            printf ("Sending file... (source: %s)\n", fullpath);    }    memset (filebuf, 0, sizeof (filebuf));    while (1)			/* our break statement will escape us when we are done */    {        acked = 0;        ssize = fread (filebuf, 1, datasize, fp);        count++;			/* count number of datasize byte portions we read from the file */        if (count == 1)		/* we always look for an ack on the FIRST packet */            bcount = 0;        else if (count == 2)	/* The second packet will always start our counter at zreo. This special case needs to exist to avoid a DBZ when count = 2 - 2 = 0 */            bcount = 0;        else            bcount = (count - 2) % ackfreq;        sprintf ((char *) packetbuf[bcount], "%c%c%c%c", 0x00, 0x03, 0x00, 0x00);	/* build data packet but write out the count as zero */        memcpy ((char *) packetbuf[bcount] + 4, filebuf, ssize);        len = 4 + ssize;        packetbuf[bcount][2] = (count & 0xFF00) >> 8;	//fill in the count (top number first)        packetbuf[bcount][3] = (count & 0x00FF);	//fill in the lower part of the count        if (debug)            printf ("Sending packet # %04d (length: %d file chunk: %d)\n",                    count, len, ssize);        if (sendto (sock, packetbuf[bcount], len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */        {            if (debug)                printf ("Mismatch in number of sent bytes\n");            return;        }        if ((count - 1) == 0 || ((count - 1) % ackfreq) == 0                || ssize != datasize)        {            /* The following 'for' loop is used to recieve/timeout ACKs */            for (j = 0; j < RETRIES; j++)            {                client_len = sizeof (ack);                errno = EAGAIN;                n = -1;                for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)                {                    n =                        recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,                                (struct sockaddr *) &ack,                                (socklen_t *) & client_len);                    usleep (1000);                }                if (n < 0 && errno != EAGAIN)                {                    if (debug)                        printf                            ("The server could not receive from the client (errno: %d n: %d)\n",                             errno, n);                    //resend packet                }                else if (n < 0 && errno == EAGAIN)                {                    if (debug)                        printf ("Timeout waiting for ack (errno: %d n: %d)\n",                                errno, n);                    //resend packet                }                else                {                    if (client.sin_addr.s_addr != ack.sin_addr.s_addr)	/* checks to ensure send to ip is same from ACK IP */                    {                        if (debug)                            printf                                ("Error recieving ACK (ACK from invalid address)\n");                        j--;	/* in this case someone else connected to our port. Ignore this fact and retry getting the ack */                        continue;                    }                    if (tid != ntohs (client.sin_port))	/* checks to ensure get from the correct TID */                    {                        if (debug)                            printf                                ("Error recieving file (data from invalid tid)\n");                        len =                            sprintf ((char *) recvbuf,                                    "%c%c%c%cBad/Unknown TID%c", 0x00, 0x05,                                    0x00, 0x05, 0x00);                        if (sendto (sock, recvbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */                        {                            printf                                ("Mismatch in number of sent bytes while trying to send mode error packet\n");                        }                        j--;                        continue;	/* we aren't going to let another connection spoil our first connection */                    }                    /* this formatting code is just like the code in the main function */                    bufindex = (char *) recvbuf;	//start our pointer going                    if (bufindex++[0] != 0x00)                        printf ("bad first nullbyte!\n");                    opcode = *bufindex++;                    rcount = *bufindex++ << 8;                    rcount &= 0xff00;                    rcount += (*bufindex++ & 0x00ff);                    if (opcode != 4 || rcount != count)	/* ack packet should have code 4 (ack) and should be acking the packet we just sent */                    {                        if (debug)                            printf                                ("Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",                                 count, opcode, rcount);                        /* sending error message */                        if (opcode > 5)                        {                            len = sprintf ((char *) recvbuf,                                    "%c%c%c%cIllegal operation%c",                                    0x00, 0x05, 0x00, 0x04, 0x00);                            if (sendto (sock, recvbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* send the data packet */                            {                                printf                                    ("Mismatch in number of sent bytes while trying to send mode error packet\n");                            }                        }                        /* from here we will loop back and resend */                    }                    else                    {                        if (debug)                            printf ("Remote host successfully ACK'd (#%d)\n",                                    rcount);                        break;                    }                }                for (i = 0; i <= bcount; i++)                {                    if (sendto (sock, packetbuf[i], len, 0, (struct sockaddr *) &client, sizeof (client)) != len)	/* resend the data packet */                    {                        if (debug)                            printf ("Mismatch in number of sent bytes\n");                        return;                    }                    if (debug)                        printf ("Ack(s) lost. Resending: %d\n",                                count - bcount + i);                }                if (debug)                    printf ("Ack(s) lost. Resending complete.\n");            }            /* The ack sending 'for' loop ends here */        }        else if (debug)        {            printf ("Not attempting to recieve ack. Not required. count: %d\n",                    count);            n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT, (struct sockaddr *) &ack, (socklen_t *) & client_len);	/* just do a quick check incase the remote host is trying with ackfreq = 1 */        }        if (j == RETRIES)        {            if (debug)                printf ("Ack Timeout. Aborting transfer\n");            fclose (fp);            return;        }        if (ssize != datasize)            break;        memset (filebuf, 0, sizeof (filebuf));	/* fill the filebuf with zeros so that when the fread fills it, it is a null terminated string */    }    fclose (fp);    if (debug)        printf ("File sent successfully\n");    return;}intisnotvaliddir (char *pPath)	/* this function just makes sure that the directory passed to the server is valid and adds a trailing slash if not present */{    DIR *dp;    int len;    dp = opendir (pPath);    if (dp == NULL)    {        return (0);    }    else    {        len = strlen (pPath);        closedir (dp);        if (pPath[len - 1] != '/')        {            pPath[len] = '/';            pPath[len + 1] = 0;        }        return (1);    }}voidusage (void)			/* prints program usage */{    printf        ("Usage: tftpd [options] [path]\nOptions:\n-d (debug mode)\n-h (help; this message)\n-P <port>\n-a <ack freqency. Default 1>\n-s <data chunk size in bytes. Default 512>\n");    return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -