chiark / gitweb /
sd-rtnl: route - allow GETROUTE with AF_UNSPEC
[elogind.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
27 #include "util.h"
28 #include "refcnt.h"
29 #include "missing.h"
30
31 #include "sd-rtnl.h"
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.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 PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
38
39 #define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
40
41 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
42         sd_rtnl_message *m;
43
44         assert_return(ret, -EINVAL);
45
46         /* Note that 'rtnl' is curretly unused, if we start using it internally
47            we must take care to avoid problems due to mutual references between
48            busses and their queued messages. See sd-bus.
49          */
50
51         m = new0(sd_rtnl_message, 1);
52         if (!m)
53                 return -ENOMEM;
54
55         m->n_ref = REFCNT_INIT;
56
57         m->sealed = false;
58
59         *ret = m;
60
61         return 0;
62 }
63
64 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
65         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
66         const NLType *nl_type;
67         size_t size;
68         int r;
69
70         r = type_system_get_type(NULL, &nl_type, type);
71         if (r < 0)
72                 return r;
73
74         assert(nl_type->type == NLA_NESTED);
75
76         r = message_new_empty(rtnl, &m);
77         if (r < 0)
78                 return r;
79
80         size = NLMSG_SPACE(nl_type->size);
81
82         assert(size >= sizeof(struct nlmsghdr));
83         m->hdr = malloc0(size);
84         if (!m->hdr)
85                 return -ENOMEM;
86
87         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
88
89         m->container_type_system[0] = nl_type->type_system;
90         m->hdr->nlmsg_len = size;
91         m->hdr->nlmsg_type = type;
92
93         *ret = m;
94         m = NULL;
95
96         return 0;
97 }
98
99 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
100         struct rtmsg *rtm;
101
102         assert_return(m, -EINVAL);
103         assert_return(m->hdr, -EINVAL);
104         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
105
106         rtm = NLMSG_DATA(m->hdr);
107
108         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
109             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
110                 return -ERANGE;
111
112         rtm->rtm_dst_len = prefixlen;
113
114         return 0;
115 }
116
117 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
118         struct rtmsg *rtm;
119
120         assert_return(m, -EINVAL);
121         assert_return(m->hdr, -EINVAL);
122         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
123
124         rtm = NLMSG_DATA(m->hdr);
125
126         rtm->rtm_scope = scope;
127
128         return 0;
129 }
130
131 int sd_rtnl_message_route_get_family(sd_rtnl_message *m, int *family) {
132         struct rtmsg *rtm;
133
134         assert_return(m, -EINVAL);
135         assert_return(m->hdr, -EINVAL);
136         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
137         assert_return(family, -EINVAL);
138
139         rtm = NLMSG_DATA(m->hdr);
140
141         *family = rtm->rtm_family;
142
143         return 0;
144 }
145
146 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
147                               uint16_t nlmsg_type, int rtm_family,
148                               unsigned char rtm_protocol) {
149         struct rtmsg *rtm;
150         int r;
151
152         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
153         assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
154                       rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
155         assert_return(ret, -EINVAL);
156
157         r = message_new(rtnl, ret, nlmsg_type);
158         if (r < 0)
159                 return r;
160
161         if (nlmsg_type == RTM_NEWROUTE)
162                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
163
164         rtm = NLMSG_DATA((*ret)->hdr);
165
166         rtm->rtm_family = rtm_family;
167         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
168         rtm->rtm_type = RTN_UNICAST;
169         rtm->rtm_table = RT_TABLE_MAIN;
170         rtm->rtm_protocol = rtm_protocol;
171
172         return 0;
173 }
174
175 int sd_rtnl_message_neigh_get_family(sd_rtnl_message *m, int *family) {
176         struct ndmsg *ndm;
177
178         assert_return(m, -EINVAL);
179         assert_return(m->hdr, -EINVAL);
180         assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
181         assert_return(family, -EINVAL);
182
183         ndm = NLMSG_DATA(m->hdr);
184
185         *family = ndm->ndm_family;
186
187         return 0;
188 }
189
190 int sd_rtnl_message_neigh_get_ifindex(sd_rtnl_message *m, int *index) {
191         struct ndmsg *ndm;
192
193         assert_return(m, -EINVAL);
194         assert_return(m->hdr, -EINVAL);
195         assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
196         assert_return(index, -EINVAL);
197
198         ndm = NLMSG_DATA(m->hdr);
199
200         *index = ndm->ndm_ifindex;
201
202         return 0;
203 }
204
205 int sd_rtnl_message_new_neigh(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
206         struct ndmsg *ndm;
207         int r;
208
209         assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
210         assert_return(ndm_family == AF_INET || ndm_family == AF_INET6, -EINVAL);
211         assert_return(ret, -EINVAL);
212
213         r = message_new(rtnl, ret, nlmsg_type);
214         if (r < 0)
215                 return r;
216
217         if (nlmsg_type == RTM_NEWNEIGH)
218                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
219
220         ndm = NLMSG_DATA((*ret)->hdr);
221
222         ndm->ndm_family = ndm_family;
223         ndm->ndm_ifindex = index;
224
225         return 0;
226 }
227
228 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
229         struct ifinfomsg *ifi;
230
231         assert_return(m, -EINVAL);
232         assert_return(m->hdr, -EINVAL);
233         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
234         assert_return(change, -EINVAL);
235
236         ifi = NLMSG_DATA(m->hdr);
237
238         ifi->ifi_flags = flags;
239         ifi->ifi_change = change;
240
241         return 0;
242 }
243
244 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
245         struct ifinfomsg *ifi;
246
247         assert_return(m, -EINVAL);
248         assert_return(m->hdr, -EINVAL);
249         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
250
251         ifi = NLMSG_DATA(m->hdr);
252
253         ifi->ifi_type = type;
254
255         return 0;
256 }
257
258 int sd_rtnl_message_link_set_family(sd_rtnl_message *m, unsigned family) {
259         struct ifinfomsg *ifi;
260
261         assert_return(m, -EINVAL);
262         assert_return(m->hdr, -EINVAL);
263         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
264
265         ifi = NLMSG_DATA(m->hdr);
266
267         ifi->ifi_family = family;
268
269         return 0;
270 }
271
272 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
273                              uint16_t nlmsg_type, int index) {
274         struct ifinfomsg *ifi;
275         int r;
276
277         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
278         assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
279         assert_return(ret, -EINVAL);
280
281         r = message_new(rtnl, ret, nlmsg_type);
282         if (r < 0)
283                 return r;
284
285         if (nlmsg_type == RTM_NEWLINK)
286                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
287
288         ifi = NLMSG_DATA((*ret)->hdr);
289
290         ifi->ifi_family = AF_UNSPEC;
291         ifi->ifi_index = index;
292
293         return 0;
294 }
295
296 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
297         assert_return(m, -EINVAL);
298         assert_return(m->hdr, -EINVAL);
299         assert_return(m->hdr->nlmsg_type == RTM_GETLINK  ||
300                       m->hdr->nlmsg_type == RTM_GETADDR  ||
301                       m->hdr->nlmsg_type == RTM_GETROUTE ||
302                       m->hdr->nlmsg_type == RTM_GETNEIGH,
303                       -EINVAL);
304
305         if (dump)
306                 m->hdr->nlmsg_flags |= NLM_F_DUMP;
307         else
308                 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
309
310         return 0;
311 }
312
313 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
314         struct ifaddrmsg *ifa;
315
316         assert_return(m, -EINVAL);
317         assert_return(m->hdr, -EINVAL);
318         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
319
320         ifa = NLMSG_DATA(m->hdr);
321
322         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
323             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
324                 return -ERANGE;
325
326         ifa->ifa_prefixlen = prefixlen;
327
328         return 0;
329 }
330
331 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
332         struct ifaddrmsg *ifa;
333
334         assert_return(m, -EINVAL);
335         assert_return(m->hdr, -EINVAL);
336         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
337
338         ifa = NLMSG_DATA(m->hdr);
339
340         ifa->ifa_flags = flags;
341
342         return 0;
343 }
344
345 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
346         struct ifaddrmsg *ifa;
347
348         assert_return(m, -EINVAL);
349         assert_return(m->hdr, -EINVAL);
350         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
351
352         ifa = NLMSG_DATA(m->hdr);
353
354         ifa->ifa_scope = scope;
355
356         return 0;
357 }
358
359 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
360         struct ifaddrmsg *ifa;
361
362         assert_return(m, -EINVAL);
363         assert_return(m->hdr, -EINVAL);
364         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
365         assert_return(family, -EINVAL);
366
367         ifa = NLMSG_DATA(m->hdr);
368
369         *family = ifa->ifa_family;
370
371         return 0;
372 }
373
374 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
375         struct ifaddrmsg *ifa;
376
377         assert_return(m, -EINVAL);
378         assert_return(m->hdr, -EINVAL);
379         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
380         assert_return(prefixlen, -EINVAL);
381
382         ifa = NLMSG_DATA(m->hdr);
383
384         *prefixlen = ifa->ifa_prefixlen;
385
386         return 0;
387 }
388
389 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
390         struct ifaddrmsg *ifa;
391
392         assert_return(m, -EINVAL);
393         assert_return(m->hdr, -EINVAL);
394         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
395         assert_return(scope, -EINVAL);
396
397         ifa = NLMSG_DATA(m->hdr);
398
399         *scope = ifa->ifa_scope;
400
401         return 0;
402 }
403
404 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
405         struct ifaddrmsg *ifa;
406
407         assert_return(m, -EINVAL);
408         assert_return(m->hdr, -EINVAL);
409         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
410         assert_return(flags, -EINVAL);
411
412         ifa = NLMSG_DATA(m->hdr);
413
414         *flags = ifa->ifa_flags;
415
416         return 0;
417 }
418
419 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
420         struct ifaddrmsg *ifa;
421
422         assert_return(m, -EINVAL);
423         assert_return(m->hdr, -EINVAL);
424         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
425         assert_return(ifindex, -EINVAL);
426
427         ifa = NLMSG_DATA(m->hdr);
428
429         *ifindex = ifa->ifa_index;
430
431         return 0;
432 }
433
434 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
435                              uint16_t nlmsg_type, int index,
436                              int family) {
437         struct ifaddrmsg *ifa;
438         int r;
439
440         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
441         assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
442                       index > 0, -EINVAL);
443         assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
444                       family == AF_INET || family == AF_INET6, -EINVAL);
445         assert_return(ret, -EINVAL);
446
447         r = message_new(rtnl, ret, nlmsg_type);
448         if (r < 0)
449                 return r;
450
451         if (nlmsg_type == RTM_GETADDR)
452                 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
453
454         ifa = NLMSG_DATA((*ret)->hdr);
455
456         ifa->ifa_index = index;
457         ifa->ifa_family = family;
458         if (family == AF_INET)
459                 ifa->ifa_prefixlen = 32;
460         else if (family == AF_INET6)
461                 ifa->ifa_prefixlen = 128;
462
463         return 0;
464 }
465
466 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
467                              int index, int family) {
468         int r;
469
470         r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
471         if (r < 0)
472                 return r;
473
474         (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
475
476         return 0;
477 }
478
479 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
480         if (m)
481                 assert_se(REFCNT_INC(m->n_ref) >= 2);
482
483         return m;
484 }
485
486 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
487         if (m && REFCNT_DEC(m->n_ref) <= 0) {
488                 unsigned i;
489
490                 free(m->hdr);
491
492                 for (i = 0; i <= m->n_containers; i++)
493                         free(m->rta_offset_tb[i]);
494
495                 sd_rtnl_message_unref(m->next);
496
497                 free(m);
498         }
499
500         return NULL;
501 }
502
503 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
504         assert_return(m, -EINVAL);
505         assert_return(type, -EINVAL);
506
507         *type = m->hdr->nlmsg_type;
508
509         return 0;
510 }
511
512 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
513         assert_return(m, -EINVAL);
514
515         return !m->hdr->nlmsg_pid;
516 }
517
518 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
519         struct ifinfomsg *ifi;
520
521         assert_return(m, -EINVAL);
522         assert_return(m->hdr, -EINVAL);
523         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
524         assert_return(ifindex, -EINVAL);
525
526         ifi = NLMSG_DATA(m->hdr);
527
528         *ifindex = ifi->ifi_index;
529
530         return 0;
531 }
532
533 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
534         struct ifinfomsg *ifi;
535
536         assert_return(m, -EINVAL);
537         assert_return(m->hdr, -EINVAL);
538         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
539         assert_return(flags, -EINVAL);
540
541         ifi = NLMSG_DATA(m->hdr);
542
543         *flags = ifi->ifi_flags;
544
545         return 0;
546 }
547
548 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
549         struct ifinfomsg *ifi;
550
551         assert_return(m, -EINVAL);
552         assert_return(m->hdr, -EINVAL);
553         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
554         assert_return(type, -EINVAL);
555
556         ifi = NLMSG_DATA(m->hdr);
557
558         *type = ifi->ifi_type;
559
560         return 0;
561 }
562
563 /* If successful the updated message will be correctly aligned, if
564    unsuccessful the old message is untouched. */
565 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
566         uint32_t rta_length;
567         size_t message_length, padding_length;
568         struct nlmsghdr *new_hdr;
569         struct rtattr *rta;
570         char *padding;
571         unsigned i;
572         int offset;
573
574         assert(m);
575         assert(m->hdr);
576         assert(!m->sealed);
577         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
578         assert(!data || data_length);
579
580         /* get offset of the new attribute */
581         offset = m->hdr->nlmsg_len;
582
583         /* get the size of the new rta attribute (with padding at the end) */
584         rta_length = RTA_LENGTH(data_length);
585
586         /* get the new message size (with padding at the end) */
587         message_length = offset + RTA_ALIGN(rta_length);
588
589         /* realloc to fit the new attribute */
590         new_hdr = realloc(m->hdr, message_length);
591         if (!new_hdr)
592                 return -ENOMEM;
593         m->hdr = new_hdr;
594
595         /* get pointer to the attribute we are about to add */
596         rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
597
598         /* if we are inside containers, extend them */
599         for (i = 0; i < m->n_containers; i++)
600                 GET_CONTAINER(m, i)->rta_len += message_length - offset;
601
602         /* fill in the attribute */
603         rta->rta_type = type;
604         rta->rta_len = rta_length;
605         if (data)
606                 /* we don't deal with the case where the user lies about the type
607                  * and gives us too little data (so don't do that)
608                  */
609                 padding = mempcpy(RTA_DATA(rta), data, data_length);
610         else {
611                 /* if no data was passed, make sure we still initialize the padding
612                    note that we can have data_length > 0 (used by some containers) */
613                 padding = RTA_DATA(rta);
614         }
615
616         /* make sure also the padding at the end of the message is initialized */
617         padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
618         memzero(padding, padding_length);
619
620         /* update message size */
621         m->hdr->nlmsg_len = message_length;
622
623         return offset;
624 }
625
626 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
627         const NLType *type;
628         int r;
629
630         r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
631         if (r < 0)
632                 return r;
633
634         if (type->type != data_type)
635                 return -EINVAL;
636
637         return type->size;
638 }
639
640 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
641         size_t length, size;
642         int r;
643
644         assert_return(m, -EINVAL);
645         assert_return(!m->sealed, -EPERM);
646         assert_return(data, -EINVAL);
647
648         r = message_attribute_has_type(m, type, NLA_STRING);
649         if (r < 0)
650                 return r;
651         else
652                 size = (size_t)r;
653
654         if (size) {
655                 length = strnlen(data, size);
656                 if (length >= size)
657                         return -EINVAL;
658         } else
659                 length = strlen(data);
660
661         r = add_rtattr(m, type, data, length + 1);
662         if (r < 0)
663                 return r;
664
665         return 0;
666 }
667
668 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
669         int r;
670
671         assert_return(m, -EINVAL);
672         assert_return(!m->sealed, -EPERM);
673
674         r = message_attribute_has_type(m, type, NLA_U8);
675         if (r < 0)
676                 return r;
677
678         r = add_rtattr(m, type, &data, sizeof(uint8_t));
679         if (r < 0)
680                 return r;
681
682         return 0;
683 }
684
685
686 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
687         int r;
688
689         assert_return(m, -EINVAL);
690         assert_return(!m->sealed, -EPERM);
691
692         r = message_attribute_has_type(m, type, NLA_U16);
693         if (r < 0)
694                 return r;
695
696         r = add_rtattr(m, type, &data, sizeof(uint16_t));
697         if (r < 0)
698                 return r;
699
700         return 0;
701 }
702
703 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
704         int r;
705
706         assert_return(m, -EINVAL);
707         assert_return(!m->sealed, -EPERM);
708
709         r = message_attribute_has_type(m, type, NLA_U32);
710         if (r < 0)
711                 return r;
712
713         r = add_rtattr(m, type, &data, sizeof(uint32_t));
714         if (r < 0)
715                 return r;
716
717         return 0;
718 }
719
720 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
721         int r;
722
723         assert_return(m, -EINVAL);
724         assert_return(!m->sealed, -EPERM);
725         assert_return(data, -EINVAL);
726
727         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
728         if (r < 0)
729                 return r;
730
731         r = add_rtattr(m, type, data, sizeof(struct in_addr));
732         if (r < 0)
733                 return r;
734
735         return 0;
736 }
737
738 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
739         int r;
740
741         assert_return(m, -EINVAL);
742         assert_return(!m->sealed, -EPERM);
743         assert_return(data, -EINVAL);
744
745         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
746         if (r < 0)
747                 return r;
748
749         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
750         if (r < 0)
751                 return r;
752
753         return 0;
754 }
755
756 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
757         int r;
758
759         assert_return(m, -EINVAL);
760         assert_return(!m->sealed, -EPERM);
761         assert_return(data, -EINVAL);
762
763         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
764         if (r < 0)
765                 return r;
766
767         r = add_rtattr(m, type, data, ETH_ALEN);
768         if (r < 0)
769                 return r;
770
771         return 0;
772 }
773
774 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
775         int r;
776
777         assert_return(m, -EINVAL);
778         assert_return(!m->sealed, -EPERM);
779         assert_return(info, -EINVAL);
780
781         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
782         if (r < 0)
783                 return r;
784
785         r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
786         if (r < 0)
787                 return r;
788
789         return 0;
790 }
791
792 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
793         size_t size;
794         int r;
795
796         assert_return(m, -EINVAL);
797         assert_return(!m->sealed, -EPERM);
798         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
799
800         r = message_attribute_has_type(m, type, NLA_NESTED);
801         if (r < 0)
802                 return r;
803         else
804                 size = (size_t)r;
805
806         r = type_system_get_type_system(m->container_type_system[m->n_containers],
807                                         &m->container_type_system[m->n_containers + 1],
808                                         type);
809         if (r < 0)
810                 return r;
811
812         r = add_rtattr(m, type | NLA_F_NESTED, NULL, size);
813         if (r < 0)
814                 return r;
815
816         m->container_offsets[m->n_containers ++] = r;
817
818         return 0;
819 }
820
821 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
822         const NLTypeSystemUnion *type_system_union;
823         int r;
824
825         assert_return(m, -EINVAL);
826         assert_return(!m->sealed, -EPERM);
827
828         r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
829         if (r < 0)
830                 return r;
831
832         r = type_system_union_get_type_system(type_system_union,
833                                               &m->container_type_system[m->n_containers + 1],
834                                               key);
835         if (r < 0)
836                 return r;
837
838         r = sd_rtnl_message_append_string(m, type_system_union->match, key);
839         if (r < 0)
840                 return r;
841
842         /* do we evere need non-null size */
843         r = add_rtattr(m, type, NULL, 0);
844         if (r < 0)
845                 return r;
846
847         m->container_offsets[m->n_containers ++] = r;
848
849         return 0;
850 }
851
852
853 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
854         assert_return(m, -EINVAL);
855         assert_return(!m->sealed, -EPERM);
856         assert_return(m->n_containers > 0, -EINVAL);
857
858         m->container_type_system[m->n_containers] = NULL;
859         m->n_containers --;
860
861         return 0;
862 }
863
864 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
865         struct rtattr *rta;
866
867         assert_return(m, -EINVAL);
868         assert_return(m->sealed, -EPERM);
869         assert_return(data, -EINVAL);
870         assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
871         assert(m->rta_offset_tb[m->n_containers]);
872         assert(type < m->rta_tb_size[m->n_containers]);
873
874         if(!m->rta_offset_tb[m->n_containers][type])
875                 return -ENODATA;
876
877         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
878
879         *data = RTA_DATA(rta);
880
881         return RTA_PAYLOAD(rta);
882 }
883
884 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
885         int r;
886         void *attr_data;
887
888         assert_return(m, -EINVAL);
889
890         r = message_attribute_has_type(m, type, NLA_STRING);
891         if (r < 0)
892                 return r;
893
894         r = rtnl_message_read_internal(m, type, &attr_data);
895         if (r < 0)
896                 return r;
897         else if (strnlen(attr_data, r) >= (size_t) r)
898                 return -EIO;
899
900         if (data)
901                 *data = (const char *) attr_data;
902
903         return 0;
904 }
905
906 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
907         int r;
908         void *attr_data;
909
910         assert_return(m, -EINVAL);
911
912         r = message_attribute_has_type(m, type, NLA_U8);
913         if (r < 0)
914                 return r;
915
916         r = rtnl_message_read_internal(m, type, &attr_data);
917         if (r < 0)
918                 return r;
919         else if ((size_t) r < sizeof(uint8_t))
920                 return -EIO;
921
922         if (data)
923                 *data = *(uint8_t *) attr_data;
924
925         return 0;
926 }
927
928 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
929         int r;
930         void *attr_data;
931
932         assert_return(m, -EINVAL);
933
934         r = message_attribute_has_type(m, type, NLA_U16);
935         if (r < 0)
936                 return r;
937
938         r = rtnl_message_read_internal(m, type, &attr_data);
939         if (r < 0)
940                 return r;
941         else if ((size_t) r < sizeof(uint16_t))
942                 return -EIO;
943
944         if (data)
945                 *data = *(uint16_t *) attr_data;
946
947         return 0;
948 }
949
950 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
951         int r;
952         void *attr_data;
953
954         assert_return(m, -EINVAL);
955
956         r = message_attribute_has_type(m, type, NLA_U32);
957         if (r < 0)
958                 return r;
959
960         r = rtnl_message_read_internal(m, type, &attr_data);
961         if (r < 0)
962                 return r;
963         else if ((size_t)r < sizeof(uint32_t))
964                 return -EIO;
965
966         if (data)
967                 *data = *(uint32_t *) attr_data;
968
969         return 0;
970 }
971
972 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
973         int r;
974         void *attr_data;
975
976         assert_return(m, -EINVAL);
977
978         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
979         if (r < 0)
980                 return r;
981
982         r = rtnl_message_read_internal(m, type, &attr_data);
983         if (r < 0)
984                 return r;
985         else if ((size_t)r < sizeof(struct ether_addr))
986                 return -EIO;
987
988         if (data)
989                 memcpy(data, attr_data, sizeof(struct ether_addr));
990
991         return 0;
992 }
993
994 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
995         int r;
996         void *attr_data;
997
998         assert_return(m, -EINVAL);
999
1000         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
1001         if (r < 0)
1002                 return r;
1003
1004         r = rtnl_message_read_internal(m, type, &attr_data);
1005         if (r < 0)
1006                 return r;
1007         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
1008                 return -EIO;
1009
1010         if (info)
1011                 memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
1012
1013         return 0;
1014 }
1015
1016 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
1017         int r;
1018         void *attr_data;
1019
1020         assert_return(m, -EINVAL);
1021
1022         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1023         if (r < 0)
1024                 return r;
1025
1026         r = rtnl_message_read_internal(m, type, &attr_data);
1027         if (r < 0)
1028                 return r;
1029         else if ((size_t)r < sizeof(struct in_addr))
1030                 return -EIO;
1031
1032         if (data)
1033                 memcpy(data, attr_data, sizeof(struct in_addr));
1034
1035         return 0;
1036 }
1037
1038 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
1039         int r;
1040         void *attr_data;
1041
1042         assert_return(m, -EINVAL);
1043
1044         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
1045         if (r < 0)
1046                 return r;
1047
1048         r = rtnl_message_read_internal(m, type, &attr_data);
1049         if (r < 0)
1050                 return r;
1051         else if ((size_t)r < sizeof(struct in6_addr))
1052                 return -EIO;
1053
1054         if (data)
1055                 memcpy(data, attr_data, sizeof(struct in6_addr));
1056
1057         return 0;
1058 }
1059
1060 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
1061         const NLType *nl_type;
1062         const NLTypeSystem *type_system;
1063         void *container;
1064         size_t size;
1065         int r;
1066
1067         assert_return(m, -EINVAL);
1068         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
1069
1070         r = type_system_get_type(m->container_type_system[m->n_containers],
1071                                  &nl_type,
1072                                  type);
1073         if (r < 0)
1074                 return r;
1075
1076         if (nl_type->type == NLA_NESTED) {
1077                 r = type_system_get_type_system(m->container_type_system[m->n_containers],
1078                                                 &type_system,
1079                                                 type);
1080                 if (r < 0)
1081                         return r;
1082         } else if (nl_type->type == NLA_UNION) {
1083                 const NLTypeSystemUnion *type_system_union;
1084                 const char *key;
1085
1086                 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1087                                                       &type_system_union,
1088                                                       type);
1089                 if (r < 0)
1090                         return r;
1091
1092                 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1093                 if (r < 0)
1094                         return r;
1095
1096                 r = type_system_union_get_type_system(type_system_union,
1097                                                       &type_system,
1098                                                       key);
1099                 if (r < 0)
1100                         return r;
1101         } else
1102                 return -EINVAL;
1103
1104         r = rtnl_message_read_internal(m, type, &container);
1105         if (r < 0)
1106                 return r;
1107         else
1108                 size = (size_t)r;
1109
1110         m->n_containers ++;
1111
1112         r = rtnl_message_parse(m,
1113                                &m->rta_offset_tb[m->n_containers],
1114                                &m->rta_tb_size[m->n_containers],
1115                                type_system->max,
1116                                container,
1117                                size);
1118         if (r < 0) {
1119                 m->n_containers --;
1120                 return r;
1121         }
1122
1123         m->container_type_system[m->n_containers] = type_system;
1124
1125         return 0;
1126 }
1127
1128 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1129         assert_return(m, -EINVAL);
1130         assert_return(m->sealed, -EINVAL);
1131         assert_return(m->n_containers > 0, -EINVAL);
1132
1133         free(m->rta_offset_tb[m->n_containers]);
1134         m->rta_offset_tb[m->n_containers] = NULL;
1135         m->container_type_system[m->n_containers] = NULL;
1136
1137         m->n_containers --;
1138
1139         return 0;
1140 }
1141
1142 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1143         assert(m);
1144         assert(m->hdr);
1145
1146         return m->hdr->nlmsg_seq;
1147 }
1148
1149 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1150         struct nlmsgerr *err;
1151
1152         assert_return(m, -EINVAL);
1153         assert_return(m->hdr, -EINVAL);
1154
1155         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1156                 return 0;
1157
1158         err = NLMSG_DATA(m->hdr);
1159
1160         return err->error;
1161 }
1162
1163 int rtnl_message_parse(sd_rtnl_message *m,
1164                        size_t **rta_offset_tb,
1165                        unsigned short *rta_tb_size,
1166                        int max,
1167                        struct rtattr *rta,
1168                        unsigned int rt_len) {
1169         unsigned short type;
1170         size_t *tb;
1171
1172         tb = new0(size_t, max + 1);
1173         if(!tb)
1174                 return -ENOMEM;
1175
1176         *rta_tb_size = max + 1;
1177
1178         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1179                 type = RTA_TYPE(rta);
1180
1181                 /* if the kernel is newer than the headers we used
1182                    when building, we ignore out-of-range attributes
1183                  */
1184                 if (type > max)
1185                         continue;
1186
1187                 if (tb[type])
1188                         log_debug("rtnl: message parse - overwriting repeated attribute");
1189
1190                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1191         }
1192
1193         *rta_offset_tb = tb;
1194
1195         return 0;
1196 }
1197
1198 /* returns the number of bytes sent, or a negative error code */
1199 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1200         union {
1201                 struct sockaddr sa;
1202                 struct sockaddr_nl nl;
1203         } addr = {
1204                 .nl.nl_family = AF_NETLINK,
1205         };
1206         ssize_t k;
1207
1208         assert(nl);
1209         assert(m);
1210         assert(m->hdr);
1211
1212         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1213                         0, &addr.sa, sizeof(addr));
1214         if (k < 0)
1215                 return (errno == EAGAIN) ? 0 : -errno;
1216
1217         return k;
1218 }
1219
1220 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1221         uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1222                             CMSG_SPACE(sizeof(struct nl_pktinfo))];
1223         struct msghdr msg = {
1224                 .msg_iov = iov,
1225                 .msg_iovlen = 1,
1226                 .msg_control = cred_buffer,
1227                 .msg_controllen = sizeof(cred_buffer),
1228         };
1229         struct cmsghdr *cmsg;
1230         uint32_t group = 0;
1231         bool auth = false;
1232         int r;
1233
1234         assert(fd >= 0);
1235         assert(iov);
1236
1237         r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1238         if (r < 0) {
1239                 /* no data */
1240                 if (errno == ENOBUFS)
1241                         log_debug("rtnl: kernel receive buffer overrun");
1242
1243                 return (errno == EAGAIN) ? 0 : -errno;
1244         } else if (r == 0)
1245                 /* connection was closed by the kernel */
1246                 return -ECONNRESET;
1247
1248         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1249                 if (cmsg->cmsg_level == SOL_SOCKET &&
1250                     cmsg->cmsg_type == SCM_CREDENTIALS &&
1251                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1252                         struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1253
1254                         /* from the kernel */
1255                         if (ucred->uid == 0 && ucred->pid == 0)
1256                                 auth = true;
1257                 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1258                            cmsg->cmsg_type == NETLINK_PKTINFO &&
1259                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1260                         struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1261
1262                         /* multi-cast group */
1263                         group = pktinfo->group;
1264                 }
1265         }
1266
1267         if (!auth)
1268                 /* not from the kernel, ignore */
1269                 return 0;
1270
1271         if (group)
1272                 *_group = group;
1273
1274         return r;
1275 }
1276
1277 /* On success, the number of bytes received is returned and *ret points to the received message
1278  * which has a valid header and the correct size.
1279  * If nothing useful was received 0 is returned.
1280  * On failure, a negative error code is returned.
1281  */
1282 int socket_read_message(sd_rtnl *rtnl) {
1283         _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1284         struct iovec iov = {};
1285         uint32_t group = 0;
1286         bool multi_part = false, done = false;
1287         struct nlmsghdr *new_msg;
1288         size_t len;
1289         int r;
1290         unsigned i = 0;
1291
1292         assert(rtnl);
1293         assert(rtnl->rbuffer);
1294         assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1295
1296         /* read nothing, just get the pending message size */
1297         r = socket_recv_message(rtnl->fd, &iov, &group, true);
1298         if (r <= 0)
1299                 return r;
1300         else
1301                 len = (size_t)r;
1302
1303         /* make room for the pending message */
1304         if (!greedy_realloc((void **)&rtnl->rbuffer,
1305                             &rtnl->rbuffer_allocated,
1306                             len, sizeof(uint8_t)))
1307                 return -ENOMEM;
1308
1309         iov.iov_base = rtnl->rbuffer;
1310         iov.iov_len = rtnl->rbuffer_allocated;
1311
1312         /* read the pending message */
1313         r = socket_recv_message(rtnl->fd, &iov, &group, false);
1314         if (r <= 0)
1315                 return r;
1316         else
1317                 len = (size_t)r;
1318
1319         if (len > rtnl->rbuffer_allocated)
1320                 /* message did not fit in read buffer */
1321                 return -EIO;
1322
1323         if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1324                 multi_part = true;
1325
1326                 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1327                         if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1328                             rtnl->rbuffer->nlmsg_seq) {
1329                                 first = rtnl->rqueue_partial[i];
1330                                 break;
1331                         }
1332                 }
1333         }
1334
1335         for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1336                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1337                 const NLType *nl_type;
1338
1339                 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1340                         /* not broadcast and not for us */
1341                         continue;
1342
1343                 if (new_msg->nlmsg_type == NLMSG_NOOP)
1344                         /* silently drop noop messages */
1345                         continue;
1346
1347                 if (new_msg->nlmsg_type == NLMSG_DONE) {
1348                         /* finished reading multi-part message */
1349                         done = true;
1350                         break;
1351                 }
1352
1353                 /* check that we support this message type */
1354                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1355                 if (r < 0) {
1356                         if (r == -ENOTSUP)
1357                                 log_debug("sd-rtnl: ignored message with unknown type: %u",
1358                                           new_msg->nlmsg_type);
1359
1360                         continue;
1361                 }
1362
1363                 /* check that the size matches the message type */
1364                 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size)) {
1365                         log_debug("sd-rtnl: message larger than expected, dropping");
1366                         continue;
1367                 }
1368
1369                 r = message_new_empty(rtnl, &m);
1370                 if (r < 0)
1371                         return r;
1372
1373                 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1374                 if (!m->hdr)
1375                         return -ENOMEM;
1376
1377                 /* seal and parse the top-level message */
1378                 r = sd_rtnl_message_rewind(m);
1379                 if (r < 0)
1380                         return r;
1381
1382                 /* push the message onto the multi-part message stack */
1383                 if (first)
1384                         m->next = first;
1385                 first = m;
1386                 m = NULL;
1387         }
1388
1389         if (len)
1390                 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1391
1392         if (!first)
1393                 return 0;
1394
1395         if (!multi_part || done) {
1396                 /* we got a complete message, push it on the read queue */
1397                 r = rtnl_rqueue_make_room(rtnl);
1398                 if (r < 0)
1399                         return r;
1400
1401                 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1402                 first = NULL;
1403
1404                 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1405                         /* remove the message form the partial read queue */
1406                         memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1407                                 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1408                         rtnl->rqueue_partial_size --;
1409                 }
1410
1411                 return 1;
1412         } else {
1413                 /* we only got a partial multi-part message, push it on the
1414                    partial read queue */
1415                 if (i < rtnl->rqueue_partial_size) {
1416                         rtnl->rqueue_partial[i] = first;
1417                 } else {
1418                         r = rtnl_rqueue_partial_make_room(rtnl);
1419                         if (r < 0)
1420                                 return r;
1421
1422                         rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1423                 }
1424                 first = NULL;
1425
1426                 return 0;
1427         }
1428 }
1429
1430 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1431         const NLType *type;
1432         unsigned i;
1433         int r;
1434
1435         assert_return(m, -EINVAL);
1436
1437         /* don't allow appending to message once parsed */
1438         if (!m->sealed)
1439                 rtnl_message_seal(m);
1440
1441         for (i = 1; i <= m->n_containers; i++) {
1442                 free(m->rta_offset_tb[i]);
1443                 m->rta_offset_tb[i] = NULL;
1444                 m->rta_tb_size[i] = 0;
1445                 m->container_type_system[i] = NULL;
1446         }
1447
1448         m->n_containers = 0;
1449
1450         if (m->rta_offset_tb[0]) {
1451                 /* top-level attributes have already been parsed */
1452                 return 0;
1453         }
1454
1455         assert(m->hdr);
1456
1457         r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1458         if (r < 0)
1459                 return r;
1460
1461         if (type->type == NLA_NESTED) {
1462                 const NLTypeSystem *type_system = type->type_system;
1463
1464                 assert(type_system);
1465
1466                 m->container_type_system[0] = type_system;
1467
1468                 r = rtnl_message_parse(m,
1469                                        &m->rta_offset_tb[m->n_containers],
1470                                        &m->rta_tb_size[m->n_containers],
1471                                        type_system->max,
1472                                        (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1473                                                         NLMSG_ALIGN(type->size)),
1474                                        NLMSG_PAYLOAD(m->hdr, type->size));
1475                 if (r < 0)
1476                         return r;
1477         }
1478
1479         return 0;
1480 }
1481
1482 void rtnl_message_seal(sd_rtnl_message *m) {
1483         assert(m);
1484         assert(!m->sealed);
1485
1486         m->sealed = true;
1487 }
1488
1489 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1490         assert_return(m, NULL);
1491
1492         return m->next;
1493 }