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