libc: removing newlib, adding BSD libc
[barrelfish] / lib / net / net_filter.c
1 /*
2  * Copyright (c) 2017, ETH Zurich.
3  * All rights reserved.
4  *
5  * This file is distributed under the terms in the attached LICENSE file.
6  * If you do not find this file, copies can be found by writing to:
7  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
8  */
9
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include <barrelfish/barrelfish.h>
16 #include <barrelfish/nameservice_client.h>
17 #include <if/net_filter_defs.h>
18 #include <if/net_filter_rpcclient_defs.h>
19
20 #include <net/net_filter.h>
21
22 #include "networking_internal.h"
23 #include "debug.h"
24
25 #define MAX_NAME 128
26
27 #define NETDEBUG_SUBSYSTEM "filter"
28
29 /******************************************************************************
30  * Connection setup
31  ******************************************************************************/
32
33 // Callback for bind
34 static void bind_cb(void *st, errval_t err, struct net_filter_binding *b)
35 {
36     struct net_filter_state* filt = (struct net_filter_state*) st;
37     assert(err_is_ok(err));
38
39     NETDEBUG("Sucessfully connected to management interface\n");
40
41     filt->b = b;
42     net_filter_rpc_client_init(filt->b);
43     filt->bound = true;
44 }
45
46
47 /** Open connection to management interface */
48 static errval_t connect_to_net_filter(struct net_filter_state* st,
49                                       const char *dev_name)
50 {
51     errval_t r;
52     iref_t iref;
53     const char* prefix = "net_filter_";
54     char name[strlen(dev_name) + strlen(prefix) + 1];
55    
56     // Build label for management service
57     sprintf(name, "%s%s", prefix, dev_name);
58
59     NETDEBUG("Name lookup\n");
60     // Connect to service
61     r = nameservice_blocking_lookup(name, &iref);
62     if (err_is_fail(r)) {
63         return r;
64     }
65
66     NETDEBUG("Binding\n");
67     r = net_filter_bind(iref, bind_cb, st, get_default_waitset(),
68             IDC_BIND_FLAGS_DEFAULT);
69     if (err_is_fail(r)) {
70         return r;
71     }
72
73     NETDEBUG("Waiting to bind\n");
74     while(st->bound == false) {
75         event_dispatch(get_default_waitset());
76     }
77     
78     NETDEBUG("finished connecting\n");
79     return SYS_ERR_OK;
80 }
81
82 /******************************************************************************
83  * Helper functions
84  ******************************************************************************/
85
86 static bool filter_cmp_ip(struct net_filter_ip* f1, struct net_filter_ip* f2)
87 {
88     if (f1->ip_src == f2->ip_src &&
89         f1->ip_dst == f2->ip_dst &&
90         f1->port_src == f2->port_src &&
91         f1->port_dst == f2->port_dst &&
92         f1->qid == f2->qid &&
93         f1->type == f2->type) {
94         return true;
95     }
96     return false;
97 }
98
99 /*
100 static bool filter_cmp_mac(struct net_filter_mac* f1, struct net_filter_mac* f2)
101 {
102     if (f1->vlan_id == f2->vlan_id &&
103         f1->mac == f2->mac &&
104         f1->type == f2->type) {
105         return true;
106     }
107     return false;
108 }
109 */
110 /*
111 static bool is_reachable(struct net_filter_ip* filt)
112 {
113     struct net_filter_ele* cur = filter_state.filters_ip.start;
114     
115     while(cur != NULL) {
116         printf("reachable: port_dst: %"PRIu16" %"PRIu16" \n", cur->filter.ip.port_dst, filt->port_dst);
117         if (filter_cmp_ip(&cur->filter.ip, filt)) {
118             return true;
119         }
120         cur = cur->next;
121     }
122     return false;
123 }
124 */
125 /******************************************************************************
126  * Library function implementation
127  ******************************************************************************/
128
129 /**
130  * @brief initalized network filtering. Sets up connection to drivers
131  *        which support hardware filtering
132  *
133  * @param st        returned net filter state;
134  * @param cardname  the card name to be used
135  *
136  * @return SYS_ERR_OK on success, error on failure
137  */
138 errval_t net_filter_init(struct net_filter_state** st,
139                          const char* cardname)
140 {
141     errval_t err;
142
143     struct net_filter_state* tmp = calloc(1, sizeof(struct net_filter_state));
144     assert(tmp != NULL);
145     
146     tmp->filters_ip.start = NULL;
147     tmp->filters_ip.num_ele = 0;
148     tmp->filters_mac.start = NULL;
149     tmp->filters_mac.num_ele = 0;
150
151     err = connect_to_net_filter(tmp, cardname);
152     *st = tmp;
153     return err;
154 }
155
156
157 /**
158  * @brief Installs an L3/L4 filter in the hardware filter
159  *        tables
160  *
161  * @param st    net filter state
162  * @param filt  filter struct
163  *
164  * @return SYS_ERR_OK on success, error on failure
165  */
166 errval_t net_filter_ip_install(struct net_filter_state* st,
167                                struct net_filter_ip* filt)
168 {
169
170     assert(st->bound);
171     errval_t err;
172     uint64_t filter_id;
173
174     struct net_filter_ele* cur = st->filters_ip.start;
175     struct net_filter_ele* prev = NULL;
176
177     /* go through linked list and find last element
178      (and check if filter is already installed) */
179     if (cur == NULL) {
180         st->filters_ip.start = malloc(sizeof(struct net_filter_ele));
181         cur = st->filters_ip.start;
182     } else {
183         while(cur->next != NULL) {
184             if (filter_cmp_ip(&cur->filter.ip, filt)) {
185                 return NET_FILTER_ERR_ALREADY_EXISTS;
186             }
187             prev = cur;
188             cur = cur->next;
189         }
190
191         if (filter_cmp_ip(&cur->filter.ip, filt)) {
192             return NET_FILTER_ERR_ALREADY_EXISTS;
193         }
194
195         cur->next = malloc(sizeof(struct net_filter_ele));
196         cur = cur->next;
197     }
198
199     cur->filter.ip.ip_src = filt->ip_src;
200     cur->filter.ip.ip_dst = filt->ip_dst;
201     cur->filter.ip.port_src = filt->port_src;
202     cur->filter.ip.port_dst = filt->port_dst;
203     cur->filter.ip.qid = filt->qid;
204     cur->filter.ip.type = filt->type;
205     cur->next = NULL;
206     cur->prev = prev;
207
208     st->filters_ip.num_ele++;
209
210     err = st->b->rpc_tx_vtbl.install_filter_ip(st->b,
211                                                filt->type,
212                                                filt->qid,
213                                                filt->ip_src,
214                                                filt->ip_dst,
215                                                filt->port_src,
216                                                filt->port_dst,
217                                                &filter_id);
218     if (err_is_fail(err)) {
219         free(cur);
220         return err;
221     }
222
223     cur->filter_id = filter_id;
224     return SYS_ERR_OK;
225 }
226
227
228 /**
229  * @brief Removes an L3/L4 filter in the hardware filter
230  *        tables
231  *
232  * @param st    net filter state
233  * @param filt  filter struct
234  *
235  * @return SYS_ERR_OK on success, error on failure
236  */
237 errval_t net_filter_ip_remove(struct net_filter_state* st,
238                               struct net_filter_ip* filt)
239 {
240
241     assert(st->bound);
242     errval_t err, err2;
243     uint64_t filter_id = (uint64_t)-1;
244
245     struct net_filter_ele* cur = st->filters_ip.start;
246     struct net_filter_ele* prev = NULL;
247
248
249     // no entries
250     if (cur == NULL) {
251         return NET_FILTER_ERR_NOT_FOUND;
252     }
253
254     // Multiple entries
255     while(cur != NULL) {
256         if (filter_cmp_ip(&cur->filter.ip, filt)) {
257             filter_id = cur->filter_id;
258             break;
259         }
260         prev = cur;
261         cur = cur->next;
262     }
263
264    
265     if (filter_id == (uint64_t) -1) {
266         return NET_FILTER_ERR_NOT_FOUND;
267     }
268
269     err = st->b->rpc_tx_vtbl.remove_filter(st->b,
270                                            filt->type,
271                                            filter_id,
272                                            &err2);
273     if (err_is_fail(err) || err_is_fail(err2)) {
274         return err_is_fail(err) ? err: err2;
275     }
276
277     // remove from queue
278     if (prev != NULL) { // check if first
279         prev->next = cur->next;
280         if (cur->next != NULL) { // check if last
281             cur->next->prev = prev;
282         }
283     } else {
284         st->filters_ip.start = cur->next;
285     }
286     
287
288     free(cur);
289
290     st->filters_ip.num_ele--;
291
292     return SYS_ERR_OK;
293 }
294
295 errval_t net_filter_mac_install(struct net_filter_state* st,
296                                 struct net_filter_mac* filt)
297 {
298    USER_PANIC("NYI \n");
299 }
300
301
302 errval_t net_filter_mac_remove(struct net_filter_state* st,
303                                struct net_filter_mac* filt)
304 {
305    USER_PANIC("NYI \n");
306 }