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