~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ethtool/wol.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 
  3 #include "netlink.h"
  4 #include "common.h"
  5 #include "bitset.h"
  6 
  7 struct wol_req_info {
  8         struct ethnl_req_info           base;
  9 };
 10 
 11 struct wol_reply_data {
 12         struct ethnl_reply_data         base;
 13         struct ethtool_wolinfo          wol;
 14         bool                            show_sopass;
 15 };
 16 
 17 #define WOL_REPDATA(__reply_base) \
 18         container_of(__reply_base, struct wol_reply_data, base)
 19 
 20 const struct nla_policy ethnl_wol_get_policy[] = {
 21         [ETHTOOL_A_WOL_HEADER]          =
 22                 NLA_POLICY_NESTED(ethnl_header_policy),
 23 };
 24 
 25 static int wol_prepare_data(const struct ethnl_req_info *req_base,
 26                             struct ethnl_reply_data *reply_base,
 27                             const struct genl_info *info)
 28 {
 29         struct wol_reply_data *data = WOL_REPDATA(reply_base);
 30         struct net_device *dev = reply_base->dev;
 31         int ret;
 32 
 33         if (!dev->ethtool_ops->get_wol)
 34                 return -EOPNOTSUPP;
 35 
 36         ret = ethnl_ops_begin(dev);
 37         if (ret < 0)
 38                 return ret;
 39         dev->ethtool_ops->get_wol(dev, &data->wol);
 40         ethnl_ops_complete(dev);
 41         /* do not include password in notifications */
 42         data->show_sopass = !genl_info_is_ntf(info) &&
 43                 (data->wol.supported & WAKE_MAGICSECURE);
 44 
 45         return 0;
 46 }
 47 
 48 static int wol_reply_size(const struct ethnl_req_info *req_base,
 49                           const struct ethnl_reply_data *reply_base)
 50 {
 51         bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
 52         const struct wol_reply_data *data = WOL_REPDATA(reply_base);
 53         int len;
 54 
 55         len = ethnl_bitset32_size(&data->wol.wolopts, &data->wol.supported,
 56                                   WOL_MODE_COUNT, wol_mode_names, compact);
 57         if (len < 0)
 58                 return len;
 59         if (data->show_sopass)
 60                 len += nla_total_size(sizeof(data->wol.sopass));
 61 
 62         return len;
 63 }
 64 
 65 static int wol_fill_reply(struct sk_buff *skb,
 66                           const struct ethnl_req_info *req_base,
 67                           const struct ethnl_reply_data *reply_base)
 68 {
 69         bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
 70         const struct wol_reply_data *data = WOL_REPDATA(reply_base);
 71         int ret;
 72 
 73         ret = ethnl_put_bitset32(skb, ETHTOOL_A_WOL_MODES, &data->wol.wolopts,
 74                                  &data->wol.supported, WOL_MODE_COUNT,
 75                                  wol_mode_names, compact);
 76         if (ret < 0)
 77                 return ret;
 78         if (data->show_sopass &&
 79             nla_put(skb, ETHTOOL_A_WOL_SOPASS, sizeof(data->wol.sopass),
 80                     data->wol.sopass))
 81                 return -EMSGSIZE;
 82 
 83         return 0;
 84 }
 85 
 86 /* WOL_SET */
 87 
 88 const struct nla_policy ethnl_wol_set_policy[] = {
 89         [ETHTOOL_A_WOL_HEADER]          =
 90                 NLA_POLICY_NESTED(ethnl_header_policy),
 91         [ETHTOOL_A_WOL_MODES]           = { .type = NLA_NESTED },
 92         [ETHTOOL_A_WOL_SOPASS]          = { .type = NLA_BINARY,
 93                                             .len = SOPASS_MAX },
 94 };
 95 
 96 static int
 97 ethnl_set_wol_validate(struct ethnl_req_info *req_info, struct genl_info *info)
 98 {
 99         const struct ethtool_ops *ops = req_info->dev->ethtool_ops;
100 
101         return ops->get_wol && ops->set_wol ? 1 : -EOPNOTSUPP;
102 }
103 
104 static int
105 ethnl_set_wol(struct ethnl_req_info *req_info, struct genl_info *info)
106 {
107         struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
108         struct net_device *dev = req_info->dev;
109         struct nlattr **tb = info->attrs;
110         bool mod = false;
111         int ret;
112 
113         dev->ethtool_ops->get_wol(dev, &wol);
114         ret = ethnl_update_bitset32(&wol.wolopts, WOL_MODE_COUNT,
115                                     tb[ETHTOOL_A_WOL_MODES], wol_mode_names,
116                                     info->extack, &mod);
117         if (ret < 0)
118                 return ret;
119         if (wol.wolopts & ~wol.supported) {
120                 NL_SET_ERR_MSG_ATTR(info->extack, tb[ETHTOOL_A_WOL_MODES],
121                                     "cannot enable unsupported WoL mode");
122                 return -EINVAL;
123         }
124         if (tb[ETHTOOL_A_WOL_SOPASS]) {
125                 if (!(wol.supported & WAKE_MAGICSECURE)) {
126                         NL_SET_ERR_MSG_ATTR(info->extack,
127                                             tb[ETHTOOL_A_WOL_SOPASS],
128                                             "magicsecure not supported, cannot set password");
129                         return -EINVAL;
130                 }
131                 ethnl_update_binary(wol.sopass, sizeof(wol.sopass),
132                                     tb[ETHTOOL_A_WOL_SOPASS], &mod);
133         }
134 
135         if (!mod)
136                 return 0;
137         ret = dev->ethtool_ops->set_wol(dev, &wol);
138         if (ret)
139                 return ret;
140         dev->ethtool->wol_enabled = !!wol.wolopts;
141         return 1;
142 }
143 
144 const struct ethnl_request_ops ethnl_wol_request_ops = {
145         .request_cmd            = ETHTOOL_MSG_WOL_GET,
146         .reply_cmd              = ETHTOOL_MSG_WOL_GET_REPLY,
147         .hdr_attr               = ETHTOOL_A_WOL_HEADER,
148         .req_info_size          = sizeof(struct wol_req_info),
149         .reply_data_size        = sizeof(struct wol_reply_data),
150 
151         .prepare_data           = wol_prepare_data,
152         .reply_size             = wol_reply_size,
153         .fill_reply             = wol_fill_reply,
154 
155         .set_validate           = ethnl_set_wol_validate,
156         .set                    = ethnl_set_wol,
157         .set_ntf_cmd            = ETHTOOL_MSG_WOL_NTF,
158 };
159 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php