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