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