libnet: added functionality to request ARP lookup sent from default q
[barrelfish] / lib / net / arp.c
1 /**
2  * \file arp.c
3  * \brief
4  */
5
6
7 /*
8  * Copyright (c) 2017 ETH Zurich.
9  * All rights reserved.
10  *
11  * This file is distributed under the terms in the attached LICENSE file.
12  * If you do not find this file, copies can be found by writing to:
13  * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
14  */
15
16
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/nameservice_client.h>
19
20
21 #include <lwip/opt.h>       
22 #include <lwip/netif.h>
23 #include <lwip/timeouts.h>
24 #include <net/netif.h>
25
26 #include <netif/etharp.h>
27
28 #include <if/octopus_defs.h>
29 #include <if/net_ARP_defs.h>
30 #include <octopus/octopus.h>
31 #include <octopus/trigger.h>
32
33
34 #include "networking_internal.h"
35
36 ///< the debug subsystem
37 #define NETDEBUG_SUBSYSTEM "arpd"
38
39
40 #define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
41 #define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
42
43 #define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
44
45
46 // Reuse existing Flounder interface
47 static void arp_force_lookup(struct net_ARP_binding *b,
48                                  uint32_t ip)
49 {
50     errval_t err;
51     struct net_state *sta = (struct net_state*) b->st;
52
53     // send it multiple times 
54     // (TODO deferred event instead of sending multiple times)
55     err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
56     assert(err_is_ok(err));
57
58     err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
59     assert(err_is_ok(err));
60
61     err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
62     assert(err_is_ok(err));
63
64 } // end function: ARP_resolve_request
65
66
67 static struct net_ARP_rx_vtbl rx_arp_vtbl = {
68     .arp_force_lookup = arp_force_lookup,
69 };
70
71 /*****************************************************************
72 * Dealing with new connections
73 *****************************************************************/
74 static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
75 {   
76     b->st = st;
77     b->rx_vtbl = rx_arp_vtbl;
78     return SYS_ERR_OK;
79
80
81 /*****************************************************************
82 * exporting service
83 *****************************************************************/
84
85 static void export_ARP_cb(void *st, errval_t err, iref_t iref)
86 {
87     struct net_state *sta = st;
88
89     if (err_is_fail(err)) {
90         DEBUG_ERR(err, "service export failed");
91     }
92
93     // register this iref with the name service
94     err = nameservice_register("libnet_arp", iref);
95     if (err_is_fail(err)) {
96         DEBUG_ERR(err, "nameservice_register failed for [libnet_arp]");
97         abort(); // FIXME: Do I need abort after DEBUG_ERR?
98     }
99     sta->arp_running = true;
100 }
101
102 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
103 {
104     if (type != ETHTYPE_ARP) {
105         return netif;
106     }
107
108     struct net_state *st = netif->state;
109
110     if (!st->arp_running) {
111         return netif;
112     }
113
114     if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
115         NETDEBUG("wrong packet size received\n");
116         return netif;
117     }
118
119     struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
120
121     pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
122
123     /* RFC 826 "Packet Reception": */
124     if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
125         (hdr->hwlen != ETH_HWADDR_LEN) ||
126         (hdr->protolen != sizeof(ip4_addr_t)) ||
127         (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
128       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
129         ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
130         hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
131       return netif;
132     }
133
134     ip_addr_t ip;
135     IPADDR2_COPY(&ip, &hdr->sipaddr);
136
137     /* don't store any IPs */
138     if (ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
139         return netif;
140     }
141
142     uint64_t hwaddr = 0;
143     if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
144                          (const ip4_addr_t **)&hwaddr) != -1) {
145         return netif;
146     }
147
148     /*
149      * If already exists, return
150      */
151
152     hwaddr = 0;
153     SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
154
155     NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
156
157     oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
158
159     etharp_add_static_entry(&ip, &hdr->shwaddr);
160
161     return netif;
162 }
163
164 static errval_t arp_service_start_st(struct net_state *st)
165 {
166     errval_t err;
167
168     err = oct_init();
169     if (err_is_fail(err)) {
170         return err;
171     }
172
173     err = net_ARP_export(st, export_ARP_cb, connect_ARP_cb,
174                          get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
175     if (err_is_fail(err)) {
176         return err;
177     }
178
179     st->arp_running = true;
180
181     return SYS_ERR_OK;
182 }
183
184 errval_t arp_service_start(void)
185 {
186     return arp_service_start_st(get_default_net_state());
187 }
188
189 static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
190 {
191     errval_t err;
192
193     uint64_t ip, hwaddr;
194     err = oct_read(record, "_" ARP_ENTRY_FIELDS, &hwaddr, &ip);
195     if (err_is_fail(err)) {
196         DEBUG_ERR(err, "failed to read the entrie\n");
197     }
198
199     ip_addr_t ipaddr;
200     ipaddr.addr = (uint32_t)ip;
201
202     if (mode & OCT_ON_SET) {
203
204         NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
205
206         struct eth_addr mac;
207         SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
208
209         etharp_add_static_entry(&ipaddr, &mac);
210     } else if (mode & OCT_ON_DEL) {
211         NETDEBUG("deleting ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
212         etharp_remove_static_entry(&ipaddr);
213     }
214 }
215
216
217
218 static errval_t arp_service_subscribe_st(struct net_state *st)
219 {
220     NETDEBUG("subscribing to ARP updates..\n");
221
222     errval_t err;
223     err = oct_init();
224     if (err_is_fail(err)) {
225         return err;
226     }
227
228     st->arp_running = false;
229
230     return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
231                                              st, &st->arp_triggerid);
232 }
233
234 errval_t arp_service_subscribe(void)
235 {
236     struct net_state *st = get_default_net_state();
237     return arp_service_subscribe_st(st);
238 }
239
240
241
242 static void bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
243 {
244     assert(err_is_ok(err));
245     struct net_state* sta = (struct net_state*) st;
246
247     sta->arp = b;
248     sta->arp_connected = true;
249 }
250
251 static errval_t arp_connect(struct net_state* st)
252 {
253     errval_t err;
254     if (!st->arp_connected) {
255         iref_t iref;
256         err = nameservice_blocking_lookup("libnet_arp", &iref);
257         if (err_is_fail(err)) {
258             return err;
259         }
260
261         err = net_ARP_bind(iref, bind_cb, st, get_default_waitset(), 
262                            IDC_BIND_FLAGS_DEFAULT);
263         if (err_is_fail(err)) {
264             return err;
265         }
266     
267         while(!st->arp_connected) {
268             event_dispatch(get_default_waitset());
269         }
270     }
271     return SYS_ERR_OK;
272 }
273
274 errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac)
275 {
276     errval_t err;
277
278     err = oct_init();
279     if (err_is_fail(err)) {
280         return err;
281     }
282     
283     char* record = NULL;
284     char query[256] ;
285
286     sprintf(query, "net.arp.%d {mac: _ , ip: %d }", ip, ip);
287     err = oct_get(&record, query);
288     if (err_no(err) == OCT_ERR_NO_RECORD) {
289         struct net_state *st = get_default_net_state();
290         err = arp_connect(st);
291         if (err_is_fail(err)) {
292             return err;
293         }       
294
295         err = st->arp->tx_vtbl.arp_force_lookup(st->arp, NOP_CONT, ip);
296         if (err_is_fail(err)) {
297             return err;
298         }
299
300         err = oct_wait_for(&record, query);
301         if (err_is_fail(err)) {
302             return err;
303         }
304     } else if (err_is_fail(err)) {
305         DEBUG_ERR(err, "cannot get mac address\n");
306         return err;
307     }
308
309     uint64_t ip_adr;
310     err = oct_read(record, "_" ARP_ENTRY_FIELDS, mac, &ip_adr);
311     if (err_is_fail(err)) {
312         DEBUG_ERR(err, "failed to read the entrie\n");
313     }
314
315     return SYS_ERR_OK;
316 }
317