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