chiark / gitweb /
23c8099c30dce16fe732b80ee2b3edcec512a170
[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_is_broadcast(sd_rtnl_message *m) {
299         assert_return(m, -EINVAL);
300
301         return !m->hdr->nlmsg_pid;
302 }
303
304 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
305         struct ifinfomsg *ifi;
306
307         assert_return(m, -EINVAL);
308         assert_return(m->hdr, -EINVAL);
309         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
310         assert_return(ifindex, -EINVAL);
311
312         ifi = NLMSG_DATA(m->hdr);
313
314         *ifindex = ifi->ifi_index;
315
316         return 0;
317 }
318
319 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
320         struct ifinfomsg *ifi;
321
322         assert_return(m, -EINVAL);
323         assert_return(m->hdr, -EINVAL);
324         assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
325         assert_return(flags, -EINVAL);
326
327         ifi = NLMSG_DATA(m->hdr);
328
329         *flags = ifi->ifi_flags;
330
331         return 0;
332 }
333
334 /* If successful the updated message will be correctly aligned, if
335    unsuccessful the old message is untouched. */
336 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
337         uint32_t rta_length, message_length;
338         struct nlmsghdr *new_hdr;
339         struct rtattr *rta;
340         char *padding;
341         unsigned i;
342
343         assert(m);
344         assert(m->hdr);
345         assert(!m->sealed);
346         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
347         assert(!data || data_length > 0);
348         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
349
350         /* get the size of the new rta attribute (with padding at the end) */
351         rta_length = RTA_LENGTH(data_length);
352
353         /* get the new message size (with padding at the end) */
354         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
355
356         /* realloc to fit the new attribute */
357         new_hdr = realloc(m->hdr, message_length);
358         if (!new_hdr)
359                 return -ENOMEM;
360         m->hdr = new_hdr;
361
362         /* get pointer to the attribute we are about to add */
363         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
364
365         /* if we are inside containers, extend them */
366         for (i = 0; i < m->n_containers; i++)
367                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
368
369         /* fill in the attribute */
370         rta->rta_type = type;
371         rta->rta_len = rta_length;
372         if (!data) {
373                 /* this is the start of a new container */
374                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
375         } else {
376                 /* we don't deal with the case where the user lies about the type
377                  * and gives us too little data (so don't do that)
378                 */
379                 padding = mempcpy(RTA_DATA(rta), data, data_length);
380                 /* make sure also the padding at the end of the message is initialized */
381                 memzero(padding,
382                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
383         }
384
385         /* update message size */
386         m->hdr->nlmsg_len = message_length;
387
388         return 0;
389 }
390
391 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
392         uint16_t rtm_type;
393         int r;
394
395         assert_return(m, -EINVAL);
396         assert_return(!m->sealed, -EPERM);
397         assert_return(data, -EINVAL);
398
399         r = sd_rtnl_message_get_type(m, &rtm_type);
400         if (r < 0)
401                 return r;
402
403         /* check that the type is correct */
404         switch (rtm_type) {
405                 case RTM_NEWLINK:
406                 case RTM_SETLINK:
407                 case RTM_GETLINK:
408                 case RTM_DELLINK:
409                         if (m->n_containers == 1) {
410                                 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
411                                     type != IFLA_INFO_KIND)
412                                         return -ENOTSUP;
413                         } else {
414                                 switch (type) {
415                                         case IFLA_IFNAME:
416                                         case IFLA_IFALIAS:
417                                         case IFLA_QDISC:
418                                                 break;
419                                         default:
420                                                 return -ENOTSUP;
421                                 }
422                         }
423                         break;
424                 case RTM_NEWADDR:
425                 case RTM_GETADDR:
426                 case RTM_DELADDR:
427                         if (type != IFA_LABEL)
428                                 return -ENOTSUP;
429                         break;
430                 default:
431                         return -ENOTSUP;
432         }
433
434         r = add_rtattr(m, type, data, strlen(data) + 1);
435         if (r < 0)
436                 return r;
437
438         return 0;
439 }
440
441 int sd_rtnl_message_append_u8(sd_rtnl_message *m, unsigned short type, uint8_t data) {
442         uint16_t rtm_type;
443         int r;
444
445         assert_return(m, -EINVAL);
446         assert_return(!m->sealed, -EPERM);
447
448         r = sd_rtnl_message_get_type(m, &rtm_type);
449         if (r < 0)
450                 return r;
451
452         switch (rtm_type) {
453                 case RTM_NEWLINK:
454                 case RTM_SETLINK:
455                 case RTM_GETLINK:
456                 case RTM_DELLINK:
457                         switch (type) {
458                                 case IFLA_CARRIER:
459                                 case IFLA_OPERSTATE:
460                                 case IFLA_LINKMODE:
461                                 break;
462                         default:
463                                 return -ENOTSUP;
464                         }
465
466                         break;
467                 default:
468                         return -ENOTSUP;
469         }
470
471         r = add_rtattr(m, type, &data, sizeof(uint8_t));
472         if (r < 0)
473                 return r;
474
475         return 0;
476 }
477
478
479 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
480         uint16_t rtm_type;
481         int r;
482
483         assert_return(m, -EINVAL);
484         assert_return(!m->sealed, -EPERM);
485
486         r = sd_rtnl_message_get_type(m, &rtm_type);
487         if (r < 0)
488                 return r;
489
490         /* check that the type is correct */
491         switch (rtm_type) {
492                 case RTM_NEWLINK:
493                 case RTM_SETLINK:
494                 case RTM_GETLINK:
495                 case RTM_DELLINK:
496                         if (m->n_containers == 2 &&
497                             GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
498                             GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
499                             type == IFLA_VLAN_ID)
500                                 break;
501                         else
502                                 return -ENOTSUP;
503
504                 default:
505                         return -ENOTSUP;
506         }
507
508         r = add_rtattr(m, type, &data, sizeof(uint16_t));
509         if (r < 0)
510                 return r;
511
512         return 0;
513 }
514
515 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
516         uint16_t rtm_type;
517         int r;
518
519         assert_return(m, -EINVAL);
520         assert_return(!m->sealed, -EPERM);
521
522         r = sd_rtnl_message_get_type(m, &rtm_type);
523         if (r < 0)
524                 return r;
525
526         /* check that the type is correct */
527         switch (rtm_type) {
528                 case RTM_NEWLINK:
529                 case RTM_SETLINK:
530                 case RTM_GETLINK:
531                 case RTM_DELLINK:
532                         switch (type) {
533                                 case IFLA_MASTER:
534                                 case IFLA_MTU:
535                                 case IFLA_LINK:
536                                 case IFLA_GROUP:
537                                 case IFLA_TXQLEN:
538                                 case IFLA_WEIGHT:
539                                 case IFLA_NET_NS_FD:
540                                 case IFLA_NET_NS_PID:
541                                 case IFLA_PROMISCUITY:
542                                 case IFLA_NUM_TX_QUEUES:
543                                 case IFLA_NUM_RX_QUEUES:
544                                 case IFLA_MACVLAN_MODE:
545                                         break;
546                                 default:
547                                         return -ENOTSUP;
548                         }
549                         break;
550                 case RTM_NEWROUTE:
551                 case RTM_GETROUTE:
552                 case RTM_DELROUTE:
553                         switch (type) {
554                                 case RTA_TABLE:
555                                 case RTA_PRIORITY:
556                                 case RTA_IIF:
557                                 case RTA_OIF:
558                                 case RTA_MARK:
559                                         break;
560                                 default:
561                                         return -ENOTSUP;
562                         }
563                         break;
564                 default:
565                         return -ENOTSUP;
566         }
567
568         r = add_rtattr(m, type, &data, sizeof(uint32_t));
569         if (r < 0)
570                 return r;
571
572         return 0;
573 }
574
575 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
576         struct ifaddrmsg *ifa;
577         struct rtmsg *rtm;
578         uint16_t rtm_type;
579         int r;
580
581         assert_return(m, -EINVAL);
582         assert_return(!m->sealed, -EPERM);
583         assert_return(data, -EINVAL);
584
585         r = sd_rtnl_message_get_type(m, &rtm_type);
586         if (r < 0)
587                 return r;
588
589         /* check that the type is correct */
590         switch (rtm_type) {
591                 case RTM_NEWADDR:
592                 case RTM_GETADDR:
593                 case RTM_DELADDR:
594                         switch (type) {
595                                 case IFA_ADDRESS:
596                                 case IFA_LOCAL:
597                                 case IFA_BROADCAST:
598                                 case IFA_ANYCAST:
599                                         ifa = NLMSG_DATA(m->hdr);
600
601                                         if (ifa->ifa_family != AF_INET)
602                                                 return -EINVAL;
603
604                                         break;
605                                 default:
606                                         return -ENOTSUP;
607                         }
608                         break;
609                 case RTM_NEWROUTE:
610                 case RTM_GETROUTE:
611                 case RTM_DELROUTE:
612                         switch (type) {
613                                 case RTA_DST:
614                                 case RTA_SRC:
615                                 case RTA_GATEWAY:
616                                         rtm = NLMSG_DATA(m->hdr);
617
618                                         if (rtm->rtm_family != AF_INET)
619                                                 return -EINVAL;
620
621                                         break;
622                                 default:
623                                         return -ENOTSUP;
624                         }
625                         break;
626                 default:
627                         return -ENOTSUP;
628         }
629
630         r = add_rtattr(m, type, data, sizeof(struct in_addr));
631         if (r < 0)
632                 return r;
633
634         return 0;
635 }
636
637 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
638         struct ifaddrmsg *ifa;
639         struct rtmsg *rtm;
640         uint16_t rtm_type;
641         int r;
642
643         assert_return(m, -EINVAL);
644         assert_return(!m->sealed, -EPERM);
645         assert_return(data, -EINVAL);
646
647         r = sd_rtnl_message_get_type(m, &rtm_type);
648         if (r < 0)
649                 return r;
650
651         /* check that the type is correct */
652         switch (rtm_type) {
653                 case RTM_NEWADDR:
654                 case RTM_GETADDR:
655                 case RTM_DELADDR:
656                         switch (type) {
657                                 case IFA_ADDRESS:
658                                 case IFA_LOCAL:
659                                 case IFA_BROADCAST:
660                                 case IFA_ANYCAST:
661                                         ifa = NLMSG_DATA(m->hdr);
662
663                                         if (ifa->ifa_family != AF_INET6)
664                                                 return -EINVAL;
665
666                                         break;
667                                 default:
668                                         return -ENOTSUP;
669                         }
670                         break;
671                 case RTM_NEWROUTE:
672                 case RTM_GETROUTE:
673                 case RTM_DELROUTE:
674                         switch (type) {
675                                 case RTA_DST:
676                                 case RTA_SRC:
677                                 case RTA_GATEWAY:
678                                         rtm = NLMSG_DATA(m->hdr);
679
680                                         if (rtm->rtm_family != AF_INET6)
681                                                 return -EINVAL;
682
683                                         break;
684                                 default:
685                                         return -ENOTSUP;
686                         }
687                 default:
688                         return -ENOTSUP;
689         }
690
691         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
692         if (r < 0)
693                 return r;
694
695         return 0;
696 }
697
698 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
699         uint16_t rtm_type;
700         int r;
701
702         assert_return(m, -EINVAL);
703         assert_return(!m->sealed, -EPERM);
704         assert_return(data, -EINVAL);
705
706         sd_rtnl_message_get_type(m, &rtm_type);
707
708         switch (rtm_type) {
709                 case RTM_NEWLINK:
710                 case RTM_SETLINK:
711                 case RTM_DELLINK:
712                 case RTM_GETLINK:
713                         switch (type) {
714                                 case IFLA_ADDRESS:
715                                 case IFLA_BROADCAST:
716                                         break;
717                                 default:
718                                         return -ENOTSUP;
719                         }
720                         break;
721                 default:
722                         return -ENOTSUP;
723         }
724
725         r = add_rtattr(m, type, data, ETH_ALEN);
726         if (r < 0)
727                 return r;
728
729         return 0;
730 }
731
732 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
733         uint16_t rtm_type;
734
735         assert_return(m, -EINVAL);
736         assert_return(!m->sealed, -EPERM);
737
738         sd_rtnl_message_get_type(m, &rtm_type);
739
740         if (rtnl_message_type_is_link(rtm_type)) {
741
742                 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
743                     (type == IFLA_INFO_DATA && m->n_containers == 1 &&
744                      GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
745                         return add_rtattr(m, type, NULL, 0);
746                 else if (type == VETH_INFO_PEER && m->n_containers == 2 &&
747                          GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
748                          GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO)
749                         return add_rtattr(m, type, NULL, sizeof(struct ifinfomsg));
750         }
751
752         return -ENOTSUP;
753 }
754
755 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
756         assert_return(m, -EINVAL);
757         assert_return(!m->sealed, -EPERM);
758         assert_return(m->n_containers > 0, -EINVAL);
759
760         m->n_containers --;
761
762         return 0;
763 }
764
765 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
766         size_t remaining_size;
767         uint16_t rtm_type;
768         int r;
769
770         assert_return(m, -EINVAL);
771         assert_return(m->sealed, -EPERM);
772         assert_return(m->next_rta_offset, -EINVAL);
773         assert_return(type, -EINVAL);
774         assert_return(data, -EINVAL);
775
776         /* only read until the end of the current container */
777         if (m->n_containers)
778                 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
779                                  (m->next_rta_offset -
780                                   m->container_offsets[m->n_containers - 1]);
781         else
782                 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
783
784         if (!RTA_OK(NEXT_RTA(m), remaining_size))
785                 return 0;
786
787         /* if we read a container, return its type, but do not enter it*/
788         r = sd_rtnl_message_get_type(m, &rtm_type);
789         if (r < 0)
790                 return r;
791
792         *type = NEXT_RTA(m)->rta_type;
793
794         if (rtnl_message_type_is_link(rtm_type) &&
795             ((m->n_containers == 0 &&
796               NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
797              (m->n_containers == 1 &&
798               GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
799               NEXT_RTA(m)->rta_type == IFLA_INFO_DATA)))
800                 *data = NULL;
801         else
802                 *data = RTA_DATA(NEXT_RTA(m));
803
804         UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
805
806         return 1;
807 }
808
809 int rtnl_message_read_internal(sd_rtnl_message *m, unsigned short type, void **data) {
810         struct rtattr *rta;
811
812         assert_return(m, -EINVAL);
813         assert_return(m->sealed, -EPERM);
814         assert_return(data, -EINVAL);
815         assert_return(m->rta_offset_tb, -EINVAL);
816         assert_return(type < m->rta_tb_size, -EINVAL);
817
818         if(!m->rta_offset_tb[type])
819                 return -ENODATA;
820
821         rta = (struct rtattr*)((uint8_t *) m->hdr + m->rta_offset_tb[type]);
822
823         *data = RTA_DATA(rta);
824
825         return RTA_PAYLOAD(rta);
826 }
827
828 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
829         int r;
830         void *attr_data;
831
832         assert_return(data, -EINVAL);
833
834         r = rtnl_message_read_internal(m, type, &attr_data);
835         if (r < 0)
836                 return r;
837         else if (strnlen(attr_data, r) >= (size_t) r)
838                 return -EIO;
839
840         *data = (char *) attr_data;
841
842         return 0;
843 }
844
845 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
846         int r;
847         void *attr_data;
848
849         assert_return(data, -EINVAL);
850
851         r = rtnl_message_read_internal(m, type, &attr_data);
852         if (r < 0)
853                 return r;
854         else if ((size_t) r < sizeof(uint8_t))
855                 return -EIO;
856
857         *data = *(uint8_t *) attr_data;
858
859         return 0;
860 }
861
862 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
863         int r;
864         void *attr_data;
865
866         assert_return(data, -EINVAL);
867
868         r = rtnl_message_read_internal(m, type, &attr_data);
869         if (r < 0)
870                 return r;
871         else if ((size_t) r < sizeof(uint16_t))
872                 return -EIO;
873
874         *data = *(uint16_t *) attr_data;
875
876         return 0;
877 }
878
879 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
880         int r;
881         void *attr_data;
882
883         assert_return(data, -EINVAL);
884
885         r = rtnl_message_read_internal(m, type, &attr_data);
886         if (r < 0)
887                 return r;
888         else if ((size_t)r < sizeof(uint32_t))
889                 return -EIO;
890
891         *data = *(uint32_t *) attr_data;
892
893         return 0;
894 }
895
896 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_addr *data) {
897         int r;
898         void *attr_data;
899
900         assert_return(data, -EINVAL);
901
902         r = rtnl_message_read_internal(m, type, &attr_data);
903         if (r < 0)
904                 return r;
905         else if ((size_t)r < sizeof(struct ether_addr))
906                 return -EIO;
907
908         memcpy(data, attr_data, sizeof(struct ether_addr));
909
910         return 0;
911 }
912
913 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
914         int r;
915         void *attr_data;
916
917         assert_return(data, -EINVAL);
918
919         r = rtnl_message_read_internal(m, type, &attr_data);
920         if (r < 0)
921                 return r;
922         else if ((size_t)r < sizeof(struct in_addr))
923                 return -EIO;
924
925         memcpy(data, attr_data, sizeof(struct in_addr));
926
927         return 0;
928 }
929
930 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
931         int r;
932         void *attr_data;
933
934         assert_return(data, -EINVAL);
935
936         r = rtnl_message_read_internal(m, type, &attr_data);
937         if(r < 0)
938                 return r;
939
940         memcpy(data, attr_data, sizeof(struct in6_addr));
941
942         return 0;
943 }
944
945 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
946         assert_return(m, -EINVAL);
947         assert_return(m->sealed, -EINVAL);
948         assert_return(m->n_containers > 0, -EINVAL);
949
950         m->n_containers --;
951
952         return 0;
953 }
954
955 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
956         assert(m);
957         assert(m->hdr);
958
959         return m->hdr->nlmsg_seq;
960 }
961
962 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
963         struct nlmsgerr *err;
964
965         assert_return(m, -EINVAL);
966         assert_return(m->hdr, -EINVAL);
967
968         if (m->hdr->nlmsg_type != NLMSG_ERROR)
969                 return 0;
970
971         err = NLMSG_DATA(m->hdr);
972
973         return err->error;
974 }
975
976 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
977         int r;
978
979         assert(m);
980         assert(m->hdr);
981
982         if (m->sealed)
983                 return -EPERM;
984
985         if (nl)
986                 m->hdr->nlmsg_seq = nl->serial++;
987
988         m->sealed = true;
989
990         r = sd_rtnl_message_rewind(m);
991         if (r < 0)
992                 return r;
993
994         return 0;
995 }
996
997 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
998         assert(rtnl);
999         assert(need);
1000
1001         /* ioctl(rtnl->fd, FIONREAD, &need)
1002            Does not appear to work on netlink sockets. libnl uses
1003            MSG_PEEK instead. I don't know if that is worth the
1004            extra roundtrip.
1005
1006            For now we simply use the maximum message size the kernel
1007            may use (NLMSG_GOODSIZE), and then realloc to the actual
1008            size after reading the message (hence avoiding huge memory
1009            usage in case many small messages are kept around) */
1010         *need = page_size();
1011         if (*need > 8192UL)
1012                 *need = 8192UL;
1013
1014         return 0;
1015 }
1016
1017 int rtnl_message_parse(sd_rtnl_message *m,
1018                        size_t **rta_offset_tb,
1019                        unsigned short *rta_tb_size,
1020                        int max,
1021                        struct rtattr *rta,
1022                        unsigned int rt_len) {
1023         int type;
1024         size_t *tb;
1025
1026         tb = (size_t *) new0(size_t *, max);
1027         if(!tb)
1028                 return -ENOMEM;
1029
1030         *rta_tb_size = max;
1031
1032         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1033                 type = rta->rta_type;
1034
1035                 if (type <= max)
1036                         tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1037         }
1038
1039         *rta_offset_tb = tb;
1040
1041         return 0;
1042 }
1043
1044 /* returns the number of bytes sent, or a negative error code */
1045 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1046         union {
1047                 struct sockaddr sa;
1048                 struct sockaddr_nl nl;
1049         } addr = {
1050                 .nl.nl_family = AF_NETLINK,
1051         };
1052         ssize_t k;
1053
1054         assert(nl);
1055         assert(m);
1056         assert(m->hdr);
1057
1058         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1059                         0, &addr.sa, sizeof(addr));
1060         if (k < 0)
1061                 return (errno == EAGAIN) ? 0 : -errno;
1062
1063         return k;
1064 }
1065
1066 /* On success, the number of bytes received is returned and *ret points to the received message
1067  * which has a valid header and the correct size.
1068  * If nothing useful was received 0 is returned.
1069  * On failure, a negative error code is returned.
1070  */
1071 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1072         sd_rtnl_message *m;
1073         union {
1074                 struct sockaddr sa;
1075                 struct sockaddr_nl nl;
1076         } addr;
1077         socklen_t addr_len;
1078         int r;
1079         ssize_t k;
1080         size_t need;
1081
1082         assert(nl);
1083         assert(ret);
1084
1085         r = message_receive_need(nl, &need);
1086         if (r < 0)
1087                 return r;
1088
1089         r = message_new(nl, &m, need);
1090         if (r < 0)
1091                 return r;
1092
1093         /* don't allow sealing/appending to received messages */
1094         m->sealed = true;
1095
1096         addr_len = sizeof(addr);
1097
1098         k = recvfrom(nl->fd, m->hdr, need,
1099                         0, &addr.sa, &addr_len);
1100         if (k < 0)
1101                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
1102         else if (k == 0)
1103                 k = -ECONNRESET; /* connection was closed by the kernel */
1104         else if (addr_len != sizeof(addr.nl) ||
1105                         addr.nl.nl_family != AF_NETLINK)
1106                 k = -EIO; /* not a netlink message */
1107         else if (addr.nl.nl_pid != 0)
1108                 k = 0; /* not from the kernel */
1109         else if ((size_t) k < sizeof(struct nlmsghdr) ||
1110                         (size_t) k < m->hdr->nlmsg_len)
1111                 k = -EIO; /* too small (we do accept too big though) */
1112         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1113                 k = 0; /* not broadcast and not for us */
1114
1115         if (k > 0)
1116                 switch (m->hdr->nlmsg_type) {
1117                         /* check that the size matches the message type */
1118                         case NLMSG_ERROR:
1119                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1120                                         k = -EIO;
1121                                 break;
1122                         case RTM_NEWLINK:
1123                         case RTM_SETLINK:
1124                         case RTM_DELLINK:
1125                         case RTM_GETLINK:
1126                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1127                                         k = -EIO;
1128                                 else {
1129                                         struct ifinfomsg *ifi;
1130
1131                                         ifi = NLMSG_DATA(m->hdr);
1132                                         UPDATE_RTA(m, IFLA_RTA(ifi));
1133
1134                                         r = rtnl_message_parse(m,
1135                                                                &m->rta_offset_tb,
1136                                                                &m->rta_tb_size,
1137                                                                IFLA_MAX,
1138                                                                IFLA_RTA(ifi),
1139                                                                IFLA_PAYLOAD(m->hdr));
1140
1141                                 }
1142                                 break;
1143                         case RTM_NEWADDR:
1144                         case RTM_DELADDR:
1145                         case RTM_GETADDR:
1146                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1147                                         k = -EIO;
1148                                 else {
1149                                         struct ifaddrmsg *ifa;
1150
1151                                         ifa = NLMSG_DATA(m->hdr);
1152                                         UPDATE_RTA(m, IFA_RTA(ifa));
1153
1154                                         r = rtnl_message_parse(m,
1155                                                                &m->rta_offset_tb,
1156                                                                &m->rta_tb_size,
1157                                                                IFA_MAX,
1158                                                                IFA_RTA(ifa),
1159                                                                IFA_PAYLOAD(m->hdr));
1160                                 }
1161                                 break;
1162                         case RTM_NEWROUTE:
1163                         case RTM_DELROUTE:
1164                         case RTM_GETROUTE:
1165                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1166                                         k = -EIO;
1167                                 else {
1168                                         struct rtmsg *rtm;
1169
1170                                         rtm = NLMSG_DATA(m->hdr);
1171                                         UPDATE_RTA(m, RTM_RTA(rtm));
1172
1173                                         r = rtnl_message_parse(m,
1174                                                                &m->rta_offset_tb,
1175                                                                &m->rta_tb_size,
1176                                                                RTA_MAX,
1177                                                                RTM_RTA(rtm),
1178                                                                RTM_PAYLOAD(m->hdr));
1179                                 }
1180                                 break;
1181                         case NLMSG_NOOP:
1182                                 k = 0;
1183                                 break;
1184                         default:
1185                                 k = 0; /* ignoring message of unknown type */
1186                 }
1187
1188         if (k <= 0)
1189                 sd_rtnl_message_unref(m);
1190         else {
1191                 /* we probably allocated way too much memory, give it back */
1192                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
1193                 *ret = m;
1194         }
1195
1196         return k;
1197 }
1198
1199 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1200         struct ifinfomsg *ifi;
1201         struct ifaddrmsg *ifa;
1202         struct rtmsg *rtm;
1203
1204         assert_return(m, -EINVAL);
1205         assert_return(m->sealed, -EPERM);
1206         assert_return(m->hdr, -EINVAL);
1207
1208         switch(m->hdr->nlmsg_type) {
1209                 case RTM_NEWLINK:
1210                 case RTM_SETLINK:
1211                 case RTM_GETLINK:
1212                 case RTM_DELLINK:
1213                         ifi = NLMSG_DATA(m->hdr);
1214                         UPDATE_RTA(m, IFLA_RTA(ifi));
1215
1216                         break;
1217                 case RTM_NEWADDR:
1218                 case RTM_GETADDR:
1219                 case RTM_DELADDR:
1220                         ifa = NLMSG_DATA(m->hdr);
1221                         UPDATE_RTA(m, IFA_RTA(ifa));
1222
1223                         break;
1224                 case RTM_NEWROUTE:
1225                 case RTM_GETROUTE:
1226                 case RTM_DELROUTE:
1227                         rtm = NLMSG_DATA(m->hdr);
1228                         UPDATE_RTA(m, RTM_RTA(rtm));
1229
1230                         break;
1231                 default:
1232                         return -ENOTSUP;
1233         }
1234
1235         m->n_containers = 0;
1236
1237         return 0;
1238 }