chiark / gitweb /
sd-rtnl: add sd_rtnl_message_route_get_family
[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         r = message_attribute_has_type(m, type, NLA_STRING);
834         if (r < 0)
835                 return r;
836
837         r = rtnl_message_read_internal(m, type, &attr_data);
838         if (r < 0)
839                 return r;
840         else if (strnlen(attr_data, r) >= (size_t) r)
841                 return -EIO;
842
843         *data = (const char *) attr_data;
844
845         return 0;
846 }
847
848 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
849         int r;
850         void *attr_data;
851
852         r = message_attribute_has_type(m, type, NLA_U8);
853         if (r < 0)
854                 return r;
855
856         r = rtnl_message_read_internal(m, type, &attr_data);
857         if (r < 0)
858                 return r;
859         else if ((size_t) r < sizeof(uint8_t))
860                 return -EIO;
861
862         *data = *(uint8_t *) attr_data;
863
864         return 0;
865 }
866
867 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
868         int r;
869         void *attr_data;
870
871         r = message_attribute_has_type(m, type, NLA_U16);
872         if (r < 0)
873                 return r;
874
875         r = rtnl_message_read_internal(m, type, &attr_data);
876         if (r < 0)
877                 return r;
878         else if ((size_t) r < sizeof(uint16_t))
879                 return -EIO;
880
881         *data = *(uint16_t *) attr_data;
882
883         return 0;
884 }
885
886 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
887         int r;
888         void *attr_data;
889
890         r = message_attribute_has_type(m, type, NLA_U32);
891         if (r < 0)
892                 return r;
893
894         r = rtnl_message_read_internal(m, type, &attr_data);
895         if (r < 0)
896                 return r;
897         else if ((size_t)r < sizeof(uint32_t))
898                 return -EIO;
899
900         *data = *(uint32_t *) attr_data;
901
902         return 0;
903 }
904
905 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
906         int r;
907         void *attr_data;
908
909         r = message_attribute_has_type(m, type, NLA_ETHER_ADDR);
910         if (r < 0)
911                 return r;
912
913         r = rtnl_message_read_internal(m, type, &attr_data);
914         if (r < 0)
915                 return r;
916         else if ((size_t)r < sizeof(struct ether_addr))
917                 return -EIO;
918
919         memcpy(data, attr_data, sizeof(struct ether_addr));
920
921         return 0;
922 }
923
924 int sd_rtnl_message_read_cache_info(sd_rtnl_message *m, unsigned short type, struct ifa_cacheinfo *info) {
925         int r;
926         void *attr_data;
927
928         r = message_attribute_has_type(m, type, NLA_CACHE_INFO);
929         if (r < 0)
930                 return r;
931
932         r = rtnl_message_read_internal(m, type, &attr_data);
933         if (r < 0)
934                 return r;
935         else if ((size_t)r < sizeof(struct ifa_cacheinfo))
936                 return -EIO;
937
938         memcpy(info, attr_data, sizeof(struct ifa_cacheinfo));
939
940         return 0;
941 }
942
943 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
944         int r;
945         void *attr_data;
946
947         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
948         if (r < 0)
949                 return r;
950
951         r = rtnl_message_read_internal(m, type, &attr_data);
952         if (r < 0)
953                 return r;
954         else if ((size_t)r < sizeof(struct in_addr))
955                 return -EIO;
956
957         memcpy(data, attr_data, sizeof(struct in_addr));
958
959         return 0;
960 }
961
962 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
963         int r;
964         void *attr_data;
965
966         r = message_attribute_has_type(m, type, NLA_IN_ADDR);
967         if (r < 0)
968                 return r;
969
970         r = rtnl_message_read_internal(m, type, &attr_data);
971         if (r < 0)
972                 return r;
973         else if ((size_t)r < sizeof(struct in6_addr))
974                 return -EIO;
975
976         memcpy(data, attr_data, sizeof(struct in6_addr));
977
978         return 0;
979 }
980
981 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
982         const NLType *nl_type;
983         const NLTypeSystem *type_system;
984         void *container;
985         size_t size;
986         int r;
987
988         assert_return(m, -EINVAL);
989         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
990
991         r = type_system_get_type(m->container_type_system[m->n_containers],
992                                  &nl_type,
993                                  type);
994         if (r < 0)
995                 return r;
996
997         if (nl_type->type == NLA_NESTED) {
998                 r = type_system_get_type_system(m->container_type_system[m->n_containers],
999                                                 &type_system,
1000                                                 type);
1001                 if (r < 0)
1002                         return r;
1003         } else if (nl_type->type == NLA_UNION) {
1004                 const NLTypeSystemUnion *type_system_union;
1005                 const char *key;
1006
1007                 r = type_system_get_type_system_union(m->container_type_system[m->n_containers],
1008                                                       &type_system_union,
1009                                                       type);
1010                 if (r < 0)
1011                         return r;
1012
1013                 r = sd_rtnl_message_read_string(m, type_system_union->match, &key);
1014                 if (r < 0)
1015                         return r;
1016
1017                 r = type_system_union_get_type_system(type_system_union,
1018                                                       &type_system,
1019                                                       key);
1020                 if (r < 0)
1021                         return r;
1022         } else
1023                 return -EINVAL;
1024
1025         r = rtnl_message_read_internal(m, type, &container);
1026         if (r < 0)
1027                 return r;
1028         else
1029                 size = (size_t)r;
1030
1031         m->n_containers ++;
1032
1033         r = rtnl_message_parse(m,
1034                                &m->rta_offset_tb[m->n_containers],
1035                                &m->rta_tb_size[m->n_containers],
1036                                type_system->max,
1037                                container,
1038                                size);
1039         if (r < 0) {
1040                 m->n_containers --;
1041                 return r;
1042         }
1043
1044         m->container_type_system[m->n_containers] = type_system;
1045
1046         return 0;
1047 }
1048
1049 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
1050         assert_return(m, -EINVAL);
1051         assert_return(m->sealed, -EINVAL);
1052         assert_return(m->n_containers > 0, -EINVAL);
1053
1054         free(m->rta_offset_tb[m->n_containers]);
1055         m->rta_offset_tb[m->n_containers] = NULL;
1056         m->container_type_system[m->n_containers] = NULL;
1057
1058         m->n_containers --;
1059
1060         return 0;
1061 }
1062
1063 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
1064         assert(m);
1065         assert(m->hdr);
1066
1067         return m->hdr->nlmsg_seq;
1068 }
1069
1070 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1071         struct nlmsgerr *err;
1072
1073         assert_return(m, -EINVAL);
1074         assert_return(m->hdr, -EINVAL);
1075
1076         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1077                 return 0;
1078
1079         err = NLMSG_DATA(m->hdr);
1080
1081         return err->error;
1082 }
1083
1084 int rtnl_message_parse(sd_rtnl_message *m,
1085                        size_t **rta_offset_tb,
1086                        unsigned short *rta_tb_size,
1087                        int max,
1088                        struct rtattr *rta,
1089                        unsigned int rt_len) {
1090         unsigned short type;
1091         size_t *tb;
1092
1093         tb = new0(size_t, max + 1);
1094         if(!tb)
1095                 return -ENOMEM;
1096
1097         *rta_tb_size = max + 1;
1098
1099         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1100                 type = RTA_TYPE(rta);
1101
1102                 /* if the kernel is newer than the headers we used
1103                    when building, we ignore out-of-range attributes
1104                  */
1105                 if (type > max)
1106                         continue;
1107
1108                 if (tb[type])
1109                         log_debug("rtnl: message parse - overwriting repeated attribute");
1110
1111                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1112         }
1113
1114         *rta_offset_tb = tb;
1115
1116         return 0;
1117 }
1118
1119 /* returns the number of bytes sent, or a negative error code */
1120 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1121         union {
1122                 struct sockaddr sa;
1123                 struct sockaddr_nl nl;
1124         } addr = {
1125                 .nl.nl_family = AF_NETLINK,
1126         };
1127         ssize_t k;
1128
1129         assert(nl);
1130         assert(m);
1131         assert(m->hdr);
1132
1133         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1134                         0, &addr.sa, sizeof(addr));
1135         if (k < 0)
1136                 return (errno == EAGAIN) ? 0 : -errno;
1137
1138         return k;
1139 }
1140
1141 static int socket_recv_message(int fd, struct iovec *iov, uint32_t *_group, bool peek) {
1142         uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred)) +
1143                             CMSG_SPACE(sizeof(struct nl_pktinfo))];
1144         struct msghdr msg = {
1145                 .msg_iov = iov,
1146                 .msg_iovlen = 1,
1147                 .msg_control = cred_buffer,
1148                 .msg_controllen = sizeof(cred_buffer),
1149         };
1150         struct cmsghdr *cmsg;
1151         uint32_t group = 0;
1152         bool auth = false;
1153         int r;
1154
1155         assert(fd >= 0);
1156         assert(iov);
1157
1158         r = recvmsg(fd, &msg, MSG_TRUNC | (peek ? MSG_PEEK : 0));
1159         if (r < 0) {
1160                 /* no data */
1161                 if (errno == ENOBUFS)
1162                         log_debug("rtnl: kernel receive buffer overrun");
1163
1164                 return (errno == EAGAIN) ? 0 : -errno;
1165         } else if (r == 0)
1166                 /* connection was closed by the kernel */
1167                 return -ECONNRESET;
1168
1169         for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1170                 if (cmsg->cmsg_level == SOL_SOCKET &&
1171                     cmsg->cmsg_type == SCM_CREDENTIALS &&
1172                     cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
1173                         struct ucred *ucred = (void *)CMSG_DATA(cmsg);
1174
1175                         /* from the kernel */
1176                         if (ucred->uid == 0 && ucred->pid == 0)
1177                                 auth = true;
1178                 } else if (cmsg->cmsg_level == SOL_NETLINK &&
1179                            cmsg->cmsg_type == NETLINK_PKTINFO &&
1180                            cmsg->cmsg_len == CMSG_LEN(sizeof(struct nl_pktinfo))) {
1181                         struct nl_pktinfo *pktinfo = (void *)CMSG_DATA(cmsg);
1182
1183                         /* multi-cast group */
1184                         group = pktinfo->group;
1185                 }
1186         }
1187
1188         if (!auth)
1189                 /* not from the kernel, ignore */
1190                 return 0;
1191
1192         if (group)
1193                 *_group = group;
1194
1195         return r;
1196 }
1197
1198 /* On success, the number of bytes received is returned and *ret points to the received message
1199  * which has a valid header and the correct size.
1200  * If nothing useful was received 0 is returned.
1201  * On failure, a negative error code is returned.
1202  */
1203 int socket_read_message(sd_rtnl *rtnl) {
1204         _cleanup_rtnl_message_unref_ sd_rtnl_message *first = NULL;
1205         struct iovec iov = {};
1206         uint32_t group = 0;
1207         bool multi_part = false, done = false;
1208         struct nlmsghdr *new_msg;
1209         size_t len;
1210         int r;
1211         unsigned i = 0;
1212
1213         assert(rtnl);
1214         assert(rtnl->rbuffer);
1215         assert(rtnl->rbuffer_allocated >= sizeof(struct nlmsghdr));
1216
1217         /* read nothing, just get the pending message size */
1218         r = socket_recv_message(rtnl->fd, &iov, &group, true);
1219         if (r <= 0)
1220                 return r;
1221         else
1222                 len = (size_t)r;
1223
1224         /* make room for the pending message */
1225         if (!greedy_realloc((void **)&rtnl->rbuffer,
1226                             &rtnl->rbuffer_allocated,
1227                             len, sizeof(uint8_t)))
1228                 return -ENOMEM;
1229
1230         iov.iov_base = rtnl->rbuffer;
1231         iov.iov_len = rtnl->rbuffer_allocated;
1232
1233         /* read the pending message */
1234         r = socket_recv_message(rtnl->fd, &iov, &group, false);
1235         if (r <= 0)
1236                 return r;
1237         else
1238                 len = (size_t)r;
1239
1240         if (len > rtnl->rbuffer_allocated)
1241                 /* message did not fit in read buffer */
1242                 return -EIO;
1243
1244         if (NLMSG_OK(rtnl->rbuffer, len) && rtnl->rbuffer->nlmsg_flags & NLM_F_MULTI) {
1245                 multi_part = true;
1246
1247                 for (i = 0; i < rtnl->rqueue_partial_size; i++) {
1248                         if (rtnl_message_get_serial(rtnl->rqueue_partial[i]) ==
1249                             rtnl->rbuffer->nlmsg_seq) {
1250                                 first = rtnl->rqueue_partial[i];
1251                                 break;
1252                         }
1253                 }
1254         }
1255
1256         for (new_msg = rtnl->rbuffer; NLMSG_OK(new_msg, len); new_msg = NLMSG_NEXT(new_msg, len)) {
1257                 _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1258                 const NLType *nl_type;
1259
1260                 if (!group && new_msg->nlmsg_pid != rtnl->sockaddr.nl.nl_pid)
1261                         /* not broadcast and not for us */
1262                         continue;
1263
1264                 if (new_msg->nlmsg_type == NLMSG_NOOP)
1265                         /* silently drop noop messages */
1266                         continue;
1267
1268                 if (new_msg->nlmsg_type == NLMSG_DONE) {
1269                         /* finished reading multi-part message */
1270                         done = true;
1271                         break;
1272                 }
1273
1274                 /* check that we support this message type */
1275                 r = type_system_get_type(NULL, &nl_type, new_msg->nlmsg_type);
1276                 if (r < 0) {
1277                         if (r == -ENOTSUP)
1278                                 log_debug("sd-rtnl: ignored message with unknown type: %u",
1279                                           new_msg->nlmsg_type);
1280
1281                         continue;
1282                 }
1283
1284                 /* check that the size matches the message type */
1285                 if (new_msg->nlmsg_len < NLMSG_LENGTH(nl_type->size))
1286                         continue;
1287
1288                 r = message_new_empty(rtnl, &m);
1289                 if (r < 0)
1290                         return r;
1291
1292                 m->hdr = memdup(new_msg, new_msg->nlmsg_len);
1293                 if (!m->hdr)
1294                         return -ENOMEM;
1295
1296                 /* seal and parse the top-level message */
1297                 r = sd_rtnl_message_rewind(m);
1298                 if (r < 0)
1299                         return r;
1300
1301                 /* push the message onto the multi-part message stack */
1302                 if (first)
1303                         m->next = first;
1304                 first = m;
1305                 m = NULL;
1306         }
1307
1308         if (len)
1309                 log_debug("sd-rtnl: discarding %zu bytes of incoming message", len);
1310
1311         if (!first)
1312                 return 0;
1313
1314         if (!multi_part || done) {
1315                 /* we got a complete message, push it on the read queue */
1316                 r = rtnl_rqueue_make_room(rtnl);
1317                 if (r < 0)
1318                         return r;
1319
1320                 rtnl->rqueue[rtnl->rqueue_size ++] = first;
1321                 first = NULL;
1322
1323                 if (multi_part && (i < rtnl->rqueue_partial_size)) {
1324                         /* remove the message form the partial read queue */
1325                         memmove(rtnl->rqueue_partial + i,rtnl->rqueue_partial + i + 1,
1326                                 sizeof(sd_rtnl_message*) * (rtnl->rqueue_partial_size - i - 1));
1327                         rtnl->rqueue_partial_size --;
1328                 }
1329
1330                 return 1;
1331         } else {
1332                 /* we only got a partial multi-part message, push it on the
1333                    partial read queue */
1334                 if (i < rtnl->rqueue_partial_size) {
1335                         rtnl->rqueue_partial[i] = first;
1336                 } else {
1337                         r = rtnl_rqueue_partial_make_room(rtnl);
1338                         if (r < 0)
1339                                 return r;
1340
1341                         rtnl->rqueue_partial[rtnl->rqueue_partial_size ++] = first;
1342                 }
1343                 first = NULL;
1344
1345                 return 0;
1346         }
1347 }
1348
1349 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1350         const NLType *type;
1351         unsigned i;
1352         int r;
1353
1354         assert_return(m, -EINVAL);
1355
1356         /* don't allow appending to message once parsed */
1357         if (!m->sealed)
1358                 rtnl_message_seal(m);
1359
1360         for (i = 1; i <= m->n_containers; i++) {
1361                 free(m->rta_offset_tb[i]);
1362                 m->rta_offset_tb[i] = NULL;
1363                 m->rta_tb_size[i] = 0;
1364                 m->container_type_system[i] = NULL;
1365         }
1366
1367         m->n_containers = 0;
1368
1369         if (m->rta_offset_tb[0]) {
1370                 /* top-level attributes have already been parsed */
1371                 return 0;
1372         }
1373
1374         assert(m->hdr);
1375
1376         r = type_system_get_type(NULL, &type, m->hdr->nlmsg_type);
1377         if (r < 0)
1378                 return r;
1379
1380         if (type->type == NLA_NESTED) {
1381                 const NLTypeSystem *type_system = type->type_system;
1382
1383                 assert(type_system);
1384
1385                 m->container_type_system[0] = type_system;
1386
1387                 r = rtnl_message_parse(m,
1388                                        &m->rta_offset_tb[m->n_containers],
1389                                        &m->rta_tb_size[m->n_containers],
1390                                        type_system->max,
1391                                        (struct rtattr*)((uint8_t*)NLMSG_DATA(m->hdr) +
1392                                                         NLMSG_ALIGN(type->size)),
1393                                        NLMSG_PAYLOAD(m->hdr, type->size));
1394                 if (r < 0)
1395                         return r;
1396         }
1397
1398         return 0;
1399 }
1400
1401 void rtnl_message_seal(sd_rtnl_message *m) {
1402         assert(m);
1403         assert(!m->sealed);
1404
1405         m->sealed = true;
1406 }
1407
1408 sd_rtnl_message *sd_rtnl_message_next(sd_rtnl_message *m) {
1409         assert_return(m, NULL);
1410
1411         return m->next;
1412 }