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

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