| .. | .. |
|---|
| 17 | 17 | #include <linux/etherdevice.h> |
|---|
| 18 | 18 | #include <linux/ethtool.h> |
|---|
| 19 | 19 | #include <linux/if_vlan.h> |
|---|
| 20 | +#include <linux/string_helpers.h> |
|---|
| 20 | 21 | |
|---|
| 21 | 22 | #include "u_ether.h" |
|---|
| 22 | 23 | |
|---|
| .. | .. |
|---|
| 80 | 81 | |
|---|
| 81 | 82 | bool zlp; |
|---|
| 82 | 83 | bool no_skb_reserve; |
|---|
| 84 | + bool ifname_set; |
|---|
| 83 | 85 | u8 host_mac[ETH_ALEN]; |
|---|
| 84 | 86 | u8 dev_mac[ETH_ALEN]; |
|---|
| 85 | 87 | }; |
|---|
| .. | .. |
|---|
| 322 | 324 | /* data overrun */ |
|---|
| 323 | 325 | case -EOVERFLOW: |
|---|
| 324 | 326 | dev->net->stats.rx_over_errors++; |
|---|
| 325 | | - /* FALLTHROUGH */ |
|---|
| 327 | + fallthrough; |
|---|
| 326 | 328 | |
|---|
| 327 | 329 | default: |
|---|
| 328 | 330 | dev->net->stats.rx_errors++; |
|---|
| .. | .. |
|---|
| 445 | 447 | default: |
|---|
| 446 | 448 | dev->net->stats.tx_errors++; |
|---|
| 447 | 449 | VDBG(dev, "tx err %d\n", req->status); |
|---|
| 448 | | - /* FALLTHROUGH */ |
|---|
| 450 | + fallthrough; |
|---|
| 449 | 451 | case -ECONNRESET: /* unlink */ |
|---|
| 450 | 452 | case -ESHUTDOWN: /* disconnect etc */ |
|---|
| 451 | 453 | dev_kfree_skb_any(skb); |
|---|
| .. | .. |
|---|
| 732 | 734 | .name = "gadget", |
|---|
| 733 | 735 | }; |
|---|
| 734 | 736 | |
|---|
| 735 | | -/** |
|---|
| 737 | +/* |
|---|
| 736 | 738 | * gether_setup_name - initialize one ethernet-over-usb link |
|---|
| 737 | 739 | * @g: gadget to associated with these links |
|---|
| 738 | 740 | * @ethaddr: NULL, or a buffer in which the ethernet address of the |
|---|
| .. | .. |
|---|
| 772 | 774 | dev->qmult = qmult; |
|---|
| 773 | 775 | snprintf(net->name, sizeof(net->name), "%s%%d", netname); |
|---|
| 774 | 776 | |
|---|
| 775 | | - if (get_ether_addr(dev_addr, net->dev_addr)) |
|---|
| 777 | + if (get_ether_addr(dev_addr, net->dev_addr)) { |
|---|
| 778 | + net->addr_assign_type = NET_ADDR_RANDOM; |
|---|
| 776 | 779 | dev_warn(&g->dev, |
|---|
| 777 | 780 | "using random %s ethernet address\n", "self"); |
|---|
| 781 | + } else { |
|---|
| 782 | + net->addr_assign_type = NET_ADDR_SET; |
|---|
| 783 | + } |
|---|
| 778 | 784 | if (get_ether_addr(host_addr, dev->host_mac)) |
|---|
| 779 | 785 | dev_warn(&g->dev, |
|---|
| 780 | 786 | "using random %s ethernet address\n", "host"); |
|---|
| .. | .. |
|---|
| 831 | 837 | INIT_LIST_HEAD(&dev->tx_reqs); |
|---|
| 832 | 838 | INIT_LIST_HEAD(&dev->rx_reqs); |
|---|
| 833 | 839 | |
|---|
| 840 | + /* by default we always have a random MAC address */ |
|---|
| 841 | + net->addr_assign_type = NET_ADDR_RANDOM; |
|---|
| 842 | + |
|---|
| 834 | 843 | skb_queue_head_init(&dev->rx_frames); |
|---|
| 835 | 844 | |
|---|
| 836 | 845 | /* network device setup */ |
|---|
| .. | .. |
|---|
| 868 | 877 | g = dev->gadget; |
|---|
| 869 | 878 | |
|---|
| 870 | 879 | memcpy(net->dev_addr, dev->dev_mac, ETH_ALEN); |
|---|
| 871 | | - net->addr_assign_type = NET_ADDR_RANDOM; |
|---|
| 872 | 880 | |
|---|
| 873 | 881 | status = register_netdev(net); |
|---|
| 874 | 882 | if (status < 0) { |
|---|
| .. | .. |
|---|
| 908 | 916 | if (get_ether_addr(dev_addr, new_addr)) |
|---|
| 909 | 917 | return -EINVAL; |
|---|
| 910 | 918 | memcpy(dev->dev_mac, new_addr, ETH_ALEN); |
|---|
| 919 | + net->addr_assign_type = NET_ADDR_SET; |
|---|
| 911 | 920 | return 0; |
|---|
| 912 | 921 | } |
|---|
| 913 | 922 | EXPORT_SYMBOL_GPL(gether_set_dev_addr); |
|---|
| .. | .. |
|---|
| 967 | 976 | dev = netdev_priv(net); |
|---|
| 968 | 977 | snprintf(host_addr, len, "%pm", dev->host_mac); |
|---|
| 969 | 978 | |
|---|
| 979 | + string_upper(host_addr, host_addr); |
|---|
| 980 | + |
|---|
| 970 | 981 | return strlen(host_addr); |
|---|
| 971 | 982 | } |
|---|
| 972 | 983 | EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc); |
|---|
| .. | .. |
|---|
| 1000 | 1011 | |
|---|
| 1001 | 1012 | int gether_get_ifname(struct net_device *net, char *name, int len) |
|---|
| 1002 | 1013 | { |
|---|
| 1014 | + struct eth_dev *dev = netdev_priv(net); |
|---|
| 1003 | 1015 | int ret; |
|---|
| 1004 | 1016 | |
|---|
| 1005 | 1017 | rtnl_lock(); |
|---|
| 1006 | | - ret = snprintf(name, len, "%s\n", netdev_name(net)); |
|---|
| 1018 | + ret = scnprintf(name, len, "%s\n", |
|---|
| 1019 | + dev->ifname_set ? net->name : netdev_name(net)); |
|---|
| 1007 | 1020 | rtnl_unlock(); |
|---|
| 1008 | | - return ret < len ? ret : len; |
|---|
| 1021 | + return ret; |
|---|
| 1009 | 1022 | } |
|---|
| 1010 | 1023 | EXPORT_SYMBOL_GPL(gether_get_ifname); |
|---|
| 1011 | 1024 | |
|---|
| 1012 | | -/** |
|---|
| 1025 | +int gether_set_ifname(struct net_device *net, const char *name, int len) |
|---|
| 1026 | +{ |
|---|
| 1027 | + struct eth_dev *dev = netdev_priv(net); |
|---|
| 1028 | + char tmp[IFNAMSIZ]; |
|---|
| 1029 | + const char *p; |
|---|
| 1030 | + |
|---|
| 1031 | + if (name[len - 1] == '\n') |
|---|
| 1032 | + len--; |
|---|
| 1033 | + |
|---|
| 1034 | + if (len >= sizeof(tmp)) |
|---|
| 1035 | + return -E2BIG; |
|---|
| 1036 | + |
|---|
| 1037 | + strscpy(tmp, name, len + 1); |
|---|
| 1038 | + if (!dev_valid_name(tmp)) |
|---|
| 1039 | + return -EINVAL; |
|---|
| 1040 | + |
|---|
| 1041 | + /* Require exactly one %d, so binding will not fail with EEXIST. */ |
|---|
| 1042 | + p = strchr(name, '%'); |
|---|
| 1043 | + if (!p || p[1] != 'd' || strchr(p + 2, '%')) |
|---|
| 1044 | + return -EINVAL; |
|---|
| 1045 | + |
|---|
| 1046 | + strncpy(net->name, tmp, sizeof(net->name)); |
|---|
| 1047 | + dev->ifname_set = true; |
|---|
| 1048 | + |
|---|
| 1049 | + return 0; |
|---|
| 1050 | +} |
|---|
| 1051 | +EXPORT_SYMBOL_GPL(gether_set_ifname); |
|---|
| 1052 | + |
|---|
| 1053 | +/* |
|---|
| 1013 | 1054 | * gether_cleanup - remove Ethernet-over-USB device |
|---|
| 1014 | 1055 | * Context: may sleep |
|---|
| 1015 | 1056 | * |
|---|