route.c

00001 /*
00002  * lib/route/route.c    Routes
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup rtnl
00014  * @defgroup route Routing
00015  * @brief
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink/netlink.h>
00021 #include <netlink/cache.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/data.h>
00024 #include <netlink/route/rtnl.h>
00025 #include <netlink/route/route.h>
00026 #include <netlink/route/link.h>
00027 
00028 static struct nl_cache_ops rtnl_route_ops;
00029 
00030 static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
00031                             struct nlmsghdr *nlh, struct nl_parser_param *pp)
00032 {
00033         struct rtnl_route *route;
00034         int err;
00035 
00036         if ((err = rtnl_route_parse(nlh, &route)) < 0)
00037                 return err;
00038 
00039         err = pp->pp_cb((struct nl_object *) route, pp);
00040 
00041         rtnl_route_put(route);
00042         return err;
00043 }
00044 
00045 static int route_request_update(struct nl_cache *c, struct nl_sock *h)
00046 {
00047         struct rtmsg rhdr = {
00048                 .rtm_family = c->c_iarg1,
00049         };
00050 
00051         if (c->c_iarg2 & ROUTE_CACHE_CONTENT)
00052                 rhdr.rtm_flags |= RTM_F_CLONED;
00053 
00054         return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
00055 }
00056 
00057 /**
00058  * @name Cache Management
00059  * @{
00060  */
00061 
00062 /**
00063  * Build a route cache holding all routes currently configured in the kernel
00064  * @arg sk              Netlink socket.
00065  * @arg family          Address family of routes to cover or AF_UNSPEC
00066  * @arg flags           Flags
00067  *
00068  * Allocates a new cache, initializes it properly and updates it to
00069  * contain all routes currently configured in the kernel.
00070  *
00071  * @note The caller is responsible for destroying and freeing the
00072  *       cache after using it.
00073  * @return The cache or NULL if an error has occured.
00074  */
00075 int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags,
00076                            struct nl_cache **result)
00077 {
00078         struct nl_cache *cache;
00079         int err;
00080 
00081         if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
00082                 return -NLE_NOMEM;
00083 
00084         cache->c_iarg1 = family;
00085         cache->c_iarg2 = flags;
00086 
00087         if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
00088                 free(cache);
00089                 return err;
00090         }
00091 
00092         *result = cache;
00093         return 0;
00094 }
00095 
00096 /** @} */
00097 
00098 /**
00099  * @name Route Addition
00100  * @{
00101  */
00102 
00103 static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
00104                            struct nl_msg **result)
00105 {
00106         struct nl_msg *msg;
00107         int err;
00108 
00109         if (!(msg = nlmsg_alloc_simple(cmd, flags)))
00110                 return -NLE_NOMEM;
00111 
00112         if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
00113                 nlmsg_free(msg);
00114                 return err;
00115         }
00116 
00117         *result = msg;
00118         return 0;
00119 }
00120 
00121 int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
00122                                  struct nl_msg **result)
00123 {
00124         return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
00125                                result);
00126 }
00127 
00128 int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags)
00129 {
00130         struct nl_msg *msg;
00131         int err;
00132 
00133         if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
00134                 return err;
00135 
00136         err = nl_send_auto_complete(sk, msg);
00137         nlmsg_free(msg);
00138         if (err < 0)
00139                 return err;
00140 
00141         return wait_for_ack(sk);
00142 }
00143 
00144 int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
00145                                  struct nl_msg **result)
00146 {
00147         return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
00148 }
00149 
00150 int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags)
00151 {
00152         struct nl_msg *msg;
00153         int err;
00154 
00155         if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
00156                 return err;
00157 
00158         err = nl_send_auto_complete(sk, msg);
00159         nlmsg_free(msg);
00160         if (err < 0)
00161                 return err;
00162 
00163         return wait_for_ack(sk);
00164 }
00165 
00166 /** @} */
00167 
00168 static struct nl_af_group route_groups[] = {
00169         { AF_INET,      RTNLGRP_IPV4_ROUTE },
00170         { AF_INET6,     RTNLGRP_IPV6_ROUTE },
00171         { AF_DECnet,    RTNLGRP_DECnet_ROUTE },
00172         { END_OF_GROUP_LIST },
00173 };
00174 
00175 static struct nl_cache_ops rtnl_route_ops = {
00176         .co_name                = "route/route",
00177         .co_hdrsize             = sizeof(struct rtmsg),
00178         .co_msgtypes            = {
00179                                         { RTM_NEWROUTE, NL_ACT_NEW, "new" },
00180                                         { RTM_DELROUTE, NL_ACT_DEL, "del" },
00181                                         { RTM_GETROUTE, NL_ACT_GET, "get" },
00182                                         END_OF_MSGTYPES_LIST,
00183                                   },
00184         .co_protocol            = NETLINK_ROUTE,
00185         .co_groups              = route_groups,
00186         .co_request_update      = route_request_update,
00187         .co_msg_parser          = route_msg_parser,
00188         .co_obj_ops             = &route_obj_ops,
00189 };
00190 
00191 static void __init route_init(void)
00192 {
00193         nl_cache_mngt_register(&rtnl_route_ops);
00194 }
00195 
00196 static void __exit route_exit(void)
00197 {
00198         nl_cache_mngt_unregister(&rtnl_route_ops);
00199 }
00200 
00201 /** @} */