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