/* * Map an interface index to its name (SIOCGIFNAME)
*/
/* * We need this ioctl for efficient implementation of the * if_indextoname() function required by the IPv6 API. Without * it, we would have to search all the interfaces to find a * match. --pb
*/
/* * Perform a SIOCGIFCONF call. This structure will change * size eventually, and there is nothing I can do about it. * Thus we will need a 'compatibility mode'.
*/ int dev_ifconf(struct net *net, struct ifconf __user *uifc)
{ struct net_device *dev; void __user *pos;
size_t size; int len, total = 0, done;
/* both the ifconf and the ifreq structures are slightly different */ if (in_compat_syscall()) { struct compat_ifconf ifc32;
if (copy_from_user(&ifc32, uifc, sizeof(struct compat_ifconf))) return -EFAULT;
/* Loop over the interfaces, and write an info block for each. */
rtnl_net_lock(net);
for_each_netdev(net, dev) { if (!pos)
done = inet_gifconf(dev, NULL, 0, size); else
done = inet_gifconf(dev, pos + total,
len - total, size); if (done < 0) {
rtnl_net_unlock(net); return -EFAULT;
}
total += done;
}
rtnl_net_unlock(net);
switch (tx_type) { case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_ON: case HWTSTAMP_TX_ONESTEP_SYNC: case HWTSTAMP_TX_ONESTEP_P2P:
tx_type_valid = 1; break; case __HWTSTAMP_TX_CNT: /* not a real value */ break;
}
switch (rx_filter) { case HWTSTAMP_FILTER_NONE: case HWTSTAMP_FILTER_ALL: case HWTSTAMP_FILTER_SOME: case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_NTP_ALL:
rx_filter_valid = 1; break; case __HWTSTAMP_FILTER_CNT: /* not a real value */ break;
}
if (!tx_type_valid || !rx_filter_valid) return -ERANGE;
return 0;
}
/** * dev_get_hwtstamp_phylib() - Get hardware timestamping settings of NIC * or of attached phylib PHY * @dev: Network device * @cfg: Timestamping configuration structure * * Helper for calling the default hardware provider timestamping. * * Note: phy_mii_ioctl() only handles SIOCSHWTSTAMP (not SIOCGHWTSTAMP), and * there only exists a phydev->mii_ts->hwtstamp() method. So this will return * -EOPNOTSUPP for phylib for now, which is still more accurate than letting * the netdev handle the GET request.
*/ int dev_get_hwtstamp_phylib(struct net_device *dev, struct kernel_hwtstamp_config *cfg)
{ struct hwtstamp_provider *hwprov;
hwprov = rtnl_dereference(dev->hwprov); if (hwprov) {
cfg->qualifier = hwprov->desc.qualifier; if (hwprov->source == HWTSTAMP_SOURCE_PHYLIB &&
hwprov->phydev) return phy_hwtstamp_get(hwprov->phydev, cfg);
if (hwprov->source == HWTSTAMP_SOURCE_NETDEV) return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg);
return -EOPNOTSUPP;
}
if (phy_is_default_hwtstamp(dev->phydev)) return phy_hwtstamp_get(dev->phydev, cfg);
/* If the request was resolved through an unconverted driver, omit * the copy_to_user(), since the implementation has already done that
*/ if (!kernel_cfg.copied_to_user) {
hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) return -EFAULT;
}
return 0;
}
/** * dev_set_hwtstamp_phylib() - Change hardware timestamping of NIC * or of attached phylib PHY * @dev: Network device * @cfg: Timestamping configuration structure * @extack: Netlink extended ack message structure, for error reporting * * Helper for enforcing a common policy that phylib timestamping, if available, * should take precedence in front of hardware timestamping provided by the * netdev. If the netdev driver needs to perform specific actions even for PHY * timestamping to work properly (a switch port must trap the timestamped * frames and not forward them), it must set dev->see_all_hwtstamp_requests.
*/ int dev_set_hwtstamp_phylib(struct net_device *dev, struct kernel_hwtstamp_config *cfg, struct netlink_ext_ack *extack)
{ conststruct net_device_ops *ops = dev->netdev_ops; struct kernel_hwtstamp_config old_cfg = {}; struct hwtstamp_provider *hwprov; struct phy_device *phydev; bool changed = false; bool phy_ts; int err;
/* The driver may have modified the configuration, so copy the * updated version of it back to user space
*/ if (!kernel_cfg.copied_to_user) {
hwtstamp_config_from_kernel(&cfg, &kernel_cfg);
if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) return -EFAULT;
}
return 0;
}
staticint generic_hwtstamp_ioctl_lower(struct net_device *dev, int cmd, struct kernel_hwtstamp_config *kernel_cfg)
{ struct ifreq ifrr; int err;
case SIOCSHWTSTAMP: return dev_set_hwtstamp(dev, ifr);
case SIOCGHWTSTAMP: return dev_get_hwtstamp(dev, ifr);
case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: return dev_eth_ioctl(dev, ifr, cmd);
case SIOCBONDENSLAVE: case SIOCBONDRELEASE: case SIOCBONDSETHWADDR: case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY: case SIOCBONDCHANGEACTIVE: return dev_siocbond(dev, ifr, cmd);
/** * dev_load - load a network module * @net: the applicable net namespace * @name: name of interface * * If a network interface is not present and the process has suitable * privileges this function loads the module. If module loading is not * available in this kernel then it becomes a nop.
*/
void dev_load(struct net *net, constchar *name)
{ struct net_device *dev; int no_module;
rcu_read_lock();
dev = dev_get_by_name_rcu(net, name);
rcu_read_unlock();
no_module = !dev; if (no_module && capable(CAP_NET_ADMIN))
no_module = request_module("netdev-%s", name); if (no_module && capable(CAP_SYS_MODULE))
request_module("%s", name);
}
EXPORT_SYMBOL(dev_load);
/* * This function handles all "interface"-type I/O control requests. The actual * 'doing' part of this is dev_ifsioc above.
*/
/** * dev_ioctl - network device ioctl * @net: the applicable net namespace * @cmd: command to issue * @ifr: pointer to a struct ifreq in user space * @data: data exchanged with userspace * @need_copyout: whether or not copy_to_user() should be called * * Issue ioctl functions to devices. This is normally called by the * user space syscall interfaces but can sometimes be useful for * other purposes. The return value is the return from the syscall if * positive or a negative errno code on error.
*/
int dev_ioctl(struct net *net, unsignedint cmd, struct ifreq *ifr, void __user *data, bool *need_copyout)
{ int ret; char *colon;
if (need_copyout)
*need_copyout = true; if (cmd == SIOCGIFNAME) return dev_ifname(net, ifr);
ifr->ifr_name[IFNAMSIZ-1] = 0;
colon = strchr(ifr->ifr_name, ':'); if (colon)
*colon = 0;
/* * See which interface the caller is talking about.
*/
switch (cmd) { case SIOCGIFHWADDR:
dev_load(net, ifr->ifr_name);
ret = netif_get_mac_address(&ifr->ifr_hwaddr, net,
ifr->ifr_name); if (colon)
*colon = ':'; return ret; /* * These ioctl calls: * - can be done by all. * - atomic and do not require locking. * - return a value
*/ case SIOCGIFFLAGS: case SIOCGIFMETRIC: case SIOCGIFMTU: 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;
case SIOCETHTOOL:
dev_load(net, ifr->ifr_name);
ret = dev_ethtool(net, ifr, data); if (colon)
*colon = ':'; return ret;
/* * These ioctl calls: * - require superuser power. * - require strict serialization. * - return a value
*/ case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSIFNAME:
dev_load(net, ifr->ifr_name); if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM;
rtnl_net_lock(net);
ret = dev_ifsioc(net, ifr, data, cmd);
rtnl_net_unlock(net);
if (colon)
*colon = ':'; return ret;
/* * These ioctl calls: * - require superuser power. * - require strict serialization. * - do not return a value
*/ case SIOCSIFMAP: case SIOCSIFTXQLEN: if (!capable(CAP_NET_ADMIN)) return -EPERM;
fallthrough; /* * These ioctl calls: * - require local superuser power. * - require strict serialization. * - do not return a value
*/ 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 SIOCSHWTSTAMP: if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM;
fallthrough; case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY:
dev_load(net, ifr->ifr_name);
rtnl_net_lock(net);
ret = dev_ifsioc(net, ifr, data, cmd);
rtnl_net_unlock(net);
if (need_copyout)
*need_copyout = false; return ret;
case SIOCGIFMEM: /* Get the per device memory space. We can add this but
* currently do not support it */ case SIOCSIFMEM: /* Set the per device memory buffer space.
* Not applicable in our case */ case SIOCSIFLINK: return -ENOTTY;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.