xref: /OK3568_Linux_fs/external/rkwifibt/drivers/bcmdhd/include/bcmproto.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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