chiark / gitweb /
41a6e4ea85a504ec0ebe29c46baeb56c98cb3a25
[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_NEWLINK ||
170                       nlmsg_type == RTM_SETLINK || index > 0, -EINVAL);
171         assert_return(ret, -EINVAL);
172
173         r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
174         if (r < 0)
175                 return r;
176
177         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
178         (*ret)->hdr->nlmsg_type = nlmsg_type;
179         if (nlmsg_type == RTM_NEWLINK)
180                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
181
182         ifi = NLMSG_DATA((*ret)->hdr);
183
184         ifi->ifi_family = AF_UNSPEC;
185         ifi->ifi_index = index;
186
187         UPDATE_RTA(*ret, IFLA_RTA(ifi));
188
189         return 0;
190 }
191
192 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
193         struct ifaddrmsg *ifa;
194
195         assert_return(m, -EINVAL);
196         assert_return(m->hdr, -EINVAL);
197         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
198
199         ifa = NLMSG_DATA(m->hdr);
200
201         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
202             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
203                 return -ERANGE;
204
205         ifa->ifa_prefixlen = prefixlen;
206
207         return 0;
208 }
209
210 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
211         struct ifaddrmsg *ifa;
212
213         assert_return(m, -EINVAL);
214         assert_return(m->hdr, -EINVAL);
215         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
216
217         ifa = NLMSG_DATA(m->hdr);
218
219         ifa->ifa_flags = flags;
220
221         return 0;
222 }
223
224 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
225         struct ifaddrmsg *ifa;
226
227         assert_return(m, -EINVAL);
228         assert_return(m->hdr, -EINVAL);
229         assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
230
231         ifa = NLMSG_DATA(m->hdr);
232
233         ifa->ifa_scope = scope;
234
235         return 0;
236 }
237
238 int sd_rtnl_message_new_addr(sd_rtnl *rtnl, sd_rtnl_message **ret,
239                              uint16_t nlmsg_type, int index,
240                              unsigned char family) {
241         struct ifaddrmsg *ifa;
242         int r;
243
244         assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
245         assert_return(index > 0, -EINVAL);
246         assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
247         assert_return(ret, -EINVAL);
248
249         r = message_new(rtnl, ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
250         if (r < 0)
251                 return r;
252
253         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
254         (*ret)->hdr->nlmsg_type = nlmsg_type;
255         if (nlmsg_type == RTM_GETADDR && family == AF_INET)
256                 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
257
258         ifa = NLMSG_DATA((*ret)->hdr);
259
260         ifa->ifa_index = index;
261         ifa->ifa_family = family;
262         if (family == AF_INET)
263                 ifa->ifa_prefixlen = 32;
264         else if (family == AF_INET6)
265                 ifa->ifa_prefixlen = 128;
266
267         UPDATE_RTA(*ret, IFA_RTA(ifa));
268
269         return 0;
270 }
271
272 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
273         if (m)
274                 assert_se(REFCNT_INC(m->n_ref) >= 2);
275
276         return m;
277 }
278
279 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
280         if (m && REFCNT_DEC(m->n_ref) <= 0) {
281                 sd_rtnl_unref(m->rtnl);
282                 free(m->hdr);
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 sd_rtnl_message_exit_container(sd_rtnl_message *m) {
804         assert_return(m, -EINVAL);
805         assert_return(m->sealed, -EINVAL);
806         assert_return(m->n_containers > 0, -EINVAL);
807
808         m->n_containers --;
809
810         return 0;
811 }
812
813 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
814         assert(m);
815         assert(m->hdr);
816
817         return m->hdr->nlmsg_seq;
818 }
819
820 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
821         struct nlmsgerr *err;
822
823         assert_return(m, -EINVAL);
824         assert_return(m->hdr, -EINVAL);
825
826         if (m->hdr->nlmsg_type != NLMSG_ERROR)
827                 return 0;
828
829         err = NLMSG_DATA(m->hdr);
830
831         return err->error;
832 }
833
834 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
835         int r;
836
837         assert(m);
838         assert(m->hdr);
839
840         if (m->sealed)
841                 return -EPERM;
842
843         if (nl)
844                 m->hdr->nlmsg_seq = nl->serial++;
845
846         m->sealed = true;
847
848         r = sd_rtnl_message_rewind(m);
849         if (r < 0)
850                 return r;
851
852         return 0;
853 }
854
855 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
856         assert(rtnl);
857         assert(need);
858
859         /* ioctl(rtnl->fd, FIONREAD, &need)
860            Does not appear to work on netlink sockets. libnl uses
861            MSG_PEEK instead. I don't know if that is worth the
862            extra roundtrip.
863
864            For now we simply use the maximum message size the kernel
865            may use (NLMSG_GOODSIZE), and then realloc to the actual
866            size after reading the message (hence avoiding huge memory
867            usage in case many small messages are kept around) */
868         *need = page_size();
869         if (*need > 8192UL)
870                 *need = 8192UL;
871
872         return 0;
873 }
874
875 /* returns the number of bytes sent, or a negative error code */
876 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
877         union {
878                 struct sockaddr sa;
879                 struct sockaddr_nl nl;
880         } addr = {
881                 .nl.nl_family = AF_NETLINK,
882         };
883         ssize_t k;
884
885         assert(nl);
886         assert(m);
887         assert(m->hdr);
888
889         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
890                         0, &addr.sa, sizeof(addr));
891         if (k < 0)
892                 return (errno == EAGAIN) ? 0 : -errno;
893
894         return k;
895 }
896
897 /* On success, the number of bytes received is returned and *ret points to the received message
898  * which has a valid header and the correct size.
899  * If nothing useful was received 0 is returned.
900  * On failure, a negative error code is returned.
901  */
902 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
903         sd_rtnl_message *m;
904         union {
905                 struct sockaddr sa;
906                 struct sockaddr_nl nl;
907         } addr;
908         socklen_t addr_len;
909         int r;
910         ssize_t k;
911         size_t need;
912
913         assert(nl);
914         assert(ret);
915
916         r = message_receive_need(nl, &need);
917         if (r < 0)
918                 return r;
919
920         r = message_new(nl, &m, need);
921         if (r < 0)
922                 return r;
923
924         /* don't allow sealing/appending to received messages */
925         m->sealed = true;
926
927         addr_len = sizeof(addr);
928
929         k = recvfrom(nl->fd, m->hdr, need,
930                         0, &addr.sa, &addr_len);
931         if (k < 0)
932                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
933         else if (k == 0)
934                 k = -ECONNRESET; /* connection was closed by the kernel */
935         else if (addr_len != sizeof(addr.nl) ||
936                         addr.nl.nl_family != AF_NETLINK)
937                 k = -EIO; /* not a netlink message */
938         else if (addr.nl.nl_pid != 0)
939                 k = 0; /* not from the kernel */
940         else if ((size_t) k < sizeof(struct nlmsghdr) ||
941                         (size_t) k < m->hdr->nlmsg_len)
942                 k = -EIO; /* too small (we do accept too big though) */
943         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
944                 k = 0; /* not broadcast and not for us */
945
946         if (k > 0)
947                 switch (m->hdr->nlmsg_type) {
948                         /* check that the size matches the message type */
949                         case NLMSG_ERROR:
950                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
951                                         k = -EIO;
952                                 break;
953                         case RTM_NEWLINK:
954                         case RTM_SETLINK:
955                         case RTM_DELLINK:
956                         case RTM_GETLINK:
957                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
958                                         k = -EIO;
959                                 else {
960                                         struct ifinfomsg *ifi;
961
962                                         ifi = NLMSG_DATA(m->hdr);
963                                         UPDATE_RTA(m, IFLA_RTA(ifi));
964                                 }
965                                 break;
966                         case RTM_NEWADDR:
967                         case RTM_DELADDR:
968                         case RTM_GETADDR:
969                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
970                                         k = -EIO;
971                                 else {
972                                         struct ifaddrmsg *ifa;
973
974                                         ifa = NLMSG_DATA(m->hdr);
975                                         UPDATE_RTA(m, IFA_RTA(ifa));
976                                 }
977                                 break;
978                         case RTM_NEWROUTE:
979                         case RTM_DELROUTE:
980                         case RTM_GETROUTE:
981                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
982                                         k = -EIO;
983                                 else {
984                                         struct rtmsg *rtm;
985
986                                         rtm = NLMSG_DATA(m->hdr);
987                                         UPDATE_RTA(m, RTM_RTA(rtm));
988                                 }
989                                 break;
990                         case NLMSG_NOOP:
991                                 k = 0;
992                                 break;
993                         default:
994                                 k = 0; /* ignoring message of unknown type */
995                 }
996
997         if (k <= 0)
998                 sd_rtnl_message_unref(m);
999         else {
1000                 /* we probably allocated way too much memory, give it back */
1001                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
1002                 *ret = m;
1003         }
1004
1005         return k;
1006 }
1007
1008 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1009         struct ifinfomsg *ifi;
1010         struct ifaddrmsg *ifa;
1011         struct rtmsg *rtm;
1012
1013         assert_return(m, -EINVAL);
1014         assert_return(m->sealed, -EPERM);
1015         assert_return(m->hdr, -EINVAL);
1016
1017         switch(m->hdr->nlmsg_type) {
1018                 case RTM_NEWLINK:
1019                 case RTM_SETLINK:
1020                 case RTM_GETLINK:
1021                 case RTM_DELLINK:
1022                         ifi = NLMSG_DATA(m->hdr);
1023                         UPDATE_RTA(m, IFLA_RTA(ifi));
1024
1025                         break;
1026                 case RTM_NEWADDR:
1027                 case RTM_GETADDR:
1028                 case RTM_DELADDR:
1029                         ifa = NLMSG_DATA(m->hdr);
1030                         UPDATE_RTA(m, IFA_RTA(ifa));
1031
1032                         break;
1033                 case RTM_NEWROUTE:
1034                 case RTM_GETROUTE:
1035                 case RTM_DELROUTE:
1036                         rtm = NLMSG_DATA(m->hdr);
1037                         UPDATE_RTA(m, RTM_RTA(rtm));
1038
1039                         break;
1040                 default:
1041                         return -ENOTSUP;
1042         }
1043
1044         m->n_containers = 0;
1045
1046         return 0;
1047 }