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 45typedef 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 */ 63static 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 */ 79static 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 95typedef 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 116typedef 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 */ 131static 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 */ 156static 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 176typedef 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 */ 196static 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 */ 213static 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 */ 238static 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 */ 256static 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 */ 268errval_t tftp_send_ack(struct net_socket *socket, uint32_t blockno, 269 struct in_addr addr, uint16_t port); 270#endif /* TFTP_INTERNAL_H_ */ 271