|
@@ -633,6 +633,8 @@ static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
|
|
|
if (!nest_parms)
|
|
|
goto nla_put_failure;
|
|
|
NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state);
|
|
|
+ NLA_PUT_U8(skb, CTA_PROTOINFO_DCCP_ROLE,
|
|
|
+ ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]);
|
|
|
nla_nest_end(skb, nest_parms);
|
|
|
read_unlock_bh(&dccp_lock);
|
|
|
return 0;
|
|
@@ -644,6 +646,7 @@ nla_put_failure:
|
|
|
|
|
|
static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
|
|
|
[CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
|
|
|
+ [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 },
|
|
|
};
|
|
|
|
|
|
static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
|
|
@@ -661,11 +664,21 @@ static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
|
|
|
return err;
|
|
|
|
|
|
if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
|
|
|
- nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE)
|
|
|
+ !tb[CTA_PROTOINFO_DCCP_ROLE] ||
|
|
|
+ nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX ||
|
|
|
+ nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) {
|
|
|
return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
write_lock_bh(&dccp_lock);
|
|
|
ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
|
|
|
+ if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
|
|
|
+ ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
|
|
|
+ ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
|
|
|
+ } else {
|
|
|
+ ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER;
|
|
|
+ ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT;
|
|
|
+ }
|
|
|
write_unlock_bh(&dccp_lock);
|
|
|
return 0;
|
|
|
}
|