chiark / gitweb /
sd-rtnl: rtnl-message: remove unneeded linux includes
[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
27 #include "util.h"
28 #include "refcnt.h"
29 #include "missing.h"
30
31 #include "sd-rtnl.h"
32 #include "rtnl-util.h"
33 #include "rtnl-internal.h"
34 #include "rtnl-types.h"
35
36 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
37 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
38
39 static int message_new_empty(sd_rtnl *rtnl, sd_rtnl_message **ret) {
40         sd_rtnl_message *m;
41
42         assert_return(ret, -EINVAL);
43
44         /* Note that 'rtnl' is curretly unused, if we start using it internally
45            we must take care to avoid problems due to mutual references between
46            busses and their queued messages. See sd-bus.
47          */
48
49         m = new0(sd_rtnl_message, 1);
50         if (!m)
51                 return -ENOMEM;
52
53         m->n_ref = REFCNT_INIT;
54
55         m->sealed = false;
56
57         *ret = m;
58
59         return 0;
60 }
61
62 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, uint16_t type) {
63         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
64         const NLType *nl_type;
65         size_t size;
66         int r;
67
68         r = type_system_get_type(NULL, &nl_type, type);
69         if (r < 0)
70                 return r;
71
72         assert(nl_type->type == NLA_NESTED);
73
74         r = message_new_empty(rtnl, &m);
75         if (r < 0)
76                 return r;
77
78         size = NLMSG_SPACE(nl_type->size);
79
80         assert(size >= sizeof(struct nlmsghdr));
81         m->hdr = malloc0(size);
82         if (!m->hdr)
83                 return -ENOMEM;
84
85         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
86
87         m->container_type_system[0] = nl_type->type_system;
88         m->hdr->nlmsg_len = size;
89         m->hdr->nlmsg_type = type;
90
91         *ret = m;
92         m = NULL;
93
94         return 0;
95 }
96
97 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
98         struct rtmsg *rtm;
99
100         assert_return(m, -EINVAL);
101         assert_return(m->hdr, -EINVAL);
102         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
103
104         rtm = NLMSG_DATA(m->hdr);
105
106         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
107             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
108                 return -ERANGE;
109
110         rtm->rtm_dst_len = prefixlen;
111
112         return 0;
113 }
114
115 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
116         struct rtmsg *rtm;
117
118         assert_return(m, -EINVAL);
119         assert_return(m->hdr, -EINVAL);
120         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
121
122         rtm = NLMSG_DATA(m->hdr);
123
124         rtm->rtm_scope = scope;
125
126         return 0;
127 }
128
129 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
130                               uint16_t nlmsg_type, int rtm_family,
131                               unsigned char rtm_protocol) {
132         struct rtmsg *rtm;
133         int r;
134
135         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
136         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
137         assert_return(ret, -EINVAL);
138
139         r = message_new(rtnl, ret, nlmsg_type);
140         if (r < 0)
141                 return r;
142
143         if (nlmsg_type == RTM_NEWROUTE)
144                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
145
146         rtm = NLMSG_DATA((*ret)->hdr);
147
148         rtm->rtm_family = rtm_family;
149         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
150         rtm->rtm_type = RTN_UNICAST;
151         rtm->rtm_table = RT_TABLE_MAIN;
152         rtm->rtm_protocol = rtm_protocol;
153
154         return 0;
155 }
156
157 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
158         struct ifinfomsg *ifi;
159
160         assert_return(m, -EINVAL);
161         assert_return(m->hdr, -EINVAL);
162         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
163         assert_return(change, -EINVAL);
164
165         ifi = NLMSG_DATA(m->hdr);
166
167         ifi->ifi_flags = flags;
168         ifi->ifi_change = change;
169
170         return 0;
171 }
172
173 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
174         struct ifinfomsg *ifi;
175
176         assert_return(m, -EINVAL);
177         assert_return(m->hdr, -EINVAL);
178         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
179
180         ifi = NLMSG_DATA(m->hdr);
181
182         ifi->ifi_type = type;
183
184         return 0;
185 }
186
187 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
188                              uint16_t nlmsg_type, int index) {
189         struct ifinfomsg *ifi;
190         int r;
191
192         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
193         assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
194         assert_return(ret, -EINVAL);
195
196         r = message_new(rtnl, ret, nlmsg_type);
197         if (r < 0)
198                 return r;
199
200         if (nlmsg_type == RTM_NEWLINK)
201                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
202
203         ifi = NLMSG_DATA((*ret)->hdr);
204
205         ifi->ifi_family = AF_UNSPEC;
206         ifi->ifi_index = index;
207
208         return 0;
209 }
210
211 int sd_rtnl_message_request_dump(sd_rtnl_message *m, int dump) {
212         assert_return(m, -EINVAL);
213         assert_return(m->hdr, -EINVAL);
214         assert_return(m->hdr->nlmsg_type == RTM_GETLINK ||
215                       m->hdr->nlmsg_type == RTM_GETADDR ||
216                       m->hdr->nlmsg_type == RTM_GETROUTE,
217                       -EINVAL);
218
219         if (dump)
220                 m->hdr->nlmsg_flags |= NLM_F_DUMP;
221         else
222                 m->hdr->nlmsg_flags &= ~NLM_F_DUMP;
223
224         return 0;
225 }
226
227 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
228         struct ifaddrmsg *ifa;
229
230         assert_return(m, -EINVAL);
231         assert_return(m->hdr, -EINVAL);
232         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
233
234         ifa = NLMSG_DATA(m->hdr);
235
236         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
237             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
238                 return -ERANGE;
239
240         ifa->ifa_prefixlen = prefixlen;
241
242         return 0;
243 }
244
245 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
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_flags = flags;
255
256         return 0;
257 }
258
259 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
260         struct ifaddrmsg *ifa;
261
262         assert_return(m, -EINVAL);
263         assert_return(m->hdr, -EINVAL);
264         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
265
266         ifa = NLMSG_DATA(m->hdr);
267
268         ifa->ifa_scope = scope;
269
270         return 0;
271 }
272
273 int sd_rtnl_message_addr_get_family(sd_rtnl_message *m, int *family) {
274         struct ifaddrmsg *ifa;
275
276         assert_return(m, -EINVAL);
277         assert_return(m->hdr, -EINVAL);
278         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
279         assert_return(family, -EINVAL);
280
281         ifa = NLMSG_DATA(m->hdr);
282
283         *family = ifa->ifa_family;
284
285         return 0;
286 }
287
288 int sd_rtnl_message_addr_get_prefixlen(sd_rtnl_message *m, unsigned char *prefixlen) {
289         struct ifaddrmsg *ifa;
290
291         assert_return(m, -EINVAL);
292         assert_return(m->hdr, -EINVAL);
293         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
294         assert_return(prefixlen, -EINVAL);
295
296         ifa = NLMSG_DATA(m->hdr);
297
298         *prefixlen = ifa->ifa_prefixlen;
299
300         return 0;
301 }
302
303 int sd_rtnl_message_addr_get_scope(sd_rtnl_message *m, unsigned char *scope) {
304         struct ifaddrmsg *ifa;
305
306         assert_return(m, -EINVAL);
307         assert_return(m->hdr, -EINVAL);
308         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
309         assert_return(scope, -EINVAL);
310
311         ifa = NLMSG_DATA(m->hdr);
312
313         *scope = ifa->ifa_scope;
314
315         return 0;
316 }
317
318 int sd_rtnl_message_addr_get_flags(sd_rtnl_message *m, unsigned char *flags) {
319         struct ifaddrmsg *ifa;
320
321         assert_return(m, -EINVAL);
322         assert_return(m->hdr, -EINVAL);
323         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
324         assert_return(flags, -EINVAL);
325
326         ifa = NLMSG_DATA(m->hdr);
327
328         *flags = ifa->ifa_flags;
329
330         return 0;
331 }
332
333 int sd_rtnl_message_addr_get_ifindex(sd_rtnl_message *m, int *ifindex) {
334         struct ifaddrmsg *ifa;
335
336         assert_return(m, -EINVAL);
337         assert_return(m->hdr, -EINVAL);
338         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
339         assert_return(ifindex, -EINVAL);
340
341         ifa = NLMSG_DATA(m->hdr);
342
343         *ifindex = ifa->ifa_index;
344
345         return 0;
346 }
347
348 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
349                              uint16_t nlmsg_type, int index,
350                              int family) {
351         struct ifaddrmsg *ifa;
352         int r;
353
354         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
355         assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
356                       index > 0, -EINVAL);
357         assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
358                       family == AF_INET || family == AF_INET6, -EINVAL);
359         assert_return(ret, -EINVAL);
360
361         r = message_new(rtnl, ret, nlmsg_type);
362         if (r < 0)
363                 return r;
364
365         if (nlmsg_type == RTM_GETADDR)
366                 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
367
368         ifa = NLMSG_DATA((*ret)->hdr);
369
370         ifa->ifa_index = index;
371         ifa->ifa_family = family;
372         if (family == AF_INET)
373                 ifa->ifa_prefixlen = 32;
374         else if (family == AF_INET6)
375                 ifa->ifa_prefixlen = 128;
376
377         return 0;
378 }
379
380 int sd_rtnl_message_new_addr_update(sd_rtnl *rtnl, sd_rtnl_message **ret,
381                              int index, int family) {
382         int r;
383
384         r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
385         if (r < 0)
386                 return r;
387
388         (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
389
390         return 0;
391 }
392
393 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
394         if (m)
395                 assert_se(REFCNT_INC(m->n_ref) >= 2);
396
397         return m;
398 }
399
400 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
401         if (m && REFCNT_DEC(m->n_ref) <= 0) {
402                 unsigned i;
403
404                 free(m->hdr);
405
406                 for (i = 0; i <= m->n_containers; i++)
407                         free(m->rta_offset_tb[i]);
408
409                 sd_rtnl_message_unref(m->next);
410
411                 free(m);
412         }
413
414         return NULL;
415 }
416
417 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
418         assert_return(m, -EINVAL);
419         assert_return(type, -EINVAL);
420
421         *type = m->hdr->nlmsg_type;
422
423         return 0;
424 }
425
426 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
427         assert_return(m, -EINVAL);
428
429         return !m->hdr->nlmsg_pid;
430 }
431
432 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
433         struct ifinfomsg *ifi;
434
435         assert_return(m, -EINVAL);
436         assert_return(m->hdr, -EINVAL);
437         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
438         assert_return(ifindex, -EINVAL);
439
440         ifi = NLMSG_DATA(m->hdr);
441
442         *ifindex = ifi->ifi_index;
443
444         return 0;
445 }
446
447 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
448         struct ifinfomsg *ifi;
449
450         assert_return(m, -EINVAL);
451         assert_return(m->hdr, -EINVAL);
452         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
453         assert_return(flags, -EINVAL);
454
455         ifi = NLMSG_DATA(m->hdr);
456
457         *flags = ifi->ifi_flags;
458
459         return 0;
460 }
461
462 int sd_rtnl_message_link_get_type(sd_rtnl_message *m, unsigned *type) {
463         struct ifinfomsg *ifi;
464
465         assert_return(m, -EINVAL);
466         assert_return(m->hdr, -EINVAL);
467         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
468         assert_return(type, -EINVAL);
469
470         ifi = NLMSG_DATA(m->hdr);
471
472         *type = ifi->ifi_type;
473
474         return 0;
475 }
476
477 /* If successful the updated message will be correctly aligned, if
478    unsuccessful the old message is untouched. */
479 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
480         uint32_t rta_length;
481         size_t message_length, padding_length;
482         struct nlmsghdr *new_hdr;
483         struct rtattr *rta;
484         char *padding;
485         unsigned i;
486         int offset;
487
488         assert(m);
489         assert(m->hdr);
490         assert(!m->sealed);
491         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
492         assert(!data || data_length);
493
494         /* get offset of the new attribute */
495         offset = m->hdr->nlmsg_len;
496
497         /* get the size of the new rta attribute (with padding at the end) */
498         rta_length = RTA_LENGTH(data_length);
499
500         /* get the new message size (with padding at the end) */
501         message_length = offset + RTA_ALIGN(rta_length);
502
503         /* realloc to fit the new attribute */
504         new_hdr = realloc(m->hdr, message_length);
505         if (!new_hdr)
506                 return -ENOMEM;
507         m->hdr = new_hdr;
508
509         /* get pointer to the attribute we are about to add */
510         rta = (struct rtattr *) ((uint8_t *) m->hdr + offset);
511
512         /* if we are inside containers, extend them */
513         for (i = 0; i < m->n_containers; i++)
514                 GET_CONTAINER(m, i)->rta_len += message_length - offset;
515
516         /* fill in the attribute */
517         rta->rta_type = type;
518         rta->rta_len = rta_length;
519         if (data)
520                 /* we don't deal with the case where the user lies about the type
521                  * and gives us too little data (so don't do that)
522                  */
523                 padding = mempcpy(RTA_DATA(rta), data, data_length);
524         else {
525                 /* if no data was passed, make sure we still initialize the padding
526                    note that we can have data_length > 0 (used by some containers) */
527                 padding = RTA_DATA(rta);
528         }
529
530         /* make sure also the padding at the end of the message is initialized */
531         padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding;
532         memzero(padding, padding_length);
533
534         /* update message size */
535         m->hdr->nlmsg_len = message_length;
536
537         return offset;
538 }
539
540 static int message_attribute_has_type(sd_rtnl_message *m, uint16_t attribute_type, uint16_t data_type) {
541         const NLType *type;
542         int r;
543
544         r = type_system_get_type(m->container_type_system[m->n_containers], &type, attribute_type);
545         if (r < 0)
546                 return r;
547
548         if (type->type != data_type)
549                 return -EINVAL;
550
551         return type->size;
552 }
553
554 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
555         size_t length, size;
556         int r;
557
558         assert_return(m, -EINVAL);
559         assert_return(!m->sealed, -EPERM);
560         assert_return(data, -EINVAL);
561
562         r = message_attribute_has_type(m, type, NLA_STRING);
563         if (r < 0)
564                 return r;
565         else
566                 size = (size_t)r;
567
568         if (size) {
569                 length = strnlen(data, size);
570                 if (length >= size)
571                         return -EINVAL;
572         } else
573                 length = strlen(data);
574
575         r = add_rtattr(m, type, data, length + 1);
576         if (r < 0)
577                 return r;
578
579         return 0;
580 }
581
582 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
583         int r;
584
585         assert_return(m, -EINVAL);
586         assert_return(!m->sealed, -EPERM);
587
588         r = message_attribute_has_type(m, type, NLA_U8);
589         if (r < 0)
590                 return r;
591
592         r = add_rtattr(m, type, &data, sizeof(uint8_t));
593         if (r < 0)
594                 return r;
595
596         return 0;
597 }
598
599
600 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
601         int r;
602
603         assert_return(m, -EINVAL);
604         assert_return(!m->sealed, -EPERM);
605
606         r = message_attribute_has_type(m, type, NLA_U16);
607         if (r < 0)
608                 return r;
609
610         r = add_rtattr(m, type, &data, sizeof(uint16_t));
611         if (r < 0)
612                 return r;
613
614         return 0;
615 }
616
617 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
618         int r;
619
620         assert_return(m, -EINVAL);
621         assert_return(!m->sealed, -EPERM);
622
623         r = message_attribute_has_type(m, type, NLA_U32);
624         if (r < 0)
625                 return r;
626
627         r = add_rtattr(m, type, &data, sizeof(uint32_t));
628         if (r < 0)
629                 return r;
630
631         return 0;
632 }
633
634 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
635         int r;
636
637         assert_return(m, -EINVAL);
638         assert_return(!m->sealed, -EPERM);
639         assert_return(data, -EINVAL);
640
641         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
642         if (r < 0)
643                 return r;
644
645         r = add_rtattr(m, type, data, sizeof(struct in_addr));
646         if (r < 0)
647                 return r;
648
649         return 0;
650 }
651
652 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
653         int r;
654
655         assert_return(m, -EINVAL);
656         assert_return(!m->sealed, -EPERM);
657         assert_return(data, -EINVAL);
658
659         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
660         if (r < 0)
661                 return r;
662
663         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
664         if (r < 0)
665                 return r;
666
667         return 0;
668 }
669
670 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
671         int r;
672
673         assert_return(m, -EINVAL);
674         assert_return(!m->sealed, -EPERM);
675         assert_return(data, -EINVAL);
676
677         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
678         if (r < 0)
679                 return r;
680
681         r = add_rtattr(m, type, data, ETH_ALEN);
682         if (r < 0)
683                 return r;
684
685         return 0;
686 }
687
688 int sd_rtnl_message_append_cache_info(sd_rtnl_message *m, unsigned short type, const struct ifa_cacheinfo *info) {
689         int r;
690
691         assert_return(m, -EINVAL);
692         assert_return(!m->sealed, -EPERM);
693         assert_return(info, -EINVAL);
694
695         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
696         if (r < 0)
697                 return r;
698
699         r = add_rtattr(m, type, info, sizeof(struct ifa_cacheinfo));
700         if (r < 0)
701                 return r;
702
703         return 0;
704 }
705
706 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
707         size_t size;
708         int r;
709
710         assert_return(m, -EINVAL);
711         assert_return(!m->sealed, -EPERM);
712         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
713
714         r = message_attribute_has_type(m, type, NLA_NESTED);
715         if (r < 0)
716                 return r;
717         else
718                 size = (size_t)r;
719
720         r = type_system_get_type_system(m->container_type_system[m->n_containers],
721                                         &m->container_type_system[m->n_containers + 1],
722                                         type);
723         if (r < 0)
724                 return r;
725
726         r = add_rtattr(m, type, NULL, size);
727         if (r < 0)
728                 return r;
729
730         m->container_offsets[m->n_containers ++] = r;
731
732         return 0;
733 }
734
735 int sd_rtnl_message_open_container_union(sd_rtnl_message *m, unsigned short type, const char *key) {
736         const NLTypeSystemUnion *type_system_union;
737         int r;
738
739         assert_return(m, -EINVAL);
740         assert_return(!m->sealed, -EPERM);
741
742         r = type_system_get_type_system_union(m->container_type_system[m->n_containers], &type_system_union, type);
743         if (r < 0)
744                 return r;
745
746         r = type_system_union_get_type_system(type_system_union,
747                                               &m->container_type_system[m->n_containers + 1],
748                                               key);
749         if (r < 0)
750                 return r;
751
752         r = sd_rtnl_message_append_string(m, type_system_union->match, key);
753         if (r < 0)
754                 return r;
755
756         /* do we evere need non-null size */
757         r = add_rtattr(m, type, NULL, 0);
758         if (r < 0)
759                 return r;
760
761         m->container_offsets[m->n_containers ++] = r;
762
763         return 0;
764 }
765
766
767 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
768         assert_return(m, -EINVAL);
769         assert_return(!m->sealed, -EPERM);
770         assert_return(m->n_containers > 0, -EINVAL);
771
772         m->container_type_system[m->n_containers] = NULL;
773         m->n_containers --;
774
775         return 0;
776 }
777
778 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
779         struct rtattr *rta;
780
781         assert_return(m, -EINVAL);
782         assert_return(m->sealed, -EPERM);
783         assert_return(data, -EINVAL);
784         assert(m->n_containers <= RTNL_CONTAINER_DEPTH);
785         assert(m->rta_offset_tb[m->n_containers]);
786         assert(type < m->rta_tb_size[m->n_containers]);
787
788         if(!m->rta_offset_tb[m->n_containers][type])
789                 return -ENODATA;
790
791         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
792
793         *data = RTA_DATA(rta);
794
795         return RTA_PAYLOAD(rta);
796 }
797
798 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, const char **data) {
799         int r;
800         void *attr_data;
801
802         r = message_attribute_has_type(m, type, NLA_STRING);
803         if (r < 0)
804                 return r;
805
806         r = rtnl_message_read_internal(m, type, &attr_data);
807         if (r < 0)
808                 return r;
809         else if (strnlen(attr_data, r) >= (size_t) r)
810                 return -EIO;
811
812         *data = (const char *) attr_data;
813
814         return 0;
815 }
816
817 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
818         int r;
819         void *attr_data;
820
821         r = message_attribute_has_type(m, type, NLA_U8);
822         if (r < 0)
823                 return r;
824
825         r = rtnl_message_read_internal(m, type, &attr_data);
826         if (r < 0)
827                 return r;
828         else if ((size_t) r < sizeof(uint8_t))
829                 return -EIO;
830
831         *data = *(uint8_t *) attr_data;
832
833         return 0;
834 }
835
836 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
837         int r;
838         void *attr_data;
839
840         r = message_attribute_has_type(m, type, NLA_U16);
841         if (r < 0)
842                 return r;
843
844         r = rtnl_message_read_internal(m, type, &attr_data);
845         if (r < 0)
846                 return r;
847         else if ((size_t) r < sizeof(uint16_t))
848                 return -EIO;
849
850         *data = *(uint16_t *) attr_data;
851
852         return 0;
853 }
854
855 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
856         int r;
857         void *attr_data;
858
859         r = message_attribute_has_type(m, type, NLA_U32);
860         if (r < 0)
861                 return r;
862
863         r = rtnl_message_read_internal(m, type, &attr_data);
864         if (r < 0)
865                 return r;
866         else if ((size_t)r < sizeof(uint32_t))
867                 return -EIO;
868
869         *data = *(uint32_t *) attr_data;
870
871         return 0;
872 }
873
874 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
875         int r;
876         void *attr_data;
877
878         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
879         if (r < 0)
880                 return r;
881
882         r = rtnl_message_read_internal(m, type, &attr_data);
883         if (r < 0)
884                 return r;
885         else if ((size_t)r < sizeof(struct ether_addr))
886                 return -EIO;
887
888         memcpy(data, attr_data, sizeof(struct ether_addr));
889
890         return 0;
891 }
892
893 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
894         int r;
895         void *attr_data;
896
897         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
898         if (r < 0)
899                 return r;
900
901         r = rtnl_message_read_internal(m, type, &attr_data);
902         if (r < 0)
903                 return r;
904         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
905                 return -EIO;
906
907         memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
908
909         return 0;
910 }
911
912 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
913         int r;
914         void *attr_data;
915
916         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
917         if (r < 0)
918                 return r;
919
920         r = rtnl_message_read_internal(m, type, &attr_data);
921         if (r < 0)
922                 return r;
923         else if ((size_t)r < sizeof(struct in_addr))
924                 return -EIO;
925
926         memcpy(data, attr_data, sizeof(struct in_addr));
927
928         return 0;
929 }
930
931 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
932         int r;
933         void *attr_data;
934
935         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
936         if (r < 0)
937                 return r;
938
939         r = rtnl_message_read_internal(m, type, &attr_data);
940         if (r < 0)
941                 return r;
942         else if ((size_t)r < sizeof(struct in6_addr))
943                 return -EIO;
944
945         memcpy(data, attr_data, sizeof(struct in6_addr));
946
947         return 0;
948 }
949
950 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
951         const NLType *nl_type;
952         const NLTypeSystem *type_system;
953         void *container;
954         size_t size;
955         int r;
956
957         assert_return(m, -EINVAL);
958         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
959
960         r = type_system_get_type(m->container_type_system[m->n_containers],
961                                  &nl_type,
962                                  type);
963         if (r < 0)
964                 return r;
965
966         if (nl_type->type == NLA_NESTED) {
967                 r = type_system_get_type_system(m->container_type_system[m->n_containers],
968                                                 &type_system,
969                                                 type);
970                 if (r < 0)
971                         return r;
972         } else if (nl_type->type == NLA_UNION) {
973                 const NLTypeSystemUnion *type_system_union;
974                 const char *key;
975
976                 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
977                                                       &type_system_union,
978                                                       type);
979                 if (r < 0)
980                         return r;
981
982                 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
983                 if (r < 0)
984                         return r;
985
986                 r = type_system_union_get_type_system(type_system_union,
987                                                       &type_system,
988                                                       key);
989                 if (r < 0)
990                         return r;
991         } else
992                 return -EINVAL;
993
994         r = rtnl_message_read_internal(m, type, &container);
995         if (r < 0)
996                 return r;
997         else
998                 size = (size_t)r;
999
1000         m->n_containers ++;
1001
1002         r = rtnl_message_parse(m,
1003                                &m->rta_offset_tb[m->n_containers],
1004                                &m->rta_tb_size[m->n_containers],
1005                                type_system->max,
1006                                container,
1007                                size);
1008         if (r < 0) {
1009                 m->n_containers --;
1010                 return r;
1011         }
1012
1013         m->container_type_system[m->n_containers] = type_system;
1014
1015         return 0;
1016 }
1017
1018 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1019         assert_return(m, -EINVAL);
1020         assert_return(m->sealed, -EINVAL);
1021         assert_return(m->n_containers > 0, -EINVAL);
1022
1023         free(m->rta_offset_tb[m->n_containers]);
1024         m->rta_offset_tb[m->n_containers] = NULL;
1025         m->container_type_system[m->n_containers] = NULL;
1026
1027         m->n_containers --;
1028
1029         return 0;
1030 }
1031
1032 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1033         assert(m);
1034         assert(m->hdr);
1035
1036         return m->hdr->nlmsg_seq;
1037 }
1038
1039 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1040         struct nlmsgerr *err;
1041
1042         assert_return(m, -EINVAL);
1043         assert_return(m->hdr, -EINVAL);
1044
1045         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1046                 return 0;
1047
1048         err = NLMSG_DATA(m->hdr);
1049
1050         return err->error;
1051 }
1052
1053 int rtnl_message_parse(sd_rtnl_message *m,
1054                        size_t **rta_offset_tb,
1055                        unsigned short *rta_tb_size,
1056                        int max,
1057                        struct rtattr *rta,
1058                        unsigned int rt_len) {
1059         unsigned short type;
1060         size_t *tb;
1061
1062         tb = new0(size_t, max + 1);
1063         if(!tb)
1064                 return -ENOMEM;
1065
1066         *rta_tb_size = max + 1;
1067
1068         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1069                 type = rta->rta_type;
1070
1071                 /* if the kernel is newer than the headers we used
1072                    when building, we ignore out-of-range attributes
1073                  */
1074                 if (type > max)
1075                         continue;
1076
1077                 if (tb[type])
1078                         log_debug("rtnl: message parse - overwriting repeated attribute");
1079
1080                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1081         }
1082
1083         *rta_offset_tb = tb;
1084
1085         return 0;
1086 }
1087
1088 /* returns the number of bytes sent, or a negative error code */
1089 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1090         union {
1091                 struct sockaddr sa;
1092                 struct sockaddr_nl nl;
1093         } addr = {
1094                 .nl.nl_family = AF_NETLINK,
1095         };
1096         ssize_t k;
1097
1098         assert(nl);
1099         assert(m);
1100         assert(m->hdr);
1101
1102         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1103                         0, &addr.sa, sizeof(addr));
1104         if (k < 0)
1105                 return (errno == EAGAIN) ? 0 : -errno;
1106
1107         return k;
1108 }
1109
1110 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1111         uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1112                             CMSG_SPACE(sizeof(struct nl_pktinfo))];
1113         struct msghdr msg = {
1114                 .msg_iov = iov,
1115                 .msg_iovlen = 1,
1116                 .msg_control = cred_buffer,
1117                 .msg_controllen = sizeof(cred_buffer),
1118         };
1119         struct cmsghdr *cmsg;
1120         uint32_t group = 0;
1121         bool auth = false;
1122         int r;
1123
1124         assert(fd >= 0);
1125         assert(iov);
1126
1127         r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1128         if (r < 0) {
1129                 /* no data */
1130                 if (errno == ENOBUFS)
1131                         log_debug("rtnl: kernel receive buffer overrun");
1132
1133                 return (errno == EAGAIN) ? 0 : -errno;
1134         } else if (r == 0)
1135                 /* connection was closed by the kernel */
1136                 return -ECONNRESET;
1137
1138         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1139                 if (cmsg->cmsg_level == SOL_SOCKET &&
1140                     cmsg->cmsg_type == SCM_CREDENTIALS &&
1141                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1142                         struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1143
1144                         /* from the kernel */
1145                         if (ucred->uid == 0 && ucred->pid == 0)
1146                                 auth = true;
1147                 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1148                            cmsg->cmsg_type == NETLINK_PKTINFO &&
1149                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1150                         struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1151
1152                         /* multi-cast group */
1153                         group = pktinfo->group;
1154                 }
1155         }
1156
1157         if (!auth)
1158                 /* not from the kernel, ignore */
1159                 return 0;
1160
1161         if (group)
1162                 *_group = group;
1163
1164         return r;
1165 }
1166
1167 /* On success, the number of bytes received is returned and *ret points to the received message
1168  * which has a valid header and the correct size.
1169  * If nothing useful was received 0 is returned.
1170  * On failure, a negative error code is returned.
1171  */
1172 int socket_read_message(sd_rtnl *rtnl) {
1173         _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1174         struct iovec iov = {};
1175         uint32_t group = 0;
1176         bool multi_part = false, done = false;
1177         struct nlmsghdr *new_msg;
1178         size_t len;
1179         int r;
1180         unsigned i = 0;
1181
1182         assert(rtnl);
1183         assert(rtnl->rbuffer);
1184         assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1185
1186         /* read nothing, just get the pending message size */
1187         r = socket_recv_message(rtnl->fd, &iov, &group, true);
1188         if (r <= 0)
1189                 return r;
1190         else
1191                 len = (size_t)r;
1192
1193         /* make room for the pending message */
1194         if (!greedy_realloc((void **)&rtnl->rbuffer,
1195                             &rtnl->rbuffer_allocated,
1196                             len, sizeof(uint8_t)))
1197                 return -ENOMEM;
1198
1199         iov.iov_base = rtnl->rbuffer;
1200         iov.iov_len = rtnl->rbuffer_allocated;
1201
1202         /* read the pending message */
1203         r = socket_recv_message(rtnl->fd, &iov, &group, false);
1204         if (r <= 0)
1205                 return r;
1206         else
1207                 len = (size_t)r;
1208
1209         if (len > rtnl->rbuffer_allocated)
1210                 /* message did not fit in read buffer */
1211                 return -EIO;
1212
1213         if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1214                 multi_part = true;
1215
1216                 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1217                         if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1218                             rtnl->rbuffer->nlmsg_seq) {
1219                                 first = rtnl->rqueue_partial[i];
1220                                 break;
1221                         }
1222                 }
1223         }
1224
1225         for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1226                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1227                 const NLType *nl_type;
1228
1229                 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1230                         /* not broadcast and not for us */
1231                         continue;
1232
1233                 if (new_msg->nlmsg_type == NLMSG_NOOP)
1234                         /* silently drop noop messages */
1235                         continue;
1236
1237                 if (new_msg->nlmsg_type == NLMSG_DONE) {
1238                         /* finished reading multi-part message */
1239                         done = true;
1240                         break;
1241                 }
1242
1243                 /* check that we support this message type */
1244                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1245                 if (r < 0) {
1246                         if (r == -ENOTSUP)
1247                                 log_debug("sd-rtnl: ignored message with unknown type: %u",
1248                                           new_msg->nlmsg_type);
1249
1250                         continue;
1251                 }
1252
1253                 /* check that the size matches the message type */
1254                 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1255                         continue;
1256
1257                 r = message_new_empty(rtnl, &m);
1258                 if (r < 0)
1259                         return r;
1260
1261                 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1262                 if (!m->hdr)
1263                         return -ENOMEM;
1264
1265                 /* seal and parse the top-level message */
1266                 r = sd_rtnl_message_rewind(m);
1267                 if (r < 0)
1268                         return r;
1269
1270                 /* push the message onto the multi-part message stack */
1271                 if (first)
1272                         m->next = first;
1273                 first = m;
1274                 m = NULL;
1275         }
1276
1277         if (len)
1278                 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1279
1280         if (!first)
1281                 return 0;
1282
1283         if (!multi_part || done) {
1284                 /* we got a complete message, push it on the read queue */
1285                 r = rtnl_rqueue_make_room(rtnl);
1286                 if (r < 0)
1287                         return r;
1288
1289                 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1290                 first = NULL;
1291
1292                 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1293                         /* remove the message form the partial read queue */
1294                         memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1295                                 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1296                         rtnl->rqueue_partial_size --;
1297                 }
1298
1299                 return 1;
1300         } else {
1301                 /* we only got a partial multi-part message, push it on the
1302                    partial read queue */
1303                 if (i < rtnl->rqueue_partial_size) {
1304                         rtnl->rqueue_partial[i] = first;
1305                 } else {
1306                         r = rtnl_rqueue_partial_make_room(rtnl);
1307                         if (r < 0)
1308                                 return r;
1309
1310                         rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1311                 }
1312                 first = NULL;
1313
1314                 return 0;
1315         }
1316 }
1317
1318 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1319         const NLType *type;
1320         unsigned i;
1321         int r;
1322
1323         assert_return(m, -EINVAL);
1324
1325         /* don't allow appending to message once parsed */
1326         if (!m->sealed)
1327                 rtnl_message_seal(m);
1328
1329         for (i = 1; i <= m->n_containers; i++) {
1330                 free(m->rta_offset_tb[i]);
1331                 m->rta_offset_tb[i] = NULL;
1332                 m->rta_tb_size[i] = 0;
1333                 m->container_type_system[i] = NULL;
1334         }
1335
1336         m->n_containers = 0;
1337
1338         if (m->rta_offset_tb[0]) {
1339                 /* top-level attributes have already been parsed */
1340                 return 0;
1341         }
1342
1343         assert(m->hdr);
1344
1345         r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1346         if (r < 0)
1347                 return r;
1348
1349         if (type->type == NLA_NESTED) {
1350                 const NLTypeSystem *type_system = type->type_system;
1351
1352                 assert(type_system);
1353
1354                 m->container_type_system[0] = type_system;
1355
1356                 r = rtnl_message_parse(m,
1357                                        &m->rta_offset_tb[m->n_containers],
1358                                        &m->rta_tb_size[m->n_containers],
1359                                        type_system->max,
1360                                        (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1361                                                         NLMSG_ALIGN(type->size)),
1362                                        NLMSG_PAYLOAD(m->hdr, type->size));
1363                 if (r < 0)
1364                         return r;
1365         }
1366
1367         return 0;
1368 }
1369
1370 void rtnl_message_seal(sd_rtnl_message *m) {
1371         assert(m);
1372         assert(!m->sealed);
1373
1374         m->sealed = true;
1375 }
1376
1377 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1378         assert_return(m, NULL);
1379
1380         return m->next;
1381 }