• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * lib/route/cls/fw.c		fw classifier
3  *
4  *	This library is free software; you can redistribute it and/or
5  *	modify it under the terms of the GNU Lesser General Public
6  *	License as published by the Free Software Foundation version 2.1
7  *	of the License.
8  *
9  * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
10  * Copyright (c) 2006 Petr Gotthard <petr.gotthard@siemens.com>
11  * Copyright (c) 2006 Siemens AG Oesterreich
12  */
13 
14 /**
15  * @ingroup cls
16  * @defgroup cls_fw Firewall Classifier
17  *
18  * @{
19  */
20 
21 #include <netlink-private/netlink.h>
22 #include <netlink-private/tc.h>
23 #include <netlink/netlink.h>
24 #include <netlink-private/route/tc-api.h>
25 #include <netlink/route/classifier.h>
26 #include <netlink/route/cls/fw.h>
27 
28 /** @cond SKIP */
29 #define FW_ATTR_CLASSID      0x001
30 #define FW_ATTR_ACTION       0x002
31 #define FW_ATTR_POLICE       0x004
32 #define FW_ATTR_INDEV        0x008
33 #define FW_ATTR_MASK         0x010
34 /** @endcond */
35 
36 static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
37 	[TCA_FW_CLASSID]	= { .type = NLA_U32 },
38 	[TCA_FW_INDEV]		= { .type = NLA_STRING,
39 				    .maxlen = IFNAMSIZ },
40 	[TCA_FW_MASK]		= { .type = NLA_U32 },
41 };
42 
fw_msg_parser(struct rtnl_tc * tc,void * data)43 static int fw_msg_parser(struct rtnl_tc *tc, void *data)
44 {
45 	struct nlattr *tb[TCA_FW_MAX + 1];
46 	struct rtnl_fw *f = data;
47 	int err;
48 
49 	err = tca_parse(tb, TCA_FW_MAX, tc, fw_policy);
50 	if (err < 0)
51 		return err;
52 
53 	if (tb[TCA_FW_CLASSID]) {
54 		f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
55 		f->cf_mask |= FW_ATTR_CLASSID;
56 	}
57 
58 	if (tb[TCA_FW_ACT]) {
59 		f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]);
60 		if (!f->cf_act)
61 			return -NLE_NOMEM;
62 		f->cf_mask |= FW_ATTR_ACTION;
63 	}
64 
65 	if (tb[TCA_FW_POLICE]) {
66 		f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]);
67 		if (!f->cf_police)
68 			return -NLE_NOMEM;
69 		f->cf_mask |= FW_ATTR_POLICE;
70 	}
71 
72 	if (tb[TCA_FW_INDEV]) {
73 		nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
74 		f->cf_mask |= FW_ATTR_INDEV;
75 	}
76 
77 	if (tb[TCA_FW_MASK]) {
78 		f->cf_fwmask = nla_get_u32(tb[TCA_FW_MASK]);
79 		f->cf_mask |= FW_ATTR_MASK;
80 	}
81 
82 	return 0;
83 }
84 
fw_free_data(struct rtnl_tc * tc,void * data)85 static void fw_free_data(struct rtnl_tc *tc, void *data)
86 {
87 	struct rtnl_fw *f = data;
88 
89 	nl_data_free(f->cf_act);
90 	nl_data_free(f->cf_police);
91 }
92 
fw_clone(void * _dst,void * _src)93 static int fw_clone(void *_dst, void *_src)
94 {
95 	struct rtnl_fw *dst = _dst, *src = _src;
96 
97 	if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act)))
98 		return -NLE_NOMEM;
99 
100 	if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police)))
101 		return -NLE_NOMEM;
102 
103 	return 0;
104 }
105 
fw_dump_line(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)106 static void fw_dump_line(struct rtnl_tc *tc, void *data,
107 			 struct nl_dump_params *p)
108 {
109 	struct rtnl_fw *f = data;
110 
111 	if (!f)
112 		return;
113 
114 	if (f->cf_mask & FW_ATTR_CLASSID) {
115 		char buf[32];
116 
117 		nl_dump(p, " target %s",
118 			rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
119 	}
120 
121 	if (f->cf_mask & FW_ATTR_MASK)
122 		nl_dump(p, " mask 0x%x", f->cf_fwmask);
123 }
124 
fw_dump_details(struct rtnl_tc * tc,void * data,struct nl_dump_params * p)125 static void fw_dump_details(struct rtnl_tc *tc, void *data,
126 			    struct nl_dump_params *p)
127 {
128 	struct rtnl_fw *f = data;
129 
130 	if (f && f->cf_mask & FW_ATTR_INDEV)
131 		nl_dump(p, "indev %s ", f->cf_indev);
132 }
133 
fw_msg_fill(struct rtnl_tc * tc,void * data,struct nl_msg * msg)134 static int fw_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
135 {
136 	struct rtnl_fw *f = data;
137 
138 	if (!f)
139 		return 0;
140 
141 	if (f->cf_mask & FW_ATTR_CLASSID)
142 		NLA_PUT_U32(msg, TCA_FW_CLASSID, f->cf_classid);
143 
144 	if (f->cf_mask & FW_ATTR_ACTION)
145 		NLA_PUT_DATA(msg, TCA_FW_ACT, f->cf_act);
146 
147 	if (f->cf_mask & FW_ATTR_POLICE)
148 		NLA_PUT_DATA(msg, TCA_FW_POLICE, f->cf_police);
149 
150 	if (f->cf_mask & FW_ATTR_INDEV)
151 		NLA_PUT_STRING(msg, TCA_FW_INDEV, f->cf_indev);
152 
153 	if (f->cf_mask & FW_ATTR_MASK)
154 		NLA_PUT_U32(msg, TCA_FW_MASK, f->cf_fwmask);
155 
156 	return 0;
157 
158 nla_put_failure:
159 	return -NLE_MSGSIZE;
160 }
161 
162 /**
163  * @name Attribute Modifications
164  * @{
165  */
166 
rtnl_fw_set_classid(struct rtnl_cls * cls,uint32_t classid)167 int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
168 {
169 	struct rtnl_fw *f;
170 
171 	if (!(f = rtnl_tc_data(TC_CAST(cls))))
172 		return -NLE_NOMEM;
173 
174 	f->cf_classid = classid;
175 	f->cf_mask |= FW_ATTR_CLASSID;
176 
177 	return 0;
178 }
179 
rtnl_fw_set_mask(struct rtnl_cls * cls,uint32_t mask)180 int rtnl_fw_set_mask(struct rtnl_cls *cls, uint32_t mask)
181 {
182 	struct rtnl_fw *f;
183 
184 	if (!(f = rtnl_tc_data(TC_CAST(cls))))
185 		return -NLE_NOMEM;
186 
187 	f->cf_fwmask = mask;
188 	f->cf_mask |= FW_ATTR_MASK;
189 
190 	return 0;
191 }
192 
193 /** @} */
194 
195 static struct rtnl_tc_ops fw_ops = {
196 	.to_kind		= "fw",
197 	.to_type		= RTNL_TC_TYPE_CLS,
198 	.to_size		= sizeof(struct rtnl_fw),
199 	.to_msg_parser		= fw_msg_parser,
200 	.to_msg_fill		= fw_msg_fill,
201 	.to_free_data		= fw_free_data,
202 	.to_clone		= fw_clone,
203 	.to_dump = {
204 	    [NL_DUMP_LINE]	= fw_dump_line,
205 	    [NL_DUMP_DETAILS]	= fw_dump_details,
206 	},
207 };
208 
fw_init(void)209 static void __init fw_init(void)
210 {
211 	rtnl_tc_register(&fw_ops);
212 }
213 
fw_exit(void)214 static void __exit fw_exit(void)
215 {
216 	rtnl_tc_unregister(&fw_ops);
217 }
218 
219 /** @} */
220