17
#include <sys/socket.h>
22
#include <kernel/printk.h>
28
char name_and_mode[2];
32
char stuff[TFTP_SEGSIZE];
42
} __attribute__ ((packed));
45
char filename[PATH_MAX];
54
struct sockaddr_storage rem_addr;
55
socklen_t rem_addrlen;
59
bool transmission_end;
62
static char *get_transfer_mode(bool binary_on) {
63
return binary_on ? "octet" : "netascii";
66
static int tftp_build_msg_cmd(struct tftp_msg *msg, size_t *msg_len,
67
uint16_t type, const char *filename, char *mode) {
71
msg->opcode = htons(type);
72
*msg_len = sizeof msg->opcode;
74
ptr = &msg->op.cmd.name_and_mode[0];
75
sz = strlen(filename) + 1;
76
memcpy(ptr, filename, sz * sizeof(char));
77
*msg_len += sz * sizeof(char);
80
sz = strlen(mode) + 1;
81
memcpy(ptr, mode, sz * sizeof(char));
82
*msg_len += sz * sizeof(char);
87
static int tftp_build_msg_data(struct tftp_msg *msg, size_t *msg_len,
88
uint8_t *data, int data_len, uint16_t block_num) {
89
msg->opcode = htons(TFTP_DATA);
90
*msg_len = sizeof msg->opcode;
92
msg->op.data.block_num = htons(block_num);
93
*msg_len += sizeof msg->op.data.block_num;
95
memcpy(msg->op.data.stuff, data, data_len);
102
static int tftp_build_msg_ack(struct tftp_msg *msg, size_t *msg_len, uint16_t block_num) {
103
msg->opcode = htons(TFTP_ACK);
104
*msg_len = sizeof msg->opcode;
106
msg->op.ack.block_num = htons(block_num);
107
*msg_len += sizeof msg->op.ack.block_num;
112
static int msg_with_correct_len(struct tftp_msg *msg, size_t msg_len) {
113
size_t field_sz, left_sz;
118
field_sz = sizeof msg->opcode;
119
if (left_sz < field_sz) return 0;
123
switch (ntohs(msg->opcode)) {
126
tmp = &msg->op.cmd.name_and_mode[0];
129
if (left_sz-- == 0) return 0;
130
while (*tmp++ != '\0');
133
if (left_sz-- == 0) return 0;
134
while (*tmp++ != '\0');
138
field_sz = sizeof msg->op.data.block_num;
139
if (left_sz < field_sz) return 0;
146
field_sz = sizeof msg->op.ack.block_num;
147
if (left_sz < field_sz) return 0;
152
field_sz = sizeof msg->op.err.error_code;
153
if (left_sz < field_sz) return 0;
156
tmp = &msg->op.err.error_msg[0];
158
if (left_sz-- == 0) return 0;
159
while (*tmp++ != '\0');
169
tftp_msg_send(struct tftp_msg *msg, size_t msg_len, struct tftp_stream *s) {
175
assert(msg_with_correct_len(msg, msg_len));
177
res = sendto(s->sock, (char *)msg, msg_len, 0,
178
(struct sockaddr *) &s->rem_addr, s->rem_addrlen);
180
log_error("tftp: send() failure");
188
tftp_msg_recv(struct tftp_msg *msg, size_t *msg_len, struct tftp_stream *s) {
195
ret = recvfrom(s->sock, (char *) msg, sizeof (*msg), 0,
196
(struct sockaddr *)&s->rem_addr, &s->rem_addrlen);
198
log_error("tftp: recv() failure");
207
static struct tftp_stream stream;
209
static int make_remote_addr(const char *hostname,
210
struct sockaddr_storage *out_raddr, socklen_t *out_raddr_len) {
212
struct sockaddr_in *raddr_in;
214
raddr_in = (struct sockaddr_in *)out_raddr;
215
memset(out_raddr, 0, sizeof *out_raddr);
216
raddr_in->sin_family = AF_INET;
217
raddr_in->sin_port = htons(TFTP_TRANSFER_PORT);
218
ret = inet_aton(hostname, &raddr_in->sin_addr);
220
fprintf(stderr, "Can't parse remote address '%s`\n", hostname);
224
*out_raddr_len = sizeof *raddr_in;
229
static int tftp_resend_cmd(struct tftp_stream *s) {
230
if (0 != tftp_msg_send(&s->snd, s->snd_len, s)) {
234
if (0 != tftp_msg_recv(&s->rcv, &s->rcv_len, s)) {
241
struct tftp_stream *tftp_new_stream(const char *host, const char *file, int dir, bool binary_mode) {
242
struct tftp_stream *s = &stream;
244
memset(s, 0, sizeof(*s));
246
if (0 != make_remote_addr(host,
251
if (-1 == (s->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) {
255
if (dir == TFTP_DIR_PUT) {
256
if (0 != tftp_build_msg_cmd(&s->snd,
260
get_transfer_mode(binary_mode))) {
264
if (0 != tftp_build_msg_cmd(&s->snd,
268
get_transfer_mode(binary_mode))) {
274
if (tftp_resend_cmd(s)) {
275
log_error("ERROR\n");
278
} while (!msg_with_correct_len(&s->rcv, s->rcv_len));
280
strncpy(s->filename, file, sizeof(s->filename));
289
memset(s, 0, sizeof(*s));
294
int tftp_delete_stream(struct tftp_stream *s) {
303
memset(s, 0, sizeof(*s));
308
int tftp_stream_write(struct tftp_stream *s, uint8_t *buf, size_t len) {
310
log_warning("stream is NULL, do nothing");
314
switch (ntohs(s->rcv.opcode)) {
316
while (ntohs(s->rcv.op.ack.block_num) != s->pkg_number) {
321
return -s->rcv.op.err.error_code;
328
if ((s->pkg_number != 0) && (s->snd_len != sizeof s->snd)) {
333
if (0 != tftp_build_msg_data(&s->snd, &s->snd_len, buf, len, ++s->pkg_number)) {
338
if (0 != tftp_msg_send(&s->snd, s->snd_len, s)) {
347
int tftp_stream_read(struct tftp_stream *s, uint8_t *buf) {
350
if (s->transmission_end) {
354
switch (ntohs(s->rcv.opcode)) {
356
while (ntohs(s->rcv.op.ack.block_num) != s->pkg_number + 1) {
360
data_len = s->rcv_len - (sizeof s->rcv - sizeof s->rcv.op.data.stuff);
361
memcpy(buf, s->rcv.op.data.stuff, data_len);
363
if (s->rcv_len != sizeof(s->rcv)) {
364
s->transmission_end = true;
368
return -s->rcv.op.err.error_code;
374
if (0 != tftp_build_msg_ack(&s->snd, &s->snd_len, ++s->pkg_number)) {
378
if (0 != tftp_msg_send(&s->snd, s->snd_len, s)) {
387
const char *tftp_error(struct tftp_stream *s) {
390
return s->rcv.op.err.error_msg;