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

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