libnl 1.1.4
route_obj.c
1/*
2 * lib/route/route_obj.c Route Object
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
7 * of the License.
8 *
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup route
14 * @defgroup route_obj Route Object
15 *
16 * @par Attributes
17 * @code
18 * Name Default
19 * -------------------------------------------------------------
20 * routing table RT_TABLE_MAIN
21 * scope RT_SCOPE_NOWHERE
22 * tos 0
23 * realms 0
24 * protocol RTPROT_STATIC
25 * prio 0
26 * family AF_UNSPEC
27 * type RTN_UNICAST
28 * oif RTNL_LINK_NOT_FOUND
29 * iif NULL
30 * mpalgo IP_MP_ALG_NONE
31 * @endcode
32 *
33 * @{
34 */
35
36#include <netlink-local.h>
37#include <netlink/netlink.h>
38#include <netlink/cache.h>
39#include <netlink/utils.h>
40#include <netlink/data.h>
41#include <netlink/route/rtnl.h>
42#include <netlink/route/route.h>
43#include <netlink/route/link.h>
44
45/** @cond SKIP */
46#define ROUTE_ATTR_FAMILY 0x000001
47#define ROUTE_ATTR_TOS 0x000002
48#define ROUTE_ATTR_TABLE 0x000004
49#define ROUTE_ATTR_PROTOCOL 0x000008
50#define ROUTE_ATTR_SCOPE 0x000010
51#define ROUTE_ATTR_TYPE 0x000020
52#define ROUTE_ATTR_FLAGS 0x000040
53#define ROUTE_ATTR_DST 0x000080
54#define ROUTE_ATTR_SRC 0x000100
55#define ROUTE_ATTR_IIF 0x000200
56#define ROUTE_ATTR_OIF 0x000400
57#define ROUTE_ATTR_GATEWAY 0x000800
58#define ROUTE_ATTR_PRIO 0x001000
59#define ROUTE_ATTR_PREF_SRC 0x002000
60#define ROUTE_ATTR_METRICS 0x004000
61#define ROUTE_ATTR_MULTIPATH 0x008000
62#define ROUTE_ATTR_REALMS 0x010000
63#define ROUTE_ATTR_CACHEINFO 0x020000
64#define ROUTE_ATTR_MP_ALGO 0x040000
65/** @endcond */
66
67static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p);
68
69static void route_constructor(struct nl_object *c)
70{
71 struct rtnl_route *r = (struct rtnl_route *) c;
72
73 nl_init_list_head(&r->rt_nexthops);
74}
75
76static void route_free_data(struct nl_object *c)
77{
78 struct rtnl_route *r = (struct rtnl_route *) c;
79 struct rtnl_nexthop *nh, *tmp;
80
81 if (r == NULL)
82 return;
83
84 nl_addr_put(r->rt_dst);
85 nl_addr_put(r->rt_src);
86 nl_addr_put(r->rt_gateway);
87 nl_addr_put(r->rt_pref_src);
88
89 nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) {
90 rtnl_route_remove_nexthop(nh);
91 rtnl_route_nh_free(nh);
92 }
93}
94
95static int route_clone(struct nl_object *_dst, struct nl_object *_src)
96{
97 struct rtnl_route *dst = (struct rtnl_route *) _dst;
98 struct rtnl_route *src = (struct rtnl_route *) _src;
99 struct rtnl_nexthop *nh, *new;
100
101 if (src->rt_dst)
102 if (!(dst->rt_dst = nl_addr_clone(src->rt_dst)))
103 goto errout;
104
105 if (src->rt_src)
106 if (!(dst->rt_src = nl_addr_clone(src->rt_src)))
107 goto errout;
108
109 if (src->rt_gateway)
110 if (!(dst->rt_gateway = nl_addr_clone(src->rt_gateway)))
111 goto errout;
112
113 if (src->rt_pref_src)
114 if (!(dst->rt_pref_src = nl_addr_clone(src->rt_pref_src)))
115 goto errout;
116
117 nl_init_list_head(&dst->rt_nexthops);
118 nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) {
119 new = rtnl_route_nh_clone(nh);
120 if (!new)
121 goto errout;
122
123 rtnl_route_add_nexthop(dst, new);
124 }
125
126 return 0;
127errout:
128 return nl_get_errno();
129}
130
131static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p)
132{
133 struct rtnl_route *r = (struct rtnl_route *) a;
134 struct nl_cache *link_cache;
135 char buf[64];
136
137 link_cache = nl_cache_mngt_require("route/link");
138
139 if (!(r->ce_mask & ROUTE_ATTR_DST) ||
140 nl_addr_get_len(r->rt_dst) == 0)
141 dp_dump(p, "default ");
142 else
143 dp_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
144
145 if (r->ce_mask & ROUTE_ATTR_OIF) {
146 if (link_cache)
147 dp_dump(p, "dev %s ",
148 rtnl_link_i2name(link_cache, r->rt_oif,
149 buf, sizeof(buf)));
150 else
151 dp_dump(p, "dev %d ", r->rt_oif);
152 }
153
154 if (r->ce_mask & ROUTE_ATTR_GATEWAY)
155 dp_dump(p, "via %s ", nl_addr2str(r->rt_gateway, buf,
156 sizeof(buf)));
157 else if (r->ce_mask & ROUTE_ATTR_MULTIPATH)
158 dp_dump(p, "via nexthops ");
159
160 if (r->ce_mask & ROUTE_ATTR_SCOPE)
161 dp_dump(p, "scope %s ",
162 rtnl_scope2str(r->rt_scope, buf, sizeof(buf)));
163
164 if (r->ce_mask & ROUTE_ATTR_FLAGS && r->rt_flags) {
165 int flags = r->rt_flags;
166
167 dp_dump(p, "<");
168
169#define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \
170 flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
171 PRINT_FLAG(DEAD);
172 PRINT_FLAG(ONLINK);
173 PRINT_FLAG(PERVASIVE);
174#undef PRINT_FLAG
175
176#define PRINT_FLAG(f) if (flags & RTM_F_##f) { \
177 flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
178 PRINT_FLAG(NOTIFY);
179 PRINT_FLAG(CLONED);
180 PRINT_FLAG(EQUALIZE);
181 PRINT_FLAG(PREFIX);
182#undef PRINT_FLAG
183
184 dp_dump(p, ">");
185 }
186
187 dp_dump(p, "\n");
188
189 return 1;
190}
191
192static int route_dump_full(struct nl_object *a, struct nl_dump_params *p)
193{
194 struct rtnl_route *r = (struct rtnl_route *) a;
195 struct nl_cache *link_cache;
196 char buf[256];
197 int i, line;
198
199 link_cache = nl_cache_mngt_require("route/link");
200 line = route_dump_brief(a, p);
201
202 if (r->ce_mask & ROUTE_ATTR_MULTIPATH) {
203 struct rtnl_nexthop *nh;
204
205 nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) {
206 dp_dump_line(p, line++, " via ");
207
208 if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
209 dp_dump(p, "%s ",
210 nl_addr2str(nh->rtnh_gateway,
211 buf, sizeof(buf)));
212 if (link_cache) {
213 dp_dump(p, "dev %s ",
214 rtnl_link_i2name(link_cache,
215 nh->rtnh_ifindex,
216 buf, sizeof(buf)));
217 } else
218 dp_dump(p, "dev %d ", nh->rtnh_ifindex);
219
220 dp_dump(p, "weight %u <%s>\n", nh->rtnh_weight,
221 rtnl_route_nh_flags2str(nh->rtnh_flags,
222 buf, sizeof(buf)));
223 }
224 }
225
226 dp_dump_line(p, line++, " ");
227
228 if (r->ce_mask & ROUTE_ATTR_PREF_SRC)
229 dp_dump(p, "preferred-src %s ",
230 nl_addr2str(r->rt_pref_src, buf, sizeof(buf)));
231
232 if (r->ce_mask & ROUTE_ATTR_TABLE)
233 dp_dump(p, "table %s ",
234 rtnl_route_table2str(r->rt_table, buf, sizeof(buf)));
235
236 if (r->ce_mask & ROUTE_ATTR_TYPE)
237 dp_dump(p, "type %s ",
238 nl_rtntype2str(r->rt_type, buf, sizeof(buf)));
239
240 if (r->ce_mask & ROUTE_ATTR_PRIO)
241 dp_dump(p, "metric %#x ", r->rt_prio);
242
243 if (r->ce_mask & ROUTE_ATTR_FAMILY)
244 dp_dump(p, "family %s ",
245 nl_af2str(r->rt_family, buf, sizeof(buf)));
246
247 if (r->ce_mask & ROUTE_ATTR_PROTOCOL)
248 dp_dump(p, "protocol %s ",
249 rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf)));
250
251 dp_dump(p, "\n");
252
253 if ((r->ce_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS |
254 ROUTE_ATTR_REALMS)) ||
255 ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
256 r->rt_cacheinfo.rtci_error)) {
257 dp_dump_line(p, line++, " ");
258
259 if (r->ce_mask & ROUTE_ATTR_IIF)
260 dp_dump(p, "iif %s ", r->rt_iif);
261
262 if (r->ce_mask & ROUTE_ATTR_SRC)
263 dp_dump(p, "src %s ",
264 nl_addr2str(r->rt_src, buf, sizeof(buf)));
265
266 if (r->ce_mask & ROUTE_ATTR_TOS)
267 dp_dump(p, "tos %#x ", r->rt_tos);
268
269 if (r->ce_mask & ROUTE_ATTR_REALMS)
270 dp_dump(p, "realm %04x:%04x ",
271 RTNL_REALM_FROM(r->rt_realms),
272 RTNL_REALM_TO(r->rt_realms));
273
274 if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
275 r->rt_cacheinfo.rtci_error)
276 dp_dump(p, "error %d (%s) ", r->rt_cacheinfo.rtci_error,
277 strerror_r(-r->rt_cacheinfo.rtci_error, buf, sizeof(buf)));
278
279 dp_dump(p, "\n");
280 }
281
282 if (r->ce_mask & ROUTE_ATTR_METRICS) {
283 dp_dump_line(p, line++, " ");
284 for (i = 0; i < RTAX_MAX; i++)
285 if (r->rt_metrics_mask & (1 << i))
286 dp_dump(p, "%s %u ",
287 rtnl_route_metric2str(i+1,
288 buf, sizeof(buf)),
289 r->rt_metrics[i]);
290 dp_dump(p, "\n");
291 }
292
293 return line;
294}
295
296static int route_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
297{
298 struct rtnl_route *route = (struct rtnl_route *) obj;
299 int line;
300
301 line = route_dump_full(obj, p);
302
303 if (route->ce_mask & ROUTE_ATTR_CACHEINFO) {
304 struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo;
305 dp_dump_line(p, line++, " used %u refcnt %u ",
306 ci->rtci_used, ci->rtci_clntref);
307 dp_dump_line(p, line++, "last-use %us expires %us\n",
308 ci->rtci_last_use / nl_get_hz(),
309 ci->rtci_expires / nl_get_hz());
310 }
311
312 return line;
313}
314
315static int route_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
316{
317 struct rtnl_route *route = (struct rtnl_route *) obj;
318 char buf[128];
319 int line = 0;
320
321 dp_dump_line(p, line++, "<route>\n");
322 dp_dump_line(p, line++, " <family>%s</family>\n",
323 nl_af2str(route->rt_family, buf, sizeof(buf)));
324
325 if (route->ce_mask & ROUTE_ATTR_DST)
326 dp_dump_line(p, line++, " <dst>%s</dst>\n",
327 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
328
329 if (route->ce_mask & ROUTE_ATTR_SRC)
330 dp_dump_line(p, line++, " <src>%s</src>\n",
331 nl_addr2str(route->rt_src, buf, sizeof(buf)));
332
333 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
334 dp_dump_line(p, line++, " <gateway>%s</gateway>\n",
335 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
336
337 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
338 dp_dump_line(p, line++, " <prefsrc>%s</prefsrc>\n",
339 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
340
341 if (route->ce_mask & ROUTE_ATTR_IIF)
342 dp_dump_line(p, line++, " <iif>%s</iif>\n", route->rt_iif);
343
344 if (route->ce_mask & ROUTE_ATTR_REALMS)
345 dp_dump_line(p, line++, " <realms>%u</realms>\n",
346 route->rt_realms);
347
348 if (route->ce_mask & ROUTE_ATTR_TOS)
349 dp_dump_line(p, line++, " <tos>%u</tos>\n", route->rt_tos);
350
351 if (route->ce_mask & ROUTE_ATTR_TABLE)
352 dp_dump_line(p, line++, " <table>%u</table>\n",
353 route->rt_table);
354
355 if (route->ce_mask & ROUTE_ATTR_SCOPE)
356 dp_dump_line(p, line++, " <scope>%s</scope>\n",
357 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
358
359 if (route->ce_mask & ROUTE_ATTR_PRIO)
360 dp_dump_line(p, line++, " <metric>%u</metric>\n",
361 route->rt_prio);
362
363 if (route->ce_mask & ROUTE_ATTR_OIF) {
364 struct nl_cache *link_cache;
365
366 link_cache = nl_cache_mngt_require("route/link");
367 if (link_cache)
368 dp_dump_line(p, line++, " <oif>%s</oif>\n",
369 rtnl_link_i2name(link_cache,
370 route->rt_oif,
371 buf, sizeof(buf)));
372 else
373 dp_dump_line(p, line++, " <oif>%u</oif>\n",
374 route->rt_oif);
375 }
376
377 if (route->ce_mask & ROUTE_ATTR_TYPE)
378 dp_dump_line(p, line++, " <type>%s</type>\n",
379 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
380
381 dp_dump_line(p, line++, "</route>\n");
382
383#if 0
384 uint8_t rt_protocol;
385 uint32_t rt_flags;
386 uint32_t rt_metrics[RTAX_MAX];
387 uint32_t rt_metrics_mask;
388 struct rtnl_nexthop * rt_nexthops;
389 struct rtnl_rtcacheinfo rt_cacheinfo;
390 uint32_t rt_mp_algo;
391
392#endif
393
394 return line;
395}
396
397static int route_dump_env(struct nl_object *obj, struct nl_dump_params *p)
398{
399 struct rtnl_route *route = (struct rtnl_route *) obj;
400 char buf[128];
401 int line = 0;
402
403 dp_dump_line(p, line++, "ROUTE_FAMILY=%s\n",
404 nl_af2str(route->rt_family, buf, sizeof(buf)));
405
406 if (route->ce_mask & ROUTE_ATTR_DST)
407 dp_dump_line(p, line++, "ROUTE_DST=%s\n",
408 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
409
410 if (route->ce_mask & ROUTE_ATTR_SRC)
411 dp_dump_line(p, line++, "ROUTE_SRC=%s\n",
412 nl_addr2str(route->rt_src, buf, sizeof(buf)));
413
414 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
415 dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n",
416 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
417
418 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
419 dp_dump_line(p, line++, "ROUTE_PREFSRC=%s\n",
420 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
421
422 if (route->ce_mask & ROUTE_ATTR_IIF)
423 dp_dump_line(p, line++, "ROUTE_IIF=%s\n", route->rt_iif);
424
425 if (route->ce_mask & ROUTE_ATTR_REALMS)
426 dp_dump_line(p, line++, "ROUTE_REALM=%u\n",
427 route->rt_realms);
428
429 if (route->ce_mask & ROUTE_ATTR_TOS)
430 dp_dump_line(p, line++, "ROUTE_TOS=%u\n", route->rt_tos);
431
432 if (route->ce_mask & ROUTE_ATTR_TABLE)
433 dp_dump_line(p, line++, "ROUTE_TABLE=%u\n",
434 route->rt_table);
435
436 if (route->ce_mask & ROUTE_ATTR_SCOPE)
437 dp_dump_line(p, line++, "ROUTE_SCOPE=%s\n",
438 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
439
440 if (route->ce_mask & ROUTE_ATTR_PRIO)
441 dp_dump_line(p, line++, "ROUTE_METRIC=%u\n",
442 route->rt_prio);
443
444 if (route->ce_mask & ROUTE_ATTR_OIF) {
445 struct nl_cache *link_cache;
446
447 dp_dump_line(p, line++, "ROUTE_OIF_IFINDEX=%u\n",
448 route->rt_oif);
449
450 link_cache = nl_cache_mngt_require("route/link");
451 if (link_cache)
452 dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n",
453 rtnl_link_i2name(link_cache,
454 route->rt_oif,
455 buf, sizeof(buf)));
456 }
457
458 if (route->ce_mask & ROUTE_ATTR_TYPE)
459 dp_dump_line(p, line++, "ROUTE_TYPE=%s\n",
460 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
461
462 return line;
463}
464
465static int route_compare(struct nl_object *_a, struct nl_object *_b,
466 uint32_t attrs, int flags)
467{
468 struct rtnl_route *a = (struct rtnl_route *) _a;
469 struct rtnl_route *b = (struct rtnl_route *) _b;
470 int diff = 0;
471
472#define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
473
474 diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family);
475 diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos);
476 diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table);
477 diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol);
478 diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope);
479 diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type);
480 diff |= ROUTE_DIFF(OIF, a->rt_oif != b->rt_oif);
481 diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio);
482 diff |= ROUTE_DIFF(REALMS, a->rt_realms != b->rt_realms);
483 diff |= ROUTE_DIFF(MP_ALGO, a->rt_mp_algo != b->rt_mp_algo);
484 diff |= ROUTE_DIFF(DST, nl_addr_cmp(a->rt_dst, b->rt_dst));
485 diff |= ROUTE_DIFF(SRC, nl_addr_cmp(a->rt_src, b->rt_src));
486 diff |= ROUTE_DIFF(IIF, strcmp(a->rt_iif, b->rt_iif));
487 diff |= ROUTE_DIFF(PREF_SRC, nl_addr_cmp(a->rt_pref_src,
488 b->rt_pref_src));
489 diff |= ROUTE_DIFF(GATEWAY, nl_addr_cmp(a->rt_gateway,
490 b->rt_gateway));
491
492 /* FIXME: Compare metrics, multipath config */
493
494 if (flags & LOOSE_FLAG_COMPARISON)
495 diff |= ROUTE_DIFF(FLAGS,
496 (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask);
497 else
498 diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags);
499
500#undef ROUTE_DIFF
501
502 return diff;
503}
504
505static struct trans_tbl route_attrs[] = {
506 __ADD(ROUTE_ATTR_FAMILY, family)
507 __ADD(ROUTE_ATTR_TOS, tos)
508 __ADD(ROUTE_ATTR_TABLE, table)
509 __ADD(ROUTE_ATTR_PROTOCOL, protocol)
510 __ADD(ROUTE_ATTR_SCOPE, scope)
511 __ADD(ROUTE_ATTR_TYPE, type)
512 __ADD(ROUTE_ATTR_FLAGS, flags)
513 __ADD(ROUTE_ATTR_DST, dst)
514 __ADD(ROUTE_ATTR_SRC, src)
515 __ADD(ROUTE_ATTR_IIF, iif)
516 __ADD(ROUTE_ATTR_OIF, oif)
517 __ADD(ROUTE_ATTR_GATEWAY, gateway)
518 __ADD(ROUTE_ATTR_PRIO, prio)
519 __ADD(ROUTE_ATTR_PREF_SRC, pref_src)
520 __ADD(ROUTE_ATTR_METRICS, metrics)
521 __ADD(ROUTE_ATTR_MULTIPATH, multipath)
522 __ADD(ROUTE_ATTR_REALMS, realms)
523 __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo)
524 __ADD(ROUTE_ATTR_MP_ALGO, mp_algo)
525};
526
527static char *route_attrs2str(int attrs, char *buf, size_t len)
528{
529 return __flags2str(attrs, buf, len, route_attrs,
530 ARRAY_SIZE(route_attrs));
531}
532
533/**
534 * @name Allocation/Freeing
535 * @{
536 */
537
538struct rtnl_route *rtnl_route_alloc(void)
539{
540 return (struct rtnl_route *) nl_object_alloc(&route_obj_ops);
541}
542
543void rtnl_route_get(struct rtnl_route *route)
544{
545 nl_object_get((struct nl_object *) route);
546}
547
548void rtnl_route_put(struct rtnl_route *route)
549{
550 nl_object_put((struct nl_object *) route);
551}
552
553/** @} */
554
555/**
556 * @name Attributes
557 * @{
558 */
559
560void rtnl_route_set_table(struct rtnl_route *route, int table)
561{
562 route->rt_table = table;
563 route->ce_mask |= ROUTE_ATTR_TABLE;
564}
565
566int rtnl_route_get_table(struct rtnl_route *route)
567{
568 if (route->ce_mask & ROUTE_ATTR_TABLE)
569 return route->rt_table;
570 else
571 return RT_TABLE_MAIN;
572}
573
574void rtnl_route_set_scope(struct rtnl_route *route, int scope)
575{
576 route->rt_scope = scope;
577 route->ce_mask |= ROUTE_ATTR_SCOPE;
578}
579
580int rtnl_route_get_scope(struct rtnl_route *route)
581{
582 if (route->ce_mask & ROUTE_ATTR_SCOPE)
583 return route->rt_scope;
584 else
585 return RT_SCOPE_NOWHERE;
586}
587
588void rtnl_route_set_tos(struct rtnl_route *route, int tos)
589{
590 route->rt_tos = tos;
591 route->ce_mask |= ROUTE_ATTR_TOS;
592}
593
594int rtnl_route_get_tos(struct rtnl_route *route)
595{
596 return route->rt_tos;
597}
598
599void rtnl_route_set_realms(struct rtnl_route *route, realm_t realms)
600{
601 route->rt_realms = realms;
602 route->ce_mask |= ROUTE_ATTR_REALMS;
603}
604
605realm_t rtnl_route_get_realms(struct rtnl_route *route)
606{
607 return route->rt_realms;
608}
609
610void rtnl_route_set_protocol(struct rtnl_route *route, int proto)
611{
612 route->rt_protocol = proto;
613 route->ce_mask |= ROUTE_ATTR_PROTOCOL;
614}
615
616int rtnl_route_get_protocol(struct rtnl_route *route)
617{
618 if (route->ce_mask & ROUTE_ATTR_PROTOCOL)
619 return route->rt_protocol;
620 else
621 return RTPROT_STATIC;
622}
623
624void rtnl_route_set_prio(struct rtnl_route *route, int prio)
625{
626 route->rt_prio = prio;
627 route->ce_mask |= ROUTE_ATTR_PRIO;
628}
629
630int rtnl_route_get_prio(struct rtnl_route *route)
631{
632 return route->rt_prio;
633}
634
635void rtnl_route_set_family(struct rtnl_route *route, int family)
636{
637 route->rt_family = family;
638 route->ce_mask |= ROUTE_ATTR_FAMILY;
639}
640
641int rtnl_route_get_family(struct rtnl_route *route)
642{
643 if (route->ce_mask & ROUTE_ATTR_FAMILY)
644 return route->rt_family;
645 else
646 return AF_UNSPEC;
647}
648
649int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr)
650{
651 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
652 if (addr->a_family != route->rt_family)
653 return nl_error(EINVAL, "Address family mismatch");
654 } else
655 route->rt_family = addr->a_family;
656
657 if (route->rt_dst)
658 nl_addr_put(route->rt_dst);
659
660 nl_addr_get(addr);
661 route->rt_dst = addr;
662
663 route->ce_mask |= (ROUTE_ATTR_DST | ROUTE_ATTR_FAMILY);
664
665 return 0;
666}
667
668struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route)
669{
670 return route->rt_dst;
671}
672
673int rtnl_route_get_dst_len(struct rtnl_route *route)
674{
675 if (route->ce_mask & ROUTE_ATTR_DST)
676 return nl_addr_get_prefixlen(route->rt_dst);
677 else
678 return 0;
679}
680
681int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr)
682{
683 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
684 if (addr->a_family != route->rt_family)
685 return nl_error(EINVAL, "Address family mismatch");
686 } else
687 route->rt_family = addr->a_family;
688
689 if (route->rt_src)
690 nl_addr_put(route->rt_src);
691
692 nl_addr_get(addr);
693 route->rt_src = addr;
694 route->ce_mask |= (ROUTE_ATTR_SRC | ROUTE_ATTR_FAMILY);
695
696 return 0;
697}
698
699struct nl_addr *rtnl_route_get_src(struct rtnl_route *route)
700{
701 return route->rt_src;
702}
703
704int rtnl_route_get_src_len(struct rtnl_route *route)
705{
706 if (route->ce_mask & ROUTE_ATTR_SRC)
707 return nl_addr_get_prefixlen(route->rt_src);
708 else
709 return 0;
710}
711
712int rtnl_route_set_gateway(struct rtnl_route *route, struct nl_addr *addr)
713{
714 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
715 if (addr->a_family != route->rt_family)
716 return nl_error(EINVAL, "Address family mismatch");
717 } else
718 route->rt_family = addr->a_family;
719
720 if (route->rt_gateway)
721 nl_addr_put(route->rt_gateway);
722
723 nl_addr_get(addr);
724 route->rt_gateway = addr;
725 route->ce_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY);
726
727 return 0;
728}
729
730struct nl_addr *rtnl_route_get_gateway(struct rtnl_route *route)
731{
732 return route->rt_gateway;
733}
734
735void rtnl_route_set_type(struct rtnl_route *route, int type)
736{
737 route->rt_type = type;
738 route->ce_mask |= ROUTE_ATTR_TYPE;
739}
740
741int rtnl_route_get_type(struct rtnl_route *route)
742{
743 if (route->ce_mask & ROUTE_ATTR_TYPE)
744 return route->rt_type;
745 else
746 return RTN_UNICAST;
747}
748
749void rtnl_route_set_flags(struct rtnl_route *route, unsigned int flags)
750{
751 route->rt_flag_mask |= flags;
752 route->rt_flags |= flags;
753 route->ce_mask |= ROUTE_ATTR_FLAGS;
754}
755
756void rtnl_route_unset_flags(struct rtnl_route *route, unsigned int flags)
757{
758 route->rt_flag_mask |= flags;
759 route->rt_flags &= ~flags;
760 route->ce_mask |= ROUTE_ATTR_FLAGS;
761}
762
763unsigned int rtnl_route_get_flags(struct rtnl_route *route)
764{
765 return route->rt_flags;
766}
767
768int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value)
769{
770 if (metric > RTAX_MAX || metric < 1)
771 return nl_error(EINVAL, "Metric out of range (1..%d)",
772 RTAX_MAX);
773
774 route->rt_metrics[metric - 1] = value;
775 route->rt_metrics_mask |= (1 << (metric - 1));
776
777 return 0;
778}
779
780int rtnl_route_unset_metric(struct rtnl_route *route, int metric)
781{
782 if (metric > RTAX_MAX || metric < 1)
783 return nl_error(EINVAL, "Metric out of range (1..%d)",
784 RTAX_MAX);
785
786 route->rt_metrics_mask &= ~(1 << (metric - 1));
787
788 return 0;
789}
790
791unsigned int rtnl_route_get_metric(struct rtnl_route *route, int metric)
792{
793 if (metric > RTAX_MAX || metric < 1)
794 return UINT_MAX;
795
796 if (!(route->rt_metrics_mask & (1 << (metric - 1))))
797 return UINT_MAX;
798
799 return route->rt_metrics[metric - 1];
800}
801
802int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr)
803{
804 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
805 if (addr->a_family != route->rt_family)
806 return nl_error(EINVAL, "Address family mismatch");
807 } else
808 route->rt_family = addr->a_family;
809
810 if (route->rt_pref_src)
811 nl_addr_put(route->rt_pref_src);
812
813 nl_addr_get(addr);
814 route->rt_pref_src = addr;
815 route->ce_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY);
816
817 return 0;
818}
819
820struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route)
821{
822 return route->rt_pref_src;
823}
824
825void rtnl_route_set_oif(struct rtnl_route *route, int ifindex)
826{
827 route->rt_oif = ifindex;
828 route->ce_mask |= ROUTE_ATTR_OIF;
829}
830
831int rtnl_route_get_oif(struct rtnl_route *route)
832{
833 if (route->ce_mask & ROUTE_ATTR_OIF)
834 return route->rt_oif;
835 else
836 return RTNL_LINK_NOT_FOUND;
837}
838
839void rtnl_route_set_iif(struct rtnl_route *route, const char *name)
840{
841 strncpy(route->rt_iif, name, sizeof(route->rt_iif) - 1);
842 route->ce_mask |= ROUTE_ATTR_IIF;
843}
844
845char *rtnl_route_get_iif(struct rtnl_route *route)
846{
847 if (route->ce_mask & ROUTE_ATTR_IIF)
848 return route->rt_iif;
849 else
850 return NULL;
851}
852
853void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh)
854{
855 nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops);
856 route->ce_mask |= ROUTE_ATTR_MULTIPATH;
857}
858
859void rtnl_route_remove_nexthop(struct rtnl_nexthop *nh)
860{
861 nl_list_del(&nh->rtnh_list);
862}
863
864struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route)
865{
866 return &route->rt_nexthops;
867}
868
869void rtnl_route_set_cacheinfo(struct rtnl_route *route,
870 struct rtnl_rtcacheinfo *ci)
871{
872 memcpy(&route->rt_cacheinfo, ci, sizeof(*ci));
873 route->ce_mask |= ROUTE_ATTR_CACHEINFO;
874}
875
876uint32_t rtnl_route_get_mp_algo(struct rtnl_route *route)
877{
878 if (route->ce_mask & ROUTE_ATTR_MP_ALGO)
879 return route->rt_mp_algo;
880 else
881 return IP_MP_ALG_NONE;
882}
883
884void rtnl_route_set_mp_algo(struct rtnl_route *route, uint32_t algo)
885{
886 route->rt_mp_algo = algo;
887 route->ce_mask |= ROUTE_ATTR_MP_ALGO;
888}
889
890/** @} */
891
892struct nl_object_ops route_obj_ops = {
893 .oo_name = "route/route",
894 .oo_size = sizeof(struct rtnl_route),
895 .oo_constructor = route_constructor,
896 .oo_free_data = route_free_data,
897 .oo_clone = route_clone,
898 .oo_dump[NL_DUMP_BRIEF] = route_dump_brief,
899 .oo_dump[NL_DUMP_FULL] = route_dump_full,
900 .oo_dump[NL_DUMP_STATS] = route_dump_stats,
901 .oo_dump[NL_DUMP_XML] = route_dump_xml,
902 .oo_dump[NL_DUMP_ENV] = route_dump_env,
903 .oo_compare = route_compare,
904 .oo_attrs2str = route_attrs2str,
905 .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS |
906 ROUTE_ATTR_TABLE | ROUTE_ATTR_DST),
907};
908
909/** @} */
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:802
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
Definition: addr.c:489
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:406
unsigned int nl_addr_get_len(struct nl_addr *addr)
Get length of binary address of abstract address object.
Definition: addr.c:765
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
Get prefix length of abstract address object.
Definition: addr.c:779
struct nl_cache * nl_cache_mngt_require(const char *name)
Demand the use of a global cache.
Definition: cache_mngt.c:356
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:178
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
Definition: object.c:167
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:42
#define RTNL_REALM_TO(realm)
Extract TO realm from a realms field.
Definition: rtnl.h:42
#define RTNL_REALM_FROM(realm)
Extract FROM realm from a realms field.
Definition: rtnl.h:37
int nl_get_hz(void)
Return the value of HZ.
Definition: utils.c:428
@ NL_DUMP_FULL
Dump all attributes but no statistics.
Definition: types.h:23
@ NL_DUMP_BRIEF
Dump object in a brief one-liner.
Definition: types.h:22
@ NL_DUMP_ENV
Dump all attribtues as env variables.
Definition: types.h:26
@ NL_DUMP_STATS
Dump all attributes including statistics.
Definition: types.h:24
@ NL_DUMP_XML
Dump all attribtes in XML format.
Definition: types.h:25
Dumping parameters.
Definition: types.h:37
Object Operations.
Definition: object-api.h:255
char * oo_name
Unique name of object type.
Definition: object-api.h:261