libnetfilter_conntrack 1.1.0
expect/parse_mnl.c
1/*
2 * (C) 2005-2012 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com>
10 */
11
12#include "internal/internal.h"
13#include <assert.h>
14#include <libmnl/libmnl.h>
15
16static int nlmsg_parse_expection_attr_cb(const struct nlattr *attr, void *data)
17{
18 const struct nlattr **tb = data;
19 int type = mnl_attr_get_type(attr);
20
21 /* skip unsupported attribute in user-space */
22 if (mnl_attr_type_valid(attr, CTA_EXPECT_MAX) < 0)
23 return MNL_CB_OK;
24
25 switch(type) {
26 case CTA_EXPECT_MASTER:
27 case CTA_EXPECT_TUPLE:
28 case CTA_EXPECT_MASK:
29 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
30 abi_breakage();
31 break;
32 case CTA_EXPECT_TIMEOUT:
33 case CTA_EXPECT_FLAGS:
34 case CTA_EXPECT_ID:
35 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
36 abi_breakage();
37 break;
38 case CTA_EXPECT_HELP_NAME:
39 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
40 abi_breakage();
41 break;
42 case CTA_EXPECT_ZONE:
43 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
44 abi_breakage();
45 break;
46 }
47 tb[type] = attr;
48 return MNL_CB_OK;
49}
50
51static int nfexp_nlmsg_parse_nat_attr_cb(const struct nlattr *attr, void *data)
52{
53 int type = mnl_attr_get_type(attr);
54 const struct nlattr **tb = data;
55
56 if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
57 return MNL_CB_OK;
58
59 switch(type) {
60 case CTA_EXPECT_NAT_TUPLE:
61 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
62 abi_breakage();
63 break;
64 case CTA_EXPECT_NAT_DIR:
65 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
66 abi_breakage();
67 break;
68 }
69
70 tb[type] = attr;
71 return MNL_CB_OK;
72}
73
74static void nfexp_nlmsg_parse_nat(struct nfgenmsg *nfg,
75 const struct nlattr *attr,
76 struct nf_expect *exp)
77{
78 struct nlattr *tb[CTA_EXPECT_NAT_MAX + 1] = {};
79
80 if (mnl_attr_parse_nested(attr, nfexp_nlmsg_parse_nat_attr_cb, tb) < 0)
81 return;
82
83 exp->nat.orig.l3protonum = nfg->nfgen_family;
84 set_bit(ATTR_ORIG_L3PROTO, exp->nat.set);
85
86 if (tb[CTA_EXPECT_NAT_TUPLE]) {
87 nfct_parse_tuple(tb[CTA_EXPECT_NAT_TUPLE], &exp->nat.orig,
88 __DIR_ORIG, exp->nat.set);
89 set_bit(ATTR_EXP_NAT_TUPLE, exp->set);
90 }
91 if (tb[CTA_EXPECT_NAT_DIR]) {
92 exp->nat_dir =
93 ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_NAT_DIR]));
94 set_bit(ATTR_EXP_NAT_DIR, exp->set);
95 }
96}
97
98int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp)
99{
100 struct nlattr *tb[CTA_EXPECT_MAX+1] = {};
101 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
102
103 mnl_attr_parse(nlh, sizeof(struct nfgenmsg),
104 nlmsg_parse_expection_attr_cb, tb);
105
106 if (tb[CTA_EXPECT_MASTER]) {
107 exp->expected.orig.l3protonum = nfg->nfgen_family;
108 set_bit(ATTR_ORIG_L3PROTO, exp->expected.set);
109
110 nfct_parse_tuple(tb[CTA_EXPECT_MASTER], &exp->master.orig,
111 __DIR_ORIG, exp->master.set);
112 set_bit(ATTR_EXP_MASTER, exp->set);
113 }
114 if (tb[CTA_EXPECT_TUPLE]) {
115 exp->mask.orig.l3protonum = nfg->nfgen_family;
116 set_bit(ATTR_ORIG_L3PROTO, exp->mask.set);
117
118 nfct_parse_tuple(tb[CTA_EXPECT_TUPLE], &exp->expected.orig,
119 __DIR_ORIG, exp->expected.set);
120 set_bit(ATTR_EXP_EXPECTED, exp->set);
121 }
122 if (tb[CTA_EXPECT_MASK]) {
123 exp->master.orig.l3protonum = nfg->nfgen_family;
124 set_bit(ATTR_ORIG_L3PROTO, exp->master.set);
125
126 nfct_parse_tuple(tb[CTA_EXPECT_MASK], &exp->mask.orig,
127 __DIR_ORIG, exp->mask.set);
128 set_bit(ATTR_EXP_MASK, exp->set);
129 }
130 if (tb[CTA_EXPECT_TIMEOUT]) {
131 exp->timeout = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_TIMEOUT]));
132 set_bit(ATTR_EXP_TIMEOUT, exp->set);
133 }
134 if (tb[CTA_EXPECT_ZONE]) {
135 exp->zone = ntohs(mnl_attr_get_u16(tb[CTA_EXPECT_ZONE]));
136 set_bit(ATTR_EXP_ZONE, exp->set);
137 }
138 if (tb[CTA_EXPECT_FLAGS]) {
139 exp->flags = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_FLAGS]));
140 set_bit(ATTR_EXP_FLAGS, exp->set);
141 }
142 if (tb[CTA_EXPECT_HELP_NAME]) {
143 snprintf(exp->helper_name, NFCT_HELPER_NAME_MAX, "%s",
144 mnl_attr_get_str(tb[CTA_EXPECT_HELP_NAME]));
145 set_bit(ATTR_EXP_HELPER_NAME, exp->set);
146 }
147 if (tb[CTA_EXPECT_CLASS]) {
148 exp->class = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_CLASS]));
149 set_bit(ATTR_EXP_CLASS, exp->set);
150 }
151 if (tb[CTA_EXPECT_NAT])
152 nfexp_nlmsg_parse_nat(nfg, tb[CTA_EXPECT_NAT], exp);
153
154 if (tb[CTA_EXPECT_FN]) {
155 int len = mnl_attr_get_payload_len(tb[CTA_EXPECT_FN]);
156 /* the kernel doesn't impose a max length on this str */
157 assert(len <= __NFCT_EXPECTFN_MAX);
158 snprintf(exp->expectfn, __NFCT_EXPECTFN_MAX, "%s",
159 (char *)mnl_attr_get_payload(tb[CTA_EXPECT_FN]));
160 set_bit(ATTR_EXP_FN, exp->set);
161 }
162
163 return 0;
164}