1 /*
2 * Fundamental constants relating to IP Protocol
3 *
4 * Copyright (C) 2020, Broadcom.
5 *
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
11 *
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
19 *
20 *
21 * <<Broadcom-WL-IPTag/Dual:>>
22 */
23
24 #ifndef _bcmproto_h_
25 #define _bcmproto_h_
26
27 #ifndef _TYPEDEFS_H_
28 #include <typedefs.h>
29 #endif
30
31 #include "eapol.h"
32 #include "802.3.h"
33 #include "vlan.h"
34 #include "bcmtcp.h"
35 /* copy from igsc.h */
36 #define IGMP_HLEN 8
37
38 enum frame_l2_hdr {
39 FRAME_L2_SNAP_H = 1,
40 FRAME_L2_SNAPVLAN_H,
41 FRAME_L2_ETH_H,
42 FRAME_L2_ETHVLAN_H,
43 FRAME_L2_ERROR,
44 };
45
46 enum frame_l3_hdr {
47 FRAME_L3_IP_H = 4,
48 FRAME_L3_IP6_H = 6,
49 FRAME_L3_ARP_H,
50 FRAME_L3_8021X_EAPOLKEY_H,
51 FRAME_L3_ERROR,
52 };
53
54 enum frame_l4_hdr {
55 FRAME_L4_ICMP_H = 1,
56 FRAME_L4_IGMP_H = 2,
57 FRAME_L4_TCP_H = 6,
58 FRAME_L4_UDP_H = 17,
59 FRAME_L4_ICMP6_H = 58,
60 FRAME_L4_ERROR,
61 };
62
63 typedef struct {
64 uint8 *l2;
65 uint8 l2_t;
66 uint16 l2_len;
67 uint8 *l3;
68 uint8 l3_t;
69 uint16 l3_len;
70 uint8 *l4;
71 uint8 l4_t;
72 uint16 l4_len;
73 } frame_proto_t;
74
75 static const uint8 llc_snap_hdr[SNAP_HDR_LEN] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
76
77 /* Generic header parser function */
78 static INLINE int
hnd_frame_proto(uint8 * p,int plen,frame_proto_t * fp)79 hnd_frame_proto(uint8 *p, int plen, frame_proto_t *fp)
80 {
81 struct dot3_mac_llc_snap_header *sh = (struct dot3_mac_llc_snap_header *)p;
82 struct dot3_mac_llc_snapvlan_header *svh = (struct dot3_mac_llc_snapvlan_header *)p;
83 struct ether_header *eh = (struct ether_header *)p;
84 struct ethervlan_header *evh = (struct ethervlan_header *)p;
85 uint16 type;
86 uint16 len;
87
88 if (p == NULL || plen <= 0) {
89 return BCME_ERROR;
90 }
91
92 if (plen < (int)sizeof(*eh)) {
93 return BCME_BUFTOOSHORT;
94 }
95 type = ntoh16(eh->ether_type);
96
97 bzero(fp, sizeof(frame_proto_t));
98
99 /* L2 header/pointer check */
100 fp->l2 = p;
101 fp->l2_len = (uint16)plen;
102 if (type < ETHER_TYPE_MIN) {
103 if (plen < (int)sizeof(*sh)) {
104 return BCME_BUFTOOSHORT;
105 }
106 if (bcmp(&sh->dsap, llc_snap_hdr, SNAP_HDR_LEN) == 0) {
107 type = ntoh16(sh->type);
108 if (type == ETHER_TYPE_8021Q) {
109 fp->l2_t = FRAME_L2_SNAPVLAN_H;
110 p += sizeof(struct dot3_mac_llc_snap_header);
111 if ((plen -= sizeof(struct dot3_mac_llc_snap_header)) <= 0) {
112 return BCME_ERROR;
113 }
114 }
115 else {
116 fp->l2_t = FRAME_L2_SNAP_H;
117 type = ntoh16(svh->ether_type);
118 p += sizeof(struct dot3_mac_llc_snapvlan_header);
119 if ((plen -= sizeof(struct dot3_mac_llc_snapvlan_header)) <= 0) {
120 return BCME_ERROR;
121 }
122 }
123 }
124 else {
125 return BCME_ERROR;
126 }
127 }
128 else {
129 if (type == ETHER_TYPE_8021Q) {
130 fp->l2_t = FRAME_L2_ETHVLAN_H;
131 type = ntoh16(evh->ether_type);
132 p += ETHERVLAN_HDR_LEN;
133 if ((plen -= ETHERVLAN_HDR_LEN) <= 0) {
134 return BCME_ERROR;
135 }
136 }
137 else {
138 fp->l2_t = FRAME_L2_ETH_H;
139 p += ETHER_HDR_LEN;
140 if ((plen -= ETHER_HDR_LEN) <= 0) {
141 return BCME_ERROR;
142 }
143 }
144 }
145 /* L3 header/pointer check */
146 fp->l3 = p;
147 fp->l3_len = (uint16)plen;
148 switch (type) {
149 case ETHER_TYPE_ARP: {
150 if ((plen -= ARP_DATA_LEN) < 0) {
151 return BCME_ERROR;
152 }
153
154 fp->l3_t = FRAME_L3_ARP_H;
155 /* no layer 4 protocol, return */
156 return BCME_OK;
157 break;
158 }
159 case ETHER_TYPE_IP: {
160 struct ipv4_hdr *iph = (struct ipv4_hdr *)p;
161 len = IPV4_HLEN(iph);
162
163 if ((plen -= len) <= 0) {
164 return BCME_ERROR;
165 }
166
167 if (IP_VER(iph) == IP_VER_4 && len >= IPV4_MIN_HEADER_LEN) {
168 fp->l3_t = FRAME_L3_IP_H;
169 type = IPV4_PROT(iph);
170 p += len;
171 }
172 else {
173 /* not a valid ipv4 packet */
174 return BCME_ERROR;
175 }
176 break;
177 }
178 case ETHER_TYPE_IPV6: {
179 struct ipv6_hdr *ip6h = (struct ipv6_hdr *)p;
180
181 if ((plen -= IPV6_MIN_HLEN) <= 0) {
182 return BCME_ERROR;
183 }
184
185 if (IP_VER(ip6h) == IP_VER_6) {
186 fp->l3_t = FRAME_L3_IP6_H;
187 type = IPV6_PROT(ip6h);
188 p += IPV6_MIN_HLEN;
189 if (IPV6_EXTHDR(type)) {
190 uint8 proto = 0;
191 int32 exth_len = ipv6_exthdr_len_check(p, plen, &proto);
192 if (exth_len < 0 || ((plen -= exth_len) <= 0))
193 return BCME_ERROR;
194 type = proto;
195 p += exth_len;
196 }
197 }
198 else {
199 /* not a valid ipv6 packet */
200 return BCME_ERROR;
201 }
202 break;
203 }
204 case ETHER_TYPE_802_1X: {
205 eapol_hdr_t *eapolh = (eapol_hdr_t *)p;
206
207 if ((plen -= EAPOL_HDR_LEN) <= 0) {
208 return BCME_ERROR;
209 }
210
211 if (eapolh->type == EAPOL_KEY) {
212 fp->l3_t = FRAME_L3_8021X_EAPOLKEY_H;
213 return BCME_OK;
214 }
215 else {
216 /* not a valid ipv6 packet */
217 return BCME_ERROR;
218 }
219
220 break;
221 }
222 default:
223 /* not interesting case */
224 return BCME_ERROR;
225 break;
226 }
227
228 /* L4 header/pointer check */
229 fp->l4 = p;
230 fp->l4_len = (uint16)plen;
231 switch (type) {
232 case IP_PROT_ICMP:
233 fp->l4_t = FRAME_L4_ICMP_H;
234 if ((plen -= sizeof(struct bcmicmp_hdr)) < 0) {
235 return BCME_ERROR;
236 }
237 break;
238 case IP_PROT_IGMP:
239 fp->l4_t = FRAME_L4_IGMP_H;
240 if ((plen -= IGMP_HLEN) < 0) {
241 return BCME_ERROR;
242 }
243 break;
244 case IP_PROT_TCP:
245 fp->l4_t = FRAME_L4_TCP_H;
246 if ((plen -= sizeof(struct bcmtcp_hdr)) < 0) {
247 return BCME_ERROR;
248 }
249 break;
250 case IP_PROT_UDP:
251 fp->l4_t = FRAME_L4_UDP_H;
252 if ((plen -= sizeof(struct bcmudp_hdr)) < 0) {
253 return BCME_ERROR;
254 }
255 break;
256 case IP_PROT_ICMP6:
257 fp->l4_t = FRAME_L4_ICMP6_H;
258 if ((plen -= sizeof(struct icmp6_hdr)) < 0) {
259 return BCME_ERROR;
260 }
261 break;
262 default:
263 break;
264 }
265
266 return BCME_OK;
267 }
268
269 #define SNAP_HDR_LEN 6 /* 802.3 LLC/SNAP header length */
270
271 #define FRAME_DROP 0
272 #define FRAME_NOP 1
273 #define FRAME_TAKEN 2
274
275 #endif /* _bcmproto_h_ */
276