chiark / gitweb /
dhcp: Add function to free DHCP client data
[elogind.git] / src / libsystemd-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
39         struct rtattr *current_container;
40
41         struct rtattr *next_rta;
42         size_t remaining_size;
43
44         bool sealed:1;
45 };
46
47 static int message_new(sd_rtnl_message **ret, size_t initial_size) {
48         sd_rtnl_message *m;
49
50         assert_return(ret, -EINVAL);
51         assert_return(initial_size >= sizeof(struct nlmsghdr), -EINVAL);
52
53         m = new0(sd_rtnl_message, 1);
54         if (!m)
55                 return -ENOMEM;
56
57         m->hdr = malloc0(initial_size);
58         if (!m->hdr) {
59                 free(m);
60                 return -ENOMEM;
61         }
62
63         m->n_ref = REFCNT_INIT;
64
65         m->hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
66         m->sealed = false;
67
68         *ret = m;
69
70         return 0;
71 }
72
73 int message_new_synthetic_error(int error, uint32_t serial, sd_rtnl_message **ret) {
74         struct nlmsgerr *err;
75         int r;
76
77         assert(error <= 0);
78
79         r = message_new(ret, NLMSG_SPACE(sizeof(struct nlmsgerr)));
80         if (r < 0)
81                 return r;
82
83         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct nlmsgerr));
84         (*ret)->hdr->nlmsg_type = NLMSG_ERROR;
85         (*ret)->hdr->nlmsg_seq = serial;
86
87         err = NLMSG_DATA((*ret)->hdr);
88
89         err->error = error;
90
91         return 0;
92 }
93
94 int sd_rtnl_message_route_new(uint16_t nlmsg_type, unsigned char rtm_family,
95                               unsigned char rtm_dst_len, unsigned char rtm_src_len,
96                               unsigned char rtm_tos, unsigned char rtm_table,
97                               unsigned char rtm_scope, unsigned char rtm_protocol,
98                               unsigned char rtm_type, unsigned rtm_flags, sd_rtnl_message **ret) {
99         struct rtmsg *rtm;
100         int r;
101
102         assert_return(nlmsg_type == RTM_NEWROUTE || nlmsg_type == RTM_DELROUTE ||
103                       nlmsg_type == RTM_GETROUTE, -EINVAL);
104         assert_return(ret, -EINVAL);
105
106         r = message_new(ret, NLMSG_SPACE(sizeof(struct rtmsg)));
107         if (r < 0)
108                 return r;
109
110         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
111         (*ret)->hdr->nlmsg_type = nlmsg_type;
112         if (nlmsg_type == RTM_NEWROUTE)
113                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
114
115         rtm = NLMSG_DATA((*ret)->hdr);
116
117         rtm->rtm_family = rtm_family;
118         rtm->rtm_dst_len = rtm_dst_len;
119         rtm->rtm_src_len = rtm_src_len;
120         rtm->rtm_tos = rtm_tos;
121         rtm->rtm_table = rtm_table;
122         rtm->rtm_protocol = rtm_protocol;
123         rtm->rtm_scope = rtm_scope;
124         rtm->rtm_type = rtm_type;
125         rtm->rtm_flags = rtm_flags;
126
127         return 0;
128 }
129
130 int sd_rtnl_message_link_new(uint16_t nlmsg_type, int index, unsigned type, unsigned flags, sd_rtnl_message **ret) {
131         struct ifinfomsg *ifi;
132         int r;
133
134         assert_return(nlmsg_type == RTM_NEWLINK || nlmsg_type == RTM_DELLINK ||
135                       nlmsg_type == RTM_SETLINK || nlmsg_type == RTM_GETLINK, -EINVAL);
136         assert_return(nlmsg_type == RTM_NEWLINK || index > 0, -EINVAL);
137         assert_return(ret, -EINVAL);
138
139         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifinfomsg)));
140         if (r < 0)
141                 return r;
142
143         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
144         (*ret)->hdr->nlmsg_type = nlmsg_type;
145         if (nlmsg_type == RTM_NEWLINK)
146                 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE;
147
148         ifi = NLMSG_DATA((*ret)->hdr);
149
150         ifi->ifi_family = AF_UNSPEC;
151         ifi->ifi_index = index;
152         ifi->ifi_type = type;
153         ifi->ifi_flags = flags;
154         ifi->ifi_change = 0xffffffff;
155
156         return 0;
157 }
158
159 int sd_rtnl_message_addr_new(uint16_t nlmsg_type, int index, unsigned char family, unsigned char prefixlen, unsigned char flags, unsigned char scope, sd_rtnl_message **ret) {
160         struct ifaddrmsg *ifa;
161         int r;
162
163         assert_return(nlmsg_type == RTM_NEWADDR || nlmsg_type == RTM_DELADDR || nlmsg_type == RTM_GETADDR, -EINVAL);
164         assert_return(index > 0, -EINVAL);
165         assert_return(ret, -EINVAL);
166
167         r = message_new(ret, NLMSG_SPACE(sizeof(struct ifaddrmsg)));
168         if (r < 0)
169                 return r;
170
171         (*ret)->hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
172         (*ret)->hdr->nlmsg_type = nlmsg_type;
173
174         ifa = NLMSG_DATA((*ret)->hdr);
175
176         ifa->ifa_family = family;
177         ifa->ifa_prefixlen = prefixlen;
178         ifa->ifa_flags = flags;
179         ifa->ifa_scope = scope;
180         ifa->ifa_index = index;
181
182         return 0;
183 }
184
185 sd_rtnl_message *sd_rtnl_message_ref(sd_rtnl_message *m) {
186         if (m)
187                 assert_se(REFCNT_INC(m->n_ref) >= 2);
188
189         return m;
190 }
191
192 sd_rtnl_message *sd_rtnl_message_unref(sd_rtnl_message *m) {
193         if (m && REFCNT_DEC(m->n_ref) <= 0) {
194                 free(m->hdr);
195                 free(m);
196         }
197
198         return NULL;
199 }
200
201 int sd_rtnl_message_get_type(sd_rtnl_message *m, uint16_t *type) {
202         assert_return(m, -EINVAL);
203         assert_return(type, -EINVAL);
204
205         *type = m->hdr->nlmsg_type;
206
207         return 0;
208 }
209
210 int sd_rtnl_message_link_get_ifindex(sd_rtnl_message *m, int *ifindex) {
211         struct ifinfomsg *ifi;
212
213         assert_return(m, -EINVAL);
214         assert_return(ifindex, -EINVAL);
215         assert_return(m->hdr->nlmsg_type == RTM_NEWLINK || m->hdr->nlmsg_type == RTM_DELLINK ||
216                       m->hdr->nlmsg_type == RTM_GETLINK || m->hdr->nlmsg_type == RTM_SETLINK, -EINVAL);
217
218         ifi = NLMSG_DATA(m->hdr);
219
220         *ifindex = ifi->ifi_index;
221
222         return 0;
223 }
224
225 int sd_rtnl_message_link_get_flags(sd_rtnl_message *m, unsigned *flags) {
226         struct ifinfomsg *ifi;
227
228         assert_return(m, -EINVAL);
229         assert_return(flags, -EINVAL);
230         assert_return(m->hdr->nlmsg_type == RTM_NEWLINK || m->hdr->nlmsg_type == RTM_DELLINK ||
231                       m->hdr->nlmsg_type == RTM_GETLINK || m->hdr->nlmsg_type == RTM_SETLINK, -EINVAL);
232
233         ifi = NLMSG_DATA(m->hdr);
234
235         *flags = ifi->ifi_flags;
236
237         return 0;
238 }
239
240 /* If successful the updated message will be correctly aligned, if unsuccessful the old message is
241    untouched */
242 static int add_rtattr(sd_rtnl_message *m, unsigned short type, const void *data, size_t data_length) {
243         uint32_t rta_length, message_length;
244         struct nlmsghdr *new_hdr;
245         struct rtattr *rta;
246         char *padding;
247
248         assert(m);
249         assert(m->hdr);
250         assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len);
251         assert(!data || data_length > 0);
252
253         /* get the size of the new rta attribute (with padding at the end) */
254         rta_length = RTA_LENGTH(data_length);
255         /* get the new message size (with padding at the end)
256          */
257         message_length = m->hdr->nlmsg_len + RTA_ALIGN(rta_length);
258
259         /* realloc to fit the new attribute */
260         new_hdr = realloc(m->hdr, message_length);
261         if (!new_hdr)
262                 return -ENOMEM;
263         m->hdr = new_hdr;
264
265         /* get pointer to the attribute we are about to add */
266         rta = (struct rtattr *) ((uint8_t *) m->hdr + m->hdr->nlmsg_len);
267         /* update message size */
268         m->hdr->nlmsg_len = message_length;
269
270         /* we are inside a container, extend it */
271         if (m->current_container)
272                 m->current_container->rta_len = (unsigned char *) m->hdr +
273                                                 m->hdr->nlmsg_len -
274                                                 (unsigned char *) m->current_container;
275
276         /* fill in the attribute */
277         rta->rta_type = type;
278         rta->rta_len = rta_length;
279         if (!data) {
280                 /* this is a container, set pointer */
281                 m->current_container = rta;
282         } else {
283                 /* we don't deal with the case where the user lies about the type
284                  * and gives us too little data (so don't do that)
285                 */
286                 padding = mempcpy(RTA_DATA(rta), data, data_length);
287                 /* make sure also the padding at the end of the message is initialized */
288                 memset(padding, '\0', (unsigned char *) m->hdr +
289                                       m->hdr->nlmsg_len -
290                                       (unsigned char *) padding);
291         }
292
293         return 0;
294 }
295
296 int sd_rtnl_message_append(sd_rtnl_message *m, unsigned short type, const void *data) {
297         uint16_t rtm_type;
298         struct ifaddrmsg *ifa;
299         struct rtmsg *rtm;
300
301         assert_return(m, -EINVAL);
302         assert_return(data, -EINVAL);
303
304         sd_rtnl_message_get_type(m, &rtm_type);
305
306         if (m->current_container) {
307                 switch (rtm_type) {
308                         case RTM_NEWLINK:
309                         case RTM_SETLINK:
310                         case RTM_GETLINK:
311                         case RTM_DELLINK:
312                                 switch (m->current_container->rta_type) {
313                                         case IFLA_LINKINFO:
314                                                 switch (type) {
315                                                         case IFLA_INFO_KIND:
316                                                                 return add_rtattr(m, type, data, strlen(data) + 1);
317                                                         default:
318                                                                 return -ENOTSUP;
319                                                 }
320                                         default:
321                                                 return -ENOTSUP;
322                                 }
323                         default:
324                                 return -ENOTSUP;
325                 }
326         }
327
328         switch (rtm_type) {
329                 case RTM_NEWLINK:
330                 case RTM_SETLINK:
331                 case RTM_DELLINK:
332                 case RTM_GETLINK:
333                         switch (type) {
334                                 case IFLA_IFNAME:
335                                 case IFLA_IFALIAS:
336                                 case IFLA_QDISC:
337                                         return add_rtattr(m, type, data, strlen(data) + 1);
338                                 case IFLA_MASTER:
339                                 case IFLA_MTU:
340                                 case IFLA_LINK:
341                                         return add_rtattr(m, type, data, sizeof(uint32_t));
342                                 case IFLA_STATS:
343                                         return add_rtattr(m, type, data, sizeof(struct rtnl_link_stats));
344                                 case IFLA_ADDRESS:
345                                 case IFLA_BROADCAST:
346                                         return add_rtattr(m, type, data, ETH_ALEN);
347                                 default:
348                                         return -ENOTSUP;
349                         }
350                 case RTM_NEWADDR:
351                 case RTM_DELADDR:
352                 case RTM_GETADDR:
353                         switch (type) {
354                                 case IFA_LABEL:
355                                         return add_rtattr(m, type, data, strlen(data) + 1);
356                                 case IFA_ADDRESS:
357                                 case IFA_LOCAL:
358                                 case IFA_BROADCAST:
359                                 case IFA_ANYCAST:
360                                         ifa = NLMSG_DATA(m->hdr);
361                                         switch (ifa->ifa_family) {
362                                                 case AF_INET:
363                                                         return add_rtattr(m, type, data, sizeof(struct in_addr));
364                                                 case AF_INET6:
365                                                         return add_rtattr(m, type, data, sizeof(struct in6_addr));
366                                                 default:
367                                                         return -EINVAL;
368                                         }
369                                 default:
370                                         return -ENOTSUP;
371                         }
372                 case RTM_NEWROUTE:
373                 case RTM_DELROUTE:
374                 case RTM_GETROUTE:
375                         switch (type) {
376                                 case RTA_DST:
377                                 case RTA_SRC:
378                                 case RTA_GATEWAY:
379                                         rtm = NLMSG_DATA(m->hdr);
380                                         switch (rtm->rtm_family) {
381                                                 case AF_INET:
382                                                         return add_rtattr(m, type, data, sizeof(struct in_addr));
383                                                 case AF_INET6:
384                                                         return add_rtattr(m, type, data, sizeof(struct in6_addr));
385                                                 default:
386                                                         return -EINVAL;
387                                         }
388                                 case RTA_TABLE:
389                                 case RTA_PRIORITY:
390                                 case RTA_IIF:
391                                 case RTA_OIF:
392                                         return add_rtattr(m, type, data, sizeof(uint32_t));
393                                 default:
394                                         return -ENOTSUP;
395                         }
396                 default:
397                         return -ENOTSUP;
398         }
399 }
400
401 int sd_rtnl_message_open_container(sd_rtnl_message *m, unsigned short type) {
402         uint16_t rtm_type;
403
404         assert_return(m, -EINVAL);
405         assert_return(!m->current_container, -EINVAL);
406
407         sd_rtnl_message_get_type(m, &rtm_type);
408
409         switch (rtm_type) {
410                 case RTM_NEWLINK:
411                 case RTM_SETLINK:
412                 case RTM_GETLINK:
413                 case RTM_DELLINK:
414                         if (type == IFLA_LINKINFO)
415                                 return add_rtattr(m, type, NULL, 0);
416                         else
417                                 return -ENOTSUP;
418                 default:
419                         return -ENOTSUP;
420         }
421
422         return 0;
423 }
424
425 int sd_rtnl_message_close_container(sd_rtnl_message *m) {
426         assert_return(m, -EINVAL);
427         assert_return(m->current_container, -EINVAL);
428
429         m->current_container = NULL;
430
431         return 0;
432 }
433
434 static int message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
435         uint16_t rtm_type;
436         int r;
437
438         assert(m);
439         assert(m->next_rta);
440         assert(type);
441         assert(data);
442
443         if (!RTA_OK(m->next_rta, m->remaining_size))
444                 return 0;
445
446         /* make sure we don't try to read a container
447          * TODO: add support for entering containers for reading */
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_GETLINK:
455                 case RTM_SETLINK:
456                 case RTM_DELLINK:
457                         if (m->next_rta->rta_type == IFLA_LINKINFO) {
458                                 return -EINVAL;
459                         }
460         }
461
462         *data = RTA_DATA(m->next_rta);
463         *type = m->next_rta->rta_type;
464
465         m->next_rta = RTA_NEXT(m->next_rta, m->remaining_size);
466
467         return 1;
468 }
469
470 int sd_rtnl_message_read(sd_rtnl_message *m, unsigned short *type, void **data) {
471         uint16_t rtm_type;
472         int r;
473
474         assert_return(m, -EINVAL);
475         assert_return(data, -EINVAL);
476
477         r = sd_rtnl_message_get_type(m, &rtm_type);
478         if (r < 0)
479                 return r;
480
481         switch (rtm_type) {
482                 case RTM_NEWLINK:
483                 case RTM_SETLINK:
484                 case RTM_DELLINK:
485                 case RTM_GETLINK:
486                         if (!m->next_rta) {
487                                 struct ifinfomsg *ifi = NLMSG_DATA(m->hdr);
488
489                                 m->next_rta = IFLA_RTA(ifi);
490                                 m->remaining_size = IFLA_PAYLOAD(m->hdr);
491                         }
492                         break;
493                 case RTM_NEWADDR:
494                 case RTM_DELADDR:
495                 case RTM_GETADDR:
496                         if (!m->next_rta) {
497                                 struct ifaddrmsg *ifa = NLMSG_DATA(m->hdr);
498
499                                 m->next_rta = IFA_RTA(ifa);
500                                 m->remaining_size = IFA_PAYLOAD(m->hdr);
501                         }
502                         break;
503                 case RTM_NEWROUTE:
504                 case RTM_DELROUTE:
505                 case RTM_GETROUTE:
506                         if (!m->next_rta) {
507                                 struct rtmesg *rtm = NLMSG_DATA(m->hdr);
508
509                                 m->next_rta = RTM_RTA(rtm);
510                                 m->remaining_size = RTM_PAYLOAD(m->hdr);
511                         }
512                         break;
513                 default:
514                         return -ENOTSUP;
515         }
516
517         return message_read(m, type, data);
518 }
519
520 uint32_t message_get_serial(sd_rtnl_message *m) {
521         assert(m);
522
523         return m->hdr->nlmsg_seq;
524 }
525
526 int sd_rtnl_message_get_errno(sd_rtnl_message *m) {
527         struct nlmsgerr *err;
528
529         assert_return(m, -EINVAL);
530
531         if (m->hdr->nlmsg_type != NLMSG_ERROR)
532                 return 0;
533
534         err = NLMSG_DATA(m->hdr);
535
536         return err->error;
537 }
538
539 int message_seal(sd_rtnl *nl, sd_rtnl_message *m) {
540         if (m->sealed)
541                 return -EPERM;
542
543         m->hdr->nlmsg_seq = nl->serial++;
544         m->sealed = true;
545
546         return 0;
547 }
548
549 static int message_receive_need(sd_rtnl *rtnl, size_t *need) {
550         assert_return(rtnl, -EINVAL);
551         assert_return(need, -EINVAL);
552
553         /* ioctl(rtnl->fd, FIONREAD, &need)
554            Does not appear to work on netlink sockets. libnl uses
555            MSG_PEEK instead. I don't know if that is worth the
556            extra roundtrip.
557
558            For now we simply use the maximum message size the kernel
559            may use (NLMSG_GOODSIZE), and then realloc to the actual
560            size after reading the message (hence avoiding huge memory
561            usage in case many small messages are kept around) */
562         *need = page_size();
563         if (*need > 8192UL)
564                 *need = 8192UL;
565
566         return 0;
567 }
568
569 /* returns the number of bytes sent, or a negative error code */
570 int socket_write_message(sd_rtnl *nl, sd_rtnl_message *m) {
571         union {
572                 struct sockaddr sa;
573                 struct sockaddr_nl nl;
574         } addr = {
575                 .nl.nl_family = AF_NETLINK,
576         };
577         ssize_t k;
578
579         assert_return(nl, -EINVAL);
580         assert_return(m, -EINVAL);
581
582         k = sendto(nl->fd, m->hdr, m->hdr->nlmsg_len,
583                         0, &addr.sa, sizeof(addr));
584         if (k < 0)
585                 return (errno == EAGAIN) ? 0 : -errno;
586
587         return k;
588 }
589
590 /* On success, the number of bytes received is returned and *ret points to the received message
591  * which has a valid header and the correct size.
592  * If nothing useful was received 0 is returned.
593  * On failure, a negative error code is returned.
594  */
595 int socket_read_message(sd_rtnl *nl, sd_rtnl_message **ret) {
596         sd_rtnl_message *m;
597         union {
598                 struct sockaddr sa;
599                 struct sockaddr_nl nl;
600         } addr;
601         socklen_t addr_len;
602         int r;
603         ssize_t k;
604         size_t need;
605
606         assert_return(nl, -EINVAL);
607         assert_return(ret, -EINVAL);
608
609         r = message_receive_need(nl, &need);
610         if (r < 0)
611                 return r;
612
613         r = message_new(&m, need);
614         if (r < 0)
615                 return r;
616
617         addr_len = sizeof(addr);
618
619         k = recvfrom(nl->fd, m->hdr, need,
620                         0, &addr.sa, &addr_len);
621         if (k < 0)
622                 k = (errno == EAGAIN) ? 0 : -errno; /* no data */
623         else if (k == 0)
624                 k = -ECONNRESET; /* connection was closed by the kernel */
625         else if (addr_len != sizeof(addr.nl) ||
626                         addr.nl.nl_family != AF_NETLINK)
627                 k = -EIO; /* not a netlink message */
628         else if (addr.nl.nl_pid != 0)
629                 k = 0; /* not from the kernel */
630         else if ((size_t) k < sizeof(struct nlmsghdr) ||
631                         (size_t) k < m->hdr->nlmsg_len)
632                 k = -EIO; /* too small (we do accept too big though) */
633         else if (m->hdr->nlmsg_pid && m->hdr->nlmsg_pid != nl->sockaddr.nl.nl_pid)
634                 k = 0; /* not broadcast and not for us */
635
636         if (k > 0)
637                 switch (m->hdr->nlmsg_type) {
638                         /* check that the size matches the message type */
639                         case NLMSG_ERROR:
640                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
641                                         k = -EIO;
642                                 break;
643                         case RTM_NEWLINK:
644                         case RTM_SETLINK:
645                         case RTM_DELLINK:
646                         case RTM_GETLINK:
647                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifinfomsg)))
648                                         k = -EIO;
649                                 break;
650                         case RTM_NEWADDR:
651                         case RTM_DELADDR:
652                         case RTM_GETADDR:
653                                 if (m->hdr->nlmsg_len < NLMSG_LENGTH(sizeof(struct ifaddrmsg)))
654                                         k = -EIO;
655                                 break;
656                         case NLMSG_NOOP:
657                                 k = 0;
658                                 break;
659                         default:
660                                 k = 0; /* ignoring message of unknown type */
661                 }
662
663         if (k <= 0)
664                 sd_rtnl_message_unref(m);
665         else {
666                 /* we probably allocated way too much memory, give it back */
667                 m->hdr = realloc(m->hdr, m->hdr->nlmsg_len);
668                 *ret = m;
669         }
670
671         return k;
672 }