Main Page | Class List | File List | Class Members | File Members

fib_rules.c

Go to the documentation of this file.
00001 /* 00002 * INET An implementation of the TCP/IP protocol suite for the LINUX 00003 * operating system. INET is implemented using the BSD Socket 00004 * interface as the means of communication with the user level. 00005 * 00006 * IPv4 Forwarding Information Base: policy rules. 00007 * 00008 * Version: $Id: fib_rules.c,v 1.17 2001/10/31 21:55:54 davem Exp $ 00009 * 00010 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 00011 * 00012 * This program is free software; you can redistribute it and/or 00013 * modify it under the terms of the GNU General Public License 00014 * as published by the Free Software Foundation; either version 00015 * 2 of the License, or (at your option) any later version. 00016 * 00017 * Fixes: 00018 * Rani Assaf : local_rule cannot be deleted 00019 * Marc Boucher : routing by fwmark 00020 */ 00021 00022 #include <linux/config.h> 00023 #include <asm/uaccess.h> 00024 #include <asm/system.h> 00025 #include <asm/bitops.h> 00026 #include <linux/types.h> 00027 #include <linux/kernel.h> 00028 #include <linux/sched.h> 00029 #include <linux/mm.h> 00030 #include <linux/string.h> 00031 #include <linux/socket.h> 00032 #include <linux/sockios.h> 00033 #include <linux/errno.h> 00034 #include <linux/in.h> 00035 #include <linux/inet.h> 00036 #include <linux/netdevice.h> 00037 #include <linux/if_arp.h> 00038 #include <linux/proc_fs.h> 00039 #include <linux/skbuff.h> 00040 #include <linux/netlink.h> 00041 #include <linux/init.h> 00042 00043 #include <net/ip.h> 00044 #include <net/protocol.h> 00045 #include <net/route.h> 00046 #include <net/tcp.h> 00047 #include <net/sock.h> 00048 #include <net/ip_fib.h> 00049 00050 #define FRprintk(a...) 00051 00052 struct fib_rule 00053 { 00054 struct fib_rule *r_next; 00055 atomic_t r_clntref; 00056 u32 r_preference; 00057 unsigned char r_table; 00058 unsigned char r_action; 00059 unsigned char r_dst_len; 00060 unsigned char r_src_len; 00061 u32 r_src; 00062 u32 r_srcmask; 00063 u32 r_dst; 00064 u32 r_dstmask; 00065 u32 r_srcmap; 00066 u8 r_flags; 00067 u8 r_tos; 00068 #ifdef CONFIG_IP_ROUTE_FWMARK 00069 u32 r_fwmark; 00070 #endif 00071 int r_ifindex; 00072 #ifdef CONFIG_NET_CLS_ROUTE 00073 __u32 r_tclassid; 00074 #endif 00075 char r_ifname[IFNAMSIZ]; 00076 int r_dead; 00077 }; 00078 00079 static struct fib_rule default_rule = { 00080 r_clntref: ATOMIC_INIT(2), 00081 r_preference: 0x7FFF, 00082 r_table: RT_TABLE_DEFAULT, 00083 r_action: RTN_UNICAST, 00084 }; 00085 00086 static struct fib_rule main_rule = { 00087 r_next: &default_rule, 00088 r_clntref: ATOMIC_INIT(2), 00089 r_preference: 0x7FFE, 00090 r_table: RT_TABLE_MAIN, 00091 r_action: RTN_UNICAST, 00092 }; 00093 00094 static struct fib_rule local_rule = { 00095 r_next: &main_rule, 00096 r_clntref: ATOMIC_INIT(2), 00097 r_table: RT_TABLE_LOCAL, 00098 r_action: RTN_UNICAST, 00099 }; 00100 00101 static struct fib_rule *fib_rules = &local_rule; 00102 static rwlock_t fib_rules_lock = RW_LOCK_UNLOCKED; 00103 00104 int inet_rtm_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 00105 { 00106 struct rtattr **rta = arg; 00107 struct rtmsg *rtm = NLMSG_DATA(nlh); 00108 struct fib_rule *r, **rp; 00109 int err = -ESRCH; 00110 00111 for (rp=&fib_rules; (r=*rp) != NULL; rp=&r->r_next) { 00112 if ((!rta[RTA_SRC-1] || memcmp(RTA_DATA(rta[RTA_SRC-1]), &r->r_src, 4) == 0) && 00113 rtm->rtm_src_len == r->r_src_len && 00114 rtm->rtm_dst_len == r->r_dst_len && 00115 (!rta[RTA_DST-1] || memcmp(RTA_DATA(rta[RTA_DST-1]), &r->r_dst, 4) == 0) && 00116 rtm->rtm_tos == r->r_tos && 00117 #ifdef CONFIG_IP_ROUTE_FWMARK 00118 (!rta[RTA_PROTOINFO-1] || memcmp(RTA_DATA(rta[RTA_PROTOINFO-1]), &r->r_fwmark, 4) == 0) && 00119 #endif 00120 (!rtm->rtm_type || rtm->rtm_type == r->r_action) && 00121 (!rta[RTA_PRIORITY-1] || memcmp(RTA_DATA(rta[RTA_PRIORITY-1]), &r->r_preference, 4) == 0) && 00122 (!rta[RTA_IIF-1] || strcmp(RTA_DATA(rta[RTA_IIF-1]), r->r_ifname) == 0) && 00123 (!rtm->rtm_table || (r && rtm->rtm_table == r->r_table))) { 00124 err = -EPERM; 00125 if (r == &local_rule) 00126 break; 00127 00128 write_lock_bh(&fib_rules_lock); 00129 *rp = r->r_next; 00130 r->r_dead = 1; 00131 write_unlock_bh(&fib_rules_lock); 00132 fib_rule_put(r); 00133 err = 0; 00134 break; 00135 } 00136 } 00137 return err; 00138 } 00139 00140 /* Allocate new unique table id */ 00141 00142 static struct fib_table *fib_empty_table(void) 00143 { 00144 int id; 00145 00146 for (id = 1; id <= RT_TABLE_MAX; id++) 00147 if (fib_tables[id] == NULL) 00148 return __fib_new_table(id); 00149 return NULL; 00150 } 00151 00152 void fib_rule_put(struct fib_rule *r) 00153 { 00154 if (atomic_dec_and_test(&r->r_clntref)) { 00155 if (r->r_dead) 00156 kfree(r); 00157 else 00158 printk("Freeing alive rule %p\n", r); 00159 } 00160 } 00161 00162 int inet_rtm_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) 00163 { 00164 struct rtattr **rta = arg; 00165 struct rtmsg *rtm = NLMSG_DATA(nlh); 00166 struct fib_rule *r, *new_r, **rp; 00167 unsigned char table_id; 00168 00169 if (rtm->rtm_src_len > 32 || rtm->rtm_dst_len > 32 || 00170 (rtm->rtm_tos & ~IPTOS_TOS_MASK)) 00171 return -EINVAL; 00172 00173 if (rta[RTA_IIF-1] && RTA_PAYLOAD(rta[RTA_IIF-1]) > IFNAMSIZ) 00174 return -EINVAL; 00175 00176 table_id = rtm->rtm_table; 00177 if (table_id == RT_TABLE_UNSPEC) { 00178 struct fib_table *table; 00179 if (rtm->rtm_type == RTN_UNICAST || rtm->rtm_type == RTN_NAT) { 00180 if ((table = fib_empty_table()) == NULL) 00181 return -ENOBUFS; 00182 table_id = table->tb_id; 00183 } 00184 } 00185 00186 new_r = kmalloc(sizeof(*new_r), GFP_KERNEL); 00187 if (!new_r) 00188 return -ENOMEM; 00189 memset(new_r, 0, sizeof(*new_r)); 00190 if (rta[RTA_SRC-1]) 00191 memcpy(&new_r->r_src, RTA_DATA(rta[RTA_SRC-1]), 4); 00192 if (rta[RTA_DST-1]) 00193 memcpy(&new_r->r_dst, RTA_DATA(rta[RTA_DST-1]), 4); 00194 if (rta[RTA_GATEWAY-1]) 00195 memcpy(&new_r->r_srcmap, RTA_DATA(rta[RTA_GATEWAY-1]), 4); 00196 new_r->r_src_len = rtm->rtm_src_len; 00197 new_r->r_dst_len = rtm->rtm_dst_len; 00198 new_r->r_srcmask = inet_make_mask(rtm->rtm_src_len); 00199 new_r->r_dstmask = inet_make_mask(rtm->rtm_dst_len); 00200 new_r->r_tos = rtm->rtm_tos; 00201 #ifdef CONFIG_IP_ROUTE_FWMARK 00202 if (rta[RTA_PROTOINFO-1]) 00203 memcpy(&new_r->r_fwmark, RTA_DATA(rta[RTA_PROTOINFO-1]), 4); 00204 #endif 00205 new_r->r_action = rtm->rtm_type; 00206 new_r->r_flags = rtm->rtm_flags; 00207 if (rta[RTA_PRIORITY-1]) 00208 memcpy(&new_r->r_preference, RTA_DATA(rta[RTA_PRIORITY-1]), 4); 00209 new_r->r_table = table_id; 00210 if (rta[RTA_IIF-1]) { 00211 struct net_device *dev; 00212 memcpy(new_r->r_ifname, RTA_DATA(rta[RTA_IIF-1]), IFNAMSIZ); 00213 new_r->r_ifname[IFNAMSIZ-1] = 0; 00214 new_r->r_ifindex = -1; 00215 dev = __dev_get_by_name(new_r->r_ifname); 00216 if (dev) 00217 new_r->r_ifindex = dev->ifindex; 00218 } 00219 #ifdef CONFIG_NET_CLS_ROUTE 00220 if (rta[RTA_FLOW-1]) 00221 memcpy(&new_r->r_tclassid, RTA_DATA(rta[RTA_FLOW-1]), 4); 00222 #endif 00223 00224 rp = &fib_rules; 00225 if (!new_r->r_preference) { 00226 r = fib_rules; 00227 if (r && (r = r->r_next) != NULL) { 00228 rp = &fib_rules->r_next; 00229 if (r->r_preference) 00230 new_r->r_preference = r->r_preference - 1; 00231 } 00232 } 00233 00234 while ( (r = *rp) != NULL ) { 00235 if (r->r_preference > new_r->r_preference) 00236 break; 00237 rp = &r->r_next; 00238 } 00239 00240 new_r->r_next = r; 00241 atomic_inc(&new_r->r_clntref); 00242 write_lock_bh(&fib_rules_lock); 00243 *rp = new_r; 00244 write_unlock_bh(&fib_rules_lock); 00245 return 0; 00246 } 00247 00248 u32 fib_rules_map_destination(u32 daddr, struct fib_result *res) 00249 { 00250 u32 mask = inet_make_mask(res->prefixlen); 00251 return (daddr&~mask)|res->fi->fib_nh->nh_gw; 00252 } 00253 00254 u32 fib_rules_policy(u32 saddr, struct fib_result *res, unsigned *flags) 00255 { 00256 struct fib_rule *r = res->r; 00257 00258 if (r->r_action == RTN_NAT) { 00259 int addrtype = inet_addr_type(r->r_srcmap); 00260 00261 if (addrtype == RTN_NAT) { 00262 /* Packet is from translated source; remember it */ 00263 saddr = (saddr&~r->r_srcmask)|r->r_srcmap; 00264 *flags |= RTCF_SNAT; 00265 } else if (addrtype == RTN_LOCAL || r->r_srcmap == 0) { 00266 /* Packet is from masqueraded source; remember it */ 00267 saddr = r->r_srcmap; 00268 *flags |= RTCF_MASQ; 00269 } 00270 } 00271 return saddr; 00272 } 00273 00274 #ifdef CONFIG_NET_CLS_ROUTE 00275 u32 fib_rules_tclass(struct fib_result *res) 00276 { 00277 if (res->r) 00278 return res->r->r_tclassid; 00279 return 0; 00280 } 00281 #endif 00282 00283 00284 static void fib_rules_detach(struct net_device *dev) 00285 { 00286 struct fib_rule *r; 00287 00288 for (r=fib_rules; r; r=r->r_next) { 00289 if (r->r_ifindex == dev->ifindex) { 00290 write_lock_bh(&fib_rules_lock); 00291 r->r_ifindex = -1; 00292 write_unlock_bh(&fib_rules_lock); 00293 } 00294 } 00295 } 00296 00297 static void fib_rules_attach(struct net_device *dev) 00298 { 00299 struct fib_rule *r; 00300 00301 for (r=fib_rules; r; r=r->r_next) { 00302 if (r->r_ifindex == -1 && strcmp(dev->name, r->r_ifname) == 0) { 00303 write_lock_bh(&fib_rules_lock); 00304 r->r_ifindex = dev->ifindex; 00305 write_unlock_bh(&fib_rules_lock); 00306 } 00307 } 00308 } 00309 00310 int fib_lookup(const struct rt_key *key, struct fib_result *res) 00311 { 00312 int err; 00313 struct fib_rule *r, *policy; 00314 struct fib_table *tb; 00315 00316 u32 daddr = key->dst; 00317 u32 saddr = key->src; 00318 00319 FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", 00320 NIPQUAD(key->dst), NIPQUAD(key->src)); 00321 read_lock(&fib_rules_lock); 00322 for (r = fib_rules; r; r=r->r_next) { 00323 if (((saddr^r->r_src) & r->r_srcmask) || 00324 ((daddr^r->r_dst) & r->r_dstmask) || 00325 #ifdef CONFIG_IP_ROUTE_TOS 00326 (r->r_tos && r->r_tos != key->tos) || 00327 #endif 00328 #ifdef CONFIG_IP_ROUTE_FWMARK 00329 (r->r_fwmark && r->r_fwmark != key->fwmark) || 00330 #endif 00331 (r->r_ifindex && r->r_ifindex != key->iif)) 00332 continue; 00333 00334 FRprintk("tb %d r %d ", r->r_table, r->r_action); 00335 switch (r->r_action) { 00336 case RTN_UNICAST: 00337 case RTN_NAT: 00338 policy = r; 00339 break; 00340 case RTN_UNREACHABLE: 00341 read_unlock(&fib_rules_lock); 00342 return -ENETUNREACH; 00343 default: 00344 case RTN_BLACKHOLE: 00345 read_unlock(&fib_rules_lock); 00346 return -EINVAL; 00347 case RTN_PROHIBIT: 00348 read_unlock(&fib_rules_lock); 00349 return -EACCES; 00350 } 00351 00352 if ((tb = fib_get_table(r->r_table)) == NULL) 00353 continue; 00354 err = tb->tb_lookup(tb, key, res); 00355 if (err == 0) { 00356 res->r = policy; 00357 if (policy) 00358 atomic_inc(&policy->r_clntref); 00359 read_unlock(&fib_rules_lock); 00360 return 0; 00361 } 00362 if (err < 0 && err != -EAGAIN) { 00363 read_unlock(&fib_rules_lock); 00364 return err; 00365 } 00366 } 00367 FRprintk("FAILURE\n"); 00368 read_unlock(&fib_rules_lock); 00369 return -ENETUNREACH; 00370 } 00371 00372 void fib_select_default(const struct rt_key *key, struct fib_result *res) 00373 { 00374 if (res->r && res->r->r_action == RTN_UNICAST && 00375 FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) { 00376 struct fib_table *tb; 00377 if ((tb = fib_get_table(res->r->r_table)) != NULL) 00378 tb->tb_select_default(tb, key, res); 00379 } 00380 } 00381 00382 static int fib_rules_event(struct notifier_block *this, unsigned long event, void *ptr) 00383 { 00384 struct net_device *dev = ptr; 00385 00386 if (event == NETDEV_UNREGISTER) 00387 fib_rules_detach(dev); 00388 else if (event == NETDEV_REGISTER) 00389 fib_rules_attach(dev); 00390 return NOTIFY_DONE; 00391 } 00392 00393 00394 struct notifier_block fib_rules_notifier = { 00395 notifier_call: fib_rules_event, 00396 }; 00397 00398 static __inline__ int inet_fill_rule(struct sk_buff *skb, 00399 struct fib_rule *r, 00400 struct netlink_callback *cb) 00401 { 00402 struct rtmsg *rtm; 00403 struct nlmsghdr *nlh; 00404 unsigned char *b = skb->tail; 00405 00406 nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm)); 00407 rtm = NLMSG_DATA(nlh); 00408 rtm->rtm_family = AF_INET; 00409 rtm->rtm_dst_len = r->r_dst_len; 00410 rtm->rtm_src_len = r->r_src_len; 00411 rtm->rtm_tos = r->r_tos; 00412 #ifdef CONFIG_IP_ROUTE_FWMARK 00413 if (r->r_fwmark) 00414 RTA_PUT(skb, RTA_PROTOINFO, 4, &r->r_fwmark); 00415 #endif 00416 rtm->rtm_table = r->r_table; 00417 rtm->rtm_protocol = 0; 00418 rtm->rtm_scope = 0; 00419 rtm->rtm_type = r->r_action; 00420 rtm->rtm_flags = r->r_flags; 00421 00422 if (r->r_dst_len) 00423 RTA_PUT(skb, RTA_DST, 4, &r->r_dst); 00424 if (r->r_src_len) 00425 RTA_PUT(skb, RTA_SRC, 4, &r->r_src); 00426 if (r->r_ifname[0]) 00427 RTA_PUT(skb, RTA_IIF, IFNAMSIZ, &r->r_ifname); 00428 if (r->r_preference) 00429 RTA_PUT(skb, RTA_PRIORITY, 4, &r->r_preference); 00430 if (r->r_srcmap) 00431 RTA_PUT(skb, RTA_GATEWAY, 4, &r->r_srcmap); 00432 #ifdef CONFIG_NET_CLS_ROUTE 00433 if (r->r_tclassid) 00434 RTA_PUT(skb, RTA_FLOW, 4, &r->r_tclassid); 00435 #endif 00436 nlh->nlmsg_len = skb->tail - b; 00437 return skb->len; 00438 00439 nlmsg_failure: 00440 rtattr_failure: 00441 skb_put(skb, b - skb->tail); 00442 return -1; 00443 } 00444 00445 int inet_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 00446 { 00447 int idx; 00448 int s_idx = cb->args[0]; 00449 struct fib_rule *r; 00450 00451 read_lock(&fib_rules_lock); 00452 for (r=fib_rules, idx=0; r; r = r->r_next, idx++) { 00453 if (idx < s_idx) 00454 continue; 00455 if (inet_fill_rule(skb, r, cb) < 0) 00456 break; 00457 } 00458 read_unlock(&fib_rules_lock); 00459 cb->args[0] = idx; 00460 00461 return skb->len; 00462 } 00463 00464 void __init fib_rules_init(void) 00465 { 00466 register_netdevice_notifier(&fib_rules_notifier); 00467 }

Generated on Wed Dec 1 21:25:30 2004 for Linux 2.4.23 Networking by doxygen 1.3.8