chiark / gitweb /
sd-rtnl: tests - drop redundant tests
[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         }
968
969         r = rtnl_message_parse(m,
970                                &m->rta_offset_tb[m->n_containers + 1],
971                                &m->rta_tb_size[m->n_containers + 1],
972                                max,
973                                container,
974                                container_length);
975         if (r < 0)
976                 return r;
977
978         m->n_containers ++;
979
980         return 0;
981 }
982
983 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
984         assert_return(m, -EINVAL);
985         assert_return(m->sealed, -EINVAL);
986         assert_return(m->n_containers > 0, -EINVAL);
987
988         free(m->rta_offset_tb[m->n_containers]);
989         m->rta_offset_tb[m->n_containers] = NULL;
990
991         m->n_containers --;
992
993         return 0;
994 }
995
996 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
997         assert(m);
998         assert(m->hdr);
999
1000         return m->hdr->nlmsg_seq;
1001 }
1002
1003 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
1004         struct nlmsgerr *err;
1005
1006         assert_return(m, -EINVAL);
1007         assert_return(m->hdr, -EINVAL);
1008
1009         if (m->hdr->nlmsg_type != NLMSG_ERROR)
1010                 return 0;
1011
1012         err = NLMSG_DATA(m->hdr);
1013
1014         return err->error;
1015 }
1016
1017 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
1018         assert(rtnl);
1019         assert(need);
1020
1021         /* ioctl(rtnl->fd, FIONREAD, &need)
1022            Does not appear to work on netlink sockets. libnl uses
1023            MSG_PEEK instead. I don't know if that is worth the
1024            extra roundtrip.
1025
1026            For now we simply use the maximum message size the kernel
1027            may use (NLMSG_GOODSIZE), and then realloc to the actual
1028            size after reading the message (hence avoiding huge memory
1029            usage in case many small messages are kept around) */
1030         *need = page_size();
1031         if (*need > 8192UL)
1032                 *need = 8192UL;
1033
1034         return 0;
1035 }
1036
1037 int rtnl_message_parse(sd_rtnl_message *m,
1038                        size_t **rta_offset_tb,
1039                        unsigned short *rta_tb_size,
1040                        int max,
1041                        struct rtattr *rta,
1042                        unsigned int rt_len) {
1043         unsigned short type;
1044         size_t *tb;
1045
1046         tb = (size_t *) new0(size_t *, max);
1047         if(!tb)
1048                 return -ENOMEM;
1049
1050         *rta_tb_size = max;
1051
1052         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1053                 type = rta->rta_type;
1054
1055                 if (type > max) {
1056                         log_debug("rtnl: message parse - ignore out of range attribute type");
1057                         continue;
1058                 }
1059
1060                 if (tb[type])
1061                         log_debug("rtnl: message parse - overwriting repeated attribute");
1062
1063                 tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1064         }
1065
1066         *rta_offset_tb = tb;
1067
1068         return 0;
1069 }
1070
1071 /* returns the number of bytes sent, or a negative error code */
1072 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1073         union {
1074                 struct sockaddr sa;
1075                 struct sockaddr_nl nl;
1076         } addr = {
1077                 .nl.nl_family = AF_NETLINK,
1078         };
1079         ssize_t k;
1080
1081         assert(nl);
1082         assert(m);
1083         assert(m->hdr);
1084
1085         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1086                         0, &addr.sa, sizeof(addr));
1087         if (k < 0)
1088                 return (errno == EAGAIN) ? 0 : -errno;
1089
1090         return k;
1091 }
1092
1093 /* On success, the number of bytes received is returned and *ret points to the received message
1094  * which has a valid header and the correct size.
1095  * If nothing useful was received 0 is returned.
1096  * On failure, a negative error code is returned.
1097  */
1098 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1099         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
1100         struct nlmsghdr *new_hdr;
1101         union {
1102                 struct sockaddr sa;
1103                 struct sockaddr_nl nl;
1104         } addr;
1105         socklen_t addr_len;
1106         size_t need, len;
1107         int r;
1108
1109         assert(nl);
1110         assert(ret);
1111
1112         r = message_receive_need(nl, &need);
1113         if (r < 0)
1114                 return r;
1115
1116         r = message_new(nl, &m, need);
1117         if (r < 0)
1118                 return r;
1119
1120         addr_len = sizeof(addr);
1121
1122         r = recvfrom(nl->fd, m->hdr, need,
1123                         0, &addr.sa, &addr_len);
1124         if (r < 0)
1125                 return (errno == EAGAIN) ? 0 : -errno; /* no data */
1126         else if (r == 0)
1127                 return -ECONNRESET; /* connection was closed by the kernel */
1128         else if (addr_len != sizeof(addr.nl) ||
1129                         addr.nl.nl_family != AF_NETLINK)
1130                 return -EIO; /* not a netlink message */
1131         else if (addr.nl.nl_pid != 0)
1132                 return 0; /* not from the kernel */
1133         else if ((size_t) r < sizeof(struct nlmsghdr) ||
1134                         (size_t) r < m->hdr->nlmsg_len)
1135                 return -EIO; /* too small (we do accept too big though) */
1136         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1137                 return 0; /* not broadcast and not for us */
1138         else
1139                 len = (size_t) r;
1140
1141         /* check that the size matches the message type */
1142         switch (m->hdr->nlmsg_type) {
1143
1144         case NLMSG_ERROR:
1145                 if (len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1146                         return -EIO;
1147                 break;
1148
1149         case RTM_NEWLINK:
1150         case RTM_SETLINK:
1151         case RTM_DELLINK:
1152         case RTM_GETLINK:
1153                 if (len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1154                         return -EIO;
1155                 break;
1156
1157         case RTM_NEWADDR:
1158         case RTM_DELADDR:
1159         case RTM_GETADDR:
1160                 if (len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1161                         return -EIO;
1162                 break;
1163         case RTM_NEWROUTE:
1164         case RTM_DELROUTE:
1165         case RTM_GETROUTE:
1166                 if (len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1167                         return -EIO;
1168                 break;
1169         case NLMSG_NOOP:
1170                 return 0;
1171         default:
1172                 log_debug("sd-rtnl: ignored message with unknown type");
1173                 return 0;
1174         }
1175
1176         /* we probably allocated way too much memory, give it back */
1177         new_hdr = realloc(m->hdr, len);
1178         if (!new_hdr)
1179                 return -ENOMEM;
1180         m->hdr = new_hdr;
1181
1182         /* seal and parse the top-level message */
1183         r = sd_rtnl_message_rewind(m);
1184         if (r < 0)
1185                 return r;
1186
1187         *ret = m;
1188         m = NULL;
1189
1190         return len;
1191 }
1192
1193 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1194         struct ifinfomsg *ifi;
1195         struct ifaddrmsg *ifa;
1196         struct rtmsg *rtm;
1197         unsigned i;
1198         int r;
1199
1200         assert_return(m, -EINVAL);
1201         assert_return(m->hdr, -EINVAL);
1202
1203         /* don't allow appending to message once parsed */
1204         if (!m->sealed)
1205                 rtnl_message_seal(m);
1206
1207         for (i = 1; i <= m->n_containers; i++) {
1208                 free(m->rta_offset_tb[i]);
1209                 m->rta_offset_tb[i] = NULL;
1210                 m->rta_tb_size[i] = 0;
1211         }
1212
1213         m->n_containers = 0;
1214
1215         if (m->rta_offset_tb[0]) {
1216                 /* top-level attributes have already been parsed */
1217                 return 0;
1218         }
1219
1220         /* parse top-level attributes */
1221         switch(m->hdr->nlmsg_type) {
1222                 case NLMSG_NOOP:
1223                 case NLMSG_ERROR:
1224                         break;
1225                 case RTM_NEWLINK:
1226                 case RTM_SETLINK:
1227                 case RTM_GETLINK:
1228                 case RTM_DELLINK:
1229                         ifi = NLMSG_DATA(m->hdr);
1230
1231                         r = rtnl_message_parse(m,
1232                                                &m->rta_offset_tb[0],
1233                                                &m->rta_tb_size[0],
1234                                                IFLA_MAX,
1235                                                IFLA_RTA(ifi),
1236                                                IFLA_PAYLOAD(m->hdr));
1237                         if (r < 0)
1238                                 return r;
1239
1240                         break;
1241                 case RTM_NEWADDR:
1242                 case RTM_GETADDR:
1243                 case RTM_DELADDR:
1244                         ifa = NLMSG_DATA(m->hdr);
1245
1246                         r = rtnl_message_parse(m,
1247                                                &m->rta_offset_tb[0],
1248                                                &m->rta_tb_size[0],
1249                                                IFA_MAX,
1250                                                IFA_RTA(ifa),
1251                                                IFA_PAYLOAD(m->hdr));
1252                         if (r < 0)
1253                                 return r;
1254
1255                         break;
1256                 case RTM_NEWROUTE:
1257                 case RTM_GETROUTE:
1258                 case RTM_DELROUTE:
1259                         rtm = NLMSG_DATA(m->hdr);
1260
1261                         r = rtnl_message_parse(m,
1262                                                &m->rta_offset_tb[0],
1263                                                &m->rta_tb_size[0],
1264                                                RTA_MAX,
1265                                                RTM_RTA(rtm),
1266                                                RTM_PAYLOAD(m->hdr));
1267
1268                         break;
1269                 default:
1270                         return -ENOTSUP;
1271         }
1272
1273         return 0;
1274 }
1275
1276 void rtnl_message_seal(sd_rtnl_message *m) {
1277         assert(m);
1278         assert(!m->sealed);
1279
1280         m->sealed = true;
1281 }