]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/rtnl-message.c
Merge pull request #1880 from fsateler/sysctl-doc
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / 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 <stdbool.h>
24 #include <unistd.h>
25
26 #include "sd-netlink.h"
27
28 #include "formats-util.h"
29 #include "missing.h"
30 #include "netlink-internal.h"
31 #include "netlink-types.h"
32 #include "netlink-util.h"
33 #include "refcnt.h"
34 #include "socket-util.h"
35 #include "util.h"
36
37 int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
38 struct rtmsg *rtm;
39
40 assert_return(m, -EINVAL);
41 assert_return(m->hdr, -EINVAL);
42 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
43
44 rtm = NLMSG_DATA(m->hdr);
45
46 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
47 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
48 return -ERANGE;
49
50 rtm->rtm_dst_len = prefixlen;
51
52 return 0;
53 }
54
55 int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
56 struct rtmsg *rtm;
57
58 assert_return(m, -EINVAL);
59 assert_return(m->hdr, -EINVAL);
60 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
61
62 rtm = NLMSG_DATA(m->hdr);
63
64 if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
65 (rtm->rtm_family == AF_INET6 && prefixlen > 128))
66 return -ERANGE;
67
68 rtm->rtm_src_len = prefixlen;
69
70 return 0;
71 }
72
73 int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) {
74 struct rtmsg *rtm;
75
76 assert_return(m, -EINVAL);
77 assert_return(m->hdr, -EINVAL);
78 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
79
80 rtm = NLMSG_DATA(m->hdr);
81
82 rtm->rtm_scope = scope;
83
84 return 0;
85 }
86
87 int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) {
88 struct rtmsg *rtm;
89
90 assert_return(m, -EINVAL);
91 assert_return(m->hdr, -EINVAL);
92 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
93
94 rtm = NLMSG_DATA(m->hdr);
95
96 rtm->rtm_flags = flags;
97
98 return 0;
99 }
100
101 int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) {
102 struct rtmsg *rtm;
103
104 assert_return(m, -EINVAL);
105 assert_return(m->hdr, -EINVAL);
106 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
107 assert_return(flags, -EINVAL);
108
109 rtm = NLMSG_DATA(m->hdr);
110
111 *flags = rtm->rtm_flags;
112
113 return 0;
114 }
115
116 int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
117 struct rtmsg *rtm;
118
119 assert_return(m, -EINVAL);
120 assert_return(m->hdr, -EINVAL);
121 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
122 assert_return(family, -EINVAL);
123
124 rtm = NLMSG_DATA(m->hdr);
125
126 *family = rtm->rtm_family;
127
128 return 0;
129 }
130
131 int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
132 struct rtmsg *rtm;
133
134 assert_return(m, -EINVAL);
135 assert_return(m->hdr, -EINVAL);
136 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
137 assert_return(protocol, -EINVAL);
138
139 rtm = NLMSG_DATA(m->hdr);
140
141 *protocol = rtm->rtm_protocol;
142
143 return 0;
144 }
145
146 int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) {
147 struct rtmsg *rtm;
148
149 assert_return(m, -EINVAL);
150 assert_return(m->hdr, -EINVAL);
151 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
152 assert_return(scope, -EINVAL);
153
154 rtm = NLMSG_DATA(m->hdr);
155
156 *scope = rtm->rtm_scope;
157
158 return 0;
159 }
160
161 int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos) {
162 struct rtmsg *rtm;
163
164 assert_return(m, -EINVAL);
165 assert_return(m->hdr, -EINVAL);
166 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
167 assert_return(tos, -EINVAL);
168
169 rtm = NLMSG_DATA(m->hdr);
170
171 *tos = rtm->rtm_tos;
172
173 return 0;
174 }
175
176 int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) {
177 struct rtmsg *rtm;
178
179 assert_return(m, -EINVAL);
180 assert_return(m->hdr, -EINVAL);
181 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
182 assert_return(table, -EINVAL);
183
184 rtm = NLMSG_DATA(m->hdr);
185
186 *table = rtm->rtm_table;
187
188 return 0;
189 }
190
191 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) {
192 struct rtmsg *rtm;
193
194 assert_return(m, -EINVAL);
195 assert_return(m->hdr, -EINVAL);
196 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
197 assert_return(dst_len, -EINVAL);
198
199 rtm = NLMSG_DATA(m->hdr);
200
201 *dst_len = rtm->rtm_dst_len;
202
203 return 0;
204 }
205
206 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len) {
207 struct rtmsg *rtm;
208
209 assert_return(m, -EINVAL);
210 assert_return(m->hdr, -EINVAL);
211 assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
212 assert_return(src_len, -EINVAL);
213
214 rtm = NLMSG_DATA(m->hdr);
215
216 *src_len = rtm->rtm_src_len;
217
218 return 0;
219 }
220
221 int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret,
222 uint16_t nlmsg_type, int rtm_family,
223 unsigned char rtm_protocol) {
224 struct rtmsg *rtm;
225 int r;
226
227 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
228 assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
229 rtm_family == AF_INET || rtm_family == AF_INET6, -EINVAL);
230 assert_return(ret, -EINVAL);
231
232 r = message_new(rtnl, ret, nlmsg_type);
233 if (r < 0)
234 return r;
235
236 if (nlmsg_type == RTM_NEWROUTE)
237 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
238
239 rtm = NLMSG_DATA((*ret)->hdr);
240
241 rtm->rtm_family = rtm_family;
242 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
243 rtm->rtm_type = RTN_UNICAST;
244 rtm->rtm_table = RT_TABLE_MAIN;
245 rtm->rtm_protocol = rtm_protocol;
246
247 return 0;
248 }
249
250 int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) {
251 struct ndmsg *ndm;
252
253 assert_return(m, -EINVAL);
254 assert_return(m->hdr, -EINVAL);
255 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
256
257 ndm = NLMSG_DATA(m->hdr);
258 ndm->ndm_flags |= flags;
259
260 return 0;
261 }
262
263 int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) {
264 struct ndmsg *ndm;
265
266 assert_return(m, -EINVAL);
267 assert_return(m->hdr, -EINVAL);
268 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
269
270 ndm = NLMSG_DATA(m->hdr);
271 ndm->ndm_state |= state;
272
273 return 0;
274 }
275
276 int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) {
277 struct ndmsg *ndm;
278
279 assert_return(m, -EINVAL);
280 assert_return(m->hdr, -EINVAL);
281 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
282
283 ndm = NLMSG_DATA(m->hdr);
284 *flags = ndm->ndm_flags;
285
286 return 0;
287 }
288
289 int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) {
290 struct ndmsg *ndm;
291
292 assert_return(m, -EINVAL);
293 assert_return(m->hdr, -EINVAL);
294 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
295
296 ndm = NLMSG_DATA(m->hdr);
297 *state = ndm->ndm_state;
298
299 return 0;
300 }
301
302 int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) {
303 struct ndmsg *ndm;
304
305 assert_return(m, -EINVAL);
306 assert_return(m->hdr, -EINVAL);
307 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
308 assert_return(family, -EINVAL);
309
310 ndm = NLMSG_DATA(m->hdr);
311
312 *family = ndm->ndm_family;
313
314 return 0;
315 }
316
317 int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index) {
318 struct ndmsg *ndm;
319
320 assert_return(m, -EINVAL);
321 assert_return(m->hdr, -EINVAL);
322 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
323 assert_return(index, -EINVAL);
324
325 ndm = NLMSG_DATA(m->hdr);
326
327 *index = ndm->ndm_ifindex;
328
329 return 0;
330 }
331
332 int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
333 struct ndmsg *ndm;
334 int r;
335
336 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
337 assert_return(ndm_family == AF_INET ||
338 ndm_family == AF_INET6 ||
339 ndm_family == PF_BRIDGE, -EINVAL);
340 assert_return(ret, -EINVAL);
341
342 r = message_new(rtnl, ret, nlmsg_type);
343 if (r < 0)
344 return r;
345
346 if (nlmsg_type == RTM_NEWNEIGH)
347 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
348
349 ndm = NLMSG_DATA((*ret)->hdr);
350
351 ndm->ndm_family = ndm_family;
352 ndm->ndm_ifindex = index;
353
354 return 0;
355 }
356
357 int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) {
358 struct ifinfomsg *ifi;
359
360 assert_return(m, -EINVAL);
361 assert_return(m->hdr, -EINVAL);
362 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
363 assert_return(change, -EINVAL);
364
365 ifi = NLMSG_DATA(m->hdr);
366
367 ifi->ifi_flags = flags;
368 ifi->ifi_change = change;
369
370 return 0;
371 }
372
373 int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) {
374 struct ifinfomsg *ifi;
375
376 assert_return(m, -EINVAL);
377 assert_return(m->hdr, -EINVAL);
378 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
379
380 ifi = NLMSG_DATA(m->hdr);
381
382 ifi->ifi_type = type;
383
384 return 0;
385 }
386
387 int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) {
388 struct ifinfomsg *ifi;
389
390 assert_return(m, -EINVAL);
391 assert_return(m->hdr, -EINVAL);
392 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
393
394 ifi = NLMSG_DATA(m->hdr);
395
396 ifi->ifi_family = family;
397
398 return 0;
399 }
400
401 int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
402 uint16_t nlmsg_type, int index) {
403 struct ifinfomsg *ifi;
404 int r;
405
406 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
407 assert_return(nlmsg_type != RTM_DELLINK || index > 0, -EINVAL);
408 assert_return(ret, -EINVAL);
409
410 r = message_new(rtnl, ret, nlmsg_type);
411 if (r < 0)
412 return r;
413
414 if (nlmsg_type == RTM_NEWLINK)
415 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
416
417 ifi = NLMSG_DATA((*ret)->hdr);
418
419 ifi->ifi_family = AF_UNSPEC;
420 ifi->ifi_index = index;
421
422 return 0;
423 }
424
425 int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
426 struct ifaddrmsg *ifa;
427
428 assert_return(m, -EINVAL);
429 assert_return(m->hdr, -EINVAL);
430 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
431
432 ifa = NLMSG_DATA(m->hdr);
433
434 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
435 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
436 return -ERANGE;
437
438 ifa->ifa_prefixlen = prefixlen;
439
440 return 0;
441 }
442
443 int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) {
444 struct ifaddrmsg *ifa;
445
446 assert_return(m, -EINVAL);
447 assert_return(m->hdr, -EINVAL);
448 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
449
450 ifa = NLMSG_DATA(m->hdr);
451
452 ifa->ifa_flags = flags;
453
454 return 0;
455 }
456
457 int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) {
458 struct ifaddrmsg *ifa;
459
460 assert_return(m, -EINVAL);
461 assert_return(m->hdr, -EINVAL);
462 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
463
464 ifa = NLMSG_DATA(m->hdr);
465
466 ifa->ifa_scope = scope;
467
468 return 0;
469 }
470
471 int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family) {
472 struct ifaddrmsg *ifa;
473
474 assert_return(m, -EINVAL);
475 assert_return(m->hdr, -EINVAL);
476 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
477 assert_return(family, -EINVAL);
478
479 ifa = NLMSG_DATA(m->hdr);
480
481 *family = ifa->ifa_family;
482
483 return 0;
484 }
485
486 int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) {
487 struct ifaddrmsg *ifa;
488
489 assert_return(m, -EINVAL);
490 assert_return(m->hdr, -EINVAL);
491 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
492 assert_return(prefixlen, -EINVAL);
493
494 ifa = NLMSG_DATA(m->hdr);
495
496 *prefixlen = ifa->ifa_prefixlen;
497
498 return 0;
499 }
500
501 int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope) {
502 struct ifaddrmsg *ifa;
503
504 assert_return(m, -EINVAL);
505 assert_return(m->hdr, -EINVAL);
506 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
507 assert_return(scope, -EINVAL);
508
509 ifa = NLMSG_DATA(m->hdr);
510
511 *scope = ifa->ifa_scope;
512
513 return 0;
514 }
515
516 int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags) {
517 struct ifaddrmsg *ifa;
518
519 assert_return(m, -EINVAL);
520 assert_return(m->hdr, -EINVAL);
521 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
522 assert_return(flags, -EINVAL);
523
524 ifa = NLMSG_DATA(m->hdr);
525
526 *flags = ifa->ifa_flags;
527
528 return 0;
529 }
530
531 int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex) {
532 struct ifaddrmsg *ifa;
533
534 assert_return(m, -EINVAL);
535 assert_return(m->hdr, -EINVAL);
536 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
537 assert_return(ifindex, -EINVAL);
538
539 ifa = NLMSG_DATA(m->hdr);
540
541 *ifindex = ifa->ifa_index;
542
543 return 0;
544 }
545
546 int sd_rtnl_message_new_addr(sd_netlink *rtnl, sd_netlink_message **ret,
547 uint16_t nlmsg_type, int index,
548 int family) {
549 struct ifaddrmsg *ifa;
550 int r;
551
552 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
553 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
554 index > 0, -EINVAL);
555 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
556 family == AF_INET || family == AF_INET6, -EINVAL);
557 assert_return(ret, -EINVAL);
558
559 r = message_new(rtnl, ret, nlmsg_type);
560 if (r < 0)
561 return r;
562
563 if (nlmsg_type == RTM_GETADDR)
564 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
565
566 ifa = NLMSG_DATA((*ret)->hdr);
567
568 ifa->ifa_index = index;
569 ifa->ifa_family = family;
570 if (family == AF_INET)
571 ifa->ifa_prefixlen = 32;
572 else if (family == AF_INET6)
573 ifa->ifa_prefixlen = 128;
574
575 return 0;
576 }
577
578 int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret,
579 int index, int family) {
580 int r;
581
582 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
583 if (r < 0)
584 return r;
585
586 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
587
588 return 0;
589 }
590
591 int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) {
592 struct ifinfomsg *ifi;
593
594 assert_return(m, -EINVAL);
595 assert_return(m->hdr, -EINVAL);
596 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
597 assert_return(ifindex, -EINVAL);
598
599 ifi = NLMSG_DATA(m->hdr);
600
601 *ifindex = ifi->ifi_index;
602
603 return 0;
604 }
605
606 int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) {
607 struct ifinfomsg *ifi;
608
609 assert_return(m, -EINVAL);
610 assert_return(m->hdr, -EINVAL);
611 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
612 assert_return(flags, -EINVAL);
613
614 ifi = NLMSG_DATA(m->hdr);
615
616 *flags = ifi->ifi_flags;
617
618 return 0;
619 }
620
621 int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type) {
622 struct ifinfomsg *ifi;
623
624 assert_return(m, -EINVAL);
625 assert_return(m->hdr, -EINVAL);
626 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
627 assert_return(type, -EINVAL);
628
629 ifi = NLMSG_DATA(m->hdr);
630
631 *type = ifi->ifi_type;
632
633 return 0;
634 }
635
636 int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) {
637 assert_return(m, -EINVAL);
638 assert_return(family, -EINVAL);
639
640 assert(m->hdr);
641
642 if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
643 struct ifinfomsg *ifi;
644
645 ifi = NLMSG_DATA(m->hdr);
646
647 *family = ifi->ifi_family;
648
649 return 0;
650 } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
651 struct rtmsg *rtm;
652
653 rtm = NLMSG_DATA(m->hdr);
654
655 *family = rtm->rtm_family;
656
657 return 0;
658 } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
659 struct ndmsg *ndm;
660
661 ndm = NLMSG_DATA(m->hdr);
662
663 *family = ndm->ndm_family;
664
665 return 0;
666 } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
667 struct ifaddrmsg *ifa;
668
669 ifa = NLMSG_DATA(m->hdr);
670
671 *family = ifa->ifa_family;
672
673 return 0;
674 }
675
676 return -EOPNOTSUPP;
677 }