int dev_mc_add_excl(struct net_device *dev, unsigned char *addr) #endif { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) struct netdev_hw_addr *ha; #else struct dev_addr_list *ha; #endif int err; netif_addr_lock_bh(dev); netdev_for_each_mc_addr(ha, dev) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) if (!memcmp(ha->addr, addr, dev->addr_len)) { #else if (!memcmp(ha->da_addr, addr, dev->addr_len)) { #endif err = -EEXIST; goto out; } } netif_addr_unlock_bh(dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) return dev_mc_add(dev, addr); #else return dev_mc_add(dev, addr, ETH_ALEN, true); #endif out: netif_addr_unlock_bh(dev); return err; } EXPORT_SYMBOL(dev_mc_add_excl);
static int igmp6_group_added(struct ifmcaddr6 *mc) { struct net_device *dev = mc->idev->dev; char buf[MAX_ADDR_LEN]; #ifdef CONFIG_IPV6_MLD6_DEBUG char abuf[128]; #endif spin_lock_bh(&mc->mca_lock); #ifdef CONFIG_IPV6_MLD6_DEBUG in6_ntop(&mc->mca_addr, abuf); MDBG3((KERN_DEBUG "igmp6_group_added(mc=%p): mca_addr=%s, flag=%08x\n", mc, abuf, mc->mca_flags)); #endif if (!(mc->mca_flags&MAF_LOADED)) { mc->mca_flags |= MAF_LOADED; if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) dev_mc_add(dev, buf, dev->addr_len, 0); } spin_unlock_bh(&mc->mca_lock); if (dev->flags&IFF_UP) igmp6_join_group(mc); return 0; }
void ip_mc_filter_add(struct device *dev, unsigned long addr) { char buf[6]; if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI) return; /* Only do ethernet or FDDI for now */ ip_mc_map(addr,buf); dev_mc_add(dev,buf,ETH_ALEN,0); }
int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid) { int err; unsigned char ll_addr[ETH_ALEN]; ipv6_eth_mc_map((struct in6_addr *)mgid->raw, ll_addr); err = dev_mc_add(rxe->ndev, ll_addr); return err; }
static int igmp6_group_added(struct ifmcaddr6 *mc) { char buf[MAX_ADDR_LEN]; if (!(mc->mca_flags&MAF_LOADED)) { mc->mca_flags |= MAF_LOADED; if (ndisc_mc_map(&mc->mca_addr, buf, mc->dev, 0) == 0) dev_mc_add(mc->dev, buf, mc->dev->addr_len, 0); } if (mc->dev->flags&IFF_UP) igmp6_join_group(mc); return 0; }
static void ip_mc_filter_add(struct in_device *in_dev, u32 addr) { char buf[MAX_ADDR_LEN]; struct device *dev = in_dev->dev; /* Checking for IFF_MULTICAST here is WRONG-WRONG-WRONG. We will get multicast token leakage, when IFF_MULTICAST is changed. This check should be done in dev->set_multicast_list routine. Something sort of: if (dev->mc_list && dev->flags&IFF_MULTICAST) { do it; } --ANK */ if (arp_mc_map(addr, buf, dev, 0) == 0) dev_mc_add(dev,buf,dev->addr_len,0); }
static int igmp6_group_added(struct ifmcaddr6 *mc) { struct net_device *dev = mc->idev->dev; char buf[MAX_ADDR_LEN]; spin_lock_bh(&mc->mca_lock); if (!(mc->mca_flags&MAF_LOADED)) { mc->mca_flags |= MAF_LOADED; if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0) dev_mc_add(dev, buf, dev->addr_len, 0); } spin_unlock_bh(&mc->mca_lock); if (dev->flags&IFF_UP) igmp6_join_group(mc); return 0; }
static void packet_dev_mc(struct net_device *dev, struct packet_mclist *i, int what) { switch (i->type) { case PACKET_MR_MULTICAST: if (what > 0) dev_mc_add(dev, i->addr, i->alen, 0); else dev_mc_delete(dev, i->addr, i->alen, 0); break; case PACKET_MR_PROMISC: dev_set_promiscuity(dev, what); break; case PACKET_MR_ALLMULTI: dev_set_allmulti(dev, what); break; default:; } }
static int dev_ifsioc(void *arg, unsigned int getset) { struct ifreq ifr; struct device *dev; int ret; /* * Fetch the caller's info block into kernel space */ int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq)); if(err) return err; memcpy_fromfs(&ifr, arg, sizeof(struct ifreq)); /* * See which interface the caller is talking about. */ if ((dev = dev_get(ifr.ifr_name)) == NULL) return(-ENODEV); switch(getset) { case SIOCGIFFLAGS: /* Get interface flags */ ifr.ifr_flags = dev->flags; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFFLAGS: /* Set interface flags */ { int old_flags = dev->flags; #ifdef CONFIG_SLAVE_BALANCING if(dev->flags&IFF_SLAVE) return -EBUSY; #endif dev->flags = ifr.ifr_flags & ( IFF_UP | IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK | IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING | IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER | IFF_MULTICAST); #ifdef CONFIG_SLAVE_BALANCING if(!(dev->flags&IFF_MASTER) && dev->slave) { dev->slave->flags&=~IFF_SLAVE; dev->slave=NULL; } #endif /* * Load in the correct multicast list now the flags have changed. */ dev_mc_upload(dev); #if 0 if( dev->set_multicast_list!=NULL) { /* * Has promiscuous mode been turned off */ if ( (old_flags & IFF_PROMISC) && ((dev->flags & IFF_PROMISC) == 0)) dev->set_multicast_list(dev,0,NULL); /* * Has it been turned on */ if ( (dev->flags & IFF_PROMISC) && ((old_flags & IFF_PROMISC) == 0)) dev->set_multicast_list(dev,-1,NULL); } #endif /* * Have we downed the interface */ if ((old_flags & IFF_UP) && ((dev->flags & IFF_UP) == 0)) { ret = dev_close(dev); } else { /* * Have we upped the interface */ ret = (! (old_flags & IFF_UP) && (dev->flags & IFF_UP)) ? dev_open(dev) : 0; /* * Check the flags. */ if(ret<0) dev->flags&=~IFF_UP; /* Didn't open so down the if */ } } break; case SIOCGIFADDR: /* Get interface address (and family) */ (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr; (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_addr).sin_port = 0; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFADDR: /* Set interface address (and family) */ dev->pa_addr = (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr; dev->family = ifr.ifr_addr.sa_family; #ifdef CONFIG_INET /* This is naughty. When net-032e comes out It wants moving into the net032 code not the kernel. Till then it can sit here (SIGH) */ dev->pa_mask = ip_get_mask(dev->pa_addr); #endif dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask; ret = 0; break; case SIOCGIFBRDADDR: /* Get the broadcast address */ (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_port = 0; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFBRDADDR: /* Set the broadcast address */ dev->pa_brdaddr = (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_addr.s_addr; ret = 0; break; case SIOCGIFDSTADDR: /* Get the destination address (for point-to-point links) */ (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_port = 0; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFDSTADDR: /* Set the destination address (for point-to-point links) */ dev->pa_dstaddr = (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_addr.s_addr; ret = 0; break; case SIOCGIFNETMASK: /* Get the netmask for the interface */ (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask; (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_port = 0; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFNETMASK: /* Set the netmask for the interface */ { unsigned long mask = (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_addr.s_addr; ret = -EINVAL; /* * The mask we set must be legal. */ if (bad_mask(mask,0)) break; dev->pa_mask = mask; ret = 0; } break; case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */ ifr.ifr_metric = dev->metric; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */ dev->metric = ifr.ifr_metric; ret = 0; break; case SIOCGIFMTU: /* Get the MTU of a device */ ifr.ifr_mtu = dev->mtu; memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); ret = 0; break; case SIOCSIFMTU: /* Set the MTU of a device */ /* * MTU must be positive and under the page size problem */ if(ifr.ifr_mtu<1 || ifr.ifr_mtu>3800) return -EINVAL; dev->mtu = ifr.ifr_mtu; ret = 0; break; case SIOCGIFMEM: /* Get the per device memory space. We can add this but currently do not support it */ printk("NET: ioctl(SIOCGIFMEM, %p)\n", arg); ret = -EINVAL; break; case SIOCSIFMEM: /* Set the per device memory buffer space. Not applicable in our case */ printk("NET: ioctl(SIOCSIFMEM, %p)\n", arg); ret = -EINVAL; break; case OLD_SIOCGIFHWADDR: /* Get the hardware address. This will change and SIFHWADDR will be added */ memcpy(ifr.old_ifr_hwaddr,dev->dev_addr, MAX_ADDR_LEN); memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); ret=0; break; case SIOCGIFHWADDR: memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN); ifr.ifr_hwaddr.sa_family=dev->type; memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); ret=0; break; case SIOCSIFHWADDR: if(dev->set_mac_address==NULL) return -EOPNOTSUPP; if(ifr.ifr_hwaddr.sa_family!=dev->type) return -EINVAL; ret=dev->set_mac_address(dev,ifr.ifr_hwaddr.sa_data); break; case SIOCGIFMAP: ifr.ifr_map.mem_start=dev->mem_start; ifr.ifr_map.mem_end=dev->mem_end; ifr.ifr_map.base_addr=dev->base_addr; ifr.ifr_map.irq=dev->irq; ifr.ifr_map.dma=dev->dma; ifr.ifr_map.port=dev->if_port; memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); ret=0; break; case SIOCSIFMAP: if(dev->set_config==NULL) return -EOPNOTSUPP; return dev->set_config(dev,&ifr.ifr_map); case SIOCGIFSLAVE: #ifdef CONFIG_SLAVE_BALANCING if(dev->slave==NULL) return -ENOENT; strncpy(ifr.ifr_name,dev->name,sizeof(ifr.ifr_name)); memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); ret=0; #else return -ENOENT; #endif break; #ifdef CONFIG_SLAVE_BALANCING case SIOCSIFSLAVE: { /* * Fun game. Get the device up and the flags right without * letting some scummy user confuse us. */ unsigned long flags; struct device *slave=dev_get(ifr.ifr_slave); save_flags(flags); if(slave==NULL) { return -ENODEV; } cli(); if((slave->flags&(IFF_UP|IFF_RUNNING))!=(IFF_UP|IFF_RUNNING)) { restore_flags(flags); return -EINVAL; } if(dev->flags&IFF_SLAVE) { restore_flags(flags); return -EBUSY; } if(dev->slave!=NULL) { restore_flags(flags); return -EBUSY; } if(slave->flags&IFF_SLAVE) { restore_flags(flags); return -EBUSY; } dev->slave=slave; slave->flags|=IFF_SLAVE; dev->flags|=IFF_MASTER; restore_flags(flags); ret=0; } break; #endif case SIOCADDMULTI: if(dev->set_multicast_list==NULL) return -EINVAL; if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) return -EINVAL; dev_mc_add(dev,ifr.ifr_hwaddr.sa_data, dev->addr_len, 1); return 0; case SIOCDELMULTI: if(dev->set_multicast_list==NULL) return -EINVAL; if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) return -EINVAL; dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1); return 0; /* * Unknown or private ioctl */ default: if((getset >= SIOCDEVPRIVATE) && (getset <= (SIOCDEVPRIVATE + 15))) { if(dev->do_ioctl==NULL) return -EOPNOTSUPP; ret=dev->do_ioctl(dev, &ifr, getset); memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); break; } ret = -EINVAL; } return(ret); }
/** Taken from Gleb + Lennert's VLAN code, and modified... */ void vlan_dev_set_multicast_list(struct net_device *vlan_dev) { struct dev_mc_list *dmi; struct net_device *real_dev; int inc; if (vlan_dev && (vlan_dev->priv_flags & IFF_802_1Q_VLAN)) { /* Then it's a real vlan device, as far as we can tell.. */ real_dev = VLAN_DEV_INFO(vlan_dev)->real_dev; /* compare the current promiscuity to the last promisc we had.. */ inc = vlan_dev->promiscuity - VLAN_DEV_INFO(vlan_dev)->old_promiscuity; if (inc) { printk(KERN_INFO "%s: dev_set_promiscuity(master, %d)\n", vlan_dev->name, inc); dev_set_promiscuity(real_dev, inc); /* found in dev.c */ VLAN_DEV_INFO(vlan_dev)->old_promiscuity = vlan_dev->promiscuity; } inc = vlan_dev->allmulti - VLAN_DEV_INFO(vlan_dev)->old_allmulti; if (inc) { printk(KERN_INFO "%s: dev_set_allmulti(master, %d)\n", vlan_dev->name, inc); dev_set_allmulti(real_dev, inc); /* dev.c */ VLAN_DEV_INFO(vlan_dev)->old_allmulti = vlan_dev->allmulti; } /* looking for addresses to add to master's list */ for (dmi = vlan_dev->mc_list; dmi != NULL; dmi = dmi->next) { if (vlan_should_add_mc(dmi, VLAN_DEV_INFO(vlan_dev)->old_mc_list)) { dev_mc_add(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); printk(KERN_DEBUG "%s: add %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address to master interface\n", vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); } } /* looking for addresses to delete from master's list */ for (dmi = VLAN_DEV_INFO(vlan_dev)->old_mc_list; dmi != NULL; dmi = dmi->next) { if (vlan_should_add_mc(dmi, vlan_dev->mc_list)) { /* if we think we should add it to the new list, then we should really * delete it from the real list on the underlying device. */ dev_mc_delete(real_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); printk(KERN_DEBUG "%s: del %.2x:%.2x:%.2x:%.2x:%.2x:%.2x mcast address from master interface\n", vlan_dev->name, dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2], dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]); } } /* save multicast list */ vlan_copy_mc_list(vlan_dev->mc_list, VLAN_DEV_INFO(vlan_dev)); } }
static int dev_ifsioc(void *arg, unsigned int getset) { struct ifreq ifr; struct device *dev; int ret; /* * Fetch the caller's info block into kernel space */ int err=verify_area(VERIFY_WRITE, arg, sizeof(struct ifreq)); if(err) return err; memcpy_fromfs(&ifr, arg, sizeof(struct ifreq)); /* * See which interface the caller is talking about. */ /* * * net_alias_dev_get(): dev_get() with added alias naming magic. * only allow alias creation/deletion if (getset==SIOCSIFADDR) * */ #ifdef CONFIG_KERNELD dev_load(ifr.ifr_name); #endif #ifdef CONFIG_NET_ALIAS if ((dev = net_alias_dev_get(ifr.ifr_name, getset == SIOCSIFADDR, &err, NULL, NULL)) == NULL) return(err); #else if ((dev = dev_get(ifr.ifr_name)) == NULL) return(-ENODEV); #endif switch(getset) { case SIOCGIFFLAGS: /* Get interface flags */ ifr.ifr_flags = (dev->flags & ~IFF_SOFTHEADERS); goto rarok; case SIOCSIFFLAGS: /* Set interface flags */ { int old_flags = dev->flags; if(securelevel>0) ifr.ifr_flags&=~IFF_PROMISC; /* * We are not allowed to potentially close/unload * a device until we get this lock. */ dev_lock_wait(); /* * Set the flags on our device. */ dev->flags = (ifr.ifr_flags & ( IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK | IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING | IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER | IFF_MULTICAST)) | (dev->flags & (IFF_SOFTHEADERS|IFF_UP)); /* * Load in the correct multicast list now the flags have changed. */ dev_mc_upload(dev); /* * Have we downed the interface. We handle IFF_UP ourselves * according to user attempts to set it, rather than blindly * setting it. */ if ((old_flags^ifr.ifr_flags)&IFF_UP) /* Bit is different ? */ { if(old_flags&IFF_UP) /* Gone down */ ret=dev_close(dev); else /* Come up */ { ret=dev_open(dev); if(ret<0) dev->flags&=~IFF_UP; /* Open failed */ } } else ret=0; /* * Load in the correct multicast list now the flags have changed. */ dev_mc_upload(dev); } break; case SIOCGIFADDR: /* Get interface address (and family) */ if(ifr.ifr_addr.sa_family==AF_UNSPEC) { memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN); ifr.ifr_hwaddr.sa_family=dev->type; goto rarok; } else { (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr = dev->pa_addr; (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_addr).sin_port = 0; } goto rarok; case SIOCSIFADDR: /* Set interface address (and family) */ /* * BSDism. SIOCSIFADDR family=AF_UNSPEC sets the * physical address. We can cope with this now. */ if(ifr.ifr_addr.sa_family==AF_UNSPEC) { if(dev->set_mac_address==NULL) return -EOPNOTSUPP; if(securelevel>0) return -EPERM; ret=dev->set_mac_address(dev,&ifr.ifr_addr); } else { u32 new_pa_addr = (*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr.s_addr; u16 new_family = ifr.ifr_addr.sa_family; if (new_family == dev->family && new_pa_addr == dev->pa_addr) { ret =0; break; } if (dev->flags & IFF_UP) notifier_call_chain(&netdev_chain, NETDEV_DOWN, dev); /* * if dev is an alias, must rehash to update * address change */ #ifdef CONFIG_NET_ALIAS if (net_alias_is(dev)) net_alias_dev_rehash(dev ,&ifr.ifr_addr); #endif dev->pa_addr = new_pa_addr; dev->family = new_family; #ifdef CONFIG_INET /* This is naughty. When net-032e comes out It wants moving into the net032 code not the kernel. Till then it can sit here (SIGH) */ if (!dev->pa_mask) dev->pa_mask = ip_get_mask(dev->pa_addr); #endif if (!dev->pa_brdaddr) dev->pa_brdaddr = dev->pa_addr | ~dev->pa_mask; if (dev->flags & IFF_UP) notifier_call_chain(&netdev_chain, NETDEV_UP, dev); ret = 0; } break; case SIOCGIFBRDADDR: /* Get the broadcast address */ (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_addr.s_addr = dev->pa_brdaddr; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_port = 0; goto rarok; case SIOCSIFBRDADDR: /* Set the broadcast address */ dev->pa_brdaddr = (*(struct sockaddr_in *) &ifr.ifr_broadaddr).sin_addr.s_addr; ret = 0; break; case SIOCGIFDSTADDR: /* Get the destination address (for point-to-point links) */ (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_addr.s_addr = dev->pa_dstaddr; (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_port = 0; goto rarok; case SIOCSIFDSTADDR: /* Set the destination address (for point-to-point links) */ dev->pa_dstaddr = (*(struct sockaddr_in *) &ifr.ifr_dstaddr).sin_addr.s_addr; ret = 0; break; case SIOCGIFNETMASK: /* Get the netmask for the interface */ (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_addr.s_addr = dev->pa_mask; (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_family = dev->family; (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_port = 0; goto rarok; case SIOCSIFNETMASK: /* Set the netmask for the interface */ { unsigned long mask = (*(struct sockaddr_in *) &ifr.ifr_netmask).sin_addr.s_addr; ret = -EINVAL; /* * The mask we set must be legal. */ if (bad_mask(mask,0)) break; dev->pa_mask = mask; ret = 0; } break; case SIOCGIFMETRIC: /* Get the metric on the interface (currently unused) */ ifr.ifr_metric = dev->metric; goto rarok; case SIOCSIFMETRIC: /* Set the metric on the interface (currently unused) */ dev->metric = ifr.ifr_metric; ret=0; break; case SIOCGIFMTU: /* Get the MTU of a device */ ifr.ifr_mtu = dev->mtu; goto rarok; case SIOCSIFMTU: /* Set the MTU of a device */ if (dev->change_mtu) ret = dev->change_mtu(dev, ifr.ifr_mtu); else { /* * MTU must be positive. */ if(ifr.ifr_mtu<68) return -EINVAL; dev->mtu = ifr.ifr_mtu; ret = 0; } break; case SIOCGIFMEM: /* Get the per device memory space. We can add this but currently do not support it */ ret = -EINVAL; break; case SIOCSIFMEM: /* Set the per device memory buffer space. Not applicable in our case */ ret = -EINVAL; break; case SIOCGIFHWADDR: memcpy(ifr.ifr_hwaddr.sa_data,dev->dev_addr, MAX_ADDR_LEN); ifr.ifr_hwaddr.sa_family=dev->type; goto rarok; case SIOCSIFHWADDR: if(dev->set_mac_address==NULL) return -EOPNOTSUPP; if(securelevel > 0) return -EPERM; if(ifr.ifr_hwaddr.sa_family!=dev->type) return -EINVAL; ret=dev->set_mac_address(dev,&ifr.ifr_hwaddr); break; case SIOCGIFMAP: ifr.ifr_map.mem_start=dev->mem_start; ifr.ifr_map.mem_end=dev->mem_end; ifr.ifr_map.base_addr=dev->base_addr; ifr.ifr_map.irq=dev->irq; ifr.ifr_map.dma=dev->dma; ifr.ifr_map.port=dev->if_port; goto rarok; case SIOCSIFMAP: if(dev->set_config==NULL) return -EOPNOTSUPP; return dev->set_config(dev,&ifr.ifr_map); case SIOCADDMULTI: if(dev->set_multicast_list==NULL) return -EINVAL; if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) return -EINVAL; dev_mc_add(dev,ifr.ifr_hwaddr.sa_data, dev->addr_len, 1); return 0; case SIOCDELMULTI: if(dev->set_multicast_list==NULL) return -EINVAL; if(ifr.ifr_hwaddr.sa_family!=AF_UNSPEC) return -EINVAL; dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1); return 0; /* * Unknown or private ioctl */ default: if((getset >= SIOCDEVPRIVATE) && (getset <= (SIOCDEVPRIVATE + 15))) { if(dev->do_ioctl==NULL) return -EOPNOTSUPP; ret=dev->do_ioctl(dev, &ifr, getset); memcpy_tofs(arg,&ifr,sizeof(struct ifreq)); break; } #ifdef CONFIG_NET_RADIO if((getset >= SIOCIWFIRST) && (getset <= SIOCIWLAST)) { if(dev->do_ioctl==NULL) return -EOPNOTSUPP; /* Perform the ioctl */ ret=dev->do_ioctl(dev, &ifr, getset); /* If return args... */ if(IW_IS_GET(getset)) memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); break; } #endif /* CONFIG_NET_RADIO */ ret = -EINVAL; } return(ret); /* * The load of calls that return an ifreq and ok (saves memory). */ rarok: memcpy_tofs(arg, &ifr, sizeof(struct ifreq)); return 0; }