SingingCat 0
application
route_command.c
1#include "main-header.h"
2#include "routing.h"
3#include "route_command.h"
4
5static void route_command_list_routes(struct command *com);
6static void route_command_clear_routes(struct command *com);
7static void route_command_add_route(struct command *com);
8static void route_command_remove_route(struct command *com);
9static struct route *find_route(long target, long longsource, byte device, byte needsonline);
10#define MAX_ROUTING_ENTRIES 30
11static struct route routes[MAX_ROUTING_ENTRIES];
12
13static byte debug = 0;
14void routing_command_debug(byte b) {
15 debug = b;
16}
17
18void routing_command_init() {
19 memset(&routes, 0, sizeof(routes));
20}
21/*
22 * if we have no route to a target, we sliently drop the packet
23 * a route can have a source, target or both. "Any" is also valid for both.
24 * we can say, for example:
25 * "any packets from server to nodeX, please send via device 'radio' with nodeY being the next hop"
26 * or: "any packets from nodeX to server, please send via device 'wifi' to server"
27 * the command has multiple functions:
28 * 1) list routes
29 * 2) add route
30 * 3) delete route
31 * 4) clear routes (except routes to the sender of the packet)
32 */
33void route_command(struct command *com) {
34 long nid = ascii_parse_hex((const byte *)get_arg((struct command *)com, 0), 8, NULL);
35
36 if (nid == 1) {
37 route_command_list_routes(com);
38 return;
39 } else if (nid == 2) {
40 route_command_add_route(com);
41 return;
42 } else if (nid == 3) {
43 route_command_remove_route(com);
44 return;
45 } else if (nid == 4) {
46 route_command_clear_routes(com);
47 return;
48 } else {
49 send_command_reply(com, COMFLAGS_ACK);
50 }
51}
52static void route_command_list_routes(struct command *com) {
53 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
54}
55static void route_command_clear_routes(struct command *com) {
56 memset(&routes, 0, sizeof(routes));
57 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
58}
59int parse_route_command(struct command *com, struct route *r) {
60 if (com->argctr != 6) { // plus type
61 return 1;
62 }
63 r->target = ascii_parse_hex((const uint8_t *)get_arg(com, 1), strlen(get_arg(com, 1)), NULL);
64 r->source = ascii_parse_hex((const uint8_t *)get_arg(com, 2), strlen(get_arg(com, 2)), NULL);
65 r->sendto = ascii_parse_hex((const uint8_t *)get_arg(com, 3), strlen(get_arg(com, 3)), NULL);
66 r->out_device = ascii_parse_hex((const uint8_t *)get_arg(com, 4), strlen(get_arg(com, 4)), NULL);
67 r->match_device = ascii_parse_hex((const uint8_t *)get_arg(com, 5), strlen(get_arg(com, 5)), NULL);
68 return 0;
69}
70
71// find a free entry in our routing table
72static struct route *find_free_entry() {
73 int i;
74
75 for (i = 0; i < MAX_ROUTING_ENTRIES; i++) {
76 if (routes[i].used == 0) {
77 return &routes[i];
78 }
79 }
80 if (debug) {
81 printf("[route_command] no free routing table slot available\r\n");
82 }
83 return NULL;
84}
85
86static void route_command_add_route(struct command *com) {
87 struct route *r = find_free_entry();
88
89 if (r == NULL) {
90 send_command_reply(com, COMFLAGS_SUCCESS);
91 }
92 int err = parse_route_command(com, r);
93
94 if (err) {
95 send_command_reply(com, COMFLAGS_SUCCESS);
96 return;
97 }
98 struct route *nr = find_route(r->target, r->source, r->match_device, 0);
99
100 if (nr == NULL) {
101 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
102 r->used = 1;
103 printf("[route_command] route added to %N via %N on %i\r\n", r->target, r->sendto, r->out_device);
104 return;
105 }
106 nr->target = r->target;
107 nr->match_device = r->match_device;
108 nr->out_device = r->out_device;
109 nr->source = r->source;
110 nr->sendto = r->sendto;
111 printf("[route_command] route updated to %N via %N on %i\r\n", nr->target, nr->sendto, nr->out_device);
112
113 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
114}
115static void route_command_remove_route(struct command *com) {
116 send_command_reply(com, COMFLAGS_ACK | COMFLAGS_SUCCESS);
117}
118
119static struct route *find_route(long target, long source, byte device, byte needsonline) {
120 int i;
121
122 for (i = 0; i < MAX_ROUTING_ENTRIES; i++) {
123 struct route *r = &routes[i];
124 if (r->used == 0) {
125 continue;
126 }
127 if (
128 (r->target == target) &&
129 (r->source == source) &&
130 (r->match_device == device)) {
131 if ((needsonline) && (!is_device_online(r->out_device))) {
132 continue;
133 }
134 return r;
135 }
136 }
137 return NULL;
138}
139
140
141struct route *get_configured_route(struct command *com) {
142 struct route *r = find_route(com->target, com->sender, com->sourcedev, 1);
143
144 if (r != NULL) {
145 if (debug) {
146 printf("[route_command] route to %N via %N on %i\r\n", com->target, r->sendto, r->out_device);
147 }
148 return r;
149 }
150
151 r = find_route(com->target, 0, com->sourcedev, 1);
152 if (r != NULL) {
153 if (debug) {
154 printf("[route_command] route to %N via %N on %i\r\n", com->target, r->sendto, r->out_device);
155 }
156 return r;
157 }
158
159 r = find_route(com->target, com->sender, 0, 1);
160 if (r != NULL) {
161 if (debug) {
162 printf("[route_command] route to %N via %N on %i\r\n", com->target, r->sendto, r->out_device);
163 }
164 return r;
165 }
166
167 r = find_route(com->target, 0, 0, 1);
168 if (r != NULL) {
169 if (debug) {
170 printf("[route_command] route to %N via %N on %i\r\n", com->target, r->sendto, r->out_device);
171 }
172 return r;
173 }
174
175 if (debug) {
176 printf("[route_command] no route to %N\r\n", com->target);
177 }
178 return NULL;
179}
180
181void print_forwarding_table() {
182 int i;
183
184 printf("target | source | match_device | nexthop | out_device\r\n");
185 for (i = 0; i < MAX_ROUTING_ENTRIES; i++) {
186 struct route *r = &routes[i];
187 if (r->used == 0) {
188 continue;
189 }
190 printf("%N %N %i %N %i\r\n", r->target, r->source, r->match_device, r->sendto, r->out_device);
191 }
192 printf("Routing list complete\r\n");
193}
int send_command_reply(struct command *com, byte flags)
send a reply to a command
Definition: queue.c:562
int is_device_online(int device)
return 1 if the specified device is online and routing
Definition: routing.c:63
const char * get_arg(const struct command *com, int index)
given an argument by index[0..n], will return a pointer to the bytearray (excluding the fieldtype) th...
definitions of routing table structures
long target
Definition: command.h:16
uint8_t sourcedev
Definition: command.h:17
uint8_t argctr
Definition: command.h:24
long sender
Definition: command.h:14