15
#include <net/netdevice.h>
16
#include <net/inetdevice.h>
18
#include <net/l3/ipv4/ip.h>
19
#include <net/l4/udp.h>
20
#include <net/socket/inet_sock.h>
22
#include <net/l3/route.h>
23
#include <net/l0/net_tx.h>
24
#include <net/lib/bootp.h>
25
#include <net/l3/ipv4/ip_fragment.h>
26
#include <net/skbuff.h>
27
#include <net/l3/icmpv4.h>
29
#include <net/netfilter.h>
30
#include <kernel/printk.h>
31
#include <net/if_packet.h>
32
#include <net/l2/ethernet.h>
34
#include <embox/net/pack.h>
35
#include <net/lib/ipv4.h>
40
#include <kernel/printk.h>
46
static const struct net_pack_out_ops ip_out_ops_struct;
47
const struct net_pack_out_ops *const ip_out_ops
50
static int ip_xmit(struct sk_buff *skb) {
53
struct net_header_info hdr_info;
56
assert(skb->nh.iph != NULL);
58
hdr_info.type = ETH_P_IP;
59
hdr_info.dst_hw = NULL;
60
hdr_info.src_hw = skb->dev->dev_addr;
63
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
64
if (ip_is_local_net_ns(skb->nh.iph->daddr, IP_LOCAL_BROADCAST,
67
if (ip_is_local(skb->nh.iph->daddr, IP_LOCAL_BROADCAST)) {
69
hdr_info.dst_p = NULL;
73
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
74
ret = rt_fib_route_ip_net_ns(skb->nh.iph->daddr, &daddr,
77
ret = rt_fib_route_ip(skb->nh.iph->daddr, &daddr);
80
DBG(printk("ip_xmit: unknown target for %s\n",
81
inet_ntoa(*(struct in_addr *)&daddr)));
86
hdr_info.dst_p = &daddr;
87
hdr_info.p_len = sizeof daddr;
90
return net_tx(skb, &hdr_info);
97
static int fragment_skb_and_send(struct sk_buff *skb, struct net_device *dev) {
99
struct sk_buff_head tx_buf;
100
struct sk_buff *s_tmp;
103
ret = ip_frag(skb, dev->mtu, &tx_buf);
110
while (NULL != (s_tmp = skb_queue_pop(&tx_buf))) {
112
ip_set_check_field(s_tmp->nh.iph);
113
ret = ip_xmit(s_tmp);
118
skb_queue_purge(&tx_buf);
123
int ip_forward(struct sk_buff *skb) {
124
iphdr_t *iph = ip_hdr(skb);
125
int optlen = IP_HEADER_SIZE(iph) - IP_MIN_HEADER_SIZE;
126
struct rt_entry *best_route;
128
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
129
best_route = rt_fib_get_best_net_ns(iph->daddr,
130
NULL, skb->dev->net_ns);
132
best_route = rt_fib_get_best(iph->daddr, NULL);
140
if ((pkt_type(skb) != PACKET_HOST) || ipv4_is_multicast(iph->daddr)) {
148
if (unlikely(optlen)) {
149
icmp_discard(skb, ICMP_PARAM_PROB, ICMP_PTR_ERROR,
150
(uint8_t)IP_MIN_HEADER_SIZE);
157
if (unlikely(iph->ttl <= 1)) {
158
icmp_discard(skb, ICMP_TIME_EXCEED, ICMP_TTL_EXCEED);
162
ip_set_check_field(iph);
166
icmp_discard(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
171
if (skb->dev == best_route->dev) {
172
struct sk_buff *s_new = skb_copy(skb);
174
if (best_route->rt_gateway == INADDR_ANY) {
175
in_addr_t daddr = iph->daddr;
176
icmp_discard(s_new, ICMP_REDIRECT,
177
ICMP_HOST_REDIRECT, &daddr);
180
icmp_discard(s_new, ICMP_REDIRECT,
181
ICMP_NET_REDIRECT, best_route->rt_gateway);
187
if (ip_route(skb, NULL, best_route) < 0) {
189
if (best_route->rt_gateway == INADDR_ANY) {
190
icmp_discard(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH);
192
icmp_discard(skb, ICMP_DEST_UNREACH, ICMP_NET_UNREACH);
198
if (skb->len > best_route->dev->mtu) {
199
if (!(iph->frag_off & htons(IP_DF))) {
201
return fragment_skb_and_send(skb, best_route->dev);
204
icmp_discard(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
205
(uint16_t)best_route->dev->mtu);
213
static in_addr_t ip_get_dest_addr(const struct inet_sock *in_sk,
214
const struct sockaddr *to,
215
struct sk_buff **out_skb) {
217
const struct sockaddr_in *to_in;
219
to_in = (const struct sockaddr_in *)to;
222
return to_in->sin_addr.s_addr;
223
} else if (in_sk != NULL) {
224
return in_sk->dst_in.sin_addr.s_addr;
226
return (*out_skb)->nh.iph->saddr;
230
static int ip_make(const struct sock *sk,
231
const struct sockaddr *to,
233
struct sk_buff **out_skb) {
235
size_t hdr_size, max_size;
237
struct net_device *dev;
238
const struct inet_sock *in_sk;
240
in_addr_t src_ip, dst_ip;
245
assert(sk || *out_skb);
248
assert((to == NULL) || (to->sa_family == AF_INET));
250
in_sk = to_const_inet_sock(sk);
252
dst_ip = ip_get_dest_addr(in_sk, to, out_skb);
254
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
255
net_namespace_p net_ns;
256
fill_net_ns_from_sk(net_ns, sk, out_skb);
257
ret = rt_fib_out_dev_net_ns(dst_ip, in_sk != NULL ? &in_sk->sk : NULL,
260
ret = rt_fib_out_dev(dst_ip, in_sk != NULL ? &in_sk->sk : NULL, &dev);
263
DBG(printk("ip_make: unknown device for %s\n",
264
inet_ntoa(*(struct in_addr *)&dst_ip)));
269
assert(inetdev_get_by_dev(dev) != NULL);
271
#if defined(NET_NAMESPACE_ENABLED) && (NET_NAMESPACE_ENABLED == 1)
272
ret = rt_fib_source_ip_net_ns(dst_ip, dev, &src_ip, dev->net_ns);
274
ret = rt_fib_source_ip(dst_ip, dev, &src_ip);
277
DBG(printk("ip_make: can't resolve source ip for %s\n",
278
inet_ntoa(*(struct in_addr *)&dst_ip)));
282
proto = in_sk != NULL ? in_sk->sk.opt.so_protocol
283
: (*out_skb)->nh.iph->proto;
286
ip_length = ip_header_size((struct sock *)sk);
288
ip_length = IP_MIN_HEADER_SIZE;
292
hdr_size = dev->hdr_len + ip_length;
293
max_size = min(dev->mtu, skb_max_size());
294
if (hdr_size > max_size) {
295
DBG(printk("ip_make: hdr_size %zu is too big (max %zu)\n",
296
hdr_size, max_size));
304
*data_size = min(*data_size, max_size - hdr_size);
307
skb = skb_realloc(hdr_size + *data_size, *out_skb);
309
DBG(printk("ip_make: can't realloc packet for size %zu\n",
310
hdr_size + *data_size));
315
skb->nh.raw = skb->mac.raw + dev->hdr_len;
316
skb->h.raw = skb->nh.raw + ip_length;
318
ip_build(skb->nh.iph, ip_length + *data_size,
319
64, proto, src_ip, dst_ip);
320
if (IP_MIN_HEADER_SIZE < ip_length) {
321
ip_header_make_secure((struct sock *)sk, skb);
329
static int ip_snd(struct sk_buff *skb) {
330
static uint16_t global_id = 1230;
334
if (0 != nf_test_skb(NF_CHAIN_OUTPUT, NF_TARGET_ACCEPT, skb)) {
335
DBG(printk("ip_snd: dropped by output netfilter\n"));
340
ip_set_id_field(skb->nh.iph, global_id++);
341
ip_set_check_field(skb->nh.iph);
343
if (skb->len > skb->dev->mtu) {
344
if (!(skb->nh.iph->frag_off & htons(IP_DF))) {
345
return fragment_skb_and_send(skb, skb->dev);
352
static const struct net_pack_out_ops ip_out_ops_struct = {
353
.make_pack = &ip_make,