3
* @brief An Ethernet Address Resolution Protocol
7
* @author Anton Bondarev
8
* @author Nikolay Korotky
19
#include <embox/net/pack.h>
20
#include <framework/mod/options.h>
22
#include <net/inetdevice.h>
23
#include <net/l0/net_tx.h>
24
#include <net/l2/ethernet.h>
25
#include <net/l3/arp.h>
26
#include <net/lib/arp.h>
27
#include <net/neighbour.h>
28
#include <net/netdevice.h>
29
#include <net/skbuff.h>
30
#include <net/util/macaddr.h>
34
static void log_arp_hnd_request(const struct arphdr *rarph, uint8_t *dst_paddr,
36
static void log_arp_hnd_reply(const struct arphdr *rarph,
37
const struct arpbody *rarpb);
39
EMBOX_NET_PACK(ETH_P_ARP, arp_rcv);
41
static int arp_send(struct sk_buff *skb, struct net_device *dev, uint16_t pro,
42
uint8_t pln, uint16_t op, const void *sha, const void *spa, const void *tha,
45
struct net_header_info hdr_info;
48
if (dev->flags & IFF_NOARP) {
49
log_error("arp isn't supported by device %s", dev->name);
60
/* build device specific header */
61
/* TODO move to l0 level */
62
hdr_info.type = ETH_P_ARP;
63
hdr_info.src_hw = sha;
64
hdr_info.dst_hw = tha;
66
assert(dev->ops != NULL);
67
assert(dev->ops->build_hdr != NULL);
68
ret = dev->ops->build_hdr(skb, &hdr_info);
70
log_error("can't build device header");
74
arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln, op, sha, spa,
82
static int arp_update_neighbour(const struct arphdr *arph,
83
const struct arpbody *arpb, struct net_device *dev) {
87
return neighbour_add(ntohs(arph->ar_pro), arpb->ar_spa, arph->ar_pln, dev,
88
ntohs(arph->ar_hrd), arpb->ar_sha, arph->ar_hln, 0);
91
static int arp_hnd_request(const struct arphdr *arph,
92
const struct arpbody *arpb, struct sk_buff *skb, struct net_device *dev) {
93
uint8_t src_paddr[MAX_ADDR_LEN];
94
uint8_t dst_haddr[MAX_ADDR_LEN], dst_paddr[MAX_ADDR_LEN];
95
struct in_device *in_dev;
97
in_dev = inetdev_get_by_dev(dev);
98
assert(in_dev != NULL);
100
if ((arph->ar_pro != htons(ETH_P_IP))
101
|| (arph->ar_pln != sizeof in_dev->ifa_address)) {
102
log_error("only IPv4 is supported");
103
return -ENOSUPP; /* FIXME error: only IPv4 is supported */
106
if (0 != arp_update_neighbour(arph, arpb, dev)) {
107
log_error("can't update neighbour");
110
if (0 != memcmp(arpb->ar_tpa, &in_dev->ifa_address, arph->ar_pln)) {
111
log_error("not for us");
115
/* save src protocol address */
116
memcpy(&src_paddr[0], arpb->ar_tpa, arph->ar_pln);
118
/* save dest hardware/protocol addresses */
119
memcpy(&dst_haddr[0], arpb->ar_sha, arph->ar_hln);
120
memcpy(&dst_paddr[0], arpb->ar_spa, arph->ar_pln);
122
if (NULL == skb_declone(skb)) {
123
log_error("no memory");
127
log_arp_hnd_request(arph, &dst_paddr[0], &dst_haddr[0]);
129
return arp_send(skb, dev, ntohs(arph->ar_pro), arph->ar_pln, ARP_OP_REPLY,
130
&dev->dev_addr[0], &src_paddr[0], &dst_haddr[0], &dst_paddr[0]);
133
static int arp_hnd_reply(const struct arphdr *arph, const struct arpbody *arpb,
134
struct sk_buff *skb, struct net_device *dev) {
137
ret = arp_update_neighbour(arph, arpb, dev);
139
log_error("can't update neighbour");
143
log_arp_hnd_reply(arph, arpb);
148
static void log_arp_hnd_request(const struct arphdr *arph, uint8_t *dst_paddr,
149
uint8_t *dst_haddr) {
150
log_debug("send reply with ");
151
if (arph->ar_pro == ntohs(ETH_P_IP)) {
153
assert(arph->ar_pln == sizeof in);
154
memcpy(&in, dst_paddr, sizeof in);
155
log_debug("%s", inet_ntoa(in));
158
log_debug("unknown(%x)", htons(arph->ar_pro));
161
if (arph->ar_hrd == ntohs(ARP_HRD_ETHERNET)) {
162
assert(arph->ar_hln == ETH_ALEN);
163
log_debug("[" MACADDR_FMT "]", MACADDR_FMT_ARG(dst_haddr));
166
log_debug("[unknown(%x)]", htons(arph->ar_hrd));
170
static void log_arp_hnd_reply(const struct arphdr *arph,
171
const struct arpbody *arpb) {
172
log_debug("receive reply with ");
173
if (arph->ar_pro == ntohs(ETH_P_IP)) {
175
assert(arph->ar_pln == sizeof in);
176
memcpy(&in, arpb->ar_spa, sizeof in);
177
log_debug("%s", inet_ntoa(in));
180
log_debug("unknown(%x)", htons(arph->ar_pro));
183
if (arph->ar_hrd == ntohs(ARP_HRD_ETHERNET)) {
184
assert(arph->ar_hln == ETH_ALEN);
185
log_debug("[" MACADDR_FMT "]", MACADDR_FMT_ARG(arpb->ar_sha));
188
log_debug("[unknown(%x)]", htons(arph->ar_hrd));
192
static int arp_rcv(struct sk_buff *skb, struct net_device *dev) {
200
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
201
log_error("arp isn't supported by device %s", &dev->name[0]);
207
if (dev->hdr_len + ARP_HEADER_SIZE(arph) > skb->len) {
208
log_error("bad packet length");
213
if ((arph->ar_hrd != htons(dev->type)) || (arph->ar_hln != dev->addr_len)) {
214
log_error("invalid hardware type or address length");
219
arp_make_body(arph, &arpb);
221
switch (arph->ar_op) {
224
log_error("bad operation code");
226
case htons(ARP_OP_REQUEST):
227
ret = arp_hnd_request(arph, &arpb, skb, dev);
228
/* If there are no errors, skb was passed to net stack,
229
* so we don't need to free it */
235
case htons(ARP_OP_REPLY):
236
ret = arp_hnd_reply(arph, &arpb, skb, dev);
244
int arp_discover(struct net_device *dev, uint16_t pro, uint8_t pln,
245
const void *spa, const void *tpa) {
250
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
254
size = dev->hdr_len + ARP_CALC_HEADER_SIZE(dev->addr_len, pln);
255
if (size > dev->mtu) {
259
skb = skb_alloc(size);
265
skb->nh.raw = skb->mac.raw + dev->hdr_len;
267
ret = arp_send(skb, dev, pro, pln, ARP_OP_REQUEST, &dev->dev_addr[0], spa,
268
&dev->broadcast[0], tpa);
270
/* If there are no errors, skb was passed to net stack,
271
* so we don't need to free it */