about summary refs log tree commit diff stats
path: root/src/packet.c
blob: 0c9d592d5774bad2c399d2a82a58e97c5b1f1a2e (plain) (blame)
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
#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_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;
}