-
Notifications
You must be signed in to change notification settings - Fork 0
/
token.c
275 lines (258 loc) · 8.15 KB
/
token.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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*
* NLRI description from string using the nlri_type_tok values
*/
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include "encode.h"
#include "flospec.h"
#include "bitset.h"
#include "utils.h"
#include "token.h"
#include "iana_ip_proto.h"
#include "debug.h"
/* Get NLRI component type from the string token */
flo_comp_t get_comp_type (char *s)
{
char *p= s;
while( *p ==' ' ||*p == '\t') p++;
if (0 == strncmp(p, "ip", 2)) return NLRI_IP_PROTO;
else if (0 == strncmp(p, "icmp", 4)) {
if (0 == strncmp(p+5, "type", 4)) return NLRI_ICMP_TYPE;
else if (0 == strncmp(p+5, "code", 4)) return NLRI_ICMP_CODE;
else printf("\n Err: Unknown sub-comp [%s]", p+5);
} else if (0 == strncmp(p, "port",4)) {
if (*(p+4) == '.') {
if (0 == strncmp(p+5, "src", 3)) return NLRI_SOURCE_PORT;
else if (0 == strncmp(p+5, "dest", 4)) return NLRI_DEST_PORT;
else printf("\n Err: Unknown sub-comp [%s]", p+5);
} else return NLRI_PORT;
} else if (0 == strncmp(p, "pref", 4)) {
if (0 == strncmp(p+7, "src", 3)) return NLRI_SOURCE_PREFIX;
else if( 0 == strncmp(p+7, "dest", 4)) return NLRI_DEST_PREFIX;
else printf("\n Err: Unknown sub-comp [%s]", p+7);
} else if(0 == strncmp(p, "tcp", 3)) return NLRI_TCP_FLAGS;
else if (0 == strncmp(p, "pak",3)) return NLRI_PAK_LEN;
else if (0 == strncmp(p, "dscp",4)) return NLRI_DSCP;
else if (0 == strncmp(p, "frag",4)) return NLRI_FRAGMENT;
else printf ("\n Err: Unknown NLRI component code [%s]\n",p);
return MAX_NLRI_COMPONENTS;
}
/* similarto strtok, just that '\0' is not placed */
char* find_first(char *s, char *f)
{
int i, n = strlen(f);
char *p;
p = s;
while (*p) {
for (i = 0; i < n; i++)
if(*p == f[i])
return p;
p++;
}
return NULL;
}
/* tokenise the operator and operands */
op_t tok_op (char *s, char **l, char **r)
{
char *a;
op_t op;
a = find_first(s, "<>!=");
if (a) {
switch (*a) {
case '<':
op = *(a+1) == '=' ? OP_LE : OP_LT;
break;
case '>':
op = *(a+1) == '=' ? OP_GE : OP_GT;
break;
case '!':
op = *(a+1) == '=' ? OP_NE : OP_NE;// may give err here
break;
case '=':
op = OP_EQ;
break;
}
*a = 0;
*l = s;
*r = a+2; /* skip op */
return op;
}
return NO_OP;
}
/* assign a value for the keywords used in the nlri string */
uint32_t get_val (char *s)
{
// TODO - only commonly used protos added here,to add full set,
// have to store in tree/trie
if (!s)
return 0;
if (0 == strncmp(s,"tcp", 3)) return IP_PROTO_TCP;
else if (0 == strncmp(s,"udp", 3)) return IP_PROTO_UDP;
else if (0 == strncmp(s,"icmp", 4)) return IP_PROTO_ICMP;
else if (0 == strncmp(s,"igmp", 4)) return IP_PROTO_IGMP;
else if (0 == strncmp(s,"rsvp", 4)) return IP_PROTO_RSVP;
else return strtol(s, NULL, 0);
}
/* per nlri component tokeniser, adds the encode data in a list in the comp type slot */
void tok_comp (char *s, flo_list_t list[])
{
char *a, *b, *c, *d, *p, *q;
op_t op, prev_op;
uint32_t len = 0;
int i = 0;
flo_data_t data[10];
flo_comp_t type;
bool subval_eval = false;
op = tok_op(s, &a, &b);
DBG_PRINT ("\n TOK: main-op: [%s] [%s] [%s]", a, show_num_op(op), b);
DBG_PRINT ("\n TOK: comp type= %d" , get_comp_type(a));
type = get_comp_type(a);
if (type == MAX_NLRI_COMPONENTS)
return;
if (NLRI_PREFIX_TYPE(type)) {
p = strtok(b, "/");
q = strtok(NULL, "/");
len = get_val(q);
//data[0] = (flo_data_t) PREFIX(p, get_val(q));
data[0] = (flo_data_t) PREFIX(p, !len ? 32 : len); // IPv4 only
list[type].n = 1;
list[type].d = malloc(sizeof(flo_data_t));
if (!list[type].d) {
printf ("\n Memory allocation failure for list\n");
exit (1);
}
memcpy(list[type].d, &data, sizeof(flo_data_t));
return ;
}
data[i].op = op;
data[i].and = false;
prev_op = op;
q = strtok (b, "&");
while ((p = strtok (NULL, "&"))) {
subval_eval = true;
DBG_PRINT ("\n TOK: set AND");
/* and bit set */
op = tok_op(p+1, &c, &d);
if (op == NO_OP) {
/* no op here (use prev op) */
DBG_PRINT ("\n\t TOK: sub-NO-New-OP: [%s] [%s] [%s]", q,
show_num_op(prev_op), p);
data[i].value = get_val(q);
i++;
data[i].op = prev_op;
data[i].and = true;
data[i].value = get_val(p);
} else {
/* op is in op */
DBG_PRINT ("\n\t TOK: sub-op: [%s] [%s] [%s]", q,
show_num_op(op), d);
data[i].value = get_val(q);
i++;
data[i].op = op;
data[i].and = true;
data[i].value = get_val(d);
b = d; // put remaining in b for '|' tokeniser to use
}
}
prev_op = op;
q = strtok (b, "|");
while ((p = strtok (NULL, "|"))) {
subval_eval = true;
DBG_PRINT ("\n TOK: set OR");
/* and bit unset */
op = tok_op(p+1, &c, &d);
if (op == NO_OP) {
/* no op here (use prev op) */
DBG_PRINT ("\n\t TOK: sub-NO-New-OP: [%s] [%s] [%s]", q,
show_num_op(prev_op), p);
data[i].value = get_val(q);
i++;
data[i].op = prev_op;
data[i].and = false;
data[i].value = get_val(p);
} else {
/* op is in op */
DBG_PRINT ("\n\t TOK: sub-op: [%s] [%s] [%s]", q,
show_num_op(op), d);
data[i].value = get_val(q);
i++;
data[i].op = op;
data[i].and = false;
data[i].value = get_val(d);
}
}
if (!subval_eval) {
data[i].value = get_val(b);
}
i++;
list[type].n = i;
list[type].d = malloc(sizeof(flo_data_t)* i);
if (!list[type].d) {
printf ("\n Memory allocation failure for list\n");
exit (1);
}
memcpy(list[type].d, &data, sizeof(flo_data_t) * i);
}
/* top level tokeniser */
void tok_nlri (char *s, flo_list_t list[])
{
char *n, *p = s;
char *tmp;
unsigned char *bufp;
unsigned char buf[200] = {0}; /* sufficient ? */
unsigned char *hdr, *strt;
uint32_t len, dlen;
int i;
// flo_list_t list[MAX_NLRI_COMPONENTS] = { {0, NULL} };
/* TEST */
flo_decode_t flo_decode[MAX_NLRI_COMPONENTS+1];
int dec_len;
/* as per the RFC,all components encoded are considered ANDed */
while((n = strstr(p, "and"))) {
tmp = malloc(n - p + 1);
strncpy(tmp, p, n-p);
tmp[n - p] = '\0';
tok_comp(tmp, list);
p = n+3;
free (tmp);
}
tok_comp(p, list); /* remaining part in str */
/*
* Now the list must be populated with the components tokenised, add them to
* the buffer sorted
*/
hdr = bufp = strt = buf;
PUTSHORT(bufp, 0);
bufp += 2;
for (i = NLRI_COMP_START ; i < MAX_NLRI_COMPONENTS; i++) {
if (list[i].n && list[i].d) {
DBG_PRINT ("\n Tok: adding %s with %d comps",
show_nlri_comp(i), list[i].n );
len = flospec_encode (bufp, i, list[i].n, list[i].d);
bufp += len;
// free(list[i].d);
}
}
len = (bufp - hdr);
dlen = len - 2; /* exclude 2 b header */
if (len > 0xF0) {
PUTLONG(hdr, (dlen | 0xF000)); /* exclude header len */
} else {
*(hdr + 1) = dlen; /* data len */
strt = hdr + 1;
len -= 1;/* 1 b at start wasted */
}
printf ("\n Final buf len = %d, data/hdr len = %d (%X)\n ", len,dlen,dlen);
for (i = 0 ; i < len; i++) {
printf ("%02X ", strt[i]);
}
printf ("\n");
/* TEST */
flospec_decode(strt, flo_decode, &dec_len);
flospec_show(flo_decode, dec_len);
}