embox

Форк
0
/
arp.c 
276 строк · 6.5 Кб
1
/**
2
 * @file
3
 * @brief An Ethernet Address Resolution Protocol
4
 * @details RFC 826
5
 *
6
 * @date 11.03.09
7
 * @author Anton Bondarev
8
 * @author Nikolay Korotky
9
 * @author Ilia Vaprol
10
 */
11

12
#include <arpa/inet.h>
13
#include <assert.h>
14
#include <errno.h>
15
#include <stddef.h>
16
#include <stdint.h>
17
#include <string.h>
18

19
#include <embox/net/pack.h>
20
#include <framework/mod/options.h>
21
#include <net/if.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>
31
#include <util/log.h>
32
#include <util/math.h>
33

34
static void log_arp_hnd_request(const struct arphdr *rarph, uint8_t *dst_paddr,
35
    uint8_t *dst_haddr);
36
static void log_arp_hnd_reply(const struct arphdr *rarph,
37
    const struct arpbody *rarpb);
38

39
EMBOX_NET_PACK(ETH_P_ARP, arp_rcv);
40

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,
43
    const void *tpa) {
44
	int ret;
45
	struct net_header_info hdr_info;
46

47
	assert(dev != NULL);
48
	if (dev->flags & IFF_NOARP) {
49
		log_error("arp isn't supported by device %s", dev->name);
50
		return -ENOSUPP;
51
	}
52

53
	assert(skb != NULL);
54
	assert(pln != 0);
55
	assert(sha != NULL);
56
	assert(spa != NULL);
57
	assert(tha != NULL);
58
	assert(tpa != NULL);
59

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;
65

66
	assert(dev->ops != NULL);
67
	assert(dev->ops->build_hdr != NULL);
68
	ret = dev->ops->build_hdr(skb, &hdr_info);
69
	if (ret != 0) {
70
		log_error("can't build device header");
71
		return ret;
72
	}
73

74
	arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln, op, sha, spa,
75
	    tha, tpa);
76

77
	net_tx_direct(skb);
78

79
	return 0;
80
}
81

82
static int arp_update_neighbour(const struct arphdr *arph,
83
    const struct arpbody *arpb, struct net_device *dev) {
84
	assert(arph != NULL);
85
	assert(arpb != NULL);
86

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);
89
}
90

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;
96

97
	in_dev = inetdev_get_by_dev(dev);
98
	assert(in_dev != NULL);
99

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 */
104
	}
105

106
	if (0 != arp_update_neighbour(arph, arpb, dev)) {
107
		log_error("can't update neighbour");
108
	}
109

110
	if (0 != memcmp(arpb->ar_tpa, &in_dev->ifa_address, arph->ar_pln)) {
111
		log_error("not for us");
112
		return -EINVAL;
113
	}
114

115
	/* save src protocol address */
116
	memcpy(&src_paddr[0], arpb->ar_tpa, arph->ar_pln);
117

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);
121

122
	if (NULL == skb_declone(skb)) {
123
		log_error("no memory");
124
		return -ENOMEM;
125
	}
126

127
	log_arp_hnd_request(arph, &dst_paddr[0], &dst_haddr[0]);
128

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]);
131
}
132

133
static int arp_hnd_reply(const struct arphdr *arph, const struct arpbody *arpb,
134
    struct sk_buff *skb, struct net_device *dev) {
135
	int ret;
136

137
	ret = arp_update_neighbour(arph, arpb, dev);
138
	if (ret != 0) {
139
		log_error("can't update neighbour");
140
		return ret;
141
	}
142

143
	log_arp_hnd_reply(arph, arpb);
144

145
	return 0;
146
}
147

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)) {
152
		struct in_addr in;
153
		assert(arph->ar_pln == sizeof in);
154
		memcpy(&in, dst_paddr, sizeof in);
155
		log_debug("%s", inet_ntoa(in));
156
	}
157
	else {
158
		log_debug("unknown(%x)", htons(arph->ar_pro));
159
	}
160

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));
164
	}
165
	else {
166
		log_debug("[unknown(%x)]", htons(arph->ar_hrd));
167
	}
168
}
169

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)) {
174
		struct in_addr in;
175
		assert(arph->ar_pln == sizeof in);
176
		memcpy(&in, arpb->ar_spa, sizeof in);
177
		log_debug("%s", inet_ntoa(in));
178
	}
179
	else {
180
		log_debug("unknown(%x)", htons(arph->ar_pro));
181
	}
182

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));
186
	}
187
	else {
188
		log_debug("[unknown(%x)]", htons(arph->ar_hrd));
189
	}
190
}
191

192
static int arp_rcv(struct sk_buff *skb, struct net_device *dev) {
193
	struct arphdr *arph;
194
	struct arpbody arpb;
195
	int ret = 0;
196

197
	assert(skb != NULL);
198
	assert(dev != NULL);
199

200
	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
201
		log_error("arp isn't supported by device %s", &dev->name[0]);
202
		return 0;
203
	}
204

205
	arph = arp_hdr(skb);
206

207
	if (dev->hdr_len + ARP_HEADER_SIZE(arph) > skb->len) {
208
		log_error("bad packet length");
209
		skb_free(skb);
210
		return 0;
211
	}
212

213
	if ((arph->ar_hrd != htons(dev->type)) || (arph->ar_hln != dev->addr_len)) {
214
		log_error("invalid hardware type or address length");
215
		skb_free(skb);
216
		return 0;
217
	}
218

219
	arp_make_body(arph, &arpb);
220

221
	switch (arph->ar_op) {
222
	default:
223
		skb_free(skb);
224
		log_error("bad operation code");
225
		return 0;
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 */
230
		if (ret != 0) {
231
			skb_free(skb);
232
		}
233

234
		return ret;
235
	case htons(ARP_OP_REPLY):
236
		ret = arp_hnd_reply(arph, &arpb, skb, dev);
237

238
		skb_free(skb);
239

240
		return ret;
241
	}
242
}
243

244
int arp_discover(struct net_device *dev, uint16_t pro, uint8_t pln,
245
    const void *spa, const void *tpa) {
246
	size_t size;
247
	int ret;
248
	struct sk_buff *skb;
249

250
	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
251
		return -ENOSUPP;
252
	}
253

254
	size = dev->hdr_len + ARP_CALC_HEADER_SIZE(dev->addr_len, pln);
255
	if (size > dev->mtu) {
256
		return -EMSGSIZE;
257
	}
258

259
	skb = skb_alloc(size);
260
	if (skb == NULL) {
261
		return -ENOMEM;
262
	}
263

264
	skb->dev = dev;
265
	skb->nh.raw = skb->mac.raw + dev->hdr_len;
266

267
	ret = arp_send(skb, dev, pro, pln, ARP_OP_REQUEST, &dev->dev_addr[0], spa,
268
	    &dev->broadcast[0], tpa);
269

270
	/* If there are no errors, skb was passed to net stack,
271
	 * so we don't need to free it */
272
	if (ret != 0) {
273
		skb_free(skb);
274
	}
275
	return ret;
276
}
277

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.