]> git.proxmox.com Git - systemd.git/blob - src/libsystemd/sd-netlink/netlink-message.c
New upstream version 249~rc1
[systemd.git] / src / libsystemd / sd-netlink / netlink-message.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <netinet/in.h>
4 #include <stdbool.h>
5 #include <unistd.h>
6
7 #include "sd-netlink.h"
8
9 #include "alloc-util.h"
10 #include "format-util.h"
11 #include "memory-util.h"
12 #include "netlink-internal.h"
13 #include "netlink-types.h"
14 #include "netlink-util.h"
15 #include "socket-util.h"
16 #include "strv.h"
17
18 #define GET_CONTAINER(m, i) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset))
19
20 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
21 #define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
22
23 int message_new_empty(sd_netlink *rtnl, sd_netlink_message **ret) {
24 sd_netlink_message *m;
25
26 assert_return(ret, -EINVAL);
27
28 /* Note that 'rtnl' is currently unused, if we start using it internally
29 we must take care to avoid problems due to mutual references between
30 buses and their queued messages. See sd-bus.
31 */
32
33 m = new(sd_netlink_message, 1);
34 if (!m)
35 return -ENOMEM;
36
37 *m = (sd_netlink_message) {
38 .n_ref = 1,
39 .protocol = rtnl->protocol,
40 .sealed = false,
41 };
42
43 *ret = m;
44
45 return 0;
46 }
47
48 int message_new(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t type) {
49 _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *m = NULL;
50 const NLType *nl_type;
51 size_t size;
52 int r;
53
54 assert_return(rtnl, -EINVAL);
55
56 r = type_system_root_get_type(rtnl, &nl_type, type);
57 if (r < 0)
58 return r;
59
60 if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
61 return -EINVAL;
62
63 r = message_new_empty(rtnl, &m);
64 if (r < 0)
65 return r;
66
67 size = NLMSG_SPACE(type_get_size(nl_type));
68
69 assert(size >= sizeof(struct nlmsghdr));
70 m->hdr = malloc0(size);
71 if (!m->hdr)
72 return -ENOMEM;
73
74 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
75
76 type_get_type_system(nl_type, &m->containers[0].type_system);
77 m->hdr->nlmsg_len = size;
78 m->hdr->nlmsg_type = type;
79
80 *ret = TAKE_PTR(m);
81
82 return 0;
83 }
84
85 int sd_netlink_message_request_dump(sd_netlink_message *m, int dump) {
86 assert_return(m, -EINVAL);
87 assert_return(m->hdr, -EINVAL);
88
89 assert_return(IN_SET(m->hdr->nlmsg_type,
90 RTM_GETLINK, RTM_GETLINKPROP, RTM_GETADDR, RTM_GETROUTE, RTM_GETNEIGH,
91 RTM_GETRULE, RTM_GETADDRLABEL, RTM_GETNEXTHOP), -EINVAL);
92
93 SET_FLAG(m->hdr->nlmsg_flags, NLM_F_DUMP, dump);
94
95 return 0;
96 }
97
98 DEFINE_TRIVIAL_REF_FUNC(sd_netlink_message, sd_netlink_message);
99
100 sd_netlink_message *sd_netlink_message_unref(sd_netlink_message *m) {
101 while (m && --m->n_ref == 0) {
102 unsigned i;
103
104 free(m->hdr);
105
106 for (i = 0; i <= m->n_containers; i++)
107 free(m->containers[i].attributes);
108
109 sd_netlink_message *t = m;
110 m = m->next;
111 free(t);
112 }
113
114 return NULL;
115 }
116
117 int sd_netlink_message_get_type(sd_netlink_message *m, uint16_t *type) {
118 assert_return(m, -EINVAL);
119 assert_return(type, -EINVAL);
120
121 *type = m->hdr->nlmsg_type;
122
123 return 0;
124 }
125
126 int sd_netlink_message_set_flags(sd_netlink_message *m, uint16_t flags) {
127 assert_return(m, -EINVAL);
128 assert_return(flags, -EINVAL);
129
130 m->hdr->nlmsg_flags = flags;
131
132 return 0;
133 }
134
135 int sd_netlink_message_is_broadcast(sd_netlink_message *m) {
136 assert_return(m, -EINVAL);
137
138 return m->broadcast;
139 }
140
141 /* If successful the updated message will be correctly aligned, if
142 unsuccessful the old message is untouched. */
143 static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) {
144 size_t message_length;
145 struct nlmsghdr *new_hdr;
146 struct rtattr *rta;
147 int offset;
148
149 assert(m);
150 assert(m->hdr);
151 assert(!m->sealed);
152 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
153 assert(!data || data_length > 0);
154
155 /* get the new message size (with padding at the end) */
156 message_length = m->hdr->nlmsg_len + RTA_SPACE(data_length);
157
158 /* buffer should be smaller than both one page or 8K to be accepted by the kernel */
159 if (message_length > MIN(page_size(), 8192UL))
160 return -ENOBUFS;
161
162 /* realloc to fit the new attribute */
163 new_hdr = realloc(m->hdr, message_length);
164 if (!new_hdr)
165 return -ENOMEM;
166 m->hdr = new_hdr;
167
168 /* get pointer to the attribute we are about to add */
169 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
170
171 rtattr_append_attribute_internal(rta, type, data, data_length);
172
173 /* if we are inside containers, extend them */
174 for (unsigned i = 0; i < m->n_containers; i++)
175 GET_CONTAINER(m, i)->rta_len += RTA_SPACE(data_length);
176
177 /* update message size */
178 offset = m->hdr->nlmsg_len;
179 m->hdr->nlmsg_len = message_length;
180
181 /* return old message size */
182 return offset;
183 }
184
185 static int message_attribute_has_type(sd_netlink_message *m, size_t *out_size, uint16_t attribute_type, uint16_t data_type) {
186 const NLType *type;
187 int r;
188
189 assert(m);
190
191 r = type_system_get_type(m->containers[m->n_containers].type_system, &type, attribute_type);
192 if (r < 0)
193 return r;
194
195 if (type_get_type(type) != data_type)
196 return -EINVAL;
197
198 if (out_size)
199 *out_size = type_get_size(type);
200 return 0;
201 }
202
203 int sd_netlink_message_append_string(sd_netlink_message *m, unsigned short type, const char *data) {
204 size_t length, size;
205 int r;
206
207 assert_return(m, -EINVAL);
208 assert_return(!m->sealed, -EPERM);
209 assert_return(data, -EINVAL);
210
211 r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING);
212 if (r < 0)
213 return r;
214
215 if (size) {
216 length = strnlen(data, size+1);
217 if (length > size)
218 return -EINVAL;
219 } else
220 length = strlen(data);
221
222 r = add_rtattr(m, type, data, length + 1);
223 if (r < 0)
224 return r;
225
226 return 0;
227 }
228
229 int sd_netlink_message_append_strv(sd_netlink_message *m, unsigned short type, char * const *data) {
230 size_t length, size;
231 char * const *p;
232 int r;
233
234 assert_return(m, -EINVAL);
235 assert_return(!m->sealed, -EPERM);
236 assert_return(data, -EINVAL);
237
238 r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_STRING);
239 if (r < 0)
240 return r;
241
242 STRV_FOREACH(p, data) {
243 if (size) {
244 length = strnlen(*p, size+1);
245 if (length > size)
246 return -EINVAL;
247 } else
248 length = strlen(*p);
249
250 r = add_rtattr(m, type, *p, length + 1);
251 if (r < 0)
252 return r;
253 }
254
255 return 0;
256 }
257
258 int sd_netlink_message_append_flag(sd_netlink_message *m, unsigned short type) {
259 size_t size;
260 int r;
261
262 assert_return(m, -EINVAL);
263 assert_return(!m->sealed, -EPERM);
264
265 r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_FLAG);
266 if (r < 0)
267 return r;
268
269 r = add_rtattr(m, type, NULL, 0);
270 if (r < 0)
271 return r;
272
273 return 0;
274 }
275
276 int sd_netlink_message_append_u8(sd_netlink_message *m, unsigned short type, uint8_t data) {
277 int r;
278
279 assert_return(m, -EINVAL);
280 assert_return(!m->sealed, -EPERM);
281
282 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8);
283 if (r < 0)
284 return r;
285
286 r = add_rtattr(m, type, &data, sizeof(uint8_t));
287 if (r < 0)
288 return r;
289
290 return 0;
291 }
292
293 int sd_netlink_message_append_u16(sd_netlink_message *m, unsigned short type, uint16_t data) {
294 int r;
295
296 assert_return(m, -EINVAL);
297 assert_return(!m->sealed, -EPERM);
298
299 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16);
300 if (r < 0)
301 return r;
302
303 r = add_rtattr(m, type, &data, sizeof(uint16_t));
304 if (r < 0)
305 return r;
306
307 return 0;
308 }
309
310 int sd_netlink_message_append_u32(sd_netlink_message *m, unsigned short type, uint32_t data) {
311 int r;
312
313 assert_return(m, -EINVAL);
314 assert_return(!m->sealed, -EPERM);
315
316 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32);
317 if (r < 0)
318 return r;
319
320 r = add_rtattr(m, type, &data, sizeof(uint32_t));
321 if (r < 0)
322 return r;
323
324 return 0;
325 }
326
327 int sd_netlink_message_append_u64(sd_netlink_message *m, unsigned short type, uint64_t data) {
328 int r;
329
330 assert_return(m, -EINVAL);
331 assert_return(!m->sealed, -EPERM);
332
333 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U64);
334 if (r < 0)
335 return r;
336
337 r = add_rtattr(m, type, &data, sizeof(uint64_t));
338 if (r < 0)
339 return r;
340
341 return 0;
342 }
343
344 int sd_netlink_message_append_s8(sd_netlink_message *m, unsigned short type, int8_t data) {
345 int r;
346
347 assert_return(m, -EINVAL);
348 assert_return(!m->sealed, -EPERM);
349
350 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S8);
351 if (r < 0)
352 return r;
353
354 r = add_rtattr(m, type, &data, sizeof(int8_t));
355 if (r < 0)
356 return r;
357
358 return 0;
359 }
360
361 int sd_netlink_message_append_s16(sd_netlink_message *m, unsigned short type, int16_t data) {
362 int r;
363
364 assert_return(m, -EINVAL);
365 assert_return(!m->sealed, -EPERM);
366
367 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S16);
368 if (r < 0)
369 return r;
370
371 r = add_rtattr(m, type, &data, sizeof(int16_t));
372 if (r < 0)
373 return r;
374
375 return 0;
376 }
377
378 int sd_netlink_message_append_s32(sd_netlink_message *m, unsigned short type, int32_t data) {
379 int r;
380
381 assert_return(m, -EINVAL);
382 assert_return(!m->sealed, -EPERM);
383
384 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S32);
385 if (r < 0)
386 return r;
387
388 r = add_rtattr(m, type, &data, sizeof(int32_t));
389 if (r < 0)
390 return r;
391
392 return 0;
393 }
394
395 int sd_netlink_message_append_s64(sd_netlink_message *m, unsigned short type, int64_t data) {
396 int r;
397
398 assert_return(m, -EINVAL);
399 assert_return(!m->sealed, -EPERM);
400
401 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_S64);
402 if (r < 0)
403 return r;
404
405 r = add_rtattr(m, type, &data, sizeof(int64_t));
406 if (r < 0)
407 return r;
408
409 return 0;
410 }
411
412 int sd_netlink_message_append_data(sd_netlink_message *m, unsigned short type, const void *data, size_t len) {
413 int r;
414
415 assert_return(m, -EINVAL);
416 assert_return(!m->sealed, -EPERM);
417
418 r = add_rtattr(m, type, data, len);
419 if (r < 0)
420 return r;
421
422 return 0;
423 }
424
425 int netlink_message_append_in_addr_union(sd_netlink_message *m, unsigned short type, int family, const union in_addr_union *data) {
426 int r;
427
428 assert_return(m, -EINVAL);
429 assert_return(!m->sealed, -EPERM);
430 assert_return(data, -EINVAL);
431 assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
432
433 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
434 if (r < 0)
435 return r;
436
437 r = add_rtattr(m, type, data, FAMILY_ADDRESS_SIZE(family));
438 if (r < 0)
439 return r;
440
441 return 0;
442 }
443
444 int sd_netlink_message_append_in_addr(sd_netlink_message *m, unsigned short type, const struct in_addr *data) {
445 return netlink_message_append_in_addr_union(m, type, AF_INET, (const union in_addr_union *) data);
446 }
447
448 int sd_netlink_message_append_in6_addr(sd_netlink_message *m, unsigned short type, const struct in6_addr *data) {
449 return netlink_message_append_in_addr_union(m, type, AF_INET6, (const union in_addr_union *) data);
450 }
451
452 int netlink_message_append_sockaddr_union(sd_netlink_message *m, unsigned short type, const union sockaddr_union *data) {
453 int r;
454
455 assert_return(m, -EINVAL);
456 assert_return(!m->sealed, -EPERM);
457 assert_return(data, -EINVAL);
458 assert_return(IN_SET(data->sa.sa_family, AF_INET, AF_INET6), -EINVAL);
459
460 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_SOCKADDR);
461 if (r < 0)
462 return r;
463
464 r = add_rtattr(m, type, data, data->sa.sa_family == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6));
465 if (r < 0)
466 return r;
467
468 return 0;
469 }
470
471 int sd_netlink_message_append_sockaddr_in(sd_netlink_message *m, unsigned short type, const struct sockaddr_in *data) {
472 return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data);
473 }
474
475 int sd_netlink_message_append_sockaddr_in6(sd_netlink_message *m, unsigned short type, const struct sockaddr_in6 *data) {
476 return netlink_message_append_sockaddr_union(m, type, (const union sockaddr_union *) data);
477 }
478
479 int sd_netlink_message_append_ether_addr(sd_netlink_message *m, unsigned short type, const struct ether_addr *data) {
480 int r;
481
482 assert_return(m, -EINVAL);
483 assert_return(!m->sealed, -EPERM);
484 assert_return(data, -EINVAL);
485
486 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
487 if (r < 0)
488 return r;
489
490 r = add_rtattr(m, type, data, ETH_ALEN);
491 if (r < 0)
492 return r;
493
494 return 0;
495 }
496
497 int netlink_message_append_hw_addr(sd_netlink_message *m, unsigned short type, const struct hw_addr_data *data) {
498 int r;
499
500 assert_return(m, -EINVAL);
501 assert_return(!m->sealed, -EPERM);
502 assert_return(data, -EINVAL);
503 assert_return(data->length > 0, -EINVAL);
504
505 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
506 if (r < 0)
507 return r;
508
509 r = add_rtattr(m, type, data->bytes, data->length);
510 if (r < 0)
511 return r;
512
513 return 0;
514 }
515
516 int sd_netlink_message_append_cache_info(sd_netlink_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
517 int r;
518
519 assert_return(m, -EINVAL);
520 assert_return(!m->sealed, -EPERM);
521 assert_return(info, -EINVAL);
522
523 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO);
524 if (r < 0)
525 return r;
526
527 r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
528 if (r < 0)
529 return r;
530
531 return 0;
532 }
533
534 int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type) {
535 size_t size;
536 int r;
537
538 assert_return(m, -EINVAL);
539 assert_return(!m->sealed, -EPERM);
540 /* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
541 assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
542
543 r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
544 if (r < 0) {
545 const NLTypeSystemUnion *type_system_union;
546 int family;
547
548 r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_UNION);
549 if (r < 0)
550 return r;
551
552 r = sd_rtnl_message_get_family(m, &family);
553 if (r < 0)
554 return r;
555
556 r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
557 if (r < 0)
558 return r;
559
560 r = type_system_union_protocol_get_type_system(type_system_union,
561 &m->containers[m->n_containers + 1].type_system,
562 family);
563 if (r < 0)
564 return r;
565 } else {
566 r = type_system_get_type_system(m->containers[m->n_containers].type_system,
567 &m->containers[m->n_containers + 1].type_system,
568 type);
569 if (r < 0)
570 return r;
571 }
572
573 r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
574 if (r < 0)
575 return r;
576
577 m->containers[m->n_containers++].offset = r;
578
579 return 0;
580 }
581
582 int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned short type, const char *key) {
583 const NLTypeSystemUnion *type_system_union;
584 int r;
585
586 assert_return(m, -EINVAL);
587 assert_return(!m->sealed, -EPERM);
588 assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
589
590 r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
591 if (r < 0)
592 return r;
593
594 r = type_system_union_get_type_system(type_system_union,
595 &m->containers[m->n_containers + 1].type_system,
596 key);
597 if (r < 0)
598 return r;
599
600 r = sd_netlink_message_append_string(m, type_system_union->match, key);
601 if (r < 0)
602 return r;
603
604 /* do we ever need non-null size */
605 r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
606 if (r < 0)
607 return r;
608
609 m->containers[m->n_containers++].offset = r;
610
611 return 0;
612 }
613
614 int sd_netlink_message_close_container(sd_netlink_message *m) {
615 assert_return(m, -EINVAL);
616 assert_return(!m->sealed, -EPERM);
617 assert_return(m->n_containers > 0, -EINVAL);
618
619 m->containers[m->n_containers].type_system = NULL;
620 m->containers[m->n_containers].offset = 0;
621 m->n_containers--;
622
623 return 0;
624 }
625
626 int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
627 int r;
628
629 assert_return(m, -EINVAL);
630 assert_return(!m->sealed, -EPERM);
631 assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
632
633 r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
634 if (r < 0)
635 return r;
636
637 m->containers[m->n_containers].offset = r;
638 m->n_containers++;
639 m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
640
641 return 0;
642 }
643
644 int sd_netlink_message_cancel_array(sd_netlink_message *m) {
645 uint32_t rta_len;
646
647 assert_return(m, -EINVAL);
648 assert_return(!m->sealed, -EPERM);
649 assert_return(m->n_containers > 1, -EINVAL);
650
651 rta_len = GET_CONTAINER(m, (m->n_containers - 1))->rta_len;
652
653 for (unsigned i = 0; i < m->n_containers; i++)
654 GET_CONTAINER(m, i)->rta_len -= rta_len;
655
656 m->hdr->nlmsg_len -= rta_len;
657
658 m->n_containers--;
659 m->containers[m->n_containers].type_system = NULL;
660
661 return 0;
662 }
663
664 static int netlink_message_read_internal(
665 sd_netlink_message *m,
666 unsigned short type,
667 void **ret_data,
668 bool *ret_net_byteorder) {
669
670 struct netlink_attribute *attribute;
671 struct rtattr *rta;
672
673 assert_return(m, -EINVAL);
674 assert_return(m->sealed, -EPERM);
675
676 assert(m->n_containers < RTNL_CONTAINER_DEPTH);
677
678 if (!m->containers[m->n_containers].attributes)
679 return -ENODATA;
680
681 if (type >= m->containers[m->n_containers].n_attributes)
682 return -ENODATA;
683
684 attribute = &m->containers[m->n_containers].attributes[type];
685
686 if (attribute->offset == 0)
687 return -ENODATA;
688
689 rta = (struct rtattr*)((uint8_t *) m->hdr + attribute->offset);
690
691 if (ret_data)
692 *ret_data = RTA_DATA(rta);
693
694 if (ret_net_byteorder)
695 *ret_net_byteorder = attribute->net_byteorder;
696
697 return RTA_PAYLOAD(rta);
698 }
699
700 int sd_netlink_message_read(sd_netlink_message *m, unsigned short type, size_t size, void *data) {
701 void *attr_data;
702 int r;
703
704 assert_return(m, -EINVAL);
705
706 r = netlink_message_read_internal(m, type, &attr_data, NULL);
707 if (r < 0)
708 return r;
709
710 if ((size_t) r < size)
711 return -EIO;
712
713 if (data)
714 memcpy(data, attr_data, size);
715
716 return r;
717 }
718
719 int sd_netlink_message_read_data(sd_netlink_message *m, unsigned short type, size_t *ret_size, void **ret_data) {
720 void *attr_data, *data;
721 int r;
722
723 assert_return(m, -EINVAL);
724
725 r = netlink_message_read_internal(m, type, &attr_data, NULL);
726 if (r < 0)
727 return r;
728
729 if (ret_data) {
730 data = memdup(attr_data, r);
731 if (!data)
732 return -ENOMEM;
733
734 *ret_data = data;
735 }
736
737 if (ret_size)
738 *ret_size = r;
739
740 return r;
741 }
742
743 int sd_netlink_message_read_string_strdup(sd_netlink_message *m, unsigned short type, char **data) {
744 void *attr_data;
745 char *str;
746 int r;
747
748 assert_return(m, -EINVAL);
749
750 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING);
751 if (r < 0)
752 return r;
753
754 r = netlink_message_read_internal(m, type, &attr_data, NULL);
755 if (r < 0)
756 return r;
757
758 if (data) {
759 str = strndup(attr_data, r);
760 if (!str)
761 return -ENOMEM;
762
763 *data = str;
764 }
765
766 return 0;
767 }
768
769 int sd_netlink_message_read_string(sd_netlink_message *m, unsigned short type, const char **data) {
770 int r;
771 void *attr_data;
772
773 assert_return(m, -EINVAL);
774
775 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_STRING);
776 if (r < 0)
777 return r;
778
779 r = netlink_message_read_internal(m, type, &attr_data, NULL);
780 if (r < 0)
781 return r;
782 else if (strnlen(attr_data, r) >= (size_t) r)
783 return -EIO;
784
785 if (data)
786 *data = (const char *) attr_data;
787
788 return 0;
789 }
790
791 int sd_netlink_message_read_u8(sd_netlink_message *m, unsigned short type, uint8_t *data) {
792 int r;
793 void *attr_data;
794
795 assert_return(m, -EINVAL);
796
797 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U8);
798 if (r < 0)
799 return r;
800
801 r = netlink_message_read_internal(m, type, &attr_data, NULL);
802 if (r < 0)
803 return r;
804 else if ((size_t) r < sizeof(uint8_t))
805 return -EIO;
806
807 if (data)
808 *data = *(uint8_t *) attr_data;
809
810 return 0;
811 }
812
813 int sd_netlink_message_read_u16(sd_netlink_message *m, unsigned short type, uint16_t *data) {
814 void *attr_data;
815 bool net_byteorder;
816 int r;
817
818 assert_return(m, -EINVAL);
819
820 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U16);
821 if (r < 0)
822 return r;
823
824 r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
825 if (r < 0)
826 return r;
827 else if ((size_t) r < sizeof(uint16_t))
828 return -EIO;
829
830 if (data) {
831 if (net_byteorder)
832 *data = be16toh(*(uint16_t *) attr_data);
833 else
834 *data = *(uint16_t *) attr_data;
835 }
836
837 return 0;
838 }
839
840 int sd_netlink_message_read_u32(sd_netlink_message *m, unsigned short type, uint32_t *data) {
841 void *attr_data;
842 bool net_byteorder;
843 int r;
844
845 assert_return(m, -EINVAL);
846
847 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_U32);
848 if (r < 0)
849 return r;
850
851 r = netlink_message_read_internal(m, type, &attr_data, &net_byteorder);
852 if (r < 0)
853 return r;
854 else if ((size_t) r < sizeof(uint32_t))
855 return -EIO;
856
857 if (data) {
858 if (net_byteorder)
859 *data = be32toh(*(uint32_t *) attr_data);
860 else
861 *data = *(uint32_t *) attr_data;
862 }
863
864 return 0;
865 }
866
867 int sd_netlink_message_read_ether_addr(sd_netlink_message *m, unsigned short type, struct ether_addr *data) {
868 int r;
869 void *attr_data;
870
871 assert_return(m, -EINVAL);
872
873 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
874 if (r < 0)
875 return r;
876
877 r = netlink_message_read_internal(m, type, &attr_data, NULL);
878 if (r < 0)
879 return r;
880 else if ((size_t) r < sizeof(struct ether_addr))
881 return -EIO;
882
883 if (data)
884 memcpy(data, attr_data, sizeof(struct ether_addr));
885
886 return 0;
887 }
888
889 int netlink_message_read_hw_addr(sd_netlink_message *m, unsigned short type, struct hw_addr_data *data) {
890 int r;
891 void *attr_data;
892
893 assert_return(m, -EINVAL);
894
895 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_ETHER_ADDR);
896 if (r < 0)
897 return r;
898
899 r = netlink_message_read_internal(m, type, &attr_data, NULL);
900 if (r < 0)
901 return r;
902 else if (r > HW_ADDR_MAX_SIZE)
903 return -EIO;
904
905 if (data) {
906 memcpy(data->bytes, attr_data, r);
907 data->length = r;
908 }
909
910 return 0;
911 }
912
913 int sd_netlink_message_read_cache_info(sd_netlink_message *m, unsigned short type, struct ifa_cacheinfo *info) {
914 int r;
915 void *attr_data;
916
917 assert_return(m, -EINVAL);
918
919 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_CACHE_INFO);
920 if (r < 0)
921 return r;
922
923 r = netlink_message_read_internal(m, type, &attr_data, NULL);
924 if (r < 0)
925 return r;
926 else if ((size_t) r < sizeof(struct ifa_cacheinfo))
927 return -EIO;
928
929 if (info)
930 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
931
932 return 0;
933 }
934
935 int netlink_message_read_in_addr_union(sd_netlink_message *m, unsigned short type, int family, union in_addr_union *data) {
936 void *attr_data;
937 int r;
938
939 assert_return(m, -EINVAL);
940 assert_return(IN_SET(family, AF_INET, AF_INET6), -EINVAL);
941
942 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_IN_ADDR);
943 if (r < 0)
944 return r;
945
946 r = netlink_message_read_internal(m, type, &attr_data, NULL);
947 if (r < 0)
948 return r;
949 else if ((size_t) r < FAMILY_ADDRESS_SIZE(family))
950 return -EIO;
951
952 if (data)
953 memcpy(data, attr_data, FAMILY_ADDRESS_SIZE(family));
954
955 return 0;
956 }
957
958 int sd_netlink_message_read_in_addr(sd_netlink_message *m, unsigned short type, struct in_addr *data) {
959 union in_addr_union u;
960 int r;
961
962 r = netlink_message_read_in_addr_union(m, type, AF_INET, &u);
963 if (r >= 0 && data)
964 *data = u.in;
965
966 return r;
967 }
968
969 int sd_netlink_message_read_in6_addr(sd_netlink_message *m, unsigned short type, struct in6_addr *data) {
970 union in_addr_union u;
971 int r;
972
973 r = netlink_message_read_in_addr_union(m, type, AF_INET6, &u);
974 if (r >= 0 && data)
975 *data = u.in6;
976
977 return r;
978 }
979
980 int sd_netlink_message_has_flag(sd_netlink_message *m, unsigned short type) {
981 void *attr_data;
982 int r;
983
984 assert_return(m, -EINVAL);
985
986 /* This returns 1 when the flag is set, 0 when not set, negative errno on error. */
987
988 r = message_attribute_has_type(m, NULL, type, NETLINK_TYPE_FLAG);
989 if (r < 0)
990 return r;
991
992 r = netlink_message_read_internal(m, type, &attr_data, NULL);
993 if (r == -ENODATA)
994 return 0;
995 if (r < 0)
996 return r;
997
998 return 1;
999 }
1000
1001 int sd_netlink_message_read_strv(sd_netlink_message *m, unsigned short container_type, unsigned short type_id, char ***ret) {
1002 _cleanup_strv_free_ char **s = NULL;
1003 const NLTypeSystem *type_system;
1004 const NLType *nl_type;
1005 struct rtattr *rta;
1006 void *container;
1007 size_t rt_len;
1008 int r;
1009
1010 assert_return(m, -EINVAL);
1011 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1012
1013 r = type_system_get_type(m->containers[m->n_containers].type_system,
1014 &nl_type,
1015 container_type);
1016 if (r < 0)
1017 return r;
1018
1019 if (type_get_type(nl_type) != NETLINK_TYPE_NESTED)
1020 return -EINVAL;
1021
1022 r = type_system_get_type_system(m->containers[m->n_containers].type_system,
1023 &type_system,
1024 container_type);
1025 if (r < 0)
1026 return r;
1027
1028 r = type_system_get_type(type_system, &nl_type, type_id);
1029 if (r < 0)
1030 return r;
1031
1032 if (type_get_type(nl_type) != NETLINK_TYPE_STRING)
1033 return -EINVAL;
1034
1035 r = netlink_message_read_internal(m, container_type, &container, NULL);
1036 if (r < 0)
1037 return r;
1038
1039 rt_len = (size_t) r;
1040 rta = container;
1041
1042 /* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
1043 * LGTM.com analysis does not like the type difference. Hence, here we
1044 * introduce an unsigned short variable as a workaround. */
1045 unsigned short len = rt_len;
1046 for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
1047 unsigned short type;
1048
1049 type = RTA_TYPE(rta);
1050 if (type != type_id)
1051 continue;
1052
1053 r = strv_extend(&s, RTA_DATA(rta));
1054 if (r < 0)
1055 return r;
1056 }
1057
1058 *ret = TAKE_PTR(s);
1059 return 0;
1060 }
1061
1062 static int netlink_container_parse(sd_netlink_message *m,
1063 struct netlink_container *container,
1064 struct rtattr *rta,
1065 size_t rt_len) {
1066 _cleanup_free_ struct netlink_attribute *attributes = NULL;
1067 size_t n = 0;
1068
1069 /* RTA_OK() macro compares with rta->rt_len, which is unsigned short, and
1070 * LGTM.com analysis does not like the type difference. Hence, here we
1071 * introduce an unsigned short variable as a workaround. */
1072 unsigned short len = rt_len;
1073 for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
1074 unsigned short type;
1075
1076 type = RTA_TYPE(rta);
1077
1078 if (!GREEDY_REALLOC0(attributes, type + 1))
1079 return -ENOMEM;
1080
1081 if (attributes[type].offset != 0)
1082 log_debug("rtnl: message parse - overwriting repeated attribute");
1083
1084 attributes[type].offset = (uint8_t *) rta - (uint8_t *) m->hdr;
1085 attributes[type].nested = RTA_FLAGS(rta) & NLA_F_NESTED;
1086 attributes[type].net_byteorder = RTA_FLAGS(rta) & NLA_F_NET_BYTEORDER;
1087
1088 if (type + 1U > n)
1089 n = type + 1U;
1090 }
1091
1092 container->attributes = TAKE_PTR(attributes);
1093 container->n_attributes = n;
1094
1095 return 0;
1096 }
1097
1098 int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short type_id) {
1099 const NLType *nl_type;
1100 const NLTypeSystem *type_system;
1101 void *container;
1102 uint16_t type;
1103 size_t size;
1104 int r;
1105
1106 assert_return(m, -EINVAL);
1107 assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
1108
1109 r = type_system_get_type(m->containers[m->n_containers].type_system,
1110 &nl_type,
1111 type_id);
1112 if (r < 0)
1113 return r;
1114
1115 type = type_get_type(nl_type);
1116
1117 if (type == NETLINK_TYPE_NESTED) {
1118 r = type_system_get_type_system(m->containers[m->n_containers].type_system,
1119 &type_system,
1120 type_id);
1121 if (r < 0)
1122 return r;
1123 } else if (type == NETLINK_TYPE_UNION) {
1124 const NLTypeSystemUnion *type_system_union;
1125
1126 r = type_system_get_type_system_union(m->containers[m->n_containers].type_system,
1127 &type_system_union,
1128 type_id);
1129 if (r < 0)
1130 return r;
1131
1132 switch (type_system_union->match_type) {
1133 case NL_MATCH_SIBLING:
1134 {
1135 const char *key;
1136
1137 r = sd_netlink_message_read_string(m, type_system_union->match, &key);
1138 if (r < 0)
1139 return r;
1140
1141 r = type_system_union_get_type_system(type_system_union,
1142 &type_system,
1143 key);
1144 if (r < 0)
1145 return r;
1146
1147 break;
1148 }
1149 case NL_MATCH_PROTOCOL:
1150 {
1151 int family;
1152
1153 r = sd_rtnl_message_get_family(m, &family);
1154 if (r < 0)
1155 return r;
1156
1157 r = type_system_union_protocol_get_type_system(type_system_union,
1158 &type_system,
1159 family);
1160 if (r < 0)
1161 return r;
1162
1163 break;
1164 }
1165 default:
1166 assert_not_reached("sd-netlink: invalid type system union type");
1167 }
1168 } else
1169 return -EINVAL;
1170
1171 r = netlink_message_read_internal(m, type_id, &container, NULL);
1172 if (r < 0)
1173 return r;
1174
1175 size = (size_t) r;
1176 m->n_containers++;
1177
1178 r = netlink_container_parse(m,
1179 &m->containers[m->n_containers],
1180 container,
1181 size);
1182 if (r < 0) {
1183 m->n_containers--;
1184 return r;
1185 }
1186
1187 m->containers[m->n_containers].type_system = type_system;
1188
1189 return 0;
1190 }
1191
1192 int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id) {
1193 void *container;
1194 size_t size;
1195 int r;
1196
1197 assert_return(m, -EINVAL);
1198 assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
1199
1200 r = netlink_message_read_internal(m, type_id, &container, NULL);
1201 if (r < 0)
1202 return r;
1203
1204 size = (size_t) r;
1205 m->n_containers++;
1206
1207 r = netlink_container_parse(m,
1208 &m->containers[m->n_containers],
1209 container,
1210 size);
1211 if (r < 0) {
1212 m->n_containers--;
1213 return r;
1214 }
1215
1216 m->containers[m->n_containers].type_system = m->containers[m->n_containers - 1].type_system;
1217
1218 return 0;
1219 }
1220
1221 int sd_netlink_message_exit_container(sd_netlink_message *m) {
1222 assert_return(m, -EINVAL);
1223 assert_return(m->sealed, -EINVAL);
1224 assert_return(m->n_containers > 0, -EINVAL);
1225
1226 m->containers[m->n_containers].attributes = mfree(m->containers[m->n_containers].attributes);
1227 m->containers[m->n_containers].type_system = NULL;
1228
1229 m->n_containers--;
1230
1231 return 0;
1232 }
1233
1234 uint32_t rtnl_message_get_serial(sd_netlink_message *m) {
1235 assert(m);
1236 assert(m->hdr);
1237
1238 return m->hdr->nlmsg_seq;
1239 }
1240
1241 int sd_netlink_message_is_error(sd_netlink_message *m) {
1242 assert_return(m, 0);
1243 assert_return(m->hdr, 0);
1244
1245 return m->hdr->nlmsg_type == NLMSG_ERROR;
1246 }
1247
1248 int sd_netlink_message_get_errno(sd_netlink_message *m) {
1249 struct nlmsgerr *err;
1250
1251 assert_return(m, -EINVAL);
1252 assert_return(m->hdr, -EINVAL);
1253
1254 if (!sd_netlink_message_is_error(m))
1255 return 0;
1256
1257 err = NLMSG_DATA(m->hdr);
1258
1259 return err->error;
1260 }
1261
1262 static int netlink_message_parse_error(sd_netlink_message *m) {
1263 struct nlmsgerr *err = NLMSG_DATA(m->hdr);
1264 size_t hlen = sizeof(struct nlmsgerr);
1265
1266 /* no TLVs, nothing to do here */
1267 if (!(m->hdr->nlmsg_flags & NLM_F_ACK_TLVS))
1268 return 0;
1269
1270 /* if NLM_F_CAPPED is set then the inner err msg was capped */
1271 if (!(m->hdr->nlmsg_flags & NLM_F_CAPPED))
1272 hlen += err->msg.nlmsg_len - sizeof(struct nlmsghdr);
1273
1274 if (m->hdr->nlmsg_len <= NLMSG_SPACE(hlen))
1275 return 0;
1276
1277 return netlink_container_parse(m,
1278 &m->containers[m->n_containers],
1279 (struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + hlen),
1280 NLMSG_PAYLOAD(m->hdr, hlen));
1281 }
1282
1283 int sd_netlink_message_rewind(sd_netlink_message *m, sd_netlink *genl) {
1284 const NLType *nl_type;
1285 uint16_t type;
1286 size_t size;
1287 int r;
1288
1289 assert_return(m, -EINVAL);
1290 assert_return(genl || m->protocol != NETLINK_GENERIC, -EINVAL);
1291
1292 /* don't allow appending to message once parsed */
1293 if (!m->sealed)
1294 rtnl_message_seal(m);
1295
1296 for (unsigned i = 1; i <= m->n_containers; i++)
1297 m->containers[i].attributes = mfree(m->containers[i].attributes);
1298
1299 m->n_containers = 0;
1300
1301 if (m->containers[0].attributes)
1302 /* top-level attributes have already been parsed */
1303 return 0;
1304
1305 assert(m->hdr);
1306
1307 r = type_system_root_get_type(genl, &nl_type, m->hdr->nlmsg_type);
1308 if (r < 0)
1309 return r;
1310
1311 type = type_get_type(nl_type);
1312 size = type_get_size(nl_type);
1313
1314 if (type == NETLINK_TYPE_NESTED) {
1315 const NLTypeSystem *type_system;
1316
1317 type_get_type_system(nl_type, &type_system);
1318
1319 m->containers[0].type_system = type_system;
1320
1321 if (sd_netlink_message_is_error(m))
1322 r = netlink_message_parse_error(m);
1323 else
1324 r = netlink_container_parse(m,
1325 &m->containers[m->n_containers],
1326 (struct rtattr*)((uint8_t*) NLMSG_DATA(m->hdr) + NLMSG_ALIGN(size)),
1327 NLMSG_PAYLOAD(m->hdr, size));
1328 if (r < 0)
1329 return r;
1330 }
1331
1332 return 0;
1333 }
1334
1335 void rtnl_message_seal(sd_netlink_message *m) {
1336 assert(m);
1337 assert(!m->sealed);
1338
1339 m->sealed = true;
1340 }
1341
1342 sd_netlink_message *sd_netlink_message_next(sd_netlink_message *m) {
1343 assert_return(m, NULL);
1344
1345 return m->next;
1346 }