chiark / gitweb /
networkd: smooth transition from ipv4ll to dhcp address
[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, size_t initial_size) {
46         sd_rtnl_message *m;
47
48         assert_return(ret, -EINVAL);
49         assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
50
51         /* Note that 'rtnl' is curretly unused, if we start using it internally
52            we must take care to avoid problems due to mutual references between
53            busses and their queued messages. See sd-bus.
54          */
55
56         m = new0(sd_rtnl_message, 1);
57         if (!m)
58                 return -ENOMEM;
59
60         m->hdr = malloc0(initial_size);
61         if (!m->hdr) {
62                 free(m);
63                 return -ENOMEM;
64         }
65
66         m->n_ref = REFCNT_INIT;
67
68         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
69         m->sealed = false;
70
71         *ret = m;
72
73         return 0;
74 }
75
76 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
77         const NLType *nl_type;
78         size_t size;
79         int r;
80
81         r = type_system_get_type(NULL, &nl_type, type);
82         if (r < 0)
83                 return r;
84
85         assert(nl_type->type == NLA_NESTED);
86
87         size = NLMSG_SPACE(nl_type->size);
88
89         r = message_new_empty(rtnl, ret, size);
90         if (r < 0)
91                 return r;
92
93         (*ret)->container_type_system[0] = nl_type->type_system;
94         (*ret)->hdr->nlmsg_len = size;
95         (*ret)->hdr->nlmsg_type = type;
96
97         return 0;
98 }
99
100 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
101         struct rtmsg *rtm;
102
103         assert_return(m, -EINVAL);
104         assert_return(m->hdr, -EINVAL);
105         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
106
107         rtm = NLMSG_DATA(m->hdr);
108
109         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
110             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
111                 return -ERANGE;
112
113         rtm->rtm_dst_len = prefixlen;
114
115         return 0;
116 }
117
118 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
119         struct rtmsg *rtm;
120
121         assert_return(m, -EINVAL);
122         assert_return(m->hdr, -EINVAL);
123         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
124
125         rtm = NLMSG_DATA(m->hdr);
126
127         rtm->rtm_scope = scope;
128
129         return 0;
130 }
131
132 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
133                               uint16_t nlmsg_type, unsigned char rtm_family) {
134         struct rtmsg *rtm;
135         int r;
136
137         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
138         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
139         assert_return(ret, -EINVAL);
140
141         r = message_new(rtnl, ret, nlmsg_type);
142         if (r < 0)
143                 return r;
144
145         if (nlmsg_type == RTM_NEWROUTE)
146                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
147
148         rtm = NLMSG_DATA((*ret)->hdr);
149
150         rtm->rtm_family = rtm_family;
151         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
152         rtm->rtm_type = RTN_UNICAST;
153         rtm->rtm_table = RT_TABLE_MAIN;
154         rtm->rtm_protocol = RTPROT_BOOT;
155
156         return 0;
157 }
158
159 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
160         struct ifinfomsg *ifi;
161
162         assert_return(m, -EINVAL);
163         assert_return(m->hdr, -EINVAL);
164         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
165         assert_return(change, -EINVAL);
166
167         ifi = NLMSG_DATA(m->hdr);
168
169         ifi->ifi_flags = flags;
170         ifi->ifi_change = change;
171
172         return 0;
173 }
174
175 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
176         struct ifinfomsg *ifi;
177
178         assert_return(m, -EINVAL);
179         assert_return(m->hdr, -EINVAL);
180         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
181
182         ifi = NLMSG_DATA(m->hdr);
183
184         ifi->ifi_type = type;
185
186         return 0;
187 }
188
189 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
190                              uint16_t nlmsg_type, int index) {
191         struct ifinfomsg *ifi;
192         int r;
193
194         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
195         assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
196         assert_return(ret, -EINVAL);
197
198         r = message_new(rtnl, ret, nlmsg_type);
199         if (r < 0)
200                 return r;
201
202         if (nlmsg_type == RTM_NEWLINK)
203                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
204
205         ifi = NLMSG_DATA((*ret)->hdr);
206
207         ifi->ifi_family = AF_UNSPEC;
208         ifi->ifi_index = index;
209
210         return 0;
211 }
212
213 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
214         struct ifaddrmsg *ifa;
215
216         assert_return(m, -EINVAL);
217         assert_return(m->hdr, -EINVAL);
218         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
219
220         ifa = NLMSG_DATA(m->hdr);
221
222         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
223             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
224                 return -ERANGE;
225
226         ifa->ifa_prefixlen = prefixlen;
227
228         return 0;
229 }
230
231 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
232         struct ifaddrmsg *ifa;
233
234         assert_return(m, -EINVAL);
235         assert_return(m->hdr, -EINVAL);
236         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
237
238         ifa = NLMSG_DATA(m->hdr);
239
240         ifa->ifa_flags = flags;
241
242         return 0;
243 }
244
245 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
246         struct ifaddrmsg *ifa;
247
248         assert_return(m, -EINVAL);
249         assert_return(m->hdr, -EINVAL);
250         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
251
252         ifa = NLMSG_DATA(m->hdr);
253
254         ifa->ifa_scope = scope;
255
256         return 0;
257 }
258
259 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
260                              uint16_t nlmsg_type, int index,
261                              unsigned char family) {
262         struct ifaddrmsg *ifa;
263         int r;
264
265         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
266         assert_return(index > 0, -EINVAL);
267         assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
268         assert_return(ret, -EINVAL);
269
270         r = message_new(rtnl, ret, nlmsg_type);
271         if (r < 0)
272                 return r;
273
274         if (nlmsg_type == RTM_GETADDR && family == AF_INET)
275                 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
276
277         ifa = NLMSG_DATA((*ret)->hdr);
278
279         ifa->ifa_index = index;
280         ifa->ifa_family = family;
281         if (family == AF_INET)
282                 ifa->ifa_prefixlen = 32;
283         else if (family == AF_INET6)
284                 ifa->ifa_prefixlen = 128;
285
286         return 0;
287 }
288
289 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
290                              int index, unsigned char family) {
291         int r;
292
293         r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
294         if (r < 0)
295                 return r;
296
297         (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
298
299         return 0;
300 }
301
302 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
303         if (m)
304                 assert_se(REFCNT_INC(m->n_ref) >= 2);
305
306         return m;
307 }
308
309 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
310         if (m && REFCNT_DEC(m->n_ref) <= 0) {
311                 unsigned i;
312
313                 free(m->hdr);
314
315                 for (i = 0; i <= m->n_containers; i++)
316                         free(m->rta_offset_tb[i]);
317
318                 free(m);
319         }
320
321         return NULL;
322 }
323
324 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
325         assert_return(m, -EINVAL);
326         assert_return(type, -EINVAL);
327
328         *type = m->hdr->nlmsg_type;
329
330         return 0;
331 }
332
333 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
334         assert_return(m, -EINVAL);
335
336         return !m->hdr->nlmsg_pid;
337 }
338
339 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
340         struct ifinfomsg *ifi;
341
342         assert_return(m, -EINVAL);
343         assert_return(m->hdr, -EINVAL);
344         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
345         assert_return(ifindex, -EINVAL);
346
347         ifi = NLMSG_DATA(m->hdr);
348
349         *ifindex = ifi->ifi_index;
350
351         return 0;
352 }
353
354 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
355         struct ifinfomsg *ifi;
356
357         assert_return(m, -EINVAL);
358         assert_return(m->hdr, -EINVAL);
359         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
360         assert_return(flags, -EINVAL);
361
362         ifi = NLMSG_DATA(m->hdr);
363
364         *flags = ifi->ifi_flags;
365
366         return 0;
367 }
368
369 /* If successful the updated message will be correctly aligned, if
370    unsuccessful the old message is untouched. */
371 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
372         uint32_t rta_length, message_length;
373         struct nlmsghdr *new_hdr;
374         struct rtattr *rta;
375         char *padding;
376         unsigned i;
377
378         assert(m);
379         assert(m->hdr);
380         assert(!m->sealed);
381         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
382         assert(!data || data_length > 0);
383         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
384
385         /* get the size of the new rta attribute (with padding at the end) */
386         rta_length = RTA_LENGTH(data_length);
387
388         /* get the new message size (with padding at the end) */
389         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
390
391         /* realloc to fit the new attribute */
392         new_hdr = realloc(m->hdr, message_length);
393         if (!new_hdr)
394                 return -ENOMEM;
395         m->hdr = new_hdr;
396
397         /* get pointer to the attribute we are about to add */
398         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
399
400         /* if we are inside containers, extend them */
401         for (i = 0; i < m->n_containers; i++)
402                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
403
404         /* fill in the attribute */
405         rta->rta_type = type;
406         rta->rta_len = rta_length;
407         if (!data) {
408                 //TODO: simply return this value rather than check for !data
409                 /* this is the start of a new container */
410                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
411         } else {
412                 /* we don't deal with the case where the user lies about the type
413                  * and gives us too little data (so don't do that)
414                 */
415                 padding = mempcpy(RTA_DATA(rta), data, data_length);
416                 /* make sure also the padding at the end of the message is initialized */
417                 memzero(padding,
418                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
419         }
420
421         /* update message size */
422         m->hdr->nlmsg_len = message_length;
423
424         return 0;
425 }
426
427 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
428         const NLType *type;
429         int r;
430
431         r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
432         if (r < 0)
433                 return r;
434
435         if (type->type != data_type)
436                 return -EINVAL;
437
438         return type->size;
439 }
440
441 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
442         size_t length, size;
443         int r;
444
445         assert_return(m, -EINVAL);
446         assert_return(!m->sealed, -EPERM);
447         assert_return(data, -EINVAL);
448
449         r = message_attribute_has_type(m, type, NLA_STRING);
450         if (r < 0)
451                 return r;
452         else
453                 size = (size_t)r;
454
455         if (size) {
456                 length = strnlen(data, size);
457                 if (length >= size)
458                         return -EINVAL;
459         } else
460                 length = strlen(data);
461
462         r = add_rtattr(m, type, data, length + 1);
463         if (r < 0)
464                 return r;
465
466         return 0;
467 }
468
469 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
470         int r;
471
472         assert_return(m, -EINVAL);
473         assert_return(!m->sealed, -EPERM);
474
475         r = message_attribute_has_type(m, type, NLA_U8);
476         if (r < 0)
477                 return r;
478
479         r = add_rtattr(m, type, &data, sizeof(uint8_t));
480         if (r < 0)
481                 return r;
482
483         return 0;
484 }
485
486
487 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
488         int r;
489
490         assert_return(m, -EINVAL);
491         assert_return(!m->sealed, -EPERM);
492
493         r = message_attribute_has_type(m, type, NLA_U16);
494         if (r < 0)
495                 return r;
496
497         r = add_rtattr(m, type, &data, sizeof(uint16_t));
498         if (r < 0)
499                 return r;
500
501         return 0;
502 }
503
504 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
505         int r;
506
507         assert_return(m, -EINVAL);
508         assert_return(!m->sealed, -EPERM);
509
510         r = message_attribute_has_type(m, type, NLA_U32);
511         if (r < 0)
512                 return r;
513
514         r = add_rtattr(m, type, &data, sizeof(uint32_t));
515         if (r < 0)
516                 return r;
517
518         return 0;
519 }
520
521 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
522         int r;
523
524         assert_return(m, -EINVAL);
525         assert_return(!m->sealed, -EPERM);
526         assert_return(data, -EINVAL);
527
528         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
529         if (r < 0)
530                 return r;
531
532         r = add_rtattr(m, type, data, sizeof(struct in_addr));
533         if (r < 0)
534                 return r;
535
536         return 0;
537 }
538
539 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
540         int r;
541
542         assert_return(m, -EINVAL);
543         assert_return(!m->sealed, -EPERM);
544         assert_return(data, -EINVAL);
545
546         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
547         if (r < 0)
548                 return r;
549
550         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
551         if (r < 0)
552                 return r;
553
554         return 0;
555 }
556
557 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
558         int r;
559
560         assert_return(m, -EINVAL);
561         assert_return(!m->sealed, -EPERM);
562         assert_return(data, -EINVAL);
563
564         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
565         if (r < 0)
566                 return r;
567
568         r = add_rtattr(m, type, data, ETH_ALEN);
569         if (r < 0)
570                 return r;
571
572         return 0;
573 }
574
575 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
576         int r;
577
578         assert_return(m, -EINVAL);
579         assert_return(!m->sealed, -EPERM);
580         assert_return(info, -EINVAL);
581
582         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
583         if (r < 0)
584                 return r;
585
586         r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
587         if (r < 0)
588                 return r;
589
590         return 0;
591 }
592
593 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
594         size_t size;
595         int r;
596
597         assert_return(m, -EINVAL);
598         assert_return(!m->sealed, -EPERM);
599
600         r = message_attribute_has_type(m, type, NLA_NESTED);
601         if (r < 0)
602                 return r;
603         else
604                 size = (size_t)r;
605
606         r = type_system_get_type_system(m->container_type_system[m->n_containers],
607                                         &m->container_type_system[m->n_containers + 1],
608                                         type);
609         if (r < 0)
610                 return r;
611
612         r = add_rtattr(m, type, NULL, size);
613         if (r < 0)
614                 return r;
615
616         return 0;
617 }
618
619 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
620         const NLTypeSystemUnion *type_system_union;
621         int r;
622
623         assert_return(m, -EINVAL);
624         assert_return(!m->sealed, -EPERM);
625
626         r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
627         if (r < 0)
628                 return r;
629
630         r = type_system_union_get_type_system(type_system_union,
631                                               &m->container_type_system[m->n_containers + 1],
632                                               key);
633         if (r < 0)
634                 return r;
635
636         r = sd_rtnl_message_append_string(m, type_system_union->match, key);
637         if (r < 0)
638                 return r;
639
640         /* do we evere need non-null size */
641         r = add_rtattr(m, type, NULL, 0);
642         if (r < 0)
643                 return r;
644
645         return 0;
646 }
647
648
649 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
650         assert_return(m, -EINVAL);
651         assert_return(!m->sealed, -EPERM);
652         assert_return(m->n_containers > 0, -EINVAL);
653
654         m->container_type_system[m->n_containers] = NULL;
655         m->n_containers --;
656
657         return 0;
658 }
659
660 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
661         struct rtattr *rta;
662
663         assert_return(m, -EINVAL);
664         assert_return(m->sealed, -EPERM);
665         assert_return(data, -EINVAL);
666         assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
667         assert(m->rta_offset_tb[m->n_containers]);
668         assert(type < m->rta_tb_size[m->n_containers]);
669
670         if(!m->rta_offset_tb[m->n_containers][type])
671                 return -ENODATA;
672
673         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
674
675         *data = RTA_DATA(rta);
676
677         return RTA_PAYLOAD(rta);
678 }
679
680 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
681         int r;
682         void *attr_data;
683
684         r = message_attribute_has_type(m, type, NLA_STRING);
685         if (r < 0)
686                 return r;
687
688         r = rtnl_message_read_internal(m, type, &attr_data);
689         if (r < 0)
690                 return r;
691         else if (strnlen(attr_data, r) >= (size_t) r)
692                 return -EIO;
693
694         *data = (char *) attr_data;
695
696         return 0;
697 }
698
699 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
700         int r;
701         void *attr_data;
702
703         r = message_attribute_has_type(m, type, NLA_U8);
704         if (r < 0)
705                 return r;
706
707         r = rtnl_message_read_internal(m, type, &attr_data);
708         if (r < 0)
709                 return r;
710         else if ((size_t) r < sizeof(uint8_t))
711                 return -EIO;
712
713         *data = *(uint8_t *) attr_data;
714
715         return 0;
716 }
717
718 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
719         int r;
720         void *attr_data;
721
722         r = message_attribute_has_type(m, type, NLA_U16);
723         if (r < 0)
724                 return r;
725
726         r = rtnl_message_read_internal(m, type, &attr_data);
727         if (r < 0)
728                 return r;
729         else if ((size_t) r < sizeof(uint16_t))
730                 return -EIO;
731
732         *data = *(uint16_t *) attr_data;
733
734         return 0;
735 }
736
737 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
738         int r;
739         void *attr_data;
740
741         r = message_attribute_has_type(m, type, NLA_U32);
742         if (r < 0)
743                 return r;
744
745         r = rtnl_message_read_internal(m, type, &attr_data);
746         if (r < 0)
747                 return r;
748         else if ((size_t)r < sizeof(uint32_t))
749                 return -EIO;
750
751         *data = *(uint32_t *) attr_data;
752
753         return 0;
754 }
755
756 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
757         int r;
758         void *attr_data;
759
760         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
761         if (r < 0)
762                 return r;
763
764         r = rtnl_message_read_internal(m, type, &attr_data);
765         if (r < 0)
766                 return r;
767         else if ((size_t)r < sizeof(struct ether_addr))
768                 return -EIO;
769
770         memcpy(data, attr_data, sizeof(struct ether_addr));
771
772         return 0;
773 }
774
775 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
776         int r;
777         void *attr_data;
778
779         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
780         if (r < 0)
781                 return r;
782
783         r = rtnl_message_read_internal(m, type, &attr_data);
784         if (r < 0)
785                 return r;
786         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
787                 return -EIO;
788
789         memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
790
791         return 0;
792 }
793
794 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
795         int r;
796         void *attr_data;
797
798         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
799         if (r < 0)
800                 return r;
801
802         r = rtnl_message_read_internal(m, type, &attr_data);
803         if (r < 0)
804                 return r;
805         else if ((size_t)r < sizeof(struct in_addr))
806                 return -EIO;
807
808         memcpy(data, attr_data, sizeof(struct in_addr));
809
810         return 0;
811 }
812
813 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
814         int r;
815         void *attr_data;
816
817         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
818         if (r < 0)
819                 return r;
820
821         r = rtnl_message_read_internal(m, type, &attr_data);
822         if (r < 0)
823                 return r;
824         else if ((size_t)r < sizeof(struct in6_addr))
825                 return -EIO;
826
827         memcpy(data, attr_data, sizeof(struct in6_addr));
828
829         return 0;
830 }
831
832 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
833         const NLType *nl_type;
834         const NLTypeSystem *type_system;
835         void *container;
836         size_t size;
837         int r;
838
839         assert_return(m, -EINVAL);
840         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
841
842         r = type_system_get_type(m->container_type_system[m->n_containers],
843                                  &nl_type,
844                                  type);
845         if (r < 0)
846                 return r;
847
848         if (nl_type->type == NLA_NESTED) {
849                 r = type_system_get_type_system(m->container_type_system[m->n_containers],
850                                                 &type_system,
851                                                 type);
852                 if (r < 0)
853                         return r;
854         } else if (nl_type->type == NLA_UNION) {
855                 const NLTypeSystemUnion *type_system_union;
856                 char *key;
857
858                 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
859                                                       &type_system_union,
860                                                       type);
861                 if (r < 0)
862                         return r;
863
864                 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
865                 if (r < 0)
866                         return r;
867
868                 r = type_system_union_get_type_system(type_system_union,
869                                                       &type_system,
870                                                       key);
871                 if (r < 0)
872                         return r;
873         } else
874                 return -EINVAL;
875
876         r = rtnl_message_read_internal(m, type, &container);
877         if (r < 0)
878                 return r;
879         else
880                 size = (size_t)r;
881
882         m->n_containers ++;
883
884         r = rtnl_message_parse(m,
885                                &m->rta_offset_tb[m->n_containers],
886                                &m->rta_tb_size[m->n_containers],
887                                type_system->max,
888                                container,
889                                size);
890         if (r < 0) {
891                 m->n_containers --;
892                 return r;
893         }
894
895         m->container_type_system[m->n_containers] = type_system;
896
897         return 0;
898 }
899
900 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
901         assert_return(m, -EINVAL);
902         assert_return(m->sealed, -EINVAL);
903         assert_return(m->n_containers > 0, -EINVAL);
904
905         free(m->rta_offset_tb[m->n_containers]);
906         m->rta_offset_tb[m->n_containers] = NULL;
907         m->container_type_system[m->n_containers] = NULL;
908
909         m->n_containers --;
910
911         return 0;
912 }
913
914 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
915         assert(m);
916         assert(m->hdr);
917
918         return m->hdr->nlmsg_seq;
919 }
920
921 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
922         struct nlmsgerr *err;
923
924         assert_return(m, -EINVAL);
925         assert_return(m->hdr, -EINVAL);
926
927         if (m->hdr->nlmsg_type != NLMSG_ERROR)
928                 return 0;
929
930         err = NLMSG_DATA(m->hdr);
931
932         return err->error;
933 }
934
935 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
936         assert(rtnl);
937         assert(need);
938
939         /* ioctl(rtnl->fd, FIONREAD, &need)
940            Does not appear to work on netlink sockets. libnl uses
941            MSG_PEEK instead. I don't know if that is worth the
942            extra roundtrip.
943
944            For now we simply use the maximum message size the kernel
945            may use (NLMSG_GOODSIZE), and then realloc to the actual
946            size after reading the message (hence avoiding huge memory
947            usage in case many small messages are kept around) */
948         *need = page_size();
949         if (*need > 8192UL)
950                 *need = 8192UL;
951
952         return 0;
953 }
954
955 int rtnl_message_parse(sd_rtnl_message *m,
956                        size_t **rta_offset_tb,
957                        unsigned short *rta_tb_size,
958                        int max,
959                        struct rtattr *rta,
960                        unsigned int rt_len) {
961         unsigned short type;
962         size_t *tb;
963
964         tb = new0(size_t, max + 1);
965         if(!tb)
966                 return -ENOMEM;
967
968         *rta_tb_size = max + 1;
969
970         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
971                 type = rta->rta_type;
972
973                 /* if the kernel is newer than the headers we used
974                    when building, we ignore out-of-range attributes
975                  */
976                 if (type > max)
977                         continue;
978
979                 if (tb[type])
980                         log_debug("rtnl: message parse - overwriting repeated attribute");
981
982                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
983         }
984
985         *rta_offset_tb = tb;
986
987         return 0;
988 }
989
990 /* returns the number of bytes sent, or a negative error code */
991 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
992         union {
993                 struct sockaddr sa;
994                 struct sockaddr_nl nl;
995         } addr = {
996                 .nl.nl_family = AF_NETLINK,
997         };
998         ssize_t k;
999
1000         assert(nl);
1001         assert(m);
1002         assert(m->hdr);
1003
1004         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1005                         0, &addr.sa, sizeof(addr));
1006         if (k < 0)
1007                 return (errno == EAGAIN) ? 0 : -errno;
1008
1009         return k;
1010 }
1011
1012 /* On success, the number of bytes received is returned and *ret points to the received message
1013  * which has a valid header and the correct size.
1014  * If nothing useful was received 0 is returned.
1015  * On failure, a negative error code is returned.
1016  */
1017 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1018         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1019         const NLType *nl_type;
1020         struct nlmsghdr *new_hdr;
1021         union {
1022                 struct sockaddr sa;
1023                 struct sockaddr_nl nl;
1024         } addr;
1025         socklen_t addr_len;
1026         size_t need, len;
1027         int r;
1028
1029         assert(nl);
1030         assert(ret);
1031
1032         r = message_receive_need(nl, &need);
1033         if (r < 0)
1034                 return r;
1035
1036         r = message_new_empty(nl, &m, need);
1037         if (r < 0)
1038                 return r;
1039
1040         addr_len = sizeof(addr);
1041
1042         r = recvfrom(nl->fd, m->hdr, need,
1043                         0, &addr.sa, &addr_len);
1044         if (r < 0)
1045                 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1046         else if (r == 0)
1047                 return -ECONNRESET; /* connection was closed by the kernel */
1048         else if (addr_len != sizeof(addr.nl) ||
1049                         addr.nl.nl_family != AF_NETLINK)
1050                 return -EIO; /* not a netlink message */
1051         else if (addr.nl.nl_pid != 0)
1052                 return 0; /* not from the kernel */
1053         else if ((size_t) r < sizeof(struct nlmsghdr) ||
1054                         (size_t) r < m->hdr->nlmsg_len)
1055                 return -EIO; /* too small (we do accept too big though) */
1056         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1057                 return 0; /* not broadcast and not for us */
1058         else
1059                 len = (size_t) r;
1060
1061         /* silently drop noop messages */
1062         if (m->hdr->nlmsg_type == NLMSG_NOOP)
1063                 return 0;
1064
1065         /* check that we support this message type */
1066         r = type_system_get_type(NULL, &nl_type, m->hdr->nlmsg_type);
1067         if (r < 0) {
1068                 if (r == -ENOTSUP)
1069                         log_debug("sd-rtnl: ignored message with unknown type: %u",
1070                                   m->hdr->nlmsg_type);
1071
1072                 return 0;
1073         }
1074
1075         /* check that the size matches the message type */
1076         if (len < NLMSG_LENGTH(nl_type->size))
1077                         return -EIO;
1078
1079         /* we probably allocated way too much memory, give it back */
1080         new_hdr = realloc(m->hdr, len);
1081         if (!new_hdr)
1082                 return -ENOMEM;
1083         m->hdr = new_hdr;
1084
1085         /* seal and parse the top-level message */
1086         r = sd_rtnl_message_rewind(m);
1087         if (r < 0)
1088                 return r;
1089
1090         *ret = m;
1091         m = NULL;
1092
1093         return len;
1094 }
1095
1096 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1097         const NLType *type;
1098         unsigned i;
1099         int r;
1100
1101         assert_return(m, -EINVAL);
1102
1103         /* don't allow appending to message once parsed */
1104         if (!m->sealed)
1105                 rtnl_message_seal(m);
1106
1107         for (i = 1; i <= m->n_containers; i++) {
1108                 free(m->rta_offset_tb[i]);
1109                 m->rta_offset_tb[i] = NULL;
1110                 m->rta_tb_size[i] = 0;
1111                 m->container_type_system[i] = NULL;
1112         }
1113
1114         m->n_containers = 0;
1115
1116         if (m->rta_offset_tb[0]) {
1117                 /* top-level attributes have already been parsed */
1118                 return 0;
1119         }
1120
1121         assert(m->hdr);
1122
1123         r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1124         if (r < 0)
1125                 return r;
1126
1127         if (type->type == NLA_NESTED) {
1128                 const NLTypeSystem *type_system = type->type_system;
1129
1130                 assert(type_system);
1131
1132                 m->container_type_system[0] = type_system;
1133
1134                 r = rtnl_message_parse(m,
1135                                        &m->rta_offset_tb[m->n_containers],
1136                                        &m->rta_tb_size[m->n_containers],
1137                                        type_system->max,
1138                                        (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1139                                                         NLMSG_ALIGN(type->size)),
1140                                        NLMSG_PAYLOAD(m->hdr, type->size));
1141                 if (r < 0)
1142                         return r;
1143         }
1144
1145         return 0;
1146 }
1147
1148 void rtnl_message_seal(sd_rtnl_message *m) {
1149         assert(m);
1150         assert(!m->sealed);
1151
1152         m->sealed = true;
1153 }