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