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