forked from freifunk-gluon/ddhcpd
-
Notifications
You must be signed in to change notification settings - Fork 0
/
control.c
123 lines (95 loc) · 3.05 KB
/
control.c
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
#include "control.h"
#include "logger.h"
#include "block.h"
#include "dhcp_options.h"
#include "statistics.h"
extern int log_level;
ATTR_NONNULL_ALL int handle_command(int socket, uint8_t* buffer, ssize_t msglen, ddhcp_config* config) {
if (msglen == 0) {
DEBUG("handle_command(...): zero length command received\n");
return -2;
}
// TODO Rethink command handling and command design
DEBUG("handle_command(socket, cmd:%u, len:%i, blocks, config)\n", buffer[0], msglen);
switch (buffer[0]) {
case DDHCPCTL_BLOCK_SHOW:
if (msglen != 1) {
DEBUG("handle_command(...): message length mismatch\n");
return -2;
}
DEBUG("handle_command(...): show block status\n");
block_show_status(socket, config);
return 0;
case DDHCPCTL_DHCP_OPTIONS_SHOW:
if (msglen != 1) {
DEBUG("handle_command(...): message length mismatch\n");
return -2;
}
DEBUG("handle_command(...): show dhcp options\n");
dhcp_options_show(socket, config);
return 0;
#ifdef DDHCPD_STATISTICS
case DDHCPCTL_STATISTICS:
if (msglen != 1) {
DEBUG("handle_command(...): message length mismatch\n");
}
DEBUG("handle_command(...): show statistics\n");
statistics_show(socket, 0, config);
return 0;
case DDHCPCTL_STATISTICS_RESET:
if (msglen != 1) {
DEBUG("handle_command(...): message length mismatch\n");
}
DEBUG("handle_command(...): show statistics reset\n");
statistics_show(socket, 1, config);
return 0;
#endif
case DDHCPCTL_DHCP_OPTION_SET:
DEBUG("handle_command(...): set dhcp option\n");
if (msglen < 3) {
DEBUG("handle_command(...): message not long enough\n");
return -2;
}
if (buffer[2] + 3ul > (size_t) msglen) {
DEBUG("handle_command(...): message not long enough\n");
return -2;
}
dhcp_option* option = (dhcp_option*) calloc(sizeof(dhcp_option), 1);
if (!option) {
WARNING("handle_command(...): Failed to allocate memory for dhcp option\n");
return -1;
}
option->code = buffer[1];
option->len = buffer[2];
printf("%i:%i\n", buffer[1], buffer[2]);
option->payload = (uint8_t*) calloc(sizeof(uint8_t), option->len);
if (!option->payload) {
WARNING("handle_command(...): Failed to allocate memory for dhcp option payload\n");
free(option);
return -1;
}
memcpy(option->payload, buffer + 3, option->len);
set_option_in_store(&config->options, option);
return 0;
case DDHCPCTL_DHCP_OPTION_REMOVE:
DEBUG("handle_command(...): remove dhcp option\n");
if (msglen < 2) {
DEBUG("handle_command(...): message not long enough\n");
return -2;
}
uint8_t code = buffer[1];
remove_option_in_store(&config->options, code);
return 0;
case DDHCPCTL_LOG_LEVEL_SET:
DEBUG("handle_command(...): set log level\n");
if (msglen < 2) {
DEBUG("handle_command(...): message not long enough\n");
return -2;
}
log_level = buffer[1];
return 0;
default:
WARNING("handle_command(...): unknown command\n");
}
return -1;
}