1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <linux/kmod.h> |
3 | #include <linux/netdevice.h> |
4 | #include <linux/inetdevice.h> |
5 | #include <linux/etherdevice.h> |
6 | #include <linux/rtnetlink.h> |
7 | #include <linux/net_tstamp.h> |
8 | #include <linux/phylib_stubs.h> |
9 | #include <linux/wireless.h> |
10 | #include <linux/if_bridge.h> |
11 | #include <net/dsa_stubs.h> |
12 | #include <net/wext.h> |
13 | |
14 | #include "dev.h" |
15 | |
16 | /* |
17 | * Map an interface index to its name (SIOCGIFNAME) |
18 | */ |
19 | |
20 | /* |
21 | * We need this ioctl for efficient implementation of the |
22 | * if_indextoname() function required by the IPv6 API. Without |
23 | * it, we would have to search all the interfaces to find a |
24 | * match. --pb |
25 | */ |
26 | |
27 | static int dev_ifname(struct net *net, struct ifreq *ifr) |
28 | { |
29 | ifr->ifr_name[IFNAMSIZ-1] = 0; |
30 | return netdev_get_name(net, name: ifr->ifr_name, ifindex: ifr->ifr_ifindex); |
31 | } |
32 | |
33 | /* |
34 | * Perform a SIOCGIFCONF call. This structure will change |
35 | * size eventually, and there is nothing I can do about it. |
36 | * Thus we will need a 'compatibility mode'. |
37 | */ |
38 | int dev_ifconf(struct net *net, struct ifconf __user *uifc) |
39 | { |
40 | struct net_device *dev; |
41 | void __user *pos; |
42 | size_t size; |
43 | int len, total = 0, done; |
44 | |
45 | /* both the ifconf and the ifreq structures are slightly different */ |
46 | if (in_compat_syscall()) { |
47 | struct compat_ifconf ifc32; |
48 | |
49 | if (copy_from_user(to: &ifc32, from: uifc, n: sizeof(struct compat_ifconf))) |
50 | return -EFAULT; |
51 | |
52 | pos = compat_ptr(uptr: ifc32.ifcbuf); |
53 | len = ifc32.ifc_len; |
54 | size = sizeof(struct compat_ifreq); |
55 | } else { |
56 | struct ifconf ifc; |
57 | |
58 | if (copy_from_user(to: &ifc, from: uifc, n: sizeof(struct ifconf))) |
59 | return -EFAULT; |
60 | |
61 | pos = ifc.ifc_buf; |
62 | len = ifc.ifc_len; |
63 | size = sizeof(struct ifreq); |
64 | } |
65 | |
66 | /* Loop over the interfaces, and write an info block for each. */ |
67 | rtnl_lock(); |
68 | for_each_netdev(net, dev) { |
69 | if (!pos) |
70 | done = inet_gifconf(dev, NULL, len: 0, size); |
71 | else |
72 | done = inet_gifconf(dev, buf: pos + total, |
73 | len: len - total, size); |
74 | if (done < 0) { |
75 | rtnl_unlock(); |
76 | return -EFAULT; |
77 | } |
78 | total += done; |
79 | } |
80 | rtnl_unlock(); |
81 | |
82 | return put_user(total, &uifc->ifc_len); |
83 | } |
84 | |
85 | static int dev_getifmap(struct net_device *dev, struct ifreq *ifr) |
86 | { |
87 | struct ifmap *ifmap = &ifr->ifr_map; |
88 | |
89 | if (in_compat_syscall()) { |
90 | struct compat_ifmap *cifmap = (struct compat_ifmap *)ifmap; |
91 | |
92 | cifmap->mem_start = dev->mem_start; |
93 | cifmap->mem_end = dev->mem_end; |
94 | cifmap->base_addr = dev->base_addr; |
95 | cifmap->irq = dev->irq; |
96 | cifmap->dma = dev->dma; |
97 | cifmap->port = dev->if_port; |
98 | |
99 | return 0; |
100 | } |
101 | |
102 | ifmap->mem_start = dev->mem_start; |
103 | ifmap->mem_end = dev->mem_end; |
104 | ifmap->base_addr = dev->base_addr; |
105 | ifmap->irq = dev->irq; |
106 | ifmap->dma = dev->dma; |
107 | ifmap->port = dev->if_port; |
108 | |
109 | return 0; |
110 | } |
111 | |
112 | static int dev_setifmap(struct net_device *dev, struct ifreq *ifr) |
113 | { |
114 | struct compat_ifmap *cifmap = (struct compat_ifmap *)&ifr->ifr_map; |
115 | |
116 | if (!dev->netdev_ops->ndo_set_config) |
117 | return -EOPNOTSUPP; |
118 | |
119 | if (in_compat_syscall()) { |
120 | struct ifmap ifmap = { |
121 | .mem_start = cifmap->mem_start, |
122 | .mem_end = cifmap->mem_end, |
123 | .base_addr = cifmap->base_addr, |
124 | .irq = cifmap->irq, |
125 | .dma = cifmap->dma, |
126 | .port = cifmap->port, |
127 | }; |
128 | |
129 | return dev->netdev_ops->ndo_set_config(dev, &ifmap); |
130 | } |
131 | |
132 | return dev->netdev_ops->ndo_set_config(dev, &ifr->ifr_map); |
133 | } |
134 | |
135 | /* |
136 | * Perform the SIOCxIFxxx calls, inside rcu_read_lock() |
137 | */ |
138 | static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd) |
139 | { |
140 | int err; |
141 | struct net_device *dev = dev_get_by_name_rcu(net, name: ifr->ifr_name); |
142 | |
143 | if (!dev) |
144 | return -ENODEV; |
145 | |
146 | switch (cmd) { |
147 | case SIOCGIFFLAGS: /* Get interface flags */ |
148 | ifr->ifr_flags = (short) dev_get_flags(dev); |
149 | return 0; |
150 | |
151 | case SIOCGIFMETRIC: /* Get the metric on the interface |
152 | (currently unused) */ |
153 | ifr->ifr_metric = 0; |
154 | return 0; |
155 | |
156 | case SIOCGIFMTU: /* Get the MTU of a device */ |
157 | ifr->ifr_mtu = dev->mtu; |
158 | return 0; |
159 | |
160 | case SIOCGIFSLAVE: |
161 | err = -EINVAL; |
162 | break; |
163 | |
164 | case SIOCGIFMAP: |
165 | return dev_getifmap(dev, ifr); |
166 | |
167 | case SIOCGIFINDEX: |
168 | ifr->ifr_ifindex = dev->ifindex; |
169 | return 0; |
170 | |
171 | case SIOCGIFTXQLEN: |
172 | ifr->ifr_qlen = dev->tx_queue_len; |
173 | return 0; |
174 | |
175 | default: |
176 | /* dev_ioctl() should ensure this case |
177 | * is never reached |
178 | */ |
179 | WARN_ON(1); |
180 | err = -ENOTTY; |
181 | break; |
182 | |
183 | } |
184 | return err; |
185 | } |
186 | |
187 | static int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg) |
188 | { |
189 | enum hwtstamp_tx_types tx_type; |
190 | enum hwtstamp_rx_filters rx_filter; |
191 | int tx_type_valid = 0; |
192 | int rx_filter_valid = 0; |
193 | |
194 | if (cfg->flags & ~HWTSTAMP_FLAG_MASK) |
195 | return -EINVAL; |
196 | |
197 | tx_type = cfg->tx_type; |
198 | rx_filter = cfg->rx_filter; |
199 | |
200 | switch (tx_type) { |
201 | case HWTSTAMP_TX_OFF: |
202 | case HWTSTAMP_TX_ON: |
203 | case HWTSTAMP_TX_ONESTEP_SYNC: |
204 | case HWTSTAMP_TX_ONESTEP_P2P: |
205 | tx_type_valid = 1; |
206 | break; |
207 | case __HWTSTAMP_TX_CNT: |
208 | /* not a real value */ |
209 | break; |
210 | } |
211 | |
212 | switch (rx_filter) { |
213 | case HWTSTAMP_FILTER_NONE: |
214 | case HWTSTAMP_FILTER_ALL: |
215 | case HWTSTAMP_FILTER_SOME: |
216 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: |
217 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: |
218 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: |
219 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: |
220 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: |
221 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: |
222 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: |
223 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: |
224 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: |
225 | case HWTSTAMP_FILTER_PTP_V2_EVENT: |
226 | case HWTSTAMP_FILTER_PTP_V2_SYNC: |
227 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: |
228 | case HWTSTAMP_FILTER_NTP_ALL: |
229 | rx_filter_valid = 1; |
230 | break; |
231 | case __HWTSTAMP_FILTER_CNT: |
232 | /* not a real value */ |
233 | break; |
234 | } |
235 | |
236 | if (!tx_type_valid || !rx_filter_valid) |
237 | return -ERANGE; |
238 | |
239 | return 0; |
240 | } |
241 | |
242 | static int dev_eth_ioctl(struct net_device *dev, |
243 | struct ifreq *ifr, unsigned int cmd) |
244 | { |
245 | const struct net_device_ops *ops = dev->netdev_ops; |
246 | |
247 | if (!ops->ndo_eth_ioctl) |
248 | return -EOPNOTSUPP; |
249 | |
250 | if (!netif_device_present(dev)) |
251 | return -ENODEV; |
252 | |
253 | return ops->ndo_eth_ioctl(dev, ifr, cmd); |
254 | } |
255 | |
256 | /** |
257 | * dev_get_hwtstamp_phylib() - Get hardware timestamping settings of NIC |
258 | * or of attached phylib PHY |
259 | * @dev: Network device |
260 | * @cfg: Timestamping configuration structure |
261 | * |
262 | * Helper for enforcing a common policy that phylib timestamping, if available, |
263 | * should take precedence in front of hardware timestamping provided by the |
264 | * netdev. |
265 | * |
266 | * Note: phy_mii_ioctl() only handles SIOCSHWTSTAMP (not SIOCGHWTSTAMP), and |
267 | * there only exists a phydev->mii_ts->hwtstamp() method. So this will return |
268 | * -EOPNOTSUPP for phylib for now, which is still more accurate than letting |
269 | * the netdev handle the GET request. |
270 | */ |
271 | static int dev_get_hwtstamp_phylib(struct net_device *dev, |
272 | struct kernel_hwtstamp_config *cfg) |
273 | { |
274 | if (phy_has_hwtstamp(phydev: dev->phydev)) |
275 | return phy_hwtstamp_get(phydev: dev->phydev, config: cfg); |
276 | |
277 | return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg); |
278 | } |
279 | |
280 | static int dev_get_hwtstamp(struct net_device *dev, struct ifreq *ifr) |
281 | { |
282 | const struct net_device_ops *ops = dev->netdev_ops; |
283 | struct kernel_hwtstamp_config kernel_cfg = {}; |
284 | struct hwtstamp_config cfg; |
285 | int err; |
286 | |
287 | if (!ops->ndo_hwtstamp_get) |
288 | return dev_eth_ioctl(dev, ifr, SIOCGHWTSTAMP); /* legacy */ |
289 | |
290 | if (!netif_device_present(dev)) |
291 | return -ENODEV; |
292 | |
293 | kernel_cfg.ifr = ifr; |
294 | err = dev_get_hwtstamp_phylib(dev, cfg: &kernel_cfg); |
295 | if (err) |
296 | return err; |
297 | |
298 | /* If the request was resolved through an unconverted driver, omit |
299 | * the copy_to_user(), since the implementation has already done that |
300 | */ |
301 | if (!kernel_cfg.copied_to_user) { |
302 | hwtstamp_config_from_kernel(cfg: &cfg, kernel_cfg: &kernel_cfg); |
303 | |
304 | if (copy_to_user(to: ifr->ifr_data, from: &cfg, n: sizeof(cfg))) |
305 | return -EFAULT; |
306 | } |
307 | |
308 | return 0; |
309 | } |
310 | |
311 | /** |
312 | * dev_set_hwtstamp_phylib() - Change hardware timestamping of NIC |
313 | * or of attached phylib PHY |
314 | * @dev: Network device |
315 | * @cfg: Timestamping configuration structure |
316 | * @extack: Netlink extended ack message structure, for error reporting |
317 | * |
318 | * Helper for enforcing a common policy that phylib timestamping, if available, |
319 | * should take precedence in front of hardware timestamping provided by the |
320 | * netdev. If the netdev driver needs to perform specific actions even for PHY |
321 | * timestamping to work properly (a switch port must trap the timestamped |
322 | * frames and not forward them), it must set IFF_SEE_ALL_HWTSTAMP_REQUESTS in |
323 | * dev->priv_flags. |
324 | */ |
325 | static int dev_set_hwtstamp_phylib(struct net_device *dev, |
326 | struct kernel_hwtstamp_config *cfg, |
327 | struct netlink_ext_ack *extack) |
328 | { |
329 | const struct net_device_ops *ops = dev->netdev_ops; |
330 | bool phy_ts = phy_has_hwtstamp(phydev: dev->phydev); |
331 | struct kernel_hwtstamp_config old_cfg = {}; |
332 | bool changed = false; |
333 | int err; |
334 | |
335 | cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV; |
336 | |
337 | if (phy_ts && (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) { |
338 | err = ops->ndo_hwtstamp_get(dev, &old_cfg); |
339 | if (err) |
340 | return err; |
341 | } |
342 | |
343 | if (!phy_ts || (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) { |
344 | err = ops->ndo_hwtstamp_set(dev, cfg, extack); |
345 | if (err) { |
346 | if (extack->_msg) |
347 | netdev_err(dev, format: "%s\n" , extack->_msg); |
348 | return err; |
349 | } |
350 | } |
351 | |
352 | if (phy_ts && (dev->priv_flags & IFF_SEE_ALL_HWTSTAMP_REQUESTS)) |
353 | changed = kernel_hwtstamp_config_changed(a: &old_cfg, b: cfg); |
354 | |
355 | if (phy_ts) { |
356 | err = phy_hwtstamp_set(phydev: dev->phydev, config: cfg, extack); |
357 | if (err) { |
358 | if (changed) |
359 | ops->ndo_hwtstamp_set(dev, &old_cfg, NULL); |
360 | return err; |
361 | } |
362 | } |
363 | |
364 | return 0; |
365 | } |
366 | |
367 | static int dev_set_hwtstamp(struct net_device *dev, struct ifreq *ifr) |
368 | { |
369 | const struct net_device_ops *ops = dev->netdev_ops; |
370 | struct kernel_hwtstamp_config kernel_cfg = {}; |
371 | struct netlink_ext_ack extack = {}; |
372 | struct hwtstamp_config cfg; |
373 | int err; |
374 | |
375 | if (copy_from_user(to: &cfg, from: ifr->ifr_data, n: sizeof(cfg))) |
376 | return -EFAULT; |
377 | |
378 | hwtstamp_config_to_kernel(kernel_cfg: &kernel_cfg, cfg: &cfg); |
379 | kernel_cfg.ifr = ifr; |
380 | |
381 | err = net_hwtstamp_validate(cfg: &kernel_cfg); |
382 | if (err) |
383 | return err; |
384 | |
385 | err = dsa_conduit_hwtstamp_validate(dev, config: &kernel_cfg, extack: &extack); |
386 | if (err) { |
387 | if (extack._msg) |
388 | netdev_err(dev, format: "%s\n" , extack._msg); |
389 | return err; |
390 | } |
391 | |
392 | if (!ops->ndo_hwtstamp_set) |
393 | return dev_eth_ioctl(dev, ifr, SIOCSHWTSTAMP); /* legacy */ |
394 | |
395 | if (!netif_device_present(dev)) |
396 | return -ENODEV; |
397 | |
398 | err = dev_set_hwtstamp_phylib(dev, cfg: &kernel_cfg, extack: &extack); |
399 | if (err) |
400 | return err; |
401 | |
402 | /* The driver may have modified the configuration, so copy the |
403 | * updated version of it back to user space |
404 | */ |
405 | if (!kernel_cfg.copied_to_user) { |
406 | hwtstamp_config_from_kernel(cfg: &cfg, kernel_cfg: &kernel_cfg); |
407 | |
408 | if (copy_to_user(to: ifr->ifr_data, from: &cfg, n: sizeof(cfg))) |
409 | return -EFAULT; |
410 | } |
411 | |
412 | return 0; |
413 | } |
414 | |
415 | static int generic_hwtstamp_ioctl_lower(struct net_device *dev, int cmd, |
416 | struct kernel_hwtstamp_config *kernel_cfg) |
417 | { |
418 | struct ifreq ifrr; |
419 | int err; |
420 | |
421 | strscpy_pad(dest: ifrr.ifr_name, src: dev->name, IFNAMSIZ); |
422 | ifrr.ifr_ifru = kernel_cfg->ifr->ifr_ifru; |
423 | |
424 | err = dev_eth_ioctl(dev, ifr: &ifrr, cmd); |
425 | if (err) |
426 | return err; |
427 | |
428 | kernel_cfg->ifr->ifr_ifru = ifrr.ifr_ifru; |
429 | kernel_cfg->copied_to_user = true; |
430 | |
431 | return 0; |
432 | } |
433 | |
434 | int generic_hwtstamp_get_lower(struct net_device *dev, |
435 | struct kernel_hwtstamp_config *kernel_cfg) |
436 | { |
437 | const struct net_device_ops *ops = dev->netdev_ops; |
438 | |
439 | if (!netif_device_present(dev)) |
440 | return -ENODEV; |
441 | |
442 | if (ops->ndo_hwtstamp_get) |
443 | return dev_get_hwtstamp_phylib(dev, cfg: kernel_cfg); |
444 | |
445 | /* Legacy path: unconverted lower driver */ |
446 | return generic_hwtstamp_ioctl_lower(dev, SIOCGHWTSTAMP, kernel_cfg); |
447 | } |
448 | EXPORT_SYMBOL(generic_hwtstamp_get_lower); |
449 | |
450 | int generic_hwtstamp_set_lower(struct net_device *dev, |
451 | struct kernel_hwtstamp_config *kernel_cfg, |
452 | struct netlink_ext_ack *extack) |
453 | { |
454 | const struct net_device_ops *ops = dev->netdev_ops; |
455 | |
456 | if (!netif_device_present(dev)) |
457 | return -ENODEV; |
458 | |
459 | if (ops->ndo_hwtstamp_set) |
460 | return dev_set_hwtstamp_phylib(dev, cfg: kernel_cfg, extack); |
461 | |
462 | /* Legacy path: unconverted lower driver */ |
463 | return generic_hwtstamp_ioctl_lower(dev, SIOCSHWTSTAMP, kernel_cfg); |
464 | } |
465 | EXPORT_SYMBOL(generic_hwtstamp_set_lower); |
466 | |
467 | static int dev_siocbond(struct net_device *dev, |
468 | struct ifreq *ifr, unsigned int cmd) |
469 | { |
470 | const struct net_device_ops *ops = dev->netdev_ops; |
471 | |
472 | if (ops->ndo_siocbond) { |
473 | if (netif_device_present(dev)) |
474 | return ops->ndo_siocbond(dev, ifr, cmd); |
475 | else |
476 | return -ENODEV; |
477 | } |
478 | |
479 | return -EOPNOTSUPP; |
480 | } |
481 | |
482 | static int dev_siocdevprivate(struct net_device *dev, struct ifreq *ifr, |
483 | void __user *data, unsigned int cmd) |
484 | { |
485 | const struct net_device_ops *ops = dev->netdev_ops; |
486 | |
487 | if (ops->ndo_siocdevprivate) { |
488 | if (netif_device_present(dev)) |
489 | return ops->ndo_siocdevprivate(dev, ifr, data, cmd); |
490 | else |
491 | return -ENODEV; |
492 | } |
493 | |
494 | return -EOPNOTSUPP; |
495 | } |
496 | |
497 | static int dev_siocwandev(struct net_device *dev, struct if_settings *ifs) |
498 | { |
499 | const struct net_device_ops *ops = dev->netdev_ops; |
500 | |
501 | if (ops->ndo_siocwandev) { |
502 | if (netif_device_present(dev)) |
503 | return ops->ndo_siocwandev(dev, ifs); |
504 | else |
505 | return -ENODEV; |
506 | } |
507 | |
508 | return -EOPNOTSUPP; |
509 | } |
510 | |
511 | /* |
512 | * Perform the SIOCxIFxxx calls, inside rtnl_lock() |
513 | */ |
514 | static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data, |
515 | unsigned int cmd) |
516 | { |
517 | int err; |
518 | struct net_device *dev = __dev_get_by_name(net, name: ifr->ifr_name); |
519 | const struct net_device_ops *ops; |
520 | netdevice_tracker dev_tracker; |
521 | |
522 | if (!dev) |
523 | return -ENODEV; |
524 | |
525 | ops = dev->netdev_ops; |
526 | |
527 | switch (cmd) { |
528 | case SIOCSIFFLAGS: /* Set interface flags */ |
529 | return dev_change_flags(dev, flags: ifr->ifr_flags, NULL); |
530 | |
531 | case SIOCSIFMETRIC: /* Set the metric on the interface |
532 | (currently unused) */ |
533 | return -EOPNOTSUPP; |
534 | |
535 | case SIOCSIFMTU: /* Set the MTU of a device */ |
536 | return dev_set_mtu(dev, ifr->ifr_mtu); |
537 | |
538 | case SIOCSIFHWADDR: |
539 | if (dev->addr_len > sizeof(struct sockaddr)) |
540 | return -EINVAL; |
541 | return dev_set_mac_address_user(dev, sa: &ifr->ifr_hwaddr, NULL); |
542 | |
543 | case SIOCSIFHWBROADCAST: |
544 | if (ifr->ifr_hwaddr.sa_family != dev->type) |
545 | return -EINVAL; |
546 | memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data, |
547 | min(sizeof(ifr->ifr_hwaddr.sa_data_min), |
548 | (size_t)dev->addr_len)); |
549 | call_netdevice_notifiers(val: NETDEV_CHANGEADDR, dev); |
550 | return 0; |
551 | |
552 | case SIOCSIFMAP: |
553 | return dev_setifmap(dev, ifr); |
554 | |
555 | case SIOCADDMULTI: |
556 | if (!ops->ndo_set_rx_mode || |
557 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
558 | return -EINVAL; |
559 | if (!netif_device_present(dev)) |
560 | return -ENODEV; |
561 | return dev_mc_add_global(dev, addr: ifr->ifr_hwaddr.sa_data); |
562 | |
563 | case SIOCDELMULTI: |
564 | if (!ops->ndo_set_rx_mode || |
565 | ifr->ifr_hwaddr.sa_family != AF_UNSPEC) |
566 | return -EINVAL; |
567 | if (!netif_device_present(dev)) |
568 | return -ENODEV; |
569 | return dev_mc_del_global(dev, addr: ifr->ifr_hwaddr.sa_data); |
570 | |
571 | case SIOCSIFTXQLEN: |
572 | if (ifr->ifr_qlen < 0) |
573 | return -EINVAL; |
574 | return dev_change_tx_queue_len(dev, new_len: ifr->ifr_qlen); |
575 | |
576 | case SIOCSIFNAME: |
577 | ifr->ifr_newname[IFNAMSIZ-1] = '\0'; |
578 | return dev_change_name(dev, newname: ifr->ifr_newname); |
579 | |
580 | case SIOCWANDEV: |
581 | return dev_siocwandev(dev, ifs: &ifr->ifr_settings); |
582 | |
583 | case SIOCBRADDIF: |
584 | case SIOCBRDELIF: |
585 | if (!netif_device_present(dev)) |
586 | return -ENODEV; |
587 | if (!netif_is_bridge_master(dev)) |
588 | return -EOPNOTSUPP; |
589 | netdev_hold(dev, tracker: &dev_tracker, GFP_KERNEL); |
590 | rtnl_unlock(); |
591 | err = br_ioctl_call(net, br: netdev_priv(dev), cmd, ifr, NULL); |
592 | netdev_put(dev, tracker: &dev_tracker); |
593 | rtnl_lock(); |
594 | return err; |
595 | |
596 | case SIOCDEVPRIVATE ... SIOCDEVPRIVATE + 15: |
597 | return dev_siocdevprivate(dev, ifr, data, cmd); |
598 | |
599 | case SIOCSHWTSTAMP: |
600 | return dev_set_hwtstamp(dev, ifr); |
601 | |
602 | case SIOCGHWTSTAMP: |
603 | return dev_get_hwtstamp(dev, ifr); |
604 | |
605 | case SIOCGMIIPHY: |
606 | case SIOCGMIIREG: |
607 | case SIOCSMIIREG: |
608 | return dev_eth_ioctl(dev, ifr, cmd); |
609 | |
610 | case SIOCBONDENSLAVE: |
611 | case SIOCBONDRELEASE: |
612 | case SIOCBONDSETHWADDR: |
613 | case SIOCBONDSLAVEINFOQUERY: |
614 | case SIOCBONDINFOQUERY: |
615 | case SIOCBONDCHANGEACTIVE: |
616 | return dev_siocbond(dev, ifr, cmd); |
617 | |
618 | /* Unknown ioctl */ |
619 | default: |
620 | err = -EINVAL; |
621 | } |
622 | return err; |
623 | } |
624 | |
625 | /** |
626 | * dev_load - load a network module |
627 | * @net: the applicable net namespace |
628 | * @name: name of interface |
629 | * |
630 | * If a network interface is not present and the process has suitable |
631 | * privileges this function loads the module. If module loading is not |
632 | * available in this kernel then it becomes a nop. |
633 | */ |
634 | |
635 | void dev_load(struct net *net, const char *name) |
636 | { |
637 | struct net_device *dev; |
638 | int no_module; |
639 | |
640 | rcu_read_lock(); |
641 | dev = dev_get_by_name_rcu(net, name); |
642 | rcu_read_unlock(); |
643 | |
644 | no_module = !dev; |
645 | if (no_module && capable(CAP_NET_ADMIN)) |
646 | no_module = request_module("netdev-%s" , name); |
647 | if (no_module && capable(CAP_SYS_MODULE)) |
648 | request_module("%s" , name); |
649 | } |
650 | EXPORT_SYMBOL(dev_load); |
651 | |
652 | /* |
653 | * This function handles all "interface"-type I/O control requests. The actual |
654 | * 'doing' part of this is dev_ifsioc above. |
655 | */ |
656 | |
657 | /** |
658 | * dev_ioctl - network device ioctl |
659 | * @net: the applicable net namespace |
660 | * @cmd: command to issue |
661 | * @ifr: pointer to a struct ifreq in user space |
662 | * @data: data exchanged with userspace |
663 | * @need_copyout: whether or not copy_to_user() should be called |
664 | * |
665 | * Issue ioctl functions to devices. This is normally called by the |
666 | * user space syscall interfaces but can sometimes be useful for |
667 | * other purposes. The return value is the return from the syscall if |
668 | * positive or a negative errno code on error. |
669 | */ |
670 | |
671 | int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, |
672 | void __user *data, bool *need_copyout) |
673 | { |
674 | int ret; |
675 | char *colon; |
676 | |
677 | if (need_copyout) |
678 | *need_copyout = true; |
679 | if (cmd == SIOCGIFNAME) |
680 | return dev_ifname(net, ifr); |
681 | |
682 | ifr->ifr_name[IFNAMSIZ-1] = 0; |
683 | |
684 | colon = strchr(ifr->ifr_name, ':'); |
685 | if (colon) |
686 | *colon = 0; |
687 | |
688 | /* |
689 | * See which interface the caller is talking about. |
690 | */ |
691 | |
692 | switch (cmd) { |
693 | case SIOCGIFHWADDR: |
694 | dev_load(net, ifr->ifr_name); |
695 | ret = dev_get_mac_address(sa: &ifr->ifr_hwaddr, net, dev_name: ifr->ifr_name); |
696 | if (colon) |
697 | *colon = ':'; |
698 | return ret; |
699 | /* |
700 | * These ioctl calls: |
701 | * - can be done by all. |
702 | * - atomic and do not require locking. |
703 | * - return a value |
704 | */ |
705 | case SIOCGIFFLAGS: |
706 | case SIOCGIFMETRIC: |
707 | case SIOCGIFMTU: |
708 | case SIOCGIFSLAVE: |
709 | case SIOCGIFMAP: |
710 | case SIOCGIFINDEX: |
711 | case SIOCGIFTXQLEN: |
712 | dev_load(net, ifr->ifr_name); |
713 | rcu_read_lock(); |
714 | ret = dev_ifsioc_locked(net, ifr, cmd); |
715 | rcu_read_unlock(); |
716 | if (colon) |
717 | *colon = ':'; |
718 | return ret; |
719 | |
720 | case SIOCETHTOOL: |
721 | dev_load(net, ifr->ifr_name); |
722 | ret = dev_ethtool(net, ifr, userdata: data); |
723 | if (colon) |
724 | *colon = ':'; |
725 | return ret; |
726 | |
727 | /* |
728 | * These ioctl calls: |
729 | * - require superuser power. |
730 | * - require strict serialization. |
731 | * - return a value |
732 | */ |
733 | case SIOCGMIIPHY: |
734 | case SIOCGMIIREG: |
735 | case SIOCSIFNAME: |
736 | dev_load(net, ifr->ifr_name); |
737 | if (!ns_capable(ns: net->user_ns, CAP_NET_ADMIN)) |
738 | return -EPERM; |
739 | rtnl_lock(); |
740 | ret = dev_ifsioc(net, ifr, data, cmd); |
741 | rtnl_unlock(); |
742 | if (colon) |
743 | *colon = ':'; |
744 | return ret; |
745 | |
746 | /* |
747 | * These ioctl calls: |
748 | * - require superuser power. |
749 | * - require strict serialization. |
750 | * - do not return a value |
751 | */ |
752 | case SIOCSIFMAP: |
753 | case SIOCSIFTXQLEN: |
754 | if (!capable(CAP_NET_ADMIN)) |
755 | return -EPERM; |
756 | fallthrough; |
757 | /* |
758 | * These ioctl calls: |
759 | * - require local superuser power. |
760 | * - require strict serialization. |
761 | * - do not return a value |
762 | */ |
763 | case SIOCSIFFLAGS: |
764 | case SIOCSIFMETRIC: |
765 | case SIOCSIFMTU: |
766 | case SIOCSIFHWADDR: |
767 | case SIOCSIFSLAVE: |
768 | case SIOCADDMULTI: |
769 | case SIOCDELMULTI: |
770 | case SIOCSIFHWBROADCAST: |
771 | case SIOCSMIIREG: |
772 | case SIOCBONDENSLAVE: |
773 | case SIOCBONDRELEASE: |
774 | case SIOCBONDSETHWADDR: |
775 | case SIOCBONDCHANGEACTIVE: |
776 | case SIOCBRADDIF: |
777 | case SIOCBRDELIF: |
778 | case SIOCSHWTSTAMP: |
779 | if (!ns_capable(ns: net->user_ns, CAP_NET_ADMIN)) |
780 | return -EPERM; |
781 | fallthrough; |
782 | case SIOCBONDSLAVEINFOQUERY: |
783 | case SIOCBONDINFOQUERY: |
784 | dev_load(net, ifr->ifr_name); |
785 | rtnl_lock(); |
786 | ret = dev_ifsioc(net, ifr, data, cmd); |
787 | rtnl_unlock(); |
788 | if (need_copyout) |
789 | *need_copyout = false; |
790 | return ret; |
791 | |
792 | case SIOCGIFMEM: |
793 | /* Get the per device memory space. We can add this but |
794 | * currently do not support it */ |
795 | case SIOCSIFMEM: |
796 | /* Set the per device memory buffer space. |
797 | * Not applicable in our case */ |
798 | case SIOCSIFLINK: |
799 | return -ENOTTY; |
800 | |
801 | /* |
802 | * Unknown or private ioctl. |
803 | */ |
804 | default: |
805 | if (cmd == SIOCWANDEV || |
806 | cmd == SIOCGHWTSTAMP || |
807 | (cmd >= SIOCDEVPRIVATE && |
808 | cmd <= SIOCDEVPRIVATE + 15)) { |
809 | dev_load(net, ifr->ifr_name); |
810 | rtnl_lock(); |
811 | ret = dev_ifsioc(net, ifr, data, cmd); |
812 | rtnl_unlock(); |
813 | return ret; |
814 | } |
815 | return -ENOTTY; |
816 | } |
817 | } |
818 | |