chiark / gitweb /
c780f71881abf407b447ab2ac30ec916fa363091
[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 <linux/rtnetlink.h>
23 #include <netinet/in.h>
24 #include <netinet/ether.h>
25 #include <stdbool.h>
26 #include <unistd.h>
27 #include <linux/veth.h>
28
29 #include "util.h"
30 #include "refcnt.h"
31
32 #include "sd-rtnl.h"
33 #include "rtnl-util.h"
34 #include "rtnl-internal.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 NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
38 #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
40
41 int message_new(sd_rtnl_message **ret, size_t initial_size) {
42         sd_rtnl_message *m;
43
44         assert_return(ret, -EINVAL);
45         assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
46
47         m = new0(sd_rtnl_message, 1);
48         if (!m)
49                 return -ENOMEM;
50
51         m->hdr = malloc0(initial_size);
52         if (!m->hdr) {
53                 free(m);
54                 return -ENOMEM;
55         }
56
57         m->n_ref = REFCNT_INIT;
58
59         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
60         m->sealed = false;
61
62         *ret = m;
63
64         return 0;
65 }
66
67 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
68         struct rtmsg *rtm;
69
70         assert_return(m, -EINVAL);
71         assert_return(m->hdr, -EINVAL);
72         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
73
74         rtm = NLMSG_DATA(m->hdr);
75
76         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
77             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
78                 return -ERANGE;
79
80         rtm->rtm_dst_len = prefixlen;
81
82         return 0;
83 }
84
85 int sd_rtnl_message_new_route(uint16_t nlmsg_type, unsigned char rtm_family,
86                               sd_rtnl_message **ret) {
87         struct rtmsg *rtm;
88         int r;
89
90         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
91         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
92         assert_return(ret, -EINVAL);
93
94         r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
95         if (r < 0)
96                 return r;
97
98         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
99         (*ret)->hdr->nlmsg_type = nlmsg_type;
100         if (nlmsg_type == RTM_NEWROUTE)
101                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
102
103         rtm = NLMSG_DATA((*ret)->hdr);
104
105         UPDATE_RTA(*ret, RTM_RTA(rtm));
106
107         rtm->rtm_family = rtm_family;
108         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
109         rtm->rtm_type = RTN_UNICAST;
110         rtm->rtm_table = RT_TABLE_MAIN;
111         rtm->rtm_protocol = RTPROT_BOOT;
112
113         return 0;
114 }
115
116 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
117         struct ifinfomsg *ifi;
118
119         assert_return(m, -EINVAL);
120         assert_return(m->hdr, -EINVAL);
121         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
122
123         ifi = NLMSG_DATA(m->hdr);
124
125         ifi->ifi_flags = flags;
126         if (change)
127                 ifi->ifi_change = change;
128         else
129                 ifi->ifi_change = 0xffffffff;
130
131         return 0;
132 }
133
134 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
135         struct ifinfomsg *ifi;
136
137         assert_return(m, -EINVAL);
138         assert_return(m->hdr, -EINVAL);
139         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
140
141         ifi = NLMSG_DATA(m->hdr);
142
143         ifi->ifi_type = type;
144
145         return 0;
146 }
147
148 int sd_rtnl_message_new_link(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
149         struct ifinfomsg *ifi;
150         int r;
151
152         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
153         assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
154         assert_return(ret, -EINVAL);
155
156         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
157         if (r < 0)
158                 return r;
159
160         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
161         (*ret)->hdr->nlmsg_type = nlmsg_type;
162         if (nlmsg_type == RTM_NEWLINK)
163                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
164
165         ifi = NLMSG_DATA((*ret)->hdr);
166
167         ifi->ifi_family = AF_UNSPEC;
168         ifi->ifi_index = index;
169
170         UPDATE_RTA(*ret, IFLA_RTA(ifi));
171
172         return 0;
173 }
174
175 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
176         struct ifaddrmsg *ifa;
177
178         assert_return(m, -EINVAL);
179         assert_return(m->hdr, -EINVAL);
180         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
181
182         ifa = NLMSG_DATA(m->hdr);
183
184         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
185             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
186                 return -ERANGE;
187
188         ifa->ifa_prefixlen = prefixlen;
189
190         return 0;
191 }
192
193 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
194         struct ifaddrmsg *ifa;
195
196         assert_return(m, -EINVAL);
197         assert_return(m->hdr, -EINVAL);
198         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
199
200         ifa = NLMSG_DATA(m->hdr);
201
202         ifa->ifa_flags = flags;
203
204         return 0;
205 }
206
207 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
208         struct ifaddrmsg *ifa;
209
210         assert_return(m, -EINVAL);
211         assert_return(m->hdr, -EINVAL);
212         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
213
214         ifa = NLMSG_DATA(m->hdr);
215
216         ifa->ifa_scope = scope;
217
218         return 0;
219 }
220
221 int sd_rtnl_message_new_addr(uint16_t nlmsg_type, int index, unsigned char family,
222                              sd_rtnl_message **ret) {
223         struct ifaddrmsg *ifa;
224         int r;
225
226         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
227         assert_return(index > 0, -EINVAL);
228         assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
229         assert_return(ret, -EINVAL);
230
231         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
232         if (r < 0)
233                 return r;
234
235         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
236         (*ret)->hdr->nlmsg_type = nlmsg_type;
237
238         ifa = NLMSG_DATA((*ret)->hdr);
239
240         ifa->ifa_index = index;
241         ifa->ifa_family = family;
242         if (family == AF_INET)
243                 ifa->ifa_prefixlen = 32;
244         else if (family == AF_INET6)
245                 ifa->ifa_prefixlen = 128;
246
247         UPDATE_RTA(*ret, IFA_RTA(ifa));
248
249         return 0;
250 }
251
252 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
253         if (m)
254                 assert_se(REFCNT_INC(m->n_ref) >= 2);
255
256         return m;
257 }
258
259 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
260         if (m && REFCNT_DEC(m->n_ref) <= 0) {
261                 free(m->hdr);
262                 free(m);
263         }
264
265         return NULL;
266 }
267
268 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
269         assert_return(m, -EINVAL);
270         assert_return(type, -EINVAL);
271
272         *type = m->hdr->nlmsg_type;
273
274         return 0;
275 }
276
277 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
278         struct ifinfomsg *ifi;
279
280         assert_return(m, -EINVAL);
281         assert_return(m->hdr, -EINVAL);
282         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
283         assert_return(ifindex, -EINVAL);
284
285         ifi = NLMSG_DATA(m->hdr);
286
287         *ifindex = ifi->ifi_index;
288
289         return 0;
290 }
291
292 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
293         struct ifinfomsg *ifi;
294
295         assert_return(m, -EINVAL);
296         assert_return(m->hdr, -EINVAL);
297         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
298         assert_return(flags, -EINVAL);
299
300         ifi = NLMSG_DATA(m->hdr);
301
302         *flags = ifi->ifi_flags;
303
304         return 0;
305 }
306
307 /* If successful the updated message will be correctly aligned, if
308    unsuccessful the old message is untouched. */
309 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
310         uint32_t rta_length, message_length;
311         struct nlmsghdr *new_hdr;
312         struct rtattr *rta;
313         char *padding;
314         unsigned i;
315
316         assert(m);
317         assert(m->hdr);
318         assert(!m->sealed);
319         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
320         assert(!data || data_length > 0);
321         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
322
323         /* get the size of the new rta attribute (with padding at the end) */
324         rta_length = RTA_LENGTH(data_length);
325
326         /* get the new message size (with padding at the end) */
327         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
328
329         /* realloc to fit the new attribute */
330         new_hdr = realloc(m->hdr, message_length);
331         if (!new_hdr)
332                 return -ENOMEM;
333         m->hdr = new_hdr;
334
335         /* get pointer to the attribute we are about to add */
336         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
337
338         /* if we are inside containers, extend them */
339         for (i = 0; i < m->n_containers; i++)
340                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
341
342         /* fill in the attribute */
343         rta->rta_type = type;
344         rta->rta_len = rta_length;
345         if (!data) {
346                 /* this is the start of a new container */
347                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
348         } else {
349                 /* we don't deal with the case where the user lies about the type
350                  * and gives us too little data (so don't do that)
351                 */
352                 padding = mempcpy(RTA_DATA(rta), data, data_length);
353                 /* make sure also the padding at the end of the message is initialized */
354                 memzero(padding,
355                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
356         }
357
358         /* update message size */
359         m->hdr->nlmsg_len = message_length;
360
361         return 0;
362 }
363
364 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
365         uint16_t rtm_type;
366         int r;
367
368         assert_return(m, -EINVAL);
369         assert_return(!m->sealed, -EPERM);
370         assert_return(data, -EINVAL);
371
372         r = sd_rtnl_message_get_type(m, &rtm_type);
373         if (r < 0)
374                 return r;
375
376         /* check that the type is correct */
377         switch (rtm_type) {
378                 case RTM_NEWLINK:
379                 case RTM_SETLINK:
380                 case RTM_GETLINK:
381                 case RTM_DELLINK:
382                         if (m->n_containers == 1) {
383                                 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
384                                     type != IFLA_INFO_KIND)
385                                         return -ENOTSUP;
386                         } else {
387                                 switch (type) {
388                                         case IFLA_IFNAME:
389                                         case IFLA_IFALIAS:
390                                         case IFLA_QDISC:
391                                                 break;
392                                         default:
393                                                 return -ENOTSUP;
394                                 }
395                         }
396                         break;
397                 case RTM_NEWADDR:
398                 case RTM_GETADDR:
399                 case RTM_DELADDR:
400                         if (type != IFA_LABEL)
401                                 return -ENOTSUP;
402                         break;
403                 default:
404                         return -ENOTSUP;
405         }
406
407         r = add_rtattr(m, type, data, strlen(data) + 1);
408         if (r < 0)
409                 return r;
410
411         return 0;
412 }
413
414 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
415         uint16_t rtm_type;
416         int r;
417
418         assert_return(m, -EINVAL);
419         assert_return(!m->sealed, -EPERM);
420
421         r = sd_rtnl_message_get_type(m, &rtm_type);
422         if (r < 0)
423                 return r;
424
425         switch (rtm_type) {
426                 case RTM_NEWLINK:
427                 case RTM_SETLINK:
428                 case RTM_GETLINK:
429                 case RTM_DELLINK:
430                         switch (type) {
431                                 case IFLA_CARRIER:
432                                 case IFLA_OPERSTATE:
433                                 case IFLA_LINKMODE:
434                                 break;
435                         default:
436                                 return -ENOTSUP;
437                         }
438
439                         break;
440                 default:
441                         return -ENOTSUP;
442         }
443
444         r = add_rtattr(m, type, &data, sizeof(uint8_t));
445         if (r < 0)
446                 return r;
447
448         return 0;
449 }
450
451
452 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
453         uint16_t rtm_type;
454         int r;
455
456         assert_return(m, -EINVAL);
457         assert_return(!m->sealed, -EPERM);
458
459         r = sd_rtnl_message_get_type(m, &rtm_type);
460         if (r < 0)
461                 return r;
462
463         /* check that the type is correct */
464         switch (rtm_type) {
465                 case RTM_NEWLINK:
466                 case RTM_SETLINK:
467                 case RTM_GETLINK:
468                 case RTM_DELLINK:
469                         if (m->n_containers == 2 &&
470                             GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
471                             GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
472                             type == IFLA_VLAN_ID)
473                                 break;
474                         else
475                                 return -ENOTSUP;
476                         break;
477                 default:
478                         return -ENOTSUP;
479         }
480
481         r = add_rtattr(m, type, &data, sizeof(uint16_t));
482         if (r < 0)
483                 return r;
484
485         return 0;
486 }
487
488 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
489         uint16_t rtm_type;
490         int r;
491
492         assert_return(m, -EINVAL);
493         assert_return(!m->sealed, -EPERM);
494
495         r = sd_rtnl_message_get_type(m, &rtm_type);
496         if (r < 0)
497                 return r;
498
499         /* check that the type is correct */
500         switch (rtm_type) {
501                 case RTM_NEWLINK:
502                 case RTM_SETLINK:
503                 case RTM_GETLINK:
504                 case RTM_DELLINK:
505                         switch (type) {
506                                 case IFLA_MASTER:
507                                 case IFLA_MTU:
508                                 case IFLA_LINK:
509                                 case IFLA_GROUP:
510                                 case IFLA_TXQLEN:
511                                 case IFLA_WEIGHT:
512                                 case IFLA_NET_NS_FD:
513                                 case IFLA_NET_NS_PID:
514                                 case IFLA_PROMISCUITY:
515                                 case IFLA_NUM_TX_QUEUES:
516                                 case IFLA_NUM_RX_QUEUES:
517                                         break;
518                                 default:
519                                         return -ENOTSUP;
520                         }
521                         break;
522                 case RTM_NEWROUTE:
523                 case RTM_GETROUTE:
524                 case RTM_DELROUTE:
525                         switch (type) {
526                                 case RTA_TABLE:
527                                 case RTA_PRIORITY:
528                                 case RTA_IIF:
529                                 case RTA_OIF:
530                                 case RTA_MARK:
531                                         break;
532                                 default:
533                                         return -ENOTSUP;
534                         }
535                         break;
536                 default:
537                         return -ENOTSUP;
538         }
539
540         r = add_rtattr(m, type, &data, sizeof(uint32_t));
541         if (r < 0)
542                 return r;
543
544         return 0;
545 }
546
547 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
548         struct ifaddrmsg *ifa;
549         struct rtmsg *rtm;
550         uint16_t rtm_type;
551         int r;
552
553         assert_return(m, -EINVAL);
554         assert_return(!m->sealed, -EPERM);
555         assert_return(data, -EINVAL);
556
557         r = sd_rtnl_message_get_type(m, &rtm_type);
558         if (r < 0)
559                 return r;
560
561         /* check that the type is correct */
562         switch (rtm_type) {
563                 case RTM_NEWADDR:
564                 case RTM_GETADDR:
565                 case RTM_DELADDR:
566                         switch (type) {
567                                 case IFA_ADDRESS:
568                                 case IFA_LOCAL:
569                                 case IFA_BROADCAST:
570                                 case IFA_ANYCAST:
571                                         ifa = NLMSG_DATA(m->hdr);
572
573                                         if (ifa->ifa_family != AF_INET)
574                                                 return -EINVAL;
575
576                                         break;
577                                 default:
578                                         return -ENOTSUP;
579                         }
580                         break;
581                 case RTM_NEWROUTE:
582                 case RTM_GETROUTE:
583                 case RTM_DELROUTE:
584                         switch (type) {
585                                 case RTA_DST:
586                                 case RTA_SRC:
587                                 case RTA_GATEWAY:
588                                         rtm = NLMSG_DATA(m->hdr);
589
590                                         if (rtm->rtm_family != AF_INET)
591                                                 return -EINVAL;
592
593                                         break;
594                                 default:
595                                         return -ENOTSUP;
596                         }
597                         break;
598                 default:
599                         return -ENOTSUP;
600         }
601
602         r = add_rtattr(m, type, data, sizeof(struct in_addr));
603         if (r < 0)
604                 return r;
605
606         return 0;
607 }
608
609 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
610         struct ifaddrmsg *ifa;
611         struct rtmsg *rtm;
612         uint16_t rtm_type;
613         int r;
614
615         assert_return(m, -EINVAL);
616         assert_return(!m->sealed, -EPERM);
617         assert_return(data, -EINVAL);
618
619         r = sd_rtnl_message_get_type(m, &rtm_type);
620         if (r < 0)
621                 return r;
622
623         /* check that the type is correct */
624         switch (rtm_type) {
625                 case RTM_NEWADDR:
626                 case RTM_GETADDR:
627                 case RTM_DELADDR:
628                         switch (type) {
629                                 case IFA_ADDRESS:
630                                 case IFA_LOCAL:
631                                 case IFA_BROADCAST:
632                                 case IFA_ANYCAST:
633                                         ifa = NLMSG_DATA(m->hdr);
634
635                                         if (ifa->ifa_family != AF_INET6)
636                                                 return -EINVAL;
637
638                                         break;
639                                 default:
640                                         return -ENOTSUP;
641                         }
642                         break;
643                 case RTM_NEWROUTE:
644                 case RTM_GETROUTE:
645                 case RTM_DELROUTE:
646                         switch (type) {
647                                 case RTA_DST:
648                                 case RTA_SRC:
649                                 case RTA_GATEWAY:
650                                         rtm = NLMSG_DATA(m->hdr);
651
652                                         if (rtm->rtm_family != AF_INET6)
653                                                 return -EINVAL;
654
655                                         break;
656                                 default:
657                                         return -ENOTSUP;
658                         }
659                 default:
660                         return -ENOTSUP;
661         }
662
663         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
664         if (r < 0)
665                 return r;
666
667         return 0;
668 }
669
670 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
671         uint16_t rtm_type;
672         int r;
673
674         assert_return(m, -EINVAL);
675         assert_return(!m->sealed, -EPERM);
676         assert_return(data, -EINVAL);
677
678         sd_rtnl_message_get_type(m, &rtm_type);
679
680         switch (rtm_type) {
681                 case RTM_NEWLINK:
682                 case RTM_SETLINK:
683                 case RTM_DELLINK:
684                 case RTM_GETLINK:
685                         switch (type) {
686                                 case IFLA_ADDRESS:
687                                 case IFLA_BROADCAST:
688                                         break;
689                                 default:
690                                         return -ENOTSUP;
691                         }
692                         break;
693                 default:
694                         return -ENOTSUP;
695         }
696
697         r = add_rtattr(m, type, data, ETH_ALEN);
698         if (r < 0)
699                 return r;
700
701         return 0;
702 }
703
704 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type, size_t extra) {
705         uint16_t rtm_type;
706
707         assert_return(m, -EINVAL);
708         assert_return(!m->sealed, -EPERM);
709
710         sd_rtnl_message_get_type(m, &rtm_type);
711
712         if (rtnl_message_type_is_link(rtm_type)) {
713
714                 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
715                     (type == IFLA_INFO_DATA && m->n_containers == 1 && GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO) ||
716                     (type == VETH_INFO_PEER && m->n_containers == 2 && GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA))
717                         return add_rtattr(m, type, NULL, extra);
718         }
719
720         return -ENOTSUP;
721 }
722
723 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
724         assert_return(m, -EINVAL);
725         assert_return(!m->sealed, -EPERM);
726         assert_return(m->n_containers > 0, -EINVAL);
727
728         m->n_containers --;
729
730         return 0;
731 }
732
733 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
734         size_t remaining_size;
735         uint16_t rtm_type;
736         int r;
737
738         assert_return(m, -EINVAL);
739         assert_return(m->sealed, -EPERM);
740         assert_return(m->next_rta_offset, -EINVAL);
741         assert_return(type, -EINVAL);
742         assert_return(data, -EINVAL);
743
744         /* only read until the end of the current container */
745         if (m->n_containers)
746                 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
747                                  (m->next_rta_offset -
748                                   m->container_offsets[m->n_containers - 1]);
749         else
750                 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
751
752         if (!RTA_OK(NEXT_RTA(m), remaining_size))
753                 return 0;
754
755         /* if we read a container, enter it and return its type */
756         r = sd_rtnl_message_get_type(m, &rtm_type);
757         if (r < 0)
758                 return r;
759
760         *type = NEXT_RTA(m)->rta_type;
761
762         if (rtnl_message_type_is_link(rtm_type) &&
763             ((m->n_containers == 0 &&
764               NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
765              (m->n_containers == 1 &&
766               GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
767               NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
768                 *data = NULL;
769                 PUSH_CONTAINER(m, NEXT_RTA(m));
770                 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
771         } else {
772                 *data = RTA_DATA(NEXT_RTA(m));
773                 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
774         }
775
776         return 1;
777 }
778
779 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
780         assert_return(m, -EINVAL);
781         assert_return(m->sealed, -EINVAL);
782         assert_return(m->n_containers > 0, -EINVAL);
783
784         m->n_containers --;
785
786         return 0;
787 }
788
789 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
790         assert(m);
791         assert(m->hdr);
792
793         return m->hdr->nlmsg_seq;
794 }
795
796 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
797         struct nlmsgerr *err;
798
799         assert_return(m, -EINVAL);
800         assert_return(m->hdr, -EINVAL);
801
802         if (m->hdr->nlmsg_type != NLMSG_ERROR)
803                 return 0;
804
805         err = NLMSG_DATA(m->hdr);
806
807         return err->error;
808 }
809
810 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
811         int r;
812
813         assert(m);
814         assert(m->hdr);
815
816         if (m->sealed)
817                 return -EPERM;
818
819         if (nl)
820                 m->hdr->nlmsg_seq = nl->serial++;
821
822         m->sealed = true;
823
824         r = sd_rtnl_message_rewind(m);
825         if (r < 0)
826                 return r;
827
828         return 0;
829 }
830
831 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
832         assert(rtnl);
833         assert(need);
834
835         /* ioctl(rtnl->fd, FIONREAD, &need)
836            Does not appear to work on netlink sockets. libnl uses
837            MSG_PEEK instead. I don't know if that is worth the
838            extra roundtrip.
839
840            For now we simply use the maximum message size the kernel
841            may use (NLMSG_GOODSIZE), and then realloc to the actual
842            size after reading the message (hence avoiding huge memory
843            usage in case many small messages are kept around) */
844         *need = page_size();
845         if (*need > 8192UL)
846                 *need = 8192UL;
847
848         return 0;
849 }
850
851 /* returns the number of bytes sent, or a negative error code */
852 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
853         union {
854                 struct sockaddr sa;
855                 struct sockaddr_nl nl;
856         } addr = {
857                 .nl.nl_family = AF_NETLINK,
858         };
859         ssize_t k;
860
861         assert(nl);
862         assert(m);
863         assert(m->hdr);
864
865         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
866                         0, &addr.sa, sizeof(addr));
867         if (k < 0)
868                 return (errno == EAGAIN) ? 0 : -errno;
869
870         return k;
871 }
872
873 /* On success, the number of bytes received is returned and *ret points to the received message
874  * which has a valid header and the correct size.
875  * If nothing useful was received 0 is returned.
876  * On failure, a negative error code is returned.
877  */
878 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
879         sd_rtnl_message *m;
880         union {
881                 struct sockaddr sa;
882                 struct sockaddr_nl nl;
883         } addr;
884         socklen_t addr_len;
885         int r;
886         ssize_t k;
887         size_t need;
888
889         assert(nl);
890         assert(ret);
891
892         r = message_receive_need(nl, &need);
893         if (r < 0)
894                 return r;
895
896         r = message_new(&m, need);
897         if (r < 0)
898                 return r;
899
900         /* don't allow sealing/appending to received messages */
901         m->sealed = true;
902
903         addr_len = sizeof(addr);
904
905         k = recvfrom(nl->fd, m->hdr, need,
906                         0, &addr.sa, &addr_len);
907         if (k < 0)
908                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
909         else if (k == 0)
910                 k = -ECONNRESET; /* connection was closed by the kernel */
911         else if (addr_len != sizeof(addr.nl) ||
912                         addr.nl.nl_family != AF_NETLINK)
913                 k = -EIO; /* not a netlink message */
914         else if (addr.nl.nl_pid != 0)
915                 k = 0; /* not from the kernel */
916         else if ((size_t) k < sizeof(struct nlmsghdr) ||
917                         (size_t) k < m->hdr->nlmsg_len)
918                 k = -EIO; /* too small (we do accept too big though) */
919         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
920                 k = 0; /* not broadcast and not for us */
921
922         if (k > 0)
923                 switch (m->hdr->nlmsg_type) {
924                         struct ifinfomsg *ifi;
925                         struct ifaddrmsg *ifa;
926                         struct rtmsg *rtm;
927
928                         /* check that the size matches the message type */
929                         case NLMSG_ERROR:
930                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
931                                         k = -EIO;
932                                 break;
933                         case RTM_NEWLINK:
934                         case RTM_SETLINK:
935                         case RTM_DELLINK:
936                         case RTM_GETLINK:
937                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
938                                         k = -EIO;
939                                 else {
940                                         ifi = NLMSG_DATA(m->hdr);
941                                         UPDATE_RTA(m, IFLA_RTA(ifi));
942                                 }
943                                 break;
944                         case RTM_NEWADDR:
945                         case RTM_DELADDR:
946                         case RTM_GETADDR:
947                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
948                                         k = -EIO;
949                                 else {
950                                         ifa = NLMSG_DATA(m->hdr);
951                                         UPDATE_RTA(m, IFA_RTA(ifa));
952                                 }
953                                 break;
954                         case RTM_NEWROUTE:
955                         case RTM_DELROUTE:
956                         case RTM_GETROUTE:
957                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
958                                         k = -EIO;
959                                 else {
960                                         rtm = NLMSG_DATA(m->hdr);
961                                         UPDATE_RTA(m, RTM_RTA(rtm));
962                                 }
963                                 break;
964                         case NLMSG_NOOP:
965                                 k = 0;
966                                 break;
967                         default:
968                                 k = 0; /* ignoring message of unknown type */
969                 }
970
971         if (k <= 0)
972                 sd_rtnl_message_unref(m);
973         else {
974                 /* we probably allocated way too much memory, give it back */
975                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
976                 *ret = m;
977         }
978
979         return k;
980 }
981
982 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
983         struct ifinfomsg *ifi;
984         struct ifaddrmsg *ifa;
985         struct rtmsg *rtm;
986
987         assert_return(m, -EINVAL);
988         assert_return(m->sealed, -EPERM);
989         assert_return(m->hdr, -EINVAL);
990
991         switch(m->hdr->nlmsg_type) {
992                 case RTM_NEWLINK:
993                 case RTM_SETLINK:
994                 case RTM_GETLINK:
995                 case RTM_DELLINK:
996                         ifi = NLMSG_DATA(m->hdr);
997                         UPDATE_RTA(m, IFLA_RTA(ifi));
998
999                         break;
1000                 case RTM_NEWADDR:
1001                 case RTM_GETADDR:
1002                 case RTM_DELADDR:
1003                         ifa = NLMSG_DATA(m->hdr);
1004                         UPDATE_RTA(m, IFA_RTA(ifa));
1005
1006                         break;
1007                 case RTM_NEWROUTE:
1008                 case RTM_GETROUTE:
1009                 case RTM_DELROUTE:
1010                         rtm = NLMSG_DATA(m->hdr);
1011                         UPDATE_RTA(m, RTM_RTA(rtm));
1012
1013                         break;
1014                 default:
1015                         return -ENOTSUP;
1016         }
1017
1018         m->n_containers = 0;
1019
1020         return 0;
1021 }