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