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

📄 tftp_client.c

📁 tftp 客户端程序
💻 C
字号:
//==========================================================================////      lib/tftp_client.c////      TFTP client support////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD or other sources,// and are covered by the appropriate copyright disclaimers included herein.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas// Date:         2000-04-06// Purpose:      // Description:  //              ////####DESCRIPTIONEND####////==========================================================================// TFTP client support#define __ECOS#include <network.h>#include <arpa/tftp.h>#include <tftp_support.h>#undef  TFTP_TIMEOUT_PERIOD#undef  TFTP_TIMEOUT_MAX  #define TFTP_TIMEOUT_PERIOD    5    #define TFTP_TIMEOUT_MAX       5#define BUF_SIZE               512#define TFTP_PKT_SIZE   (BUF_SIZE+sizeof(struct tftphdr))    #define min(x,y) (x<y ? x : y)#define return_error(error)  {*err=error; \                              if (s>=0) close(s); \                              if (data) free(data); \                              return(-1); \                             }//// Read a file from a host into a local buffer.  Returns the// number of bytes actually read, or (-1) if an error occurs.// On error, *err will hold the reason.//inttftpc_get(char *filename,         struct sockaddr_in *server,         char *buf,         int len,         int mode,         int *err){    int res = 0;    int s, actual_len, data_len, recv_len, from_len;    static int get_port = 7700;    struct sockaddr_in local_addr, server_addr, from_addr;    char *data;    struct tftphdr *hdr;    char *cp, *fp;    struct timeval timeout;    int last_good_block = 0;    struct servent *server_info;    fd_set fds;    int total_timeouts = 0;    if ((data=(char *)malloc(TFTP_PKT_SIZE))==0)        return_error(TFTP_ENOSPACE);    s=-1;    hdr = (struct tftphdr *)data;            data_len=0;        *err = 0;  // Just in case    // Create initial request    hdr->th_opcode = htons(RRQ);  // Read file    data_len+=2;    cp = (char *)&hdr->th_stuff;    fp = filename;    while (*fp) {*cp++ = *fp++; data_len++;}    *cp++ = '\0'; data_len++;    if (mode == TFTP_NETASCII) {        fp = "NETASCII";    } else if (mode == TFTP_OCTET) {        fp = "OCTET";    } else {        return_error(TFTP_INVALID);    }    while (*fp) {*cp++ = *fp++; data_len++;}    *cp++ = '\0'; data_len++;    server_info = getservbyname("tftp", "udp");    if (server_info == (struct servent *)0) {        return_error(TFTP_NETERR);    }    s = socket(AF_INET, SOCK_DGRAM, 0);    if (s < 0) {        // Couldn't open a communications channel        return_error(TFTP_NETERR);    }    memset((char *)&local_addr, 0, sizeof(local_addr));    local_addr.sin_family = AF_INET;    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);    local_addr.sin_port = htons(get_port++);    if (get_port>=7800) get_port=7700;    if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {        // Problem setting up my end        return_error(TFTP_NETERR);    }    memset((char *)&server_addr, 0, sizeof(server_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_addr = server->sin_addr;    if (server->sin_port == 0) {        server_addr.sin_port = server_info->s_port; // Network order already    } else {        server_addr.sin_port = server->sin_port;    }    // Send request    if (sendto(s, data, data_len, 0,                (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {        // Problem sending request        return_error(TFTP_NETERR);    }    // Read data    fp = buf;    while (true) {        timeout.tv_sec = TFTP_TIMEOUT_PERIOD;        timeout.tv_usec = 0;        FD_ZERO(&fds);        FD_SET(s, &fds);        if (select(s+1, &fds, 0, 0, &timeout) <= 0) {            if ((++total_timeouts > TFTP_TIMEOUT_MAX) || (last_good_block == 0)) {                // Timeout - no data received                return_error(TFTP_TIMEOUT);            }            // Try resending last ACK            hdr->th_opcode = htons(ACK);            hdr->th_block = htons(last_good_block);            if (sendto(s, data, 4 /* FIXME */, 0,                        (struct sockaddr *)&from_addr, from_len) < 0) {                // Problem sending request                return_error(TFTP_NETERR);            }        } else {            if (len<TFTP_PKT_SIZE)                recv_len=len+4;     // header length            else                            recv_len = TFTP_PKT_SIZE;            from_len = sizeof(from_addr);            if ((data_len = recvfrom(s, data, recv_len, 0,                                      (struct sockaddr *)&from_addr, &from_len)) < 0) {                // What happened?                return_error(TFTP_NETERR);            }            if (ntohs(hdr->th_opcode) == DATA) {                actual_len = 0;                if (ntohs(hdr->th_block) == (last_good_block+1)) {                    // Consume this data                    cp = hdr->th_data;                    data_len -= 4;  /* Sizeof TFTP header */                    actual_len = data_len;                    res += actual_len;                    while (data_len-- > 0) {                        if (len-- > 0) {                            *fp++ = *cp++;                        } else {                            // Buffer overflow                            // dprintf("\nactural length=%d, recv_len=%d len=%d", actual_len,recv_len,len);                            return_error(TFTP_TOOLARGE);                            // close(s);                            // free(data);                            // return res;                        }                    }                    last_good_block++;                }                // Send out the ACK                hdr->th_opcode = htons(ACK);                hdr->th_block = htons(last_good_block);                if (sendto(s, data, 4 /* FIXME */, 0,                            (struct sockaddr *)&from_addr, from_len) < 0) {                    // Problem sending request                    return_error(TFTP_NETERR);                }                if (len==0 || ((actual_len >= 0) && (actual_len < BUF_SIZE))) {                    // End of data                    // dprintf("\nactural length=%d, recv_len=%d len=%d", actual_len,recv_len,len);                    close(s);                    free(data);                    return res;                }            } else             if (ntohs(hdr->th_opcode) == ERROR) {                return_error(ntohs(hdr->th_code));            } else {                // What kind of packet is this?                return_error(TFTP_PROTOCOL);            }        }    }}//// Send data to a file on a server via TFTP.//inttftpc_put(char *filename,         struct sockaddr_in *server,         char *buf,         int len,         int mode,         int *err){    int res = 0;    int s, actual_len, data_len, recv_len, from_len;    static int put_port = 7800;    struct sockaddr_in local_addr, server_addr, from_addr;    char *data;    struct tftphdr *hdr;    char *cp, *fp, *sfp;    struct timeval timeout;    int last_good_block = 0;    struct servent *server_info;    fd_set fds;    int total_timeouts = 0;    if ((data=(char *)malloc(TFTP_PKT_SIZE))==0)        return_error(TFTP_ENOSPACE);    s=-1;    // hdr = (struct tftphdr *)0;            hdr = (struct tftphdr *)data;            *err = 0;  // Just in case    server_info = getservbyname("tftp", "udp");    if (server_info == (struct servent *)0) {         return_error(TFTP_NETERR);    }    s = socket(AF_INET, SOCK_DGRAM, 0);    if (s < 0) {        // Couldn't open a communications channel         return_error(TFTP_NETERR);    }    memset((char *)&local_addr, 0, sizeof(local_addr));    local_addr.sin_family = AF_INET;    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);    local_addr.sin_port = htons(put_port++);    if (put_port>=7900) put_port=7800;    if (bind(s, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {        // Problem setting up my end         return_error(TFTP_NETERR);    }    memset((char *)&server_addr, 0, sizeof(server_addr));    server_addr.sin_family = AF_INET;    server_addr.sin_addr = server->sin_addr;    if (server->sin_port == 0) {        server_addr.sin_port = server_info->s_port; // Network order already    } else {        server_addr.sin_port = server->sin_port;    }    while (1) {        // Create initial request        hdr->th_opcode = htons(WRQ);  // Create/write file        data_len=2;        cp = (char *)&hdr->th_stuff;        fp = filename;        while (*fp) {*cp++ = *fp++; data_len++;}        *cp++ = '\0'; data_len++;        if (mode == TFTP_NETASCII) {            fp = "NETASCII";        } else if (mode == TFTP_OCTET) {            fp = "OCTET";        } else {             return_error(TFTP_INVALID);        }        while (*fp) {*cp++ = *fp++; data_len++;}        *cp++ = '\0'; data_len++;        // Send request        if (sendto(s, data, data_len, 0,                    (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {            // Problem sending request             return_error(TFTP_NETERR);        }        // Wait for ACK        timeout.tv_sec = TFTP_TIMEOUT_PERIOD;        timeout.tv_usec = 0;        FD_ZERO(&fds);        FD_SET(s, &fds);        if (select(s+1, &fds, 0, 0, &timeout) <= 0) {            if (++total_timeouts > TFTP_TIMEOUT_MAX) {                // Timeout - no ACK received                 return_error(TFTP_TIMEOUT);            }        } else {            recv_len = TFTP_PKT_SIZE;            from_len = sizeof(from_addr);            if ((data_len = recvfrom(s, data, recv_len, 0,                                      (struct sockaddr *)&from_addr, &from_len)) < 0) {                // What happened?                 return_error(TFTP_NETERR);            }            if (ntohs(hdr->th_opcode) == ACK) {                // Write request accepted - start sending data                break;            } else             if (ntohs(hdr->th_opcode) == ERROR) {                 return_error(ntohs(hdr->th_code));            } else {                // What kind of packet is this?                return_error(TFTP_PROTOCOL);            }        }    }    // Send data    sfp = buf;    last_good_block = 1;    while (res < len) {        // Build packet of data to send        data_len = min(SEGSIZE, len-res);        hdr->th_opcode = htons(DATA);        hdr->th_block = htons(last_good_block);        cp = hdr->th_data;        fp = sfp;        actual_len = data_len + 4;        // FIXME - what about "netascii" data?        while (data_len-- > 0) *cp++ = *fp++;        // Send data packet        if (sendto(s, data, actual_len, 0,                    (struct sockaddr *)&from_addr, from_len) < 0) {            // Problem sending request             return_error(TFTP_NETERR);        }        // Wait for ACK        timeout.tv_sec = TFTP_TIMEOUT_PERIOD;        timeout.tv_usec = 0;        FD_ZERO(&fds);        FD_SET(s, &fds);        if (select(s+1, &fds, 0, 0, &timeout) <= 0) {            if (++total_timeouts > TFTP_TIMEOUT_MAX) {                // Timeout - no data received                 return_error(TFTP_TIMEOUT);            }        } else {            recv_len = sizeof(data);            from_len = sizeof(from_addr);            if ((data_len = recvfrom(s, data, recv_len, 0,                                      (struct sockaddr *)&from_addr, &from_len)) < 0) {                // What happened?                 return_error(TFTP_NETERR);            }            if (ntohs(hdr->th_opcode) == ACK) {                if (ntohs(hdr->th_block) == last_good_block) {                    // Advance pointers, etc                    sfp = fp;                    res += (actual_len - 4);                                        last_good_block++;                    // dprintf("Total Len=%d, Current Len=%d\n",len,res);                 } else {                    // dprintf("Send block #%d, got ACK for #%d\n",                     //            last_good_block, ntohs(hdr->th_block));                }            } else             if (ntohs(hdr->th_opcode) == ERROR) {                 return_error(ntohs(hdr->th_code));            } else {                // What kind of packet is this?                 return_error(TFTP_PROTOCOL);            }        }    }    free(data);    close(s);    return res;}

⌨️ 快捷键说明

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