8 * Copyright (c) 2017 ETH Zurich.
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.
17 #include <barrelfish/barrelfish.h>
18 #include <barrelfish/nameservice_client.h>
22 #include <lwip/netif.h>
23 #include <lwip/timeouts.h>
24 #include <net/netif.h>
26 #include <netif/etharp.h>
28 #include <if/octopus_defs.h>
29 #include <if/net_ARP_defs.h>
30 #include <octopus/octopus.h>
31 #include <octopus/trigger.h>
34 #include "networking_internal.h"
36 ///< the debug subsystem
37 #define NETDEBUG_SUBSYSTEM "arpd"
40 #define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
41 #define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
43 #define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
46 // Reuse existing Flounder interface
47 static void arp_force_lookup(struct net_ARP_binding *b,
51 struct net_state *sta = (struct net_state*) b->st;
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));
58 err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
59 assert(err_is_ok(err));
61 err = etharp_request(&sta->netif, (ip4_addr_t*) &ip);
62 assert(err_is_ok(err));
64 } // end function: ARP_resolve_request
67 static struct net_ARP_rx_vtbl rx_arp_vtbl = {
68 .arp_force_lookup = arp_force_lookup,
71 /*****************************************************************
72 * Dealing with new connections
73 *****************************************************************/
74 static errval_t connect_ARP_cb(void *st, struct net_ARP_binding *b)
77 b->rx_vtbl = rx_arp_vtbl;
81 /*****************************************************************
83 *****************************************************************/
85 static void export_ARP_cb(void *st, errval_t err, iref_t iref)
87 struct net_state *sta = st;
89 if (err_is_fail(err)) {
90 DEBUG_ERR(err, "service export failed");
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?
99 sta->arp_running = true;
102 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
104 if (type != ETHTYPE_ARP) {
108 struct net_state *st = netif->state;
110 if (!st->arp_running) {
114 if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
115 NETDEBUG("wrong packet size received\n");
119 struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
121 pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
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));
135 IPADDR2_COPY(&ip, &hdr->sipaddr);
137 /* don't store any IPs */
138 if (ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
143 if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
144 (const ip4_addr_t **)&hwaddr) != -1) {
149 * If already exists, return
153 SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
155 NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
157 oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
159 etharp_add_static_entry(&ip, &hdr->shwaddr);
164 static errval_t arp_service_start_st(struct net_state *st)
169 if (err_is_fail(err)) {
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)) {
179 st->arp_running = true;
184 errval_t arp_service_start(void)
186 return arp_service_start_st(get_default_net_state());
189 static void arp_change_event(octopus_mode_t mode, const char* record, void* st)
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");
200 ipaddr.addr = (uint32_t)ip;
202 if (mode & OCT_ON_SET) {
204 NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
207 SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
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);
218 static errval_t arp_service_subscribe_st(struct net_state *st)
220 NETDEBUG("subscribing to ARP updates..\n");
224 if (err_is_fail(err)) {
228 st->arp_running = false;
230 return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
231 st, &st->arp_triggerid);
234 errval_t arp_service_subscribe(void)
236 struct net_state *st = get_default_net_state();
237 return arp_service_subscribe_st(st);
242 static void bind_cb(void *st, errval_t err, struct net_ARP_binding *b)
244 assert(err_is_ok(err));
245 struct net_state* sta = (struct net_state*) st;
248 sta->arp_connected = true;
251 static errval_t arp_connect(struct net_state* st)
254 if (!st->arp_connected) {
256 err = nameservice_blocking_lookup("libnet_arp", &iref);
257 if (err_is_fail(err)) {
261 err = net_ARP_bind(iref, bind_cb, st, get_default_waitset(),
262 IDC_BIND_FLAGS_DEFAULT);
263 if (err_is_fail(err)) {
267 while(!st->arp_connected) {
268 event_dispatch(get_default_waitset());
274 errval_t arp_service_get_mac(uint32_t ip, uint64_t* mac)
279 if (err_is_fail(err)) {
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)) {
295 err = st->arp->tx_vtbl.arp_force_lookup(st->arp, NOP_CONT, ip);
296 if (err_is_fail(err)) {
300 err = oct_wait_for(&record, query);
301 if (err_is_fail(err)) {
304 } else if (err_is_fail(err)) {
305 DEBUG_ERR(err, "cannot get mac address\n");
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");