Home | History | Annotate | Download | only in route
      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 (at) 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 
     28 static struct nl_cache_ops rtnl_route_ops;
     29 
     30 static 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 	err = pp->pp_cb((struct nl_object *) route, pp);
     40 
     41 	rtnl_route_put(route);
     42 	return err;
     43 }
     44 
     45 static int route_request_update(struct nl_cache *c, struct nl_sock *h)
     46 {
     47 	struct rtmsg rhdr = {
     48 		.rtm_family = c->c_iarg1,
     49 	};
     50 
     51 	if (c->c_iarg2 & ROUTE_CACHE_CONTENT)
     52 		rhdr.rtm_flags |= RTM_F_CLONED;
     53 
     54 	return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
     55 }
     56 
     57 /**
     58  * @name Cache Management
     59  * @{
     60  */
     61 
     62 /**
     63  * Build a route cache holding all routes currently configured in the kernel
     64  * @arg sk		Netlink socket.
     65  * @arg family		Address family of routes to cover or AF_UNSPEC
     66  * @arg flags		Flags
     67  *
     68  * Allocates a new cache, initializes it properly and updates it to
     69  * contain all routes currently configured in the kernel.
     70  *
     71  * @note The caller is responsible for destroying and freeing the
     72  *       cache after using it.
     73  * @return The cache or NULL if an error has occured.
     74  */
     75 int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags,
     76 			   struct nl_cache **result)
     77 {
     78 	struct nl_cache *cache;
     79 	int err;
     80 
     81 	if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
     82 		return -NLE_NOMEM;
     83 
     84 	cache->c_iarg1 = family;
     85 	cache->c_iarg2 = flags;
     86 
     87 	if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
     88 		free(cache);
     89 		return err;
     90 	}
     91 
     92 	*result = cache;
     93 	return 0;
     94 }
     95 
     96 /** @} */
     97 
     98 /**
     99  * @name Route Addition
    100  * @{
    101  */
    102 
    103 static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
    104 			   struct nl_msg **result)
    105 {
    106 	struct nl_msg *msg;
    107 	int err;
    108 
    109 	if (!(msg = nlmsg_alloc_simple(cmd, flags)))
    110 		return -NLE_NOMEM;
    111 
    112 	if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
    113 		nlmsg_free(msg);
    114 		return err;
    115 	}
    116 
    117 	*result = msg;
    118 	return 0;
    119 }
    120 
    121 int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
    122 				 struct nl_msg **result)
    123 {
    124 	return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
    125 			       result);
    126 }
    127 
    128 int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags)
    129 {
    130 	struct nl_msg *msg;
    131 	int err;
    132 
    133 	if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
    134 		return err;
    135 
    136 	err = nl_send_auto_complete(sk, msg);
    137 	nlmsg_free(msg);
    138 	if (err < 0)
    139 		return err;
    140 
    141 	return wait_for_ack(sk);
    142 }
    143 
    144 int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
    145 				 struct nl_msg **result)
    146 {
    147 	return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
    148 }
    149 
    150 int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags)
    151 {
    152 	struct nl_msg *msg;
    153 	int err;
    154 
    155 	if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
    156 		return err;
    157 
    158 	err = nl_send_auto_complete(sk, msg);
    159 	nlmsg_free(msg);
    160 	if (err < 0)
    161 		return err;
    162 
    163 	return wait_for_ack(sk);
    164 }
    165 
    166 /** @} */
    167 
    168 static struct nl_af_group route_groups[] = {
    169 	{ AF_INET,	RTNLGRP_IPV4_ROUTE },
    170 	{ AF_INET6,	RTNLGRP_IPV6_ROUTE },
    171 	{ AF_DECnet,	RTNLGRP_DECnet_ROUTE },
    172 	{ END_OF_GROUP_LIST },
    173 };
    174 
    175 static struct nl_cache_ops rtnl_route_ops = {
    176 	.co_name		= "route/route",
    177 	.co_hdrsize		= sizeof(struct rtmsg),
    178 	.co_msgtypes		= {
    179 					{ RTM_NEWROUTE, NL_ACT_NEW, "new" },
    180 					{ RTM_DELROUTE, NL_ACT_DEL, "del" },
    181 					{ RTM_GETROUTE, NL_ACT_GET, "get" },
    182 					END_OF_MSGTYPES_LIST,
    183 				  },
    184 	.co_protocol		= NETLINK_ROUTE,
    185 	.co_groups		= route_groups,
    186 	.co_request_update	= route_request_update,
    187 	.co_msg_parser		= route_msg_parser,
    188 	.co_obj_ops		= &route_obj_ops,
    189 };
    190 
    191 static void __init route_init(void)
    192 {
    193 	nl_cache_mngt_register(&rtnl_route_ops);
    194 }
    195 
    196 static void __exit route_exit(void)
    197 {
    198 	nl_cache_mngt_unregister(&rtnl_route_ops);
    199 }
    200 
    201 /** @} */
    202