diff options
author | Roland McGrath <roland@gnu.org> | 2000-02-04 06:32:39 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2000-02-04 06:32:39 +0000 |
commit | db9a26cbd125ec106e040ea6084911f9bc0c0198 (patch) | |
tree | 8394aedf0addf9de2afd46d00c192d20d9eb9092 /pfinet/linux-inet/route.c | |
parent | 8880a73970b23f10c720011cb910c0e0e1e02975 (diff) | |
download | hurd-db9a26cbd125ec106e040ea6084911f9bc0c0198.tar.gz hurd-db9a26cbd125ec106e040ea6084911f9bc0c0198.tar.bz2 hurd-db9a26cbd125ec106e040ea6084911f9bc0c0198.zip |
2000-02-03 Roland McGrath <roland@baalperazim.frob.com>
Complete overhaul of pfinet based on the IPv4 networking code from the
Linux 2.2.12 kernel sources. This page describes a single unified set
of interdependent changes, but there are so many changes that I have
broken up the log entry into paragraphs based on rough topical
divisions of the work involved.
Subset of verbatim Linux 2.2.12 sources imported on a vendor branch.
* linux-src: New directory, see README for details.
* README: New file, describes linux-src layout and procedures for
tracking Linux source updates.
Light modifications to linux-src files to avoid really bending over
backwards with the glue macros. All modifications to files in
linux-src are conditionalized by #ifdef _HURD_.
* linux-src/include/linux/net.h [_HURD_] (struct socket): New members
refcnt and identity; elide members fasync_list, file.
* linux-src/include/linux/rtnetlink.h [! CONFIG_RTNETLINK]
(rtnl_shlock, rtnl_shunlock) [! _HURD_]: Conditionalize contents on
this, making these no-ops #ifdef _HURD_.
* linux-src/net/core/dev.c [_HURD_] (dev_ioctl): Don't define the
function, instead #define it to 0.
* linux-src/net/ipv4/af_inet.c [_HURD_] (inet_ioctl): Likewise.
* linux-src/net/ipv4/arp.c [_HURD_] (arp_ioctl): Likewise.
* linux-src/net/ipv4/udp.c [_HURD_] (udp_ioctl): Likewise.
* linux-src/net/ipv4/tcp.c [_HURD_] (tcp_ioctl): Likewise.
[_HURD_] (tcp_tiocinq): New function, TIOCINQ code from tcp_ioctl.
* linux-src/net/ipv4/devinet.c [_HURD_] (devinet_ioctl): Don't define
the function, instead #define it to 0.
[_HURD_] (configure_device): New function, cobbled from SIOCSIFADDR
and SIOCSIFNETMASK code from devinet_ioctl.
* glue-include/asm, glue-include/linux: New directories.
These contain glue kludge headers that replace all of the
Linux <asm/*.h> headers except checksum.h, and several of
the Linux <linux/*.h> headers (the remainder come from
linux-src/include/linux and are mostly unmodified).
* glue-include/asm/atomic.h: New file, glue replacement header.
* glue-include/asm/bitops.h: New file, glue replacement header.
* glue-include/asm/byteorder.h: New file, glue replacement header.
* glue-include/asm/checksum.h: New file, glue replacement header.
* glue-include/asm/errno.h: New file, glue replacement header.
* glue-include/asm/hardirq.h: New file, glue replacement header.
* glue-include/asm/init.h: New file, glue replacement header.
* glue-include/asm/segment.h: New file, glue replacement header.
* glue-include/asm/spinlock.h: New file, glue replacement header.
* glue-include/asm/system.h: New file, glue replacement header.
* glue-include/asm/types.h: New file, glue replacement header.
* glue-include/asm/uaccess.h: New file, glue replacement header.
* glue-include/linux/autoconf.h: New file, glue replacement header.
* glue-include/linux/binfmts.h: New file, glue replacement header.
* glue-include/linux/config.h: New file, glue replacement header.
* glue-include/linux/errno.h: New file, glue replacement header.
* glue-include/linux/fcntl.h: New file, glue replacement header.
* glue-include/linux/fs.h: New file, glue replacement header.
* glue-include/linux/in.h: New file, glue replacement header.
* glue-include/linux/in6.h: New file, glue replacement header.
* glue-include/linux/interrupt.h: New file, glue replacement header.
* glue-include/linux/ioctl.h: New file, glue replacement header.
* glue-include/linux/ipv6.h: New file, glue replacement header.
* glue-include/linux/kernel.h: New file, glue replacement header.
* glue-include/linux/limits.h: New file, glue replacement header.
* glue-include/linux/major.h: New file, glue replacement header.
* glue-include/linux/malloc.h: New file, glue replacement header.
* glue-include/linux/mm.h: New file, glue replacement header.
* glue-include/linux/param.h: New file, glue replacement header.
* glue-include/linux/personality.h: New file, glue replacement header.
* glue-include/linux/poll.h: New file, glue replacement header.
* glue-include/linux/proc_fs.h: New file, glue replacement header.
* glue-include/linux/sched.h: New file, glue replacement header.
* glue-include/linux/slab.h: New file, glue replacement header.
* glue-include/linux/socket.h: New file, glue replacement header.
* glue-include/linux/sockios.h: New file, glue replacement header.
* glue-include/linux/stat.h: New file, glue replacement header.
* glue-include/linux/string.h: New file, glue replacement header.
* glue-include/linux/termios.h: New file, glue replacement header.
* glue-include/linux/time.h: New file, glue replacement header.
* glue-include/linux/timer.h: New file, glue replacement header.
* glue-include/linux/timex.h: New file, glue replacement header.
* glue-include/linux/types.h: New file, glue replacement header.
* glue-include/linux/un.h: New file, glue replacement header.
* glue-include/linux/version.h: New file, glue replacement header.
* glue-include/linux/wait.h: New file, glue replacement header.
* kmem_cache.c: New file. Glue code replaces Linux kmem_cache_t et al.
* stubs.c: New file. No-op functions and stub variables for a few
things the Linux networking code needs to link.
* Makefile (core-srcs, arch-lib-srcs, ethernet-srcs, ipv4-srcs): New
variables, listing sources used from linux-src subdirectories.
(LINUXSRCS): Define using those.
(SRCS): Remove devices.c; add kmem_cache.c, stubs.c.
(UNUSEDSRC): Variable removed.
(vpath %.c): Remove vpath for $(srcdir)/linux-inet directory.
Add vpaths for $(srcdir)/linux-src subdirectories.
(CPPFLAGS): Add -D_HURD_SYSTYPE defining it to $(asm_syntax) as a
double-quoted string. Add -I's for glue-include and linux-src/include.
* pfinet.h: Include <sys/socket.h>, and not <linux/netdevice.h>.
(master_device): Remove decl.
(global_lock, packet_queue_lock): Remove common defns.
(global_lock, net_bh_lock): Declare them as externs.
(struct sockaddr): Remove len member, make address member just a
struct sockaddr rather than a 0-length array.
(setup_loopback_device, become_task_protid, become_task): Remove decls.
(ethernet_initialize): Declare it.
(input_work_thread): Remove decl.
(net_bh_thread): Declare it.
(tcp_readable): Remove decl.
(tcp_tiocinq): Declare it.
* config.h: Rewritten based on Linux 2.2.12 set of CONFIG_* options.
(CONFIG_NET, CONFIG_INET, CONFIG_SKB_LARGE): These are the only
Linux config options we set.
(CONFIG_IP_NOSIOCRT): New macro (not a proper config option, but
used conveniently in the code).
* ethernet.c (ethernet_set_multi): Take only one parameter.
Remove assert, since we always get passed IGMP_ALL_HOSTS.
(ethernet_thread): Make static.
(ethernet_demuxer): Use __mutex_lock in place of mutex_lock, so as to
get cthreads instead of linux/spinlock.h glue macros. Lock
net_bh_lock instead of global_lock. Set SKB->protocol with
eth_type_trans before calling netif_rx.
(ethernet_initialize): New function, one-time initialization broken
out of ethernet_open.
(ethernet_open): Ports setup moved to ethernet_initialize.
Don't use `errno' to avoid glue conflicts.
Use get_privileged_ports here to get the master device port, and
deallocate it after calling device_open.
(ethernet_xmit): Use assert_perror. Only one arg to dev_kfree_skb now.
(setup_ethernet_device): Change initializations for structure changes.
Call dev_init_buffers and register_netdevice on the device.
* timer-emul.c (all functions): Use __mutex_lock instead of mutex_lock.
Adjust for renaming of `prevp' member to `prev' in struct timer_list.
(mod_timer): New function.
* socket.c (proto_ops): Variable removed.
(net_families): New variable replaces it.
(sock_register): Rewritten for new calling convention, set
net_families rather than proto_ops.
(make_sock_user, clean_socketport, sock_alloc, sock_release):
Functions moved here from misc.c.
* sched.c (packet_queue_lock): Variable removed.
(net_bh_lock, net_bh_wakeup): New variables.
(current): Variable removed (now a macro in the glue headers).
(interruptible_sleep_on, wake_up_interruptible): Functions removed.
They are replaced by inlines in the glue headers.
(become_task, become_task_protid): Functions removed; they are
replaced by macros in glue-include/linux/sched.h.
(net_bh_worker): New function.
* loopback.c: Completely rewritten, mostly copied from linux-2.2.12's
drivers/net/loopback.c source file.
* io-ops.c (all functions): Use __mutex_lock in place of mutex_lock.
(S_io_write): Call ops->sendmsg instead of ops->write,
which no longer exists. If O_NONBLOCK is set, set MSG_DONTWAIT in
msg_flags.
(S_io_read): Call ops->recvmsg instead of ops->read,
which no longer exists If O_NONBLOCK is set, pass MSG_DONTWAIT.
(S_io_readable): Use USER->sock->data in place of USER->sock->sk.
For SOCK_STREAM and SOCK_SEQPACKET types, call tcp_tiocinq.
(S_io_set_all_openmodes, S_io_get_openmodes, S_io_set_some_openmodes,
S_io_clear_some_openmodes): Member USER->sock->userflags is now
renamed USER->sock->flags.
(S_io_select): Completely rewritten using ops->poll.
(select_wait): Function removed.
(S_io_stat): Set st_mode to reflect S_IFSOCK.
* socket-ops.c (all functions): Use __mutex_lock instead of mutex_lock.
(S_socket_create): Don't set SOCK->ops or call SOCK->ops->create.
Instead, call net_families[PF_INET]->create.
(S_socket_listen): Remove extra checks; just call ops->listen.
(S_socket_accept): Remove extra checks before ops->accept call.
Avoid use of goto.
(S_socket_connect): Remove extra checks; just call ops->connect.
(S_socket_bind): Adjust for struct sock_addr changes.
(S_socket_create_address): Likewise.
(S_socket_whatis_address): Likewise.
(S_socket_connect2): Don't diddle data structures after
ops->socketpair call.
(S_socket_getopt): Use sock_getsockopt if LEVEL is SOL_SOCKET.
Accept any data size, not just sizeof (int).
(S_socket_setopt): Use sock_setsockopt if LEVEL is SOL_SOCKET.
(S_socket_send): Always use ops->sendmsg instead of ops->send or
ops->sendto, which no longer exist. If O_NONBLOCK is set, set
MSG_DONTWAIT in msg_flags.
(S_socket_recv): Always use ops->recvmsg instead of ops->recv, which
no longer exists. If O_NONBLOCK is set, set MSG_DONTWAIT in flags.
Check for error from S_socket_create_address.
* main.c (find_device): Don't try to set ether_dev.pa_mask (it's gone).
(main): Don't call init_devices. Call ethernet_initialize.
Start net_bh_worker instead of input_work_thread. Don't call
setup_loopback_device. Instead, take global_lock, do prepare_current,
and then call sk_init, skb_init, inet_proto_init, and net_dev_init.
Keep global_lock held while calling argp_parse.
Call arrange_shutdown_notification only after all that.
Fix error call for "contacting parent" to pass ERR instead of errno.
* options.c (ADDR): #undef before defining macro.
(parse_opt): #if 0 out EDESTADDRREQ check (I don't understand it).
To apply settings, call configure_devices.
(ADD_ADDR_OPT): #if 0 --address and --netmask options. Needs fixed.
* misc.c (make_sock_user, clean_socketport, sock_alloc, sock_release):
Functions moved to socket.c.
(sock_release_peer): Function removed.
(make_sockaddr_port): Use struct sockaddr_storage to size buffer.
Fix size calculation for new struct sock_addr layout.
Initialize sa_family and sa_len of new struct sock_addr.
Remove the old Linux (2.0.??) network stack and the glue code for it.
* linux-inet, asm, linux: Directories and all files removed.
Some of the new files in glue-include came from the old glue headers
in the asm and linux directories, but most were substantially modified.
* devices.c: File removed. The equivalent glue is now elsewhere.
Diffstat (limited to 'pfinet/linux-inet/route.c')
-rw-r--r-- | pfinet/linux-inet/route.c | 684 |
1 files changed, 0 insertions, 684 deletions
diff --git a/pfinet/linux-inet/route.c b/pfinet/linux-inet/route.c deleted file mode 100644 index ce06dcfe..00000000 --- a/pfinet/linux-inet/route.c +++ /dev/null @@ -1,684 +0,0 @@ -/* - * INET An implementation of the TCP/IP protocol suite for the LINUX - * operating system. INET is implemented using the BSD Socket - * interface as the means of communication with the user level. - * - * ROUTE - implementation of the IP router. - * - * Version: @(#)route.c 1.0.14 05/31/93 - * - * Authors: Ross Biro, <bir7@leland.Stanford.Edu> - * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> - * Alan Cox, <gw4pts@gw4pts.ampr.org> - * Linus Torvalds, <Linus.Torvalds@helsinki.fi> - * - * Fixes: - * Alan Cox : Verify area fixes. - * Alan Cox : cli() protects routing changes - * Rui Oliveira : ICMP routing table updates - * (rco@di.uminho.pt) Routing table insertion and update - * Linus Torvalds : Rewrote bits to be sensible - * Alan Cox : Added BSD route gw semantics - * Alan Cox : Super /proc >4K - * Alan Cox : MTU in route table - * Alan Cox : MSS actually. Also added the window - * clamper. - * Sam Lantinga : Fixed route matching in rt_del() - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <asm/segment.h> -#include <asm/system.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/string.h> -#include <linux/socket.h> -#include <linux/sockios.h> -#include <linux/errno.h> -#include <linux/in.h> -#include <linux/inet.h> -#include <linux/netdevice.h> -#include "ip.h" -#include "protocol.h" -#include "route.h" -#include "tcp.h" -#include <linux/skbuff.h> -#include "sock.h" -#include "icmp.h" - -/* - * The routing table list - */ - -static struct rtable *rt_base = NULL; - -/* - * Pointer to the loopback route - */ - -static struct rtable *rt_loopback = NULL; - -/* - * Remove a routing table entry. - */ - -static void rt_del(unsigned long dst, char *devname) -{ - struct rtable *r, **rp; - unsigned long flags; - - rp = &rt_base; - - /* - * This must be done with interrupts off because we could take - * an ICMP_REDIRECT. - */ - - save_flags(flags); - cli(); - while((r = *rp) != NULL) - { - /* Make sure both the destination and the device match */ - if ( r->rt_dst != dst || - (devname != NULL && strcmp((r->rt_dev)->name,devname) != 0) ) - { - rp = &r->rt_next; - continue; - } - *rp = r->rt_next; - - /* - * If we delete the loopback route update its pointer. - */ - - if (rt_loopback == r) - rt_loopback = NULL; - kfree_s(r, sizeof(struct rtable)); - } - restore_flags(flags); -} - - -/* - * Remove all routing table entries for a device. This is called when - * a device is downed. - */ - -void ip_rt_flush(struct device *dev) -{ - struct rtable *r; - struct rtable **rp; - unsigned long flags; - - rp = &rt_base; - save_flags(flags); - cli(); - while ((r = *rp) != NULL) { - if (r->rt_dev != dev) { - rp = &r->rt_next; - continue; - } - *rp = r->rt_next; - if (rt_loopback == r) - rt_loopback = NULL; - kfree_s(r, sizeof(struct rtable)); - } - restore_flags(flags); -} - -/* - * Used by 'rt_add()' when we can't get the netmask any other way.. - * - * If the lower byte or two are zero, we guess the mask based on the - * number of zero 8-bit net numbers, otherwise we use the "default" - * masks judging by the destination address and our device netmask. - */ - -static inline unsigned long default_mask(unsigned long dst) -{ - dst = ntohl(dst); - if (IN_CLASSA(dst)) - return htonl(IN_CLASSA_NET); - if (IN_CLASSB(dst)) - return htonl(IN_CLASSB_NET); - return htonl(IN_CLASSC_NET); -} - - -/* - * If no mask is specified then generate a default entry. - */ - -static unsigned long guess_mask(unsigned long dst, struct device * dev) -{ - unsigned long mask; - - if (!dst) - return 0; - mask = default_mask(dst); - if ((dst ^ dev->pa_addr) & mask) - return mask; - return dev->pa_mask; -} - - -/* - * Find the route entry through which our gateway will be reached - */ - -static inline struct device * get_gw_dev(unsigned long gw) -{ - struct rtable * rt; - - for (rt = rt_base ; ; rt = rt->rt_next) - { - if (!rt) - return NULL; - if ((gw ^ rt->rt_dst) & rt->rt_mask) - continue; - /* - * Gateways behind gateways are a no-no - */ - - if (rt->rt_flags & RTF_GATEWAY) - return NULL; - return rt->rt_dev; - } -} - -/* - * Rewrote rt_add(), as the old one was weird - Linus - * - * This routine is used to update the IP routing table, either - * from the kernel (ICMP_REDIRECT) or via an ioctl call issued - * by the superuser. - */ - -void ip_rt_add(short flags, unsigned long dst, unsigned long mask, - unsigned long gw, struct device *dev, unsigned short mtu, unsigned long window) -{ - struct rtable *r, *rt; - struct rtable **rp; - unsigned long cpuflags; - - /* - * A host is a unique machine and has no network bits. - */ - - if (flags & RTF_HOST) - { - mask = 0xffffffff; - } - - /* - * Calculate the network mask - */ - - else if (!mask) - { - if (!((dst ^ dev->pa_addr) & dev->pa_mask)) - { - mask = dev->pa_mask; - flags &= ~RTF_GATEWAY; - if (flags & RTF_DYNAMIC) - { - /*printk("Dynamic route to my own net rejected\n");*/ - return; - } - } - else - mask = guess_mask(dst, dev); - dst &= mask; - } - - /* - * A gateway must be reachable and not a local address - */ - - if (gw == dev->pa_addr) - flags &= ~RTF_GATEWAY; - - if (flags & RTF_GATEWAY) - { - /* - * Don't try to add a gateway we can't reach.. - */ - - if (dev != get_gw_dev(gw)) - return; - - flags |= RTF_GATEWAY; - } - else - gw = 0; - - /* - * Allocate an entry and fill it in. - */ - - rt = (struct rtable *) kmalloc(sizeof(struct rtable), GFP_ATOMIC); - if (rt == NULL) - { - return; - } - memset(rt, 0, sizeof(struct rtable)); - rt->rt_flags = flags | RTF_UP; - rt->rt_dst = dst; - rt->rt_dev = dev; - rt->rt_gateway = gw; - rt->rt_mask = mask; - rt->rt_mss = dev->mtu - HEADER_SIZE; - rt->rt_window = 0; /* Default is no clamping */ - - /* Are the MSS/Window valid ? */ - - if(rt->rt_flags & RTF_MSS) - rt->rt_mss = mtu; - - if(rt->rt_flags & RTF_WINDOW) - rt->rt_window = window; - - /* - * What we have to do is loop though this until we have - * found the first address which has a higher generality than - * the one in rt. Then we can put rt in right before it. - * The interrupts must be off for this process. - */ - - save_flags(cpuflags); - cli(); - - /* - * Remove old route if we are getting a duplicate. - */ - - rp = &rt_base; - while ((r = *rp) != NULL) - { - if (r->rt_dst != dst || - r->rt_mask != mask) - { - rp = &r->rt_next; - continue; - } - *rp = r->rt_next; - if (rt_loopback == r) - rt_loopback = NULL; - kfree_s(r, sizeof(struct rtable)); - } - - /* - * Add the new route - */ - - rp = &rt_base; - while ((r = *rp) != NULL) { - if ((r->rt_mask & mask) != mask) - break; - rp = &r->rt_next; - } - rt->rt_next = r; - *rp = rt; - - /* - * Update the loopback route - */ - - if ((rt->rt_dev->flags & IFF_LOOPBACK) && !rt_loopback) - rt_loopback = rt; - - /* - * Restore the interrupts and return - */ - - restore_flags(cpuflags); - return; -} - -/* - * Remove a routing table entry (exported version). - */ -void ip_rt_del (unsigned long dst, struct device *dev) -{ - /* Should probably just copy contents of rt_del and replace name - comparison with device comparsion. */ - rt_del (dst, dev->name); -} - - -/* - * Check if a mask is acceptable. - */ - -static inline int bad_mask(unsigned long mask, unsigned long addr) -{ - if (addr & (mask = ~mask)) - return 1; - mask = ntohl(mask); - if (mask & (mask+1)) - return 1; - return 0; -} - -/* - * Process a route add request from the user - */ - -static int rt_new(struct rtentry *r) -{ - int err; - char * devname; - struct device * dev = NULL; - unsigned long flags, daddr, mask, gw; - - /* - * If a device is specified find it. - */ - - if ((devname = r->rt_dev) != NULL) - { - err = getname(devname, &devname); - if (err) - return err; - dev = dev_get(devname); - putname(devname); - if (!dev) - return -EINVAL; - } - - /* - * If the device isn't INET, don't allow it - */ - - if (r->rt_dst.sa_family != AF_INET) - return -EAFNOSUPPORT; - - /* - * Make local copies of the important bits - */ - - flags = r->rt_flags; - daddr = ((struct sockaddr_in *) &r->rt_dst)->sin_addr.s_addr; - mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr; - gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr; - - - /* - * BSD emulation: Permits route add someroute gw one-of-my-addresses - * to indicate which iface. Not as clean as the nice Linux dev technique - * but people keep using it... - */ - - if (!dev && (flags & RTF_GATEWAY)) - { - struct device *dev2; - for (dev2 = dev_base ; dev2 != NULL ; dev2 = dev2->next) - { - if ((dev2->flags & IFF_UP) && dev2->pa_addr == gw) - { - flags &= ~RTF_GATEWAY; - dev = dev2; - break; - } - } - } - - /* - * Ignore faulty masks - */ - - if (bad_mask(mask, daddr)) - mask = 0; - - /* - * Set the mask to nothing for host routes. - */ - - if (flags & RTF_HOST) - mask = 0xffffffff; - else if (mask && r->rt_genmask.sa_family != AF_INET) - return -EAFNOSUPPORT; - - /* - * You can only gateway IP via IP.. - */ - - if (flags & RTF_GATEWAY) - { - if (r->rt_gateway.sa_family != AF_INET) - return -EAFNOSUPPORT; - if (!dev) - dev = get_gw_dev(gw); - } - else if (!dev) - dev = ip_dev_check(daddr); - - /* - * Unknown device. - */ - - if (dev == NULL) - return -ENETUNREACH; - - /* - * Add the route - */ - - ip_rt_add(flags, daddr, mask, gw, dev, r->rt_mss, r->rt_window); - return 0; -} - - -/* - * Remove a route, as requested by the user. - */ - -static int rt_kill(struct rtentry *r) -{ - struct sockaddr_in *trg; - char *devname; - int err; - - trg = (struct sockaddr_in *) &r->rt_dst; - if ((devname = r->rt_dev) != NULL) - { - err = getname(devname, &devname); - if (err) - return err; - } - rt_del(trg->sin_addr.s_addr, devname); - if ( devname != NULL ) - putname(devname); - return 0; -} - - -/* - * Called from the PROCfs module. This outputs /proc/net/route. - */ - -int rt_get_info(char *buffer, char **start, off_t offset, int length) -{ - struct rtable *r; - int len=0; - off_t pos=0; - off_t begin=0; - int size; - - len += sprintf(buffer, - "Iface\tDestination\tGateway \tFlags\tRefCnt\tUse\tMetric\tMask\t\tMTU\tWindow\n"); - pos=len; - - /* - * This isn't quite right -- r->rt_dst is a struct! - */ - - for (r = rt_base; r != NULL; r = r->rt_next) - { - size = sprintf(buffer+len, "%s\t%08lX\t%08lX\t%02X\t%d\t%lu\t%d\t%08lX\t%d\t%lu\n", - r->rt_dev->name, r->rt_dst, r->rt_gateway, - r->rt_flags, r->rt_refcnt, r->rt_use, r->rt_metric, - r->rt_mask, (int)r->rt_mss, r->rt_window); - len+=size; - pos+=size; - if(pos<offset) - { - len=0; - begin=pos; - } - if(pos>offset+length) - break; - } - - *start=buffer+(offset-begin); - len-=(offset-begin); - if(len>length) - len=length; - return len; -} - -/* - * This is hackish, but results in better code. Use "-S" to see why. - */ - -#define early_out ({ goto no_route; 1; }) - -/* - * Route a packet. This needs to be fairly quick. Florian & Co. - * suggested a unified ARP and IP routing cache. Done right its - * probably a brilliant idea. I'd actually suggest a unified - * ARP/IP routing/Socket pointer cache. Volunteers welcome - */ - -struct rtable * ip_rt_route(unsigned long daddr, struct options *opt, unsigned long *src_addr) -{ - struct rtable *rt; - - for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) - { - if (!((rt->rt_dst ^ daddr) & rt->rt_mask)) - break; - /* - * broadcast addresses can be special cases.. - */ - if (rt->rt_flags & RTF_GATEWAY) - continue; - if ((rt->rt_dev->flags & IFF_BROADCAST) && - (rt->rt_dev->pa_brdaddr == daddr)) - break; - } - - if(src_addr!=NULL) - *src_addr= rt->rt_dev->pa_addr; - - if (daddr == rt->rt_dev->pa_addr) { - if ((rt = rt_loopback) == NULL) - goto no_route; - } - rt->rt_use++; - return rt; -no_route: - return NULL; -} - -struct rtable * ip_rt_local(unsigned long daddr, struct options *opt, unsigned long *src_addr) -{ - struct rtable *rt; - - for (rt = rt_base; rt != NULL || early_out ; rt = rt->rt_next) - { - /* - * No routed addressing. - */ - if (rt->rt_flags&RTF_GATEWAY) - continue; - - if (!((rt->rt_dst ^ daddr) & rt->rt_mask)) - break; - /* - * broadcast addresses can be special cases.. - */ - - if ((rt->rt_dev->flags & IFF_BROADCAST) && - rt->rt_dev->pa_brdaddr == daddr) - break; - } - - if(src_addr!=NULL) - *src_addr= rt->rt_dev->pa_addr; - - if (daddr == rt->rt_dev->pa_addr) { - if ((rt = rt_loopback) == NULL) - goto no_route; - } - rt->rt_use++; - return rt; -no_route: - return NULL; -} - -/* - * Backwards compatibility - */ - -static int ip_get_old_rtent(struct old_rtentry * src, struct rtentry * rt) -{ - int err; - struct old_rtentry tmp; - - err=verify_area(VERIFY_READ, src, sizeof(*src)); - if (err) - return err; - memcpy_fromfs(&tmp, src, sizeof(*src)); - memset(rt, 0, sizeof(*rt)); - rt->rt_dst = tmp.rt_dst; - rt->rt_gateway = tmp.rt_gateway; - rt->rt_genmask.sa_family = AF_INET; - ((struct sockaddr_in *) &rt->rt_genmask)->sin_addr.s_addr = tmp.rt_genmask; - rt->rt_flags = tmp.rt_flags; - rt->rt_dev = tmp.rt_dev; - printk("Warning: obsolete routing request made.\n"); - return 0; -} - -#ifndef _HURD_ -/* - * Handle IP routing ioctl calls. These are used to manipulate the routing tables - */ - -int ip_rt_ioctl(unsigned int cmd, void *arg) -{ - int err; - struct rtentry rt; - - switch(cmd) - { - case SIOCADDRTOLD: /* Old style add route */ - case SIOCDELRTOLD: /* Old style delete route */ - if (!suser()) - return -EPERM; - err = ip_get_old_rtent((struct old_rtentry *) arg, &rt); - if (err) - return err; - return (cmd == SIOCDELRTOLD) ? rt_kill(&rt) : rt_new(&rt); - - case SIOCADDRT: /* Add a route */ - case SIOCDELRT: /* Delete a route */ - if (!suser()) - return -EPERM; - err=verify_area(VERIFY_READ, arg, sizeof(struct rtentry)); - if (err) - return err; - memcpy_fromfs(&rt, arg, sizeof(struct rtentry)); - return (cmd == SIOCDELRT) ? rt_kill(&rt) : rt_new(&rt); - } - - return -EINVAL; -} -#endif |