1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include "packet.h"
char *nbd_tftp_error_to_message(nbd_tftp_ecode error) {
switch (error) {
case 0:
return "ERROR";
case 1:
return "File not Found";
case 2:
return "Access violation";
case 3:
return "Disk full or allocation exceeded";
case 4:
return "Illegal TFTP operation";
case 5:
return "Unknown Transfer ID";
case 6:
return "File already exists";
case 7:
return "No such user";
}
return "UNKNOWN ERROR";
}
char *nbd_tftp_ser_data(nbd_tftp_packet_data d) {
char *buf = malloc(sizeof(d.opcode) + sizeof(d.block_num) + d.datalen);
if (buf != NULL) {
uint16_t netopcode = htons(d.opcode);
uint16_t netbnum = htons(d.block_num);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
memcpy((buf + sizeof(netopcode) + sizeof(netbnum)), d.data, d.datalen);
}
return buf;
}
char *nbd_tftp_ser_data_from_parts(uint16_t blocknum, char *data, size_t datalen) {
char *buf = malloc(sizeof(uint16_t) + sizeof(blocknum) + datalen);
if (buf != NULL) {
uint16_t netopcode = htons(3);
uint16_t netbnum = htons(blocknum);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
memcpy((buf + sizeof(netopcode) + sizeof(netbnum)), data, datalen);
}
return buf;
}
nbd_tftp_packet_data nbd_tftp_de_data(char *data, size_t len) {
nbd_tftp_packet_data ret = { 0, 0, (char *)NULL, (size_t)0 };
if ((len >= 4) && (data != NULL)) {
ret.opcode = ((uint16_t)data[0] << 8) + data[1];
ret.block_num = ((uint16_t)data[2] << 8) + data[3];
ret.datalen = len - 4;
if (ret.datalen > 0) {
if ((ret.data = malloc(ret.datalen)) != NULL) {
memcpy(ret.data, (data + 4), ret.datalen);
}
}
}
return ret;
}
char *nbd_tftp_ser_error(nbd_tftp_packet_error e) {
char *buf = malloc(sizeof(e.opcode) + sizeof((uint16_t)e.err) + strlen(e.emsg));
if (buf != NULL) {
uint16_t netopcode = htons(e.opcode);
uint16_t netecode = htons((uint16_t)e.err);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netecode, sizeof(netecode));
memcpy((buf + sizeof(netopcode) + sizeof(netecode)), e.emsg, strlen(e.emsg));
}
return buf;
}
char *nbd_tftp_ser_error_from_code(nbd_tftp_ecode error) {
char *emsg = nbd_tftp_error_to_message(error);
char *buf = malloc(sizeof(uint16_t) + sizeof(uint16_t) + strlen(emsg));
if (buf != NULL) {
uint16_t netopcode = htons(5);
uint16_t netecode = htons((uint16_t)error);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netecode, sizeof(netecode));
memcpy((buf + sizeof(netopcode) + sizeof(netecode)), emsg, strlen(emsg));
}
return buf;
}
char *nbd_tftp_ser_ack(nbd_tftp_packet_ack ack) {
char *buf = malloc(sizeof(ack.opcode) + sizeof(ack.block_num));
if (buf != NULL) {
uint16_t netopcode = htons(ack.opcode);
uint16_t netbnum = htons(ack.block_num);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
}
return buf;
}
char *nbd_tftp_ser_ack_from_block_num(uint16_t block_num) {
char *buf = malloc(sizeof(uint16_t) + sizeof(block_num));
if (buf != NULL) {
uint16_t netopcode = htons(4);
uint16_t netbnum = htons(block_num);
memcpy(buf, &netopcode, sizeof(netopcode));
memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
}
return buf;
}
nbd_tftp_packet_ack nbd_tftp_de_ack(char *buf, ssize_t buflen) {
nbd_tftp_packet_ack ack = { 0, 0 };
if ((buf != NULL) && (buflen == 4)) {
uint16_t opcode = ((uint16_t)buf[0] << 8) + buf[1];
uint16_t block_num = ((uint16_t)buf[2] << 8) + buf[3];
ack.opcode = opcode;
ack.block_num = block_num;
}
return ack;
}
|