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#include <collections/list.h>
20
21
22#include <lwip/opt.h>
23#include <lwip/netif.h>
24#include <lwip/timeouts.h>
25#include <net/netif.h>
26
27#include <netif/etharp.h>
28
29#include <if/octopus_defs.h>
30#include <if/net_ARP_defs.h>
31#include <octopus/octopus.h>
32#include <octopus/trigger.h>
33
34
35#include "networking_internal.h"
36
37///< the debug subsystem
38#define NETDEBUG_SUBSYSTEM "arpd"
39
40
41#define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
42#define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
43
44#define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
45#define ARP_RESEND_FREQ 500*1000
46
47struct arp_request {
48    uint32_t ip;
49};
50
51static void arp_timer_callback(void *data)
52{
53    errval_t err;
54    char* record;
55    char query[128];
56
57    struct net_state *st = (struct net_state*) data;
58
59    // remove all the outstanding ARPs that are finished
60    for (int i = 0; i < collections_list_size(st->outstanding_arp) ; i++) {
61        struct arp_request* req = (struct arp_request*) collections_list_get_ith_item(st->outstanding_arp, i);
62        sprintf(query, "net.arp.%d {mac: _ , ip: %d }", req->ip, req->ip);
63        err = oct_get(&record, query);
64        if (err_is_ok(err)) {
65            // remove from outstanding arps
66            collections_list_remove_ith_item(st->outstanding_arp, i);
67        }
68    }
69
70    // no outstanding ARPs
71    if (collections_list_size(st->outstanding_arp) == 0) {
72        NETDEBUG("Stopping ARP periodic event \n");
73        err = periodic_event_cancel(&st->arp_send);
74        assert(err_is_ok(err));
75        return;
76    }
77
78    // Resend all other outstanding ARPs
79    for (int i = 0; i < collections_list_size(st->outstanding_arp) ; i++) {
80        struct arp_request* req = (struct arp_request*) collections_list_get_ith_item(st->outstanding_arp, i);
81        NETDEBUG("Starting ARP for ip %u \n", req->ip);
82        err = etharp_request(&st->netif, (ip4_addr_t*) &req->ip);
83        assert(err_is_ok(err));
84    }
85}
86
87static void arp_request_free(void *data)
88{
89    free(data);
90}
91
92// Reuse existing Flounder interface
93static void arp_force_lookup(struct net_ARP_binding *b,
94                             uint32_t ip)
95{
96    errval_t err;
97    struct net_state *sta = (struct net_state*) b->st;
98
99    if (sta->outstanding_arp == NULL) {
100       collections_list_create(&sta->outstanding_arp, arp_request_free);
101       assert(sta->outstanding_arp != NULL);
102    }
103
104    if (collections_list_size(sta->outstanding_arp) == 0) {
105        NETDEBUG("Starting ARP periodic event\n");
106        err = periodic_event_create(&sta->arp_send, get_default_waitset(),
107                                    ARP_RESEND_FREQ, MKCLOSURE(arp_timer_callback, sta));
108        assert(err_is_ok(err));
109    }
110
111    struct arp_request* new_arp = malloc(sizeof(struct arp_request));
112    collections_list_insert(sta->outstanding_arp, new_arp);
113
114    // send one but if it fails, periodic event will call it again
115    err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
116    assert(err_is_ok(err));
117} // end function: ARP_resolve_request
118
119
120static struct net_ARP_rx_vtbl rx_arp_vtbl = {
121    .arp_force_lookup = arp_force_lookup,
122};
123
124/*****************************************************************
125* Dealing with new connections
126*****************************************************************/
127static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
128{
129    b->st = st;
130    b->rx_vtbl = rx_arp_vtbl;
131    return SYS_ERR_OK;
132}
133
134/*****************************************************************
135* exporting service
136*****************************************************************/
137
138static void export_ARP_cb(void *st, errval_t err, iref_t iref)
139{
140    struct net_state *sta = st;
141
142    if (err_is_fail(err)) {
143        DEBUG_ERR(err, "service export failed");
144    }
145
146    // register this iref with the name service
147    err = nameservice_register("libnet_arp", iref);
148    if (err_is_fail(err)) {
149        DEBUG_ERR(err, "nameservice_register failed for [libnet_arp]");
150        abort(); // FIXME: Do I need abort after DEBUG_ERR?
151    }
152    sta->arp_running = true;
153}
154
155struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
156{
157    if (type != ETHTYPE_ARP) {
158        return netif;
159    }
160
161    struct net_state *st = netif->state;
162
163    if (!st->arp_running) {
164        return netif;
165    }
166
167    if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
168        NETDEBUG("wrong packet size received\n");
169        return netif;
170    }
171
172    struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
173
174    pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
175
176    /* RFC 826 "Packet Reception": */
177    if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
178        (hdr->hwlen != ETH_HWADDR_LEN) ||
179        (hdr->protolen != sizeof(ip4_addr_t)) ||
180        (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
181      LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
182        ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
183        hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
184      return netif;
185    }
186
187    ip_addr_t ip;
188    IPADDR2_COPY(&ip, &hdr->sipaddr);
189
190    /* don't store any IPs */
191    if (ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
192        return netif;
193    }
194
195    uint64_t hwaddr = 0;
196    if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
197                         (const ip4_addr_t **)&hwaddr) != -1) {
198        return netif;
199    }
200
201    /*
202     * If already exists, return
203     */
204
205    hwaddr = 0;
206    SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
207
208    NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
209
210    oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
211
212    etharp_add_static_entry(&ip, &hdr->shwaddr);
213
214    return netif;
215}
216
217static errval_t arp_service_start_st(struct net_state *st)
218{
219    errval_t err;
220
221    err = oct_init();
222    if (err_is_fail(err)) {
223        return err;
224    }
225
226    err = net_ARP_export(st, export_ARP_cb, connect_ARP_cb,
227                         get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT);
228    if (err_is_fail(err)) {
229        return err;
230    }
231
232    st->arp_running = true;
233
234    return SYS_ERR_OK;
235}
236
237errval_t arp_service_start(void)
238{
239    return arp_service_start_st(get_default_net_state());
240}
241
242static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
243{
244    errval_t err;
245
246    uint64_t ip, hwaddr;
247    err = oct_read(record, "_" ARP_ENTRY_FIELDS, &hwaddr, &ip);
248    if (err_is_fail(err)) {
249        DEBUG_ERR(err, "failed to read the entrie\n");
250    }
251
252    ip_addr_t ipaddr;
253    ipaddr.addr = (uint32_t)ip;
254
255    if (mode & OCT_ON_SET) {
256
257        NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
258
259        struct eth_addr mac;
260        SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
261
262        etharp_add_static_entry(&ipaddr, &mac);
263    } else if (mode & OCT_ON_DEL) {
264        NETDEBUG("deleting ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
265        etharp_remove_static_entry(&ipaddr);
266    }
267}
268
269
270
271static errval_t arp_service_subscribe_st(struct net_state *st)
272{
273    NETDEBUG("subscribing to ARP updates..\n");
274
275    errval_t err;
276    err = oct_init();
277    if (err_is_fail(err)) {
278        return err;
279    }
280
281    st->arp_running = false;
282
283    return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
284                                             st, &st->arp_triggerid);
285}
286
287errval_t arp_service_subscribe(void)
288{
289    struct net_state *st = get_default_net_state();
290    return arp_service_subscribe_st(st);
291}
292
293
294
295static void bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
296{
297    assert(err_is_ok(err));
298    struct net_state* sta = (struct net_state*) st;
299
300    sta->arp = b;
301    sta->arp_connected = true;
302}
303
304static errval_t arp_connect(struct net_state* st)
305{
306    errval_t err;
307    if (!st->arp_connected) {
308        iref_t iref;
309        err = nameservice_blocking_lookup("libnet_arp", &iref);
310        if (err_is_fail(err)) {
311            return err;
312        }
313
314        err = net_ARP_bind(iref, bind_cb, st, get_default_waitset(),
315                           IDC_BIND_FLAGS_DEFAULT);
316        if (err_is_fail(err)) {
317            return err;
318        }
319
320        while(!st->arp_connected) {
321            event_dispatch(get_default_waitset());
322        }
323    }
324    return SYS_ERR_OK;
325}
326
327errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac)
328{
329    errval_t err;
330
331    err = oct_init();
332    if (err_is_fail(err)) {
333        return err;
334    }
335
336    char* record = NULL;
337    char query[256] ;
338
339    sprintf(query, "net.arp.%d {mac: _ , ip: %d }", ip, ip);
340    err = oct_get(&record, query);
341    if (err_no(err) == OCT_ERR_NO_RECORD) {
342        struct net_state *st = get_default_net_state();
343        err = arp_connect(st);
344        if (err_is_fail(err)) {
345            return err;
346        }
347
348        err = st->arp->tx_vtbl.arp_force_lookup(st->arp, NOP_CONT, ip);
349        if (err_is_fail(err)) {
350            return err;
351        }
352
353        err = oct_wait_for(&record, query);
354        if (err_is_fail(err)) {
355            return err;
356        }
357    } else if (err_is_fail(err)) {
358        DEBUG_ERR(err, "cannot get mac address\n");
359        return err;
360    }
361
362    uint64_t ip_adr;
363    err = oct_read(record, "_" ARP_ENTRY_FIELDS, mac, &ip_adr);
364    if (err_is_fail(err)) {
365        DEBUG_ERR(err, "failed to read the entrie\n");
366    }
367
368    return SYS_ERR_OK;
369}
370
371