xref: /OK3568_Linux_fs/app/forlinx/quectelCM/libmnl/attr.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * (C) 2008-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  */
9 #include <limits.h>	/* for INT_MAX */
10 #include <string.h>
11 #include <errno.h>
12 
13 #include "libmnl.h"
14 
15 /**
16  * \defgroup attr Netlink attribute helpers
17  *
18  * Netlink Type-Length-Value (TLV) attribute:
19  * \verbatim
20 	|<-- 2 bytes -->|<-- 2 bytes -->|<-- variable -->|
21 	-------------------------------------------------
22 	|     length    |      type     |      value     |
23 	-------------------------------------------------
24 	|<--------- header ------------>|<-- payload --->|
25 \endverbatim
26  * The payload of the Netlink message contains sequences of attributes that are
27  * expressed in TLV format.
28  *
29  * @{
30  */
31 
32 /**
33  * mnl_attr_get_type - get type of netlink attribute
34  * \param attr pointer to netlink attribute
35  *
36  * This function returns the attribute type.
37  */
mnl_attr_get_type(const struct nlattr * attr)38 uint16_t mnl_attr_get_type(const struct nlattr *attr)
39 {
40 	return attr->nla_type & NLA_TYPE_MASK;
41 }
42 
43 /**
44  * mnl_attr_get_len - get length of netlink attribute
45  * \param attr pointer to netlink attribute
46  *
47  * This function returns the attribute length that is the attribute header
48  * plus the attribute payload.
49  */
mnl_attr_get_len(const struct nlattr * attr)50 uint16_t mnl_attr_get_len(const struct nlattr *attr)
51 {
52 	return attr->nla_len;
53 }
54 
55 /**
56  * mnl_attr_get_payload_len - get the attribute payload-value length
57  * \param attr pointer to netlink attribute
58  *
59  * This function returns the attribute payload-value length.
60  */
mnl_attr_get_payload_len(const struct nlattr * attr)61 uint16_t mnl_attr_get_payload_len(const struct nlattr *attr)
62 {
63 	return attr->nla_len - MNL_ATTR_HDRLEN;
64 }
65 
66 /**
67  * mnl_attr_get_payload - get pointer to the attribute payload
68  * \param attr pointer to netlink attribute
69  *
70  * This function return a pointer to the attribute payload.
71  */
mnl_attr_get_payload(const struct nlattr * attr)72 void *mnl_attr_get_payload(const struct nlattr *attr)
73 {
74 	return (void *)attr + MNL_ATTR_HDRLEN;
75 }
76 
77 /**
78  * mnl_attr_ok - check if there is room for an attribute in a buffer
79  * \param attr attribute that we want to check if there is room for
80  * \param len remaining bytes in a buffer that contains the attribute
81  *
82  * This function is used to check that a buffer, which is supposed to contain
83  * an attribute, has enough room for the attribute that it stores, i.e. this
84  * function can be used to verify that an attribute is neither malformed nor
85  * truncated.
86  *
87  * This function does not set errno in case of error since it is intended
88  * for iterations. Thus, it returns true on success and false on error.
89  *
90  * The len parameter may be negative in the case of malformed messages during
91  * attribute iteration, that is why we use a signed integer.
92  */
mnl_attr_ok(const struct nlattr * attr,int len)93 bool mnl_attr_ok(const struct nlattr *attr, int len)
94 {
95 	return len >= (int)sizeof(struct nlattr) &&
96 	       attr->nla_len >= sizeof(struct nlattr) &&
97 	       (int)attr->nla_len <= len;
98 }
99 
100 /**
101  * mnl_attr_next - get the next attribute in the payload of a netlink message
102  * \param attr pointer to the current attribute
103  *
104  * This function returns a pointer to the next attribute after the one passed
105  * as parameter. You have to use mnl_attr_ok() to ensure that the next
106  * attribute is valid.
107  */
mnl_attr_next(const struct nlattr * attr)108 struct nlattr *mnl_attr_next(const struct nlattr *attr)
109 {
110 	return (struct nlattr *)((void *)attr + MNL_ALIGN(attr->nla_len));
111 }
112 
113 /**
114  * mnl_attr_type_valid - check if the attribute type is valid
115  * \param attr pointer to attribute to be checked
116  * \param max maximum attribute type
117  *
118  * This function allows to check if the attribute type is higher than the
119  * maximum supported type. If the attribute type is invalid, this function
120  * returns -1 and errno is explicitly set. On success, this function returns 1.
121  *
122  * Strict attribute checking in user-space is not a good idea since you may
123  * run an old application with a newer kernel that supports new attributes.
124  * This leads to backward compatibility breakages in user-space. Better check
125  * if you support an attribute, if not, skip it.
126  */
mnl_attr_type_valid(const struct nlattr * attr,uint16_t max)127 int mnl_attr_type_valid(const struct nlattr *attr, uint16_t max)
128 {
129 	if (mnl_attr_get_type(attr) > max) {
130 		errno = EOPNOTSUPP;
131 		return -1;
132 	}
133 	return 1;
134 }
135 
__mnl_attr_validate(const struct nlattr * attr,enum mnl_attr_data_type type,size_t exp_len)136 static int __mnl_attr_validate(const struct nlattr *attr,
137 			       enum mnl_attr_data_type type, size_t exp_len)
138 {
139 	uint16_t attr_len = mnl_attr_get_payload_len(attr);
140 	const char *attr_data = mnl_attr_get_payload(attr);
141 
142 	if (attr_len < exp_len) {
143 		errno = ERANGE;
144 		return -1;
145 	}
146 	switch(type) {
147 	case MNL_TYPE_FLAG:
148 		if (attr_len > 0) {
149 			errno = ERANGE;
150 			return -1;
151 		}
152 		break;
153 	case MNL_TYPE_NUL_STRING:
154 		if (attr_len == 0) {
155 			errno = ERANGE;
156 			return -1;
157 		}
158 		if (attr_data[attr_len-1] != '\0') {
159 			errno = EINVAL;
160 			return -1;
161 		}
162 		break;
163 	case MNL_TYPE_STRING:
164 		if (attr_len == 0) {
165 			errno = ERANGE;
166 			return -1;
167 		}
168 		break;
169 	case MNL_TYPE_NESTED:
170 		/* empty nested attributes are OK. */
171 		if (attr_len == 0)
172 			break;
173 		/* if not empty, they must contain one header, eg. flag */
174 		if (attr_len < MNL_ATTR_HDRLEN) {
175 			errno = ERANGE;
176 			return -1;
177 		}
178 		break;
179 	default:
180 		/* make gcc happy. */
181 		break;
182 	}
183 	if (exp_len && attr_len > exp_len) {
184 		errno = ERANGE;
185 		return -1;
186 	}
187 	return 0;
188 }
189 
190 static const size_t mnl_attr_data_type_len[MNL_TYPE_MAX] = {
191 	[MNL_TYPE_U8]		= sizeof(uint8_t),
192 	[MNL_TYPE_U16]		= sizeof(uint16_t),
193 	[MNL_TYPE_U32]		= sizeof(uint32_t),
194 	[MNL_TYPE_U64]		= sizeof(uint64_t),
195 	[MNL_TYPE_MSECS]	= sizeof(uint64_t),
196 };
197 
198 /**
199  * mnl_attr_validate - validate netlink attribute (simplified version)
200  * \param attr pointer to netlink attribute that we want to validate
201  * \param type data type (see enum mnl_attr_data_type)
202  *
203  * The validation is based on the data type. Specifically, it checks that
204  * integers (u8, u16, u32 and u64) have enough room for them. This function
205  * returns -1 in case of error, and errno is explicitly set.
206  */
mnl_attr_validate(const struct nlattr * attr,enum mnl_attr_data_type type)207 int mnl_attr_validate(const struct nlattr *attr, enum mnl_attr_data_type type)
208 {
209 	int exp_len;
210 
211 	if (type >= MNL_TYPE_MAX) {
212 		errno = EINVAL;
213 		return -1;
214 	}
215 	exp_len = mnl_attr_data_type_len[type];
216 	return __mnl_attr_validate(attr, type, exp_len);
217 }
218 
219 /**
220  * mnl_attr_validate2 - validate netlink attribute (extended version)
221  * \param attr pointer to netlink attribute that we want to validate
222  * \param type attribute type (see enum mnl_attr_data_type)
223  * \param exp_len expected attribute data size
224  *
225  * This function allows to perform a more accurate validation for attributes
226  * whose size is variable. If the size of the attribute is not what we expect,
227  * this functions returns -1 and errno is explicitly set.
228  */
mnl_attr_validate2(const struct nlattr * attr,enum mnl_attr_data_type type,size_t exp_len)229 int mnl_attr_validate2(const struct nlattr *attr,
230 				     enum mnl_attr_data_type type,
231 				     size_t exp_len)
232 {
233 	if (type >= MNL_TYPE_MAX) {
234 		errno = EINVAL;
235 		return -1;
236 	}
237 	return __mnl_attr_validate(attr, type, exp_len);
238 }
239 
240 /**
241  * mnl_attr_parse - parse attributes
242  * \param nlh pointer to netlink message
243  * \param offset offset to start parsing from (if payload is after any header)
244  * \param cb callback function that is called for each attribute
245  * \param data pointer to data that is passed to the callback function
246  *
247  * This function allows to iterate over the sequence of attributes that compose
248  * the Netlink message. You can then put the attribute in an array as it
249  * usually happens at this stage or you can use any other data structure (such
250  * as lists or trees).
251  *
252  * This function propagates the return value of the callback, which can be
253  * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
254  */
mnl_attr_parse(const struct nlmsghdr * nlh,unsigned int offset,mnl_attr_cb_t cb,void * data)255 int mnl_attr_parse(const struct nlmsghdr *nlh,
256 				 unsigned int offset, mnl_attr_cb_t cb,
257 				 void *data)
258 {
259 	int ret = MNL_CB_OK;
260 	const struct nlattr *attr;
261 
262 	mnl_attr_for_each(attr, nlh, offset)
263 		if ((ret = cb(attr, data)) <= MNL_CB_STOP)
264 			return ret;
265 	return ret;
266 }
267 
268 /**
269  * mnl_attr_parse_nested - parse attributes inside a nest
270  * \param nested pointer to netlink attribute that contains a nest
271  * \param cb callback function that is called for each attribute in the nest
272  * \param data pointer to data passed to the callback function
273  *
274  * This function allows to iterate over the sequence of attributes that compose
275  * the Netlink message. You can then put the attribute in an array as it
276  * usually happens at this stage or you can use any other data structure (such
277  * as lists or trees).
278  *
279  * This function propagates the return value of the callback, which can be
280  * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
281  */
mnl_attr_parse_nested(const struct nlattr * nested,mnl_attr_cb_t cb,void * data)282 int mnl_attr_parse_nested(const struct nlattr *nested,
283 					mnl_attr_cb_t cb, void *data)
284 {
285 	int ret = MNL_CB_OK;
286 	const struct nlattr *attr;
287 
288 	mnl_attr_for_each_nested(attr, nested)
289 		if ((ret = cb(attr, data)) <= MNL_CB_STOP)
290 			return ret;
291 	return ret;
292 }
293 
294 /**
295  * mnl_attr_parse_payload - parse attributes in payload of Netlink message
296  * \param payload pointer to payload of the Netlink message
297  * \param payload_len payload length that contains the attributes
298  * \param cb callback function that is called for each attribute
299  * \param data pointer to data that is passed to the callback function
300  *
301  * This function takes a pointer to the area that contains the attributes,
302  * commonly known as the payload of the Netlink message. Thus, you have to
303  * pass a pointer to the Netlink message payload, instead of the entire
304  * message.
305  *
306  * This function allows you to iterate over the sequence of attributes that are
307  * located at some payload offset. You can then put the attributes in one array
308  * as usual, or you can use any other data structure (such as lists or trees).
309  *
310  * This function propagates the return value of the callback, which can be
311  * MNL_CB_ERROR, MNL_CB_OK or MNL_CB_STOP.
312  */
mnl_attr_parse_payload(const void * payload,size_t payload_len,mnl_attr_cb_t cb,void * data)313 int mnl_attr_parse_payload(const void *payload,
314 					 size_t payload_len,
315 					 mnl_attr_cb_t cb, void *data)
316 {
317 	int ret = MNL_CB_OK;
318 	const struct nlattr *attr;
319 
320 	mnl_attr_for_each_payload(payload, payload_len)
321 		if ((ret = cb(attr, data)) <= MNL_CB_STOP)
322 			return ret;
323 	return ret;
324 }
325 
326 /**
327  * mnl_attr_get_u8 - returns 8-bit unsigned integer attribute payload
328  * \param attr pointer to netlink attribute
329  *
330  * This function returns the 8-bit value of the attribute payload.
331  */
mnl_attr_get_u8(const struct nlattr * attr)332 uint8_t mnl_attr_get_u8(const struct nlattr *attr)
333 {
334 	return *((uint8_t *)mnl_attr_get_payload(attr));
335 }
336 
337 /**
338  * mnl_attr_get_u16 - returns 16-bit unsigned integer attribute payload
339  * \param attr pointer to netlink attribute
340  *
341  * This function returns the 16-bit value of the attribute payload.
342  */
mnl_attr_get_u16(const struct nlattr * attr)343 uint16_t mnl_attr_get_u16(const struct nlattr *attr)
344 {
345 	return *((uint16_t *)mnl_attr_get_payload(attr));
346 }
347 
348 /**
349  * mnl_attr_get_u32 - returns 32-bit unsigned integer attribute payload
350  * \param attr pointer to netlink attribute
351  *
352  * This function returns the 32-bit value of the attribute payload.
353  */
mnl_attr_get_u32(const struct nlattr * attr)354 uint32_t mnl_attr_get_u32(const struct nlattr *attr)
355 {
356 	return *((uint32_t *)mnl_attr_get_payload(attr));
357 }
358 
359 /**
360  * mnl_attr_get_u64 - returns 64-bit unsigned integer attribute.
361  * \param attr pointer to netlink attribute
362  *
363  * This function returns the 64-bit value of the attribute payload. This
364  * function is align-safe, since accessing 64-bit Netlink attributes is a
365  * common source of alignment issues.
366  */
mnl_attr_get_u64(const struct nlattr * attr)367 uint64_t mnl_attr_get_u64(const struct nlattr *attr)
368 {
369 	uint64_t tmp;
370 	memcpy(&tmp, mnl_attr_get_payload(attr), sizeof(tmp));
371 	return tmp;
372 }
373 
374 /**
375  * mnl_attr_get_str - returns pointer to string attribute.
376  * \param attr pointer to netlink attribute
377  *
378  * This function returns the payload of string attribute value.
379  */
mnl_attr_get_str(const struct nlattr * attr)380 const char *mnl_attr_get_str(const struct nlattr *attr)
381 {
382 	return mnl_attr_get_payload(attr);
383 }
384 
385 /**
386  * mnl_attr_put - add an attribute to netlink message
387  * \param nlh pointer to the netlink message
388  * \param type netlink attribute type that you want to add
389  * \param len netlink attribute payload length
390  * \param data pointer to the data that will be stored by the new attribute
391  *
392  * This function updates the length field of the Netlink message (nlmsg_len)
393  * by adding the size (header + payload) of the new attribute.
394  */
mnl_attr_put(struct nlmsghdr * nlh,uint16_t type,size_t len,const void * data)395 void mnl_attr_put(struct nlmsghdr *nlh, uint16_t type,
396 				size_t len, const void *data)
397 {
398 	struct nlattr *attr = mnl_nlmsg_get_payload_tail(nlh);
399 	uint16_t payload_len = MNL_ALIGN(sizeof(struct nlattr)) + len;
400 	int pad;
401 
402 	attr->nla_type = type;
403 	attr->nla_len = payload_len;
404 	memcpy(mnl_attr_get_payload(attr), data, len);
405 	pad = MNL_ALIGN(len) - len;
406 	if (pad > 0)
407 		memset(mnl_attr_get_payload(attr) + len, 0, pad);
408 
409 	nlh->nlmsg_len += MNL_ALIGN(payload_len);
410 }
411 
412 /**
413  * mnl_attr_put_u8 - add 8-bit unsigned integer attribute to netlink message
414  * \param nlh pointer to the netlink message
415  * \param type netlink attribute type
416  * \param data 8-bit unsigned integer data that is stored by the new attribute
417  *
418  * This function updates the length field of the Netlink message (nlmsg_len)
419  * by adding the size (header + payload) of the new attribute.
420  */
mnl_attr_put_u8(struct nlmsghdr * nlh,uint16_t type,uint8_t data)421 void mnl_attr_put_u8(struct nlmsghdr *nlh, uint16_t type,
422 				   uint8_t data)
423 {
424 	mnl_attr_put(nlh, type, sizeof(uint8_t), &data);
425 }
426 
427 /**
428  * mnl_attr_put_u16 - add 16-bit unsigned integer attribute to netlink message
429  * \param nlh pointer to the netlink message
430  * \param type netlink attribute type
431  * \param data 16-bit unsigned integer data that is stored by the new attribute
432  *
433  * This function updates the length field of the Netlink message (nlmsg_len)
434  * by adding the size (header + payload) of the new attribute.
435  */
mnl_attr_put_u16(struct nlmsghdr * nlh,uint16_t type,uint16_t data)436 void mnl_attr_put_u16(struct nlmsghdr *nlh, uint16_t type,
437 				    uint16_t data)
438 {
439 	mnl_attr_put(nlh, type, sizeof(uint16_t), &data);
440 }
441 
442 /**
443  * mnl_attr_put_u32 - add 32-bit unsigned integer attribute to netlink message
444  * \param nlh pointer to the netlink message
445  * \param type netlink attribute type
446  * \param data 32-bit unsigned integer data that is stored by the new attribute
447  *
448  * This function updates the length field of the Netlink message (nlmsg_len)
449  * by adding the size (header + payload) of the new attribute.
450  */
mnl_attr_put_u32(struct nlmsghdr * nlh,uint16_t type,uint32_t data)451 void mnl_attr_put_u32(struct nlmsghdr *nlh, uint16_t type,
452 				    uint32_t data)
453 {
454 	mnl_attr_put(nlh, type, sizeof(uint32_t), &data);
455 }
456 
457 /**
458  * mnl_attr_put_u64 - add 64-bit unsigned integer attribute to netlink message
459  * \param nlh pointer to the netlink message
460  * \param type netlink attribute type
461  * \param data 64-bit unsigned integer data that is stored by the new attribute
462  *
463  * This function updates the length field of the Netlink message (nlmsg_len)
464  * by adding the size (header + payload) of the new attribute.
465  */
mnl_attr_put_u64(struct nlmsghdr * nlh,uint16_t type,uint64_t data)466 void mnl_attr_put_u64(struct nlmsghdr *nlh, uint16_t type,
467 				    uint64_t data)
468 {
469 	mnl_attr_put(nlh, type, sizeof(uint64_t), &data);
470 }
471 
472 /**
473  * mnl_attr_put_str - add string attribute to netlink message
474  * \param nlh  pointer to the netlink message
475  * \param type netlink attribute type
476  * \param data pointer to string data that is stored by the new attribute
477  *
478  * This function updates the length field of the Netlink message (nlmsg_len)
479  * by adding the size (header + payload) of the new attribute.
480  */
mnl_attr_put_str(struct nlmsghdr * nlh,uint16_t type,const char * data)481 void mnl_attr_put_str(struct nlmsghdr *nlh, uint16_t type,
482 				    const char *data)
483 {
484 	mnl_attr_put(nlh, type, strlen(data), data);
485 }
486 
487 /**
488  * mnl_attr_put_strz - add string attribute to netlink message
489  * \param nlh pointer to the netlink message
490  * \param type netlink attribute type
491  * \param data pointer to string data that is stored by the new attribute
492  *
493  * This function is similar to mnl_attr_put_str, but it includes the
494  * NUL/zero ('\0') terminator at the end of the string.
495  *
496  * This function updates the length field of the Netlink message (nlmsg_len)
497  * by adding the size (header + payload) of the new attribute.
498  */
mnl_attr_put_strz(struct nlmsghdr * nlh,uint16_t type,const char * data)499 void mnl_attr_put_strz(struct nlmsghdr *nlh, uint16_t type,
500 				     const char *data)
501 {
502 	mnl_attr_put(nlh, type, strlen(data)+1, data);
503 }
504 
505 /**
506  * mnl_attr_nest_start - start an attribute nest
507  * \param nlh pointer to the netlink message
508  * \param type netlink attribute type
509  *
510  * This function adds the attribute header that identifies the beginning of
511  * an attribute nest. This function always returns a valid pointer to the
512  * beginning of the nest.
513  */
mnl_attr_nest_start(struct nlmsghdr * nlh,uint16_t type)514 struct nlattr *mnl_attr_nest_start(struct nlmsghdr *nlh,
515 						 uint16_t type)
516 {
517 	struct nlattr *start = mnl_nlmsg_get_payload_tail(nlh);
518 
519 	/* set start->nla_len in mnl_attr_nest_end() */
520 	start->nla_type = NLA_F_NESTED | type;
521 	nlh->nlmsg_len += MNL_ALIGN(sizeof(struct nlattr));
522 
523 	return start;
524 }
525 
526 /**
527  * mnl_attr_put_check - add an attribute to netlink message
528  * \param nlh pointer to the netlink message
529  * \param buflen size of buffer which stores the message
530  * \param type netlink attribute type that you want to add
531  * \param len netlink attribute payload length
532  * \param data pointer to the data that will be stored by the new attribute
533  *
534  * This function first checks that the data can be added to the message
535  * (fits into the buffer) and then updates the length field of the Netlink
536  * message (nlmsg_len) by adding the size (header + payload) of the new
537  * attribute. The function returns true if the attribute could be added
538  * to the message, otherwise false is returned.
539  */
mnl_attr_put_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,size_t len,const void * data)540 bool mnl_attr_put_check(struct nlmsghdr *nlh, size_t buflen,
541 				      uint16_t type, size_t len,
542 				      const void *data)
543 {
544 	if (nlh->nlmsg_len + MNL_ATTR_HDRLEN + MNL_ALIGN(len) > buflen)
545 		return false;
546 	mnl_attr_put(nlh, type, len, data);
547 	return true;
548 }
549 
550 /**
551  * mnl_attr_put_u8_check - add 8-bit unsigned int attribute to netlink message
552  * \param nlh pointer to the netlink message
553  * \param buflen size of buffer which stores the message
554  * \param type netlink attribute type
555  * \param data 8-bit unsigned integer data that is stored by the new attribute
556  *
557  * This function first checks that the data can be added to the message
558  * (fits into the buffer) and then updates the length field of the Netlink
559  * message (nlmsg_len) by adding the size (header + payload) of the new
560  * attribute. The function returns true if the attribute could be added
561  * to the message, otherwise false is returned.
562  */
mnl_attr_put_u8_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint8_t data)563 bool mnl_attr_put_u8_check(struct nlmsghdr *nlh, size_t buflen,
564 					 uint16_t type, uint8_t data)
565 {
566 	return mnl_attr_put_check(nlh, buflen, type, sizeof(uint8_t), &data);
567 }
568 
569 /**
570  * mnl_attr_put_u16_check - add 16-bit unsigned int attribute to netlink message
571  * \param nlh pointer to the netlink message
572  * \param buflen size of buffer which stores the message
573  * \param type netlink attribute type
574  * \param data 16-bit unsigned integer data that is stored by the new attribute
575  *
576  * This function first checks that the data can be added to the message
577  * (fits into the buffer) and then updates the length field of the Netlink
578  * message (nlmsg_len) by adding the size (header + payload) of the new
579  * attribute. The function returns true if the attribute could be added
580  * to the message, otherwise false is returned.
581  * This function updates the length field of the Netlink message (nlmsg_len)
582  * by adding the size (header + payload) of the new attribute.
583  */
mnl_attr_put_u16_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint16_t data)584 bool mnl_attr_put_u16_check(struct nlmsghdr *nlh, size_t buflen,
585 					  uint16_t type, uint16_t data)
586 {
587 	return mnl_attr_put_check(nlh, buflen, type, sizeof(uint16_t), &data);
588 }
589 
590 /**
591  * mnl_attr_put_u32_check - add 32-bit unsigned int attribute to netlink message
592  * \param nlh pointer to the netlink message
593  * \param buflen size of buffer which stores the message
594  * \param type netlink attribute type
595  * \param data 32-bit unsigned integer data that is stored by the new attribute
596  *
597  * This function first checks that the data can be added to the message
598  * (fits into the buffer) and then updates the length field of the Netlink
599  * message (nlmsg_len) by adding the size (header + payload) of the new
600  * attribute. The function returns true if the attribute could be added
601  * to the message, otherwise false is returned.
602  * This function updates the length field of the Netlink message (nlmsg_len)
603  * by adding the size (header + payload) of the new attribute.
604  */
mnl_attr_put_u32_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint32_t data)605 bool mnl_attr_put_u32_check(struct nlmsghdr *nlh, size_t buflen,
606 					  uint16_t type, uint32_t data)
607 {
608 	return mnl_attr_put_check(nlh, buflen, type, sizeof(uint32_t), &data);
609 }
610 
611 /**
612  * mnl_attr_put_u64_check - add 64-bit unsigned int attribute to netlink message
613  * \param nlh pointer to the netlink message
614  * \param buflen size of buffer which stores the message
615  * \param type netlink attribute type
616  * \param data 64-bit unsigned integer data that is stored by the new attribute
617  *
618  * This function first checks that the data can be added to the message
619  * (fits into the buffer) and then updates the length field of the Netlink
620  * message (nlmsg_len) by adding the size (header + payload) of the new
621  * attribute. The function returns true if the attribute could be added
622  * to the message, otherwise false is returned.
623  * This function updates the length field of the Netlink message (nlmsg_len)
624  * by adding the size (header + payload) of the new attribute.
625  */
mnl_attr_put_u64_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,uint64_t data)626 bool mnl_attr_put_u64_check(struct nlmsghdr *nlh, size_t buflen,
627 					  uint16_t type, uint64_t data)
628 {
629 	return mnl_attr_put_check(nlh, buflen, type, sizeof(uint64_t), &data);
630 }
631 
632 /**
633  * mnl_attr_put_str_check - add string attribute to netlink message
634  * \param nlh  pointer to the netlink message
635  * \param buflen size of buffer which stores the message
636  * \param type netlink attribute type
637  * \param data pointer to string data that is stored by the new attribute
638  *
639  * This function first checks that the data can be added to the message
640  * (fits into the buffer) and then updates the length field of the Netlink
641  * message (nlmsg_len) by adding the size (header + payload) of the new
642  * attribute. The function returns true if the attribute could be added
643  * to the message, otherwise false is returned.
644  * This function updates the length field of the Netlink message (nlmsg_len)
645  * by adding the size (header + payload) of the new attribute.
646  */
mnl_attr_put_str_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)647 bool mnl_attr_put_str_check(struct nlmsghdr *nlh, size_t buflen,
648 					  uint16_t type, const char *data)
649 {
650 	return mnl_attr_put_check(nlh, buflen, type, strlen(data), data);
651 }
652 
653 /**
654  * mnl_attr_put_strz_check - add string attribute to netlink message
655  * \param nlh pointer to the netlink message
656  * \param buflen size of buffer which stores the message
657  * \param type netlink attribute type
658  * \param data pointer to string data that is stored by the new attribute
659  *
660  * This function is similar to mnl_attr_put_str, but it includes the
661  * NUL/zero ('\0') terminator at the end of the string.
662  *
663  * This function first checks that the data can be added to the message
664  * (fits into the buffer) and then updates the length field of the Netlink
665  * message (nlmsg_len) by adding the size (header + payload) of the new
666  * attribute. The function returns true if the attribute could be added
667  * to the message, otherwise false is returned.
668  */
mnl_attr_put_strz_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type,const char * data)669 bool mnl_attr_put_strz_check(struct nlmsghdr *nlh, size_t buflen,
670 					   uint16_t type, const char *data)
671 {
672 	return mnl_attr_put_check(nlh, buflen, type, strlen(data)+1, data);
673 }
674 
675 /**
676  * mnl_attr_nest_start_check - start an attribute nest
677  * \param buflen size of buffer which stores the message
678  * \param nlh pointer to the netlink message
679  * \param type netlink attribute type
680  *
681  * This function adds the attribute header that identifies the beginning of
682  * an attribute nest. If the nested attribute cannot be added then NULL,
683  * otherwise valid pointer to the beginning of the nest is returned.
684  */
mnl_attr_nest_start_check(struct nlmsghdr * nlh,size_t buflen,uint16_t type)685 struct nlattr *mnl_attr_nest_start_check(struct nlmsghdr *nlh,
686 						       size_t buflen,
687 						       uint16_t type)
688 {
689 	if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > buflen)
690 		return NULL;
691 	return mnl_attr_nest_start(nlh, type);
692 }
693 
694 /**
695  * mnl_attr_nest_end - end an attribute nest
696  * \param nlh pointer to the netlink message
697  * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
698  *
699  * This function updates the attribute header that identifies the nest.
700  */
mnl_attr_nest_end(struct nlmsghdr * nlh,struct nlattr * start)701 void mnl_attr_nest_end(struct nlmsghdr *nlh,
702 				     struct nlattr *start)
703 {
704 	start->nla_len = mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
705 }
706 
707 /**
708  * mnl_attr_nest_cancel - cancel an attribute nest
709  * \param nlh pointer to the netlink message
710  * \param start pointer to the attribute nest returned by mnl_attr_nest_start()
711  *
712  * This function updates the attribute header that identifies the nest.
713  */
mnl_attr_nest_cancel(struct nlmsghdr * nlh,struct nlattr * start)714 void mnl_attr_nest_cancel(struct nlmsghdr *nlh,
715 					struct nlattr *start)
716 {
717 	nlh->nlmsg_len -= mnl_nlmsg_get_payload_tail(nlh) - (void *)start;
718 }
719 
720 /**
721  * @}
722  */
723