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