Skip to content

Commit 6742ca1

Browse files
vincent-mailholmarckleinebudde
authored andcommitted
can: netlink: add userland error messages
Use NL_SET_ERR_MSG() and NL_SET_ERR_MSG_FMT() to return meaningful error messages to the userland whenever a -EOPNOTSUPP error is returned due to a failed validation of the CAN netlink arguments. Signed-off-by: Vincent Mailhol <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 7de5454 commit 6742ca1

File tree

1 file changed

+62
-20
lines changed

1 file changed

+62
-20
lines changed

drivers/net/can/dev/netlink.c

Lines changed: 62 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,23 @@ static int can_validate_tdc(struct nlattr *data_tdc,
6464
bool tdc_auto = tdc_flags & CAN_CTRLMODE_TDC_AUTO_MASK;
6565
int err;
6666

67-
/* CAN_CTRLMODE_TDC_{AUTO,MANUAL} are mutually exclusive */
68-
if (tdc_auto && tdc_manual)
67+
if (tdc_auto && tdc_manual) {
68+
NL_SET_ERR_MSG(extack,
69+
"TDC manual and auto modes are mutually exclusive");
6970
return -EOPNOTSUPP;
71+
}
7072

7173
/* If one of the CAN_CTRLMODE_TDC_* flag is set then TDC
7274
* must be set and vice-versa
7375
*/
74-
if ((tdc_auto || tdc_manual) != !!data_tdc)
76+
if ((tdc_auto || tdc_manual) && !data_tdc) {
77+
NL_SET_ERR_MSG(extack, "TDC parameters are missing");
78+
return -EOPNOTSUPP;
79+
}
80+
if (!(tdc_auto || tdc_manual) && data_tdc) {
81+
NL_SET_ERR_MSG(extack, "TDC mode (auto or manual) is missing");
7582
return -EOPNOTSUPP;
83+
}
7684

7785
/* If providing TDC parameters, at least TDCO is needed. TDCV
7886
* is needed if and only if CAN_CTRLMODE_TDC_MANUAL is set
@@ -86,15 +94,23 @@ static int can_validate_tdc(struct nlattr *data_tdc,
8694
return err;
8795

8896
if (tb_tdc[IFLA_CAN_TDC_TDCV]) {
89-
if (tdc_auto)
97+
if (tdc_auto) {
98+
NL_SET_ERR_MSG(extack,
99+
"TDCV is incompatible with TDC auto mode");
90100
return -EOPNOTSUPP;
101+
}
91102
} else {
92-
if (tdc_manual)
103+
if (tdc_manual) {
104+
NL_SET_ERR_MSG(extack,
105+
"TDC manual mode requires TDCV");
93106
return -EOPNOTSUPP;
107+
}
94108
}
95109

96-
if (!tb_tdc[IFLA_CAN_TDC_TDCO])
110+
if (!tb_tdc[IFLA_CAN_TDC_TDCO]) {
111+
NL_SET_ERR_MSG(extack, "TDCO is missing");
97112
return -EOPNOTSUPP;
113+
}
98114
}
99115

100116
return 0;
@@ -105,6 +121,7 @@ static int can_validate_databittiming(struct nlattr *data[],
105121
int ifla_can_data_bittiming, u32 flags)
106122
{
107123
struct nlattr *data_tdc;
124+
const char *type;
108125
u32 tdc_flags;
109126
bool is_on;
110127
int err;
@@ -120,18 +137,31 @@ static int can_validate_databittiming(struct nlattr *data[],
120137
data_tdc = data[IFLA_CAN_TDC];
121138
tdc_flags = flags & CAN_CTRLMODE_FD_TDC_MASK;
122139
is_on = flags & CAN_CTRLMODE_FD;
140+
type = "FD";
123141
} else {
124142
return -EOPNOTSUPP; /* Place holder for CAN XL */
125143
}
126144

