7 static 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
);
50 static void udp_send(struct netconn
*conn
, const void *data
, size_t len
)
58 printf("netbuf allocation error\n");
62 pbuf
= netbuf_alloc(nbuf
, len
);
64 printf("pbuf allocation error\n");
68 memcpy(pbuf
, data
, len
);
70 err
= netconn_send(conn
, nbuf
);
72 printf("netconn_send error %d\n", err
);
81 * Send an ERROR packet. This is used to terminate a connection.
83 * @inode: Inode structure
84 * @errnum: Error number (network byte order)
85 * @errstr: Error string (included in packet)
87 static void tftp_error(struct inode
*inode
, uint16_t errnum
,
95 int len
= min(strlen(errstr
), sizeof(err_buf
.err_msg
)-1);
96 struct pxe_pvt_inode
*socket
= PVT(inode
);
98 err_buf
.err_op
= TFTP_ERROR
;
99 err_buf
.err_num
= errnum
;
100 memcpy(err_buf
.err_msg
, errstr
, len
);
101 err_buf
.err_msg
[len
] = '\0';
103 udp_send(socket
->conn
, &err_buf
, 4 + len
+ 1);
107 * Send ACK packet. This is a common operation and so is worth canning.
109 * @param: inode, Inode pointer
110 * @param: ack_num, Packet # to ack (host byte order)
113 static void ack_packet(struct inode
*inode
, uint16_t ack_num
)
115 static uint16_t ack_packet_buf
[2];
116 struct pxe_pvt_inode
*socket
= PVT(inode
);
118 /* Packet number to ack */
119 ack_packet_buf
[0] = TFTP_ACK
;
120 ack_packet_buf
[1] = htons(ack_num
);
122 udp_send(socket
->conn
, ack_packet_buf
, 4);
126 * Get a fresh packet if the buffer is drained, and we haven't hit
127 * EOF yet. The buffer should be filled immediately after draining!
129 static void tftp_get_packet(struct inode
*inode
)
132 const uint8_t *timeout_ptr
;
137 struct tftp_packet
*pkt
= NULL
;
140 struct pxe_pvt_inode
*socket
= PVT(inode
);
143 * Start by ACKing the previous packet; this should cause
144 * the next packet to be sent.
146 timeout_ptr
= TimeoutTable
;
147 timeout
= *timeout_ptr
++;
151 ack_packet(inode
, socket
->tftp_lastpkt
);
154 nbuf
= netconn_recv(socket
->conn
);
156 jiffies_t now
= jiffies();
158 if (now
-oldtime
>= timeout
) {
160 timeout
= *timeout_ptr
++;
170 nbuf_len
= netbuf_len(nbuf
);
171 if (nbuf_len
<= socket
->tftp_blksize
+ 4)
172 netbuf_copy(nbuf
, socket
->tftp_pktbuf
, nbuf_len
);
174 nbuf_len
= 0; /* invalid packet */
176 if (nbuf_len
< 4) /* Bad size for a DATA packet */
179 pkt
= (struct tftp_packet
*)(socket
->tftp_pktbuf
);
180 if (pkt
->opcode
!= TFTP_DATA
) /* Not a data packet */
183 /* If goes here, recevie OK, break */
191 last_pkt
= socket
->tftp_lastpkt
;
193 serial
= ntohs(pkt
->serial
);
194 if (serial
!= last_pkt
) {
196 * Wrong packet, ACK the packet and try again.
197 * This is presumably because the ACK got lost,
198 * so the server just resent the previous packet.
201 printf("Wrong packet, wanted %04x, got %04x\n", \
202 htons(last_pkt
), htons(*(uint16_t *)(data
+2)));
207 /* It's the packet we want. We're also EOF if the size < blocksize */
208 socket
->tftp_lastpkt
= last_pkt
; /* Update last packet number */
209 buffersize
= nbuf_len
- 4; /* Skip TFTP header */
210 socket
->tftp_dataptr
= socket
->tftp_pktbuf
+ 4;
211 socket
->tftp_filepos
+= buffersize
;
212 socket
->tftp_bytesleft
= buffersize
;
213 if (buffersize
< socket
->tftp_blksize
) {
214 /* it's the last block, ACK packet immediately */
215 ack_packet(inode
, serial
);
217 /* Make sure we know we are at end of file */
218 inode
->size
= socket
->tftp_filepos
;
219 socket
->tftp_goteof
= 1;
220 tftp_close_file(inode
);
224 const struct pxe_conn_ops tftp_conn_ops
= {
225 .fill_buffer
= tftp_get_packet
,
226 .close
= tftp_close_file
,
230 * Open a TFTP connection to the server
232 * @param:inode, the inode to store our state in
233 * @param:ip, the ip to contact to get the file
234 * @param:filename, the file we wanna open
236 * @out: open_file_t structure, stores in file->open_file
237 * @out: the lenght of this file, stores in file->file_len
240 void tftp_open(struct url_info
*url
, int flags
, struct inode
*inode
,
243 struct pxe_pvt_inode
*socket
= PVT(inode
);
250 static const char rrq_tail
[] = "octet\0""tsize\0""0\0""blksize\0""1408";
251 char rrq_packet_buf
[2+2*FILENAME_MAX
+sizeof rrq_tail
];
252 char reply_packet_buf
[PKTBUF_SIZE
];
253 const struct tftp_options
*tftp_opt
;
258 const uint8_t *timeout_ptr
;
263 uint32_t opdata
, *opdata_ptr
;
266 (void)redir
; /* TFTP does not redirect */
269 if (url
->type
!= URL_OLD_TFTP
) {
271 * The TFTP URL specification allows the TFTP to end with a
272 * ;mode= which we just ignore.
274 url_unescape(url
->path
, ';');
278 url
->port
= TFTP_PORT
;
280 socket
->ops
= &tftp_conn_ops
;
281 socket
->conn
= netconn_new(NETCONN_UDP
);
285 socket
->conn
->recv_timeout
= 15; /* A 15 ms recv timeout... */
286 err
= netconn_bind(socket
->conn
, NULL
, 0);
288 printf("netconn_bind error %d\n", err
);
292 buf
= rrq_packet_buf
;
293 *(uint16_t *)buf
= TFTP_RRQ
; /* TFTP opcode */
296 buf
= stpcpy(buf
, url
->path
);
298 buf
++; /* Point *past* the final NULL */
299 memcpy(buf
, rrq_tail
, sizeof rrq_tail
);
300 buf
+= sizeof rrq_tail
;
302 rrq_len
= buf
- rrq_packet_buf
;
304 timeout_ptr
= TimeoutTable
; /* Reset timeout */
307 netconn_disconnect(socket
->conn
);
308 timeout
= *timeout_ptr
++;
310 return; /* No file available... */
314 netconn_connect(socket
->conn
, &addr
, url
->port
);
315 udp_send(socket
->conn
, rrq_packet_buf
, rrq_len
);
317 /* If the WRITE call fails, we let the timeout take care of it... */
319 netconn_disconnect(socket
->conn
);
321 nbuf
= netconn_recv(socket
->conn
);
323 jiffies_t now
= jiffies();
324 if (now
- oldtime
>= timeout
)
327 /* Make sure the packet actually came from the server */
329 ok_source
= netbuf_fromaddr(nbuf
)->addr
== url
->ip
;
330 nbuf_len
= netbuf_len(nbuf
);
331 if (nbuf_len
<= PKTBUF_SIZE
)
332 netbuf_copy(nbuf
, reply_packet_buf
, nbuf_len
);
334 nbuf_len
= 0; /* impossible mtu < PKTBUF_SIZE */
341 netconn_connect(socket
->conn
, netbuf_fromaddr(nbuf
), netbuf_fromport(nbuf
));
343 /* filesize <- -1 == unknown */
345 socket
->tftp_blksize
= TFTP_BLOCKSIZE
;
346 buffersize
= nbuf_len
- 2; /* bytes after opcode */
348 goto wait_pkt
; /* Garbled reply */
351 * Get the opcode type, and parse it
353 opcode
= *(uint16_t *)reply_packet_buf
;
357 goto done
; /* ERROR reply; don't try again */
361 * If the server doesn't support any options, we'll get a
362 * DATA reply instead of OACK. Stash the data in the file
363 * buffer and go with the default value for all options...
365 * We got a DATA packet, meaning no options are
366 * suported. Save the data away and consider the
367 * length undefined, *unless* this is the only
373 data
= reply_packet_buf
+ 2;
374 blk_num
= ntohs(*(uint16_t *)data
);
378 socket
->tftp_lastpkt
= blk_num
;
379 if (buffersize
> TFTP_BLOCKSIZE
)
380 goto err_reply
; /* Corrupt */
382 socket
->tftp_pktbuf
= malloc(TFTP_BLOCKSIZE
+ 4);
383 if (!socket
->tftp_pktbuf
)
384 goto err_reply
; /* Internal error */
386 if (buffersize
< TFTP_BLOCKSIZE
) {
388 * This is the final EOF packet, already...
389 * We know the filesize, but we also want to
390 * ack the packet and set the EOF flag.
392 inode
->size
= buffersize
;
393 socket
->tftp_goteof
= 1;
394 ack_packet(inode
, blk_num
);
397 socket
->tftp_bytesleft
= buffersize
;
398 socket
->tftp_dataptr
= socket
->tftp_pktbuf
;
399 memcpy(socket
->tftp_pktbuf
, data
, buffersize
);
404 * Now we need to parse the OACK packet to get the transfer
408 options
= reply_packet_buf
+ 2;
415 * If we find an option which starts with a NUL byte,
416 * (a null option), we're either seeing garbage that some
417 * TFTP servers add to the end of the packet, or we have
418 * no clue how to parse the rest of the packet (what is
419 * an option name and what is a value?) In either case,
427 break; /* Found a final null */
432 break; /* Unterminated option */
434 /* Consume the terminal null */
439 break; /* No option data */
442 * Parse option pointed to by options; guaranteed to be
445 tftp_opt
= tftp_options
;
446 for (i
= 0; i
< tftp_nopts
; i
++) {
447 if (!strcmp(opt
, tftp_opt
->str_ptr
))
452 goto err_reply
; /* Non-negotitated option returned,
453 no idea what it means ...*/
455 /* get the address of the filed that we want to write on */
456 opdata_ptr
= (uint32_t *)((char *)inode
+ tftp_opt
->offset
);
459 /* do convert a number-string to decimal number, just like atoi */
460 while (buffersize
--) {
463 break; /* found a final null */
466 goto err_reply
; /* Not a decimal digit */
467 opdata
= opdata
*10 + d
;
469 *opdata_ptr
= opdata
;
472 if (socket
->tftp_blksize
< 64 || socket
->tftp_blksize
> PKTBUF_SIZE
)
475 /* Parsing successful, allocate buffer */
476 socket
->tftp_pktbuf
= malloc(socket
->tftp_blksize
+ 4);
477 if (!socket
->tftp_pktbuf
)
483 printf("TFTP unknown opcode %d\n", ntohs(opcode
));
488 /* Build the TFTP error packet */
489 tftp_error(inode
, TFTP_EOPTNEG
, "TFTP protocol error");
494 netconn_delete(socket
->conn
);