embox

Форк
0
/
ip6_output.c 
123 строки · 2.8 Кб
1
/**
2
 * @file
3
 * @brief The Internet Protocol Version 6 (IPV6) module.
4
 *
5
 * @date 24.10.13
6
 * @author Ilia Vaprol
7
 */
8

9
#include <errno.h>
10
#include <net/l3/ipv6.h>
11
#include <net/l2/ethernet.h>
12
#include <net/inetdevice.h>
13
#include <net/l0/net_tx.h>
14
#include <net/skbuff.h>
15
#include <util/math.h>
16
#include <embox/net/pack.h>
17
#include <net/socket/inet6_sock.h>
18
#include <string.h>
19
#include <net/lib/ipv6.h>
20

21
static const struct net_pack_out_ops ip6_out_ops_struct;
22
const struct net_pack_out_ops *const ip6_out_ops = &ip6_out_ops_struct;
23

24
static int ip6_xmit(struct sk_buff *skb) {
25
	struct net_header_info hdr_info;
26

27
	assert(skb != NULL);
28
	assert(skb->nh.iph != NULL);
29

30
	hdr_info.type = ETH_P_IPV6;
31

32
	hdr_info.dst_hw = NULL;
33

34
	/* FIXME */
35
	assert(skb->dev != NULL);
36
	hdr_info.src_hw = skb->dev->dev_addr;
37
	if (skb->dev->flags & IFF_LOOPBACK) {
38
		hdr_info.dst_p = NULL;
39
	}
40
	else {
41
		hdr_info.dst_p = &skb->nh.ip6h->daddr;
42
		hdr_info.p_len = sizeof(skb->nh.ip6h->daddr);
43
	}
44

45
	return net_tx(skb, &hdr_info);
46
}
47

48
static int ip6_make(const struct sock *sk,
49
		const struct sockaddr *to,
50
		size_t *data_size, struct sk_buff **out_skb) {
51
	size_t hdr_size, max_size;
52
	struct sk_buff *skb;
53
	struct net_device *dev;
54
	const struct inet6_sock *in6_sk;
55
	const struct sockaddr_in6 *to_in6;
56
	uint8_t nexthdr;
57
	const struct in6_addr *src_ip6;
58
	struct in6_addr dst_ip6;
59

60
	assert((to == NULL) || (to->sa_family == AF_INET6));
61
	assert(data_size != NULL);
62
	assert(out_skb != NULL);
63
	assert((sk != NULL) || (*out_skb != NULL));
64

65
	in6_sk = to_const_inet6_sock(sk);
66
	to_in6 = (const struct sockaddr_in6 *)to;
67

68
	assert((to_in6 == NULL)
69
			|| (to_in6->sin6_family == AF_INET6));
70

71
	memcpy(&dst_ip6, to_in6 != NULL ? &to_in6->sin6_addr
72
				: in6_sk != NULL ? &in6_sk->dst_in6.sin6_addr
73
				: &(*out_skb)->nh.ip6h->saddr, /* make a reply */
74
			sizeof dst_ip6);
75
	/* FIXME use route */
76
	if (0 == memcmp(&dst_ip6, &in6addr_loopback,
77
				sizeof dst_ip6)) {
78
		dev = netdev_get_by_name("lo");
79
	}
80
	else {
81
		dev = netdev_get_by_name("eth0");
82
	}
83
	assert(dev != NULL);
84

85
	assert(inetdev_get_by_dev(dev) != NULL);
86
	src_ip6 = &inetdev_get_by_dev(dev)->ifa6_address;
87

88
	nexthdr = in6_sk != NULL ? in6_sk->sk.opt.so_protocol
89
			: (*out_skb)->nh.ip6h->nexthdr;
90

91
	hdr_size = dev->hdr_len + IP6_HEADER_SIZE;
92
	max_size = min(dev->mtu, skb_max_size());
93
	if (hdr_size > max_size) {
94
		return -EMSGSIZE;
95
	}
96

97
	*data_size = min(*data_size, max_size - hdr_size);
98

99
	skb = skb_realloc(hdr_size + *data_size, *out_skb);
100
	if (skb == NULL) {
101
		return -ENOMEM;
102
	}
103

104
	skb->dev = dev;
105
	skb->nh.raw = skb->mac.raw + dev->hdr_len;
106
	skb->h.raw = skb->nh.raw + IP6_HEADER_SIZE;
107

108
	ip6_build(skb->nh.ip6h, *data_size, nexthdr, 64, src_ip6,
109
			&dst_ip6);
110

111
	*out_skb = skb;
112

113
	return 0;
114
}
115

116
static int ip6_snd(struct sk_buff *skb) {
117
	return ip6_xmit(skb);
118
}
119

120
static const struct net_pack_out_ops ip6_out_ops_struct = {
121
	.make_pack = &ip6_make,
122
	.snd_pack = &ip6_snd
123
};
124

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

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

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

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