2 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
8 * Development of this code funded by Astaro AG (http://www.astaro.com/)
11 #include <asm/unaligned.h>
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/netlink.h>
16 #include <linux/netfilter.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <net/netfilter/nf_tables_core.h>
19 #include <net/netfilter/nf_tables.h>
21 struct nft_byteorder
{
22 enum nft_registers sreg
:8;
23 enum nft_registers dreg
:8;
24 enum nft_byteorder_ops op
:8;
29 static void nft_byteorder_eval(const struct nft_expr
*expr
,
30 struct nft_regs
*regs
,
31 const struct nft_pktinfo
*pkt
)
33 const struct nft_byteorder
*priv
= nft_expr_priv(expr
);
34 u32
*src
= ®s
->data
[priv
->sreg
];
35 u32
*dst
= ®s
->data
[priv
->dreg
];
36 union { u32 u32
; u16 u16
; } *s
, *d
;
47 case NFT_BYTEORDER_NTOH
:
48 for (i
= 0; i
< priv
->len
/ 8; i
++) {
49 src64
= get_unaligned_be64(&src
[i
]);
50 src64
= be64_to_cpu((__force __be64
)src64
);
51 put_unaligned_be64(src64
, &dst
[i
]);
54 case NFT_BYTEORDER_HTON
:
55 for (i
= 0; i
< priv
->len
/ 8; i
++) {
56 src64
= get_unaligned_be64(&src
[i
]);
57 src64
= (__force u64
)cpu_to_be64(src64
);
58 put_unaligned_be64(src64
, &dst
[i
]);
66 case NFT_BYTEORDER_NTOH
:
67 for (i
= 0; i
< priv
->len
/ 4; i
++)
68 d
[i
].u32
= ntohl((__force __be32
)s
[i
].u32
);
70 case NFT_BYTEORDER_HTON
:
71 for (i
= 0; i
< priv
->len
/ 4; i
++)
72 d
[i
].u32
= (__force __u32
)htonl(s
[i
].u32
);
78 case NFT_BYTEORDER_NTOH
:
79 for (i
= 0; i
< priv
->len
/ 2; i
++)
80 d
[i
].u16
= ntohs((__force __be16
)s
[i
].u16
);
82 case NFT_BYTEORDER_HTON
:
83 for (i
= 0; i
< priv
->len
/ 2; i
++)
84 d
[i
].u16
= (__force __u16
)htons(s
[i
].u16
);
91 static const struct nla_policy nft_byteorder_policy
[NFTA_BYTEORDER_MAX
+ 1] = {
92 [NFTA_BYTEORDER_SREG
] = { .type
= NLA_U32
},
93 [NFTA_BYTEORDER_DREG
] = { .type
= NLA_U32
},
94 [NFTA_BYTEORDER_OP
] = { .type
= NLA_U32
},
95 [NFTA_BYTEORDER_LEN
] = { .type
= NLA_U32
},
96 [NFTA_BYTEORDER_SIZE
] = { .type
= NLA_U32
},
99 static int nft_byteorder_init(const struct nft_ctx
*ctx
,
100 const struct nft_expr
*expr
,
101 const struct nlattr
* const tb
[])
103 struct nft_byteorder
*priv
= nft_expr_priv(expr
);
106 if (tb
[NFTA_BYTEORDER_SREG
] == NULL
||
107 tb
[NFTA_BYTEORDER_DREG
] == NULL
||
108 tb
[NFTA_BYTEORDER_LEN
] == NULL
||
109 tb
[NFTA_BYTEORDER_SIZE
] == NULL
||
110 tb
[NFTA_BYTEORDER_OP
] == NULL
)
113 priv
->op
= ntohl(nla_get_be32(tb
[NFTA_BYTEORDER_OP
]));
115 case NFT_BYTEORDER_NTOH
:
116 case NFT_BYTEORDER_HTON
:
122 priv
->size
= ntohl(nla_get_be32(tb
[NFTA_BYTEORDER_SIZE
]));
123 switch (priv
->size
) {
132 priv
->sreg
= nft_parse_register(tb
[NFTA_BYTEORDER_SREG
]);
133 priv
->len
= ntohl(nla_get_be32(tb
[NFTA_BYTEORDER_LEN
]));
134 err
= nft_validate_register_load(priv
->sreg
, priv
->len
);
138 priv
->dreg
= nft_parse_register(tb
[NFTA_BYTEORDER_DREG
]);
139 return nft_validate_register_store(ctx
, priv
->dreg
, NULL
,
140 NFT_DATA_VALUE
, priv
->len
);
143 static int nft_byteorder_dump(struct sk_buff
*skb
, const struct nft_expr
*expr
)
145 const struct nft_byteorder
*priv
= nft_expr_priv(expr
);
147 if (nft_dump_register(skb
, NFTA_BYTEORDER_SREG
, priv
->sreg
))
148 goto nla_put_failure
;
149 if (nft_dump_register(skb
, NFTA_BYTEORDER_DREG
, priv
->dreg
))
150 goto nla_put_failure
;
151 if (nla_put_be32(skb
, NFTA_BYTEORDER_OP
, htonl(priv
->op
)))
152 goto nla_put_failure
;
153 if (nla_put_be32(skb
, NFTA_BYTEORDER_LEN
, htonl(priv
->len
)))
154 goto nla_put_failure
;
155 if (nla_put_be32(skb
, NFTA_BYTEORDER_SIZE
, htonl(priv
->size
)))
156 goto nla_put_failure
;
163 static struct nft_expr_type nft_byteorder_type
;
164 static const struct nft_expr_ops nft_byteorder_ops
= {
165 .type
= &nft_byteorder_type
,
166 .size
= NFT_EXPR_SIZE(sizeof(struct nft_byteorder
)),
167 .eval
= nft_byteorder_eval
,
168 .init
= nft_byteorder_init
,
169 .dump
= nft_byteorder_dump
,
172 static struct nft_expr_type nft_byteorder_type __read_mostly
= {
174 .ops
= &nft_byteorder_ops
,
175 .policy
= nft_byteorder_policy
,
176 .maxattr
= NFTA_BYTEORDER_MAX
,
177 .owner
= THIS_MODULE
,
180 int __init
nft_byteorder_module_init(void)
182 return nft_register_expr(&nft_byteorder_type
);
185 void nft_byteorder_module_exit(void)
187 nft_unregister_expr(&nft_byteorder_type
);