route.c revision 8a3efffa5b3fde252675239914118664d36a2c24
1/*
2 * lib/route/route.c	Routes
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-2008 Thomas Graf <tgraf@suug.ch>
10 */
11
12/**
13 * @ingroup rtnl
14 * @defgroup route Routing
15 * @brief
16 * @{
17 */
18
19#include <netlink-local.h>
20#include <netlink/netlink.h>
21#include <netlink/cache.h>
22#include <netlink/utils.h>
23#include <netlink/data.h>
24#include <netlink/route/rtnl.h>
25#include <netlink/route/route.h>
26#include <netlink/route/link.h>
27
28static struct nl_cache_ops rtnl_route_ops;
29
30static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
31			    struct nlmsghdr *nlh, struct nl_parser_param *pp)
32{
33	struct rtnl_route *route;
34	int err;
35
36	if ((err = rtnl_route_parse(nlh, &route)) < 0)
37		return err;
38
39	if ((err = pp->pp_cb((struct nl_object *) route, pp)) < 0)
40		goto errout;
41
42	err = P_ACCEPT;
43
44errout:
45	rtnl_route_put(route);
46	return err;
47}
48
49static int route_request_update(struct nl_cache *c, struct nl_handle *h)
50{
51	struct rtmsg rhdr = {
52		.rtm_family = c->c_iarg1,
53	};
54
55	if (c->c_iarg2 & ROUTE_CACHE_CONTENT)
56		rhdr.rtm_flags |= RTM_F_CLONED;
57
58	return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
59}
60
61/**
62 * @name Cache Management
63 * @{
64 */
65
66/**
67 * Build a route cache holding all routes currently configured in the kernel
68 * @arg handle		netlink handle
69 * @arg family		Address family of routes to cover or AF_UNSPEC
70 * @arg flags		Flags
71 *
72 * Allocates a new cache, initializes it properly and updates it to
73 * contain all routes currently configured in the kernel.
74 *
75 * @note The caller is responsible for destroying and freeing the
76 *       cache after using it.
77 * @return The cache or NULL if an error has occured.
78 */
79int rtnl_route_alloc_cache(struct nl_handle *handle, int family, int flags,
80			   struct nl_cache **result)
81{
82	struct nl_cache *cache;
83	int err;
84
85	if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
86		return -NLE_NOMEM;
87
88	cache->c_iarg1 = family;
89	cache->c_iarg2 = flags;
90
91	if (handle && (err = nl_cache_refill(handle, cache)) < 0) {
92		free(cache);
93		return err;
94	}
95
96	*result = cache;
97	return 0;
98}
99
100/** @} */
101
102/**
103 * @name Route Addition
104 * @{
105 */
106
107static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
108			   struct nl_msg **result)
109{
110	struct nl_msg *msg;
111	int err;
112
113	if (!(msg = nlmsg_alloc_simple(cmd, flags)))
114		return -NLE_NOMEM;
115
116	if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
117		nlmsg_free(msg);
118		return err;
119	}
120
121	*result = msg;
122	return 0;
123}
124
125int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
126				 struct nl_msg **result)
127{
128	return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
129			       result);
130}
131
132int rtnl_route_add(struct nl_handle *handle, struct rtnl_route *route,
133		   int flags)
134{
135	struct nl_msg *msg;
136	int err;
137
138	if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
139		return err;
140
141	err = nl_send_auto_complete(handle, msg);
142	nlmsg_free(msg);
143	if (err < 0)
144		return err;
145
146	return nl_wait_for_ack(handle);
147}
148
149int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
150				 struct nl_msg **result)
151{
152	return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
153}
154
155int rtnl_route_delete(struct nl_handle *handle, struct rtnl_route *route,
156		      int flags)
157{
158	struct nl_msg *msg;
159	int err;
160
161	if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
162		return err;
163
164	err = nl_send_auto_complete(handle, msg);
165	nlmsg_free(msg);
166	if (err < 0)
167		return err;
168
169	return nl_wait_for_ack(handle);
170}
171
172/** @} */
173
174static struct nl_af_group route_groups[] = {
175	{ AF_INET,	RTNLGRP_IPV4_ROUTE },
176	{ AF_INET6,	RTNLGRP_IPV6_ROUTE },
177	{ AF_DECnet,	RTNLGRP_DECnet_ROUTE },
178	{ END_OF_GROUP_LIST },
179};
180
181static struct nl_cache_ops rtnl_route_ops = {
182	.co_name		= "route/route",
183	.co_hdrsize		= sizeof(struct rtmsg),
184	.co_msgtypes		= {
185					{ RTM_NEWROUTE, NL_ACT_NEW, "new" },
186					{ RTM_DELROUTE, NL_ACT_DEL, "del" },
187					{ RTM_GETROUTE, NL_ACT_GET, "get" },
188					END_OF_MSGTYPES_LIST,
189				  },
190	.co_protocol		= NETLINK_ROUTE,
191	.co_groups		= route_groups,
192	.co_request_update	= route_request_update,
193	.co_msg_parser		= route_msg_parser,
194	.co_obj_ops		= &route_obj_ops,
195};
196
197static void __init route_init(void)
198{
199	nl_cache_mngt_register(&rtnl_route_ops);
200}
201
202static void __exit route_exit(void)
203{
204	nl_cache_mngt_unregister(&rtnl_route_ops);
205}
206
207/** @} */
208