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