chiark / gitweb /
sd-rtnl: message - don't try to enter unsupported containers
[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 #include <linux/if_bridge.h>
28
29 #include "util.h"
30 #include "refcnt.h"
31 #include "missing.h"
32
33 #include "sd-rtnl.h"
34 #include "rtnl-util.h"
35 #include "rtnl-internal.h"
36
37 #define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
38 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
39
40 int message_new(sd_rtnl *rtnl, sd_rtnl_message **ret, size_t initial_size) {
41         sd_rtnl_message *m;
42
43         assert_return(ret, -EINVAL);
44         assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
45
46         m = new0(sd_rtnl_message, 1);
47         if (!m)
48                 return -ENOMEM;
49
50         m->hdr = malloc0(initial_size);
51         if (!m->hdr) {
52                 free(m);
53                 return -ENOMEM;
54         }
55
56         m->n_ref = REFCNT_INIT;
57
58         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
59         m->sealed = false;
60
61         if (rtnl)
62                 m->rtnl = sd_rtnl_ref(rtnl);
63
64         *ret = m;
65
66         return 0;
67 }
68
69 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
70         struct rtmsg *rtm;
71
72         assert_return(m, -EINVAL);
73         assert_return(m->hdr, -EINVAL);
74         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
75
76         rtm = NLMSG_DATA(m->hdr);
77
78         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
79             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
80                 return -ERANGE;
81
82         rtm->rtm_dst_len = prefixlen;
83
84         return 0;
85 }
86
87 int sd_rtnl_message_route_set_scope(sd_rtnl_message *m, unsigned char scope) {
88         struct rtmsg *rtm;
89
90         assert_return(m, -EINVAL);
91         assert_return(m->hdr, -EINVAL);
92         assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
93
94         rtm = NLMSG_DATA(m->hdr);
95
96         rtm->rtm_scope = scope;
97
98         return 0;
99 }
100
101 int sd_rtnl_message_new_route(sd_rtnl *rtnl, sd_rtnl_message **ret,
102                               uint16_t nlmsg_type, unsigned char rtm_family) {
103         struct rtmsg *rtm;
104         int r;
105
106         assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
107         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
108         assert_return(ret, -EINVAL);
109
110         r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct rtmsg)));
111         if (r < 0)
112                 return r;
113
114         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
115         (*ret)->hdr->nlmsg_type = nlmsg_type;
116         if (nlmsg_type == RTM_NEWROUTE)
117                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
118
119         rtm = NLMSG_DATA((*ret)->hdr);
120
121         rtm->rtm_family = rtm_family;
122         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
123         rtm->rtm_type = RTN_UNICAST;
124         rtm->rtm_table = RT_TABLE_MAIN;
125         rtm->rtm_protocol = RTPROT_BOOT;
126
127         return 0;
128 }
129
130 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
131         struct ifinfomsg *ifi;
132
133         assert_return(m, -EINVAL);
134         assert_return(m->hdr, -EINVAL);
135         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
136         assert_return(change, -EINVAL);
137
138         ifi = NLMSG_DATA(m->hdr);
139
140         ifi->ifi_flags = flags;
141         ifi->ifi_change = change;
142
143         return 0;
144 }
145
146 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
147         struct ifinfomsg *ifi;
148
149         assert_return(m, -EINVAL);
150         assert_return(m->hdr, -EINVAL);
151         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
152
153         ifi = NLMSG_DATA(m->hdr);
154
155         ifi->ifi_type = type;
156
157         return 0;
158 }
159
160 int sd_rtnl_message_new_link(sd_rtnl *rtnl, sd_rtnl_message **ret,
161                              uint16_t nlmsg_type, int index) {
162         struct ifinfomsg *ifi;
163         int r;
164
165         assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
166         assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
167         assert_return(ret, -EINVAL);
168
169         r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
170         if (r < 0)
171                 return r;
172
173         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
174         (*ret)->hdr->nlmsg_type = nlmsg_type;
175         if (nlmsg_type == RTM_NEWLINK)
176                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
177
178         ifi = NLMSG_DATA((*ret)->hdr);
179
180         ifi->ifi_family = AF_UNSPEC;
181         ifi->ifi_index = index;
182
183         return 0;
184 }
185
186 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
187         struct ifaddrmsg *ifa;
188
189         assert_return(m, -EINVAL);
190         assert_return(m->hdr, -EINVAL);
191         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
192
193         ifa = NLMSG_DATA(m->hdr);
194
195         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
196             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
197                 return -ERANGE;
198
199         ifa->ifa_prefixlen = prefixlen;
200
201         return 0;
202 }
203
204 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
205         struct ifaddrmsg *ifa;
206
207         assert_return(m, -EINVAL);
208         assert_return(m->hdr, -EINVAL);
209         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
210
211         ifa = NLMSG_DATA(m->hdr);
212
213         ifa->ifa_flags = flags;
214
215         return 0;
216 }
217
218 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
219         struct ifaddrmsg *ifa;
220
221         assert_return(m, -EINVAL);
222         assert_return(m->hdr, -EINVAL);
223         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
224
225         ifa = NLMSG_DATA(m->hdr);
226
227         ifa->ifa_scope = scope;
228
229         return 0;
230 }
231
232 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
233                              uint16_t nlmsg_type, int index,
234                              unsigned char family) {
235         struct ifaddrmsg *ifa;
236         int r;
237
238         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
239         assert_return(index > 0, -EINVAL);
240         assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
241         assert_return(ret, -EINVAL);
242
243         r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
244         if (r < 0)
245                 return r;
246
247         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
248         (*ret)->hdr->nlmsg_type = nlmsg_type;
249         if (nlmsg_type == RTM_GETADDR && family == AF_INET)
250                 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
251
252         ifa = NLMSG_DATA((*ret)->hdr);
253
254         ifa->ifa_index = index;
255         ifa->ifa_family = family;
256         if (family == AF_INET)
257                 ifa->ifa_prefixlen = 32;
258         else if (family == AF_INET6)
259                 ifa->ifa_prefixlen = 128;
260
261         return 0;
262 }
263
264 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
265         if (m)
266                 assert_se(REFCNT_INC(m->n_ref) >= 2);
267
268         return m;
269 }
270
271 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
272         if (m && REFCNT_DEC(m->n_ref) <= 0) {
273                 unsigned i;
274
275                 sd_rtnl_unref(m->rtnl);
276                 free(m->hdr);
277
278                 for (i = 0; i < m->n_containers; i++)
279                         free(m->rta_offset_tb[i]);
280
281                 free(m);
282         }
283
284         return NULL;
285 }
286
287 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
288         assert_return(m, -EINVAL);
289         assert_return(type, -EINVAL);
290
291         *type = m->hdr->nlmsg_type;
292
293         return 0;
294 }
295
296 int sd_rtnl_message_is_broadcast(sd_rtnl_message *m) {
297         assert_return(m, -EINVAL);
298
299         return !m->hdr->nlmsg_pid;
300 }
301
302 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
303         struct ifinfomsg *ifi;
304
305         assert_return(m, -EINVAL);
306         assert_return(m->hdr, -EINVAL);
307         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
308         assert_return(ifindex, -EINVAL);
309
310         ifi = NLMSG_DATA(m->hdr);
311
312         *ifindex = ifi->ifi_index;
313
314         return 0;
315 }
316
317 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
318         struct ifinfomsg *ifi;
319
320         assert_return(m, -EINVAL);
321         assert_return(m->hdr, -EINVAL);
322         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
323         assert_return(flags, -EINVAL);
324
325         ifi = NLMSG_DATA(m->hdr);
326
327         *flags = ifi->ifi_flags;
328
329         return 0;
330 }
331
332 /* If successful the updated message will be correctly aligned, if
333    unsuccessful the old message is untouched. */
334 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
335         uint32_t rta_length, message_length;
336         struct nlmsghdr *new_hdr;
337         struct rtattr *rta;
338         char *padding;
339         unsigned i;
340
341         assert(m);
342         assert(m->hdr);
343         assert(!m->sealed);
344         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
345         assert(!data || data_length > 0);
346         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
347
348         /* get the size of the new rta attribute (with padding at the end) */
349         rta_length = RTA_LENGTH(data_length);
350
351         /* get the new message size (with padding at the end) */
352         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
353
354         /* realloc to fit the new attribute */
355         new_hdr = realloc(m->hdr, message_length);
356         if (!new_hdr)
357                 return -ENOMEM;
358         m->hdr = new_hdr;
359
360         /* get pointer to the attribute we are about to add */
361         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
362
363         /* if we are inside containers, extend them */
364         for (i = 0; i < m->n_containers; i++)
365                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
366
367         /* fill in the attribute */
368         rta->rta_type = type;
369         rta->rta_len = rta_length;
370         if (!data) {
371                 /* this is the start of a new container */
372                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
373         } else {
374                 /* we don't deal with the case where the user lies about the type
375                  * and gives us too little data (so don't do that)
376                 */
377                 padding = mempcpy(RTA_DATA(rta), data, data_length);
378                 /* make sure also the padding at the end of the message is initialized */
379                 memzero(padding,
380                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
381         }
382
383         /* update message size */
384         m->hdr->nlmsg_len = message_length;
385
386         return 0;
387 }
388
389 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
390         uint16_t rtm_type;
391         int r;
392
393         assert_return(m, -EINVAL);
394         assert_return(!m->sealed, -EPERM);
395         assert_return(data, -EINVAL);
396
397         r = sd_rtnl_message_get_type(m, &rtm_type);
398         if (r < 0)
399                 return r;
400
401         /* check that the type is correct */
402         switch (rtm_type) {
403                 case RTM_NEWLINK:
404                 case RTM_SETLINK:
405                 case RTM_GETLINK:
406                 case RTM_DELLINK:
407                         if (m->n_containers == 1) {
408                                 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
409                                     type != IFLA_INFO_KIND)
410                                         return -ENOTSUP;
411                         } else {
412                                 switch (type) {
413                                         case IFLA_IFNAME:
414                                         case IFLA_IFALIAS:
415                                         case IFLA_QDISC:
416                                                 break;
417                                         default:
418                                                 return -ENOTSUP;
419                                 }
420                         }
421                         break;
422                 case RTM_NEWADDR:
423                 case RTM_GETADDR:
424                 case RTM_DELADDR:
425                         if (type != IFA_LABEL)
426                                 return -ENOTSUP;
427                         break;
428                 default:
429                         return -ENOTSUP;
430         }
431
432         r = add_rtattr(m, type, data, strlen(data) + 1);
433         if (r < 0)
434                 return r;
435
436         return 0;
437 }
438
439 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
440         uint16_t rtm_type;
441         int r;
442
443         assert_return(m, -EINVAL);
444         assert_return(!m->sealed, -EPERM);
445
446         r = sd_rtnl_message_get_type(m, &rtm_type);
447         if (r < 0)
448                 return r;
449
450         switch (rtm_type) {
451                 case RTM_NEWLINK:
452                 case RTM_SETLINK:
453                 case RTM_GETLINK:
454                 case RTM_DELLINK:
455                         switch (type) {
456                                 case IFLA_CARRIER:
457                                 case IFLA_OPERSTATE:
458                                 case IFLA_LINKMODE:
459                                 break;
460                         default:
461                                 return -ENOTSUP;
462                         }
463
464                         break;
465                 default:
466                         return -ENOTSUP;
467         }
468
469         r = add_rtattr(m, type, &data, sizeof(uint8_t));
470         if (r < 0)
471                 return r;
472
473         return 0;
474 }
475
476
477 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
478         uint16_t rtm_type;
479         int r;
480
481         assert_return(m, -EINVAL);
482         assert_return(!m->sealed, -EPERM);
483
484         r = sd_rtnl_message_get_type(m, &rtm_type);
485         if (r < 0)
486                 return r;
487
488         /* check that the type is correct */
489         switch (rtm_type) {
490                 case RTM_NEWLINK:
491                 case RTM_SETLINK:
492                 case RTM_GETLINK:
493                 case RTM_DELLINK:
494                         if (m->n_containers == 2 &&
495                             GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
496                             GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
497                             type == IFLA_VLAN_ID)
498                                 break;
499                         else
500                                 return -ENOTSUP;
501
502                 default:
503                         return -ENOTSUP;
504         }
505
506         r = add_rtattr(m, type, &data, sizeof(uint16_t));
507         if (r < 0)
508                 return r;
509
510         return 0;
511 }
512
513 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
514         uint16_t rtm_type;
515         int r;
516
517         assert_return(m, -EINVAL);
518         assert_return(!m->sealed, -EPERM);
519
520         r = sd_rtnl_message_get_type(m, &rtm_type);
521         if (r < 0)
522                 return r;
523
524         /* check that the type is correct */
525         switch (rtm_type) {
526                 case RTM_NEWLINK:
527                 case RTM_SETLINK:
528                 case RTM_GETLINK:
529                 case RTM_DELLINK:
530                         switch (type) {
531                                 case IFLA_MASTER:
532                                 case IFLA_MTU:
533                                 case IFLA_LINK:
534                                 case IFLA_GROUP:
535                                 case IFLA_TXQLEN:
536                                 case IFLA_WEIGHT:
537                                 case IFLA_NET_NS_FD:
538                                 case IFLA_NET_NS_PID:
539                                 case IFLA_PROMISCUITY:
540                                 case IFLA_NUM_TX_QUEUES:
541                                 case IFLA_NUM_RX_QUEUES:
542                                 case IFLA_MACVLAN_MODE:
543                                         break;
544                                 default:
545                                         return -ENOTSUP;
546                         }
547                         break;
548                 case RTM_NEWROUTE:
549                 case RTM_GETROUTE:
550                 case RTM_DELROUTE:
551                         switch (type) {
552                                 case RTA_TABLE:
553                                 case RTA_PRIORITY:
554                                 case RTA_IIF:
555                                 case RTA_OIF:
556                                 case RTA_MARK:
557                                         break;
558                                 default:
559                                         return -ENOTSUP;
560                         }
561                         break;
562                 default:
563                         return -ENOTSUP;
564         }
565
566         r = add_rtattr(m, type, &data, sizeof(uint32_t));
567         if (r < 0)
568                 return r;
569
570         return 0;
571 }
572
573 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
574         struct ifaddrmsg *ifa;
575         struct rtmsg *rtm;
576         uint16_t rtm_type;
577         int r;
578
579         assert_return(m, -EINVAL);
580         assert_return(!m->sealed, -EPERM);
581         assert_return(data, -EINVAL);
582
583         r = sd_rtnl_message_get_type(m, &rtm_type);
584         if (r < 0)
585                 return r;
586
587         /* check that the type is correct */
588         switch (rtm_type) {
589                 case RTM_NEWADDR:
590                 case RTM_GETADDR:
591                 case RTM_DELADDR:
592                         switch (type) {
593                                 case IFA_ADDRESS:
594                                 case IFA_LOCAL:
595                                 case IFA_BROADCAST:
596                                 case IFA_ANYCAST:
597                                         ifa = NLMSG_DATA(m->hdr);
598
599                                         if (ifa->ifa_family != AF_INET)
600                                                 return -EINVAL;
601
602                                         break;
603                                 default:
604                                         return -ENOTSUP;
605                         }
606                         break;
607                 case RTM_NEWROUTE:
608                 case RTM_GETROUTE:
609                 case RTM_DELROUTE:
610                         switch (type) {
611                                 case RTA_DST:
612                                 case RTA_SRC:
613                                 case RTA_GATEWAY:
614                                         rtm = NLMSG_DATA(m->hdr);
615
616                                         if (rtm->rtm_family != AF_INET)
617                                                 return -EINVAL;
618
619                                         break;
620                                 default:
621                                         return -ENOTSUP;
622                         }
623                         break;
624                 default:
625                         return -ENOTSUP;
626         }
627
628         r = add_rtattr(m, type, data, sizeof(struct in_addr));
629         if (r < 0)
630                 return r;
631
632         return 0;
633 }
634
635 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
636         struct ifaddrmsg *ifa;
637         struct rtmsg *rtm;
638         uint16_t rtm_type;
639         int r;
640
641         assert_return(m, -EINVAL);
642         assert_return(!m->sealed, -EPERM);
643         assert_return(data, -EINVAL);
644
645         r = sd_rtnl_message_get_type(m, &rtm_type);
646         if (r < 0)
647                 return r;
648
649         /* check that the type is correct */
650         switch (rtm_type) {
651                 case RTM_NEWADDR:
652                 case RTM_GETADDR:
653                 case RTM_DELADDR:
654                         switch (type) {
655                                 case IFA_ADDRESS:
656                                 case IFA_LOCAL:
657                                 case IFA_BROADCAST:
658                                 case IFA_ANYCAST:
659                                         ifa = NLMSG_DATA(m->hdr);
660
661                                         if (ifa->ifa_family != AF_INET6)
662                                                 return -EINVAL;
663
664                                         break;
665                                 default:
666                                         return -ENOTSUP;
667                         }
668                         break;
669                 case RTM_NEWROUTE:
670                 case RTM_GETROUTE:
671                 case RTM_DELROUTE:
672                         switch (type) {
673                                 case RTA_DST:
674                                 case RTA_SRC:
675                                 case RTA_GATEWAY:
676                                         rtm = NLMSG_DATA(m->hdr);
677
678                                         if (rtm->rtm_family != AF_INET6)
679                                                 return -EINVAL;
680
681                                         break;
682                                 default:
683                                         return -ENOTSUP;
684                         }
685                 default:
686                         return -ENOTSUP;
687         }
688
689         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
690         if (r < 0)
691                 return r;
692
693         return 0;
694 }
695
696 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
697         uint16_t rtm_type;
698         int r;
699
700         assert_return(m, -EINVAL);
701         assert_return(!m->sealed, -EPERM);
702         assert_return(data, -EINVAL);
703
704         sd_rtnl_message_get_type(m, &rtm_type);
705
706         switch (rtm_type) {
707                 case RTM_NEWLINK:
708                 case RTM_SETLINK:
709                 case RTM_DELLINK:
710                 case RTM_GETLINK:
711                         switch (type) {
712                                 case IFLA_ADDRESS:
713                                 case IFLA_BROADCAST:
714                                         break;
715                                 default:
716                                         return -ENOTSUP;
717                         }
718                         break;
719                 default:
720                         return -ENOTSUP;
721         }
722
723         r = add_rtattr(m, type, data, ETH_ALEN);
724         if (r < 0)
725                 return r;
726
727         return 0;
728 }
729
730 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
731         uint16_t rtm_type;
732
733         assert_return(m, -EINVAL);
734         assert_return(!m->sealed, -EPERM);
735
736         sd_rtnl_message_get_type(m, &rtm_type);
737
738         if (rtnl_message_type_is_link(rtm_type)) {
739
740                 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
741                     (type == IFLA_INFO_DATA && m->n_containers == 1 &&
742                      GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
743                         return add_rtattr(m, type, NULL, 0);
744                 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
745                          GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
746                          GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
747                         return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
748         }
749
750         return -ENOTSUP;
751 }
752
753 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
754         assert_return(m, -EINVAL);
755         assert_return(!m->sealed, -EPERM);
756         assert_return(m->n_containers > 0, -EINVAL);
757
758         m->n_containers --;
759
760         return 0;
761 }
762
763 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
764         struct rtattr *rta;
765
766         assert_return(m, -EINVAL);
767         assert_return(m->sealed, -EPERM);
768         assert_return(data, -EINVAL);
769         assert_return(m->rta_offset_tb[m->n_containers], -EINVAL);
770         assert_return(type < m->rta_tb_size[m->n_containers], -EINVAL);
771
772         if(!m->rta_offset_tb[m->n_containers][type])
773                 return -ENODATA;
774
775         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[m->n_containers][type]);
776
777         *data = RTA_DATA(rta);
778
779         return RTA_PAYLOAD(rta);
780 }
781
782 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
783         int r;
784         void *attr_data;
785
786         assert_return(data, -EINVAL);
787
788         r = rtnl_message_read_internal(m, type, &attr_data);
789         if (r < 0)
790                 return r;
791         else if (strnlen(attr_data, r) >= (size_t) r)
792                 return -EIO;
793
794         *data = (char *) attr_data;
795
796         return 0;
797 }
798
799 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
800         int r;
801         void *attr_data;
802
803         assert_return(data, -EINVAL);
804
805         r = rtnl_message_read_internal(m, type, &attr_data);
806         if (r < 0)
807                 return r;
808         else if ((size_t) r < sizeof(uint8_t))
809                 return -EIO;
810
811         *data = *(uint8_t *) attr_data;
812
813         return 0;
814 }
815
816 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
817         int r;
818         void *attr_data;
819
820         assert_return(data, -EINVAL);
821
822         r = rtnl_message_read_internal(m, type, &attr_data);
823         if (r < 0)
824                 return r;
825         else if ((size_t) r < sizeof(uint16_t))
826                 return -EIO;
827
828         *data = *(uint16_t *) attr_data;
829
830         return 0;
831 }
832
833 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
834         int r;
835         void *attr_data;
836
837         assert_return(data, -EINVAL);
838
839         r = rtnl_message_read_internal(m, type, &attr_data);
840         if (r < 0)
841                 return r;
842         else if ((size_t)r < sizeof(uint32_t))
843                 return -EIO;
844
845         *data = *(uint32_t *) attr_data;
846
847         return 0;
848 }
849
850 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
851         int r;
852         void *attr_data;
853
854         assert_return(data, -EINVAL);
855
856         r = rtnl_message_read_internal(m, type, &attr_data);
857         if (r < 0)
858                 return r;
859         else if ((size_t)r < sizeof(struct ether_addr))
860                 return -EIO;
861
862         memcpy(data, attr_data, sizeof(struct ether_addr));
863
864         return 0;
865 }
866
867 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
868         int r;
869         void *attr_data;
870
871         assert_return(data, -EINVAL);
872
873         r = rtnl_message_read_internal(m, type, &attr_data);
874         if (r < 0)
875                 return r;
876         else if ((size_t)r < sizeof(struct in_addr))
877                 return -EIO;
878
879         memcpy(data, attr_data, sizeof(struct in_addr));
880
881         return 0;
882 }
883
884 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
885         int r;
886         void *attr_data;
887
888         assert_return(data, -EINVAL);
889
890         r = rtnl_message_read_internal(m, type, &attr_data);
891         if (r < 0)
892                 return r;
893         else if ((size_t)r < sizeof(struct in6_addr))
894                 return -EIO;
895
896         memcpy(data, attr_data, sizeof(struct in6_addr));
897
898         return 0;
899 }
900
901 int sd_rtnl_message_enter_container(sd_rtnl_message *m, unsigned short type) {
902         uint16_t rtm_type;
903         unsigned short parent_type;
904         void *container;
905         size_t container_length;
906         int max, r;
907
908         assert_return(m, -EINVAL);
909         assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
910
911         r = rtnl_message_read_internal(m, type, &container);
912         if (r < 0)
913                 return r;
914         else
915                 container_length = r;
916
917         r = sd_rtnl_message_get_type(m, &rtm_type);
918         if (r < 0)
919                 return r;
920
921         if (rtnl_message_type_is_link(rtm_type)) {
922                 switch (m->n_containers) {
923                         case 0:
924                                 switch (type) {
925                                         case IFLA_LINKINFO:
926                                                 max = IFLA_INFO_MAX;
927                                                 break;
928                                         default:
929                                                 return -ENOTSUP;
930                                 }
931                                 break;
932                         case 1:
933                                 parent_type = GET_CONTAINER(m, 0)->rta_type;
934                                 switch (parent_type) {
935                                         case IFLA_LINKINFO:
936                                                 switch (type) {
937                                                         case IFLA_INFO_DATA: {
938                                                                 char *kind;
939
940                                                                 r = sd_rtnl_message_read_string(m, IFLA_INFO_KIND, &kind);
941                                                                 if (r < 0)
942                                                                         return r;
943
944                                                                 if (streq(kind, "vlan")) {
945                                                                         max = IFLA_VLAN_MAX;
946                                                                 } else if (streq(kind, "bridge")) {
947                                                                         max = IFLA_BRIDGE_MAX;
948                                                                 } else if (streq(kind, "veth")) {
949                                                                         max = VETH_INFO_MAX;
950                                                                         container = IFLA_RTA(container);
951                                                                 } else
952                                                                         return -ENOTSUP;
953
954                                                                 break;
955                                                         }
956                                                         default:
957                                                                 return -ENOTSUP;
958                                                 }
959                                                 break;
960                                         default:
961                                                 return -ENOTSUP;
962                                 }
963                                 break;
964                         default:
965                                 return -ENOTSUP;
966                 }
967         } else
968                 return -ENOTSUP;
969
970         r = rtnl_message_parse(m,
971                                &m->rta_offset_tb[m->n_containers + 1],
972                                &m->rta_tb_size[m->n_containers + 1],
973                                max,
974                                container,
975                                container_length);
976         if (r < 0)
977                 return r;
978
979         m->n_containers ++;
980
981         return 0;
982 }
983
984 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
985         assert_return(m, -EINVAL);
986         assert_return(m->sealed, -EINVAL);
987         assert_return(m->n_containers > 0, -EINVAL);
988
989         free(m->rta_offset_tb[m->n_containers]);
990         m->rta_offset_tb[m->n_containers] = NULL;
991
992         m->n_containers --;
993
994         return 0;
995 }
996
997 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
998         assert(m);
999         assert(m->hdr);
1000
1001         return m->hdr->nlmsg_seq;
1002 }
1003
1004 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1005         struct nlmsgerr *err;
1006
1007         assert_return(m, -EINVAL);
1008         assert_return(m->hdr, -EINVAL);
1009
1010         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1011                 return 0;
1012
1013         err = NLMSG_DATA(m->hdr);
1014
1015         return err->error;
1016 }
1017
1018 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1019         assert(rtnl);
1020         assert(need);
1021
1022         /* ioctl(rtnl->fd, FIONREAD, &need)
1023            Does not appear to work on netlink sockets. libnl uses
1024            MSG_PEEK instead. I don't know if that is worth the
1025            extra roundtrip.
1026
1027            For now we simply use the maximum message size the kernel
1028            may use (NLMSG_GOODSIZE), and then realloc to the actual
1029            size after reading the message (hence avoiding huge memory
1030            usage in case many small messages are kept around) */
1031         *need = page_size();
1032         if (*need > 8192UL)
1033                 *need = 8192UL;
1034
1035         return 0;
1036 }
1037
1038 int rtnl_message_parse(sd_rtnl_message *m,
1039                        size_t **rta_offset_tb,
1040                        unsigned short *rta_tb_size,
1041                        int max,
1042                        struct rtattr *rta,
1043                        unsigned int rt_len) {
1044         unsigned short type;
1045         size_t *tb;
1046
1047         tb = (size_t *) new0(size_t *, max);
1048         if(!tb)
1049                 return -ENOMEM;
1050
1051         *rta_tb_size = max;
1052
1053         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1054                 type = rta->rta_type;
1055
1056                 if (type > max) {
1057                         log_debug("rtnl: message parse - ignore out of range attribute type");
1058                         continue;
1059                 }
1060
1061                 if (tb[type])
1062                         log_debug("rtnl: message parse - overwriting repeated attribute");
1063
1064                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1065         }
1066
1067         *rta_offset_tb = tb;
1068
1069         return 0;
1070 }
1071
1072 /* returns the number of bytes sent, or a negative error code */
1073 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1074         union {
1075                 struct sockaddr sa;
1076                 struct sockaddr_nl nl;
1077         } addr = {
1078                 .nl.nl_family = AF_NETLINK,
1079         };
1080         ssize_t k;
1081
1082         assert(nl);
1083         assert(m);
1084         assert(m->hdr);
1085
1086         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1087                         0, &addr.sa, sizeof(addr));
1088         if (k < 0)
1089                 return (errno == EAGAIN) ? 0 : -errno;
1090
1091         return k;
1092 }
1093
1094 /* On success, the number of bytes received is returned and *ret points to the received message
1095  * which has a valid header and the correct size.
1096  * If nothing useful was received 0 is returned.
1097  * On failure, a negative error code is returned.
1098  */
1099 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1100         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1101         struct nlmsghdr *new_hdr;
1102         union {
1103                 struct sockaddr sa;
1104                 struct sockaddr_nl nl;
1105         } addr;
1106         socklen_t addr_len;
1107         size_t need, len;
1108         int r;
1109
1110         assert(nl);
1111         assert(ret);
1112
1113         r = message_receive_need(nl, &need);
1114         if (r < 0)
1115                 return r;
1116
1117         r = message_new(nl, &m, need);
1118         if (r < 0)
1119                 return r;
1120
1121         addr_len = sizeof(addr);
1122
1123         r = recvfrom(nl->fd, m->hdr, need,
1124                         0, &addr.sa, &addr_len);
1125         if (r < 0)
1126                 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1127         else if (r == 0)
1128                 return -ECONNRESET; /* connection was closed by the kernel */
1129         else if (addr_len != sizeof(addr.nl) ||
1130                         addr.nl.nl_family != AF_NETLINK)
1131                 return -EIO; /* not a netlink message */
1132         else if (addr.nl.nl_pid != 0)
1133                 return 0; /* not from the kernel */
1134         else if ((size_t) r < sizeof(struct nlmsghdr) ||
1135                         (size_t) r < m->hdr->nlmsg_len)
1136                 return -EIO; /* too small (we do accept too big though) */
1137         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1138                 return 0; /* not broadcast and not for us */
1139         else
1140                 len = (size_t) r;
1141
1142         /* check that the size matches the message type */
1143         switch (m->hdr->nlmsg_type) {
1144
1145         case NLMSG_ERROR:
1146                 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1147                         return -EIO;
1148                 break;
1149
1150         case RTM_NEWLINK:
1151         case RTM_SETLINK:
1152         case RTM_DELLINK:
1153         case RTM_GETLINK:
1154                 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1155                         return -EIO;
1156                 break;
1157
1158         case RTM_NEWADDR:
1159         case RTM_DELADDR:
1160         case RTM_GETADDR:
1161                 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1162                         return -EIO;
1163                 break;
1164         case RTM_NEWROUTE:
1165         case RTM_DELROUTE:
1166         case RTM_GETROUTE:
1167                 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1168                         return -EIO;
1169                 break;
1170         case NLMSG_NOOP:
1171                 return 0;
1172         default:
1173                 log_debug("sd-rtnl: ignored message with unknown type");
1174                 return 0;
1175         }
1176
1177         /* we probably allocated way too much memory, give it back */
1178         new_hdr = realloc(m->hdr, len);
1179         if (!new_hdr)
1180                 return -ENOMEM;
1181         m->hdr = new_hdr;
1182
1183         /* seal and parse the top-level message */
1184         r = sd_rtnl_message_rewind(m);
1185         if (r < 0)
1186                 return r;
1187
1188         *ret = m;
1189         m = NULL;
1190
1191         return len;
1192 }
1193
1194 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1195         struct ifinfomsg *ifi;
1196         struct ifaddrmsg *ifa;
1197         struct rtmsg *rtm;
1198         unsigned i;
1199         int r;
1200
1201         assert_return(m, -EINVAL);
1202         assert_return(m->hdr, -EINVAL);
1203
1204         /* don't allow appending to message once parsed */
1205         if (!m->sealed)
1206                 rtnl_message_seal(m);
1207
1208         for (i = 1; i <= m->n_containers; i++) {
1209                 free(m->rta_offset_tb[i]);
1210                 m->rta_offset_tb[i] = NULL;
1211                 m->rta_tb_size[i] = 0;
1212         }
1213
1214         m->n_containers = 0;
1215
1216         if (m->rta_offset_tb[0]) {
1217                 /* top-level attributes have already been parsed */
1218                 return 0;
1219         }
1220
1221         /* parse top-level attributes */
1222         switch(m->hdr->nlmsg_type) {
1223                 case NLMSG_NOOP:
1224                 case NLMSG_ERROR:
1225                         break;
1226                 case RTM_NEWLINK:
1227                 case RTM_SETLINK:
1228                 case RTM_GETLINK:
1229                 case RTM_DELLINK:
1230                         ifi = NLMSG_DATA(m->hdr);
1231
1232                         r = rtnl_message_parse(m,
1233                                                &m->rta_offset_tb[0],
1234                                                &m->rta_tb_size[0],
1235                                                IFLA_MAX,
1236                                                IFLA_RTA(ifi),
1237                                                IFLA_PAYLOAD(m->hdr));
1238                         if (r < 0)
1239                                 return r;
1240
1241                         break;
1242                 case RTM_NEWADDR:
1243                 case RTM_GETADDR:
1244                 case RTM_DELADDR:
1245                         ifa = NLMSG_DATA(m->hdr);
1246
1247                         r = rtnl_message_parse(m,
1248                                                &m->rta_offset_tb[0],
1249                                                &m->rta_tb_size[0],
1250                                                IFA_MAX,
1251                                                IFA_RTA(ifa),
1252                                                IFA_PAYLOAD(m->hdr));
1253                         if (r < 0)
1254                                 return r;
1255
1256                         break;
1257                 case RTM_NEWROUTE:
1258                 case RTM_GETROUTE:
1259                 case RTM_DELROUTE:
1260                         rtm = NLMSG_DATA(m->hdr);
1261
1262                         r = rtnl_message_parse(m,
1263                                                &m->rta_offset_tb[0],
1264                                                &m->rta_tb_size[0],
1265                                                RTA_MAX,
1266                                                RTM_RTA(rtm),
1267                                                RTM_PAYLOAD(m->hdr));
1268
1269                         break;
1270                 default:
1271                         return -ENOTSUP;
1272         }
1273
1274         return 0;
1275 }
1276
1277 void rtnl_message_seal(sd_rtnl_message *m) {
1278         assert(m);
1279         assert(!m->sealed);
1280
1281         m->sealed = true;
1282 }