hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/***
 *
 *  ipv4/ip_input.c - process incoming IP packets
 *
 *  Copyright (C) 2002      Ulrich Marx <marx@kammer.uni-hannover.de>
 *                2003-2005 Jan Kiszka <jan.kiszka@web.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */
 
#include <net/checksum.h>
#include <net/ip.h>
 
#include <rtskb.h>
#include <rtnet_socket.h>
#include <stack_mgr.h>
#include <ipv4/ip_fragment.h>
#include <ipv4/protocol.h>
#include <ipv4/route.h>
 
#if IS_ENABLED(CONFIG_XENO_DRIVERS_NET_ADDON_PROXY)
#include <ipv4/ip_input.h>
 
rt_ip_fallback_handler_t rt_ip_fallback_handler = NULL;
EXPORT_SYMBOL_GPL(rt_ip_fallback_handler);
#endif /* CONFIG_XENO_DRIVERS_NET_ADDON_PROXY */
 
/***
 *  rt_ip_local_deliver
 */
static inline void rt_ip_local_deliver(struct rtskb *skb)
{
   struct iphdr *iph = skb->nh.iph;
   unsigned short protocol = iph->protocol;
   struct rtinet_protocol *ipprot;
   struct rtsocket *sock;
   int err;
 
   ipprot = rt_inet_protocols[rt_inet_hashkey(protocol)];
 
   /* Check if we are supporting the protocol */
   if ((ipprot != NULL) && (ipprot->protocol == protocol)) {
       __rtskb_pull(skb, iph->ihl * 4);
 
       /* Point into the IP datagram, just past the header. */
       skb->h.raw = skb->data;
 
       /* Reassemble IP fragments */
       if (iph->frag_off & htons(IP_MF | IP_OFFSET)) {
           skb = rt_ip_defrag(skb, ipprot);
           if (!skb)
               return;
 
           sock = skb->sk;
       } else {
           /* Get the destination socket */
           if ((sock = ipprot->dest_socket(skb)) == NULL) {
#if IS_ENABLED(CONFIG_XENO_DRIVERS_NET_ADDON_PROXY)
               if (rt_ip_fallback_handler) {
                   __rtskb_push(skb, iph->ihl * 4);
                   rt_ip_fallback_handler(skb);
                   return;
               }
#endif
               kfree_rtskb(skb);
               return;
           }
 
           /* Acquire the rtskb, to unlock the device skb pool */
           err = rtskb_acquire(skb, &sock->skb_pool);
 
           if (err) {
               kfree_rtskb(skb);
               rt_socket_dereference(sock);
               return;
           }
       }
 
       /* Deliver the packet to the next layer */
       ipprot->rcv_handler(skb);
 
       /* Packet is queued, socket can be released */
       rt_socket_dereference(sock);
#if IS_ENABLED(CONFIG_XENO_DRIVERS_NET_ADDON_PROXY)
   } else if (rt_ip_fallback_handler) {
       /* If a fallback handler for IP protocol has been installed,
         * call it. */
       rt_ip_fallback_handler(skb);
#endif /* CONFIG_XENO_DRIVERS_NET_ADDON_PROXY */
   } else {
       if (IS_ENABLED(CONFIG_XENO_DRIVERS_NET_RTIPV4_DEBUG))
           rtdm_printk("RTnet: no protocol found\n");
       kfree_rtskb(skb);
   }
}
 
/***
 *  rt_ip_rcv
 */
int rt_ip_rcv(struct rtskb *skb, struct rtpacket_type *pt)
{
   struct iphdr *iph;
   __u32 len;
 
   /* When the interface is in promisc. mode, drop all the crap
     * that it receives, do not try to analyse it.
     */
   if (skb->pkt_type == PACKET_OTHERHOST)
       goto drop;
 
   iph = skb->nh.iph;
 
   /*
     *  RFC1122: 3.1.2.2 MUST silently discard any IP frame that fails the checksum.
     *
     *  Is the datagram acceptable?
     *
     *  1.  Length at least the size of an ip header
     *  2.  Version of 4
     *  3.  Checksums correctly. [Speed optimisation for later, skip loopback checksums]
     *  4.  Doesn't have a bogus length
     */
   if (iph->ihl < 5 || iph->version != 4)
       goto drop;
 
   if (ip_fast_csum((u8 *)iph, iph->ihl) != 0)
       goto drop;
 
   len = ntohs(iph->tot_len);
   if ((skb->len < len) || (len < ((__u32)iph->ihl << 2)))
       goto drop;
 
   rtskb_trim(skb, len);
 
#ifdef CONFIG_XENO_DRIVERS_NET_RTIPV4_ROUTER
   if (rt_ip_route_forward(skb, iph->daddr))
       return 0;
#endif /* CONFIG_XENO_DRIVERS_NET_RTIPV4_ROUTER */
 
   rt_ip_local_deliver(skb);
   return 0;
 
drop:
   kfree_rtskb(skb);
   return 0;
}