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