765819ab01bcd8ea5700518c8c78d0e6eb228b1a
[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 NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey *key,
32                             POVS_PACKET_HDR_INFO layers);
33
34 static __inline ULONG
35 OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB)
36 {
37     INT length = 0;
38     NET_BUFFER *nb;
39
40     nb = NET_BUFFER_LIST_FIRST_NB(_pNB);
41     ASSERT(nb);
42     while(nb) {
43         length += NET_BUFFER_DATA_LENGTH(nb);
44         nb = NET_BUFFER_NEXT_NB(nb);
45     }
46
47     return length;
48 }
49
50 /*
51  * Returns the ctl field from the TCP header in 'packet', or 0 if the field
52  * can't be read.  The caller must have ensured that 'packet' contains a TCP
53  * header.
54  *
55  * We can't just use TCPHdr, from netProto.h, for this because that
56  * breaks the flags down into individual bit-fields.  We can't even use
57  * offsetof because that will try to take the address of a bit-field,
58  * which C does not allow.
59  */
60 static UINT16
61 OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN
62              const POVS_PACKET_HDR_INFO layers) // IN
63 {
64 #define TCP_CTL_OFS 12                // Offset of "ctl" field in TCP header.
65 #define TCP_FLAGS(CTL) ((CTL) & 0x3f) // Obtain TCP flags from CTL.
66
67     const UINT16 *ctl;
68     UINT16 storage;
69
70     ctl = OvsGetPacketBytes(packet, sizeof *ctl, layers->l4Offset + TCP_CTL_OFS,
71                          &storage);
72     return ctl ? *ctl : 0;
73 }
74
75
76 static UINT8
77 OvsGetTcpFlags(const NET_BUFFER_LIST *packet,    // IN
78                const POVS_PACKET_HDR_INFO layers) // IN
79 {
80     if (layers->isTcp) {
81         return TCP_FLAGS(OvsGetTcpCtl(packet, layers));
82     } else {
83         return 0;
84     }
85 }
86
87 static const EtherArp *
88 OvsGetArp(const NET_BUFFER_LIST *packet,
89           UINT32 ofs,
90           EtherArp *storage)
91 {
92     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
93 }
94
95 static const IPHdr *
96 OvsGetIp(const NET_BUFFER_LIST *packet,
97          UINT32 ofs,
98          IPHdr *storage)
99 {
100     const IPHdr *ip = OvsGetPacketBytes(packet, sizeof *ip, ofs, storage);
101     if (ip) {
102         int ipLen = ip->ihl * 4;
103         if (ipLen >= sizeof *ip && OvsPacketLenNBL(packet) >= ofs + ipLen) {
104             return ip;
105         }
106     }
107     return NULL;
108 }
109
110 static const TCPHdr *
111 OvsGetTcp(const NET_BUFFER_LIST *packet,
112           UINT32 ofs,
113           TCPHdr *storage)
114 {
115     const TCPHdr *tcp = OvsGetPacketBytes(packet, sizeof *tcp, ofs, storage);
116     if (tcp) {
117         int tcpLen = tcp->doff * 4;
118         if (tcpLen >= sizeof *tcp && OvsPacketLenNBL(packet) >= ofs + tcpLen) {
119             return tcp;
120         }
121     }
122     return NULL;
123 }
124
125 static const UDPHdr *
126 OvsGetUdp(const NET_BUFFER_LIST *packet,
127           UINT32 ofs,
128           UDPHdr *storage)
129 {
130     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
131 }
132
133 static const ICMPHdr *
134 OvsGetIcmp(const NET_BUFFER_LIST *packet,
135            UINT32 ofs,
136            ICMPHdr *storage)
137 {
138     return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage);
139 }
140
141 #endif /* __PACKET_PARSER_H_ */