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

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