1 #define __MOS_CORE_
2
3 #include <string.h>
4 #include <netinet/ip.h>
5 #include <stdbool.h>
6
7 #include "ip_in.h"
8 #include "ip_out.h"
9 #include "tcp.h"
10 #include "mtcp_api.h"
11 #include "debug.h"
12 #include "mos_api.h"
13 #include "icmp.h"
14 #include "config.h"
15
16 #define ETH_P_IP_FRAG 0xF800
17 #define ETH_P_IPV6_FRAG 0xF6DD
18
19
20 /*----------------------------------------------------------------------------*/
21 inline void
FillInPacketIPContext(struct pkt_ctx * pctx,struct iphdr * iph,int ip_len)22 FillInPacketIPContext (struct pkt_ctx *pctx, struct iphdr *iph, int ip_len)
23 {
24 pctx->p.iph = iph;
25 pctx->p.ip_len = ip_len;
26
27 return;
28 }
29 /*----------------------------------------------------------------------------*/
30 inline int
ProcessInIPv4Packet(mtcp_manager_t mtcp,struct pkt_ctx * pctx)31 ProcessInIPv4Packet(mtcp_manager_t mtcp, struct pkt_ctx *pctx)
32 {
33 bool release = false;
34 int ret;
35 struct mon_listener *walk;
36 /* check and process IPv4 packets */
37 struct iphdr* iph =
38 (struct iphdr *)((char *)pctx->p.ethh + sizeof(struct ethhdr));
39 int ip_len = ntohs(iph->tot_len);
40
41 /* drop the packet shorter than ip header */
42 if (ip_len < sizeof(struct iphdr)) {
43 ret = ERROR;
44 goto __return;
45 }
46
47 if (iph->version != IPVERSION ) {
48 release = true;
49 ret = FALSE;
50 goto __return;
51 }
52
53 FillInPacketIPContext(pctx, iph, ip_len);
54
55 /* callback for monitor raw socket */
56 TAILQ_FOREACH(walk, &mtcp->monitors, link)
57 if (walk->socket->socktype == MOS_SOCK_MONITOR_RAW) {
58 if (ISSET_BPFFILTER(walk->raw_pkt_fcode) &&
59 EVAL_BPFFILTER(walk->raw_pkt_fcode, (uint8_t *)pctx->p.ethh,
60 pctx->p.eth_len))
61 HandleCallback(mtcp, MOS_NULL, walk->socket, MOS_SIDE_BOTH,
62 pctx, MOS_ON_PKT_IN);
63 }
64
65 /* if there is no MOS_SOCK_STREAM or MOS_SOCK_MONITOR_STREAM socket,
66 forward IP packet before reaching upper (transport) layer */
67 if (mtcp->num_msp == 0 && mtcp->num_esp == 0) {
68 if (pctx->forward) {
69 ForwardIPPacket(mtcp, pctx);
70 }
71 return TRUE;
72 }
73
74 if (ip_fast_csum(iph, iph->ihl)) {
75 ret = ERROR;
76 goto __return;
77 }
78
79 switch (iph->protocol) {
80 case IPPROTO_TCP:
81 return ProcessInTCPPacket(mtcp, pctx);
82 case IPPROTO_ICMP:
83 if (ProcessICMPPacket(mtcp, pctx))
84 return TRUE;
85 default:
86 /* forward other protocols without any processing */
87 if (!mtcp->num_msp || !pctx->forward)
88 release = true;
89 else
90 ForwardIPPacket(mtcp, pctx);
91
92 ret = FALSE;
93 goto __return;
94 }
95
96 __return:
97 if (release && mtcp->iom->release_pkt)
98 mtcp->iom->release_pkt(mtcp->ctx, pctx->p.in_ifidx,
99 (unsigned char *)pctx->p.ethh, pctx->p.eth_len);
100 return ret;
101 }
102 /*----------------------------------------------------------------------------*/
103