libnl 3.0
|
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 /** @} */