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