root/net/inet/dev.c

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

DEFINITIONS

This source file includes following definitions.
  1. min
  2. get_mask
  3. ip_addr_match
  4. chk_addr
  5. my_addr
  6. dev_add_pack
  7. dev_remove_pack
  8. dev_get
  9. dev_check
  10. dev_open
  11. dev_close
  12. dev_queue_xmit
  13. netif_rx
  14. dev_rint
  15. dev_transmit
  16. in_inet_bh
  17. inet_bh
  18. dev_tint
  19. dev_ifconf
  20. sprintf_stats
  21. dev_get_info
  22. bad_mask
  23. dev_ifsioc
  24. dev_ioctl
  25. dev_init

   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.0.19  05/31/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  *
  30  *              This program is free software; you can redistribute it and/or
  31  *              modify it under the terms of the GNU General Public License
  32  *              as published by the Free Software Foundation; either version
  33  *              2 of the License, or (at your option) any later version.
  34  */
  35 #include <asm/segment.h>
  36 #include <asm/system.h>
  37 #include <asm/bitops.h>
  38 #include <linux/config.h>
  39 #include <linux/types.h>
  40 #include <linux/kernel.h>
  41 #include <linux/sched.h>
  42 #include <linux/string.h>
  43 #include <linux/mm.h>
  44 #include <linux/socket.h>
  45 #include <linux/sockios.h>
  46 #include <linux/in.h>
  47 #include <linux/errno.h>
  48 #include <linux/interrupt.h>
  49 #include <linux/if_ether.h>
  50 #include "inet.h"
  51 #include "dev.h"
  52 #include "eth.h"
  53 #include "ip.h"
  54 #include "route.h"
  55 #include "protocol.h"
  56 #include "tcp.h"
  57 #include "skbuff.h"
  58 #include "sock.h"
  59 #include "arp.h"
  60 #ifdef CONFIG_AX25
  61 #include "ax25.h"
  62 #endif
  63 
  64 
  65 #ifdef CONFIG_IPX
  66 
  67 static struct packet_type ipx_8023_type = {
  68   NET16(ETH_P_802_3),
  69   0,
  70   ipx_rcv,
  71   NULL,
  72   NULL
  73 };
  74 
  75 static struct packet_type ipx_packet_type = {
  76   NET16(ETH_P_IPX),
  77   0,
  78   ipx_rcv,
  79   NULL,
  80   &ipx_8023_type
  81 };
  82 
  83 #endif
  84 
  85 #ifdef CONFIG_AX25
  86 
  87 static struct packet_type ax25_packet_type = {
  88   NET16(ETH_P_AX25),
  89   0,
  90   ax25_rcv,
  91   NULL,
  92 #ifdef CONFIG_IPX
  93   &ipx_packet_type
  94 #else
  95   NULL
  96 #endif
  97 };
  98 #endif
  99 
 100 
 101 static struct packet_type arp_packet_type = {
 102   NET16(ETH_P_ARP),
 103   0,            /* copy */
 104   arp_rcv,
 105   NULL,
 106 #ifdef CONFIG_IPX
 107 #ifndef CONFIG_AX25
 108   &ipx_packet_type
 109 #else
 110   &ax25_packet_type
 111 #endif
 112 #else
 113   NULL          /* next */
 114 #endif
 115 };
 116 
 117 
 118 static struct packet_type ip_packet_type = {
 119   NET16(ETH_P_IP),
 120   0,            /* copy */
 121   ip_rcv,
 122   NULL,
 123   &arp_packet_type
 124 };
 125    
 126 
 127 struct packet_type *ptype_base = &ip_packet_type;
 128 static struct sk_buff *volatile backlog = NULL;
 129 static unsigned long ip_bcast = 0;
 130 
 131 
 132 /* Return the lesser of the two values. */
 133 static unsigned long
 134 min(unsigned long a, unsigned long b)
     /* [previous][next][first][last][top][bottom][index][help] */
 135 {
 136   if (a < b) return(a);
 137   return(b);
 138 }
 139 
 140 
 141 /* Determine a default network mask, based on the IP address. */
 142 static unsigned long
 143 get_mask(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 144 {
 145   unsigned long dst;
 146 
 147   if (addr == 0L) 
 148         return(0L);     /* special case */
 149 
 150   dst = ntohl(addr);
 151   if (IN_CLASSA(dst)) 
 152         return(htonl(IN_CLASSA_NET));
 153   if (IN_CLASSB(dst)) 
 154         return(htonl(IN_CLASSB_NET));
 155   if (IN_CLASSC(dst)) 
 156         return(htonl(IN_CLASSC_NET));
 157   
 158   /* Something else, probably a subnet. */
 159   return(0);
 160 }
 161 
 162 
 163 int
 164 ip_addr_match(unsigned long me, unsigned long him)
     /* [previous][next][first][last][top][bottom][index][help] */
 165 {
 166   int i;
 167   unsigned long mask=0xFFFFFFFF;
 168   DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
 169   DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
 170 
 171   if (me == him) 
 172         return(1);
 173   for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8) {
 174         if ((me & 0xFF) != (him & 0xFF)) {
 175                 /*
 176                  * The only way this could be a match is for
 177                  * the rest of addr1 to be 0 or 255.
 178                  */
 179                 if (me != 0 && me != mask) return(0);
 180                 return(1);
 181         }
 182   }
 183   return(1);
 184 }
 185 
 186 
 187 /* Check the address for our address, broadcasts, etc. */
 188 int
 189 chk_addr(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 190 {
 191   struct device *dev;
 192   unsigned long dst;
 193 
 194   DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
 195   dst = ntohl(addr);
 196 
 197   /* Accept both `all ones' and `all zeros' as BROADCAST. */
 198   if (dst == INADDR_ANY || dst == INADDR_BROADCAST) {
 199         DPRINTF((DBG_DEV, "BROADCAST\n"));
 200         return(IS_BROADCAST);
 201   }
 202 
 203   /* Accept all of the `loopback' class A net. */
 204   if ((dst & IN_CLASSA_NET) == 0x7F000000L) {
 205         DPRINTF((DBG_DEV, "LOOPBACK\n"));
 206 
 207         /*
 208          * We force `loopback' to be equal to MY_ADDR.
 209          */
 210         return(IS_MYADDR);
 211         /* return(IS_LOOPBACK); */
 212   }
 213 
 214   /* OK, now check the interface addresses. */
 215   for (dev = dev_base; dev != NULL; dev = dev->next) {
 216         if (!(dev->flags&IFF_UP))
 217                 continue;
 218         if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
 219                 return(IS_MYADDR);
 220         /* Is it the exact IP address? */
 221         if (addr == dev->pa_addr) {
 222                 DPRINTF((DBG_DEV, "MYADDR\n"));
 223                 return(IS_MYADDR);
 224         }
 225 
 226         /* Nope. Check for a subnetwork broadcast. */
 227         if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask)) {
 228                 if ((addr & ~dev->pa_mask) == 0) {
 229                         DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
 230                         return(IS_BROADCAST);
 231                 }
 232                 if (((addr & ~dev->pa_mask) | dev->pa_mask)
 233                                                 == INADDR_BROADCAST) {
 234                         DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
 235                         return(IS_BROADCAST);
 236                 }
 237         }
 238 
 239         /* Nope. Check for Network broadcast. */
 240         if(IN_CLASSA(dst)) {
 241           if( addr == (dev->pa_addr | 0xffffff00)) {
 242             DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
 243             return(IS_BROADCAST);
 244           }
 245         }
 246         else if(IN_CLASSB(dst)) {
 247           if( addr == (dev->pa_addr | 0xffff0000)) {
 248             DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
 249             return(IS_BROADCAST);
 250           }
 251         }
 252         else {   /* IN_CLASSC */
 253           if( addr == (dev->pa_addr | 0xff000000)) {
 254             DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
 255             return(IS_BROADCAST);
 256           }
 257         }
 258   }
 259 
 260   DPRINTF((DBG_DEV, "NONE\n"));
 261   
 262   return(0);            /* no match at all */
 263 }
 264 
 265 
 266 /*
 267  * Retrieve our own address.
 268  * Because the loopback address (127.0.0.1) is already recognized
 269  * automatically, we can use the loopback interface's address as
 270  * our "primary" interface.  This is the addressed used by IP et
 271  * al when it doesn't know which address to use (i.e. it does not
 272  * yet know from or to which interface to go...).
 273  */
 274 unsigned long
 275 my_addr(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 276 {
 277   struct device *dev;
 278 
 279   for (dev = dev_base; dev != NULL; dev = dev->next) {
 280         if (dev->flags & IFF_LOOPBACK) return(dev->pa_addr);
 281   }
 282   return(0);
 283 }
 284 
 285 
 286 /* Add a protocol ID to the list.  This will change soon. */
 287 void
 288 dev_add_pack(struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290   struct packet_type *p1;
 291 
 292   pt->next = ptype_base;
 293 
 294   /* See if we need to copy it. */
 295   for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
 296         if (p1->type == pt->type) {
 297                 pt->copy = 1;
 298                 break;
 299         }
 300   }
 301   ptype_base = pt;
 302 }
 303 
 304 
 305 /* Remove a protocol ID from the list.  This will change soon. */
 306 void
 307 dev_remove_pack(struct packet_type *pt)
     /* [previous][next][first][last][top][bottom][index][help] */
 308 {
 309   struct packet_type *lpt, *pt1;
 310 
 311   if (pt == ptype_base) {
 312         ptype_base = pt->next;
 313         return;
 314   }
 315 
 316   lpt = NULL;
 317   for (pt1 = ptype_base; pt1->next != NULL; pt1 = pt1->next) {
 318         if (pt1->next == pt ) {
 319                 cli();
 320                 if (!pt->copy && lpt) 
 321                         lpt->copy = 0;
 322                 pt1->next = pt->next;
 323                 sti();
 324                 return;
 325         }
 326 
 327         if (pt1->next -> type == pt ->type) {
 328                 lpt = pt1->next;
 329         }
 330   }
 331 }
 332 
 333 
 334 /* Find an interface in the list. This will change soon. */
 335 struct device *
 336 dev_get(char *name)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338   struct device *dev;
 339 
 340   for (dev = dev_base; dev != NULL; dev = dev->next) {
 341         if (strcmp(dev->name, name) == 0) 
 342                 return(dev);
 343   }
 344   return(NULL);
 345 }
 346 
 347 
 348 /* Find an interface that can handle addresses for a certain address. */
 349 struct device *
 350 dev_check(unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352   struct device *dev;
 353 
 354   for (dev = dev_base; dev; dev = dev->next)
 355         if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
 356             (addr == dev->pa_dstaddr))
 357                 return dev;
 358   for (dev = dev_base; dev; dev = dev->next)
 359         if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
 360             (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
 361             (dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
 362                 break;
 363   /* no need to check broadcast addresses */
 364   return dev;
 365 }
 366 
 367 
 368 /* Prepare an interface for use. */
 369 int
 370 dev_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 371 {
 372   int ret = 0;
 373 
 374   if (dev->open) 
 375         ret = dev->open(dev);
 376   if (ret == 0) 
 377         dev->flags |= (IFF_UP | IFF_RUNNING);
 378 
 379   return(ret);
 380 }
 381 
 382 
 383 /* Completely shutdown an interface. */
 384 int
 385 dev_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 386 {
 387   if (dev->flags != 0) {
 388         int ct=0;
 389         dev->flags = 0;
 390         if (dev->stop) 
 391                 dev->stop(dev);
 392         rt_flush(dev);
 393         dev->pa_addr = 0;
 394         dev->pa_dstaddr = 0;
 395         dev->pa_brdaddr = 0;
 396         dev->pa_mask = 0;
 397         /* Purge any queued packets when we down the link */
 398         while(ct<DEV_NUMBUFFS)
 399         {
 400                 struct sk_buff *skb;
 401                 while((skb=skb_dequeue(&dev->buffs[ct]))!=NULL)
 402                         if(skb->free)
 403                                 kfree_skb(skb,FREE_WRITE);
 404                 ct++;
 405         }
 406   }
 407 
 408   return(0);
 409 }
 410 
 411 
 412 /* Send (or queue for sending) a packet. */
 413 void
 414 dev_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
     /* [previous][next][first][last][top][bottom][index][help] */
 415 {
 416   int where = 0;                /* used to say if the packet should go  */
 417                                 /* at the front or the back of the      */
 418                                 /* queue.                               */
 419 
 420   DPRINTF((DBG_DEV, "dev_queue_xmit(skb=%X, dev=%X, pri = %d)\n",
 421                                                         skb, dev, pri));
 422 
 423   if (dev == NULL) {
 424         printk("dev.c: dev_queue_xmit: dev = NULL\n");
 425         return;
 426   }
 427  
 428   IS_SKB(skb);
 429     
 430   skb->dev = dev;
 431   if (skb->next != NULL) {
 432         /* Make sure we haven't missed an interrupt. */
 433         dev->hard_start_xmit(NULL, dev);
 434         return;
 435   }
 436 
 437   if (pri < 0) {
 438         pri = -pri-1;
 439         where = 1;
 440   }
 441 
 442   if (pri >= DEV_NUMBUFFS) {
 443         printk("bad priority in dev_queue_xmit.\n");
 444         pri = 1;
 445   }
 446 
 447   if (dev->hard_start_xmit(skb, dev) == 0) {
 448         return;
 449   }
 450 
 451   /* Put skb into a bidirectional circular linked list. */
 452   DPRINTF((DBG_DEV, "dev_queue_xmit dev->buffs[%d]=%X\n",
 453                                         pri, dev->buffs[pri]));
 454 
 455   /* Interrupts should already be cleared by hard_start_xmit. */
 456   cli();
 457   skb->magic = DEV_QUEUE_MAGIC;
 458   if(where)
 459         skb_queue_head(&dev->buffs[pri],skb);
 460   else
 461         skb_queue_tail(&dev->buffs[pri],skb);
 462   skb->magic = DEV_QUEUE_MAGIC;
 463   sti();
 464 }
 465 
 466 /*
 467  * Receive a packet from a device driver and queue it for the upper
 468  * (protocol) levels.  It always succeeds.
 469  */
 470 void
 471 netif_rx(struct sk_buff *skb)
     /* [previous][next][first][last][top][bottom][index][help] */
 472 {
 473   /* Set any necessary flags. */
 474   skb->sk = NULL;
 475   skb->free = 1;
 476   
 477   /* and add it to the "backlog" queue. */
 478   IS_SKB(skb);
 479   skb_queue_tail(&backlog,skb);
 480    
 481   /* If any packet arrived, mark it for processing. */
 482   if (backlog != NULL) mark_bh(INET_BH);
 483 
 484   return;
 485 }
 486 
 487 
 488 /*
 489  * The old interface to fetch a packet from a device driver.
 490  * This function is the base level entry point for all drivers that
 491  * want to send a packet to the upper (protocol) levels.  It takes
 492  * care of de-multiplexing the packet to the various modules based
 493  * on their protocol ID.
 494  *
 495  * Return values:       1 <- exit I can't do any more
 496  *                      0 <- feed me more (i.e. "done", "OK"). 
 497  */
 498 int
 499 dev_rint(unsigned char *buff, long len, int flags, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 500 {
 501   static int dropping = 0;
 502   struct sk_buff *skb = NULL;
 503   unsigned char *to;
 504   int amount, left;
 505   int len2;
 506 
 507   if (dev == NULL || buff == NULL || len <= 0) return(1);
 508   if (flags & IN_SKBUFF) {
 509         skb = (struct sk_buff *) buff;
 510   } else {
 511         if (dropping) {
 512           if (backlog != NULL)
 513               return(1);
 514           printk("INET: dev_rint: no longer dropping packets.\n");
 515           dropping = 0;
 516         }
 517 
 518         skb = alloc_skb(sizeof(*skb) + len, GFP_ATOMIC);
 519         if (skb == NULL) {
 520                 printk("dev_rint: packet dropped on %s (no memory) !\n",
 521                        dev->name);
 522                 dropping = 1;
 523                 return(1);
 524         }
 525         skb->mem_len = sizeof(*skb) + len;
 526         skb->mem_addr = (struct sk_buff *) skb;
 527 
 528         /* First we copy the packet into a buffer, and save it for later. */
 529         to = (unsigned char *) (skb + 1);
 530         left = len;
 531         len2 = len;
 532         while (len2 > 0) {
 533                 amount = min(len2, (unsigned long) dev->rmem_end -
 534                                                 (unsigned long) buff);
 535                 memcpy(to, buff, amount);
 536                 len2 -= amount;
 537                 left -= amount;
 538                 buff += amount;
 539                 to += amount;
 540                 if ((unsigned long) buff == dev->rmem_end)
 541                         buff = (unsigned char *) dev->rmem_start;
 542         }
 543   }
 544   skb->len = len;
 545   skb->dev = dev;
 546   skb->free = 1;
 547 
 548   netif_rx(skb);
 549   /* OK, all done. */
 550   return(0);
 551 }
 552 
 553 
 554 /* This routine causes all interfaces to try to send some data. */
 555 void
 556 dev_transmit(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 557 {
 558   struct device *dev;
 559 
 560   for (dev = dev_base; dev != NULL; dev = dev->next) {
 561         if (!dev->tbusy) {
 562                 dev_tint(dev);
 563         }
 564   }
 565 }
 566 
 567 static volatile char in_bh = 0;
 568 
 569 int in_inet_bh()        /* Used by timer.c */
     /* [previous][next][first][last][top][bottom][index][help] */
 570 {
 571         return(in_bh==0?0:1);
 572 }
 573 
 574 /*
 575  * This function gets called periodically, to see if we can
 576  * process any data that came in from some interface.
 577  *
 578  */
 579 void
 580 inet_bh(void *tmp)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582   struct sk_buff *skb;
 583   struct packet_type *ptype;
 584   unsigned short type;
 585   unsigned char flag = 0;
 586 
 587 
 588   /* Atomically check and mark our BUSY state. */
 589   if (set_bit(1, (void*)&in_bh))
 590       return;
 591 
 592   /* Can we send anything now? */
 593   dev_transmit();
 594   
 595   /* Any data left to process? */
 596   while((skb=skb_dequeue(&backlog))!=NULL)
 597   {
 598         flag=0;
 599         sti();
 600        /*
 601         * Bump the pointer to the next structure.
 602         * This assumes that the basic 'skb' pointer points to
 603         * the MAC header, if any (as indicated by its "length"
 604         * field).  Take care now!
 605         */
 606        skb->h.raw = (unsigned char *) (skb + 1) + skb->dev->hard_header_len;
 607        skb->len -= skb->dev->hard_header_len;
 608 
 609        /*
 610         * Fetch the packet protocol ID.  This is also quite ugly, as
 611         * it depends on the protocol driver (the interface itself) to
 612         * know what the type is, or where to get it from.  The Ethernet
 613         * interfaces fetch the ID from the two bytes in the Ethernet MAC
 614         * header (the h_proto field in struct ethhdr), but drivers like
 615         * SLIP and PLIP have no alternative but to force the type to be
 616         * IP or something like that.  Sigh- FvK
 617         * FIXME: Ethernet drivers need potty training in 802.3 packets -AC
 618         */
 619        type = skb->dev->type_trans(skb, skb->dev);
 620 
 621         /*
 622          * We got a packet ID.  Now loop over the "known protocols"
 623          * table (which is actually a linked list, but this will
 624          * change soon if I get my way- FvK), and forward the packet
 625          * to anyone who wants it.
 626          */
 627         for (ptype = ptype_base; ptype != NULL; ptype = ptype->next) {
 628                 if (ptype->type == type) {
 629                         struct sk_buff *skb2;
 630 
 631                         if (ptype->copy) {      /* copy if we need to   */
 632                                 skb2 = alloc_skb(skb->mem_len, GFP_ATOMIC);
 633                                 if (skb2 == NULL) 
 634                                         continue;
 635                                 memcpy(skb2, (const void *) skb, skb->mem_len);
 636                                 skb2->mem_addr = skb2;
 637                                 skb2->h.raw = (unsigned char *)(
 638                                     (unsigned long) skb2 +
 639                                     (unsigned long) skb->h.raw -
 640                                     (unsigned long) skb
 641                                 );
 642                                 skb2->free = 1;
 643                         } else {
 644                                 skb2 = skb;
 645                         }
 646 
 647                         /* This used to be in the 'else' part, but then
 648                          * we don't have this flag set when we get a
 649                          * protocol that *does* require copying... -FvK
 650                          */
 651                         flag = 1;
 652 
 653                         /* Kick the protocol handler. */
 654                         ptype->func(skb2, skb->dev, ptype);
 655                 }
 656         }
 657 
 658         /*
 659          * That's odd.  We got an unknown packet.  Who's using
 660          * stuff like Novell or Amoeba on this network??
 661          */
 662         if (!flag) {
 663                 DPRINTF((DBG_DEV,
 664                         "INET: unknown packet type 0x%04X (ignored)\n", type));
 665                 skb->sk = NULL;
 666                 kfree_skb(skb, FREE_WRITE);
 667         }
 668 
 669         /* Again, see if we can transmit anything now. */
 670         dev_transmit();
 671         cli();
 672   }
 673   in_bh = 0;
 674   sti();
 675   dev_transmit();
 676 }
 677 
 678 
 679 /*
 680  * This routine is called when an device driver (i.e. an
 681  * interface) is * ready to transmit a packet.
 682  */
 683  
 684 void dev_tint(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 685 {
 686         int i;
 687         struct sk_buff *skb;
 688         
 689         for(i = 0;i < DEV_NUMBUFFS; i++) {
 690                 while((skb=skb_dequeue(&dev->buffs[i]))!=NULL)
 691                 {
 692                         skb->magic = 0;
 693                         skb->next = NULL;
 694                         skb->prev = NULL;
 695                         dev->queue_xmit(skb,dev,-i - 1);
 696                         if (dev->tbusy)
 697                                 return;
 698                 }
 699         }
 700 }
 701 
 702 
 703 /* Perform a SIOCGIFCONF call. */
 704 static int
 705 dev_ifconf(char *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 706 {
 707   struct ifconf ifc;
 708   struct ifreq ifr;
 709   struct device *dev;
 710   char *pos;
 711   int len;
 712 
 713   /* Fetch the caller's info block. */
 714   verify_area(VERIFY_WRITE, arg, sizeof(struct ifconf));
 715   memcpy_fromfs(&ifc, arg, sizeof(struct ifconf));
 716   len = ifc.ifc_len;
 717   pos = ifc.ifc_buf;
 718 
 719   /* Loop over the interfaces, and write an info block for each. */
 720   for (dev = dev_base; dev != NULL; dev = dev->next) {
 721         if(!(dev->flags & IFF_UP))
 722                 continue;
 723         memset(&ifr, 0, sizeof(struct ifreq));
 724         strcpy(ifr.ifr_name, dev->name);
 725         (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family;
 726         (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
 727 
 728         /* Write this block to the caller's space. */
 729         memcpy_tofs(pos, &ifr, sizeof(struct ifreq));
 730         pos += sizeof(struct ifreq);
 731         len -= sizeof(struct ifreq);
 732         if (len < sizeof(struct ifreq)) break;
 733   }
 734 
 735   /* All done.  Write the updated control block back to the caller. */
 736   ifc.ifc_len = (pos - ifc.ifc_buf);
 737   ifc.ifc_req = (struct ifreq *) ifc.ifc_buf;
 738   memcpy_tofs(arg, &ifc, sizeof(struct ifconf));
 739   return(pos - arg);
 740 }
 741 
 742 /* Print device statistics. */
 743 char *sprintf_stats(char *buffer, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 744 {
 745   char *pos = buffer;
 746   struct enet_statistics *stats = (dev->get_stats ? dev->get_stats(dev): NULL);
 747 
 748   if (stats)
 749     pos += sprintf(pos, "%6s:%7d %4d %4d %4d %4d %8d %4d %4d %4d %5d %4d\n",
 750                    dev->name,
 751                    stats->rx_packets, stats->rx_errors,
 752                    stats->rx_dropped + stats->rx_missed_errors,
 753                    stats->rx_fifo_errors,
 754                    stats->rx_length_errors + stats->rx_over_errors
 755                    + stats->rx_crc_errors + stats->rx_frame_errors,
 756                    stats->tx_packets, stats->tx_errors, stats->tx_dropped,
 757                    stats->tx_fifo_errors, stats->collisions,
 758                    stats->tx_carrier_errors + stats->tx_aborted_errors
 759                    + stats->tx_window_errors + stats->tx_heartbeat_errors);
 760   else
 761       pos += sprintf(pos, "%6s: No statistics available.\n", dev->name);
 762 
 763   return pos;
 764 }
 765 
 766 /* Called from the PROCfs module. */
 767 int
 768 dev_get_info(char *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
 769 {
 770   char *pos = buffer;
 771   struct device *dev;
 772 
 773   pos +=
 774       sprintf(pos,
 775               "Inter-|   Receive                  |  Transmit\n"
 776               " face |packets errs drop fifo frame|packets errs drop fifo colls carrier\n");
 777   for (dev = dev_base; dev != NULL; dev = dev->next) {
 778       pos = sprintf_stats(pos, dev);
 779   }
 780   return pos - buffer;
 781 }
 782 
 783 static inline int bad_mask(unsigned long mask, unsigned long addr)
     /* [previous][next][first][last][top][bottom][index][help] */
 784 {
 785         if (addr & (mask = ~mask))
 786                 return 1;
 787         mask = ntohl(mask);
 788         if (mask & (mask+1))
 789                 return 1;
 790         return 0;
 791 }
 792 
 793 /* Perform the SIOCxIFxxx calls. */
 794 static int
 795 dev_ifsioc(void *arg, unsigned int getset)
     /* [previous][next][first][last][top][bottom][index][help] */
 796 {
 797   struct ifreq ifr;
 798   struct device *dev;
 799   int ret;
 800 
 801   /* Fetch the caller's info block. */
 802   verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq));
 803   memcpy_fromfs(&ifr, arg, sizeof(struct ifreq));
 804 
 805   /* See which interface the caller is talking about. */
 806   if ((dev = dev_get(ifr.ifr_name)) == NULL) return(-EINVAL);
 807 
 808   switch(getset) {
 809         case SIOCGIFFLAGS:
 810                 ifr.ifr_flags = dev->flags;
 811                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 812                 ret = 0;
 813                 break;
 814         case SIOCSIFFLAGS:
 815                 {
 816                   int old_flags = dev->flags;
 817                   dev->flags = ifr.ifr_flags & (
 818                         IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
 819                         IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
 820                         IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI);
 821                         
 822                   if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0))
 823                         dev->set_multicast_list(dev,0,NULL);
 824                   if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0))
 825                         dev->set_multicast_list(dev,-1,NULL);
 826                   if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) {
 827                         ret = dev_close(dev);
 828                   } else
 829                       ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP))
 830                         ? dev_open(dev) : 0;
 831                 }
 832                 break;
 833         case SIOCGIFADDR:
 834                 (*(struct sockaddr_in *)
 835                   &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr;
 836                 (*(struct sockaddr_in *)
 837                   &ifr.ifr_addr).sin_family = dev->family;
 838                 (*(struct sockaddr_in *)
 839                   &ifr.ifr_addr).sin_port = 0;
 840                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 841                 ret = 0;
 842                 break;
 843         case SIOCSIFADDR:
 844                 dev->pa_addr = (*(struct sockaddr_in *)
 845                                  &ifr.ifr_addr).sin_addr.s_addr;
 846                 dev->family = ifr.ifr_addr.sa_family;
 847                 dev->pa_mask = get_mask(dev->pa_addr);
 848                 dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
 849                 ret = 0;
 850                 break;
 851         case SIOCGIFBRDADDR:
 852                 (*(struct sockaddr_in *)
 853                   &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr;
 854                 (*(struct sockaddr_in *)
 855                   &ifr.ifr_broadaddr).sin_family = dev->family;
 856                 (*(struct sockaddr_in *)
 857                   &ifr.ifr_broadaddr).sin_port = 0;
 858                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 859                 ret = 0;
 860                 break;
 861         case SIOCSIFBRDADDR:
 862                 dev->pa_brdaddr = (*(struct sockaddr_in *)
 863                                     &ifr.ifr_broadaddr).sin_addr.s_addr;
 864                 ret = 0;
 865                 break;
 866         case SIOCGIFDSTADDR:
 867                 (*(struct sockaddr_in *)
 868                   &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr;
 869                 (*(struct sockaddr_in *)
 870                   &ifr.ifr_broadaddr).sin_family = dev->family;
 871                 (*(struct sockaddr_in *)
 872                   &ifr.ifr_broadaddr).sin_port = 0;
 873                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 874                 ret = 0;
 875                 break;
 876         case SIOCSIFDSTADDR:
 877                 dev->pa_dstaddr = (*(struct sockaddr_in *)
 878                                     &ifr.ifr_dstaddr).sin_addr.s_addr;
 879                 ret = 0;
 880                 break;
 881         case SIOCGIFNETMASK:
 882                 (*(struct sockaddr_in *)
 883                   &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask;
 884                 (*(struct sockaddr_in *)
 885                   &ifr.ifr_netmask).sin_family = dev->family;
 886                 (*(struct sockaddr_in *)
 887                   &ifr.ifr_netmask).sin_port = 0;
 888                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 889                 ret = 0;
 890                 break;
 891         case SIOCSIFNETMASK: {
 892                 unsigned long mask = (*(struct sockaddr_in *)
 893                         &ifr.ifr_netmask).sin_addr.s_addr;
 894                 ret = -EINVAL;
 895                 if (bad_mask(mask,0))
 896                         break;
 897                 dev->pa_mask = mask;
 898                 ret = 0;
 899                 break;
 900         }
 901         case SIOCGIFMETRIC:
 902                 ifr.ifr_metric = dev->metric;
 903                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 904                 ret = 0;
 905                 break;
 906         case SIOCSIFMETRIC:
 907                 dev->metric = ifr.ifr_metric;
 908                 ret = 0;
 909                 break;
 910         case SIOCGIFMTU:
 911                 ifr.ifr_mtu = dev->mtu;
 912                 memcpy_tofs(arg, &ifr, sizeof(struct ifreq));
 913                 ret = 0;
 914                 break;
 915         case SIOCSIFMTU:
 916                 dev->mtu = ifr.ifr_mtu;
 917                 ret = 0;
 918                 break;
 919         case SIOCGIFMEM:
 920                 printk("NET: ioctl(SIOCGIFMEM, 0x%08X)\n", (int)arg);
 921                 ret = -EINVAL;
 922                 break;
 923         case SIOCSIFMEM:
 924                 printk("NET: ioctl(SIOCSIFMEM, 0x%08X)\n", (int)arg);
 925                 ret = -EINVAL;
 926                 break;
 927         case SIOCGIFHWADDR:
 928                 memcpy(ifr.ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN);
 929                 memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
 930                 ret=0;
 931                 break;
 932         default:
 933                 ret = -EINVAL;
 934   }
 935   return(ret);
 936 }
 937 
 938 
 939 /* This function handles all "interface"-type I/O control requests. */
 940 int
 941 dev_ioctl(unsigned int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 942 {
 943   struct iflink iflink;
 944   struct ddi_device *dev;
 945   int ret;
 946 
 947   switch(cmd) {
 948   case IP_SET_DEV:
 949       {   /* Maintain backwards-compatibility, to be deleted for 1.00. */
 950           struct device *dev;
 951           /* The old 'struct ip_config'. */
 952           struct ip_config {
 953               char name[MAX_IP_NAME];
 954               unsigned long paddr, router, net,up:1,destroy:1;
 955           } ipc;
 956           int retval, loopback;
 957 
 958           printk("INET: Warning: old-style ioctl(IP_SET_DEV) called!\n");
 959           if (!suser())
 960               return (-EPERM);
 961           
 962           verify_area (VERIFY_WRITE, arg, sizeof (ipc));
 963           memcpy_fromfs(&ipc, arg, sizeof (ipc));
 964           ipc.name[MAX_IP_NAME-1] = 0;
 965           loopback = (strcmp(ipc.name, "loopback") == 0);
 966           dev = dev_get( loopback ? "lo" : ipc.name);
 967           if (dev == NULL)
 968               return -EINVAL;
 969           ipc.destroy = 0;
 970           dev->pa_addr = ipc.paddr;
 971           dev->family = AF_INET;
 972           dev->pa_mask = get_mask(dev->pa_addr);
 973           dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask;
 974           if (ipc.net != 0xffffffff) {
 975               dev->flags |= IFF_BROADCAST;
 976               dev->pa_brdaddr = ipc.net;
 977           }
 978           
 979           /* To be proper we should delete the route here. */
 980           if (ipc.up == 0)
 981               return (dev->flags & IFF_UP != 0) ? dev_close(dev) : 0;
 982 
 983           if ((dev->flags & IFF_UP) == 0
 984               && (retval = dev_open(dev)) != 0)
 985               return retval;
 986           printk("%s: adding HOST route of %8.8lx.\n", dev->name,
 987                  htonl(ipc.paddr));
 988           rt_add(RTF_HOST, ipc.paddr, 0, 0, dev);
 989           if (ipc.router != 0 && ipc.router != -1) {
 990               rt_add(RTF_GATEWAY, ipc.paddr, 0, ipc.router, dev);
 991               printk("%s: adding GATEWAY route of %8.8lx.\n",
 992                      dev->name, htonl(ipc.paddr));
 993 
 994           }
 995           return 0;
 996       }
 997         case SIOCGIFCONF:
 998                 (void) dev_ifconf((char *) arg);
 999                 ret = 0;
1000                 break;
1001         case SIOCGIFFLAGS:
1002         case SIOCSIFFLAGS:
1003         case SIOCGIFADDR:
1004         case SIOCSIFADDR:
1005         case SIOCGIFDSTADDR:
1006         case SIOCSIFDSTADDR:
1007         case SIOCGIFBRDADDR:
1008         case SIOCSIFBRDADDR:
1009         case SIOCGIFNETMASK:
1010         case SIOCSIFNETMASK:
1011         case SIOCGIFMETRIC:
1012         case SIOCSIFMETRIC:
1013         case SIOCGIFMTU:
1014         case SIOCSIFMTU:
1015         case SIOCGIFMEM:
1016         case SIOCSIFMEM:
1017         case SIOCGIFHWADDR:
1018                 if (!suser()) return(-EPERM);
1019                 ret = dev_ifsioc(arg, cmd);
1020                 break;
1021         case SIOCSIFLINK:
1022                 if (!suser()) return(-EPERM);
1023                 memcpy_fromfs(&iflink, arg, sizeof(iflink));
1024                 dev = ddi_map(iflink.id);
1025                 if (dev == NULL) return(-EINVAL);
1026 
1027                 /* Now allocate an interface and connect it. */
1028                 printk("AF_INET: DDI \"%s\" linked to stream \"%s\"\n",
1029                                                 dev->name, iflink.stream);
1030                 ret = 0;
1031                 break;
1032         default:
1033                 ret = -EINVAL;
1034   }
1035 
1036   return(ret);
1037 }
1038 
1039 
1040 /* Initialize the DEV module. */
1041 void
1042 dev_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1043 {
1044   struct device *dev, *dev2;
1045 
1046   /* Add the devices.
1047    * If the call to dev->init fails, the dev is removed
1048    * from the chain disconnecting the device until the
1049    * next reboot.
1050    */
1051   dev2 = NULL;
1052   for (dev = dev_base; dev != NULL; dev=dev->next) {
1053         if (dev->init && dev->init(dev)) {
1054                 if (dev2 == NULL) dev_base = dev->next;
1055                   else dev2->next = dev->next;
1056         } else {
1057                 dev2 = dev;
1058         }
1059   }
1060 
1061   /* Set up some IP addresses. */
1062   ip_bcast = in_aton("255.255.255.255");
1063 }

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