xref: /linux/tools/net/ynl/lib/ynl.c (revision 85502b2214d50ba0ddf2a5fb454e4d28a160d175)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 #include <errno.h>
3 #include <poll.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <unistd.h>
8 #include <linux/types.h>
9 #include <linux/genetlink.h>
10 #include <sys/socket.h>
11 
12 #include "ynl.h"
13 
14 #define ARRAY_SIZE(arr)		(sizeof(arr) / sizeof(*arr))
15 
16 #define __yerr_msg(yse, _msg...)					\
17 	({								\
18 		struct ynl_error *_yse = (yse);				\
19 									\
20 		if (_yse) {						\
21 			snprintf(_yse->msg, sizeof(_yse->msg) - 1,  _msg); \
22 			_yse->msg[sizeof(_yse->msg) - 1] = 0;		\
23 		}							\
24 	})
25 
26 #define __yerr_code(yse, _code...)		\
27 	({					\
28 		struct ynl_error *_yse = (yse);	\
29 						\
30 		if (_yse) {			\
31 			_yse->code = _code;	\
32 		}				\
33 	})
34 
35 #define __yerr(yse, _code, _msg...)		\
36 	({					\
37 		__yerr_msg(yse, _msg);		\
38 		__yerr_code(yse, _code);	\
39 	})
40 
41 #define __perr(yse, _msg)		__yerr(yse, errno, _msg)
42 
43 #define yerr_msg(_ys, _msg...)		__yerr_msg(&(_ys)->err, _msg)
44 #define yerr(_ys, _code, _msg...)	__yerr(&(_ys)->err, _code, _msg)
45 #define perr(_ys, _msg)			__yerr(&(_ys)->err, errno, _msg)
46 
47 /* -- Netlink boiler plate */
48 static bool
ynl_err_walk_is_sel(const struct ynl_policy_nest * policy,const struct nlattr * attr)49 ynl_err_walk_is_sel(const struct ynl_policy_nest *policy,
50 		    const struct nlattr *attr)
51 {
52 	unsigned int type = ynl_attr_type(attr);
53 
54 	return policy && type <= policy->max_attr &&
55 		policy->table[type].is_selector;
56 }
57 
58 static const struct ynl_policy_nest *
ynl_err_walk_sel_policy(const struct ynl_policy_attr * policy_attr,const struct nlattr * selector)59 ynl_err_walk_sel_policy(const struct ynl_policy_attr *policy_attr,
60 			const struct nlattr *selector)
61 {
62 	const struct ynl_policy_nest *policy = policy_attr->nest;
63 	const char *sel;
64 	unsigned int i;
65 
66 	if (!policy_attr->is_submsg)
67 		return policy;
68 
69 	sel = ynl_attr_get_str(selector);
70 	for (i = 0; i <= policy->max_attr; i++) {
71 		if (!strcmp(sel, policy->table[i].name))
72 			return policy->table[i].nest;
73 	}
74 
75 	return NULL;
76 }
77 
78 static int
ynl_err_walk_report_one(const struct ynl_policy_nest * policy,const struct nlattr * selector,unsigned int type,char * str,int str_sz,int * n)79 ynl_err_walk_report_one(const struct ynl_policy_nest *policy,
80 			const struct nlattr *selector, unsigned int type,
81 			char *str, int str_sz, int *n)
82 {
83 	if (!policy) {
84 		if (*n < str_sz)
85 			*n += snprintf(str, str_sz, "!policy");
86 		return 1;
87 	}
88 
89 	if (type > policy->max_attr) {
90 		if (*n < str_sz)
91 			*n += snprintf(str, str_sz, "!oob");
92 		return 1;
93 	}
94 
95 	if (!policy->table[type].name) {
96 		if (*n < str_sz)
97 			*n += snprintf(str, str_sz, "!name");
98 		return 1;
99 	}
100 
101 	if (*n < str_sz) {
102 		int sz;
103 
104 		sz = snprintf(str, str_sz - *n,
105 			      ".%s", policy->table[type].name);
106 		*n += sz;
107 		str += sz;
108 	}
109 
110 	if (policy->table[type].is_submsg) {
111 		if (!selector) {
112 			if (*n < str_sz)
113 				*n += snprintf(str, str_sz, "(!selector)");
114 			return 1;
115 		}
116 
117 		if (ynl_attr_type(selector) !=
118 		    policy->table[type].selector_type) {
119 			if (*n < str_sz)
120 				*n += snprintf(str, str_sz, "(!=selector)");
121 			return 1;
122 		}
123 
124 		if (*n < str_sz)
125 			*n += snprintf(str, str_sz - *n, "(%s)",
126 				       ynl_attr_get_str(selector));
127 	}
128 
129 	return 0;
130 }
131 
132 static int
ynl_err_walk(struct ynl_sock * ys,void * start,void * end,unsigned int off,const struct ynl_policy_nest * policy,char * str,int str_sz,const struct ynl_policy_nest ** nest_pol)133 ynl_err_walk(struct ynl_sock *ys, void *start, void *end, unsigned int off,
134 	     const struct ynl_policy_nest *policy, char *str, int str_sz,
135 	     const struct ynl_policy_nest **nest_pol)
136 {
137 	const struct ynl_policy_nest *next_pol;
138 	const struct nlattr *selector = NULL;
139 	unsigned int astart_off, aend_off;
140 	const struct nlattr *attr;
141 	unsigned int data_len;
142 	unsigned int type;
143 	bool found = false;
144 	int n = 0;
145 
146 	if (!policy) {
147 		if (n < str_sz)
148 			n += snprintf(str, str_sz, "!policy");
149 		return n;
150 	}
151 
152 	data_len = end - start;
153 
154 	ynl_attr_for_each_payload(start, data_len, attr) {
155 		astart_off = (char *)attr - (char *)start;
156 		aend_off = (char *)ynl_attr_data_end(attr) - (char *)start;
157 
158 		if (ynl_err_walk_is_sel(policy, attr))
159 			selector = attr;
160 
161 		if (aend_off <= off)
162 			continue;
163 
164 		found = true;
165 		break;
166 	}
167 	if (!found)
168 		return 0;
169 
170 	off -= astart_off;
171 
172 	type = ynl_attr_type(attr);
173 
174 	if (ynl_err_walk_report_one(policy, selector, type, str, str_sz, &n))
175 		return n;
176 
177 	next_pol = ynl_err_walk_sel_policy(&policy->table[type], selector);
178 	if (!next_pol)
179 		return n;
180 
181 	if (!off) {
182 		if (nest_pol)
183 			*nest_pol = next_pol;
184 		return n;
185 	}
186 
187 	if (!next_pol) {
188 		if (n < str_sz)
189 			n += snprintf(str, str_sz, "!nest");
190 		return n;
191 	}
192 
193 	off -= sizeof(struct nlattr);
194 	start =  ynl_attr_data(attr);
195 	end = start + ynl_attr_data_len(attr);
196 
197 	return n + ynl_err_walk(ys, start, end, off, next_pol,
198 				&str[n], str_sz - n, nest_pol);
199 }
200 
201 #define NLMSGERR_ATTR_MISS_TYPE (NLMSGERR_ATTR_POLICY + 1)
202 #define NLMSGERR_ATTR_MISS_NEST (NLMSGERR_ATTR_POLICY + 2)
203 #define NLMSGERR_ATTR_MAX (NLMSGERR_ATTR_MAX + 2)
204 
205 static int
ynl_ext_ack_check(struct ynl_sock * ys,const struct nlmsghdr * nlh,unsigned int hlen)206 ynl_ext_ack_check(struct ynl_sock *ys, const struct nlmsghdr *nlh,
207 		  unsigned int hlen)
208 {
209 	const struct nlattr *tb[NLMSGERR_ATTR_MAX + 1] = {};
210 	char miss_attr[sizeof(ys->err.msg)];
211 	char bad_attr[sizeof(ys->err.msg)];
212 	const struct nlattr *attr;
213 	const char *str = NULL;
214 
215 	if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS)) {
216 		yerr_msg(ys, "%s", strerror(ys->err.code));
217 		return YNL_PARSE_CB_OK;
218 	}
219 
220 	ynl_attr_for_each(attr, nlh, hlen) {
221 		unsigned int len, type;
222 
223 		len = ynl_attr_data_len(attr);
224 		type = ynl_attr_type(attr);
225 
226 		if (type > NLMSGERR_ATTR_MAX)
227 			continue;
228 
229 		tb[type] = attr;
230 
231 		switch (type) {
232 		case NLMSGERR_ATTR_OFFS:
233 		case NLMSGERR_ATTR_MISS_TYPE:
234 		case NLMSGERR_ATTR_MISS_NEST:
235 			if (len != sizeof(__u32))
236 				return YNL_PARSE_CB_ERROR;
237 			break;
238 		case NLMSGERR_ATTR_MSG:
239 			str = ynl_attr_get_str(attr);
240 			if (str[len - 1])
241 				return YNL_PARSE_CB_ERROR;
242 			break;
243 		default:
244 			break;
245 		}
246 	}
247 
248 	bad_attr[0] = '\0';
249 	miss_attr[0] = '\0';
250 
251 	if (tb[NLMSGERR_ATTR_OFFS]) {
252 		unsigned int n, off;
253 		void *start, *end;
254 
255 		ys->err.attr_offs = ynl_attr_get_u32(tb[NLMSGERR_ATTR_OFFS]);
256 
257 		n = snprintf(bad_attr, sizeof(bad_attr), "%sbad attribute: ",
258 			     str ? " (" : "");
259 
260 		start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
261 		end = ynl_nlmsg_end_addr(ys->nlh);
262 
263 		off = ys->err.attr_offs;
264 		off -= sizeof(struct nlmsghdr);
265 		off -= ys->req_hdr_len;
266 
267 		n += ynl_err_walk(ys, start, end, off, ys->req_policy,
268 				  &bad_attr[n], sizeof(bad_attr) - n, NULL);
269 
270 		if (n >= sizeof(bad_attr))
271 			n = sizeof(bad_attr) - 1;
272 		bad_attr[n] = '\0';
273 	}
274 	if (tb[NLMSGERR_ATTR_MISS_TYPE]) {
275 		const struct ynl_policy_nest *nest_pol = NULL;
276 		unsigned int n, off, type;
277 		void *start, *end;
278 		int n2;
279 
280 		type = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_TYPE]);
281 
282 		n = snprintf(miss_attr, sizeof(miss_attr), "%smissing attribute: ",
283 			     bad_attr[0] ? ", " : (str ? " (" : ""));
284 
285 		start = ynl_nlmsg_data_offset(ys->nlh, ys->req_hdr_len);
286 		end = ynl_nlmsg_end_addr(ys->nlh);
287 
288 		nest_pol = ys->req_policy;
289 		if (tb[NLMSGERR_ATTR_MISS_NEST]) {
290 			off = ynl_attr_get_u32(tb[NLMSGERR_ATTR_MISS_NEST]);
291 			off -= sizeof(struct nlmsghdr);
292 			off -= ys->req_hdr_len;
293 
294 			n += ynl_err_walk(ys, start, end, off, ys->req_policy,
295 					  &miss_attr[n], sizeof(miss_attr) - n,
296 					  &nest_pol);
297 		}
298 
299 		n2 = 0;
300 		ynl_err_walk_report_one(nest_pol, NULL, type, &miss_attr[n],
301 					sizeof(miss_attr) - n, &n2);
302 		n += n2;
303 
304 		if (n >= sizeof(miss_attr))
305 			n = sizeof(miss_attr) - 1;
306 		miss_attr[n] = '\0';
307 	}
308 
309 	/* Implicitly depend on ys->err.code already set */
310 	if (str)
311 		yerr_msg(ys, "Kernel %s: '%s'%s%s%s",
312 			 ys->err.code ? "error" : "warning",
313 			 str, bad_attr, miss_attr,
314 			 bad_attr[0] || miss_attr[0] ? ")" : "");
315 	else if (bad_attr[0] || miss_attr[0])
316 		yerr_msg(ys, "Kernel %s: %s%s",
317 			 ys->err.code ? "error" : "warning",
318 			 bad_attr, miss_attr);
319 	else
320 		yerr_msg(ys, "%s", strerror(ys->err.code));
321 
322 	return YNL_PARSE_CB_OK;
323 }
324 
325 static int
ynl_cb_error(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)326 ynl_cb_error(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
327 {
328 	const struct nlmsgerr *err = ynl_nlmsg_data(nlh);
329 	unsigned int hlen;
330 	int code;
331 
332 	code = err->error >= 0 ? err->error : -err->error;
333 	yarg->ys->err.code = code;
334 	errno = code;
335 
336 	hlen = sizeof(*err);
337 	if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
338 		hlen += ynl_nlmsg_data_len(&err->msg);
339 
340 	ynl_ext_ack_check(yarg->ys, nlh, hlen);
341 
342 	return code ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_STOP;
343 }
344 
ynl_cb_done(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)345 static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
346 {
347 	int err;
348 
349 	err = *(int *)NLMSG_DATA(nlh);
350 	if (err < 0) {
351 		yarg->ys->err.code = -err;
352 		errno = -err;
353 
354 		ynl_ext_ack_check(yarg->ys, nlh, sizeof(int));
355 
356 		return YNL_PARSE_CB_ERROR;
357 	}
358 	return YNL_PARSE_CB_STOP;
359 }
360 
361 /* Attribute validation */
362 
ynl_attr_validate(struct ynl_parse_arg * yarg,const struct nlattr * attr)363 int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
364 {
365 	const struct ynl_policy_attr *policy;
366 	unsigned int type, len;
367 	unsigned char *data;
368 
369 	data = ynl_attr_data(attr);
370 	len = ynl_attr_data_len(attr);
371 	type = ynl_attr_type(attr);
372 	if (type > yarg->rsp_policy->max_attr) {
373 		yerr(yarg->ys, YNL_ERROR_INTERNAL,
374 		     "Internal error, validating unknown attribute");
375 		return -1;
376 	}
377 
378 	policy = &yarg->rsp_policy->table[type];
379 
380 	switch (policy->type) {
381 	case YNL_PT_REJECT:
382 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
383 		     "Rejected attribute (%s)", policy->name);
384 		return -1;
385 	case YNL_PT_IGNORE:
386 		break;
387 	case YNL_PT_U8:
388 		if (len == sizeof(__u8))
389 			break;
390 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
391 		     "Invalid attribute (u8 %s)", policy->name);
392 		return -1;
393 	case YNL_PT_U16:
394 		if (len == sizeof(__u16))
395 			break;
396 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
397 		     "Invalid attribute (u16 %s)", policy->name);
398 		return -1;
399 	case YNL_PT_U32:
400 		if (len == sizeof(__u32))
401 			break;
402 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
403 		     "Invalid attribute (u32 %s)", policy->name);
404 		return -1;
405 	case YNL_PT_U64:
406 		if (len == sizeof(__u64))
407 			break;
408 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
409 		     "Invalid attribute (u64 %s)", policy->name);
410 		return -1;
411 	case YNL_PT_UINT:
412 		if (len == sizeof(__u32) || len == sizeof(__u64))
413 			break;
414 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
415 		     "Invalid attribute (uint %s)", policy->name);
416 		return -1;
417 	case YNL_PT_FLAG:
418 		/* Let flags grow into real attrs, why not.. */
419 		break;
420 	case YNL_PT_NEST:
421 		if (!len || len >= sizeof(*attr))
422 			break;
423 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
424 		     "Invalid attribute (nest %s)", policy->name);
425 		return -1;
426 	case YNL_PT_BINARY:
427 		if (!policy->len || len == policy->len)
428 			break;
429 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
430 		     "Invalid attribute (binary %s)", policy->name);
431 		return -1;
432 	case YNL_PT_NUL_STR:
433 		if (len && (!policy->len || len <= policy->len) && !data[len - 1])
434 			break;
435 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
436 		     "Invalid attribute (string %s)", policy->name);
437 		return -1;
438 	case YNL_PT_BITFIELD32:
439 		if (len == sizeof(struct nla_bitfield32))
440 			break;
441 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
442 		     "Invalid attribute (bitfield32 %s)", policy->name);
443 		return -1;
444 	default:
445 		yerr(yarg->ys, YNL_ERROR_ATTR_INVALID,
446 		     "Invalid attribute (unknown %s)", policy->name);
447 		return -1;
448 	}
449 
450 	return 0;
451 }
452 
ynl_submsg_failed(struct ynl_parse_arg * yarg,const char * field_name,const char * sel_name)453 int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
454 		      const char *sel_name)
455 {
456 	yerr(yarg->ys, YNL_ERROR_SUBMSG_KEY,
457 	     "Parsing error: Sub-message key not set (msg %s, key %s)",
458 	     field_name, sel_name);
459 	return YNL_PARSE_CB_ERROR;
460 }
461 
462 /* Generic code */
463 
ynl_err_reset(struct ynl_sock * ys)464 static void ynl_err_reset(struct ynl_sock *ys)
465 {
466 	ys->err.code = 0;
467 	ys->err.attr_offs = 0;
468 	ys->err.msg[0] = 0;
469 }
470 
ynl_msg_start(struct ynl_sock * ys,__u32 id,__u16 flags)471 struct nlmsghdr *ynl_msg_start(struct ynl_sock *ys, __u32 id, __u16 flags)
472 {
473 	struct nlmsghdr *nlh;
474 
475 	ynl_err_reset(ys);
476 
477 	nlh = ys->nlh = ynl_nlmsg_put_header(ys->tx_buf);
478 	nlh->nlmsg_type	= id;
479 	nlh->nlmsg_flags = flags;
480 	nlh->nlmsg_seq = ++ys->seq;
481 
482 	/* This is a local YNL hack for length checking, we put the buffer
483 	 * length in nlmsg_pid, since messages sent to the kernel always use
484 	 * PID 0. Message needs to be terminated with ynl_msg_end().
485 	 */
486 	nlh->nlmsg_pid = YNL_SOCKET_BUFFER_SIZE;
487 
488 	return nlh;
489 }
490 
ynl_msg_end(struct ynl_sock * ys,struct nlmsghdr * nlh)491 static int ynl_msg_end(struct ynl_sock *ys, struct nlmsghdr *nlh)
492 {
493 	/* We stash buffer length in nlmsg_pid. */
494 	if (nlh->nlmsg_pid == 0) {
495 		yerr(ys, YNL_ERROR_INPUT_INVALID,
496 		     "Unknown input buffer length");
497 		return -EINVAL;
498 	}
499 	if (nlh->nlmsg_pid == YNL_MSG_OVERFLOW) {
500 		yerr(ys, YNL_ERROR_INPUT_TOO_BIG,
501 		     "Constructed message longer than internal buffer");
502 		return -EMSGSIZE;
503 	}
504 
505 	nlh->nlmsg_pid = 0;
506 	return 0;
507 }
508 
509 struct nlmsghdr *
ynl_gemsg_start(struct ynl_sock * ys,__u32 id,__u16 flags,__u8 cmd,__u8 version)510 ynl_gemsg_start(struct ynl_sock *ys, __u32 id, __u16 flags,
511 		__u8 cmd, __u8 version)
512 {
513 	struct genlmsghdr gehdr;
514 	struct nlmsghdr *nlh;
515 	void *data;
516 
517 	nlh = ynl_msg_start(ys, id, flags);
518 
519 	memset(&gehdr, 0, sizeof(gehdr));
520 	gehdr.cmd = cmd;
521 	gehdr.version = version;
522 
523 	data = ynl_nlmsg_put_extra_header(nlh, sizeof(gehdr));
524 	memcpy(data, &gehdr, sizeof(gehdr));
525 
526 	return nlh;
527 }
528 
ynl_msg_start_req(struct ynl_sock * ys,__u32 id,__u16 flags)529 struct nlmsghdr *ynl_msg_start_req(struct ynl_sock *ys, __u32 id, __u16 flags)
530 {
531 	return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | flags);
532 }
533 
ynl_msg_start_dump(struct ynl_sock * ys,__u32 id)534 struct nlmsghdr *ynl_msg_start_dump(struct ynl_sock *ys, __u32 id)
535 {
536 	return ynl_msg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP);
537 }
538 
539 struct nlmsghdr *
ynl_gemsg_start_req(struct ynl_sock * ys,__u32 id,__u8 cmd,__u8 version)540 ynl_gemsg_start_req(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
541 {
542 	return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK, cmd, version);
543 }
544 
545 struct nlmsghdr *
ynl_gemsg_start_dump(struct ynl_sock * ys,__u32 id,__u8 cmd,__u8 version)546 ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version)
547 {
548 	return ynl_gemsg_start(ys, id, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP,
549 			       cmd, version);
550 }
551 
ynl_cb_null(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)552 static int ynl_cb_null(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
553 {
554 	yerr(yarg->ys, YNL_ERROR_UNEXPECT_MSG,
555 	     "Received a message when none were expected");
556 
557 	return YNL_PARSE_CB_ERROR;
558 }
559 
560 static int
__ynl_sock_read_msgs(struct ynl_parse_arg * yarg,ynl_parse_cb_t cb,int flags)561 __ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb, int flags)
562 {
563 	struct ynl_sock *ys = yarg->ys;
564 	const struct nlmsghdr *nlh;
565 	ssize_t len, rem;
566 	int ret;
567 
568 	len = recv(ys->socket, ys->rx_buf, YNL_SOCKET_BUFFER_SIZE, flags);
569 	if (len < 0) {
570 		if (flags & MSG_DONTWAIT && errno == EAGAIN)
571 			return YNL_PARSE_CB_STOP;
572 		return len;
573 	}
574 
575 	ret = YNL_PARSE_CB_STOP;
576 	for (rem = len; rem > 0; NLMSG_NEXT(nlh, rem)) {
577 		nlh = (struct nlmsghdr *)&ys->rx_buf[len - rem];
578 		if (!NLMSG_OK(nlh, rem)) {
579 			yerr(yarg->ys, YNL_ERROR_INV_RESP,
580 			     "Invalid message or trailing data in the response.");
581 			return YNL_PARSE_CB_ERROR;
582 		}
583 
584 		if (nlh->nlmsg_flags & NLM_F_DUMP_INTR) {
585 			/* TODO: handle this better */
586 			yerr(yarg->ys, YNL_ERROR_DUMP_INTER,
587 			     "Dump interrupted / inconsistent, please retry.");
588 			return YNL_PARSE_CB_ERROR;
589 		}
590 
591 		switch (nlh->nlmsg_type) {
592 		case 0:
593 			yerr(yarg->ys, YNL_ERROR_INV_RESP,
594 			     "Invalid message type in the response.");
595 			return YNL_PARSE_CB_ERROR;
596 		case NLMSG_NOOP:
597 		case NLMSG_OVERRUN ... NLMSG_MIN_TYPE - 1:
598 			ret = YNL_PARSE_CB_OK;
599 			break;
600 		case NLMSG_ERROR:
601 			ret = ynl_cb_error(nlh, yarg);
602 			break;
603 		case NLMSG_DONE:
604 			ret = ynl_cb_done(nlh, yarg);
605 			break;
606 		default:
607 			ret = cb(nlh, yarg);
608 			break;
609 		}
610 	}
611 
612 	return ret;
613 }
614 
ynl_sock_read_msgs(struct ynl_parse_arg * yarg,ynl_parse_cb_t cb)615 static int ynl_sock_read_msgs(struct ynl_parse_arg *yarg, ynl_parse_cb_t cb)
616 {
617 	return __ynl_sock_read_msgs(yarg, cb, 0);
618 }
619 
ynl_recv_ack(struct ynl_sock * ys,int ret)620 static int ynl_recv_ack(struct ynl_sock *ys, int ret)
621 {
622 	struct ynl_parse_arg yarg = { .ys = ys, };
623 
624 	if (!ret) {
625 		yerr(ys, YNL_ERROR_EXPECT_ACK,
626 		     "Expecting an ACK but nothing received");
627 		return -1;
628 	}
629 
630 	return ynl_sock_read_msgs(&yarg, ynl_cb_null);
631 }
632 
633 /* Init/fini and genetlink boiler plate */
634 static int
ynl_get_family_info_mcast(struct ynl_sock * ys,const struct nlattr * mcasts)635 ynl_get_family_info_mcast(struct ynl_sock *ys, const struct nlattr *mcasts)
636 {
637 	const struct nlattr *entry, *attr;
638 	unsigned int i;
639 
640 	ynl_attr_for_each_nested(attr, mcasts)
641 		ys->n_mcast_groups++;
642 
643 	if (!ys->n_mcast_groups)
644 		return 0;
645 
646 	ys->mcast_groups = calloc(ys->n_mcast_groups,
647 				  sizeof(*ys->mcast_groups));
648 	if (!ys->mcast_groups)
649 		return YNL_PARSE_CB_ERROR;
650 
651 	i = 0;
652 	ynl_attr_for_each_nested(entry, mcasts) {
653 		ynl_attr_for_each_nested(attr, entry) {
654 			if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_ID)
655 				ys->mcast_groups[i].id = ynl_attr_get_u32(attr);
656 			if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GRP_NAME) {
657 				strncpy(ys->mcast_groups[i].name,
658 					ynl_attr_get_str(attr),
659 					GENL_NAMSIZ - 1);
660 				ys->mcast_groups[i].name[GENL_NAMSIZ - 1] = 0;
661 			}
662 		}
663 		i++;
664 	}
665 
666 	return 0;
667 }
668 
669 static int
ynl_get_family_info_cb(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)670 ynl_get_family_info_cb(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
671 {
672 	struct ynl_sock *ys = yarg->ys;
673 	const struct nlattr *attr;
674 	bool found_id = true;
675 
676 	ynl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) {
677 		if (ynl_attr_type(attr) == CTRL_ATTR_MCAST_GROUPS)
678 			if (ynl_get_family_info_mcast(ys, attr))
679 				return YNL_PARSE_CB_ERROR;
680 
681 		if (ynl_attr_type(attr) != CTRL_ATTR_FAMILY_ID)
682 			continue;
683 
684 		if (ynl_attr_data_len(attr) != sizeof(__u16)) {
685 			yerr(ys, YNL_ERROR_ATTR_INVALID, "Invalid family ID");
686 			return YNL_PARSE_CB_ERROR;
687 		}
688 
689 		ys->family_id = ynl_attr_get_u16(attr);
690 		found_id = true;
691 	}
692 
693 	if (!found_id) {
694 		yerr(ys, YNL_ERROR_ATTR_MISSING, "Family ID missing");
695 		return YNL_PARSE_CB_ERROR;
696 	}
697 	return YNL_PARSE_CB_OK;
698 }
699 
ynl_sock_read_family(struct ynl_sock * ys,const char * family_name)700 static int ynl_sock_read_family(struct ynl_sock *ys, const char *family_name)
701 {
702 	struct ynl_parse_arg yarg = { .ys = ys, };
703 	struct nlmsghdr *nlh;
704 	int err;
705 
706 	nlh = ynl_gemsg_start_req(ys, GENL_ID_CTRL, CTRL_CMD_GETFAMILY, 1);
707 	ynl_attr_put_str(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
708 
709 	err = ynl_msg_end(ys, nlh);
710 	if (err < 0)
711 		return err;
712 
713 	err = send(ys->socket, nlh, nlh->nlmsg_len, 0);
714 	if (err < 0) {
715 		perr(ys, "failed to request socket family info");
716 		return err;
717 	}
718 
719 	err = ynl_sock_read_msgs(&yarg, ynl_get_family_info_cb);
720 	if (err < 0) {
721 		free(ys->mcast_groups);
722 		perr(ys, "failed to receive the socket family info - no such family?");
723 		return err;
724 	}
725 
726 	err = ynl_recv_ack(ys, err);
727 	if (err < 0) {
728 		free(ys->mcast_groups);
729 		return err;
730 	}
731 
732 	return 0;
733 }
734 
735 struct ynl_sock *
ynl_sock_create(const struct ynl_family * yf,struct ynl_error * yse)736 ynl_sock_create(const struct ynl_family *yf, struct ynl_error *yse)
737 {
738 	struct sockaddr_nl addr;
739 	struct ynl_sock *ys;
740 	socklen_t addrlen;
741 	int sock_type;
742 	int one = 1;
743 
744 	ys = malloc(sizeof(*ys) + 2 * YNL_SOCKET_BUFFER_SIZE);
745 	if (!ys)
746 		return NULL;
747 	memset(ys, 0, sizeof(*ys));
748 
749 	ys->family = yf;
750 	ys->tx_buf = &ys->raw_buf[0];
751 	ys->rx_buf = &ys->raw_buf[YNL_SOCKET_BUFFER_SIZE];
752 	ys->ntf_last_next = &ys->ntf_first;
753 
754 	sock_type = yf->is_classic ? yf->classic_id : NETLINK_GENERIC;
755 
756 	ys->socket = socket(AF_NETLINK, SOCK_RAW, sock_type);
757 	if (ys->socket < 0) {
758 		__perr(yse, "failed to create a netlink socket");
759 		goto err_free_sock;
760 	}
761 
762 	if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_CAP_ACK,
763 		       &one, sizeof(one))) {
764 		__perr(yse, "failed to enable netlink ACK");
765 		goto err_close_sock;
766 	}
767 	if (setsockopt(ys->socket, SOL_NETLINK, NETLINK_EXT_ACK,
768 		       &one, sizeof(one))) {
769 		__perr(yse, "failed to enable netlink ext ACK");
770 		goto err_close_sock;
771 	}
772 
773 	memset(&addr, 0, sizeof(addr));
774 	addr.nl_family = AF_NETLINK;
775 	if (bind(ys->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
776 		__perr(yse, "unable to bind to a socket address");
777 		goto err_close_sock;
778 	}
779 
780 	memset(&addr, 0, sizeof(addr));
781 	addrlen = sizeof(addr);
782 	if (getsockname(ys->socket, (struct sockaddr *)&addr, &addrlen) < 0) {
783 		__perr(yse, "unable to read socket address");
784 		goto err_close_sock;
785 	}
786 	ys->portid = addr.nl_pid;
787 	ys->seq = random();
788 
789 	if (yf->is_classic) {
790 		ys->family_id = yf->classic_id;
791 	} else if (ynl_sock_read_family(ys, yf->name)) {
792 		if (yse)
793 			memcpy(yse, &ys->err, sizeof(*yse));
794 		goto err_close_sock;
795 	}
796 
797 	return ys;
798 
799 err_close_sock:
800 	close(ys->socket);
801 err_free_sock:
802 	free(ys);
803 	return NULL;
804 }
805 
ynl_sock_destroy(struct ynl_sock * ys)806 void ynl_sock_destroy(struct ynl_sock *ys)
807 {
808 	struct ynl_ntf_base_type *ntf;
809 
810 	close(ys->socket);
811 	while ((ntf = ynl_ntf_dequeue(ys)))
812 		ynl_ntf_free(ntf);
813 	free(ys->mcast_groups);
814 	free(ys);
815 }
816 
817 /* YNL multicast handling */
818 
ynl_ntf_free(struct ynl_ntf_base_type * ntf)819 void ynl_ntf_free(struct ynl_ntf_base_type *ntf)
820 {
821 	ntf->free(ntf);
822 }
823 
ynl_subscribe(struct ynl_sock * ys,const char * grp_name)824 int ynl_subscribe(struct ynl_sock *ys, const char *grp_name)
825 {
826 	unsigned int i;
827 	int err;
828 
829 	for (i = 0; i < ys->n_mcast_groups; i++)
830 		if (!strcmp(ys->mcast_groups[i].name, grp_name))
831 			break;
832 	if (i == ys->n_mcast_groups) {
833 		yerr(ys, ENOENT, "Multicast group '%s' not found", grp_name);
834 		return -1;
835 	}
836 
837 	err = setsockopt(ys->socket, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
838 			 &ys->mcast_groups[i].id,
839 			 sizeof(ys->mcast_groups[i].id));
840 	if (err < 0) {
841 		perr(ys, "Subscribing to multicast group failed");
842 		return -1;
843 	}
844 
845 	return 0;
846 }
847 
ynl_socket_get_fd(struct ynl_sock * ys)848 int ynl_socket_get_fd(struct ynl_sock *ys)
849 {
850 	return ys->socket;
851 }
852 
ynl_ntf_dequeue(struct ynl_sock * ys)853 struct ynl_ntf_base_type *ynl_ntf_dequeue(struct ynl_sock *ys)
854 {
855 	struct ynl_ntf_base_type *ntf;
856 
857 	if (!ynl_has_ntf(ys))
858 		return NULL;
859 
860 	ntf = ys->ntf_first;
861 	ys->ntf_first = ntf->next;
862 	if (ys->ntf_last_next == &ntf->next)
863 		ys->ntf_last_next = &ys->ntf_first;
864 
865 	return ntf;
866 }
867 
ynl_ntf_parse(struct ynl_sock * ys,const struct nlmsghdr * nlh)868 static int ynl_ntf_parse(struct ynl_sock *ys, const struct nlmsghdr *nlh)
869 {
870 	struct ynl_parse_arg yarg = { .ys = ys, };
871 	const struct ynl_ntf_info *info;
872 	struct ynl_ntf_base_type *rsp;
873 	__u32 cmd;
874 	int ret;
875 
876 	if (ys->family->is_classic) {
877 		cmd = nlh->nlmsg_type;
878 	} else {
879 		struct genlmsghdr *gehdr;
880 
881 		gehdr = ynl_nlmsg_data(nlh);
882 		cmd = gehdr->cmd;
883 	}
884 
885 	if (cmd >= ys->family->ntf_info_size)
886 		return YNL_PARSE_CB_ERROR;
887 	info = &ys->family->ntf_info[cmd];
888 	if (!info->cb)
889 		return YNL_PARSE_CB_ERROR;
890 
891 	rsp = calloc(1, info->alloc_sz);
892 	rsp->free = info->free;
893 	yarg.data = rsp->data;
894 	yarg.rsp_policy = info->policy;
895 
896 	ret = info->cb(nlh, &yarg);
897 	if (ret <= YNL_PARSE_CB_STOP)
898 		goto err_free;
899 
900 	rsp->family = nlh->nlmsg_type;
901 	rsp->cmd = cmd;
902 
903 	*ys->ntf_last_next = rsp;
904 	ys->ntf_last_next = &rsp->next;
905 
906 	return YNL_PARSE_CB_OK;
907 
908 err_free:
909 	info->free(rsp);
910 	return YNL_PARSE_CB_ERROR;
911 }
912 
913 static int
ynl_ntf_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)914 ynl_ntf_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
915 {
916 	return ynl_ntf_parse(yarg->ys, nlh);
917 }
918 
ynl_ntf_check(struct ynl_sock * ys)919 int ynl_ntf_check(struct ynl_sock *ys)
920 {
921 	struct ynl_parse_arg yarg = { .ys = ys, };
922 	int err;
923 
924 	do {
925 		err = __ynl_sock_read_msgs(&yarg, ynl_ntf_trampoline,
926 					   MSG_DONTWAIT);
927 		if (err < 0)
928 			return err;
929 	} while (err > 0);
930 
931 	return 0;
932 }
933 
934 /* YNL specific helpers used by the auto-generated code */
935 
936 struct ynl_dump_list_type *YNL_LIST_END = (void *)(0xb4d123);
937 
ynl_error_unknown_notification(struct ynl_sock * ys,__u8 cmd)938 void ynl_error_unknown_notification(struct ynl_sock *ys, __u8 cmd)
939 {
940 	yerr(ys, YNL_ERROR_UNKNOWN_NTF,
941 	     "Unknown notification message type '%d'", cmd);
942 }
943 
ynl_error_parse(struct ynl_parse_arg * yarg,const char * msg)944 int ynl_error_parse(struct ynl_parse_arg *yarg, const char *msg)
945 {
946 	yerr(yarg->ys, YNL_ERROR_INV_RESP, "Error parsing response: %s", msg);
947 	return YNL_PARSE_CB_ERROR;
948 }
949 
950 static int
ynl_check_alien(struct ynl_sock * ys,const struct nlmsghdr * nlh,__u32 rsp_cmd)951 ynl_check_alien(struct ynl_sock *ys, const struct nlmsghdr *nlh, __u32 rsp_cmd)
952 {
953 	if (ys->family->is_classic) {
954 		if (nlh->nlmsg_type != rsp_cmd)
955 			return ynl_ntf_parse(ys, nlh);
956 	} else {
957 		struct genlmsghdr *gehdr;
958 
959 		if (ynl_nlmsg_data_len(nlh) < sizeof(*gehdr)) {
960 			yerr(ys, YNL_ERROR_INV_RESP,
961 			     "Kernel responded with truncated message");
962 			return -1;
963 		}
964 
965 		gehdr = ynl_nlmsg_data(nlh);
966 		if (gehdr->cmd != rsp_cmd)
967 			return ynl_ntf_parse(ys, nlh);
968 	}
969 
970 	return 0;
971 }
972 
973 static
ynl_req_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * yarg)974 int ynl_req_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
975 {
976 	struct ynl_req_state *yrs = (void *)yarg;
977 	int ret;
978 
979 	ret = ynl_check_alien(yrs->yarg.ys, nlh, yrs->rsp_cmd);
980 	if (ret)
981 		return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
982 
983 	return yrs->cb(nlh, &yrs->yarg);
984 }
985 
ynl_exec(struct ynl_sock * ys,struct nlmsghdr * req_nlh,struct ynl_req_state * yrs)986 int ynl_exec(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
987 	     struct ynl_req_state *yrs)
988 {
989 	int err;
990 
991 	err = ynl_msg_end(ys, req_nlh);
992 	if (err < 0)
993 		return err;
994 
995 	err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
996 	if (err < 0)
997 		return err;
998 
999 	do {
1000 		err = ynl_sock_read_msgs(&yrs->yarg, ynl_req_trampoline);
1001 	} while (err > 0);
1002 
1003 	return err;
1004 }
1005 
1006 static int
ynl_dump_trampoline(const struct nlmsghdr * nlh,struct ynl_parse_arg * data)1007 ynl_dump_trampoline(const struct nlmsghdr *nlh, struct ynl_parse_arg *data)
1008 {
1009 	struct ynl_dump_state *ds = (void *)data;
1010 	struct ynl_dump_list_type *obj;
1011 	struct ynl_parse_arg yarg = {};
1012 	int ret;
1013 
1014 	ret = ynl_check_alien(ds->yarg.ys, nlh, ds->rsp_cmd);
1015 	if (ret)
1016 		return ret < 0 ? YNL_PARSE_CB_ERROR : YNL_PARSE_CB_OK;
1017 
1018 	obj = calloc(1, ds->alloc_sz);
1019 	if (!obj)
1020 		return YNL_PARSE_CB_ERROR;
1021 
1022 	if (!ds->first)
1023 		ds->first = obj;
1024 	if (ds->last)
1025 		ds->last->next = obj;
1026 	ds->last = obj;
1027 
1028 	yarg = ds->yarg;
1029 	yarg.data = &obj->data;
1030 
1031 	return ds->cb(nlh, &yarg);
1032 }
1033 
ynl_dump_end(struct ynl_dump_state * ds)1034 static void *ynl_dump_end(struct ynl_dump_state *ds)
1035 {
1036 	if (!ds->first)
1037 		return YNL_LIST_END;
1038 
1039 	ds->last->next = YNL_LIST_END;
1040 	return ds->first;
1041 }
1042 
ynl_exec_dump(struct ynl_sock * ys,struct nlmsghdr * req_nlh,struct ynl_dump_state * yds)1043 int ynl_exec_dump(struct ynl_sock *ys, struct nlmsghdr *req_nlh,
1044 		  struct ynl_dump_state *yds)
1045 {
1046 	int err;
1047 
1048 	err = ynl_msg_end(ys, req_nlh);
1049 	if (err < 0)
1050 		return err;
1051 
1052 	err = send(ys->socket, req_nlh, req_nlh->nlmsg_len, 0);
1053 	if (err < 0)
1054 		return err;
1055 
1056 	do {
1057 		err = ynl_sock_read_msgs(&yds->yarg, ynl_dump_trampoline);
1058 		if (err < 0)
1059 			goto err_close_list;
1060 	} while (err > 0);
1061 
1062 	yds->first = ynl_dump_end(yds);
1063 	return 0;
1064 
1065 err_close_list:
1066 	yds->first = ynl_dump_end(yds);
1067 	return -1;
1068 }
1069