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