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