7b8e656ed3c0a6617d09d13bbdedeb0ad95dceff
[cascardo/ovs.git] / datapath-windows / ovsext / PacketParser.h
1 /*
2  * Copyright (c) 2014 VMware, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __PACKET_PARSER_H_
18 #define __PACKET_PARSER_H_ 1
19
20 #include "precomp.h"
21 #include "NetProto.h"
22
23 const VOID* OvsGetPacketBytes(const NET_BUFFER_LIST *_pNB, UINT32 len,
24                               UINT32 SrcOffset, VOID *storage);
25 NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, OvsFlowKey *key,
26                         POVS_PACKET_HDR_INFO layers);
27 VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow,
28                  POVS_PACKET_HDR_INFO layers);
29 VOID OvsParseUdp(const NET_BUFFER_LIST *packet, L4Key *flow,
30                  POVS_PACKET_HDR_INFO layers);
31 VOID OvsParseSctp(const NET_BUFFER_LIST *packet, L4Key *flow,
32                   POVS_PACKET_HDR_INFO layers);
33 NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey *key,
34                             POVS_PACKET_HDR_INFO layers);
35
36 static __inline ULONG
37 OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB)
38 {
39     INT length = 0;
40     NET_BUFFER *nb;
41
42     nb = NET_BUFFER_LIST_FIRST_NB(_pNB);
43     ASSERT(nb);
44     while(nb) {
45         length += NET_BUFFER_DATA_LENGTH(nb);
46         nb = NET_BUFFER_NEXT_NB(nb);
47     }
48
49     return length;
50 }
51
52 /*
53  * Returns the ctl field from the TCP header in 'packet', or 0 if the field
54  * can't be read.  The caller must have ensured that 'packet' contains a TCP
55  * header.
56  *
57  * We can't just use TCPHdr, from netProto.h, for this because that
58  * breaks the flags down into individual bit-fields.  We can't even use
59  * offsetof because that will try to take the address of a bit-field,
60  * which C does not allow.
61  */
62 static UINT16
63 OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN
64              const POVS_PACKET_HDR_INFO layers) // IN
65 {
66 #define TCP_CTL_OFS 12                // Offset of "ctl" field in TCP header.
67 #define TCP_FLAGS(CTL) ((CTL) & 0x3f) // Obtain TCP flags from CTL.
68
69     const UINT16 *ctl;
70     UINT16 storage;
71
72     ctl = OvsGetPacketBytes(packet, sizeof *ctl, layers->l4Offset + TCP_CTL_OFS,
73                          &storage);
74     return ctl ? *ctl : 0;
75 }
76
77
78 static UINT8
79 OvsGetTcpFlags(const NET_BUFFER_LIST *packet,    // IN
80                const OvsFlowKey *key,   // IN
81                const POVS_PACKET_HDR_INFO layers) // IN
82 {
83     UNREFERENCED_PARAMETER(key); // should be removed later
84
85     if (layers->isTcp) {
86         return TCP_FLAGS(OvsGetTcpCtl(packet, layers));
87     } else {
88         return 0;
89     }
90 }
91
92 static const EtherArp *
93 OvsGetArp(const NET_BUFFER_LIST *packet,
94           UINT32 ofs,
95           EtherArp *storage)
96 {
97     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
98 }
99
100 static const IPHdr *
101 OvsGetIp(const NET_BUFFER_LIST *packet,
102          UINT32 ofs,
103          IPHdr *storage)
104 {
105     const IPHdr *ip = OvsGetPacketBytes(packet, sizeof *ip, ofs, storage);
106     if (ip) {
107         int ipLen = ip->ihl * 4;
108         if (ipLen >= sizeof *ip && OvsPacketLenNBL(packet) >= ofs + ipLen) {
109             return ip;
110         }
111     }
112     return NULL;
113 }
114
115 static const TCPHdr *
116 OvsGetTcp(const NET_BUFFER_LIST *packet,
117           UINT32 ofs,
118           TCPHdr *storage)
119 {
120     const TCPHdr *tcp = OvsGetPacketBytes(packet, sizeof *tcp, ofs, storage);
121     if (tcp) {
122         int tcpLen = tcp->doff * 4;
123         if (tcpLen >= sizeof *tcp && OvsPacketLenNBL(packet) >= ofs + tcpLen) {
124             return tcp;
125         }
126     }
127     return NULL;
128 }
129
130 static const UDPHdr *
131 OvsGetUdp(const NET_BUFFER_LIST *packet,
132           UINT32 ofs,
133           UDPHdr *storage)
134 {
135     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
136 }
137
138 static const SCTPHdr *
139 OvsGetSctp(const NET_BUFFER_LIST *packet,
140            UINT32 ofs,
141            SCTPHdr *storage)
142 {
143     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
144 }
145
146 static const ICMPHdr *
147 OvsGetIcmp(const NET_BUFFER_LIST *packet,
148            UINT32 ofs,
149            ICMPHdr *storage)
150 {
151     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
152 }
153
154 #endif /* __PACKET_PARSER_H_ */