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