libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/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  * @arg result          Result pointer
00068  *
00069  * Allocates a new cache, initializes it properly and updates it to
00070  * contain all routes currently configured in the kernel.
00071  *
00072  * @note The caller is responsible for destroying and freeing the
00073  *       cache after using it.
00074  * @return 0 on success or a negative error code.
00075  */
00076 int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags,
00077                            struct nl_cache **result)
00078 {
00079         struct nl_cache *cache;
00080         int err;
00081 
00082         if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
00083                 return -NLE_NOMEM;
00084 
00085         cache->c_iarg1 = family;
00086         cache->c_iarg2 = flags;
00087 
00088         if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
00089                 free(cache);
00090                 return err;
00091         }
00092 
00093         *result = cache;
00094         return 0;
00095 }
00096 
00097 /** @} */
00098 
00099 /**
00100  * @name Route Addition
00101  * @{
00102  */
00103 
00104 static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
00105                            struct nl_msg **result)
00106 {
00107         struct nl_msg *msg;
00108         int err;
00109 
00110         if (!(msg = nlmsg_alloc_simple(cmd, flags)))
00111                 return -NLE_NOMEM;
00112 
00113         if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
00114                 nlmsg_free(msg);
00115                 return err;
00116         }
00117 
00118         *result = msg;
00119         return 0;
00120 }
00121 
00122 int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
00123                                  struct nl_msg **result)
00124 {
00125         return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
00126                                result);
00127 }
00128 
00129 int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags)
00130 {
00131         struct nl_msg *msg;
00132         int err;
00133 
00134         if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
00135                 return err;
00136 
00137         err = nl_send_auto_complete(sk, msg);
00138         nlmsg_free(msg);
00139         if (err < 0)
00140                 return err;
00141 
00142         return wait_for_ack(sk);
00143 }
00144 
00145 int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
00146                                  struct nl_msg **result)
00147 {
00148         return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
00149 }
00150 
00151 int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags)
00152 {
00153         struct nl_msg *msg;
00154         int err;
00155 
00156         if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
00157                 return err;
00158 
00159         err = nl_send_auto_complete(sk, msg);
00160         nlmsg_free(msg);
00161         if (err < 0)
00162                 return err;
00163 
00164         return wait_for_ack(sk);
00165 }
00166 
00167 /** @} */
00168 
00169 static struct nl_af_group route_groups[] = {
00170         { AF_INET,      RTNLGRP_IPV4_ROUTE },
00171         { AF_INET6,     RTNLGRP_IPV6_ROUTE },
00172         { AF_DECnet,    RTNLGRP_DECnet_ROUTE },
00173         { END_OF_GROUP_LIST },
00174 };
00175 
00176 static struct nl_cache_ops rtnl_route_ops = {
00177         .co_name                = "route/route",
00178         .co_hdrsize             = sizeof(struct rtmsg),
00179         .co_msgtypes            = {
00180                                         { RTM_NEWROUTE, NL_ACT_NEW, "new" },
00181                                         { RTM_DELROUTE, NL_ACT_DEL, "del" },
00182                                         { RTM_GETROUTE, NL_ACT_GET, "get" },
00183                                         END_OF_MSGTYPES_LIST,
00184                                   },
00185         .co_protocol            = NETLINK_ROUTE,
00186         .co_groups              = route_groups,
00187         .co_request_update      = route_request_update,
00188         .co_msg_parser          = route_msg_parser,
00189         .co_obj_ops             = &route_obj_ops,
00190 };
00191 
00192 static void __init route_init(void)
00193 {
00194         nl_cache_mngt_register(&rtnl_route_ops);
00195 }
00196 
00197 static void __exit route_exit(void)
00198 {
00199         nl_cache_mngt_unregister(&rtnl_route_ops);
00200 }
00201 
00202 /** @} */