]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-rtnl/rtnl-message.c
udev: persistent naming - we cannot use virtio numbers as they are not stable
[thirdparty/systemd.git] / src / libsystemd / sd-rtnl / rtnl-message.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <netinet/in.h>
23 #include <netinet/ether.h>
24 #include <stdbool.h>
25 #include <unistd.h>
26 #include <linux/veth.h>
27 #include <linux/if.h>
28 #include <linux/ip.h>
29 #include <linux/if_tunnel.h>
30 #include <linux/if_bridge.h>
31
32 #include "util.h"
33 #include "refcnt.h"
34 #include "missing.h"
35
36 #include "sd-rtnl.h"
37 #include "rtnl-util.h"
38 #include "rtnl-internal.h"
39
40 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
41 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
42
43 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, size_t initial_size) {
44 sd_rtnl_message *m;
45
46 assert_return(ret, -EINVAL);
47 assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
48
49 m = new0(sd_rtnl_message, 1);
50 if (!m)
51 return -ENOMEM;
52
53 m->hdr = malloc0(initial_size);
54 if (!m->hdr) {
55 free(m);
56 return -ENOMEM;
57 }
58
59 m->n_ref = REFCNT_INIT;
60
61 m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
62 m->sealed = false;
63
64 if (rtnl)
65 m->rtnl = sd_rtnl_ref(rtnl);
66
67 *ret = m;
68
69 return 0;
70 }
71
72 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
73 struct rtmsg *rtm;
74
75 assert_return(m, -EINVAL);
76 assert_return(m->hdr, -EINVAL);
77 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
78
79 rtm = NLMSG_DATA(m->hdr);
80
81 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
82 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
83 return -ERANGE;
84
85 rtm->rtm_dst_len = prefixlen;
86
87 return 0;
88 }
89
90 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
91 struct rtmsg *rtm;
92
93 assert_return(m, -EINVAL);
94 assert_return(m->hdr, -EINVAL);
95 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
96
97 rtm = NLMSG_DATA(m->hdr);
98
99 rtm->rtm_scope = scope;
100
101 return 0;
102 }
103
104 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
105 uint16_t nlmsg_type, unsigned char rtm_family) {
106 struct rtmsg *rtm;
107 int r;
108
109 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
110 assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
111 assert_return(ret, -EINVAL);
112
113 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
114 if (r < 0)
115 return r;
116
117 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
118 (*ret)->hdr->nlmsg_type = nlmsg_type;
119 if (nlmsg_type == RTM_NEWROUTE)
120 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
121
122 rtm = NLMSG_DATA((*ret)->hdr);
123
124 rtm->rtm_family = rtm_family;
125 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
126 rtm->rtm_type = RTN_UNICAST;
127 rtm->rtm_table = RT_TABLE_MAIN;
128 rtm->rtm_protocol = RTPROT_BOOT;
129
130 return 0;
131 }
132
133 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
134 struct ifinfomsg *ifi;
135
136 assert_return(m, -EINVAL);
137 assert_return(m->hdr, -EINVAL);
138 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
139 assert_return(change, -EINVAL);
140
141 ifi = NLMSG_DATA(m->hdr);
142
143 ifi->ifi_flags = flags;
144 ifi->ifi_change = change;
145
146 return 0;
147 }
148
149 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
150 struct ifinfomsg *ifi;
151
152 assert_return(m, -EINVAL);
153 assert_return(m->hdr, -EINVAL);
154 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
155
156 ifi = NLMSG_DATA(m->hdr);
157
158 ifi->ifi_type = type;
159
160 return 0;
161 }
162
163 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
164 uint16_t nlmsg_type, int index) {
165 struct ifinfomsg *ifi;
166 int r;
167
168 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
169 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
170 assert_return(ret, -EINVAL);
171
172 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
173 if (r < 0)
174 return r;
175
176 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
177 (*ret)->hdr->nlmsg_type = nlmsg_type;
178 if (nlmsg_type == RTM_NEWLINK)
179 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
180
181 ifi = NLMSG_DATA((*ret)->hdr);
182
183 ifi->ifi_family = AF_UNSPEC;
184 ifi->ifi_index = index;
185
186 return 0;
187 }
188
189 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
190 struct ifaddrmsg *ifa;
191
192 assert_return(m, -EINVAL);
193 assert_return(m->hdr, -EINVAL);
194 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
195
196 ifa = NLMSG_DATA(m->hdr);
197
198 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
199 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
200 return -ERANGE;
201
202 ifa->ifa_prefixlen = prefixlen;
203
204 return 0;
205 }
206
207 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
208 struct ifaddrmsg *ifa;
209
210 assert_return(m, -EINVAL);
211 assert_return(m->hdr, -EINVAL);
212 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
213
214 ifa = NLMSG_DATA(m->hdr);
215
216 ifa->ifa_flags = flags;
217
218 return 0;
219 }
220
221 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
222 struct ifaddrmsg *ifa;
223
224 assert_return(m, -EINVAL);
225 assert_return(m->hdr, -EINVAL);
226 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
227
228 ifa = NLMSG_DATA(m->hdr);
229
230 ifa->ifa_scope = scope;
231
232 return 0;
233 }
234
235 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
236 uint16_t nlmsg_type, int index,
237 unsigned char family) {
238 struct ifaddrmsg *ifa;
239 int r;
240
241 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
242 assert_return(index > 0, -EINVAL);
243 assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
244 assert_return(ret, -EINVAL);
245
246 r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
247 if (r < 0)
248 return r;
249
250 (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
251 (*ret)->hdr->nlmsg_type = nlmsg_type;
252 if (nlmsg_type == RTM_GETADDR && family == AF_INET)
253 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
254
255 ifa = NLMSG_DATA((*ret)->hdr);
256
257 ifa->ifa_index = index;
258 ifa->ifa_family = family;
259 if (family == AF_INET)
260 ifa->ifa_prefixlen = 32;
261 else if (family == AF_INET6)
262 ifa->ifa_prefixlen = 128;
263
264 return 0;
265 }
266
267 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
268 if (m)
269 assert_se(REFCNT_INC(m->n_ref) >= 2);
270
271 return m;
272 }
273
274 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
275 if (m && REFCNT_DEC(m->n_ref) <= 0) {
276 unsigned i;
277
278 sd_rtnl_unref(m->rtnl);
279 free(m->hdr);
280
281 for (i = 0; i < m->n_containers; i++)
282 free(m->rta_offset_tb[i]);
283
284 free(m);
285 }
286
287 return NULL;
288 }
289
290 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
291 assert_return(m, -EINVAL);
292 assert_return(type, -EINVAL);
293
294 *type = m->hdr->nlmsg_type;
295
296 return 0;
297 }
298
299 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
300 assert_return(m, -EINVAL);
301
302 return !m->hdr->nlmsg_pid;
303 }
304
305 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
306 struct ifinfomsg *ifi;
307
308 assert_return(m, -EINVAL);
309 assert_return(m->hdr, -EINVAL);
310 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
311 assert_return(ifindex, -EINVAL);
312
313 ifi = NLMSG_DATA(m->hdr);
314
315 *ifindex = ifi->ifi_index;
316
317 return 0;
318 }
319
320 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
321 struct ifinfomsg *ifi;
322
323 assert_return(m, -EINVAL);
324 assert_return(m->hdr, -EINVAL);
325 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
326 assert_return(flags, -EINVAL);
327
328 ifi = NLMSG_DATA(m->hdr);
329
330 *flags = ifi->ifi_flags;
331
332 return 0;
333 }
334
335 /* If successful the updated message will be correctly aligned, if
336 unsuccessful the old message is untouched. */
337 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
338 uint32_t rta_length, message_length;
339 struct nlmsghdr *new_hdr;
340 struct rtattr *rta;
341 char *padding;
342 unsigned i;
343
344 assert(m);
345 assert(m->hdr);
346 assert(!m->sealed);
347 assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
348 assert(!data || data_length > 0);
349 assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
350
351 /* get the size of the new rta attribute (with padding at the end) */
352 rta_length = RTA_LENGTH(data_length);
353
354 /* get the new message size (with padding at the end) */
355 message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
356
357 /* realloc to fit the new attribute */
358 new_hdr = realloc(m->hdr, message_length);
359 if (!new_hdr)
360 return -ENOMEM;
361 m->hdr = new_hdr;
362
363 /* get pointer to the attribute we are about to add */
364 rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
365
366 /* if we are inside containers, extend them */
367 for (i = 0; i < m->n_containers; i++)
368 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
369
370 /* fill in the attribute */
371 rta->rta_type = type;
372 rta->rta_len = rta_length;
373 if (!data) {
374 /* this is the start of a new container */
375 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
376 } else {
377 /* we don't deal with the case where the user lies about the type
378 * and gives us too little data (so don't do that)
379 */
380 padding = mempcpy(RTA_DATA(rta), data, data_length);
381 /* make sure also the padding at the end of the message is initialized */
382 memzero(padding,
383 (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
384 }
385
386 /* update message size */
387 m->hdr->nlmsg_len = message_length;
388
389 return 0;
390 }
391
392 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
393 uint16_t rtm_type;
394 int r;
395
396 assert_return(m, -EINVAL);
397 assert_return(!m->sealed, -EPERM);
398 assert_return(data, -EINVAL);
399
400 r = sd_rtnl_message_get_type(m, &rtm_type);
401 if (r < 0)
402 return r;
403
404 /* check that the type is correct */
405 switch (rtm_type) {
406 case RTM_NEWLINK:
407 case RTM_SETLINK:
408 case RTM_GETLINK:
409 case RTM_DELLINK:
410 if (m->n_containers == 1) {
411 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
412 type != IFLA_INFO_KIND)
413 return -ENOTSUP;
414 } else {
415 switch (type) {
416 case IFLA_IFNAME:
417 case IFLA_IFALIAS:
418 case IFLA_QDISC:
419 break;
420 default:
421 return -ENOTSUP;
422 }
423 }
424 break;
425 case RTM_NEWADDR:
426 case RTM_GETADDR:
427 case RTM_DELADDR:
428 if (type != IFA_LABEL)
429 return -ENOTSUP;
430 break;
431 default:
432 return -ENOTSUP;
433 }
434
435 r = add_rtattr(m, type, data, strlen(data) + 1);
436 if (r < 0)
437 return r;
438
439 return 0;
440 }
441
442 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
443 uint16_t rtm_type;
444 int r;
445
446 assert_return(m, -EINVAL);
447 assert_return(!m->sealed, -EPERM);
448
449 r = sd_rtnl_message_get_type(m, &rtm_type);
450 if (r < 0)
451 return r;
452
453 switch (rtm_type) {
454 case RTM_NEWLINK:
455 case RTM_SETLINK:
456 case RTM_GETLINK:
457 case RTM_DELLINK:
458 switch (type) {
459 case IFLA_CARRIER:
460 case IFLA_OPERSTATE:
461 case IFLA_LINKMODE:
462 case IFLA_IPTUN_TTL:
463 case IFLA_IPTUN_TOS:
464 case IFLA_IPTUN_PROTO:
465 case IFLA_IPTUN_PMTUDISC:
466 case IFLA_IPTUN_ENCAP_LIMIT:
467 case IFLA_GRE_TTL:
468 break;
469 default:
470 return -ENOTSUP;
471 }
472
473 break;
474 default:
475 return -ENOTSUP;
476 }
477
478 r = add_rtattr(m, type, &data, sizeof(uint8_t));
479 if (r < 0)
480 return r;
481
482 return 0;
483 }
484
485
486 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
487 uint16_t rtm_type;
488 int r;
489
490 assert_return(m, -EINVAL);
491 assert_return(!m->sealed, -EPERM);
492
493 r = sd_rtnl_message_get_type(m, &rtm_type);
494 if (r < 0)
495 return r;
496
497 /* check that the type is correct */
498 switch (rtm_type) {
499 case RTM_NEWLINK:
500 case RTM_SETLINK:
501 case RTM_GETLINK:
502 case RTM_DELLINK:
503 if (m->n_containers == 2 &&
504 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
505 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA) {
506 switch (type) {
507 case IFLA_VLAN_ID:
508 case IFLA_IPTUN_FLAGS:
509 case IFLA_GRE_IFLAGS:
510 case IFLA_GRE_OFLAGS:
511 case IFLA_IPTUN_6RD_PREFIXLEN:
512 case IFLA_IPTUN_6RD_RELAY_PREFIXLEN:
513 break;
514 default:
515 return -ENOTSUP;
516 }
517 } else
518 return -ENOTSUP;
519
520 break;
521 default:
522 return -ENOTSUP;
523 }
524
525 r = add_rtattr(m, type, &data, sizeof(uint16_t));
526 if (r < 0)
527 return r;
528
529 return 0;
530 }
531
532 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
533 uint16_t rtm_type;
534 int r;
535
536 assert_return(m, -EINVAL);
537 assert_return(!m->sealed, -EPERM);
538
539 r = sd_rtnl_message_get_type(m, &rtm_type);
540 if (r < 0)
541 return r;
542
543 /* check that the type is correct */
544 switch (rtm_type) {
545 case RTM_NEWLINK:
546 case RTM_SETLINK:
547 case RTM_GETLINK:
548 case RTM_DELLINK:
549 switch (type) {
550 case IFLA_MASTER:
551 case IFLA_MTU:
552 case IFLA_LINK:
553 case IFLA_GROUP:
554 case IFLA_TXQLEN:
555 case IFLA_WEIGHT:
556 case IFLA_NET_NS_FD:
557 case IFLA_NET_NS_PID:
558 case IFLA_PROMISCUITY:
559 case IFLA_NUM_TX_QUEUES:
560 case IFLA_NUM_RX_QUEUES:
561 case IFLA_IPTUN_LOCAL:
562 case IFLA_IPTUN_REMOTE:
563 case IFLA_MACVLAN_MODE:
564 case IFLA_IPTUN_FLAGS:
565 case IFLA_IPTUN_FLOWINFO:
566 case IFLA_GRE_FLOWINFO:
567 break;
568 default:
569 return -ENOTSUP;
570 }
571 break;
572 case RTM_NEWROUTE:
573 case RTM_GETROUTE:
574 case RTM_DELROUTE:
575 switch (type) {
576 case RTA_TABLE:
577 case RTA_PRIORITY:
578 case RTA_IIF:
579 case RTA_OIF:
580 case RTA_MARK:
581 break;
582 default:
583 return -ENOTSUP;
584 }
585 break;
586 default:
587 return -ENOTSUP;
588 }
589
590 r = add_rtattr(m, type, &data, sizeof(uint32_t));
591 if (r < 0)
592 return r;
593
594 return 0;
595 }
596
597 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
598 struct ifaddrmsg *ifa;
599 struct rtmsg *rtm;
600 uint16_t rtm_type;
601 int r;
602
603 assert_return(m, -EINVAL);
604 assert_return(!m->sealed, -EPERM);
605 assert_return(data, -EINVAL);
606
607 r = sd_rtnl_message_get_type(m, &rtm_type);
608 if (r < 0)
609 return r;
610
611 /* check that the type is correct */
612 switch (rtm_type) {
613 case RTM_NEWADDR:
614 case RTM_GETADDR:
615 case RTM_DELADDR:
616 switch (type) {
617 case IFA_ADDRESS:
618 case IFA_LOCAL:
619 case IFA_BROADCAST:
620 case IFA_ANYCAST:
621 case IFLA_GRE_LOCAL:
622 case IFLA_GRE_REMOTE:
623 ifa = NLMSG_DATA(m->hdr);
624
625 if (ifa->ifa_family != AF_INET)
626 return -EINVAL;
627
628 break;
629 default:
630 return -ENOTSUP;
631 }
632 break;
633 case RTM_NEWROUTE:
634 case RTM_GETROUTE:
635 case RTM_DELROUTE:
636 switch (type) {
637 case RTA_DST:
638 case RTA_SRC:
639 case RTA_GATEWAY:
640 rtm = NLMSG_DATA(m->hdr);
641
642 if (rtm->rtm_family != AF_INET)
643 return -EINVAL;
644
645 break;
646 default:
647 return -ENOTSUP;
648 }
649 break;
650 default:
651 return -ENOTSUP;
652 }
653
654 r = add_rtattr(m, type, data, sizeof(struct in_addr));
655 if (r < 0)
656 return r;
657
658 return 0;
659 }
660
661 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
662 struct ifaddrmsg *ifa;
663 struct rtmsg *rtm;
664 uint16_t rtm_type;
665 int r;
666
667 assert_return(m, -EINVAL);
668 assert_return(!m->sealed, -EPERM);
669 assert_return(data, -EINVAL);
670
671 r = sd_rtnl_message_get_type(m, &rtm_type);
672 if (r < 0)
673 return r;
674
675 /* check that the type is correct */
676 switch (rtm_type) {
677 case RTM_NEWADDR:
678 case RTM_GETADDR:
679 case RTM_DELADDR:
680 switch (type) {
681 case IFA_ADDRESS:
682 case IFA_LOCAL:
683 case IFA_BROADCAST:
684 case IFA_ANYCAST:
685 case IFLA_GRE_LOCAL:
686 case IFLA_GRE_REMOTE:
687 case IFLA_IPTUN_6RD_PREFIX:
688 ifa = NLMSG_DATA(m->hdr);
689
690 if (ifa->ifa_family != AF_INET6)
691 return -EINVAL;
692
693 break;
694 default:
695 return -ENOTSUP;
696 }
697 break;
698 case RTM_NEWROUTE:
699 case RTM_GETROUTE:
700 case RTM_DELROUTE:
701 switch (type) {
702 case RTA_DST:
703 case RTA_SRC:
704 case RTA_GATEWAY:
705 rtm = NLMSG_DATA(m->hdr);
706
707 if (rtm->rtm_family != AF_INET6)
708 return -EINVAL;
709
710 break;
711 default:
712 return -ENOTSUP;
713 }
714 default:
715 return -ENOTSUP;
716 }
717
718 r = add_rtattr(m, type, data, sizeof(struct in6_addr));
719 if (r < 0)
720 return r;
721
722 return 0;
723 }
724
725 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
726 uint16_t rtm_type;
727 int r;
728
729 assert_return(m, -EINVAL);
730 assert_return(!m->sealed, -EPERM);
731 assert_return(data, -EINVAL);
732
733 sd_rtnl_message_get_type(m, &rtm_type);
734
735 switch (rtm_type) {
736 case RTM_NEWLINK:
737 case RTM_SETLINK:
738 case RTM_DELLINK:
739 case RTM_GETLINK:
740 switch (type) {
741 case IFLA_ADDRESS:
742 case IFLA_BROADCAST:
743 break;
744 default:
745 return -ENOTSUP;
746 }
747 break;
748 default:
749 return -ENOTSUP;
750 }
751
752 r = add_rtattr(m, type, data, ETH_ALEN);
753 if (r < 0)
754 return r;
755
756 return 0;
757 }
758
759 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
760 uint16_t rtm_type;
761
762 assert_return(m, -EINVAL);
763 assert_return(!m->sealed, -EPERM);
764
765 sd_rtnl_message_get_type(m, &rtm_type);
766
767 if (rtnl_message_type_is_link(rtm_type)) {
768
769 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
770 (type == IFLA_INFO_DATA && m->n_containers == 1 &&
771 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
772 return add_rtattr(m, type, NULL, 0);
773 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
774 GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
775 GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
776 return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
777 }
778
779 return -ENOTSUP;
780 }
781
782 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
783 assert_return(m, -EINVAL);
784 assert_return(!m->sealed, -EPERM);
785 assert_return(m->n_containers > 0, -EINVAL);
786
787 m->n_containers --;
788
789 return 0;
790 }
791
792 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
793 struct rtattr *rta;
794
795 assert_return(m, -EINVAL);
796 assert_return(m->sealed, -EPERM);
797 assert_return(data, -EINVAL);
798 assert_return(m->rta_offset_tb[m->n_containers], -EINVAL);
799 assert_return(type < m->rta_tb_size[m->n_containers], -EINVAL);
800
801 if(!m->rta_offset_tb[m->n_containers][type])
802 return -ENODATA;
803
804 rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
805
806 *data = RTA_DATA(rta);
807
808 return RTA_PAYLOAD(rta);
809 }
810
811 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
812 int r;
813 void *attr_data;
814
815 assert_return(data, -EINVAL);
816
817 r = rtnl_message_read_internal(m, type, &attr_data);
818 if (r < 0)
819 return r;
820 else if (strnlen(attr_data, r) >= (size_t) r)
821 return -EIO;
822
823 *data = (char *) attr_data;
824
825 return 0;
826 }
827
828 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
829 int r;
830 void *attr_data;
831
832 assert_return(data, -EINVAL);
833
834 r = rtnl_message_read_internal(m, type, &attr_data);
835 if (r < 0)
836 return r;
837 else if ((size_t) r < sizeof(uint8_t))
838 return -EIO;
839
840 *data = *(uint8_t *) attr_data;
841
842 return 0;
843 }
844
845 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
846 int r;
847 void *attr_data;
848
849 assert_return(data, -EINVAL);
850
851 r = rtnl_message_read_internal(m, type, &attr_data);
852 if (r < 0)
853 return r;
854 else if ((size_t) r < sizeof(uint16_t))
855 return -EIO;
856
857 *data = *(uint16_t *) attr_data;
858
859 return 0;
860 }
861
862 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
863 int r;
864 void *attr_data;
865
866 assert_return(data, -EINVAL);
867
868 r = rtnl_message_read_internal(m, type, &attr_data);
869 if (r < 0)
870 return r;
871 else if ((size_t)r < sizeof(uint32_t))
872 return -EIO;
873
874 *data = *(uint32_t *) attr_data;
875
876 return 0;
877 }
878
879 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
880 int r;
881 void *attr_data;
882
883 assert_return(data, -EINVAL);
884
885 r = rtnl_message_read_internal(m, type, &attr_data);
886 if (r < 0)
887 return r;
888 else if ((size_t)r < sizeof(struct ether_addr))
889 return -EIO;
890
891 memcpy(data, attr_data, sizeof(struct ether_addr));
892
893 return 0;
894 }
895
896 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
897 int r;
898 void *attr_data;
899
900 assert_return(data, -EINVAL);
901
902 r = rtnl_message_read_internal(m, type, &attr_data);
903 if (r < 0)
904 return r;
905 else if ((size_t)r < sizeof(struct in_addr))
906 return -EIO;
907
908 memcpy(data, attr_data, sizeof(struct in_addr));
909
910 return 0;
911 }
912
913 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
914 int r;
915 void *attr_data;
916
917 assert_return(data, -EINVAL);
918
919 r = rtnl_message_read_internal(m, type, &attr_data);
920 if (r < 0)
921 return r;
922 else if ((size_t)r < sizeof(struct in6_addr))
923 return -EIO;
924
925 memcpy(data, attr_data, sizeof(struct in6_addr));
926
927 return 0;
928 }
929
930 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
931 uint16_t rtm_type;
932 unsigned short parent_type;
933 void *container;
934 size_t container_length;
935 int max, r;
936
937 assert_return(m, -EINVAL);
938 assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
939
940 r = rtnl_message_read_internal(m, type, &container);
941 if (r < 0)
942 return r;
943 else
944 container_length = r;
945
946 r = sd_rtnl_message_get_type(m, &rtm_type);
947 if (r < 0)
948 return r;
949
950 if (rtnl_message_type_is_link(rtm_type)) {
951 switch (m->n_containers) {
952 case 0:
953 switch (type) {
954 case IFLA_LINKINFO:
955 max = IFLA_INFO_MAX;
956 break;
957 default:
958 return -ENOTSUP;
959 }
960 break;
961 case 1:
962 parent_type = GET_CONTAINER(m, 0)->rta_type;
963 switch (parent_type) {
964 case IFLA_LINKINFO:
965 switch (type) {
966 case IFLA_INFO_DATA: {
967 char *kind;
968
969 r = sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &kind);
970 if (r < 0)
971 return r;
972
973 if (streq(kind, "vlan")) {
974 max = IFLA_VLAN_MAX;
975 } else if (streq(kind, "bridge")) {
976 max = IFLA_BRIDGE_MAX;
977 } else if (streq(kind, "veth")) {
978 max = VETH_INFO_MAX;
979 container = IFLA_RTA(container);
980 } else
981 return -ENOTSUP;
982
983 break;
984 }
985 default:
986 return -ENOTSUP;
987 }
988 break;
989 default:
990 return -ENOTSUP;
991 }
992 break;
993 default:
994 return -ENOTSUP;
995 }
996 } else
997 return -ENOTSUP;
998
999 r = rtnl_message_parse(m,
1000 &m->rta_offset_tb[m->n_containers + 1],
1001 &m->rta_tb_size[m->n_containers + 1],
1002 max,
1003 container,
1004 container_length);
1005 if (r < 0)
1006 return r;
1007
1008 m->n_containers ++;
1009
1010 return 0;
1011 }
1012
1013 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1014 assert_return(m, -EINVAL);
1015 assert_return(m->sealed, -EINVAL);
1016 assert_return(m->n_containers > 0, -EINVAL);
1017
1018 free(m->rta_offset_tb[m->n_containers]);
1019 m->rta_offset_tb[m->n_containers] = NULL;
1020
1021 m->n_containers --;
1022
1023 return 0;
1024 }
1025
1026 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1027 assert(m);
1028 assert(m->hdr);
1029
1030 return m->hdr->nlmsg_seq;
1031 }
1032
1033 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1034 struct nlmsgerr *err;
1035
1036 assert_return(m, -EINVAL);
1037 assert_return(m->hdr, -EINVAL);
1038
1039 if (m->hdr->nlmsg_type != NLMSG_ERROR)
1040 return 0;
1041
1042 err = NLMSG_DATA(m->hdr);
1043
1044 return err->error;
1045 }
1046
1047 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1048 assert(rtnl);
1049 assert(need);
1050
1051 /* ioctl(rtnl->fd, FIONREAD, &need)
1052 Does not appear to work on netlink sockets. libnl uses
1053 MSG_PEEK instead. I don't know if that is worth the
1054 extra roundtrip.
1055
1056 For now we simply use the maximum message size the kernel
1057 may use (NLMSG_GOODSIZE), and then realloc to the actual
1058 size after reading the message (hence avoiding huge memory
1059 usage in case many small messages are kept around) */
1060 *need = page_size();
1061 if (*need > 8192UL)
1062 *need = 8192UL;
1063
1064 return 0;
1065 }
1066
1067 int rtnl_message_parse(sd_rtnl_message *m,
1068 size_t **rta_offset_tb,
1069 unsigned short *rta_tb_size,
1070 int max,
1071 struct rtattr *rta,
1072 unsigned int rt_len) {
1073 unsigned short type;
1074 size_t *tb;
1075
1076 tb = (size_t *) new0(size_t *, max);
1077 if(!tb)
1078 return -ENOMEM;
1079
1080 *rta_tb_size = max;
1081
1082 for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1083 type = rta->rta_type;
1084
1085 if (type > max) {
1086 log_debug("rtnl: message parse - ignore out of range attribute type");
1087 continue;
1088 }
1089
1090 if (tb[type])
1091 log_debug("rtnl: message parse - overwriting repeated attribute");
1092
1093 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1094 }
1095
1096 *rta_offset_tb = tb;
1097
1098 return 0;
1099 }
1100
1101 /* returns the number of bytes sent, or a negative error code */
1102 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1103 union {
1104 struct sockaddr sa;
1105 struct sockaddr_nl nl;
1106 } addr = {
1107 .nl.nl_family = AF_NETLINK,
1108 };
1109 ssize_t k;
1110
1111 assert(nl);
1112 assert(m);
1113 assert(m->hdr);
1114
1115 k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1116 0, &addr.sa, sizeof(addr));
1117 if (k < 0)
1118 return (errno == EAGAIN) ? 0 : -errno;
1119
1120 return k;
1121 }
1122
1123 /* On success, the number of bytes received is returned and *ret points to the received message
1124 * which has a valid header and the correct size.
1125 * If nothing useful was received 0 is returned.
1126 * On failure, a negative error code is returned.
1127 */
1128 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1129 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1130 struct nlmsghdr *new_hdr;
1131 union {
1132 struct sockaddr sa;
1133 struct sockaddr_nl nl;
1134 } addr;
1135 socklen_t addr_len;
1136 size_t need, len;
1137 int r;
1138
1139 assert(nl);
1140 assert(ret);
1141
1142 r = message_receive_need(nl, &need);
1143 if (r < 0)
1144 return r;
1145
1146 r = message_new(nl, &m, need);
1147 if (r < 0)
1148 return r;
1149
1150 addr_len = sizeof(addr);
1151
1152 r = recvfrom(nl->fd, m->hdr, need,
1153 0, &addr.sa, &addr_len);
1154 if (r < 0)
1155 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1156 else if (r == 0)
1157 return -ECONNRESET; /* connection was closed by the kernel */
1158 else if (addr_len != sizeof(addr.nl) ||
1159 addr.nl.nl_family != AF_NETLINK)
1160 return -EIO; /* not a netlink message */
1161 else if (addr.nl.nl_pid != 0)
1162 return 0; /* not from the kernel */
1163 else if ((size_t) r < sizeof(struct nlmsghdr) ||
1164 (size_t) r < m->hdr->nlmsg_len)
1165 return -EIO; /* too small (we do accept too big though) */
1166 else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1167 return 0; /* not broadcast and not for us */
1168 else
1169 len = (size_t) r;
1170
1171 /* check that the size matches the message type */
1172 switch (m->hdr->nlmsg_type) {
1173
1174 case NLMSG_ERROR:
1175 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1176 return -EIO;
1177 break;
1178
1179 case RTM_NEWLINK:
1180 case RTM_SETLINK:
1181 case RTM_DELLINK:
1182 case RTM_GETLINK:
1183 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1184 return -EIO;
1185 break;
1186
1187 case RTM_NEWADDR:
1188 case RTM_DELADDR:
1189 case RTM_GETADDR:
1190 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1191 return -EIO;
1192 break;
1193 case RTM_NEWROUTE:
1194 case RTM_DELROUTE:
1195 case RTM_GETROUTE:
1196 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1197 return -EIO;
1198 break;
1199 case NLMSG_NOOP:
1200 return 0;
1201 default:
1202 log_debug("sd-rtnl: ignored message with unknown type");
1203 return 0;
1204 }
1205
1206 /* we probably allocated way too much memory, give it back */
1207 new_hdr = realloc(m->hdr, len);
1208 if (!new_hdr)
1209 return -ENOMEM;
1210 m->hdr = new_hdr;
1211
1212 /* seal and parse the top-level message */
1213 r = sd_rtnl_message_rewind(m);
1214 if (r < 0)
1215 return r;
1216
1217 *ret = m;
1218 m = NULL;
1219
1220 return len;
1221 }
1222
1223 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1224 struct ifinfomsg *ifi;
1225 struct ifaddrmsg *ifa;
1226 struct rtmsg *rtm;
1227 unsigned i;
1228 int r;
1229
1230 assert_return(m, -EINVAL);
1231 assert_return(m->hdr, -EINVAL);
1232
1233 /* don't allow appending to message once parsed */
1234 if (!m->sealed)
1235 rtnl_message_seal(m);
1236
1237 for (i = 1; i <= m->n_containers; i++) {
1238 free(m->rta_offset_tb[i]);
1239 m->rta_offset_tb[i] = NULL;
1240 m->rta_tb_size[i] = 0;
1241 }
1242
1243 m->n_containers = 0;
1244
1245 if (m->rta_offset_tb[0]) {
1246 /* top-level attributes have already been parsed */
1247 return 0;
1248 }
1249
1250 /* parse top-level attributes */
1251 switch(m->hdr->nlmsg_type) {
1252 case NLMSG_NOOP:
1253 case NLMSG_ERROR:
1254 break;
1255 case RTM_NEWLINK:
1256 case RTM_SETLINK:
1257 case RTM_GETLINK:
1258 case RTM_DELLINK:
1259 ifi = NLMSG_DATA(m->hdr);
1260
1261 r = rtnl_message_parse(m,
1262 &m->rta_offset_tb[0],
1263 &m->rta_tb_size[0],
1264 IFLA_MAX,
1265 IFLA_RTA(ifi),
1266 IFLA_PAYLOAD(m->hdr));
1267 if (r < 0)
1268 return r;
1269
1270 break;
1271 case RTM_NEWADDR:
1272 case RTM_GETADDR:
1273 case RTM_DELADDR:
1274 ifa = NLMSG_DATA(m->hdr);
1275
1276 r = rtnl_message_parse(m,
1277 &m->rta_offset_tb[0],
1278 &m->rta_tb_size[0],
1279 IFA_MAX,
1280 IFA_RTA(ifa),
1281 IFA_PAYLOAD(m->hdr));
1282 if (r < 0)
1283 return r;
1284
1285 break;
1286 case RTM_NEWROUTE:
1287 case RTM_GETROUTE:
1288 case RTM_DELROUTE:
1289 rtm = NLMSG_DATA(m->hdr);
1290
1291 r = rtnl_message_parse(m,
1292 &m->rta_offset_tb[0],
1293 &m->rta_tb_size[0],
1294 RTA_MAX,
1295 RTM_RTA(rtm),
1296 RTM_PAYLOAD(m->hdr));
1297
1298 break;
1299 default:
1300 return -ENOTSUP;
1301 }
1302
1303 return 0;
1304 }
1305
1306 void rtnl_message_seal(sd_rtnl_message *m) {
1307 assert(m);
1308 assert(!m->sealed);
1309
1310 m->sealed = true;
1311 }