tftpclient: converting to net sockets
[barrelfish] / lib / tftp / tftp_internal.h
1 /**
2  * \file
3  * \brief TFTP library
4  */
5
6 /*
7  * Copyright (c) 2015 ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13  */
14
15 #ifndef TFTP_INTERNAL_H_
16 #define TFTP_INTERNAL_H_ 1
17
18 /*
19  * ------------------------------------------------------------------------------
20  * General defines
21  * ------------------------------------------------------------------------------
22  */
23 #define TFTP_BLOCKSIZE      512
24 #define TFTP_MAX_MSGSIZE    (4 + TFTP_BLOCKSIZE)
25 #define TFTP_TIMEOUT        500
26
27
28 /*
29  * ------------------------------------------------------------------------------
30  * Debugging options
31  * ------------------------------------------------------------------------------
32  */
33 //#define TFTP_DEBUG(x...) debug_printf("[tftp] " x)
34 #define TFTP_DEBUG(x...)
35 //#define TFTP_DEBUG_PACKETS(x...) debug_printf("[tftp] " x)
36 #define TFTP_DEBUG_PACKETS(x...)
37
38 /*
39  * ------------------------------------------------------------------------------
40  * operation codes
41  * ------------------------------------------------------------------------------
42  */
43
44 ///< TFTP Operation Codes
45 typedef enum tftp_op {
46     TFTP_OP_INVALID   = 0,  ///< op code is invalid
47     TFTP_OP_READ_REQ  = 1,  ///< read request
48     TFTP_OP_WRITE_REQ = 2,  ///< write request
49     TFTP_OP_DATA      = 3,  ///< data response
50     TFTP_OP_ACK       = 4,  ///< ack response
51     TFTP_OP_ERROR     = 5   ///< error response
52 } tpft_op_t;
53
54
55 /**
56  * \brief writes the opcode into the buffer
57  *
58  * \param buf       buffer where to write the opcode to
59  * \param opcode    opcode to be written
60  *
61  * \return number of bytes written
62  */
63 static inline size_t set_opcode(void *buf, uint16_t opcode)
64 {
65     uint8_t *p = buf;
66     *p = ((opcode >> 8) & 0xff); p++;
67     *p = (opcode & 0xff);
68
69     return sizeof(uint16_t);
70 }
71
72 /**
73  * \brief obtains the opcode from the buffer
74  *
75  * \param buf   buffer where to extract the op code
76  *
77  * \return tftp op code
78  */
79 static inline tpft_op_t get_opcode(void *buf)
80 {
81     uint8_t *p = buf;
82     uint16_t opcode = (*p) << 8; p++;
83     opcode |= *p;
84
85     return (tpft_op_t)opcode;
86 }
87
88 /*
89  * ------------------------------------------------------------------------------
90  * Operation codes
91  * ------------------------------------------------------------------------------
92  */
93
94 ///< TFTP state
95 typedef enum tpft_st {
96     TFTP_ST_INVALID,        ///< state is invalid
97     TFTP_ST_CLOSED,         ///< connection is closed
98     TFTP_ST_IDLE,           ///< the client is connected and in the  idle state
99     TFTP_ST_LAST_ACK_SENT,  ///< last ack has been sent
100     TFTP_ST_LAST_DATA_SENT, ///< last data response sent
101     TFTP_ST_ERROR,          ///< tftp request resulted in an error
102     TFTP_ST_READ_REQ_SENT,  ///< a read request has been sent
103     TFTP_ST_WRITE_REQ_SENT, ///< a write request has been sent
104     TFTP_ST_DATA_SENT,      ///< data respnse is being sent
105     TFTP_ST_ACK_SENT,       ///< ack has been sent
106 } tftp_st_t;
107
108
109 /*
110  * ------------------------------------------------------------------------------
111  * Transfer modes
112  * ------------------------------------------------------------------------------
113  */
114
115 ///< operation mode of the TFTP connection
116 typedef enum tftp_mode {
117     TFTP_MODE_INVALID,      ///< invalid operation mode
118     TFTP_MODE_OCTET,        ///< use octet moded
119     TFTP_MODE_NETASCII,     ///< use netsascii mode
120     TFTP_MODE_MAIL,         ///< use mail mode
121 } tftp_mode_t;
122
123 /**
124  * \brief sets the transfer mode in a buffer
125  *
126  * \param buf   buffer where to write the transfer mode to
127  * \param mode  transfer mode to write
128  *
129  * \returns number of bytes written
130  */
131 static inline size_t set_mode(void *buf, tftp_mode_t mode)
132 {
133     switch(mode) {
134         case TFTP_MODE_OCTET:
135             return snprintf(buf, 6, "octet")+1;
136             break;
137         case TFTP_MODE_NETASCII:
138             return snprintf(buf, 6, "netascii")+1;
139             break;
140         case TFTP_MODE_MAIL:
141             return snprintf(buf, 5, "mail")+1;
142             break;
143         default:
144             assert(!"this should not happen");
145             return 0;
146     }
147 }
148
149 /**
150  * \brief parses the transfer mode from the buffer
151  *
152  * \param buf   buffer to extract the transfer mode from
153  *
154  * \return tftp transfer mode
155  */
156 static inline tftp_mode_t get_mode(void *buf)
157 {
158     if (strncmp(buf, "octet", 5) == 0) {
159         return TFTP_MODE_OCTET;
160     } else if (strncmp(buf, "netascii", 8) == 0) {
161         return TFTP_MODE_NETASCII;
162     } else if (strncmp(buf, "mail", 4) == 0) {
163         return TFTP_MODE_MAIL;
164     }
165
166     return TFTP_MODE_INVALID;
167 }
168
169 /*
170  * ------------------------------------------------------------------------------
171  * Error
172  * ------------------------------------------------------------------------------
173  */
174
175 ///< possible tftp errors in packages
176 typedef enum tftp_err {
177     TFTP_ERR_NOT_DEFINED = 0,             ///< not defined
178     TFTP_ERR_NOT_FOUND =  1,              ///< file not found
179     TFTP_ERR_ACCESS_DENIED =  2,          ///< access denied
180     TFTP_ERR_DISK_FULL = 3,               ///< disk is full
181     TFTP_ERR_UNKNOWN_TID =   4,           ///< unkown transfer id
182     TFTP_ERR_ILLEGAL_OP = 5,              ///< illegal operation
183     TFTP_ERR_FILE_EXISTS =  6,            ///< destination file exist
184     TFTP_ERR_NO_SUCH_USER =  7,           ///< no such user
185     TFTP_ERR_INVALID_BUFFER = 0xFFFFFFFF, ///< invalid buffer
186 } tftp_err_t;
187
188 /**
189  * \brief extracts the error code from an error package
190  *
191  * \param buf       buffer to extract the error code from
192  * \param buflen    length of the buffer in bytes
193  *
194  * \returns tftp error code
195  */
196 static inline tftp_err_t get_error(void *buf, size_t buflen) {
197     if (buflen < 5) {
198         return TFTP_ERR_INVALID_BUFFER;
199     }
200     uint8_t *p = buf;
201
202     return (tftp_err_t)((p[2] << 8) + p[3]);
203 }
204
205 /**
206  * \brief sets the error code in a buffer
207  *
208  * \param buf   buffer where to write the error code
209  * \param error error code to write
210  *
211  * \returns number of bytes written
212  */
213 static inline size_t set_error(void *buf, tftp_err_t error)
214 {
215     uint8_t *p = buf;
216     p[0] = 0;
217     p[1] = 1;
218     p[2] = ((error >> 8) & 0xff);
219     p[3] = (error & 0xff);
220
221     return 4;
222 }
223
224 /*
225  * ------------------------------------------------------------------------------
226  * Data packets
227  * ------------------------------------------------------------------------------
228  */
229
230 /**
231  * \brief extracts the block number from a buffer
232  *
233  * \param buf       buffer where to extract the block number
234  * \param buflen    length of the buffer
235  *
236  * \return block number or TFTP_BLOCKNO_INVALID
237  */
238 static inline uint32_t get_block_no(void *buf, size_t buflen)
239 {
240     if (buflen < 4) {
241         return TFTP_ERR_INVALID_BUFFER;
242     }
243
244     uint8_t *data = buf;
245     return (data[2] << 8) + data[3];
246 }
247
248 /**
249  * \brief sets the block number in a buffer
250  *
251  * \param buf       buffer where to write the block number to
252  * \param blockno   block number to write
253  *
254  * \return  number of bytes written
255  */
256 static inline size_t set_block_no(void *buf, uint16_t blockno) {
257     uint8_t *p = buf;
258     *p = (uint8_t)((blockno >> 8) & 0xff); p++;
259     *p = (uint8_t)(blockno & 0xff);
260     return sizeof(uint16_t);
261 }
262
263 /*
264  * ------------------------------------------------------------------------------
265  * Sending generic messages
266  * ------------------------------------------------------------------------------
267  */
268 errval_t tftp_send_ack(struct net_socket *socket, uint32_t blockno,
269                        struct in_addr addr, uint16_t port,
270                        void *payload);
271 #endif /* TFTP_INTERNAL_H_ */