root/net/inet/devinet.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ip_get_mask
  2. ip_addr_match
  3. chk_addr
  4. my_addr
  5. dev_check

   1 /*
   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3  *              operating system.  INET is implemented using the  BSD Socket
   4  *              interface as the means of communication with the user level.
   5  *
   6  *              Interface (streams) handling functions.
   7  *
   8  * Version:     @(#)dev.c       1.28    20/12/93
   9  *
  10  * Authors:     Ross Biro, <bir7@leland.Stanford.Edu>
  11  *              Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  12  *              Mark Evans, <evansmp@uhura.aston.ac.uk>
  13  * 
  14  * Fixes:       
  15  *              Alan Cox:       check_addr returns a value for a wrong subnet
  16  *                              ie not us but don't forward this!
  17  *              Alan Cox:       block timer if the inet_bh handler is running
  18  *              Alan Cox:       generic queue code added. A lot neater now
  19  *              C.E.Hawkins:    SIOCGIFCONF only reports 'upped' interfaces
  20  *              C.E.Hawkins:    IFF_PROMISC support
  21  *              Alan Cox:       Supports Donald Beckers new hardware 
  22  *                              multicast layer, but not yet multicast lists.
  23  *              Alan Cox:       ip_addr_match problems with class A/B nets.
  24  *              C.E.Hawkins     IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT]
  25  *              Alan Cox:       Removed bogus subnet check now the subnet code
  26  *                              a) actually works for all A/B nets
  27  *                              b) doesn't forward off the same interface.
  28  *              Alan Cox:       Multiple extra protocols
  29  *              Alan Cox:       A Couple more escaped verify_area calls die
  30  *              Alan Cox:       IP_SET_DEV is gone (forever) as per Fred's comment.
  31  *              Alan Cox:       Grand tidy up ready for the big day.
  32  *              Alan Cox:       Handles dev_open errors correctly.
  33  *              Alan Cox:       IP and generic parts split
  34  *
  35  *              This program is free software; you can redistribute it and/or
  36  *              modify it under the terms of the GNU General Public License
  37  *              as published by the Free Software Foundation; either version
  38  *              2 of the License, or (at your option) any later version.
  39  */
  40 
  41 #include <asm/segment.h>
  42 #include <asm/system.h>
  43 #include <asm/bitops.h>
  44 #include <linux/config.h>
  45 #include <linux/types.h>
  46 #include <linux/kernel.h>
  47 #include <linux/sched.h>
  48 #include <linux/string.h>
  49 #include <linux/mm.h>
  50 #include <linux/socket.h>
  51 #include <linux/sockios.h>
  52 #include <linux/in.h>
  53 #include <linux/errno.h>
  54 #include <linux/interrupt.h>
  55 #include <linux/if_ether.h>
  56 #include "inet.h"
  57 #include "devinet.h"
  58 #include "eth.h"
  59 #include "ip.h"
  60 #include "route.h"
  61 #include "protocol.h"
  62 #include "tcp.h"
  63 #include "skbuff.h"
  64 
  65 
  66 /* 
  67  *      Determine a default network mask, based on the IP address.
  68  */
  69 
  70 unsigned long ip_get_mask(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         unsigned long dst;
  73 
  74         if (addr == 0L) 
  75                 return(0L);     /* special case */
  76 
  77         dst = ntohl(addr);
  78         if (IN_CLASSA(dst)) 
  79                 return(htonl(IN_CLASSA_NET));
  80         if (IN_CLASSB(dst)) 
  81                 return(htonl(IN_CLASSB_NET));
  82         if (IN_CLASSC(dst)) 
  83                 return(htonl(IN_CLASSC_NET));
  84         
  85         /* Something else, probably a subnet. */
  86         return(0);
  87 }
  88 
  89 /*
  90  *      See if a pair of addresses match.
  91  */
  92 
  93 int ip_addr_match(unsigned long me, unsigned long him)
     /* [previous][next][first][last][top][bottom][index][help] */
  94 {
  95         int i;
  96         unsigned long mask=0xFFFFFFFF;
  97         DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
  98         DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
  99 
 100         /* Fast path for 99.9% of cases */
 101         if (me == him) 
 102                 return(1);
 103                 
 104         for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8) 
 105         {
 106                 if ((me & 0xFF) != (him & 0xFF)) 
 107                 {
 108                         /*
 109                          * The only way this could be a match is for
 110                          * the rest of addr1 to be 0 or 255.
 111                          */
 112                         if (me != 0 && me != mask) 
 113                                 return(0);
 114                         return(1);
 115                 }
 116         }
 117         return(1);
 118 }
 119 
 120 
 121 /*
 122  *      Check the address for our address, broadcasts, etc. 
 123  *
 124  *      This routine is used a lot, and in many time critical
 125  *      places. It's already _TOO_ slow so be careful how you
 126  *      alter it.
 127  */
 128  
 129 int chk_addr(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         struct device *dev;
 132         unsigned long dst;
 133 
 134         DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
 135         dst = ntohl(addr);
 136 
 137         /*
 138          * Accept both `all ones' and `all zeros' as BROADCAST. 
 139          * All 0's is the old BSD broadcast.
 140          */
 141          
 142         if (dst == INADDR_ANY || dst == INADDR_BROADCAST) 
 143         {
 144                 DPRINTF((DBG_DEV, "BROADCAST\n"));
 145                 return(IS_BROADCAST);
 146         }
 147 
 148         /* Accept all of the `loopback' class A net. */
 149         if ((dst & IN_CLASSA_NET) == 0x7F000000L) 
 150         {
 151                 DPRINTF((DBG_DEV, "LOOPBACK\n"));
 152 
 153                 /*
 154                  * We force `loopback' to be equal to MY_ADDR.
 155                  */
 156                 return(IS_MYADDR);
 157                 /* return(IS_LOOPBACK); */
 158         }
 159 
 160         /* OK, now check the interface addresses. */
 161         for (dev = dev_base; dev != NULL; dev = dev->next) 
 162         {
 163                 if (!(dev->flags&IFF_UP))
 164                         continue;
 165                 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
 166                         return(IS_MYADDR);
 167                 /* Is it the exact IP address? */
 168                 if (addr == dev->pa_addr) 
 169                 {
 170                         DPRINTF((DBG_DEV, "MYADDR\n"));
 171                         return(IS_MYADDR);
 172                 }
 173 
 174                 /* Nope. Check for a subnetwork broadcast. */
 175                 if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask)) 
 176                 {
 177                         if ((addr & ~dev->pa_mask) == 0) 
 178                         {
 179                                 DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
 180                                 return(IS_BROADCAST);
 181                         }
 182                         if (((addr & ~dev->pa_mask) | dev->pa_mask)
 183                                                 == INADDR_BROADCAST) 
 184                         {
 185                                 DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
 186                                 return(IS_BROADCAST);
 187                         }
 188                 }
 189 
 190                 /* Nope. Check for Network broadcast. */
 191                 if(IN_CLASSA(dst)) 
 192                 {
 193                         if( addr == (dev->pa_addr | 0xffffff00)) 
 194                         {
 195                                 DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
 196                                 return(IS_BROADCAST);
 197                         }
 198                 }
 199                 else if(IN_CLASSB(dst)) 
 200                 {
 201                         if( addr == (dev->pa_addr | 0xffff0000)) 
 202                         {
 203                                 DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
 204                                 return(IS_BROADCAST);
 205                         }
 206                 }
 207                 else 
 208                 {   /* IN_CLASSC */
 209                         if( addr == (dev->pa_addr | 0xff000000)) 
 210                         {
 211                                 DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
 212                                 return(IS_BROADCAST);
 213                         }
 214                 }
 215         }
 216 
 217         DPRINTF((DBG_DEV, "NONE\n"));
 218   
 219         return(0);              /* no match at all */
 220 }
 221 
 222 
 223 /*
 224  * Retrieve our own address.
 225  * Because the loopback address (127.0.0.1) is already recognized
 226  * automatically, we can use the loopback interface's address as
 227  * our "primary" interface.  This is the addressed used by IP et
 228  * al when it doesn't know which address to use (i.e. it does not
 229  * yet know from or to which interface to go...).
 230  */
 231 
 232 unsigned long my_addr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 233 {
 234         struct device *dev;
 235 
 236         for (dev = dev_base; dev != NULL; dev = dev->next) 
 237         {
 238                 if (dev->flags & IFF_LOOPBACK) 
 239                         return(dev->pa_addr);
 240         }
 241         return(0);
 242 }
 243 
 244 
 245 
 246 /*
 247  *      Find an interface that can handle addresses for a certain address. 
 248  */
 249  
 250 struct device *dev_check(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 251 {
 252         struct device *dev;
 253 
 254         for (dev = dev_base; dev; dev = dev->next)
 255                 if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
 256                         (addr == dev->pa_dstaddr))
 257                         return dev;
 258         for (dev = dev_base; dev; dev = dev->next)
 259                 if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
 260                         (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
 261                         (dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
 262                         break;
 263   /* no need to check broadcast addresses */
 264         return dev;
 265 }
 266 

/* [previous][next][first][last][top][bottom][index][help] */