embox

Форк
0
/
rarp.c 
276 строк · 7.1 Кб
1
/**
2
 * @file
3
 * @brief A Reverse Address Resolution Protocol
4
 * @details RFC 903
5
 *
6
 * @date 29.09.12
7
 * @author Ilia Vaprol
8
 */
9

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

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

33
// Forward declarations
34
static void log_rarp_hnd_request(const struct arphdr *rarph, uint8_t *dst_paddr,
35
    uint8_t *dst_haddr);
36
static void log_rarp_hnd_reply(const struct arphdr *rarph,
37
    const struct arpbody *rarpb);
38

39
EMBOX_NET_PACK(ETH_P_RARP, rarp_rcv);
40

41
static int rarp_xmit(struct sk_buff *skb) {
42
	assert(skb != NULL);
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",
46
		    &skb->dev->name[0]);
47
		skb_free(skb);
48
		return 0; /* error: rarp doesn't supported by device */
49
	}
50

51
	/* fall through to dev layer */
52
	return net_tx_direct(skb);
53
}
54

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) {
58
	int ret;
59
	size_t size;
60
	struct net_header_info hdr_info;
61

62
	assert(skb != NULL);
63
	assert(dev != NULL);
64
	assert(pln != 0);
65
	assert(sha != NULL);
66
	assert(spa != NULL);
67
	assert(tha != NULL);
68
	assert(tpa != NULL);
69
	assert(tar != NULL);
70

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()));
75
		if (skb) {
76
			skb_free(skb); /* TODO */
77
		}
78
		return -EMSGSIZE; /* error: hdr size is too big */
79
	}
80

81
	skb = skb_realloc(size, skb);
82
	if (skb == NULL) {
83
		log_error("rarp_send: no memory\n");
84
		return -ENOMEM; /* error: no memory */
85
	}
86

87
	skb->dev = dev;
88
	skb->nh.raw = skb->mac.raw + dev->hdr_len;
89

90
	/* build device specific header */
91
	/* TODO move to l0 level */
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);
98
	if (ret != 0) {
99
		log_error("rarp_send: can't build device header\n");
100
		skb_free(skb);
101
		return ret;
102
	}
103

104
	/* build RARP header */
105
	arp_build(arp_hdr(skb), dev->type, pro, dev->addr_len, pln, op, sha, spa,
106
	    tha, tpa);
107

108
	/* and send */
109
	return rarp_xmit(skb);
110
}
111

112
static int rarp_hnd_request(const struct arphdr *rarph,
113
    const struct arpbody *rarpb, struct sk_buff *skb, struct net_device *dev) {
114
	int ret;
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;
119

120
	in_dev = inetdev_get_by_dev(dev);
121
	assert(in_dev != NULL);
122

123
	/* check protocol capabilities */
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");
127
		skb_free(skb);
128
		return 0; /* FIXME error: only IPv4 is supported */
129
	}
130

131
	/* get source protocol address */
132
	memcpy(&src_paddr[0], &in_dev->ifa_address, rarph->ar_pln);
133

134
	/* get dest addresses */
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]);
138
	if (ret != 0) {
139
		log_error("rarp_hnd_request: paddr not found in neighbour\n");
140
		skb_free(skb);
141
		return ret != -ENOENT ? ret : 0;
142
	}
143

144
	/* get target hardware address */
145
	memcpy(&tar_haddr[0], rarpb->ar_sha, rarph->ar_hln);
146

147
	/* declone sk_buff */
148
	if (NULL == skb_declone(skb)) {
149
		log_error("rarp_hnd_request: no memory\n");
150
		skb_free(skb);
151
		return -ENOMEM;
152
	}
153

154
	if (log_level_self() == LOG_DEBUG) {
155
		log_rarp_hnd_request(rarph, &dst_paddr[0], &dst_haddr[0]);
156
	}
157

158
	/* send reply */
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]);
162
}
163

164
static int rarp_hnd_reply(const struct arphdr *rarph,
165
    const struct arpbody *rarpb, struct sk_buff *skb, struct net_device *dev) {
166
	int ret;
167

168
	assert(rarph != NULL);
169
	assert(rarpb != NULL);
170

171
	/* save destination hardware and protocol addresses */
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);
174
	if (ret != 0) {
175
		log_error("rarp_hnd_reply: can't update neighbour\n");
176
		skb_free(skb);
177
		return ret;
178
	}
179

180
	if (log_level_self() == LOG_DEBUG) {
181
		log_rarp_hnd_reply(rarph, rarpb);
182
	}
183

184
	/* free sk_buff */
185
	skb_free(skb);
186

187
	return 0;
188
}
189

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)) {
194
		struct in_addr in;
195
		assert(rarph->ar_pln == sizeof in);
196
		memcpy(&in, dst_paddr, sizeof in);
197
		log_debug("%s", inet_ntoa(in));
198
	}
199
	else {
200
		log_debug("unknown(%x)", htons(rarph->ar_pro));
201
	}
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));
205
	}
206
	else {
207
		log_debug("[unknown(%x)]", htons(rarph->ar_hrd));
208
	}
209
	log_debug("\n");
210
}
211

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)) {
216
		struct in_addr in;
217
		assert(rarph->ar_pln == sizeof in);
218
		memcpy(&in, rarpb->ar_tpa, sizeof in);
219
		log_debug("%s", inet_ntoa(in));
220
	}
221
	else {
222
		log_debug("unknown(%x)", htons(rarph->ar_pro));
223
	}
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));
227
	}
228
	else {
229
		log_debug("[unknown(%x)]", htons(rarph->ar_hrd));
230
	}
231
	log_debug("\n");
232
}
233

234
static int rarp_rcv(struct sk_buff *skb, struct net_device *dev) {
235
	struct arphdr *rarph;
236
	struct arpbody rarpb;
237

238
	assert(skb != NULL);
239
	assert(dev != NULL);
240

241
	/* check device flags */
242
	if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
243
		return 0; /* error: rarp doesn't supported by device */
244
	}
245

246
	rarph = arp_hdr(skb);
247

248
	/* check hardware and protocol address lengths */
249
	if (dev->hdr_len + ARP_HEADER_SIZE(rarph) > skb->len) {
250
		skb_free(skb);
251
		return 0; /* error: bad packet */
252
	}
253

254
	/* check device capabilities */
255
	if ((rarph->ar_hrd != htons(dev->type))
256
	    || (rarph->ar_hln != dev->addr_len)) {
257
		skb_free(skb);
258
		return 0; /* error: invalid hardware address info */
259
	}
260

261
	/* build rarp body */
262
	arp_make_body(rarph, &rarpb);
263

264
	/* process the packet by the operation code */
265
	switch (rarph->ar_op) {
266
	default:
267
		skb_free(skb);
268
		return 0; /* error: bad operation type */
269
	case htons(RARP_OP_REQUEST):
270
		/* handling request */
271
		return rarp_hnd_request(rarph, &rarpb, skb, dev);
272
	case htons(RARP_OP_REPLY):
273
		/* handling reply */
274
		return rarp_hnd_reply(rarph, &rarpb, skb, dev);
275
	}
276
}
277

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

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

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

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