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