Skip to content

Commit 1d199d3

Browse files
robertwilhelmallannielsen
authored andcommitted
Add CoAP protocol support.
1 parent e922a34 commit 1d199d3

File tree

7 files changed

+428
-37
lines changed

7 files changed

+428
-37
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
22
cmake_minimum_required(VERSION 2.8.12)
33

44
option(TEST_ENABLE "Enable tests" off)
@@ -55,6 +55,7 @@ add_library(libef STATIC
5555
src/ef-arp.c
5656
src/ef-buf.c
5757
src/ef-capture.c
58+
src/ef-coap.c
5859
src/ef-eth.c
5960
src/ef-exec.c
6061
src/ef-icmp.c

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# EasyFraems (`ef`)
1+
# EasyFrames (`ef`)
22

33
This is a small and simple command-line tool for network testing. The tool makes
44
it simple to compose a frame, inject and express what and where frames are

src/ef-coap.c

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
#include <stdio.h>
2+
#include "ef.h"
3+
4+
5+
enum {
6+
COAP_FIELD_VERSION,
7+
COAP_FIELD_TYPE,
8+
COAP_FIELD_TOKEN_LENGTH,
9+
COAP_FIELD_CODE,
10+
COAP_FIELD_MESSAGE_ID,
11+
COAP_FIELD_TOKEN,
12+
13+
COAP_FIELD_LAST
14+
};
15+
16+
enum {
17+
COAP_OPT_FIELD_NUM,
18+
COAP_OPT_FIELD_VAL,
19+
20+
COAP_OPT_FIELD_LAST
21+
};
22+
23+
enum {
24+
COAP_PARMS_FIELD_PAR,
25+
26+
COAP_PARMS_FIELD_LAST
27+
};
28+
29+
static buf_t *coap_parse_code(hdr_t *hdr, int hdr_offset, const char *s, int bytes) {
30+
buf_t *b = NULL;
31+
uint8_t tmp;
32+
uint8_t valid = 0;
33+
34+
if ((strlen(s) == 4)
35+
&& (s[0] >= '0' && s[0] <= '7')
36+
&& (s[1] == '.')
37+
&& (s[2] >= '0' && s[2] <= '3')
38+
&& (s[3] >= '0' && s[2] <= '9')) {
39+
tmp = s[2] - '0';
40+
tmp = tmp * 10 + s[3] - '0';
41+
if (tmp < 32) {
42+
tmp = ((s[0] - '0') << 5) + tmp;
43+
valid = 1;
44+
}
45+
}
46+
47+
if (valid) {
48+
b = balloc(1);
49+
b->data[0] = tmp;
50+
}
51+
52+
return b;
53+
}
54+
55+
buf_t *coap_parse_token(hdr_t *hdr, int hdr_offset, const char *s, int bytes) {
56+
int i, offset = 0;
57+
buf_t *b;
58+
59+
b = parse_var_bytes_hex(s,1);
60+
61+
if (!b) {
62+
return 0;
63+
}
64+
65+
if (b->size > 8 || b->size == 0) {
66+
return 0;
67+
}
68+
hdr->fields[COAP_FIELD_TOKEN].bit_width = b->size * 8;
69+
70+
for (i = 0; i < COAP_FIELD_LAST; ++i) {
71+
hdr->fields[i].bit_offset = offset;
72+
offset = hdr->fields[i].bit_offset + hdr->fields[i].bit_width;
73+
}
74+
75+
hdr->size = offset / 8;
76+
77+
78+
return b;
79+
}
80+
81+
int coap_parse_parms(hdr_t *hdr, int hdr_offset, struct field *f, int argc, const char *argv[]){
82+
int res;
83+
buf_t *b, *bb = 0;
84+
85+
res = parse_var_bytes(&b, argc, argv);
86+
87+
if (res > 1 && res <= argc) {
88+
bb = balloc(b->size + 1);
89+
if (!bb) {
90+
return 0;
91+
}
92+
93+
*(bb->data) = 0xFF;
94+
memcpy(bb->data + 1, b->data, b->size);
95+
96+
f->val = bb;
97+
f->bit_width = bb->size * 8;
98+
hdr->size += bb->size;
99+
100+
bfree(b);
101+
102+
return res;
103+
}
104+
105+
if (b)
106+
bfree(b);
107+
108+
return 0;
109+
}
110+
111+
static int coap_fill_defaults(struct frame *f, int stack_idx) {
112+
char buf[16];
113+
hdr_t *h = f->stack[stack_idx];
114+
field_t *tkl = find_field(h, "tkl");
115+
field_t *token = find_field(h, "token");
116+
117+
if (!tkl->val) {
118+
if (token->val) {
119+
snprintf(buf, 16, "%d", BIT_TO_BYTE(h->fields[COAP_FIELD_TOKEN].bit_width));
120+
tkl->val = parse_bytes(buf, 1);
121+
}
122+
}
123+
124+
return 0;
125+
}
126+
127+
128+
static field_t COAP_FIELDS[] = {
129+
[COAP_FIELD_VERSION] =
130+
{ .name = "ver",
131+
.help = "CoAP version number, has to be 1",
132+
.bit_width = 2 },
133+
[COAP_FIELD_TYPE]
134+
{ .name = "type",
135+
.help = "message type: Confirmable (0), Non-confirmable (1), Acknowledgement (2), or Reset (3)",
136+
.bit_width = 2 },
137+
[COAP_FIELD_TOKEN_LENGTH]
138+
{ .name = "tkl",
139+
.help = "Token length, 0-8 bytes",
140+
.bit_width = 4 },
141+
[COAP_FIELD_CODE]
142+
{ .name = "code",
143+
.help = "message code, split into a 3-bit class and a 5-bit detail e.g. 0.01 (GET) or 4.04 (Not found)",
144+
.bit_width = 8,
145+
.parser = coap_parse_code },
146+
[COAP_FIELD_MESSAGE_ID]
147+
{ .name = "msgid",
148+
.help = "Used to detect message duplication and to match messages",
149+
.bit_width = 16 },
150+
[COAP_FIELD_TOKEN]
151+
{ .name = "token",
152+
.help = "Token length must not greater than 8 bytes. (optional)",
153+
.bit_width = 0,
154+
.parser = coap_parse_token }
155+
};
156+
157+
static hdr_t HDR_COAP = {
158+
.name = "coap",
159+
.help = "Constrained Application Protocol",
160+
.fields = COAP_FIELDS,
161+
.fields_size = sizeof(COAP_FIELDS) / sizeof(COAP_FIELDS[0]),
162+
.frame_fill_defaults = coap_fill_defaults,
163+
.parser = hdr_parse_fields,
164+
};
165+
166+
static int options_fill_defaults(struct frame *f, int stack_idx) {
167+
buf_t *bb, *b;
168+
169+
uint16_t delta;
170+
uint16_t delta_ext = 0;
171+
uint16_t len = 0;
172+
uint16_t len_ext = 0;
173+
uint16_t i;
174+
int offset = 0;
175+
176+
177+
hdr_t *hdr = f->stack[stack_idx];
178+
field_t *fnum = find_field(hdr, "num");
179+
field_t *fval = find_field(hdr, "val");
180+
181+
if (!fnum) {
182+
return 0;
183+
}
184+
185+
if (fval){
186+
len = fval->val->size;
187+
}
188+
189+
delta = fnum->val->data[0] * 256 + fnum->val->data[1];
190+
191+
b = balloc(5);
192+
193+
i = 1;
194+
if (delta > 12) {
195+
if (delta > 268) {
196+
delta_ext = delta - 269;
197+
delta = 14;
198+
*(b->data + i++) = delta_ext >> 8;
199+
*(b->data + i++) = delta_ext & 0xFF;
200+
}
201+
else {
202+
delta_ext = delta - 13;
203+
delta = 13;
204+
*(b->data + i++) = delta_ext;
205+
}
206+
}
207+
*(b->data) = delta << 4;
208+
209+
if (len > 12) {
210+
if (len > 268) {
211+
len_ext = len - 269;
212+
len = 14;
213+
*(b->data + i++) = len_ext >> 8;
214+
*(b->data + i++) = len_ext & 0xFF;
215+
}
216+
else {
217+
len_ext = len - 13;
218+
len = 13;
219+
*(b->data + i++) = len_ext;
220+
}
221+
}
222+
223+
*(b->data) |= len & 0x0F;
224+
225+
bb = balloc(i);
226+
memcpy(bb->data,b->data, i);
227+
228+
bfree(fnum->val);
229+
fnum->val = bb;
230+
231+
hdr->fields[COAP_OPT_FIELD_NUM].bit_width = fnum->val->size * 8;
232+
233+
for (i = 0; i < COAP_OPT_FIELD_LAST; ++i) {
234+
hdr->fields[i].bit_offset = offset;
235+
offset = hdr->fields[i].bit_offset + hdr->fields[i].bit_width;
236+
}
237+
hdr->size = offset / 8;
238+
239+
bfree(b);
240+
return 0;
241+
}
242+
243+
static field_t COAP_OPT_FIELDS[] = {
244+
[COAP_OPT_FIELD_NUM]
245+
{ .name = "num", /* holds num and len fields */
246+
.help = "CoAP Option Number",
247+
.bit_width = 16, /* will be fixed in options_fill_defaults() */
248+
},
249+
[COAP_OPT_FIELD_VAL]
250+
{ .name = "val",
251+
.help = "CoAP Option Value",
252+
.bit_width = 0,
253+
.parser_multi = field_parse_multi_var_byte
254+
}
255+
};
256+
257+
static hdr_t HDR_COAP_OPTIONS = {
258+
.name = "coap-opt",
259+
.help = "Constrained Application Protocol Options, several fields allowed. (optional)",
260+
.fields = COAP_OPT_FIELDS,
261+
.fields_size = sizeof(COAP_OPT_FIELDS) / sizeof(COAP_OPT_FIELDS[0]),
262+
.frame_fill_defaults = options_fill_defaults,
263+
.parser = hdr_parse_fields,
264+
};
265+
266+
static int parameters_fill_defaults(struct frame *f, int stack_idx) {
267+
return 0;
268+
}
269+
270+
static field_t COAP_PARMS_FIELDS[] = {
271+
[COAP_PARMS_FIELD_PAR]
272+
{ .name = "par",
273+
.help = "CoAP Parameter field.",
274+
.bit_width = 0,
275+
.parser_multi = coap_parse_parms }
276+
};
277+
278+
static hdr_t HDR_COAP_PARMS = {
279+
.name = "coap-parms",
280+
.help = "Constrained Application Protocol Parameters. (optional)",
281+
.fields = COAP_PARMS_FIELDS,
282+
.fields_size = sizeof(COAP_PARMS_FIELDS) / sizeof(COAP_PARMS_FIELDS[0]),
283+
.frame_fill_defaults = parameters_fill_defaults,
284+
.parser = hdr_parse_fields,
285+
};
286+
287+
288+
void coap_init() {
289+
def_offset(&HDR_COAP);
290+
def_val(&HDR_COAP, "ver", "1");
291+
def_val(&HDR_COAP, "type", "0");
292+
def_val(&HDR_COAP, "tkl", "0");
293+
def_val(&HDR_COAP, "code", "0");
294+
def_val(&HDR_COAP, "msgid", "0");
295+
296+
def_offset(&HDR_COAP_OPTIONS);
297+
def_offset(&HDR_COAP_PARMS);
298+
299+
hdr_tmpls[HDR_TMPL_COAP] = &HDR_COAP;
300+
hdr_tmpls[HDR_TMPL_COAP_OPTIONS] = &HDR_COAP_OPTIONS;
301+
hdr_tmpls[HDR_TMPL_COAP_PARMS] = &HDR_COAP_PARMS;
302+
303+
}
304+
305+
void coap_uninit() {
306+
uninit_frame_data(&HDR_COAP);
307+
/*! \TODO free the buffers */
308+
hdr_tmpls[HDR_TMPL_COAP] = 0;
309+
hdr_tmpls[HDR_TMPL_COAP_OPTIONS] = 0;
310+
hdr_tmpls[HDR_TMPL_COAP_PARMS] = 0;
311+
}

0 commit comments

Comments
 (0)