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