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