URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [net/] [ipv4/] [devinet.c] - Rev 1629
Go to most recent revision | Compare with Previous | Blame | View Log
/* * NET3 IP device support routines. * * 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. * * Derived from the IP parts of dev.c 1.0.19 * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Mark Evans, <evansmp@uhura.aston.ac.uk> * * Additional Authors: * Alan Cox, <gw4pts@gw4pts.ampr.org> */ #include <linux/config.h> /* For CONFIG_IP_CLASSLESS */ #include <asm/segment.h> #include <asm/system.h> #include <asm/bitops.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/socket.h> #include <linux/sockios.h> #include <linux/in.h> #include <linux/errno.h> #include <linux/interrupt.h> #include <linux/if_ether.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <net/ip.h> #include <net/route.h> #include <net/protocol.h> #include <net/tcp.h> #include <linux/skbuff.h> #include <net/sock.h> #include <net/arp.h> /* * Determine a default network mask, based on the IP address. */ unsigned long ip_get_mask(unsigned long addr) { unsigned long dst; if (addr == 0L) return(0L); /* special case */ dst = ntohl(addr); if (IN_CLASSA(dst)) return(htonl(IN_CLASSA_NET)); if (IN_CLASSB(dst)) return(htonl(IN_CLASSB_NET)); if (IN_CLASSC(dst)) return(htonl(IN_CLASSC_NET)); /* * Something else, probably a multicast. */ return(0); } /* * Check the address for our address, broadcasts, etc. * * I intend to fix this to at the very least cache the last * resolved entry. */ int ip_chk_addr(unsigned long addr) { struct device *dev; #ifndef CONFIG_IP_CLASSLESS unsigned long mask; #endif /* * Accept both `all ones' and `all zeros' as BROADCAST. * (Support old BSD in other words). This old BSD * support will go very soon as it messes other things * up. * Also accept `loopback broadcast' as BROADCAST. */ if (addr == INADDR_ANY || addr == INADDR_BROADCAST || addr == htonl(0x7FFFFFFFL)) return IS_BROADCAST; #ifndef CONFIG_IP_CLASSLESS mask = ip_get_mask(addr); /* * Accept all of the `loopback' class A net. */ if ((addr & mask) == htonl(0x7F000000L)) return IS_MYADDR; #else if ((addr & htonl(0x7F000000L)) == htonl(0x7F000000L)) return IS_MYADDR; #endif /* * OK, now check the interface addresses. We could * speed this by keeping a dev and a dev_up chain. */ for (dev = dev_base; dev != NULL; dev = dev->next) { if ((!(dev->flags & IFF_UP)) || dev->family!=AF_INET) continue; /* * If the protocol address of the device is 0 this is special * and means we are address hunting (eg bootp). */ if (dev->pa_addr == 0) return IS_MYADDR; /* * Is it the exact IP address? */ if (addr == dev->pa_addr) return IS_MYADDR; /* * Is it our broadcast address? */ if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr) return IS_BROADCAST; /* * Nope. Check for a subnetwork broadcast. */ if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0) { if ((addr & ~dev->pa_mask) == 0) return IS_BROADCAST; if ((addr & ~dev->pa_mask) == ~dev->pa_mask) return IS_BROADCAST; } #ifndef CONFIG_IP_CLASSLESS /* * Nope. Check for Network broadcast. */ if (((addr ^ dev->pa_addr) & mask) == 0) { if ((addr & ~mask) == 0) return IS_BROADCAST; if ((addr & ~mask) == ~mask) return IS_BROADCAST; } #endif } if(IN_MULTICAST(ntohl(addr))) return IS_MULTICAST; return 0; /* no match at all */ } /* * Retrieve our own address. * * Because the loopback address (127.0.0.1) is already recognized * automatically, we can use the loopback interface's address as * our "primary" interface. This is the address used by IP et * al when it doesn't know which address to use (i.e. it does not * yet know from or to which interface to go...). */ unsigned long ip_my_addr(void) { struct device *dev; for (dev = dev_base; dev != NULL; dev = dev->next) { if (dev->flags & IFF_LOOPBACK) return(dev->pa_addr); } return(0); } /* * Find an interface that can handle addresses for a certain address. */ struct device * ip_dev_bynet(unsigned long addr, unsigned long mask) { struct device *dev; struct device *best_dev = NULL; __u32 best_mask = mask; for (dev = dev_base; dev; dev = dev->next) { if (!(dev->flags & IFF_UP)) continue; if (dev->flags & IFF_POINTOPOINT) { if (addr == dev->pa_dstaddr) return dev; continue; } if (dev->pa_mask & (addr ^ dev->pa_addr)) continue; if (mask == dev->pa_mask) return dev; if (best_dev && (best_mask & dev->pa_mask) != best_mask) continue; best_dev = dev; best_mask = dev->pa_mask; } return best_dev; } /* * Find the first device with a given source address. */ struct device *ip_dev_find(unsigned long addr) { struct device *dev; for(dev = dev_base; dev; dev=dev->next) { if((dev->flags&IFF_UP) && dev->pa_addr==addr) return dev; } return NULL; } struct device *dev_getbytype(unsigned short type) { struct device *dev; for (dev = dev_base; dev != NULL; dev = dev->next) { if (dev->type == type && !(dev->flags&(IFF_LOOPBACK|IFF_NOARP))) return(dev); } return(NULL); }
Go to most recent revision | Compare with Previous | Blame | View Log