/* Return the list of devices in the format provided by SIOCGIFCONF in IFR, but don't return more then AMOUNT bytes. If AMOUNT is negative, there is no limit. */ error_t S_pfinet_siocgifconf (io_t port, vm_size_t amount, char **ifr, mach_msg_type_number_t *len) { error_t err = 0; struct ifconf ifc; pthread_mutex_lock (&global_lock); if (amount == (vm_size_t) -1) { /* Get the needed buffer length. */ ifc.ifc_buf = NULL; ifc.ifc_len = 0; err = dev_ifconf ((char *) &ifc); if (err) { pthread_mutex_unlock (&global_lock); return -err; } amount = ifc.ifc_len; } else ifc.ifc_len = amount; if (amount > 0) { /* Possibly allocate a new buffer. */ if (*len < amount) ifc.ifc_buf = (char *) mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); else ifc.ifc_buf = *ifr; err = dev_ifconf ((char *) &ifc); } if (err) { *len = 0; if (ifc.ifc_buf != *ifr) munmap (ifc.ifc_buf, amount); } else { *len = ifc.ifc_len; *ifr = ifc.ifc_buf; } pthread_mutex_unlock (&global_lock); return err; }
int dev_ioctl(unsigned int cmd, void *arg) { switch(cmd) { case SIOCGIFCONF: (void) dev_ifconf((char *) arg); return 0; /* * Ioctl calls that can be done by all. */ case SIOCGIFFLAGS: case SIOCGIFADDR: case SIOCGIFDSTADDR: case SIOCGIFBRDADDR: case SIOCGIFNETMASK: case SIOCGIFMETRIC: case SIOCGIFMTU: case SIOCGIFMEM: case SIOCGIFHWADDR: case SIOCSIFHWADDR: case OLD_SIOCGIFHWADDR: case SIOCGIFSLAVE: case SIOCGIFMAP: return dev_ifsioc(arg, cmd); /* * Ioctl calls requiring the power of a superuser */ case SIOCSIFFLAGS: case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: case SIOCSIFNETMASK: case SIOCSIFMETRIC: case SIOCSIFMTU: case SIOCSIFMEM: case SIOCSIFMAP: case SIOCSIFSLAVE: case SIOCADDMULTI: case SIOCDELMULTI: if (!suser()) return -EPERM; return dev_ifsioc(arg, cmd); case SIOCSIFLINK: return -EINVAL; /* * Unknown or private ioctl. */ default: if((cmd >= SIOCDEVPRIVATE) && (cmd <= (SIOCDEVPRIVATE + 15))) { return dev_ifsioc(arg, cmd); } return -EINVAL; } }
int dev_ioctl(unsigned int cmd, void *arg) { switch(cmd) { /* * The old old setup ioctl. Even its name and this entry will soon be * just so much ionization on a backup tape. */ case SIOCGIFCONF: (void) dev_ifconf((char *) arg); return 0; /* * Ioctl calls that can be done by all. */ case SIOCGIFFLAGS: case SIOCGIFADDR: case SIOCGIFDSTADDR: case SIOCGIFBRDADDR: case SIOCGIFNETMASK: case SIOCGIFMETRIC: case SIOCGIFMTU: case SIOCGIFMEM: case SIOCGIFHWADDR: case SIOCSIFHWADDR: case OLD_SIOCGIFHWADDR: case SIOCGIFSLAVE: case SIOCGIFMAP: return dev_ifsioc(arg, cmd); /* * Ioctl calls requiring the power of a superuser */ case SIOCSIFFLAGS: case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: case SIOCSIFNETMASK: case SIOCSIFMETRIC: case SIOCSIFMTU: case SIOCSIFMEM: case SIOCSIFMAP: case SIOCSIFSLAVE: case SIOCDEVPRIVATE: if (!suser()) return -EPERM; return dev_ifsioc(arg, cmd); case SIOCSIFLINK: return -EINVAL; /* * Unknown ioctl. */ default: return -EINVAL; } }