?? route.generic
字號(hào):
+ return -EINVAL;+ }++ /* INTERFACE */+ /* Store the interface information to allow users to get it via+ * [SOL_IP, IP_PKTINFO] conrol message for locally seen packets+ * (including broadcast and multicast ones). --SAW */+ rth->rt_iif = key->oif ? : dev_out->ifindex;+ /* Set output device */+ rth->u.dst.dev = dev_out;+ dev_hold(dev_out);++ /* Set GATEWAY */+ rth->rt_gateway = daddr;+ /* if res->fi != NULL set the real gateway */+ rt_set_nexthop(rth, res, 0);++ rth->rt_flags = flags;++ hash = rt_hash_code(key->dst, key->src^(key->oif<<5), key->tos);+ return rt_intern_hash(hash, rth, rp);+}+ /* * Major route resolver routine. */- int ip_route_output_slow(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif) { struct rt_key key; struct fib_result res;- unsigned flags = 0;- struct rtable *rth; struct net_device *dev_out = NULL;- unsigned hash;- int free_res = 0; int err; - tos &= IPTOS_TOS_MASK|RTO_ONLINK; key.dst = daddr; key.src = saddr; key.tos = tos&IPTOS_TOS_MASK;@@ -1619,252 +1792,100 @@ res.r = NULL; #endif - if (saddr) {- if (MULTICAST(saddr) || BADCLASS(saddr) || ZERONET(saddr))- return -EINVAL;-- /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */- dev_out = ip_dev_find(saddr);- if (dev_out == NULL)- return -EINVAL;-- /* I removed check for oif == dev_out->oif here.- It was wrong by three reasons:- 1. ip_dev_find(saddr) can return wrong iface, if saddr is- assigned to multiple interfaces.- 2. Moreover, we are allowed to send packets with saddr- of another iface. --ANK- */-- if (oif == 0 &&- (MULTICAST(daddr) || daddr == 0xFFFFFFFF)) {- /* Special hack: user can direct multicasts- and limited broadcast via necessary interface- without fiddling with IP_MULTICAST_IF or IP_PKTINFO.- This hack is not just for fun, it allows- vic,vat and friends to work.- They bind socket to loopback, set ttl to zero- and expect that it will work.- From the viewpoint of routing cache they are broken,- because we are not allowed to build multicast path- with loopback source addr (look, routing cache- cannot know, that ttl is zero, so that packet- will not leave this host and route is valid).- Luckily, this hack is good workaround.- */-- key.oif = dev_out->ifindex;- goto make_route;- }- if (dev_out)- dev_put(dev_out);- dev_out = NULL;- }- if (oif) {- dev_out = dev_get_by_index(oif);- if (dev_out == NULL)- return -ENODEV;- if (__in_dev_get(dev_out) == NULL) {- dev_put(dev_out);- return -ENODEV; /* Wrong error code */- }-- if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF) {- if (!key.src)- key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);- goto make_route;- }- if (!key.src) {- if (MULTICAST(daddr))- key.src = inet_select_addr(dev_out, 0, key.scope);- else if (!daddr)- key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);- }- }+ if (!daddr)+ goto dest_insanity; - if (!key.dst) {- key.dst = key.src;- if (!key.dst)- key.dst = key.src = htonl(INADDR_LOOPBACK);- if (dev_out)- dev_put(dev_out);- dev_out = &loopback_dev;+ err = fib_lookup(&key, &res);+ if (!err) {+ dev_out = FIB_RES_DEV(res); dev_hold(dev_out);- key.oif = loopback_dev.ifindex;- res.type = RTN_LOCAL;- flags |= RTCF_LOCAL;- goto make_route;- }-- if (fib_lookup(&key, &res)) {- res.fi = NULL;- if (oif) {- /* Apparently, routing tables are wrong. Assume,- that the destination is on link.-- WHY? DW.- Because we are allowed to send to iface- even if it has NO routes and NO assigned- addresses. When oif is specified, routing- tables are looked up with only one purpose:- to catch if destination is gatewayed, rather than- direct. Moreover, if MSG_DONTROUTE is set,- we send packet, ignoring both routing tables- and ifaddr state. --ANK--- We could make it even if oif is unknown,- likely IPv6, but we do not.+ if (saddr) {+ /* Verify user supplied source address */+ err = outrt_check_src(saddr, daddr, tos, dev_out);+ } else {+ /* Obtain path source from routing table */+ saddr = FIB_RES_PREFSRC(res);+ /* We don't verify source address obtained from routing+ * table. It's a task of administrators to keep it+ * sane. */-- if (key.src == 0)- key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);- res.type = RTN_UNICAST;- goto make_route; }- if (dev_out)- dev_put(dev_out);- return -ENETUNREACH;- }- free_res = 1;-- if (res.type == RTN_NAT)- goto e_inval;-- if (res.type == RTN_LOCAL) {- if (!key.src)- key.src = key.dst;- if (dev_out)- dev_put(dev_out);- dev_out = &loopback_dev;- dev_hold(dev_out);- key.oif = dev_out->ifindex;- if (res.fi)- fib_info_put(res.fi);- res.fi = NULL;- flags |= RTCF_LOCAL;- goto make_route;- }--#ifdef CONFIG_IP_ROUTE_MULTIPATH- if (res.fi->fib_nhs > 1 && key.oif == 0)- fib_select_multipath(&key, &res);- else-#endif- if (res.prefixlen==0 && res.type == RTN_UNICAST && key.oif == 0)- fib_select_default(&key, &res);-- if (!key.src)- key.src = FIB_RES_PREFSRC(res);-- if (dev_out)- dev_put(dev_out);- dev_out = FIB_RES_DEV(res);- dev_hold(dev_out);- key.oif = dev_out->ifindex;--make_route:- if (LOOPBACK(key.src) && !(dev_out->flags&IFF_LOOPBACK))- goto e_inval;-- if (key.dst == 0xFFFFFFFF)- res.type = RTN_BROADCAST;- else if (MULTICAST(key.dst))- res.type = RTN_MULTICAST;- else if (BADCLASS(key.dst) || ZERONET(key.dst))- goto e_inval;+ if (!err)+ err = outrt_make_route(rp, &key, daddr, saddr,+ dev_out, &res);+ fib_res_put(&res);+ /* The usual code path ends here */ - if (dev_out->flags&IFF_LOOPBACK)- flags |= RTCF_LOCAL;+ } else if (err == -ENETUNREACH) { - if (res.type == RTN_BROADCAST) {- flags |= RTCF_BROADCAST|RTCF_LOCAL;- if (res.fi) {- fib_info_put(res.fi);- res.fi = NULL;- }- } else if (res.type == RTN_MULTICAST) {- flags |= RTCF_MULTICAST|RTCF_LOCAL;- read_lock(&inetdev_lock);- if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), daddr))- flags &= ~RTCF_LOCAL;- read_unlock(&inetdev_lock);- /* If multicast route do not exist use- default one, but do not gateway in this case.- Yes, it is hack.+ /* Just return if the access is prohibited etc.+ If the routing table doesn't have both an appropriate route+ and a default assume that the destination is on link. --SAW++ WHY? DW.+ Because we are allowed to send to iface+ even if it has NO routes and NO assigned+ addresses. When oif is specified, routing+ tables are looked up with only one purpose:+ to catch if destination is gatewayed, rather than+ direct. Moreover, if MSG_DONTROUTE is set,+ we send packet, ignoring both routing tables+ and ifaddr state. --ANK++ We could make it even if oif is unknown,+ likely IPv6, but we do not.++ The above statements aren't exactly correct.+ Routing tables contain a lot of useful information (like+ preferred source, for instance). But the general idea is+ right. --SAW */- if (res.fi && res.prefixlen < 4) {- fib_info_put(res.fi);- res.fi = NULL;- }- }-- rth = dst_alloc(&ipv4_dst_ops);- if (!rth)- goto e_nobufs;-- atomic_set(&rth->u.dst.__refcnt, 1);- rth->u.dst.flags= DST_HOST;- rth->key.dst = daddr;- rth->key.tos = tos;- rth->key.src = saddr;- rth->key.iif = 0;- rth->key.oif = oif;- rth->rt_dst = key.dst;- rth->rt_src = key.src;-#ifdef CONFIG_IP_ROUTE_NAT- rth->rt_dst_map = key.dst;- rth->rt_src_map = key.src;-#endif- rth->rt_iif = oif ? : dev_out->ifindex;- rth->u.dst.dev = dev_out;- dev_hold(dev_out);- rth->rt_gateway = key.dst;- rth->rt_spec_dst= key.src;-- rth->u.dst.output=ip_output;-- if (flags&RTCF_LOCAL) {- rth->u.dst.input = ip_local_deliver;- rth->rt_spec_dst = key.dst;- }- if (flags&(RTCF_BROADCAST|RTCF_MULTICAST)) {- rth->rt_spec_dst = key.src;- if (flags&RTCF_LOCAL && !(dev_out->flags&IFF_LOOPBACK))- rth->u.dst.output = ip_mc_output;-#ifdef CONFIG_IP_MROUTE- if (res.type == RTN_MULTICAST) {- struct in_device *in_dev = in_dev_get(dev_out);- if (in_dev) {- if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(daddr)) {- rth->u.dst.input = ip_mr_input;- rth->u.dst.output = ip_mc_output;- }- in_dev_put(in_dev);+ if (oif) {+ err = -ENODEV;+ dev_out = dev_get_by_index(oif);+ if (dev_out == NULL)+ goto out;+ if (__in_dev_get(dev_out) == NULL)+ goto out; /* Wrong error code */+ if (saddr) {+ /* Verify user supplied source address */+ err = outrt_check_src(saddr, daddr, tos, dev_out);+ if (err)+ goto out;+ } else {+ int scope;+ if (LOCAL_MCAST(daddr) || daddr == 0xFFFFFFFF)+ scope = RT_SCOPE_LINK;+ else if (MULTICAST(daddr))+ scope = key.scope;+ else+ scope = RT_SCOPE_HOST;+ saddr = inet_select_addr(dev_out, 0, scope); }- }-#endif+ res.type = RTN_UNICAST;+ res.fi = NULL;+ err = outrt_make_route(rp, &key, daddr, saddr, dev_out,+ &res);+ } else+ err = -ENETUNREACH; }-- rt_set_nexthop(rth, &res, 0);-- rth->rt_flags = flags;-- hash = rt_hash_code(daddr, saddr^(oif<<5), tos);- err = rt_intern_hash(hash, rth, rp);-done:- if (free_res)- fib_res_put(&res);+out: if (dev_out) dev_put(dev_out); return err; -e_inval:- err = -EINVAL;- goto done;-e_nobufs:- err = -ENOBUFS;- goto done;+ /* I don't know what reason this hack was for */+dest_insanity:+ daddr = saddr;+ if (!daddr)+ daddr = saddr = htonl(INADDR_LOOPBACK);+ dev_out = &loopback_dev;+ dev_hold(dev_out);+ key.oif = loopback_dev.ifindex;+ res.type = RTN_LOCAL;+ res.fi = NULL;+ err = outrt_make_route(rp, &key, daddr, saddr, dev_out, &res);+ goto out; } int ip_route_output(struct rtable **rp, u32 daddr, u32 saddr, u32 tos, int oif)
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -