17
#include <embox/net/pack.h>
18
#include <framework/mod/options.h>
20
#include <net/inetdevice.h>
21
#include <net/l0/net_tx.h>
22
#include <net/l2/ethernet.h>
23
#include <net/l3/arp.h>
24
#include <net/l3/rarp.h>
25
#include <net/lib/arp.h>
26
#include <net/neighbour.h>
27
#include <net/netdevice.h>
28
#include <net/skbuff.h>
29
#include <net/util/macaddr.h>
34
static void log_rarp_hnd_request(const struct arphdr *rarph, uint8_t *dst_paddr,
36
static void log_rarp_hnd_reply(const struct arphdr *rarph,
37
const struct arpbody *rarpb);
39
EMBOX_NET_PACK(ETH_P_RARP, rarp_rcv);
41
static int rarp_xmit(struct sk_buff *skb) {
43
assert(skb->dev != NULL);
44
if (skb->dev->flags & IFF_NOARP) {
45
log_error("rarp_xmit: rarp doesn't supported by device %s\n",
52
return net_tx_direct(skb);
55
static int rarp_send(struct sk_buff *skb, struct net_device *dev, uint16_t pro,
56
uint8_t pln, uint16_t op, const void *sha, const void *spa, const void *tha,
57
const void *tpa, const void *tar) {
60
struct net_header_info hdr_info;
71
size = dev->hdr_len + ARP_CALC_HEADER_SIZE(dev->addr_len, pln);
72
if (size > min(dev->mtu, skb_max_size())) {
73
log_error("rarp_send: hdr size %zu is too big (max %zu)\n", size,
74
min(dev->mtu, skb_max_size()));
81
skb = skb_realloc(size, skb);
83
log_error("rarp_send: no memory\n");
88
skb->nh.raw = skb->mac.raw + dev->hdr_len;
92
hdr_info.type = ETH_P_RARP;
93
hdr_info.src_hw = sha;
94
hdr_info.dst_hw = tar;
95
assert(dev->ops != NULL);
96
assert(dev->ops->build_hdr != NULL);
97
ret = dev->ops->build_hdr(skb, &hdr_info);
99
log_error("rarp_send: can't build device header\n");
105
arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln, op, sha, spa,
109
return rarp_xmit(skb);
112
static int rarp_hnd_request(const struct arphdr *rarph,
113
const struct arpbody *rarpb, struct sk_buff *skb, struct net_device *dev) {
115
uint8_t src_paddr[MAX_ADDR_LEN];
116
uint8_t dst_haddr[MAX_ADDR_LEN], dst_paddr[MAX_ADDR_LEN];
117
uint8_t tar_haddr[MAX_ADDR_LEN];
118
struct in_device *in_dev;
120
in_dev = inetdev_get_by_dev(dev);
121
assert(in_dev != NULL);
124
if ((rarph->ar_pro != htons(ETH_P_IP))
125
|| (rarph->ar_pln != sizeof in_dev->ifa_address)) {
126
log_error("rarp_hnd_request: only IPv4 is supported\n");
132
memcpy(&src_paddr[0], &in_dev->ifa_address, rarph->ar_pln);
135
memcpy(&dst_haddr[0], rarpb->ar_tha, rarph->ar_hln);
136
ret = neighbour_get_paddr(ntohs(rarph->ar_hrd), &dst_haddr[0], dev,
137
ntohs(rarph->ar_pro), rarph->ar_pln, &dst_paddr[0]);
139
log_error("rarp_hnd_request: paddr not found in neighbour\n");
141
return ret != -ENOENT ? ret : 0;
145
memcpy(&tar_haddr[0], rarpb->ar_sha, rarph->ar_hln);
148
if (NULL == skb_declone(skb)) {
149
log_error("rarp_hnd_request: no memory\n");
154
if (log_level_self() == LOG_DEBUG) {
155
log_rarp_hnd_request(rarph, &dst_paddr[0], &dst_haddr[0]);
159
return rarp_send(skb, dev, ntohs(rarph->ar_pro), rarph->ar_pln,
160
RARP_OP_REPLY, &dev->dev_addr[0], &src_paddr[0], &dst_haddr[0],
161
&dst_paddr[0], &tar_haddr[0]);
164
static int rarp_hnd_reply(const struct arphdr *rarph,
165
const struct arpbody *rarpb, struct sk_buff *skb, struct net_device *dev) {
168
assert(rarph != NULL);
169
assert(rarpb != NULL);
172
ret = neighbour_add(ntohs(rarph->ar_pro), rarpb->ar_tpa, rarph->ar_pln, dev,
173
ntohs(rarph->ar_hrd), rarpb->ar_tha, rarph->ar_hln, 0);
175
log_error("rarp_hnd_reply: can't update neighbour\n");
180
if (log_level_self() == LOG_DEBUG) {
181
log_rarp_hnd_reply(rarph, rarpb);
190
static void log_rarp_hnd_request(const struct arphdr *rarph, uint8_t *dst_paddr,
191
uint8_t *dst_haddr) {
192
log_debug("rarp_hnd_request: send reply with ");
193
if (rarph->ar_pro == ntohs(ETH_P_IP)) {
195
assert(rarph->ar_pln == sizeof in);
196
memcpy(&in, dst_paddr, sizeof in);
197
log_debug("%s", inet_ntoa(in));
200
log_debug("unknown(%x)", htons(rarph->ar_pro));
202
if (rarph->ar_hrd == ntohs(ARP_HRD_ETHERNET)) {
203
assert(rarph->ar_hln == ETH_ALEN);
204
log_debug("[" MACADDR_FMT "]", MACADDR_FMT_ARG(dst_haddr));
207
log_debug("[unknown(%x)]", htons(rarph->ar_hrd));
212
static void log_rarp_hnd_reply(const struct arphdr *rarph,
213
const struct arpbody *rarpb) {
214
log_debug("rarp_hnd_reply: receive reply with ");
215
if (rarph->ar_pro == ntohs(ETH_P_IP)) {
217
assert(rarph->ar_pln == sizeof in);
218
memcpy(&in, rarpb->ar_tpa, sizeof in);
219
log_debug("%s", inet_ntoa(in));
222
log_debug("unknown(%x)", htons(rarph->ar_pro));
224
if (rarph->ar_hrd == ntohs(ARP_HRD_ETHERNET)) {
225
assert(rarph->ar_hln == ETH_ALEN);
226
log_debug("[" MACADDR_FMT "]", MACADDR_FMT_ARG(rarpb->ar_tha));
229
log_debug("[unknown(%x)]", htons(rarph->ar_hrd));
234
static int rarp_rcv(struct sk_buff *skb, struct net_device *dev) {
235
struct arphdr *rarph;
236
struct arpbody rarpb;
242
if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
246
rarph = arp_hdr(skb);
249
if (dev->hdr_len + ARP_HEADER_SIZE(rarph) > skb->len) {
255
if ((rarph->ar_hrd != htons(dev->type))
256
|| (rarph->ar_hln != dev->addr_len)) {
262
arp_make_body(rarph, &rarpb);
265
switch (rarph->ar_op) {
269
case htons(RARP_OP_REQUEST):
271
return rarp_hnd_request(rarph, &rarpb, skb, dev);
272
case htons(RARP_OP_REPLY):
274
return rarp_hnd_reply(rarph, &rarpb, skb, dev);