7 const uint8_t TimeoutTable
[] = {
8 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31, 37, 44,
9 53, 64, 77, 92, 110, 132, 159, 191, 229, 255, 255, 255, 255, 0
12 const char *str_ptr
; /* string pointer */
13 size_t offset
; /* offset into socket structre */
21 #define IFIELD(x) offsetof(struct inode, x)
22 #define PFIELD(x) (offsetof(struct inode, pvt) + \
23 offsetof(struct pxe_pvt_inode, x))
25 static const struct tftp_options tftp_options
[] =
27 { "tsize", IFIELD(size
) },
28 { "blksize", PFIELD(tftp_blksize
) },
30 static const int tftp_nopts
= sizeof tftp_options
/ sizeof tftp_options
[0];
32 static void tftp_error(struct inode
*file
, uint16_t errnum
,
35 static void tftp_close_file(struct inode
*inode
)
37 struct pxe_pvt_inode
*socket
= PVT(inode
);
38 if (!socket
->tftp_goteof
) {
39 tftp_error(inode
, 0, "No error, file close");
42 netconn_delete(socket
->conn
);
48 * Send an ERROR packet. This is used to terminate a connection.
50 * @inode: Inode structure
51 * @errnum: Error number (network byte order)
52 * @errstr: Error string (included in packet)
54 static void tftp_error(struct inode
*inode
, uint16_t errnum
,
63 int len
= min(strlen(errstr
), sizeof(err_buf
.err_msg
)-1);
64 struct pxe_pvt_inode
*socket
= PVT(inode
);
66 err_buf
.err_op
= TFTP_ERROR
;
67 err_buf
.err_num
= errnum
;
68 memcpy(err_buf
.err_msg
, errstr
, len
);
69 err_buf
.err_msg
[len
] = '\0';
72 netbuf_ref(nbuf
, &err_buf
, 4 + len
+ 1);
73 netconn_send(socket
->conn
, nbuf
);
74 /* If something goes wrong, there is nothing we can do, anyway... */
79 * Send ACK packet. This is a common operation and so is worth canning.
81 * @param: inode, Inode pointer
82 * @param: ack_num, Packet # to ack (host byte order)
85 static void ack_packet(struct inode
*inode
, uint16_t ack_num
)
88 static uint16_t ack_packet_buf
[2];
90 struct pxe_pvt_inode
*socket
= PVT(inode
);
92 /* Packet number to ack */
93 ack_packet_buf
[0] = TFTP_ACK
;
94 ack_packet_buf
[1] = htons(ack_num
);
97 netbuf_ref(nbuf
, ack_packet_buf
, 4);
98 err
= netconn_send(socket
->conn
, nbuf
);
102 printf("sent %s\n", err
? "FAILED" : "OK");
107 * Get a fresh packet if the buffer is drained, and we haven't hit
108 * EOF yet. The buffer should be filled immediately after draining!
110 static void tftp_get_packet(struct inode
*inode
)
113 const uint8_t *timeout_ptr
;
118 struct tftp_packet
*pkt
= NULL
;
121 struct pxe_pvt_inode
*socket
= PVT(inode
);
124 * Start by ACKing the previous packet; this should cause
125 * the next packet to be sent.
127 timeout_ptr
= TimeoutTable
;
128 timeout
= *timeout_ptr
++;
132 ack_packet(inode
, socket
->tftp_lastpkt
);
135 nbuf
= netconn_recv(socket
->conn
);
137 jiffies_t now
= jiffies();
139 if (now
-oldtime
>= timeout
) {
141 timeout
= *timeout_ptr
++;
151 nbuf_len
= netbuf_len(nbuf
);
152 if (nbuf_len
<= socket
->tftp_blksize
+ 4)
153 netbuf_copy(nbuf
, socket
->tftp_pktbuf
, nbuf_len
);
155 nbuf_len
= 0; /* invalid packet */
157 if (nbuf_len
< 4) /* Bad size for a DATA packet */
160 pkt
= (struct tftp_packet
*)(socket
->tftp_pktbuf
);
161 if (pkt
->opcode
!= TFTP_DATA
) /* Not a data packet */
164 /* If goes here, recevie OK, break */
172 last_pkt
= socket
->tftp_lastpkt
;
174 serial
= ntohs(pkt
->serial
);
175 if (serial
!= last_pkt
) {
177 * Wrong packet, ACK the packet and try again.
178 * This is presumably because the ACK got lost,
179 * so the server just resent the previous packet.
182 printf("Wrong packet, wanted %04x, got %04x\n", \
183 htons(last_pkt
), htons(*(uint16_t *)(data
+2)));
188 /* It's the packet we want. We're also EOF if the size < blocksize */
189 socket
->tftp_lastpkt
= last_pkt
; /* Update last packet number */
190 buffersize
= nbuf_len
- 4; /* Skip TFTP header */
191 socket
->tftp_dataptr
= socket
->tftp_pktbuf
+ 4;
192 socket
->tftp_filepos
+= buffersize
;
193 socket
->tftp_bytesleft
= buffersize
;
194 if (buffersize
< socket
->tftp_blksize
) {
195 /* it's the last block, ACK packet immediately */
196 ack_packet(inode
, serial
);
198 /* Make sure we know we are at end of file */
199 inode
->size
= socket
->tftp_filepos
;
200 socket
->tftp_goteof
= 1;
201 tftp_close_file(inode
);
205 const struct pxe_conn_ops tftp_conn_ops
= {
206 .fill_buffer
= tftp_get_packet
,
207 .close
= tftp_close_file
,
211 * Open a TFTP connection to the server
213 * @param:inode, the inode to store our state in
214 * @param:ip, the ip to contact to get the file
215 * @param:filename, the file we wanna open
217 * @out: open_file_t structure, stores in file->open_file
218 * @out: the lenght of this file, stores in file->file_len
221 void tftp_open(struct url_info
*url
, int flags
, struct inode
*inode
,
224 struct pxe_pvt_inode
*socket
= PVT(inode
);
231 static const char rrq_tail
[] = "octet\0""tsize\0""0\0""blksize\0""1408";
232 char rrq_packet_buf
[2+2*FILENAME_MAX
+sizeof rrq_tail
];
233 char reply_packet_buf
[PKTBUF_SIZE
];
234 const struct tftp_options
*tftp_opt
;
239 const uint8_t *timeout_ptr
;
244 uint32_t opdata
, *opdata_ptr
;
247 (void)redir
; /* TFTP does not redirect */
250 if (url
->type
!= URL_OLD_TFTP
) {
252 * The TFTP URL specification allows the TFTP to end with a
253 * ;mode= which we just ignore.
255 url_unescape(url
->path
, ';');
259 url
->port
= TFTP_PORT
;
261 socket
->ops
= &tftp_conn_ops
;
262 socket
->conn
= netconn_new(NETCONN_UDP
);
266 socket
->conn
->recv_timeout
= 15; /* A 15 ms recv timeout... */
267 err
= netconn_bind(socket
->conn
, NULL
, 0);
269 printf("netconn_bind error %d\n", err
);
273 buf
= rrq_packet_buf
;
274 *(uint16_t *)buf
= TFTP_RRQ
; /* TFTP opcode */
277 buf
= stpcpy(buf
, url
->path
);
279 buf
++; /* Point *past* the final NULL */
280 memcpy(buf
, rrq_tail
, sizeof rrq_tail
);
281 buf
+= sizeof rrq_tail
;
283 rrq_len
= buf
- rrq_packet_buf
;
285 timeout_ptr
= TimeoutTable
; /* Reset timeout */
288 netconn_disconnect(socket
->conn
);
289 timeout
= *timeout_ptr
++;
291 return; /* No file available... */
295 netbuf_ref(nbuf
, rrq_packet_buf
, rrq_len
);
297 netconn_sendto(socket
->conn
, nbuf
, &addr
, url
->port
);
300 /* If the WRITE call fails, we let the timeout take care of it... */
302 netconn_disconnect(socket
->conn
);
304 nbuf
= netconn_recv(socket
->conn
);
306 jiffies_t now
= jiffies();
307 if (now
- oldtime
>= timeout
)
310 /* Make sure the packet actually came from the server */
312 ok_source
= netbuf_fromaddr(nbuf
)->addr
== url
->ip
;
313 nbuf_len
= netbuf_len(nbuf
);
314 if (nbuf_len
<= PKTBUF_SIZE
)
315 netbuf_copy(nbuf
, reply_packet_buf
, nbuf_len
);
317 nbuf_len
= 0; /* impossible mtu < PKTBUF_SIZE */
324 netconn_connect(socket
->conn
, netbuf_fromaddr(nbuf
), netbuf_fromport(nbuf
));
326 /* filesize <- -1 == unknown */
328 socket
->tftp_blksize
= TFTP_BLOCKSIZE
;
329 buffersize
= nbuf_len
- 2; /* bytes after opcode */
331 goto wait_pkt
; /* Garbled reply */
334 * Get the opcode type, and parse it
336 opcode
= *(uint16_t *)reply_packet_buf
;
340 goto done
; /* ERROR reply; don't try again */
344 * If the server doesn't support any options, we'll get a
345 * DATA reply instead of OACK. Stash the data in the file
346 * buffer and go with the default value for all options...
348 * We got a DATA packet, meaning no options are
349 * suported. Save the data away and consider the
350 * length undefined, *unless* this is the only
356 data
= reply_packet_buf
+ 2;
357 blk_num
= ntohs(*(uint16_t *)data
);
361 socket
->tftp_lastpkt
= blk_num
;
362 if (buffersize
> TFTP_BLOCKSIZE
)
363 goto err_reply
; /* Corrupt */
365 socket
->tftp_pktbuf
= malloc(TFTP_BLOCKSIZE
+ 4);
366 if (!socket
->tftp_pktbuf
)
367 goto err_reply
; /* Internal error */
369 if (buffersize
< TFTP_BLOCKSIZE
) {
371 * This is the final EOF packet, already...
372 * We know the filesize, but we also want to
373 * ack the packet and set the EOF flag.
375 inode
->size
= buffersize
;
376 socket
->tftp_goteof
= 1;
377 ack_packet(inode
, blk_num
);
380 socket
->tftp_bytesleft
= buffersize
;
381 socket
->tftp_dataptr
= socket
->tftp_pktbuf
;
382 memcpy(socket
->tftp_pktbuf
, data
, buffersize
);
387 * Now we need to parse the OACK packet to get the transfer
391 options
= reply_packet_buf
+ 2;
398 * If we find an option which starts with a NUL byte,
399 * (a null option), we're either seeing garbage that some
400 * TFTP servers add to the end of the packet, or we have
401 * no clue how to parse the rest of the packet (what is
402 * an option name and what is a value?) In either case,
410 break; /* Found a final null */
415 break; /* Unterminated option */
417 /* Consume the terminal null */
422 break; /* No option data */
425 * Parse option pointed to by options; guaranteed to be
428 tftp_opt
= tftp_options
;
429 for (i
= 0; i
< tftp_nopts
; i
++) {
430 if (!strcmp(opt
, tftp_opt
->str_ptr
))
435 goto err_reply
; /* Non-negotitated option returned,
436 no idea what it means ...*/
438 /* get the address of the filed that we want to write on */
439 opdata_ptr
= (uint32_t *)((char *)inode
+ tftp_opt
->offset
);
442 /* do convert a number-string to decimal number, just like atoi */
443 while (buffersize
--) {
446 break; /* found a final null */
449 goto err_reply
; /* Not a decimal digit */
450 opdata
= opdata
*10 + d
;
452 *opdata_ptr
= opdata
;
455 if (socket
->tftp_blksize
< 64 || socket
->tftp_blksize
> PKTBUF_SIZE
)
458 /* Parsing successful, allocate buffer */
459 socket
->tftp_pktbuf
= malloc(socket
->tftp_blksize
+ 4);
460 if (!socket
->tftp_pktbuf
)
466 printf("TFTP unknown opcode %d\n", ntohs(opcode
));
471 /* Build the TFTP error packet */
472 tftp_error(inode
, TFTP_EOPTNEG
, "TFTP protocol error");
477 netconn_delete(socket
->conn
);