[BACK]Return to if_tap.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/net/if_tap.c between version 1.47 and 1.47.2.3

version 1.47, 2008/08/26 11:06:59 version 1.47.2.3, 2009/04/28 07:37:16
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
 /*  /*
  *  Copyright (c) 2003, 2004, 2008 The NetBSD Foundation.   *  Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation.
  *  All rights reserved.   *  All rights reserved.
  *   *
  *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
Line 37  __KERNEL_RCSID(0, "$NetBSD$");
Line 37  __KERNEL_RCSID(0, "$NetBSD$");
   
 #if defined(_KERNEL_OPT)  #if defined(_KERNEL_OPT)
 #include "bpfilter.h"  #include "bpfilter.h"
   #include "opt_modular.h"
   #include "opt_compat_netbsd.h"
 #endif  #endif
   
 #include <sys/param.h>  #include <sys/param.h>
Line 49  __KERNEL_RCSID(0, "$NetBSD$");
Line 51  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/filedesc.h>  #include <sys/filedesc.h>
 #include <sys/ksyms.h>  #include <sys/ksyms.h>
 #include <sys/poll.h>  #include <sys/poll.h>
   #include <sys/proc.h>
 #include <sys/select.h>  #include <sys/select.h>
 #include <sys/sockio.h>  #include <sys/sockio.h>
   #if defined(COMPAT_40) || defined(MODULAR)
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
   #endif
 #include <sys/kauth.h>  #include <sys/kauth.h>
 #include <sys/mutex.h>  #include <sys/mutex.h>
 #include <sys/simplelock.h>  #include <sys/simplelock.h>
 #include <sys/intr.h>  #include <sys/intr.h>
   #include <sys/stat.h>
   
 #include <net/if.h>  #include <net/if.h>
 #include <net/if_dl.h>  #include <net/if_dl.h>
Line 68  __KERNEL_RCSID(0, "$NetBSD$");
Line 74  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <compat/sys/sockio.h>  #include <compat/sys/sockio.h>
   
   #if defined(COMPAT_40) || defined(MODULAR)
 /*  /*
  * sysctl node management   * sysctl node management
  *   *
  * It's not really possible to use a SYSCTL_SETUP block with   * It's not really possible to use a SYSCTL_SETUP block with
  * current LKM implementation, so it is easier to just define   * current module implementation, so it is easier to just define
  * our own function.   * our own function.
  *   *
  * The handler function is a "helper" in Andrew Brown's sysctl   * The handler function is a "helper" in Andrew Brown's sysctl
Line 85  __KERNEL_RCSID(0, "$NetBSD$");
Line 92  __KERNEL_RCSID(0, "$NetBSD$");
 static int tap_node;  static int tap_node;
 static int      tap_sysctl_handler(SYSCTLFN_PROTO);  static int      tap_sysctl_handler(SYSCTLFN_PROTO);
 SYSCTL_SETUP_PROTO(sysctl_tap_setup);  SYSCTL_SETUP_PROTO(sysctl_tap_setup);
   #endif
   
 /*  /*
  * Since we're an Ethernet device, we need the 3 following   * Since we're an Ethernet device, we need the 3 following
Line 108  struct tap_softc {
Line 116  struct tap_softc {
         kmutex_t        sc_rdlock;          kmutex_t        sc_rdlock;
         struct simplelock       sc_kqlock;          struct simplelock       sc_kqlock;
         void            *sc_sih;          void            *sc_sih;
           struct timespec sc_atime;
           struct timespec sc_mtime;
           struct timespec sc_btime;
 };  };
   
 /* autoconf(9) glue */  /* autoconf(9) glue */
Line 138  static int tap_fops_write(file_t *, off_
Line 149  static int tap_fops_write(file_t *, off_
     kauth_cred_t, int);      kauth_cred_t, int);
 static int      tap_fops_ioctl(file_t *, u_long, void *);  static int      tap_fops_ioctl(file_t *, u_long, void *);
 static int      tap_fops_poll(file_t *, int);  static int      tap_fops_poll(file_t *, int);
   static int      tap_fops_stat(file_t *, struct stat *);
 static int      tap_fops_kqfilter(file_t *, struct knote *);  static int      tap_fops_kqfilter(file_t *, struct knote *);
   
 static const struct fileops tap_fileops = {  static const struct fileops tap_fileops = {
         tap_fops_read,          .fo_read = tap_fops_read,
         tap_fops_write,          .fo_write = tap_fops_write,
         tap_fops_ioctl,          .fo_ioctl = tap_fops_ioctl,
         fnullop_fcntl,          .fo_fcntl = fnullop_fcntl,
         tap_fops_poll,          .fo_poll = tap_fops_poll,
         fbadop_stat,          .fo_stat = tap_fops_stat,
         tap_fops_close,          .fo_close = tap_fops_close,
         tap_fops_kqfilter,          .fo_kqfilter = tap_fops_kqfilter,
           .fo_drain = fnullop_drain,
 };  };
   
 /* Helper for cloning open() */  /* Helper for cloning open() */
