chiark / gitweb /
sd-rtnl: never treat broadcasts as replies
[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         assert_return(m, -EINVAL);
811         assert_return(m->sealed, -EPERM);
812         assert_return(data, -EINVAL);
813         assert_return(m->rta_offset_tb, -EINVAL);
814         assert_return(type < m->rta_tb_size, -EINVAL);
815
816         if(!m->rta_offset_tb[type])
817                 return -ENODATA;
818
819         *data = RTA_DATA((struct rtattr *)((uint8_t *) m->hdr + m->rta_offset_tb[type]));
820
821         return 0;
822 }
823
824 int sd_rtnl_message_read_string(sd_rtnl_message *m, unsigned short type, char **data) {
825         int r;
826         void *attr_data;
827
828         assert_return(data, -EINVAL);
829
830         r = rtnl_message_read_internal(m, type, &attr_data);
831         if(r < 0)
832                 return r;
833
834         *data = (char *) attr_data;
835
836         return 0;
837 }
838
839 int sd_rtnl_message_read_u8(sd_rtnl_message *m, unsigned short type, uint8_t *data) {
840         int r;
841         void *attr_data;
842
843         assert_return(data, -EINVAL);
844
845         r = rtnl_message_read_internal(m, type, &attr_data);
846         if(r < 0)
847                 return r;
848
849         *data = *(uint8_t *) attr_data;
850
851         return 0;
852 }
853
854 int sd_rtnl_message_read_u16(sd_rtnl_message *m, unsigned short type, uint16_t *data) {
855         int r;
856         void *attr_data;
857
858         assert_return(data, -EINVAL);
859
860         r = rtnl_message_read_internal(m, type, &attr_data);
861         if(r < 0)
862                 return r;
863
864         *data = *(uint16_t *) attr_data;
865
866         return 0;
867 }
868
869 int sd_rtnl_message_read_u32(sd_rtnl_message *m, unsigned short type, uint32_t *data) {
870         int r;
871         void *attr_data;
872
873         assert_return(data, -EINVAL);
874
875         r = rtnl_message_read_internal(m, type, &attr_data);
876         if(r < 0)
877                 return r;
878
879         *data = *(uint32_t *) attr_data;
880
881         return 0;
882 }
883
884 int sd_rtnl_message_read_ether_addr(sd_rtnl_message *m, unsigned short type, struct ether_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
894         memcpy(data, attr_data, sizeof(struct ether_addr));
895
896         return 0;
897 }
898
899 int sd_rtnl_message_read_in_addr(sd_rtnl_message *m, unsigned short type, struct in_addr *data) {
900         int r;
901         void *attr_data;
902
903         assert_return(data, -EINVAL);
904
905         r = rtnl_message_read_internal(m, type, &attr_data);
906         if(r < 0)
907                 return r;
908
909         memcpy(data, attr_data, sizeof(struct in_addr));
910
911         return 0;
912 }
913
914 int sd_rtnl_message_read_in6_addr(sd_rtnl_message *m, unsigned short type, struct in6_addr *data) {
915         int r;
916         void *attr_data;
917
918         assert_return(data, -EINVAL);
919
920         r = rtnl_message_read_internal(m, type, &attr_data);
921         if(r < 0)
922                 return r;
923
924         memcpy(data, attr_data, sizeof(struct in6_addr));
925
926         return 0;
927 }
928
929 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
930         assert_return(m, -EINVAL);
931         assert_return(m->sealed, -EINVAL);
932         assert_return(m->n_containers > 0, -EINVAL);
933
934         m->n_containers --;
935
936         return 0;
937 }
938
939 uint32_t rtnl_message_get_serial(sd_rtnl_message *m) {
940         assert(m);
941         assert(m->hdr);
942
943         return m->hdr->nlmsg_seq;
944 }
945
946 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
947         struct nlmsgerr *err;
948
949         assert_return(m, -EINVAL);
950         assert_return(m->hdr, -EINVAL);
951
952         if (m->hdr->nlmsg_type != NLMSG_ERROR)
953                 return 0;
954
955         err = NLMSG_DATA(m->hdr);
956
957         return err->error;
958 }
959
960 int rtnl_message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
961         int r;
962
963         assert(m);
964         assert(m->hdr);
965
966         if (m->sealed)
967                 return -EPERM;
968
969         if (nl)
970                 m->hdr->nlmsg_seq = nl->serial++;
971
972         m->sealed = true;
973
974         r = sd_rtnl_message_rewind(m);
975         if (r < 0)
976                 return r;
977
978         return 0;
979 }
980
981 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
982         assert(rtnl);
983         assert(need);
984
985         /* ioctl(rtnl->fd, FIONREAD, &need)
986            Does not appear to work on netlink sockets. libnl uses
987            MSG_PEEK instead. I don't know if that is worth the
988            extra roundtrip.
989
990            For now we simply use the maximum message size the kernel
991            may use (NLMSG_GOODSIZE), and then realloc to the actual
992            size after reading the message (hence avoiding huge memory
993            usage in case many small messages are kept around) */
994         *need = page_size();
995         if (*need > 8192UL)
996                 *need = 8192UL;
997
998         return 0;
999 }
1000
1001 int rtnl_message_parse(sd_rtnl_message *m,
1002                        size_t **rta_offset_tb,
1003                        unsigned short *rta_tb_size,
1004                        int max,
1005                        struct rtattr *rta,
1006                        unsigned int rt_len) {
1007         int type;
1008         size_t *tb;
1009
1010         tb = (size_t *) new0(size_t *, max);
1011         if(!tb)
1012                 return -ENOMEM;
1013
1014         *rta_tb_size = max;
1015
1016         for (; RTA_OK(rta, rt_len); rta = RTA_NEXT(rta, rt_len)) {
1017                 type = rta->rta_type;
1018
1019                 if (type < max && !tb[type])
1020                         tb[type] = (uint8_t *) rta - (uint8_t *) m->hdr;
1021         }
1022
1023         *rta_offset_tb = tb;
1024
1025         return 0;
1026 }
1027
1028 /* returns the number of bytes sent, or a negative error code */
1029 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
1030         union {
1031                 struct sockaddr sa;
1032                 struct sockaddr_nl nl;
1033         } addr = {
1034                 .nl.nl_family = AF_NETLINK,
1035         };
1036         ssize_t k;
1037
1038         assert(nl);
1039         assert(m);
1040         assert(m->hdr);
1041
1042         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
1043                         0, &addr.sa, sizeof(addr));
1044         if (k < 0)
1045                 return (errno == EAGAIN) ? 0 : -errno;
1046
1047         return k;
1048 }
1049
1050 /* On success, the number of bytes received is returned and *ret points to the received message
1051  * which has a valid header and the correct size.
1052  * If nothing useful was received 0 is returned.
1053  * On failure, a negative error code is returned.
1054  */
1055 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
1056         sd_rtnl_message *m;
1057         union {
1058                 struct sockaddr sa;
1059                 struct sockaddr_nl nl;
1060         } addr;
1061         socklen_t addr_len;
1062         int r;
1063         ssize_t k;
1064         size_t need;
1065
1066         assert(nl);
1067         assert(ret);
1068
1069         r = message_receive_need(nl, &need);
1070         if (r < 0)
1071                 return r;
1072
1073         r = message_new(nl, &m, need);
1074         if (r < 0)
1075                 return r;
1076
1077         /* don't allow sealing/appending to received messages */
1078         m->sealed = true;
1079
1080         addr_len = sizeof(addr);
1081
1082         k = recvfrom(nl->fd, m->hdr, need,
1083                         0, &addr.sa, &addr_len);
1084         if (k < 0)
1085                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
1086         else if (k == 0)
1087                 k = -ECONNRESET; /* connection was closed by the kernel */
1088         else if (addr_len != sizeof(addr.nl) ||
1089                         addr.nl.nl_family != AF_NETLINK)
1090                 k = -EIO; /* not a netlink message */
1091         else if (addr.nl.nl_pid != 0)
1092                 k = 0; /* not from the kernel */
1093         else if ((size_t) k < sizeof(struct nlmsghdr) ||
1094                         (size_t) k < m->hdr->nlmsg_len)
1095                 k = -EIO; /* too small (we do accept too big though) */
1096         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
1097                 k = 0; /* not broadcast and not for us */
1098
1099         if (k > 0)
1100                 switch (m->hdr->nlmsg_type) {
1101                         /* check that the size matches the message type */
1102                         case NLMSG_ERROR:
1103                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
1104                                         k = -EIO;
1105                                 break;
1106                         case RTM_NEWLINK:
1107                         case RTM_SETLINK:
1108                         case RTM_DELLINK:
1109                         case RTM_GETLINK:
1110                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
1111                                         k = -EIO;
1112                                 else {
1113                                         struct ifinfomsg *ifi;
1114
1115                                         ifi = NLMSG_DATA(m->hdr);
1116                                         UPDATE_RTA(m, IFLA_RTA(ifi));
1117
1118                                         r = rtnl_message_parse(m,
1119                                                                &m->rta_offset_tb,
1120                                                                &m->rta_tb_size,
1121                                                                IFLA_MAX,
1122                                                                IFLA_RTA(ifi),
1123                                                                IFLA_PAYLOAD(m->hdr));
1124
1125                                 }
1126                                 break;
1127                         case RTM_NEWADDR:
1128                         case RTM_DELADDR:
1129                         case RTM_GETADDR:
1130                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
1131                                         k = -EIO;
1132                                 else {
1133                                         struct ifaddrmsg *ifa;
1134
1135                                         ifa = NLMSG_DATA(m->hdr);
1136                                         UPDATE_RTA(m, IFA_RTA(ifa));
1137
1138                                         r = rtnl_message_parse(m,
1139                                                                &m->rta_offset_tb,
1140                                                                &m->rta_tb_size,
1141                                                                IFA_MAX,
1142                                                                IFA_RTA(ifa),
1143                                                                IFA_PAYLOAD(m->hdr));
1144                                 }
1145                                 break;
1146                         case RTM_NEWROUTE:
1147                         case RTM_DELROUTE:
1148                         case RTM_GETROUTE:
1149                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
1150                                         k = -EIO;
1151                                 else {
1152                                         struct rtmsg *rtm;
1153
1154                                         rtm = NLMSG_DATA(m->hdr);
1155                                         UPDATE_RTA(m, RTM_RTA(rtm));
1156
1157                                         r = rtnl_message_parse(m,
1158                                                                &m->rta_offset_tb,
1159                                                                &m->rta_tb_size,
1160                                                                RTA_MAX,
1161                                                                RTM_RTA(rtm),
1162                                                                RTM_PAYLOAD(m->hdr));
1163                                 }
1164                                 break;
1165                         case NLMSG_NOOP:
1166                                 k = 0;
1167                                 break;
1168                         default:
1169                                 k = 0; /* ignoring message of unknown type */
1170                 }
1171
1172         if (k <= 0)
1173                 sd_rtnl_message_unref(m);
1174         else {
1175                 /* we probably allocated way too much memory, give it back */
1176                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
1177                 *ret = m;
1178         }
1179
1180         return k;
1181 }
1182
1183 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1184         struct ifinfomsg *ifi;
1185         struct ifaddrmsg *ifa;
1186         struct rtmsg *rtm;
1187
1188         assert_return(m, -EINVAL);
1189         assert_return(m->sealed, -EPERM);
1190         assert_return(m->hdr, -EINVAL);
1191
1192         switch(m->hdr->nlmsg_type) {
1193                 case RTM_NEWLINK:
1194                 case RTM_SETLINK:
1195                 case RTM_GETLINK:
1196                 case RTM_DELLINK:
1197                         ifi = NLMSG_DATA(m->hdr);
1198                         UPDATE_RTA(m, IFLA_RTA(ifi));
1199
1200                         break;
1201                 case RTM_NEWADDR:
1202                 case RTM_GETADDR:
1203                 case RTM_DELADDR:
1204                         ifa = NLMSG_DATA(m->hdr);
1205                         UPDATE_RTA(m, IFA_RTA(ifa));
1206
1207                         break;
1208                 case RTM_NEWROUTE:
1209                 case RTM_GETROUTE:
1210                 case RTM_DELROUTE:
1211                         rtm = NLMSG_DATA(m->hdr);
1212                         UPDATE_RTA(m, RTM_RTA(rtm));
1213
1214                         break;
1215                 default:
1216                         return -ENOTSUP;
1217         }
1218
1219         m->n_containers = 0;
1220
1221         return 0;
1222 }