chiark / gitweb /
sd-dhcp-client/net-util: make netmask_to_prefixlen generic
[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 <linux/rtnetlink.h>
23 #include <netinet/in.h>
24 #include <netinet/ether.h>
25 #include <stdbool.h>
26 #include <unistd.h>
27
28 #include "util.h"
29 #include "refcnt.h"
30
31 #include "sd-rtnl.h"
32 #include "rtnl-internal.h"
33
34 struct sd_rtnl_message {
35         RefCount n_ref;
36
37         struct nlmsghdr *hdr;
38         size_t container_offsets[RTNL_CONTAINER_DEPTH]; /* offset from hdr to each container's start */
39         unsigned n_containers; /* number of containers */
40         size_t next_rta_offset; /* offset from hdr to next rta */
41
42         bool sealed:1;
43 };
44
45 #define GET_CONTAINER(m, i) (i < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->container_offsets[i]) : NULL)
46 #define NEXT_RTA(m) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->next_rta_offset))
47 #define UPDATE_RTA(m, new) (m)->next_rta_offset = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
48 #define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers ++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
49
50 static int message_new(sd_rtnl_message **ret, size_t initial_size) {
51         sd_rtnl_message *m;
52
53         assert_return(ret, -EINVAL);
54         assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
55
56         m = new0(sd_rtnl_message, 1);
57         if (!m)
58                 return -ENOMEM;
59
60         m->hdr = malloc0(initial_size);
61         if (!m->hdr) {
62                 free(m);
63                 return -ENOMEM;
64         }
65
66         m->n_ref = REFCNT_INIT;
67
68         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
69         m->sealed = false;
70
71         *ret = m;
72
73         return 0;
74 }
75
76 int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) {
77         struct nlmsgerr *err;
78         int r;
79
80         assert(error <= 0);
81
82         r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr)));
83         if (r < 0)
84                 return r;
85
86         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
87         (*ret)->hdr->nlmsg_type = NLMSG_ERROR;
88         (*ret)->hdr->nlmsg_seq = serial;
89
90         err = NLMSG_DATA((*ret)->hdr);
91
92         err->error = error;
93
94         return 0;
95 }
96
97 bool message_type_is_route(uint16_t type) {
98         switch (type) {
99                 case RTM_NEWROUTE:
100                 case RTM_GETROUTE:
101                 case RTM_DELROUTE:
102                         return true;
103                 default:
104                         return false;
105         }
106 }
107
108 bool message_type_is_link(uint16_t type) {
109         switch (type) {
110                 case RTM_NEWLINK:
111                 case RTM_SETLINK:
112                 case RTM_GETLINK:
113                 case RTM_DELLINK:
114                         return true;
115                 default:
116                         return false;
117         }
118 }
119
120 bool message_type_is_addr(uint16_t type) {
121         switch (type) {
122                 case RTM_NEWADDR:
123                 case RTM_GETADDR:
124                 case RTM_DELADDR:
125                         return true;
126                 default:
127                         return false;
128         }
129 }
130
131 int sd_rtnl_message_route_set_dst_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
132         struct rtmsg *rtm;
133
134         assert_return(m, -EINVAL);
135         assert_return(m->hdr, -EINVAL);
136         assert_return(message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
137
138         rtm = NLMSG_DATA(m->hdr);
139
140         if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
141             (rtm->rtm_family == AF_INET6 && prefixlen > 128))
142                 return -ERANGE;
143
144         rtm->rtm_dst_len = prefixlen;
145
146         return 0;
147 }
148
149 int sd_rtnl_message_route_new(uint16_t nlmsg_type, unsigned char rtm_family,
150                               sd_rtnl_message **ret) {
151         struct rtmsg *rtm;
152         int r;
153
154         assert_return(message_type_is_route(nlmsg_type), -EINVAL);
155         assert_return(rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
156         assert_return(ret, -EINVAL);
157
158         r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
159         if (r < 0)
160                 return r;
161
162         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
163         (*ret)->hdr->nlmsg_type = nlmsg_type;
164         if (nlmsg_type == RTM_NEWROUTE)
165                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
166
167         rtm = NLMSG_DATA((*ret)->hdr);
168
169         UPDATE_RTA(*ret, RTM_RTA(rtm));
170
171         rtm->rtm_family = rtm_family;
172         rtm->rtm_scope = RT_SCOPE_UNIVERSE;
173         rtm->rtm_type = RTN_UNICAST;
174         rtm->rtm_table = RT_TABLE_MAIN;
175         rtm->rtm_protocol = RTPROT_BOOT;
176
177         return 0;
178 }
179
180 int sd_rtnl_message_link_set_flags(sd_rtnl_message *m, unsigned flags, unsigned change) {
181         struct ifinfomsg *ifi;
182
183         assert_return(m, -EINVAL);
184         assert_return(m->hdr, -EINVAL);
185         assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
186
187         ifi = NLMSG_DATA(m->hdr);
188
189         ifi->ifi_flags = flags;
190         if (change)
191                 ifi->ifi_change = change;
192         else
193                 ifi->ifi_change = 0xffffffff;
194
195         return 0;
196 }
197
198 int sd_rtnl_message_link_set_type(sd_rtnl_message *m, unsigned type) {
199         struct ifinfomsg *ifi;
200
201         assert_return(m, -EINVAL);
202         assert_return(m->hdr, -EINVAL);
203         assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
204
205         ifi = NLMSG_DATA(m->hdr);
206
207         ifi->ifi_type = type;
208
209         return 0;
210 }
211
212 int sd_rtnl_message_link_new(uint16_t nlmsg_type, int index, sd_rtnl_message **ret) {
213         struct ifinfomsg *ifi;
214         int r;
215
216         assert_return(message_type_is_link(nlmsg_type), -EINVAL);
217         assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
218         assert_return(ret, -EINVAL);
219
220         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
221         if (r < 0)
222                 return r;
223
224         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
225         (*ret)->hdr->nlmsg_type = nlmsg_type;
226         if (nlmsg_type == RTM_NEWLINK)
227                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
228
229         ifi = NLMSG_DATA((*ret)->hdr);
230
231         ifi->ifi_family = AF_UNSPEC;
232         ifi->ifi_index = index;
233
234         UPDATE_RTA(*ret, IFLA_RTA(ifi));
235
236         return 0;
237 }
238
239 int sd_rtnl_message_addr_set_prefixlen(sd_rtnl_message *m, unsigned char prefixlen) {
240         struct ifaddrmsg *ifa;
241
242         assert_return(m, -EINVAL);
243         assert_return(m->hdr, -EINVAL);
244         assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
245
246         ifa = NLMSG_DATA(m->hdr);
247
248         if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
249             (ifa->ifa_family == AF_INET6 && prefixlen > 128))
250                 return -ERANGE;
251
252         ifa->ifa_prefixlen = prefixlen;
253
254         return 0;
255 }
256
257 int sd_rtnl_message_addr_set_flags(sd_rtnl_message *m, unsigned char flags) {
258         struct ifaddrmsg *ifa;
259
260         assert_return(m, -EINVAL);
261         assert_return(m->hdr, -EINVAL);
262         assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
263
264         ifa = NLMSG_DATA(m->hdr);
265
266         ifa->ifa_flags = flags;
267
268         return 0;
269 }
270
271 int sd_rtnl_message_addr_set_scope(sd_rtnl_message *m, unsigned char scope) {
272         struct ifaddrmsg *ifa;
273
274         assert_return(m, -EINVAL);
275         assert_return(m->hdr, -EINVAL);
276         assert_return(message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
277
278         ifa = NLMSG_DATA(m->hdr);
279
280         ifa->ifa_scope = scope;
281
282         return 0;
283 }
284
285 int sd_rtnl_message_addr_new(uint16_t nlmsg_type, int index, unsigned char family,
286                              sd_rtnl_message **ret) {
287         struct ifaddrmsg *ifa;
288         int r;
289
290         assert_return(message_type_is_addr(nlmsg_type), -EINVAL);
291         assert_return(index > 0, -EINVAL);
292         assert_return(family == AF_INET || family == AF_INET6, -EINVAL);
293         assert_return(ret, -EINVAL);
294
295         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
296         if (r < 0)
297                 return r;
298
299         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
300         (*ret)->hdr->nlmsg_type = nlmsg_type;
301
302         ifa = NLMSG_DATA((*ret)->hdr);
303
304         ifa->ifa_index = index;
305         ifa->ifa_family = family;
306         if (family == AF_INET)
307                 ifa->ifa_prefixlen = 32;
308         else if (family == AF_INET6)
309                 ifa->ifa_prefixlen = 128;
310
311         UPDATE_RTA(*ret, IFA_RTA(ifa));
312
313         return 0;
314 }
315
316 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
317         if (m)
318                 assert_se(REFCNT_INC(m->n_ref) >= 2);
319
320         return m;
321 }
322
323 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
324         if (m && REFCNT_DEC(m->n_ref) <= 0) {
325                 free(m->hdr);
326                 free(m);
327         }
328
329         return NULL;
330 }
331
332 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
333         assert_return(m, -EINVAL);
334         assert_return(type, -EINVAL);
335
336         *type = m->hdr->nlmsg_type;
337
338         return 0;
339 }
340
341 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
342         struct ifinfomsg *ifi;
343
344         assert_return(m, -EINVAL);
345         assert_return(m->hdr, -EINVAL);
346         assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
347         assert_return(ifindex, -EINVAL);
348
349         ifi = NLMSG_DATA(m->hdr);
350
351         *ifindex = ifi->ifi_index;
352
353         return 0;
354 }
355
356 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
357         struct ifinfomsg *ifi;
358
359         assert_return(m, -EINVAL);
360         assert_return(m->hdr, -EINVAL);
361         assert_return(message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
362         assert_return(flags, -EINVAL);
363
364         ifi = NLMSG_DATA(m->hdr);
365
366         *flags = ifi->ifi_flags;
367
368         return 0;
369 }
370
371 /* If successful the updated message will be correctly aligned, if
372    unsuccessful the old message is untouched. */
373 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
374         uint32_t rta_length, message_length;
375         struct nlmsghdr *new_hdr;
376         struct rtattr *rta;
377         char *padding;
378         unsigned i;
379
380         assert(m);
381         assert(m->hdr);
382         assert(!m->sealed);
383         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
384         assert(!data || data_length > 0);
385         assert(data || m->n_containers < RTNL_CONTAINER_DEPTH);
386
387         /* get the size of the new rta attribute (with padding at the end) */
388         rta_length = RTA_LENGTH(data_length);
389
390         /* get the new message size (with padding at the end) */
391         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
392
393         /* realloc to fit the new attribute */
394         new_hdr = realloc(m->hdr, message_length);
395         if (!new_hdr)
396                 return -ENOMEM;
397         m->hdr = new_hdr;
398
399         /* get pointer to the attribute we are about to add */
400         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
401
402         /* if we are inside containers, extend them */
403         for (i = 0; i < m->n_containers; i++)
404                 GET_CONTAINER(m, i)->rta_len += message_length - m->hdr->nlmsg_len;
405
406         /* fill in the attribute */
407         rta->rta_type = type;
408         rta->rta_len = rta_length;
409         if (!data) {
410                 /* this is the start of a new container */
411                 m->container_offsets[m->n_containers ++] = m->hdr->nlmsg_len;
412         } else {
413                 /* we don't deal with the case where the user lies about the type
414                  * and gives us too little data (so don't do that)
415                 */
416                 padding = mempcpy(RTA_DATA(rta), data, data_length);
417                 /* make sure also the padding at the end of the message is initialized */
418                 memzero(padding,
419                         (uint8_t *) m->hdr + message_length - (uint8_t *) padding);
420         }
421
422         /* update message size */
423         m->hdr->nlmsg_len = message_length;
424
425         return 0;
426 }
427
428 int sd_rtnl_message_append_string(sd_rtnl_message *m, unsigned short type, const char *data) {
429         uint16_t rtm_type;
430         int r;
431
432         assert_return(m, -EINVAL);
433         assert_return(!m->sealed, -EPERM);
434         assert_return(data, -EINVAL);
435
436         r = sd_rtnl_message_get_type(m, &rtm_type);
437         if (r < 0)
438                 return r;
439
440         /* check that the type is correct */
441         switch (rtm_type) {
442                 case RTM_NEWLINK:
443                 case RTM_SETLINK:
444                 case RTM_GETLINK:
445                 case RTM_DELLINK:
446                         if (m->n_containers == 1) {
447                                 if (GET_CONTAINER(m, 0)->rta_type != IFLA_LINKINFO ||
448                                     type != IFLA_INFO_KIND)
449                                         return -ENOTSUP;
450                         } else {
451                                 switch (type) {
452                                         case IFLA_IFNAME:
453                                         case IFLA_IFALIAS:
454                                         case IFLA_QDISC:
455                                                 break;
456                                         default:
457                                                 return -ENOTSUP;
458                                 }
459                         }
460                         break;
461                 case RTM_NEWADDR:
462                 case RTM_GETADDR:
463                 case RTM_DELADDR:
464                         if (type != IFA_LABEL)
465                                 return -ENOTSUP;
466                         break;
467                 default:
468                         return -ENOTSUP;
469         }
470
471         r = add_rtattr(m, type, data, strlen(data) + 1);
472         if (r < 0)
473                 return r;
474
475         return 0;
476 }
477
478 int sd_rtnl_message_append_u16(sd_rtnl_message *m, unsigned short type, uint16_t data) {
479         uint16_t rtm_type;
480         int r;
481
482         assert_return(m, -EINVAL);
483         assert_return(!m->sealed, -EPERM);
484
485         r = sd_rtnl_message_get_type(m, &rtm_type);
486         if (r < 0)
487                 return r;
488
489         /* check that the type is correct */
490         switch (rtm_type) {
491                 case RTM_NEWLINK:
492                 case RTM_SETLINK:
493                 case RTM_GETLINK:
494                 case RTM_DELLINK:
495                         if (m->n_containers == 2 &&
496                             GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
497                             GET_CONTAINER(m, 1)->rta_type == IFLA_INFO_DATA &&
498                             type == IFLA_VLAN_ID)
499                                 break;
500                         else
501                                 return -ENOTSUP;
502                         break;
503                 default:
504                         return -ENOTSUP;
505         }
506
507         r = add_rtattr(m, type, &data, sizeof(uint16_t));
508         if (r < 0)
509                 return r;
510
511         return 0;
512 }
513
514 int sd_rtnl_message_append_u32(sd_rtnl_message *m, unsigned short type, uint32_t data) {
515         uint16_t rtm_type;
516         int r;
517
518         assert_return(m, -EINVAL);
519         assert_return(!m->sealed, -EPERM);
520
521         r = sd_rtnl_message_get_type(m, &rtm_type);
522         if (r < 0)
523                 return r;
524
525         /* check that the type is correct */
526         switch (rtm_type) {
527                 case RTM_NEWLINK:
528                 case RTM_SETLINK:
529                 case RTM_GETLINK:
530                 case RTM_DELLINK:
531                         switch (type) {
532                                 case IFLA_MASTER:
533                                 case IFLA_MTU:
534                                 case IFLA_LINK:
535                                         break;
536                                 default:
537                                         return -ENOTSUP;
538                         }
539                         break;
540                 case RTM_NEWROUTE:
541                 case RTM_GETROUTE:
542                 case RTM_DELROUTE:
543                         switch (type) {
544                                 case RTA_TABLE:
545                                 case RTA_PRIORITY:
546                                 case RTA_IIF:
547                                 case RTA_OIF:
548                                         break;
549                                 default:
550                                         return -ENOTSUP;
551                         }
552                         break;
553                 default:
554                         return -ENOTSUP;
555         }
556
557         r = add_rtattr(m, type, &data, sizeof(uint32_t));
558         if (r < 0)
559                 return r;
560
561         return 0;
562 }
563
564 int sd_rtnl_message_append_in_addr(sd_rtnl_message *m, unsigned short type, const struct in_addr *data) {
565         struct ifaddrmsg *ifa;
566         struct rtmsg *rtm;
567         uint16_t rtm_type;
568         int r;
569
570         assert_return(m, -EINVAL);
571         assert_return(!m->sealed, -EPERM);
572         assert_return(data, -EINVAL);
573
574         r = sd_rtnl_message_get_type(m, &rtm_type);
575         if (r < 0)
576                 return r;
577
578         /* check that the type is correct */
579         switch (rtm_type) {
580                 case RTM_NEWADDR:
581                 case RTM_GETADDR:
582                 case RTM_DELADDR:
583                         switch (type) {
584                                 case IFA_ADDRESS:
585                                 case IFA_LOCAL:
586                                 case IFA_BROADCAST:
587                                 case IFA_ANYCAST:
588                                         ifa = NLMSG_DATA(m->hdr);
589
590                                         if (ifa->ifa_family != AF_INET)
591                                                 return -EINVAL;
592
593                                         break;
594                                 default:
595                                         return -ENOTSUP;
596                         }
597                         break;
598                 case RTM_NEWROUTE:
599                 case RTM_GETROUTE:
600                 case RTM_DELROUTE:
601                         switch (type) {
602                                 case RTA_DST:
603                                 case RTA_SRC:
604                                 case RTA_GATEWAY:
605                                         rtm = NLMSG_DATA(m->hdr);
606
607                                         if (rtm->rtm_family != AF_INET)
608                                                 return -EINVAL;
609
610                                         break;
611                                 default:
612                                         return -ENOTSUP;
613                         }
614                         break;
615                 default:
616                         return -ENOTSUP;
617         }
618
619         r = add_rtattr(m, type, data, sizeof(struct in_addr));
620         if (r < 0)
621                 return r;
622
623         return 0;
624 }
625
626 int sd_rtnl_message_append_in6_addr(sd_rtnl_message *m, unsigned short type, const struct in6_addr *data) {
627         struct ifaddrmsg *ifa;
628         struct rtmsg *rtm;
629         uint16_t rtm_type;
630         int r;
631
632         assert_return(m, -EINVAL);
633         assert_return(!m->sealed, -EPERM);
634         assert_return(data, -EINVAL);
635
636         r = sd_rtnl_message_get_type(m, &rtm_type);
637         if (r < 0)
638                 return r;
639
640         /* check that the type is correct */
641         switch (rtm_type) {
642                 case RTM_NEWADDR:
643                 case RTM_GETADDR:
644                 case RTM_DELADDR:
645                         switch (type) {
646                                 case IFA_ADDRESS:
647                                 case IFA_LOCAL:
648                                 case IFA_BROADCAST:
649                                 case IFA_ANYCAST:
650                                         ifa = NLMSG_DATA(m->hdr);
651
652                                         if (ifa->ifa_family != AF_INET6)
653                                                 return -EINVAL;
654
655                                         break;
656                                 default:
657                                         return -ENOTSUP;
658                         }
659                         break;
660                 case RTM_NEWROUTE:
661                 case RTM_GETROUTE:
662                 case RTM_DELROUTE:
663                         switch (type) {
664                                 case RTA_DST:
665                                 case RTA_SRC:
666                                 case RTA_GATEWAY:
667                                         rtm = NLMSG_DATA(m->hdr);
668
669                                         if (rtm->rtm_family != AF_INET6)
670                                                 return -EINVAL;
671
672                                         break;
673                                 default:
674                                         return -ENOTSUP;
675                         }
676                 default:
677                         return -ENOTSUP;
678         }
679
680         r = add_rtattr(m, type, data, sizeof(struct in6_addr));
681         if (r < 0)
682                 return r;
683
684         return 0;
685 }
686
687 int sd_rtnl_message_append_ether_addr(sd_rtnl_message *m, unsigned short type, const struct ether_addr *data) {
688         uint16_t rtm_type;
689         int r;
690
691         assert_return(m, -EINVAL);
692         assert_return(!m->sealed, -EPERM);
693         assert_return(data, -EINVAL);
694
695         sd_rtnl_message_get_type(m, &rtm_type);
696
697         switch (rtm_type) {
698                 case RTM_NEWLINK:
699                 case RTM_SETLINK:
700                 case RTM_DELLINK:
701                 case RTM_GETLINK:
702                         switch (type) {
703                                 case IFLA_ADDRESS:
704                                 case IFLA_BROADCAST:
705                                         break;
706                                 default:
707                                         return -ENOTSUP;
708                         }
709                         break;
710                 default:
711                         return -ENOTSUP;
712         }
713
714         r = add_rtattr(m, type, data, ETH_ALEN);
715         if (r < 0)
716                 return r;
717
718         return 0;
719 }
720
721 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
722         uint16_t rtm_type;
723
724         assert_return(m, -EINVAL);
725         assert_return(!m->sealed, -EPERM);
726
727         sd_rtnl_message_get_type(m, &rtm_type);
728
729         if (message_type_is_link(rtm_type)) {
730                 if ((type == IFLA_LINKINFO && m->n_containers == 0) ||
731                     (type == IFLA_INFO_DATA && m->n_containers == 1 &&
732                      GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO))
733                         return add_rtattr(m, type, NULL, 0);
734                 else
735                         return -ENOTSUP;
736         } else
737                 return -ENOTSUP;
738
739         return 0;
740 }
741
742 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
743         assert_return(m, -EINVAL);
744         assert_return(!m->sealed, -EPERM);
745         assert_return(m->n_containers > 0, -EINVAL);
746
747         m->n_containers --;
748
749         return 0;
750 }
751
752 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
753         size_t remaining_size;
754         uint16_t rtm_type;
755         int r;
756
757         assert_return(m, -EINVAL);
758         assert_return(m->sealed, -EPERM);
759         assert_return(m->next_rta_offset, -EINVAL);
760         assert_return(type, -EINVAL);
761         assert_return(data, -EINVAL);
762
763         /* only read until the end of the current container */
764         if (m->n_containers)
765                 remaining_size = GET_CONTAINER(m, m->n_containers - 1)->rta_len -
766                                  (m->next_rta_offset -
767                                   m->container_offsets[m->n_containers - 1]);
768         else
769                 remaining_size = m->hdr->nlmsg_len - m->next_rta_offset;
770
771         if (!RTA_OK(NEXT_RTA(m), remaining_size))
772                 return 0;
773
774         /* if we read a container, enter it and return its type */
775         r = sd_rtnl_message_get_type(m, &rtm_type);
776         if (r < 0)
777                 return r;
778
779         *type = NEXT_RTA(m)->rta_type;
780
781         if (message_type_is_link(rtm_type) &&
782             ((m->n_containers == 0 &&
783               NEXT_RTA(m)->rta_type == IFLA_LINKINFO) ||
784              (m->n_containers == 1 &&
785               GET_CONTAINER(m, 0)->rta_type == IFLA_LINKINFO &&
786               NEXT_RTA(m)->rta_type == IFLA_INFO_DATA))) {
787                 *data = NULL;
788                 PUSH_CONTAINER(m, NEXT_RTA(m));
789                 UPDATE_RTA(m, RTA_DATA(NEXT_RTA(m)));
790         } else {
791                 *data = RTA_DATA(NEXT_RTA(m));
792                 UPDATE_RTA(m, RTA_NEXT(NEXT_RTA(m), remaining_size));
793         }
794
795         return 1;
796 }
797
798 int sd_rtnl_message_exit_container(sd_rtnl_message *m) {
799         assert_return(m, -EINVAL);
800         assert_return(m->sealed, -EINVAL);
801         assert_return(m->n_containers > 0, -EINVAL);
802
803         m->n_containers --;
804
805         return 0;
806 }
807
808 uint32_t message_get_serial(sd_rtnl_message *m) {
809         assert(m);
810         assert(m->hdr);
811
812         return m->hdr->nlmsg_seq;
813 }
814
815 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
816         struct nlmsgerr *err;
817
818         assert_return(m, -EINVAL);
819         assert_return(m->hdr, -EINVAL);
820
821         if (m->hdr->nlmsg_type != NLMSG_ERROR)
822                 return 0;
823
824         err = NLMSG_DATA(m->hdr);
825
826         return err->error;
827 }
828
829 int message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
830         int r;
831
832         assert(m);
833         assert(m->hdr);
834
835         if (m->sealed)
836                 return -EPERM;
837
838         if (nl)
839                 m->hdr->nlmsg_seq = nl->serial++;
840
841         m->sealed = true;
842
843         r = sd_rtnl_message_rewind(m);
844         if (r < 0)
845                 return r;
846
847         return 0;
848 }
849
850 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
851         assert(rtnl);
852         assert(need);
853
854         /* ioctl(rtnl->fd, FIONREAD, &need)
855            Does not appear to work on netlink sockets. libnl uses
856            MSG_PEEK instead. I don't know if that is worth the
857            extra roundtrip.
858
859            For now we simply use the maximum message size the kernel
860            may use (NLMSG_GOODSIZE), and then realloc to the actual
861            size after reading the message (hence avoiding huge memory
862            usage in case many small messages are kept around) */
863         *need = page_size();
864         if (*need > 8192UL)
865                 *need = 8192UL;
866
867         return 0;
868 }
869
870 /* returns the number of bytes sent, or a negative error code */
871 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
872         union {
873                 struct sockaddr sa;
874                 struct sockaddr_nl nl;
875         } addr = {
876                 .nl.nl_family = AF_NETLINK,
877         };
878         ssize_t k;
879
880         assert(nl);
881         assert(m);
882         assert(m->hdr);
883
884         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
885                         0, &addr.sa, sizeof(addr));
886         if (k < 0)
887                 return (errno == EAGAIN) ? 0 : -errno;
888
889         return k;
890 }
891
892 /* On success, the number of bytes received is returned and *ret points to the received message
893  * which has a valid header and the correct size.
894  * If nothing useful was received 0 is returned.
895  * On failure, a negative error code is returned.
896  */
897 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
898         sd_rtnl_message *m;
899         union {
900                 struct sockaddr sa;
901                 struct sockaddr_nl nl;
902         } addr;
903         socklen_t addr_len;
904         int r;
905         ssize_t k;
906         size_t need;
907
908         assert(nl);
909         assert(ret);
910
911         r = message_receive_need(nl, &need);
912         if (r < 0)
913                 return r;
914
915         r = message_new(&m, need);
916         if (r < 0)
917                 return r;
918
919         /* don't allow sealing/appending to received messages */
920         m->sealed = true;
921
922         addr_len = sizeof(addr);
923
924         k = recvfrom(nl->fd, m->hdr, need,
925                         0, &addr.sa, &addr_len);
926         if (k < 0)
927                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
928         else if (k == 0)
929                 k = -ECONNRESET; /* connection was closed by the kernel */
930         else if (addr_len != sizeof(addr.nl) ||
931                         addr.nl.nl_family != AF_NETLINK)
932                 k = -EIO; /* not a netlink message */
933         else if (addr.nl.nl_pid != 0)
934                 k = 0; /* not from the kernel */
935         else if ((size_t) k < sizeof(struct nlmsghdr) ||
936                         (size_t) k < m->hdr->nlmsg_len)
937                 k = -EIO; /* too small (we do accept too big though) */
938         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
939                 k = 0; /* not broadcast and not for us */
940
941         if (k > 0)
942                 switch (m->hdr->nlmsg_type) {
943                         struct ifinfomsg *ifi;
944                         struct ifaddrmsg *ifa;
945                         struct rtmsg *rtm;
946
947                         /* check that the size matches the message type */
948                         case NLMSG_ERROR:
949                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
950                                         k = -EIO;
951                                 break;
952                         case RTM_NEWLINK:
953                         case RTM_SETLINK:
954                         case RTM_DELLINK:
955                         case RTM_GETLINK:
956                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
957                                         k = -EIO;
958                                 else {
959                                         ifi = NLMSG_DATA(m->hdr);
960                                         UPDATE_RTA(m, IFLA_RTA(ifi));
961                                 }
962                                 break;
963                         case RTM_NEWADDR:
964                         case RTM_DELADDR:
965                         case RTM_GETADDR:
966                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
967                                         k = -EIO;
968                                 else {
969                                         ifa = NLMSG_DATA(m->hdr);
970                                         UPDATE_RTA(m, IFA_RTA(ifa));
971                                 }
972                                 break;
973                         case RTM_NEWROUTE:
974                         case RTM_DELROUTE:
975                         case RTM_GETROUTE:
976                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtmsg)))
977                                         k = -EIO;
978                                 else {
979                                         rtm = NLMSG_DATA(m->hdr);
980                                         UPDATE_RTA(m, RTM_RTA(rtm));
981                                 }
982                                 break;
983                         case NLMSG_NOOP:
984                                 k = 0;
985                                 break;
986                         default:
987                                 k = 0; /* ignoring message of unknown type */
988                 }
989
990         if (k <= 0)
991                 sd_rtnl_message_unref(m);
992         else {
993                 /* we probably allocated way too much memory, give it back */
994                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
995                 *ret = m;
996         }
997
998         return k;
999 }
1000
1001 int sd_rtnl_message_rewind(sd_rtnl_message *m) {
1002         struct ifinfomsg *ifi;
1003         struct ifaddrmsg *ifa;
1004         struct rtmsg *rtm;
1005
1006         assert_return(m, -EINVAL);
1007         assert_return(m->sealed, -EPERM);
1008         assert_return(m->hdr, -EINVAL);
1009
1010         switch(m->hdr->nlmsg_type) {
1011                 case RTM_NEWLINK:
1012                 case RTM_SETLINK:
1013                 case RTM_GETLINK:
1014                 case RTM_DELLINK:
1015                         ifi = NLMSG_DATA(m->hdr);
1016                         UPDATE_RTA(m, IFLA_RTA(ifi));
1017
1018                         break;
1019                 case RTM_NEWADDR:
1020                 case RTM_GETADDR:
1021                 case RTM_DELADDR:
1022                         ifa = NLMSG_DATA(m->hdr);
1023                         UPDATE_RTA(m, IFA_RTA(ifa));
1024
1025                         break;
1026                 case RTM_NEWROUTE:
1027                 case RTM_GETROUTE:
1028                 case RTM_DELROUTE:
1029                         rtm = NLMSG_DATA(m->hdr);
1030                         UPDATE_RTA(m, RTM_RTA(rtm));
1031
1032                         break;
1033                 default:
1034                         return -ENOTSUP;
1035         }
1036
1037         m->n_containers = 0;
1038
1039         return 0;
1040 }