Line 197  static int tap_init(struct ifnet *);
Line 210  static int tap_init(struct ifnet *);
 static int      tap_ioctl(struct ifnet *, u_long, void *);  static int      tap_ioctl(struct ifnet *, u_long, void *);
   
 /* Internal functions */  /* Internal functions */
   #if defined(COMPAT_40) || defined(MODULAR)
 static int      tap_lifaddr(struct ifnet *, u_long, struct ifaliasreq *);  static int      tap_lifaddr(struct ifnet *, u_long, struct ifaliasreq *);
   #endif
 static void     tap_softintr(void *);  static void     tap_softintr(void *);
   
 /*  /*
Line 246  tap_attach(device_t parent, device_t sel
Line 261  tap_attach(device_t parent, device_t sel
 {  {
         struct tap_softc *sc = device_private(self);          struct tap_softc *sc = device_private(self);
         struct ifnet *ifp;          struct ifnet *ifp;
   #if defined(COMPAT_40) || defined(MODULAR)
         const struct sysctlnode *node;          const struct sysctlnode *node;
           int error;
   #endif
         uint8_t enaddr[ETHER_ADDR_LEN] =          uint8_t enaddr[ETHER_ADDR_LEN] =
             { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff };              { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff };
         char enaddrstr[3 * ETHER_ADDR_LEN];          char enaddrstr[3 * ETHER_ADDR_LEN];
         struct timeval tv;          struct timeval tv;
         uint32_t ui;          uint32_t ui;
         int error;  
   
         sc->sc_dev = self;          sc->sc_dev = self;
         sc->sc_sih = softint_establish(SOFTINT_CLOCK, tap_softintr, sc);          sc->sc_sih = softint_establish(SOFTINT_CLOCK, tap_softintr, sc);
           getnanotime(&sc->sc_btime);
           sc->sc_atime = sc->sc_mtime = sc->sc_btime;
   
           if (!pmf_device_register(self, NULL, NULL))
                   aprint_error_dev(self, "couldn't establish power handler\n");
   
         /*          /*
          * In order to obtain unique initial Ethernet address on a host,           * In order to obtain unique initial Ethernet address on a host,
Line 309  tap_attach(device_t parent, device_t sel
Line 331  tap_attach(device_t parent, device_t sel
   
         sc->sc_flags = 0;          sc->sc_flags = 0;
   
   #if defined(COMPAT_40) || defined(MODULAR)
         /*          /*
          * Add a sysctl node for that interface.           * Add a sysctl node for that interface.
          *           *
Line 331  tap_attach(device_t parent, device_t sel
Line 354  tap_attach(device_t parent, device_t sel
             CTL_EOL)) != 0)              CTL_EOL)) != 0)
                 aprint_error_dev(self, "sysctl_createv returned %d, ignoring\n",                  aprint_error_dev(self, "sysctl_createv returned %d, ignoring\n",
                     error);                      error);
   #endif
   
         /*          /*
          * Initialize the two locks for the device.           * Initialize the two locks for the device.
Line 362  tap_detach(device_t self, int flags)
Line 386  tap_detach(device_t self, int flags)
 {  {
         struct tap_softc *sc = device_private(self);          struct tap_softc *sc = device_private(self);
         struct ifnet *ifp = &sc->sc_ec.ec_if;          struct ifnet *ifp = &sc->sc_ec.ec_if;
         int error, s;  #if defined(COMPAT_40) || defined(MODULAR)
           int error;
   #endif
           int s;
   
         sc->sc_flags |= TAP_GOING;          sc->sc_flags |= TAP_GOING;
         s = splnet();          s = splnet();
Line 372  tap_detach(device_t self, int flags)
Line 399  tap_detach(device_t self, int flags)
   
         softint_disestablish(sc->sc_sih);          softint_disestablish(sc->sc_sih);
   
   #if defined(COMPAT_40) || defined(MODULAR)
         /*          /*
          * Destroying a single leaf is a very straightforward operation using           * Destroying a single leaf is a very straightforward operation using
          * sysctl_destroyv.  One should be sure to always end the path with           * sysctl_destroyv.  One should be sure to always end the path with
Line 381  tap_detach(device_t self, int flags)
Line 409  tap_detach(device_t self, int flags)
             device_unit(sc->sc_dev), CTL_EOL)) != 0)              device_unit(sc->sc_dev), CTL_EOL)) != 0)
                 aprint_error_dev(self,                  aprint_error_dev(self,
                     "sysctl_destroyv returned %d, ignoring\n", error);                      "sysctl_destroyv returned %d, ignoring\n", error);
   #endif
         ether_ifdetach(ifp);          ether_ifdetach(ifp);
         if_detach(ifp);          if_detach(ifp);
         ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY);          ifmedia_delete_instance(&sc->sc_im, IFM_INST_ANY);
         seldestroy(&sc->sc_rsel);          seldestroy(&sc->sc_rsel);
         mutex_destroy(&sc->sc_rdlock);          mutex_destroy(&sc->sc_rdlock);
   
           pmf_device_deregister(self);
   
         return (0);          return (0);
 }  }
   
Line 516  tap_ioctl(struct ifnet *ifp, u_long cmd,
Line 547  tap_ioctl(struct ifnet *ifp, u_long cmd,
         case SIOCGIFMEDIA:          case SIOCGIFMEDIA:
                 error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);                  error = ifmedia_ioctl(ifp, ifr, &sc->sc_im, cmd);
                 break;                  break;
   #if defined(COMPAT_40) || defined(MODULAR)
         case SIOCSIFPHYADDR:          case SIOCSIFPHYADDR:
                 error = tap_lifaddr(ifp, cmd, (struct ifaliasreq *)data);                  error = tap_lifaddr(ifp, cmd, (struct ifaliasreq *)data);
                 break;                  break;
   #endif
         default:          default:
                 error = ether_ioctl(ifp, cmd, data);                  error = ether_ioctl(ifp, cmd, data);
                 if (error == ENETRESET)                  if (error == ENETRESET)
Line 531  tap_ioctl(struct ifnet *ifp, u_long cmd,
Line 564  tap_ioctl(struct ifnet *ifp, u_long cmd,
         return (error);          return (error);
 }  }
   
   #if defined(COMPAT_40) || defined(MODULAR)
 /*  /*
  * Helper function to set Ethernet address.  This shouldn't be done there,   * Helper function to set Ethernet address.  This has been replaced by
  * and should actually be available to all Ethernet drivers, real or not.   * the generic SIOCALIFADDR ioctl on a PF_LINK socket.
  */   */
 static int  static int
 tap_lifaddr(struct ifnet *ifp, u_long cmd, struct ifaliasreq *ifra)  tap_lifaddr(struct ifnet *ifp, u_long cmd, struct ifaliasreq *ifra)
 {  {
         const struct sockaddr_dl *sdl = satosdl(&ifra->ifra_addr);          const struct sockaddr *sa = &ifra->ifra_addr;
   
         if (sdl->sdl_family != AF_LINK)          if (sa->sa_family != AF_LINK)
                 return (EINVAL);                  return (EINVAL);
   
         if_set_sadl(ifp, CLLADDR(sdl), ETHER_ADDR_LEN);          if_set_sadl(ifp, sa->sa_data, ETHER_ADDR_LEN, false);
   
         return (0);          return (0);
 }  }
   #endif
   
 /*  /*
  * _init() would typically be called when an interface goes up,   * _init() would typically be called when an interface goes up,
Line 863  tap_dev_read(int unit, struct uio *uio, 
Line 898  tap_dev_read(int unit, struct uio *uio, 
         if (sc == NULL)          if (sc == NULL)
                 return (ENXIO);                  return (ENXIO);
   
           getnanotime(&sc->sc_atime);
   
         ifp = &sc->sc_ec.ec_if;          ifp = &sc->sc_ec.ec_if;
         if ((ifp->if_flags & IFF_UP) == 0)          if ((ifp->if_flags & IFF_UP) == 0)
                 return (EHOSTDOWN);                  return (EHOSTDOWN);
Line 880  tap_dev_read(int unit, struct uio *uio, 
Line 917  tap_dev_read(int unit, struct uio *uio, 
         s = splnet();          s = splnet();
         if (IFQ_IS_EMPTY(&ifp->if_snd)) {          if (IFQ_IS_EMPTY(&ifp->if_snd)) {
                 ifp->if_flags &= ~IFF_OACTIVE;                  ifp->if_flags &= ~IFF_OACTIVE;
                 splx(s);  
                 /*                  /*
                  * We must release the lock before sleeping, and re-acquire it                   * We must release the lock before sleeping, and re-acquire it
                  * after.                   * after.
Line 890  tap_dev_read(int unit, struct uio *uio, 
Line 926  tap_dev_read(int unit, struct uio *uio, 
                         error = EWOULDBLOCK;                          error = EWOULDBLOCK;
                 else                  else
                         error = tsleep(sc, PSOCK|PCATCH, "tap", 0);                          error = tsleep(sc, PSOCK|PCATCH, "tap", 0);
                   splx(s);
   
                 if (error != 0)                  if (error != 0)
                         return (error);                          return (error);
                 /* The device might have been downed */                  /* The device might have been downed */
