chiark / gitweb /
a5b09eddad79162f3db59f674d860062d321d52b
[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_EXCL;
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, message_length;
456         struct nlmsghdr *new_hdr;
457         struct rtattr *rta;
458         char *padding;
459         unsigned i;
460
461         assert(m);
462         assert(m->hdr);
463         assert(!m->sealed);
464         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
465         assert(!data || data_length > 0);
466         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
467
468         /* get the size of the new rta attribute (with padding at the end) */
469         rta_length = RTA_LENGTH(data_length);
470
471         /* get the new message size (with padding at the end) */
472         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
473
474         /* realloc to fit the new attribute */
475         new_hdr = realloc(m->hdr, message_length);
476         if (!new_hdr)
477                 return -ENOMEM;
478         m->hdr = new_hdr;
479
480         /* get pointer to the attribute we are about to add */
481         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
482
483         /* if we are inside containers, extend them */
484         for (i = 0; i < m->n_containers; i++)
485                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
486
487         /* fill in the attribute */
488         rta->rta_type = type;
489         rta->rta_len = rta_length;
490         if (!data) {
491                 //TODO: simply return this value rather than check for !data
492                 /* this is the start of a new container */
493                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
494         } else {
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                 /* make sure also the padding at the end of the message is initialized */
500                 memzero(padding,
501                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
502         }
503
504         /* update message size */
505         m->hdr->nlmsg_len = message_length;
506
507         return 0;
508 }
509
510 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
511         const NLType *type;
512         int r;
513
514         r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
515         if (r < 0)
516                 return r;
517
518         if (type->type != data_type)
519                 return -EINVAL;
520
521         return type->size;
522 }
523
524 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
525         size_t length, size;
526         int r;
527
528         assert_return(m, -EINVAL);
529         assert_return(!m->sealed, -EPERM);
530         assert_return(data, -EINVAL);
531
532         r = message_attribute_has_type(m, type, NLA_STRING);
533         if (r < 0)
534                 return r;
535         else
536                 size = (size_t)r;
537
538         if (size) {
539                 length = strnlen(data, size);
540                 if (length >= size)
541                         return -EINVAL;
542         } else
543                 length = strlen(data);
544
545         r = add_rtattr(m, type, data, length + 1);
546         if (r < 0)
547                 return r;
548
549         return 0;
550 }
551
552 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
553         int r;
554
555         assert_return(m, -EINVAL);
556         assert_return(!m->sealed, -EPERM);
557
558         r = message_attribute_has_type(m, type, NLA_U8);
559         if (r < 0)
560                 return r;
561
562         r = add_rtattr(m, type, &data, sizeof(uint8_t));
563         if (r < 0)
564                 return r;
565
566         return 0;
567 }
568
569
570 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
571         int r;
572
573         assert_return(m, -EINVAL);
574         assert_return(!m->sealed, -EPERM);
575
576         r = message_attribute_has_type(m, type, NLA_U16);
577         if (r < 0)
578                 return r;
579
580         r = add_rtattr(m, type, &data, sizeof(uint16_t));
581         if (r < 0)
582                 return r;
583
584         return 0;
585 }
586
587 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
588         int r;
589
590         assert_return(m, -EINVAL);
591         assert_return(!m->sealed, -EPERM);
592
593         r = message_attribute_has_type(m, type, NLA_U32);
594         if (r < 0)
595                 return r;
596
597         r = add_rtattr(m, type, &data, sizeof(uint32_t));
598         if (r < 0)
599                 return r;
600
601         return 0;
602 }
603
604 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
605         int r;
606
607         assert_return(m, -EINVAL);
608         assert_return(!m->sealed, -EPERM);
609         assert_return(data, -EINVAL);
610
611         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
612         if (r < 0)
613                 return r;
614
615         r = add_rtattr(m, type, data, sizeof(struct in_addr));
616         if (r < 0)
617                 return r;
618
619         return 0;
620 }
621
622 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
623         int r;
624
625         assert_return(m, -EINVAL);
626         assert_return(!m->sealed, -EPERM);
627         assert_return(data, -EINVAL);
628
629         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
630         if (r < 0)
631                 return r;
632
633         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
634         if (r < 0)
635                 return r;
636
637         return 0;
638 }
639
640 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
641         int r;
642
643         assert_return(m, -EINVAL);
644         assert_return(!m->sealed, -EPERM);
645         assert_return(data, -EINVAL);
646
647         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
648         if (r < 0)
649                 return r;
650
651         r = add_rtattr(m, type, data, ETH_ALEN);
652         if (r < 0)
653                 return r;
654
655         return 0;
656 }
657
658 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
659         int r;
660
661         assert_return(m, -EINVAL);
662         assert_return(!m->sealed, -EPERM);
663         assert_return(info, -EINVAL);
664
665         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
666         if (r < 0)
667                 return r;
668
669         r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
670         if (r < 0)
671                 return r;
672
673         return 0;
674 }
675
676 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
677         size_t size;
678         int r;
679
680         assert_return(m, -EINVAL);
681         assert_return(!m->sealed, -EPERM);
682
683         r = message_attribute_has_type(m, type, NLA_NESTED);
684         if (r < 0)
685                 return r;
686         else
687                 size = (size_t)r;
688
689         r = type_system_get_type_system(m->container_type_system[m->n_containers],
690                                         &m->container_type_system[m->n_containers + 1],
691                                         type);
692         if (r < 0)
693                 return r;
694
695         r = add_rtattr(m, type, NULL, size);
696         if (r < 0)
697                 return r;
698
699         return 0;
700 }
701
702 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
703         const NLTypeSystemUnion *type_system_union;
704         int r;
705
706         assert_return(m, -EINVAL);
707         assert_return(!m->sealed, -EPERM);
708
709         r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
710         if (r < 0)
711                 return r;
712
713         r = type_system_union_get_type_system(type_system_union,
714                                               &m->container_type_system[m->n_containers + 1],
715                                               key);
716         if (r < 0)
717                 return r;
718
719         r = sd_rtnl_message_append_string(m, type_system_union->match, key);
720         if (r < 0)
721                 return r;
722
723         /* do we evere need non-null size */
724         r = add_rtattr(m, type, NULL, 0);
725         if (r < 0)
726                 return r;
727
728         return 0;
729 }
730
731
732 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
733         assert_return(m, -EINVAL);
734         assert_return(!m->sealed, -EPERM);
735         assert_return(m->n_containers > 0, -EINVAL);
736
737         m->container_type_system[m->n_containers] = NULL;
738         m->n_containers --;
739
740         return 0;
741 }
742
743 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
744         struct rtattr *rta;
745
746         assert_return(m, -EINVAL);
747         assert_return(m->sealed, -EPERM);
748         assert_return(data, -EINVAL);
749         assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
750         assert(m->rta_offset_tb[m->n_containers]);
751         assert(type < m->rta_tb_size[m->n_containers]);
752
753         if(!m->rta_offset_tb[m->n_containers][type])
754                 return -ENODATA;
755
756         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
757
758         *data = RTA_DATA(rta);
759
760         return RTA_PAYLOAD(rta);
761 }
762
763 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
764         int r;
765         void *attr_data;
766
767         r = message_attribute_has_type(m, type, NLA_STRING);
768         if (r < 0)
769                 return r;
770
771         r = rtnl_message_read_internal(m, type, &attr_data);
772         if (r < 0)
773                 return r;
774         else if (strnlen(attr_data, r) >= (size_t) r)
775                 return -EIO;
776
777         *data = (char *) attr_data;
778
779         return 0;
780 }
781
782 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
783         int r;
784         void *attr_data;
785
786         r = message_attribute_has_type(m, type, NLA_U8);
787         if (r < 0)
788                 return r;
789
790         r = rtnl_message_read_internal(m, type, &attr_data);
791         if (r < 0)
792                 return r;
793         else if ((size_t) r < sizeof(uint8_t))
794                 return -EIO;
795
796         *data = *(uint8_t *) attr_data;
797
798         return 0;
799 }
800
801 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
802         int r;
803         void *attr_data;
804
805         r = message_attribute_has_type(m, type, NLA_U16);
806         if (r < 0)
807                 return r;
808
809         r = rtnl_message_read_internal(m, type, &attr_data);
810         if (r < 0)
811                 return r;
812         else if ((size_t) r < sizeof(uint16_t))
813                 return -EIO;
814
815         *data = *(uint16_t *) attr_data;
816
817         return 0;
818 }
819
820 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
821         int r;
822         void *attr_data;
823
824         r = message_attribute_has_type(m, type, NLA_U32);
825         if (r < 0)
826                 return r;
827
828         r = rtnl_message_read_internal(m, type, &attr_data);
829         if (r < 0)
830                 return r;
831         else if ((size_t)r < sizeof(uint32_t))
832                 return -EIO;
833
834         *data = *(uint32_t *) attr_data;
835
836         return 0;
837 }
838
839 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
840         int r;
841         void *attr_data;
842
843         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
844         if (r < 0)
845                 return r;
846
847         r = rtnl_message_read_internal(m, type, &attr_data);
848         if (r < 0)
849                 return r;
850         else if ((size_t)r < sizeof(struct ether_addr))
851                 return -EIO;
852
853         memcpy(data, attr_data, sizeof(struct ether_addr));
854
855         return 0;
856 }
857
858 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
859         int r;
860         void *attr_data;
861
862         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
863         if (r < 0)
864                 return r;
865
866         r = rtnl_message_read_internal(m, type, &attr_data);
867         if (r < 0)
868                 return r;
869         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
870                 return -EIO;
871
872         memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
873
874         return 0;
875 }
876
877 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
878         int r;
879         void *attr_data;
880
881         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
882         if (r < 0)
883                 return r;
884
885         r = rtnl_message_read_internal(m, type, &attr_data);
886         if (r < 0)
887                 return r;
888         else if ((size_t)r < sizeof(struct in_addr))
889                 return -EIO;
890
891         memcpy(data, attr_data, sizeof(struct in_addr));
892
893         return 0;
894 }
895
896 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
897         int r;
898         void *attr_data;
899
900         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
901         if (r < 0)
902                 return r;
903
904         r = rtnl_message_read_internal(m, type, &attr_data);
905         if (r < 0)
906                 return r;
907         else if ((size_t)r < sizeof(struct in6_addr))
908                 return -EIO;
909
910         memcpy(data, attr_data, sizeof(struct in6_addr));
911
912         return 0;
913 }
914
915 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
916         const NLType *nl_type;
917         const NLTypeSystem *type_system;
918         void *container;
919         size_t size;
920         int r;
921
922         assert_return(m, -EINVAL);
923         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
924
925         r = type_system_get_type(m->container_type_system[m->n_containers],
926                                  &nl_type,
927                                  type);
928         if (r < 0)
929                 return r;
930
931         if (nl_type->type == NLA_NESTED) {
932                 r = type_system_get_type_system(m->container_type_system[m->n_containers],
933                                                 &type_system,
934                                                 type);
935                 if (r < 0)
936                         return r;
937         } else if (nl_type->type == NLA_UNION) {
938                 const NLTypeSystemUnion *type_system_union;
939                 char *key;
940
941                 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
942                                                       &type_system_union,
943                                                       type);
944                 if (r < 0)
945                         return r;
946
947                 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
948                 if (r < 0)
949                         return r;
950
951                 r = type_system_union_get_type_system(type_system_union,
952                                                       &type_system,
953                                                       key);
954                 if (r < 0)
955                         return r;
956         } else
957                 return -EINVAL;
958
959         r = rtnl_message_read_internal(m, type, &container);
960         if (r < 0)
961                 return r;
962         else
963                 size = (size_t)r;
964
965         m->n_containers ++;
966
967         r = rtnl_message_parse(m,
968                                &m->rta_offset_tb[m->n_containers],
969                                &m->rta_tb_size[m->n_containers],
970                                type_system->max,
971                                container,
972                                size);
973         if (r < 0) {
974                 m->n_containers --;
975                 return r;
976         }
977
978         m->container_type_system[m->n_containers] = type_system;
979
980         return 0;
981 }
982
983 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
984         assert_return(m, -EINVAL);
985         assert_return(m->sealed, -EINVAL);
986         assert_return(m->n_containers > 0, -EINVAL);
987
988         free(m->rta_offset_tb[m->n_containers]);
989         m->rta_offset_tb[m->n_containers] = NULL;
990         m->container_type_system[m->n_containers] = NULL;
991
992         m->n_containers --;
993
994         return 0;
995 }
996
997 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
998         assert(m);
999         assert(m->hdr);
1000
1001         return m->hdr->nlmsg_seq;
1002 }
1003
1004 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1005         struct nlmsgerr *err;
1006
1007         assert_return(m, -EINVAL);
1008         assert_return(m->hdr, -EINVAL);
1009
1010         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1011                 return 0;
1012
1013         err = NLMSG_DATA(m->hdr);
1014
1015         return err->error;
1016 }
1017
1018 int rtnl_message_parse(sd_rtnl_message *m,
1019                        size_t **rta_offset_tb,
1020                        unsigned short *rta_tb_size,
1021                        int max,
1022                        struct rtattr *rta,
1023                        unsigned int rt_len) {
1024         unsigned short type;
1025         size_t *tb;
1026
1027         tb = new0(size_t, max + 1);
1028         if(!tb)
1029                 return -ENOMEM;
1030
1031         *rta_tb_size = max + 1;
1032
1033         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1034                 type = rta->rta_type;
1035
1036                 /* if the kernel is newer than the headers we used
1037                    when building, we ignore out-of-range attributes
1038                  */
1039                 if (type > max)
1040                         continue;
1041
1042                 if (tb[type])
1043                         log_debug("rtnl: message parse - overwriting repeated attribute");
1044
1045                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1046         }
1047
1048         *rta_offset_tb = tb;
1049
1050         return 0;
1051 }
1052
1053 /* returns the number of bytes sent, or a negative error code */
1054 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1055         union {
1056                 struct sockaddr sa;
1057                 struct sockaddr_nl nl;
1058         } addr = {
1059                 .nl.nl_family = AF_NETLINK,
1060         };
1061         ssize_t k;
1062
1063         assert(nl);
1064         assert(m);
1065         assert(m->hdr);
1066
1067         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1068                         0, &addr.sa, sizeof(addr));
1069         if (k < 0)
1070                 return (errno == EAGAIN) ? 0 : -errno;
1071
1072         return k;
1073 }
1074
1075 /* On success, the number of bytes received is returned and *ret points to the received message
1076  * which has a valid header and the correct size.
1077  * If nothing useful was received 0 is returned.
1078  * On failure, a negative error code is returned.
1079  */
1080 int socket_read_message(sd_rtnl *rtnl) {
1081         _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1082         uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
1083         struct iovec iov = {};
1084         struct msghdr msg = {
1085                 .msg_iov = &iov,
1086                 .msg_iovlen = 1,
1087                 .msg_control = cred_buffer,
1088                 .msg_controllen = sizeof(cred_buffer),
1089         };
1090         struct cmsghdr *cmsg;
1091         bool auth = false, multi_part = false, done = false;
1092         struct nlmsghdr *new_msg;
1093         size_t len;
1094         int r;
1095         unsigned i;
1096
1097         assert(rtnl);
1098         assert(rtnl->rbuffer);
1099         assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1100
1101         /* read nothing, just get the pending message size */
1102         r = recvmsg(rtnl->fd, &msg, MSG_PEEK | MSG_TRUNC);
1103         if (r < 0)
1104                 /* no data */
1105                 return (errno == EAGAIN) ? 0 : -errno;
1106         else if (r == 0)
1107                 /* connection was closed by the kernel */
1108                 return -ECONNRESET;
1109         else
1110                 len = (size_t)r;
1111
1112         /* make room for the pending message */
1113         if (!greedy_realloc((void **)&rtnl->rbuffer,
1114                             &rtnl->rbuffer_allocated,
1115                             len, sizeof(uint8_t)))
1116                 return -ENOMEM;
1117
1118         iov.iov_base = rtnl->rbuffer;
1119         iov.iov_len = rtnl->rbuffer_allocated;
1120
1121         r = recvmsg(rtnl->fd, &msg, MSG_TRUNC);
1122         if (r < 0)
1123                 /* no data */
1124                 return (errno == EAGAIN) ? 0 : -errno;
1125         else if (r == 0)
1126                 /* connection was closed by the kernel */
1127                 return -ECONNRESET;
1128         else
1129                 len = (size_t)r;
1130
1131         if (len > rtnl->rbuffer_allocated)
1132                 /* message did not fit in read buffer */
1133                 return -EIO;
1134
1135         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1136                 if (cmsg->cmsg_level == SOL_SOCKET &&
1137                     cmsg->cmsg_type == SCM_CREDENTIALS &&
1138                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1139                         struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1140
1141                         /* from the kernel */
1142                         if (ucred->uid == 0 && ucred->pid == 0) {
1143                                 auth = true;
1144                                 break;
1145                         }
1146                 }
1147         }
1148
1149         if (!auth)
1150                 /* not from the kernel, ignore */
1151                 return 0;
1152
1153         if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1154                 multi_part = true;
1155
1156                 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1157                         if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1158                             rtnl->rbuffer->nlmsg_seq) {
1159                                 first = rtnl->rqueue_partial[i];
1160                                 break;
1161                         }
1162                 }
1163         }
1164
1165         for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1166                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1167                 const NLType *nl_type;
1168
1169                 if (new_msg->nlmsg_pid && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1170                         /* not broadcast and not for us */
1171                         continue;
1172
1173                 if (new_msg->nlmsg_type == NLMSG_NOOP)
1174                         /* silently drop noop messages */
1175                         continue;
1176
1177                 if (new_msg->nlmsg_type == NLMSG_DONE) {
1178                         /* finished reading multi-part message */
1179                         done = true;
1180                         break;
1181                 }
1182
1183                 /* check that we support this message type */
1184                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1185                 if (r < 0) {
1186                         if (r == -ENOTSUP)
1187                                 log_debug("sd-rtnl: ignored message with unknown type: %u",
1188                                           new_msg->nlmsg_type);
1189
1190                         continue;
1191                 }
1192
1193                 /* check that the size matches the message type */
1194                 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1195                         continue;
1196
1197                 r = message_new_empty(rtnl, &m);
1198                 if (r < 0)
1199                         return r;
1200
1201                 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1202                 if (!m->hdr)
1203                         return -ENOMEM;
1204
1205                 /* seal and parse the top-level message */
1206                 r = sd_rtnl_message_rewind(m);
1207                 if (r < 0)
1208                         return r;
1209
1210                 /* push the message onto the multi-part message stack */
1211                 if (first)
1212                         m->next = first;
1213                 first = m;
1214                 m = NULL;
1215         }
1216
1217         if (len)
1218                 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1219
1220         if (!first)
1221                 return 0;
1222
1223         if (!multi_part || done) {
1224                 /* we got a complete message, push it on the read queue */
1225                 r = rtnl_rqueue_make_room(rtnl);
1226                 if (r < 0)
1227                         return r;
1228
1229                 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1230                 first = NULL;
1231
1232                 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1233                         /* remove the message form the partial read queue */
1234                         memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1235                                 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1236                         rtnl->rqueue_partial_size --;
1237                 }
1238
1239                 return 1;
1240         } else {
1241                 /* we only got a partial multi-part message, push it on the
1242                    partial read queue */
1243                 if (i < rtnl->rqueue_partial_size) {
1244                         rtnl->rqueue_partial[i] = first;
1245                 } else {
1246                         r = rtnl_rqueue_partial_make_room(rtnl);
1247                         if (r < 0)
1248                                 return r;
1249
1250                         rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1251                 }
1252                 first = NULL;
1253
1254                 return 0;
1255         }
1256 }
1257
1258 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1259         const NLType *type;
1260         unsigned i;
1261         int r;
1262
1263         assert_return(m, -EINVAL);
1264
1265         /* don't allow appending to message once parsed */
1266         if (!m->sealed)
1267                 rtnl_message_seal(m);
1268
1269         for (i = 1; i <= m->n_containers; i++) {
1270                 free(m->rta_offset_tb[i]);
1271                 m->rta_offset_tb[i] = NULL;
1272                 m->rta_tb_size[i] = 0;
1273                 m->container_type_system[i] = NULL;
1274         }
1275
1276         m->n_containers = 0;
1277
1278         if (m->rta_offset_tb[0]) {
1279                 /* top-level attributes have already been parsed */
1280                 return 0;
1281         }
1282
1283         assert(m->hdr);
1284
1285         r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1286         if (r < 0)
1287                 return r;
1288
1289         if (type->type == NLA_NESTED) {
1290                 const NLTypeSystem *type_system = type->type_system;
1291
1292                 assert(type_system);
1293
1294                 m->container_type_system[0] = type_system;
1295
1296                 r = rtnl_message_parse(m,
1297                                        &m->rta_offset_tb[m->n_containers],
1298                                        &m->rta_tb_size[m->n_containers],
1299                                        type_system->max,
1300                                        (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1301                                                         NLMSG_ALIGN(type->size)),
1302                                        NLMSG_PAYLOAD(m->hdr, type->size));
1303                 if (r < 0)
1304                         return r;
1305         }
1306
1307         return 0;
1308 }
1309
1310 void rtnl_message_seal(sd_rtnl_message *m) {
1311         assert(m);
1312         assert(!m->sealed);
1313
1314         m->sealed = true;
1315 }
1316
1317 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1318         assert_return(m, NULL);
1319
1320         return m->next;
1321 }