User Tools

Site Tools


ip_up_down

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
ip_up_down [2018/10/04 10:52]
rpjday [Sockets and ioctl calls]
ip_up_down [2018/10/04 11:09] (current)
rpjday [__dev_change_flags()]
Line 407: Line 407:
  
 <​code>​ <​code>​
 +int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
 +{
  
 +... snip ...
 +
 + switch (cmd) {
 + /*
 + * These ioctl calls:
 + * - can be done by all.
 + * - atomic and do not require locking.
 + * - return a value
 + */
 + case SIOCGIFFLAGS:​
 + case SIOCGIFMETRIC:​
 + case SIOCGIFMTU:
 + case SIOCGIFHWADDR:​
 + case SIOCGIFSLAVE:​
 + case SIOCGIFMAP:
 + case SIOCGIFINDEX:​
 + case SIOCGIFTXQLEN:​
 + dev_load(net,​ ifr->​ifr_name);​
 + rcu_read_lock();​
 + ret = dev_ifsioc_locked(net,​ ifr, cmd);
 + rcu_read_unlock();​
 + if (colon)
 + *colon = ':';​
 + return ret;
 +
 +... snip ...
 +
 + case SIOCSIFFLAGS:​
 + case SIOCSIFMETRIC:​
 + case SIOCSIFMTU:
 + case SIOCSIFHWADDR:​
 + case SIOCSIFSLAVE:​
 + case SIOCADDMULTI:​
 + case SIOCDELMULTI:​
 + case SIOCSIFHWBROADCAST:​
 + case SIOCSMIIREG:​
 + case SIOCBONDENSLAVE:​
 + case SIOCBONDRELEASE:​
 + case SIOCBONDSETHWADDR:​
 + case SIOCBONDCHANGEACTIVE:​
 + case SIOCBRADDIF:​
 + case SIOCBRDELIF:​
 + case SIOCSHWTSTAMP:​
 + if (!ns_capable(net->​user_ns,​ CAP_NET_ADMIN))
 + return -EPERM;
 + /* fall through */
 + case SIOCBONDSLAVEINFOQUERY:​
 + case SIOCBONDINFOQUERY:​
 + dev_load(net,​ ifr->​ifr_name);​
 + rtnl_lock();​
 + ret = dev_ifsioc(net,​ ifr, cmd);
 + rtnl_unlock();​
 + if (need_copyout)
 + *need_copyout = false;
 + return ret;
 </​code>​ </​code>​
  
 +==== dev_ifsioc() ====
  
 +<​code>​
 +static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
 +{
 + int err;
 + struct net_device *dev = __dev_get_by_name(net,​ ifr->​ifr_name);​
 + const struct net_device_ops *ops;
 +
 + if (!dev)
 + return -ENODEV;
 +
 + ops = dev->​netdev_ops;​
 +
 + switch (cmd) {
 + case SIOCSIFFLAGS:​ /​* Set interface flags */
 + return dev_change_flags(dev,​ ifr->​ifr_flags);​
 +</​code>​
 +
 +===== net/​core/​dev.c =====
 +
 +==== dev_change_flags() ====
 +
 +<​code>​
 +int dev_change_flags(struct net_device *dev, unsigned int flags)
 +{
 + int ret;
 + unsigned int changes, old_flags = dev->​flags,​ old_gflags = dev->​gflags;​
 +
 + ret = __dev_change_flags(dev,​ flags);
 + if (ret < 0)
 + return ret;
 +
 + changes = (old_flags ^ dev->​flags) | (old_gflags ^ dev->​gflags);​
 + __dev_notify_flags(dev,​ old_flags, changes);
 + return ret;
 +}
 +</​code>​
 +
 +==== __dev_change_flags() ====
 +
 +<​code>​
 +int __dev_change_flags(struct net_device *dev, unsigned int flags)
 +{
 + unsigned int old_flags = dev->​flags;​
 + int ret;
 +
 + ASSERT_RTNL();​
 +
 + /*
 + * Set the flags on our device.
 + */
 +
 + dev->​flags = (flags & (IFF_DEBUG | IFF_NOTRAILERS | IFF_NOARP |
 +        ​IFF_DYNAMIC | IFF_MULTICAST | IFF_PORTSEL |
 +        ​IFF_AUTOMEDIA)) |
 +      ​(dev->​flags & (IFF_UP | IFF_VOLATILE | IFF_PROMISC |
 +     IFF_ALLMULTI));​
 +
 +... snip ...
 +
 + ret = 0;
 + if ((old_flags ^ flags) & IFF_UP) {
 + if (old_flags & IFF_UP)
 + __dev_close(dev);​
 + else
 + ret = __dev_open(dev);​
 + }
 +</​code>​
ip_up_down.1538650325.txt.gz ยท Last modified: 2018/10/04 10:52 by rpjday