xref: /OK3568_Linux_fs/app/forlinx/quectelCM/libmnl/callback.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * (C) 2008-2010 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 
10 #include <errno.h>
11 
12 #include "libmnl.h"
13 
mnl_cb_noop(const struct nlmsghdr * nlh,void * data)14 static int mnl_cb_noop(const struct nlmsghdr *nlh, void *data)
15 {
16 	(void)nlh;
17 	(void)data;
18 	return MNL_CB_OK;
19 }
20 
mnl_cb_error(const struct nlmsghdr * nlh,void * data)21 static int mnl_cb_error(const struct nlmsghdr *nlh, void *data)
22 {
23 	const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
24 	(void)data;
25 	if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr))) {
26 		errno = EBADMSG;
27 		return MNL_CB_ERROR;
28 	}
29 	/* Netlink subsystems returns the errno value with different signess */
30 	if (err->error < 0)
31 		errno = -err->error;
32 	else
33 		errno = err->error;
34 
35 	return err->error == 0 ? MNL_CB_STOP : MNL_CB_ERROR;
36 }
37 
mnl_cb_stop(const struct nlmsghdr * nlh,void * data)38 static int mnl_cb_stop(const struct nlmsghdr *nlh, void *data)
39 {
40 	(void)nlh;
41 	(void)data;
42 	return MNL_CB_STOP;
43 }
44 
45 static const mnl_cb_t default_cb_array[NLMSG_MIN_TYPE] = {
46 	[NLMSG_NOOP]	= mnl_cb_noop,
47 	[NLMSG_ERROR]	= mnl_cb_error,
48 	[NLMSG_DONE]	= mnl_cb_stop,
49 	[NLMSG_OVERRUN]	= mnl_cb_noop,
50 };
51 
__mnl_cb_run(const void * buf,size_t numbytes,unsigned int seq,unsigned int portid,mnl_cb_t cb_data,void * data,const mnl_cb_t * cb_ctl_array,unsigned int cb_ctl_array_len)52 static inline int __mnl_cb_run(const void *buf, size_t numbytes,
53 			       unsigned int seq, unsigned int portid,
54 			       mnl_cb_t cb_data, void *data,
55 			       const mnl_cb_t *cb_ctl_array,
56 			       unsigned int cb_ctl_array_len)
57 {
58 	int ret = MNL_CB_OK, len = numbytes;
59 	const struct nlmsghdr *nlh = buf;
60 
61 	while (mnl_nlmsg_ok(nlh, len)) {
62 		/* check message source */
63 		if (!mnl_nlmsg_portid_ok(nlh, portid)) {
64 			errno = ESRCH;
65 			return -1;
66 		}
67 		/* perform sequence tracking */
68 		if (!mnl_nlmsg_seq_ok(nlh, seq)) {
69 			errno = EPROTO;
70 			return -1;
71 		}
72 
73 		/* dump was interrupted */
74 		if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
75 			errno = EINTR;
76 			return -1;
77 		}
78 
79 		/* netlink data message handling */
80 		if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) {
81 			if (cb_data){
82 				ret = cb_data(nlh, data);
83 				if (ret <= MNL_CB_STOP)
84 					goto out;
85 			}
86 		} else if (nlh->nlmsg_type < cb_ctl_array_len) {
87 			if (cb_ctl_array && cb_ctl_array[nlh->nlmsg_type]) {
88 				ret = cb_ctl_array[nlh->nlmsg_type](nlh, data);
89 				if (ret <= MNL_CB_STOP)
90 					goto out;
91 			}
92 		} else if (default_cb_array[nlh->nlmsg_type]) {
93 			ret = default_cb_array[nlh->nlmsg_type](nlh, data);
94 			if (ret <= MNL_CB_STOP)
95 				goto out;
96 		}
97 		nlh = mnl_nlmsg_next(nlh, &len);
98 	}
99 out:
100 	return ret;
101 }
102 
103 /**
104  * \defgroup callback Callback helpers
105  * @{
106  */
107 
108 /**
109  * mnl_cb_run2 - callback runqueue for netlink messages
110  * \param buf buffer that contains the netlink messages
111  * \param numbytes number of bytes stored in the buffer
112  * \param seq sequence number that we expect to receive
113  * \param portid Netlink PortID that we expect to receive
114  * \param cb_data callback handler for data messages
115  * \param data pointer to data that will be passed to the data callback handler
116  * \param cb_ctl_array array of custom callback handlers from control messages
117  * \param cb_ctl_array_len array length of custom control callback handlers
118  *
119  * You can set the cb_ctl_array to NULL if you want to use the default control
120  * callback handlers, in that case, the parameter cb_ctl_array_len is not
121  * checked.
122  *
123  * Your callback may return three possible values:
124  * 	- MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
125  * 	- MNL_CB_STOP (=0): stop callback runqueue.
126  * 	- MNL_CB_OK (>=1): no problem has occurred.
127  *
128  * This function propagates the callback return value. On error, it returns
129  * -1 and errno is explicitly set. If the portID is not the expected, errno
130  * is set to ESRCH. If the sequence number is not the expected, errno is set
131  * to EPROTO. If the dump was interrupted, errno is set to EINTR and you should
132  * request a new fresh dump again.
133  */
mnl_cb_run2(const void * buf,size_t numbytes,unsigned int seq,unsigned int portid,mnl_cb_t cb_data,void * data,const mnl_cb_t * cb_ctl_array,unsigned int cb_ctl_array_len)134 int mnl_cb_run2(const void *buf, size_t numbytes,
135 			      unsigned int seq, unsigned int portid,
136 			      mnl_cb_t cb_data, void *data,
137 			      const mnl_cb_t *cb_ctl_array,
138 			      unsigned int cb_ctl_array_len)
139 {
140 	return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data,
141 			    cb_ctl_array, cb_ctl_array_len);
142 }
143 
144 /**
145  * mnl_cb_run - callback runqueue for netlink messages (simplified version)
146  * \param buf buffer that contains the netlink messages
147  * \param numbytes number of bytes stored in the buffer
148  * \param seq sequence number that we expect to receive
149  * \param portid Netlink PortID that we expect to receive
150  * \param cb_data callback handler for data messages
151  * \param data pointer to data that will be passed to the data callback handler
152  *
153  * This function is like mnl_cb_run2() but it does not allow you to set
154  * the control callback handlers.
155  *
156  * Your callback may return three possible values:
157  * 	- MNL_CB_ERROR (<=-1): an error has occurred. Stop callback runqueue.
158  * 	- MNL_CB_STOP (=0): stop callback runqueue.
159  * 	- MNL_CB_OK (>=1): no problems has occurred.
160  *
161  * This function propagates the callback return value.
162  */
mnl_cb_run(const void * buf,size_t numbytes,unsigned int seq,unsigned int portid,mnl_cb_t cb_data,void * data)163 int mnl_cb_run(const void *buf, size_t numbytes, unsigned int seq,
164 			     unsigned int portid, mnl_cb_t cb_data, void *data)
165 {
166 	return __mnl_cb_run(buf, numbytes, seq, portid, cb_data, data, NULL, 0);
167 }
168 
169 /**
170  * @}
171  */
172