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