0e01eb9dde4cc5bef56ec9fc6d55bce026b2748a
[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
19
20 #include <lwip/opt.h>
21 #include <lwip/netif.h>
22 #include <lwip/timeouts.h>
23 #include <net/netif.h>
24
25 #include <netif/etharp.h>
26
27 #include <if/octopus_defs.h>
28 #include <octopus/octopus.h>
29 #include <octopus/trigger.h>
30
31
32 #include "networking_internal.h"
33
34 ///< the debug subsystem
35 #define NETDEBUG_SUBSYSTEM "arpd"
36
37
38 #define ARP_ENTRY_FIELDS "{mac: %d, ip: %d}"
39 #define ARP_ENTRY "net.arp.%d {mac: %lu, ip: %d}"
40
41 #define ARP_ENTRY_REGEX "r'net\\.arp\\.[0-9]+' { mac: _, ip: _}"
42
43 struct netif *arp_filter_netif(struct pbuf *p, struct netif *netif, uint16_t type)
44 {
45     if (type != ETHTYPE_ARP) {
46         return netif;
47     }
48
49     struct net_state *st = netif->state;
50
51     if (!st->arp_running) {
52         return netif;
53     }
54
55     if (p->len < SIZEOF_ETH_HDR || pbuf_header(p, (s16_t)-SIZEOF_ETH_HDR)) {
56         NETDEBUG("wrong packet size received\n");
57         return netif;
58     }
59
60     struct etharp_hdr *hdr = (struct etharp_hdr *)p->payload;
61
62     pbuf_header(p, (s16_t)SIZEOF_ETH_HDR);
63
64     /* RFC 826 "Packet Reception": */
65     if ((hdr->hwtype != PP_HTONS(HWTYPE_ETHERNET)) ||
66         (hdr->hwlen != ETH_HWADDR_LEN) ||
67         (hdr->protolen != sizeof(ip4_addr_t)) ||
68         (hdr->proto != PP_HTONS(ETHTYPE_IP)))  {
69       LWIP_DEBUGF(ETHARP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING,
70         ("etharp_input: packet dropped, wrong hw type, hwlen, proto, protolen or ethernet type (%"U16_F"/%"U16_F"/%"U16_F"/%"U16_F")\n",
71         hdr->hwtype, (u16_t)hdr->hwlen, hdr->proto, (u16_t)hdr->protolen));
72       return netif;
73     }
74
75     ip_addr_t ip;
76     IPADDR2_COPY(&ip, &hdr->sipaddr);
77
78     /* don't store any IPs */
79     if (ip_addr_cmp(&st->netif.ip_addr, IP_ADDR_ANY)) {
80         return netif;
81     }
82
83     uint64_t hwaddr = 0;
84     if (etharp_find_addr(netif, &ip, (struct eth_addr **)&hwaddr,
85                          (const ip4_addr_t **)&hwaddr) != -1) {
86         return netif;
87     }
88
89     /*
90      * If already exists, return
91      */
92
93     hwaddr = 0;
94     SMEMCPY(&hwaddr, hdr->shwaddr.addr, sizeof(hdr->shwaddr));
95
96     NETDEBUG("set " ARP_ENTRY "\n", ip.addr, hwaddr, ip.addr);
97
98     oct_set(ARP_ENTRY, ip.addr, hwaddr, ip.addr);
99
100     etharp_add_static_entry(&ip, &hdr->shwaddr);
101
102     return netif;
103 }
104
105 static errval_t arp_service_start_st(struct net_state *st)
106 {
107     errval_t err;
108
109     err = oct_init();
110     if (err_is_fail(err)) {
111         return err;
112     }
113
114     st->arp_running = true;
115
116     return SYS_ERR_OK;
117 }
118
119 errval_t arp_service_start(void)
120 {
121     return arp_service_start_st(get_default_net_state());
122 }
123
124 static  void arp_change_event(octopus_mode_t mode, const char* record, void* st)
125 {
126     errval_t err;
127
128     uint64_t ip, hwaddr;
129     err = oct_read(record, "_" ARP_ENTRY_FIELDS, &hwaddr, &ip);
130     if (err_is_fail(err)) {
131         DEBUG_ERR(err, "failed to read the entrie\n");
132     }
133
134     ip_addr_t ipaddr;
135     ipaddr.addr = (uint32_t)ip;
136
137     if (mode & OCT_ON_SET) {
138
139         NETDEBUG("adding ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
140
141         struct eth_addr mac;
142         SMEMCPY(mac.addr, &hwaddr, sizeof(mac));
143
144         etharp_add_static_entry(&ipaddr, &mac);
145     } else if (mode & OCT_ON_DEL) {
146         NETDEBUG("deleting ARP entries: ip=%u, mac=%lx\n", ipaddr.addr, hwaddr);
147         etharp_remove_static_entry(&ipaddr);
148     }
149 }
150
151 static errval_t arp_service_subscribe_st(struct net_state *st)
152 {
153     NETDEBUG("subscribing to ARP updates..\n");
154
155     errval_t err;
156     err = oct_init();
157     if (err_is_fail(err)) {
158         return err;
159     }
160
161     st->arp_running = false;
162
163     return oct_trigger_existing_and_watch(ARP_ENTRY_REGEX, arp_change_event,
164                                              st, &st->arp_triggerid);
165 }
166
167 errval_t arp_service_subscribe(void)
168 {
169     struct net_state *st = get_default_net_state();
170     return arp_service_subscribe_st(st);
171 }