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