• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2022 Huawei Device Co., Ltd.
4  *
5  * Description: This file implements the function
6  * of decapsulating the NewIP protocol header.
7  *
8  * Author: Yang Yanjun <yangyanjun@huawei.com>
9  *
10  * Data: 2022-07-18
11  */
12 #include "nip_hdr.h"
13 
14 /* Must carry the current field */
_get_nip_hdr_bitmap(struct nip_buff * nbuf,unsigned char bitmap[],unsigned char bitmap_index_max)15 static int _get_nip_hdr_bitmap(struct nip_buff *nbuf,
16 			       unsigned char bitmap[],
17 			       unsigned char bitmap_index_max)
18 {
19 	int i = 0;
20 
21 	if (nbuf->remaining_len < sizeof(unsigned char))
22 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
23 
24 	if (*nbuf->data & NIP_BITMAP_INVALID_SET)
25 		return -NIP_HDR_BITMAP_INVALID;
26 
27 	do {
28 		if (i >= bitmap_index_max)
29 			return -NIP_HDR_BITMAP_NUM_OUT_RANGE;
30 
31 		if (nbuf->remaining_len < sizeof(unsigned char))
32 			return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
33 
34 		bitmap[i] = *nbuf->data;
35 		nip_buff_pull(nbuf, sizeof(unsigned char));
36 	} while (bitmap[i++] & NIP_BITMAP_HAVE_MORE_BIT);
37 
38 	return i;
39 }
40 
41 /* Must carry the current field */
_get_nip_hdr_ttl(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)42 static int _get_nip_hdr_ttl(struct nip_buff *nbuf,
43 			    unsigned char bitmap,
44 			    struct nip_hdr_decap *niph)
45 {
46 	if (!(bitmap & NIP_BITMAP_INCLUDE_TTL))
47 		return -NIP_HDR_NO_TTL;
48 
49 	if (nbuf->remaining_len < sizeof(niph->ttl))
50 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
51 
52 	niph->ttl = *nbuf->data;
53 	niph->include_ttl = 1;
54 	nip_buff_pull(nbuf, sizeof(niph->ttl));
55 
56 	return 0;
57 }
58 
59 /* Optional fields */
60 /* Communication between devices of the same version may not carry packet Header length,
61  * but communication between devices of different versions must carry packet header length
62  */
_get_nip_hdr_len(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)63 static int _get_nip_hdr_len(struct nip_buff *nbuf,
64 			    unsigned char bitmap,
65 			    struct nip_hdr_decap *niph)
66 {
67 	if (!(bitmap & NIP_BITMAP_INCLUDE_HDR_LEN))
68 		return 0;
69 
70 	if (nbuf->remaining_len < sizeof(niph->hdr_len))
71 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
72 
73 	/* Total_len is a network sequence and cannot be
74 	 * compared directly with the local sequence
75 	 */
76 	niph->hdr_len = *nbuf->data;
77 	niph->include_hdr_len = 1;
78 	nip_buff_pull(nbuf, sizeof(niph->hdr_len));
79 
80 	if (niph->include_total_len && niph->hdr_len >= niph->rcv_buf_len)
81 		return -NIP_HDR_LEN_OUT_RANGE;
82 
83 	return 0;
84 }
85 
86 /* Must carry the current field */
_get_nip_hdr_nexthdr(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)87 static int _get_nip_hdr_nexthdr(struct nip_buff *nbuf,
88 				unsigned char bitmap,
89 				struct nip_hdr_decap *niph)
90 {
91 	if (!(bitmap & NIP_BITMAP_INCLUDE_NEXT_HDR))
92 		return -NIP_HDR_NO_NEXT_HDR;
93 
94 	if (nbuf->remaining_len < sizeof(niph->nexthdr))
95 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
96 
97 	niph->nexthdr = *nbuf->data;
98 	niph->include_nexthdr = 1;
99 	nip_buff_pull(nbuf, sizeof(niph->nexthdr));
100 
101 	return 0;
102 }
103 
104 /* Must carry the current field */
105 /* Note: niph->saddr is network order.(big end) */
_get_nip_hdr_daddr(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)106 static int _get_nip_hdr_daddr(struct nip_buff *nbuf,
107 			      unsigned char bitmap,
108 			      struct nip_hdr_decap *niph)
109 {
110 	unsigned char *p;
111 
112 	if (!(bitmap & NIP_BITMAP_INCLUDE_DADDR))
113 		return -NIP_HDR_NO_DADDR;
114 
115 	p = decode_nip_addr(nbuf, &niph->daddr);
116 	if (!p)
117 		return -NIP_HDR_DECAP_DADDR_ERR;
118 
119 	if (nip_addr_invalid(&niph->daddr))
120 		return -NIP_HDR_DADDR_INVALID;
121 
122 	niph->include_daddr = 1;
123 	return 0;
124 }
125 
126 /* Optional fields */
127 /* Note: niph->daddr is network order.(big end) */
_get_nip_hdr_saddr(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)128 static int _get_nip_hdr_saddr(struct nip_buff *nbuf,
129 			      unsigned char bitmap,
130 			      struct nip_hdr_decap *niph)
131 {
132 	unsigned char *p;
133 
134 	if (!(bitmap & NIP_BITMAP_INCLUDE_SADDR))
135 		return 0;
136 
137 	p = decode_nip_addr(nbuf, &niph->saddr);
138 	if (!p)
139 		return -NIP_HDR_DECAP_SADDR_ERR;
140 
141 	if (nip_addr_invalid(&niph->saddr))
142 		return -NIP_HDR_SADDR_INVALID;
143 
144 	niph->include_saddr = 1;
145 	return 0;
146 }
147 
148 /* Optional fields: tcp/arp need, udp needless */
149 /* Note: niph->total_len is network order.(big end), need change to host order */
_get_nip_total_len(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)150 static int _get_nip_total_len(struct nip_buff *nbuf,
151 			      unsigned char bitmap,
152 			      struct nip_hdr_decap *niph)
153 {
154 	if (!(bitmap & NIP_BITMAP_INCLUDE_TOTAL_LEN))
155 		return 0;
156 
157 	if (nbuf->remaining_len < sizeof(niph->total_len))
158 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
159 
160 	/* Total_len is a network sequence and cannot be
161 	 * compared directly with the local sequence
162 	 */
163 	niph->total_len = *((unsigned short *)nbuf->data);
164 	niph->include_total_len = 1;
165 	nip_buff_pull(nbuf, sizeof(niph->total_len));
166 
167 	return 0;
168 }
169 
_nip_hdr_bitmap0_parse(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)170 static int _nip_hdr_bitmap0_parse(struct nip_buff *nbuf,
171 				  unsigned char bitmap,
172 				  struct nip_hdr_decap *niph)
173 {
174 	int err;
175 
176 	err = _get_nip_hdr_ttl(nbuf, bitmap, niph);
177 	if (err < 0)
178 		return err;
179 
180 	/* Optional fields */
181 	err = _get_nip_total_len(nbuf, bitmap, niph);
182 	if (err < 0)
183 		return err;
184 
185 	err = _get_nip_hdr_nexthdr(nbuf, bitmap, niph);
186 	if (err < 0)
187 		return err;
188 
189 	err = _get_nip_hdr_daddr(nbuf, bitmap, niph);
190 	if (err < 0)
191 		return err;
192 
193 	err = _get_nip_hdr_saddr(nbuf, bitmap, niph);
194 	if (err < 0)
195 		return err;
196 
197 	return 0;
198 }
199 
_nip_hdr_bitmap1_parse(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)200 static int _nip_hdr_bitmap1_parse(struct nip_buff *nbuf,
201 				  unsigned char bitmap,
202 				  struct nip_hdr_decap *niph)
203 {
204 	int err;
205 
206 	/* If add new field needs to be modified with the macro definition */
207 	if (bitmap & NIP_INVALID_BITMAP_2)
208 		niph->include_unknown_bit = 1;
209 
210 	/* Optional fields */
211 	err = _get_nip_hdr_len(nbuf, bitmap, niph);
212 	if (err < 0)
213 		return err;
214 
215 	return 0;
216 }
217 
_nip_hdr_unknown_bit_check(struct nip_buff * nbuf,unsigned char bitmap,struct nip_hdr_decap * niph)218 static int _nip_hdr_unknown_bit_check(struct nip_buff *nbuf,
219 				      unsigned char bitmap,
220 				      struct nip_hdr_decap *niph)
221 {
222 	niph->include_unknown_bit = 1;
223 	return 0;
224 }
225 
226 #define FACTORY_NUM_MAX 3
227 static int (*hdr_parse_factory[FACTORY_NUM_MAX])(struct nip_buff *,
228 						 unsigned char,
229 						 struct nip_hdr_decap *) = {
230 	_nip_hdr_bitmap0_parse,
231 	_nip_hdr_bitmap1_parse,
232 	_nip_hdr_unknown_bit_check,
233 };
234 
nip_hdr_check(struct nip_hdr_decap * niph)235 static int nip_hdr_check(struct nip_hdr_decap *niph)
236 {
237 	if (niph->include_unknown_bit && !niph->include_hdr_len)
238 		/* different ver pkt but no hdr len */
239 		return -NIP_HDR_UNKNOWN_AND_NO_HDR_LEN;
240 
241 	if (niph->include_hdr_len) {
242 		if (niph->hdr_len == 0 ||
243 		    niph->hdr_len < niph->hdr_real_len)
244 			return -NIP_HDR_LEN_INVALID;
245 	}
246 
247 	return 0;
248 }
249 
250 /* Note:
251  * 1.niph->total_len is network order.(big end), need change to host order
252  * 2.niph->saddr/daddr is network order.(big end)
253  */
nip_hdr_parse(unsigned char * rcv_buf,unsigned int buf_len,struct nip_hdr_decap * niph)254 int nip_hdr_parse(unsigned char *rcv_buf, unsigned int buf_len, struct nip_hdr_decap *niph)
255 {
256 	int i = 0;
257 	int ret;
258 	unsigned char bitmap[BITMAP_MAX] = {0};
259 	int num;
260 	struct nip_buff nbuf;
261 
262 	nbuf.data = rcv_buf;
263 	if (!nbuf.data)
264 		return 0;
265 
266 	nbuf.remaining_len = buf_len;
267 	num = _get_nip_hdr_bitmap(&nbuf, bitmap, BITMAP_MAX);
268 	if (num <= 0)
269 		return num;
270 
271 	niph->rcv_buf_len = buf_len;
272 	while (i < num) {
273 		int err;
274 
275 		if (i >= FACTORY_NUM_MAX)
276 			break;
277 
278 		err = hdr_parse_factory[i](&nbuf, bitmap[i], niph);
279 		if (err < 0)
280 			return err;
281 
282 		i++;
283 	}
284 
285 	if (buf_len < nbuf.remaining_len)
286 		return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
287 
288 	niph->hdr_real_len = (unsigned char)(buf_len - nbuf.remaining_len);
289 	ret = nip_hdr_check(niph);
290 	if (ret < 0)
291 		return ret;
292 
293 	return niph->hdr_len > niph->hdr_real_len ?
294 	       niph->hdr_len : niph->hdr_real_len;
295 }
296 
297