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

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