tftp_client.c
来自「eCos操作系统源码」· C语言 代码 · 共 573 行 · 第 1/2 页
C
573 行
freeaddrinfo(res); 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.//// Depreciated. Use tftp_client_get instead.inttftp_get(char *filename, struct sockaddr_in *server, char *buf, int len, int mode, int *err){ char server_name[20]; char *ret; int port; ret = inet_ntop(AF_INET, (void *)&server->sin_addr, server_name, sizeof(server_name)); if (NULL == ret) { *err = TFTP_NETERR; return -1; } port = server->sin_port; return tftp_client_get(filename, server_name, port, buf, len, mode, err);}//// Send data to a file on a server via TFTP.//inttftp_put(char *filename, struct sockaddr_in *server, char *buf, int len, int mode, int *err){ char server_name[20]; char *ret; int port; ret = inet_ntop(AF_INET, (void *)&server->sin_addr, server_name, sizeof(server_name)); if (NULL == ret) { *err = TFTP_NETERR; return -1; } port = server->sin_port; return tftp_client_put(filename, server_name, port, buf, len, mode, err);}//// Put a file to a host from a local buffer. Returns the// number of bytes actually writen, or (-1) if an error occurs.// On error, *err will hold the reason.// This version uses the server name. This can be a name for DNS lookup// or a dotty or colony number format for IPv4 or IPv6.int tftp_client_put(char *filename, char *server, int port, char *buf, int len, int mode, int *err) { int result = 0; int s = -1, actual_len, data_len, recv_len, from_len; static int put_port = 7800; struct sockaddr local_addr, from_addr; char data[SEGSIZE+sizeof(struct tftphdr)]; struct tftphdr *hdr = (struct tftphdr *)data; char *cp, *fp, *sfp; struct timeval timeout; unsigned short last_good_block = 0; fd_set fds; int total_timeouts = 0; struct addrinfo hints; struct addrinfo * addrinfo; struct addrinfo * res; int error; *err = 0; // Just in case memset(&hints,0,sizeof(hints)); hints.ai_family = PF_UNSPEC; error = getaddrinfo(server, "tftp", &hints, &res); if (error) { *err = TFTP_NETERR; return -1; } addrinfo = res; while (addrinfo) { s = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol); if (s >= 0) { memcpy(&local_addr,addrinfo->ai_addr,addrinfo->ai_addrlen); switch(addrinfo->ai_addr->sa_family) { case AF_INET: { struct sockaddr_in * saddr = (struct sockaddr_in *) addrinfo->ai_addr; struct sockaddr_in * laddr = (struct sockaddr_in *) &local_addr; if (port) { saddr->sin_port = htons(port); } laddr->sin_port = htons(put_port++); laddr->sin_addr.s_addr = INADDR_ANY; break; }#ifdef CYGPKG_NET_INET6 case AF_INET6: { struct sockaddr_in6 * saddr = (struct sockaddr_in6 *) addrinfo->ai_addr; struct sockaddr_in6 * laddr = (struct sockaddr_in6 *) &local_addr; if (port) { saddr->sin6_port = htons(port); } laddr->sin6_port = htons(put_port++); laddr->sin6_addr = in6addr_any; break; }#endif default: *err = TFTP_NETERR; goto out; } if (bind(s, (struct sockaddr *)&local_addr, addrinfo->ai_addrlen) < 0) { // Problem setting up my end *err = TFTP_NETERR; goto out; } while (1) { // Create initial request hdr->th_opcode = htons(WRQ); // Create/write file cp = (char *)&hdr->th_stuff; fp = filename; while (*fp) *cp++ = *fp++; *cp++ = '\0'; if (mode == TFTP_NETASCII) { fp = "NETASCII"; } else if (mode == TFTP_OCTET) { fp = "OCTET"; } else { *err = TFTP_INVALID; goto out; } while (*fp) *cp++ = *fp++; *cp++ = '\0'; // Send request if (sendto(s, data, (int)(cp-data), 0, addrinfo->ai_addr, addrinfo->ai_addrlen) < 0) { // Problem sending request *err = TFTP_NETERR; goto nextaddr; } // 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_RETRIES_MAX) { // Timeout - no ACK received *err = TFTP_TIMEOUT; goto nextaddr; } } else { recv_len = sizeof(data); from_len = sizeof(from_addr); if ((data_len = recvfrom(s, &data, recv_len, 0, &from_addr, &from_len)) < 0) { // What happened? *err = TFTP_NETERR; goto out; } if (ntohs(hdr->th_opcode) == ACK) { // Write request accepted - start sending data break; } else if (ntohs(hdr->th_opcode) == ERROR) { *err = ntohs(hdr->th_code); goto out; } else { // What kind of packet is this? goto out; } } } // Send data sfp = buf; last_good_block = 1; while (result < len) { // Build packet of data to send data_len = min(SEGSIZE, len-result); 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, &from_addr, from_len) < 0) { // Problem sending request *err = TFTP_NETERR; goto out; } // 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 *err = TFTP_TIMEOUT; goto out; } } else { recv_len = sizeof(data); from_len = sizeof(from_addr); if ((data_len = recvfrom(s, &data, recv_len, 0, &from_addr, &from_len)) < 0) { // What happened? *err = TFTP_NETERR; goto out; } if (ntohs(hdr->th_opcode) == ACK) { if (ntohs(hdr->th_block) == last_good_block) { // Advance pointers, etc sfp = fp; result += (actual_len - 4); last_good_block++; } else { diag_printf("Send block #%d, got ACK for #%d\n", last_good_block, ntohs(hdr->th_block)); } } else if (ntohs(hdr->th_opcode) == ERROR) { *err = ntohs(hdr->th_code); goto out; } else { // What kind of packet is this? *err = TFTP_PROTOCOL; goto out; } } } close (s); return result; } // If we got here, it means there was a problem connecting to the // server. Try the next address returned by getaddrinfo nextaddr: if (-1 != s) { close(s); } addrinfo=addrinfo->ai_next; } // We ran into problems. Cleanup out: if (-1 != s) { close (s); } freeaddrinfo(res); return -1;}// EOF tftp_client.c
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?