Mercurial > ecos
annotate packages/net/common/current/src/tftp_client.c @ 2453:9ccbf76434a0
2007-12-21 Oyvind Harboe <oyvind.harboe@zylin.com>
* src/tftp_client.c, include/arpa/tftp.h, cdl/net.cdl: tftp
blksize negotiation support. >512 byte block sizes improves tftp
GET performance. Switched to memcpy(), which matters for larger
blocks.
| author | asl |
|---|---|
| date | Sun, 06 Jan 2008 11:13:51 +0000 |
| parents | e400ce1dbe07 |
| children | 74dbf4c3f2e1 |
| rev | line source |
|---|---|
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
1 //========================================================================== |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
2 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
3 // lib/tftp_client.c |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
4 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
5 // TFTP client support |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
6 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
7 //========================================================================== |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
8 //####ECOSGPLCOPYRIGHTBEGIN#### |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
9 // ------------------------------------------- |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
10 // This file is part of eCos, the Embedded Configurable Operating System. |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
| 957 | 12 // Copyright (C) 2003 Andrew.Lunn@ascom.ch |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
13 // |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
14 // eCos is free software; you can redistribute it and/or modify it under |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
15 // the terms of the GNU General Public License as published by the Free |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
16 // Software Foundation; either version 2 or (at your option) any later version. |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
17 // |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
21 // for more details. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
22 // |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
23 // You should have received a copy of the GNU General Public License along |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
24 // with eCos; if not, write to the Free Software Foundation, Inc., |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
26 // |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
27 // As a special exception, if other files instantiate templates or use macros |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
28 // or inline functions from this file, or you compile this file and link it |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
29 // with other works to produce a work based on this file, this file does not |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
30 // by itself cause the resulting work to be covered by the GNU General Public |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
31 // License. However the source code for this file must still be made available |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
32 // in accordance with section (3) of the GNU General Public License. |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
33 // |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
34 // This exception does not invalidate any other reasons why a work based on |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
35 // this file might be covered by the GNU General Public License. |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
36 // |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
38 // at http://sources.redhat.com/ecos/ecos-license/ |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
39 // ------------------------------------------- |
|
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
40 //####ECOSGPLCOPYRIGHTEND#### |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
41 //========================================================================== |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
42 //#####DESCRIPTIONBEGIN#### |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
43 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
44 // Author(s): gthomas |
| 957 | 45 // Contributors: gthomas, andrew.lunn@ascom.ch |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
46 // Date: 2000-04-06 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
47 // Purpose: |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
48 // Description: |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
49 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
50 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
51 //####DESCRIPTIONEND#### |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
52 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
53 //========================================================================== |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
54 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
55 // TFTP client support |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
56 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
57 #include <network.h> |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
58 #include <arpa/tftp.h> |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
59 #include <tftp_support.h> |
| 2453 | 60 #include <stdlib.h> |
| 61 #include <stdio.h> | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
62 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
63 #define min(x,y) (x<y ? x : y) |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
64 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
65 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
66 // Read a file from a host into a local buffer. Returns the |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
67 // number of bytes actually read, or (-1) if an error occurs. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
68 // On error, *err will hold the reason. |
| 957 | 69 // This version uses the server name. This can be a name for DNS lookup |
| 70 // or a dotty or colony number format for IPv4 or IPv6. | |
| 2453 | 71 static int tftp_client_get_inner(char *data, |
| 72 const char * const filename, | |
| 73 const char * const server, | |
| 74 const int port, | |
| 75 char *buf, | |
| 76 int len, | |
| 77 const int mode, | |
| 78 int * const err | |
| 79 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 80 ,int negotiate | |
| 81 #endif | |
| 82 ) { | |
| 83 | |
| 84 int blksize=SEGSIZE; | |
| 957 | 85 int result = 0; |
| 86 int s=-1; | |
|
2025
2de3997bad7b
* src/tftp_dummy_file.c: unsigned char when needed to prevent warnings.
asl
parents:
1302
diff
changeset
|
87 int actual_len, data_len; |
|
2de3997bad7b
* src/tftp_dummy_file.c: unsigned char when needed to prevent warnings.
asl
parents:
1302
diff
changeset
|
88 socklen_t from_len, recv_len; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
89 static int get_port = 7700; |
| 957 | 90 struct addrinfo * addrinfo; |
| 91 struct addrinfo * res; | |
| 92 struct addrinfo hints; | |
| 93 int error; | |
| 94 | |
| 95 struct sockaddr local_addr, from_addr; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
96 struct tftphdr *hdr = (struct tftphdr *)data; |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
97 const char *fp; |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
98 char *cp, *bp; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
99 struct timeval timeout; |
| 270 | 100 unsigned short last_good_block = 0; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
101 fd_set fds; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
102 int total_timeouts = 0; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
103 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
104 *err = 0; // Just in case |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
105 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
106 // Create initial request |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
107 hdr->th_opcode = htons(RRQ); // Read file |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
108 cp = (char *)&hdr->th_stuff; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
109 fp = filename; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
110 while (*fp) *cp++ = *fp++; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
111 *cp++ = '\0'; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
112 if (mode == TFTP_NETASCII) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
113 fp = "NETASCII"; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
114 } else if (mode == TFTP_OCTET) { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
115 fp = "OCTET"; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
116 } else { |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
117 *err = TFTP_INVALID; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
118 return -1; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
119 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
120 while (*fp) *cp++ = *fp++; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
121 *cp++ = '\0'; |
| 2453 | 122 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET |
| 123 if (negotiate) { | |
| 124 fp="blksize"; | |
| 125 while (*fp) | |
| 126 *cp++ = *fp++; | |
| 127 *cp++ = '\0'; | |
| 128 cp+=sprintf(cp, "%d", CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET_SIZE); | |
| 129 *cp++ = '\0'; | |
| 130 } | |
| 131 #endif | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
132 |
| 957 | 133 memset(&hints,0,sizeof(hints)); |
| 134 hints.ai_family = PF_UNSPEC; | |
| 135 error = getaddrinfo(server, "tftp", &hints, &res); | |
| 136 if (error) { | |
| 137 *err = TFTP_NETERR; | |
| 138 return -1; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
139 } |
| 957 | 140 |
| 141 addrinfo = res; | |
| 142 while (addrinfo) { | |
| 143 s = socket(addrinfo->ai_family, addrinfo->ai_socktype, | |
| 2453 | 144 addrinfo->ai_protocol); |
| 957 | 145 if (s >= 0) { |
| 2453 | 146 memcpy(&local_addr,addrinfo->ai_addr,addrinfo->ai_addrlen); |
| 147 switch(addrinfo->ai_addr->sa_family) { | |
| 148 case AF_INET: { | |
| 149 struct sockaddr_in * saddr = | |
| 150 (struct sockaddr_in *) addrinfo->ai_addr; | |
| 151 struct sockaddr_in * laddr = | |
| 152 (struct sockaddr_in *) &local_addr; | |
| 153 if (port) { | |
| 154 saddr->sin_port = htons(port); | |
| 155 } | |
| 156 laddr->sin_port = htons(get_port++); | |
| 157 laddr->sin_addr.s_addr = INADDR_ANY; | |
| 158 break; | |
| 159 } | |
| 957 | 160 #ifdef CYGPKG_NET_INET6 |
| 2453 | 161 case AF_INET6: { |
| 162 struct sockaddr_in6 * saddr = | |
| 163 (struct sockaddr_in6 *) addrinfo->ai_addr; | |
| 164 struct sockaddr_in6 * laddr = | |
| 165 (struct sockaddr_in6 *) &local_addr; | |
| 166 if (port) { | |
| 167 saddr->sin6_port = htons(port); | |
| 168 } | |
| 169 laddr->sin6_port = htons(get_port++); | |
| 170 laddr->sin6_addr = in6addr_any; | |
| 171 break; | |
| 172 } | |
| 957 | 173 #endif |
| 2453 | 174 default: |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
175 *err = TFTP_NETERR; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
176 goto out; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
177 } |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
178 |
| 2453 | 179 if (bind(s,&local_addr,addrinfo->ai_addrlen) < 0) { |
| 180 *err = TFTP_NETERR; | |
| 181 goto out; | |
| 182 } | |
| 183 | |
| 184 // Send request | |
| 185 if (sendto(s, data, (int)(cp-data), 0, | |
| 186 addrinfo->ai_addr, | |
| 187 addrinfo->ai_addrlen) < 0) { | |
| 188 // Problem sending request | |
| 189 *err = TFTP_NETERR; | |
| 190 goto nextaddr; | |
| 191 } | |
| 192 | |
| 193 // Read data | |
| 194 bp = buf; | |
| 195 while (true) { | |
| 196 timeout.tv_sec = TFTP_TIMEOUT_PERIOD; | |
| 197 timeout.tv_usec = 0; | |
| 198 FD_ZERO(&fds); | |
| 199 FD_SET(s, &fds); | |
| 200 if (select(s+1, &fds, 0, 0, &timeout) <= 0) { | |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
201 total_timeouts++; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
202 if ((last_good_block == 0) && (total_timeouts > TFTP_RETRIES_MAX)) { |
| 2453 | 203 // Timeout - no data received. Probably no server. |
| 204 *err = TFTP_TIMEOUT; | |
| 205 goto nextaddr; | |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
206 } |
| 2453 | 207 if (total_timeouts > TFTP_TIMEOUT_MAX) { |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
208 // Timeout - have received data. Network problem? |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
209 *err = TFTP_TIMEOUT; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
210 goto out; |
| 2453 | 211 } |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
212 |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
213 if (last_good_block == 0 ) { |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
214 // Send request |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
215 if (sendto(s, data, (int)(cp-data), 0, |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
216 addrinfo->ai_addr, |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
217 addrinfo->ai_addrlen) < 0) { |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
218 // Problem sending request |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
219 *err = TFTP_NETERR; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
220 goto nextaddr; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
221 } |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
222 } else { |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
223 // Try resending last ACK |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
224 hdr->th_opcode = htons(ACK); |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
225 hdr->th_block = htons(last_good_block); |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
226 if (sendto(s, data, 4 /* FIXME */, 0, |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
227 &from_addr, from_len) < 0) { |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
228 // Problem sending request |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
229 *err = TFTP_NETERR; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
230 goto out; |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
231 } |
|
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
232 } |
| 2453 | 233 } else { |
| 234 recv_len = blksize+sizeof(struct tftphdr); | |
| 235 from_len = sizeof(from_addr); | |
| 236 if ((data_len = recvfrom(s, data, recv_len, 0, | |
| 237 &from_addr, &from_len)) < 0) { | |
| 238 // What happened? | |
| 239 *err = TFTP_NETERR; | |
| 240 goto out; | |
| 241 } | |
| 242 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 243 if (ntohs(hdr->th_opcode) == OACK) { | |
| 244 // We can have only *one* option, the one we sent.. | |
| 245 if (strncmp(data+2, "blksize", data_len)==0) { | |
| 246 blksize=atol(data+2+strlen("blksize")+1); | |
| 247 } else { | |
| 248 // option ignored, use default. | |
| 249 } | |
| 250 // Send out the ACK | |
| 251 hdr->th_opcode = htons(ACK); | |
| 252 hdr->th_block = htons(last_good_block); | |
| 253 if (sendto(s, data, 4 /* FIXME */, 0, | |
| 254 &from_addr, from_len) < 0) { | |
| 255 // Problem sending request | |
| 256 *err = TFTP_NETERR; | |
| 257 goto out; | |
| 258 } | |
| 259 } else | |
| 260 #endif | |
| 261 if (ntohs(hdr->th_opcode) == DATA) { | |
| 262 actual_len = 0; | |
| 263 if (ntohs(hdr->th_block) == (last_good_block+1)) { | |
| 264 // Consume this data | |
| 265 cp = hdr->th_data; | |
| 266 data_len -= 4; /* Sizeof TFTP header */ | |
| 267 actual_len = data_len; | |
| 268 result += actual_len; | |
| 269 if (len<data_len) | |
| 270 { | |
| 271 // Buffer overflow | |
| 272 *err = TFTP_TOOLARGE; | |
| 273 goto out; | |
| 274 } | |
| 275 memcpy(bp, cp, data_len); | |
| 276 bp+=data_len; | |
| 277 len-=data_len; | |
| 278 last_good_block++; | |
| 279 } else { | |
| 280 // To prevent an out-of-sequence packet from | |
| 281 // terminating transmission prematurely, set | |
| 282 // actual_len to a full size packet. | |
| 283 actual_len = blksize; | |
| 284 } | |
| 285 // Send out the ACK | |
| 286 hdr->th_opcode = htons(ACK); | |
| 287 hdr->th_block = htons(last_good_block); | |
| 288 if (sendto(s, data, 4 /* FIXME */, 0, | |
| 289 &from_addr, from_len) < 0) { | |
| 290 // Problem sending request | |
| 291 *err = TFTP_NETERR; | |
| 292 goto out; | |
| 293 } | |
| 294 // A short packet marks the end of the file. | |
| 295 /* 4 = Sizeof TFTP header */ | |
| 296 if ((actual_len >= 0) && (actual_len < blksize)) { | |
| 297 // End of data | |
| 298 close(s); | |
| 299 freeaddrinfo(res); | |
| 300 return result; | |
| 301 } | |
| 302 } else | |
| 303 if (ntohs(hdr->th_opcode) == ERROR) { | |
| 304 *err = ntohs(hdr->th_code); | |
| 305 goto out; | |
| 306 } else { | |
| 307 // What kind of packet is this? | |
| 308 *err = TFTP_PROTOCOL; | |
| 309 goto out; | |
| 310 } | |
| 311 } | |
| 312 } | |
| 957 | 313 } |
| 314 // If we got here, it means there was a problem connecting to the | |
| 315 // server. Try the next address returned by getaddrinfo | |
| 316 nextaddr: | |
| 317 if (-1 != s) { | |
| 2453 | 318 close(s); |
| 957 | 319 } |
| 320 addrinfo=addrinfo->ai_next; | |
| 321 } | |
| 322 // We ran into problems. Cleanup | |
| 323 out: | |
| 324 if (-1 != s) { | |
| 325 close (s); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
326 } |
| 957 | 327 freeaddrinfo(res); |
| 328 return -1; | |
| 329 } | |
| 2453 | 330 |
| 331 | |
| 332 int tftp_client_get(const char * const filename, | |
| 333 const char * const server, | |
| 334 const int port, | |
| 335 char *buf, | |
| 336 int len, | |
| 337 const int mode, | |
| 338 int * const err) { | |
| 339 int result; | |
| 340 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 341 char *data = malloc(CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET_SIZE+ | |
| 342 sizeof(struct tftphdr)); | |
| 343 if (data==NULL) { | |
| 344 *err=TFTP_ENOSPACE; | |
| 345 return -1; | |
| 346 } | |
| 347 #else | |
| 348 char data[SEGSIZE+sizeof(struct tftphdr)]; | |
| 349 #endif | |
| 350 result=tftp_client_get_inner(data, filename, server, | |
| 351 port, buf, len, mode, err | |
| 352 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 353 ,1 | |
| 354 #endif | |
| 355 ); | |
| 356 if (result<0) | |
| 357 { | |
| 358 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 359 // try without negotiating packet size. The serves that do | |
| 360 // not support options negotiation may or may not ignore the | |
| 361 // options. If they return an error in the case of options | |
| 362 // this code path will try without packet size negotiation. | |
| 363 result=tftp_client_get_inner(data, filename, server, | |
| 364 port, buf, len, mode, err, | |
| 365 0); | |
| 366 #endif | |
| 367 } | |
| 368 | |
| 369 #ifdef CYGPKG_NET_TFTPD_CLIENT_BIG_PACKET | |
| 370 free(data); | |
| 371 #endif | |
| 372 | |
| 373 return result; | |
| 374 } | |
| 375 | |
| 957 | 376 // |
| 377 // Read a file from a host into a local buffer. Returns the | |
| 378 // number of bytes actually read, or (-1) if an error occurs. | |
| 379 // On error, *err will hold the reason. | |
| 380 // | |
| 381 // Depreciated. Use tftp_client_get instead. | |
| 382 int | |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
383 tftp_get(const char * const filename, |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
384 const struct sockaddr_in * const server, |
| 957 | 385 char *buf, |
| 386 int len, | |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
387 const int mode, |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
388 int * const err) |
| 957 | 389 { |
| 390 char server_name[20]; | |
| 391 char *ret; | |
| 392 int port; | |
| 393 | |
| 394 ret = inet_ntop(AF_INET, (void *)&server->sin_addr, | |
| 2453 | 395 server_name, sizeof(server_name)); |
| 957 | 396 if (NULL == ret) { |
| 397 *err = TFTP_NETERR; | |
| 398 return -1; | |
| 399 } | |
| 400 port = server->sin_port; | |
| 401 | |
| 402 return tftp_client_get(filename, server_name, port, buf, len, mode, err); | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
403 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
404 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
405 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
406 // Send data to a file on a server via TFTP. |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
407 // |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
408 int |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
409 tftp_put(const char * const filename, |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
410 const struct sockaddr_in * const server, |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
411 const char *buf, |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
412 int len, |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
413 const int mode, |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
414 int * const err) |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
415 { |
| 957 | 416 char server_name[20]; |
| 417 char *ret; | |
| 418 int port; | |
| 419 | |
| 420 ret = inet_ntop(AF_INET, (void *)&server->sin_addr, | |
| 2453 | 421 server_name, sizeof(server_name)); |
| 957 | 422 if (NULL == ret) { |
| 423 *err = TFTP_NETERR; | |
| 424 return -1; | |
| 425 } | |
| 426 port = server->sin_port; | |
| 427 | |
| 428 return tftp_client_put(filename, server_name, port, buf, len, mode, err); | |
| 429 } | |
| 430 | |
| 431 // | |
| 432 // Put a file to a host from a local buffer. Returns the | |
| 433 // number of bytes actually writen, or (-1) if an error occurs. | |
| 434 // On error, *err will hold the reason. | |
| 435 // This version uses the server name. This can be a name for DNS lookup | |
| 436 // or a dotty or colony number format for IPv4 or IPv6. | |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
437 int tftp_client_put(const char * const filename, |
| 2453 | 438 const char * const server, |
| 439 const int port, | |
| 440 const char *buf, | |
| 441 int len, | |
| 442 const int mode, | |
| 443 int * const err) { | |
| 957 | 444 |
| 445 int result = 0; | |
|
2025
2de3997bad7b
* src/tftp_dummy_file.c: unsigned char when needed to prevent warnings.
asl
parents:
1302
diff
changeset
|
446 int s = -1, actual_len, data_len; |
|
2de3997bad7b
* src/tftp_dummy_file.c: unsigned char when needed to prevent warnings.
asl
parents:
1302
diff
changeset
|
447 socklen_t recv_len, from_len; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
448 static int put_port = 7800; |
| 957 | 449 struct sockaddr local_addr, from_addr; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
450 char data[SEGSIZE+sizeof(struct tftphdr)]; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
451 struct tftphdr *hdr = (struct tftphdr *)data; |
|
2069
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
452 const char *fp, *sfp; |
|
e400ce1dbe07
* src/tftp_client.c, include/tftp_support.h: const parameters
asl
parents:
2025
diff
changeset
|
453 char *cp; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
454 struct timeval timeout; |
| 270 | 455 unsigned short last_good_block = 0; |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
456 fd_set fds; |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
457 int total_timeouts = 0; |
| 957 | 458 struct addrinfo hints; |
| 459 struct addrinfo * addrinfo; | |
| 460 struct addrinfo * res; | |
| 461 int error; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
462 |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
463 *err = 0; // Just in case |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
464 |
| 957 | 465 memset(&hints,0,sizeof(hints)); |
| 466 hints.ai_family = PF_UNSPEC; | |
| 467 error = getaddrinfo(server, "tftp", &hints, &res); | |
| 468 if (error) { | |
| 469 *err = TFTP_NETERR; | |
| 470 return -1; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
471 } |
| 957 | 472 |
| 473 addrinfo = res; | |
| 474 while (addrinfo) { | |
| 475 s = socket(addrinfo->ai_family, addrinfo->ai_socktype, | |
| 2453 | 476 addrinfo->ai_protocol); |
| 957 | 477 if (s >= 0) { |
| 2453 | 478 memcpy(&local_addr,addrinfo->ai_addr,addrinfo->ai_addrlen); |
| 479 switch(addrinfo->ai_addr->sa_family) { | |
| 480 case AF_INET: { | |
| 481 struct sockaddr_in * saddr = | |
| 482 (struct sockaddr_in *) addrinfo->ai_addr; | |
| 483 struct sockaddr_in * laddr = | |
| 484 (struct sockaddr_in *) &local_addr; | |
| 485 if (port) { | |
| 486 saddr->sin_port = htons(port); | |
| 487 } | |
| 488 laddr->sin_port = htons(put_port++); | |
| 489 laddr->sin_addr.s_addr = INADDR_ANY; | |
| 490 break; | |
| 491 } | |
| 957 | 492 #ifdef CYGPKG_NET_INET6 |
| 2453 | 493 case AF_INET6: { |
| 494 struct sockaddr_in6 * saddr = | |
| 495 (struct sockaddr_in6 *) addrinfo->ai_addr; | |
| 496 struct sockaddr_in6 * laddr = | |
| 497 (struct sockaddr_in6 *) &local_addr; | |
| 498 if (port) { | |
| 499 saddr->sin6_port = htons(port); | |
| 500 } | |
| 501 laddr->sin6_port = htons(put_port++); | |
| 502 laddr->sin6_addr = in6addr_any; | |
| 503 break; | |
| 504 } | |
| 957 | 505 #endif |
| 2453 | 506 default: |
| 507 *err = TFTP_NETERR; | |
| 508 goto out; | |
| 509 } | |
| 510 if (bind(s, | |
| 511 (struct sockaddr *)&local_addr, | |
| 512 addrinfo->ai_addrlen) < 0) { | |
| 513 // Problem setting up my end | |
| 514 *err = TFTP_NETERR; | |
| 515 goto out; | |
| 516 } | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
517 |
| 2453 | 518 while (1) { |
| 519 // Create initial request | |
| 520 hdr->th_opcode = htons(WRQ); // Create/write file | |
| 521 cp = (char *)&hdr->th_stuff; | |
| 522 fp = filename; | |
| 523 while (*fp) *cp++ = *fp++; | |
| 524 *cp++ = '\0'; | |
| 525 if (mode == TFTP_NETASCII) { | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
526 fp = "NETASCII"; |
| 2453 | 527 } else if (mode == TFTP_OCTET) { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
528 fp = "OCTET"; |
| 2453 | 529 } else { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
530 *err = TFTP_INVALID; |
| 2453 | 531 goto out; |
| 532 } | |
| 533 while (*fp) *cp++ = *fp++; | |
| 534 *cp++ = '\0'; | |
| 535 // Send request | |
| 536 if (sendto(s, data, (int)(cp-data), 0, | |
| 537 addrinfo->ai_addr, | |
| 538 addrinfo->ai_addrlen) < 0) { | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
539 // Problem sending request |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
540 *err = TFTP_NETERR; |
| 2453 | 541 goto nextaddr; |
| 542 } | |
| 543 // Wait for ACK | |
| 544 timeout.tv_sec = TFTP_TIMEOUT_PERIOD; | |
| 545 timeout.tv_usec = 0; | |
| 546 FD_ZERO(&fds); | |
| 547 FD_SET(s, &fds); | |
| 548 if (select(s+1, &fds, 0, 0, &timeout) <= 0) { | |
|
1007
16d247bb9c70
* src/ifaddrs.c (getifaddrs): Fill in flags, netmask and broadcast
asl
parents:
957
diff
changeset
|
549 if (++total_timeouts > TFTP_RETRIES_MAX) { |
| 2453 | 550 // Timeout - no ACK received |
| 551 *err = TFTP_TIMEOUT; | |
| 552 goto nextaddr; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
553 } |
| 2453 | 554 } else { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
555 recv_len = sizeof(data); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
556 from_len = sizeof(from_addr); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
557 if ((data_len = recvfrom(s, &data, recv_len, 0, |
| 957 | 558 &from_addr, &from_len)) < 0) { |
| 2453 | 559 // What happened? |
| 560 *err = TFTP_NETERR; | |
| 561 goto out; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
562 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
563 if (ntohs(hdr->th_opcode) == ACK) { |
| 2453 | 564 // Write request accepted - start sending data |
| 565 break; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
566 } else |
| 2453 | 567 if (ntohs(hdr->th_opcode) == ERROR) { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
568 *err = ntohs(hdr->th_code); |
| 957 | 569 goto out; |
| 2453 | 570 } else { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
571 // What kind of packet is this? |
| 2453 | 572 goto out; |
| 573 } | |
| 574 } | |
| 575 } | |
| 576 | |
| 577 // Send data | |
| 578 sfp = buf; | |
| 579 last_good_block = 1; | |
| 580 while (result < len) { | |
| 581 // Build packet of data to send | |
| 582 data_len = min(SEGSIZE, len-result); | |
| 583 hdr->th_opcode = htons(DATA); | |
| 584 hdr->th_block = htons(last_good_block); | |
| 585 cp = hdr->th_data; | |
| 586 fp = sfp; | |
| 587 actual_len = data_len + 4; | |
| 588 // FIXME - what about "netascii" data? | |
| 589 while (data_len-- > 0) *cp++ = *fp++; | |
| 590 // Send data packet | |
| 591 if (sendto(s, data, actual_len, 0, | |
| 592 &from_addr, from_len) < 0) { | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
593 // Problem sending request |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
594 *err = TFTP_NETERR; |
| 2453 | 595 goto out; |
| 596 } | |
| 597 // Wait for ACK | |
| 598 timeout.tv_sec = TFTP_TIMEOUT_PERIOD; | |
| 599 timeout.tv_usec = 0; | |
| 600 FD_ZERO(&fds); | |
| 601 FD_SET(s, &fds); | |
| 602 if (select(s+1, &fds, 0, 0, &timeout) <= 0) { | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
603 if (++total_timeouts > TFTP_TIMEOUT_MAX) { |
| 2453 | 604 // Timeout - no data received |
| 605 *err = TFTP_TIMEOUT; | |
| 606 goto out; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
607 } |
| 2453 | 608 } else { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
609 recv_len = sizeof(data); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
610 from_len = sizeof(from_addr); |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
611 if ((data_len = recvfrom(s, &data, recv_len, 0, |
| 957 | 612 &from_addr, &from_len)) < 0) { |
| 2453 | 613 // What happened? |
| 614 *err = TFTP_NETERR; | |
| 615 goto out; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
616 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
617 if (ntohs(hdr->th_opcode) == ACK) { |
| 2453 | 618 if (ntohs(hdr->th_block) == last_good_block) { |
| 619 // Advance pointers, etc | |
| 620 sfp = fp; | |
| 621 result += (actual_len - 4); | |
| 622 last_good_block++; | |
| 623 } else { | |
| 624 diag_printf("Send block #%d, got ACK for #%d\n", | |
| 625 last_good_block, ntohs(hdr->th_block)); | |
| 626 } | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
627 } else |
| 2453 | 628 if (ntohs(hdr->th_opcode) == ERROR) { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
629 *err = ntohs(hdr->th_code); |
| 957 | 630 goto out; |
| 2453 | 631 } else { |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
632 // What kind of packet is this? |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
633 *err = TFTP_PROTOCOL; |
| 2453 | 634 goto out; |
| 635 } | |
| 636 } | |
| 637 } | |
| 638 close (s); | |
| 639 return result; | |
| 957 | 640 } |
| 641 | |
| 642 // If we got here, it means there was a problem connecting to the | |
| 643 // server. Try the next address returned by getaddrinfo | |
| 644 nextaddr: | |
| 645 if (-1 != s) { | |
| 2453 | 646 close(s); |
| 957 | 647 } |
| 648 addrinfo=addrinfo->ai_next; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
649 } |
| 957 | 650 // We ran into problems. Cleanup |
| 651 out: | |
| 652 if (-1 != s) { | |
| 653 close (s); | |
| 654 } | |
| 655 freeaddrinfo(res); | |
| 656 return -1; | |
|
208
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
657 } |
|
e0c0827131d1
Merge from eCos master repository on 2002-05-20-20:11:54-BST
jlarmour
parents:
diff
changeset
|
658 |
|
490
7c34839e7e97
* src/bootp_support.c: Fix licence which should always have been
jlarmour
parents:
270
diff
changeset
|
659 // EOF tftp_client.c |