Line 937  out:
Line 975  out:
 }  }
   
 static int  static int
   tap_fops_stat(file_t *fp, struct stat *st)
   {
           int error;
           struct tap_softc *sc;
           int unit = (uintptr_t)fp->f_data;
   
           (void)memset(st, 0, sizeof(*st));
   
           KERNEL_LOCK(1, NULL);
           sc = device_lookup_private(&tap_cd, unit);
           if (sc == NULL) {
                   error = ENXIO;
                   goto out;
           }
   
           st->st_dev = makedev(cdevsw_lookup_major(&tap_cdevsw), unit);
           st->st_atimespec = sc->sc_atime;
           st->st_mtimespec = sc->sc_mtime;
           st->st_ctimespec = st->st_birthtimespec = sc->sc_btime;
           st->st_uid = kauth_cred_geteuid(fp->f_cred);
           st->st_gid = kauth_cred_getegid(fp->f_cred);
   out:
           KERNEL_UNLOCK_ONE(NULL);
           return error;
   }
   
   static int
 tap_cdev_write(dev_t dev, struct uio *uio, int flags)  tap_cdev_write(dev_t dev, struct uio *uio, int flags)
 {  {
         return tap_dev_write(minor(dev), uio, flags);          return tap_dev_write(minor(dev), uio, flags);
Line 967  tap_dev_write(int unit, struct uio *uio,
Line 1032  tap_dev_write(int unit, struct uio *uio,
         if (sc == NULL)          if (sc == NULL)
                 return (ENXIO);                  return (ENXIO);
   
           getnanotime(&sc->sc_mtime);
         ifp = &sc->sc_ec.ec_if;          ifp = &sc->sc_ec.ec_if;
   
         /* One write, one packet, that's the rule */          /* One write, one packet, that's the rule */
Line 1212  tap_kqread(struct knote *kn, long hint)
Line 1278  tap_kqread(struct knote *kn, long hint)
         return rv;          return rv;
 }  }
   
   #if defined(COMPAT_40) || defined(MODULAR)
 /*  /*
  * sysctl management routines   * sysctl management routines
  * You can set the address of an interface through:   * You can set the address of an interface through:
Line 1225  tap_kqread(struct knote *kn, long hint)
Line 1292  tap_kqread(struct knote *kn, long hint)
  * (called a link set) which is used at init_sysctl() time to cycle   * (called a link set) which is used at init_sysctl() time to cycle
  * through all those functions to create the kernel's sysctl tree.   * through all those functions to create the kernel's sysctl tree.
  *   *
  * It is not (currently) possible to use link sets in a LKM, so the   * It is not possible to use link sets in a module, so the
  * easiest is to simply call our own setup routine at load time.   * easiest is to simply call our own setup routine at load time.
  *   *
  * In the SYSCTL_SETUP blocks you find in the kernel, nodes have the   * In the SYSCTL_SETUP blocks you find in the kernel, nodes have the
Line 1339  tap_sysctl_handler(SYSCTLFN_ARGS)
Line 1406  tap_sysctl_handler(SYSCTLFN_ARGS)
         /* Commit change */          /* Commit change */
         if (ether_nonstatic_aton(enaddr, addr) != 0)          if (ether_nonstatic_aton(enaddr, addr) != 0)
                 return (EINVAL);                  return (EINVAL);
         if_set_sadl(ifp, enaddr, ETHER_ADDR_LEN);          if_set_sadl(ifp, enaddr, ETHER_ADDR_LEN, false);
         return (error);          return (error);
 }  }
   #endif

Legend:
Removed from v.1.47  
changed lines
  Added in v.1.47.2.3

CVSweb <webmaster@jp.NetBSD.org>