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