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