127145
if (is_on) {
128-
if (!data[IFLA_CAN_BITTIMING] || !data[ifla_can_data_bittiming])
146+
if (!data[IFLA_CAN_BITTIMING] || !data[ifla_can_data_bittiming]) {
147+
NL_SET_ERR_MSG_FMT(extack,
148+
"Provide both nominal and %s data bittiming",
149+
type);
129150
return -EOPNOTSUPP;
130-
}
131-
132-
if (data[ifla_can_data_bittiming] || data_tdc) {
133-
if (!is_on)
151+
}
152+
} else {
153+
if (data[ifla_can_data_bittiming]) {
154+
NL_SET_ERR_MSG_FMT(extack,
155+
"%s data bittiming requires CAN %s",
156+
type, type);
134157
return -EOPNOTSUPP;
158+
}
159+
if (data_tdc) {
160+
NL_SET_ERR_MSG_FMT(extack,
161+
"%s TDC requires CAN %s",
162+
type, type);
163+
return -EOPNOTSUPP;
164+
}
135165
}
136166

137167
err = can_validate_bittiming(data, extack, ifla_can_data_bittiming);
@@ -178,8 +208,7 @@ static int can_ctrlmode_changelink(struct net_device *dev,
178208
{
179209
struct can_priv *priv = netdev_priv(dev);
180210
struct can_ctrlmode *cm;
181-
u32 maskedflags;
182-
u32 ctrlstatic;
211+
u32 ctrlstatic, maskedflags, notsupp, ctrlstatic_missing;
183212

184213
if (!data[IFLA_CAN_CTRLMODE])
185214
return 0;
@@ -189,20 +218,28 @@ static int can_ctrlmode_changelink(struct net_device *dev,
189218
return -EBUSY;
190219

191220
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
192-
maskedflags = cm->flags & cm->mask;
193221
ctrlstatic = can_get_static_ctrlmode(priv);
222+
maskedflags = cm->flags & cm->mask;
223+
notsupp = maskedflags & ~(priv->ctrlmode_supported | ctrlstatic);
224+
ctrlstatic_missing = (maskedflags & ctrlstatic) ^ ctrlstatic;
194225

195-
/* check whether provided bits are allowed to be passed */
196-
if (maskedflags & ~(priv->ctrlmode_supported | ctrlstatic))
226+
if (notsupp) {
227+
NL_SET_ERR_MSG_FMT(extack,
228+
"requested control mode %s not supported",
229+
can_get_ctrlmode_str(notsupp));
197230
return -EOPNOTSUPP;
231+
}
198232

199233
/* do not check for static fd-non-iso if 'fd' is disabled */
200234
if (!(maskedflags & CAN_CTRLMODE_FD))
201235
ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
202236

203-
/* make sure static options are provided by configuration */
204-
if ((maskedflags & ctrlstatic) != ctrlstatic)
237+
if (ctrlstatic_missing) {
238+
NL_SET_ERR_MSG_FMT(extack,
239+
"missing required %s static control mode",
240+
can_get_ctrlmode_str(ctrlstatic_missing));
205241
return -EOPNOTSUPP;
242+
}
206243

207244
/* If a top dependency flag is provided, reset all its dependencies */
208245
if (cm->mask & CAN_CTRLMODE_FD)
@@ -234,8 +271,10 @@ static int can_tdc_changelink(struct data_bittiming_params *dbt_params,
234271
const struct can_tdc_const *tdc_const = dbt_params->tdc_const;
235272
int err;
236273

237-
if (!tdc_const)
274+
if (!tdc_const) {
275+
NL_SET_ERR_MSG(extack, "The device does not support TDC");
238276
return -EOPNOTSUPP;
277+
}
239278

240279
err = nla_parse_nested(tb_tdc, IFLA_CAN_TDC_MAX, nla,
241280
can_tdc_policy, extack);
@@ -450,8 +489,11 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
450489
const unsigned int num_term = priv->termination_const_cnt;
451490
unsigned int i;
452491

453-
if (!priv->do_set_termination)
492+
if (!priv->do_set_termination) {
493+
NL_SET_ERR_MSG(extack,
494+
"Termination is not configurable on this device");
454495
return -EOPNOTSUPP;
496+
}
455497

456498
/* check whether given value is supported by the interface */
457499
for (i = 0; i < num_term; i++) {

0 commit comments

Comments
 (0)