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-2009 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_api
16  * @defgroup fw Firewall Classifier
17  *
18  * @{
19  */
20 
21 #include <netlink-local.h>
22 #include <netlink-tc.h>
23 #include <netlink/netlink.h>
24 #include <netlink/route/classifier.h>
25 #include <netlink/route/classifier-modules.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 /** @endcond */
34 
35 static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
36 	[TCA_FW_CLASSID]	= { .type = NLA_U32 },
37 	[TCA_FW_INDEV]		= { .type = NLA_STRING,
38 				    .maxlen = IFNAMSIZ },
39 };
40 
fw_msg_parser(struct rtnl_cls * cls)41 static int fw_msg_parser(struct rtnl_cls *cls)
42 {
43 	struct rtnl_fw *f = rtnl_cls_data(cls);
44 	struct nlattr *tb[TCA_FW_MAX + 1];
45 	int err;
46 
47 	err = tca_parse(tb, TCA_FW_MAX, (struct rtnl_tca *) cls, fw_policy);
48 	if (err < 0)
49 		return err;
50 
51 	if (tb[TCA_FW_CLASSID]) {
52 		f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
53 		f->cf_mask |= FW_ATTR_CLASSID;
54 	}
55 
56 	if (tb[TCA_FW_ACT]) {
57 		f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]);
58 		if (!f->cf_act)
59 			return -NLE_NOMEM;
60 		f->cf_mask |= FW_ATTR_ACTION;
61 	}
62 
63 	if (tb[TCA_FW_POLICE]) {
64 		f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]);
65 		if (!f->cf_police)
66 			return -NLE_NOMEM;
67 		f->cf_mask |= FW_ATTR_POLICE;
68 	}
69 
70 	if (tb[TCA_FW_INDEV]) {
71 		nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
72 		f->cf_mask |= FW_ATTR_INDEV;
73 	}
74 
75 	return 0;
76 }
77 
fw_free_data(struct rtnl_cls * cls)78 static void fw_free_data(struct rtnl_cls *cls)
79 {
80 	struct rtnl_fw *f = rtnl_cls_data(cls);
81 
82 	nl_data_free(f->cf_act);
83 	nl_data_free(f->cf_police);
84 }
85 
fw_clone(struct rtnl_cls * _dst,struct rtnl_cls * _src)86 static int fw_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
87 {
88 	struct rtnl_fw *dst = rtnl_cls_data(_dst);
89 	struct rtnl_fw *src = rtnl_cls_data(_src);
90 
91 	if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act)))
92 		return -NLE_NOMEM;
93 
94 	if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police)))
95 		return -NLE_NOMEM;
96 
97 	return 0;
98 }
99 
fw_dump_line(struct rtnl_cls * cls,struct nl_dump_params * p)100 static void fw_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
101 {
102 	struct rtnl_fw *f = rtnl_cls_data(cls);
103 	char buf[32];
104 
105 	if (f->cf_mask & FW_ATTR_CLASSID)
106 		nl_dump(p, " target %s",
107 			rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
108 }
109 
fw_dump_details(struct rtnl_cls * cls,struct nl_dump_params * p)110 static void fw_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
111 {
112 	struct rtnl_fw *f = rtnl_cls_data(cls);
113 
114 	if (f->cf_mask & FW_ATTR_INDEV)
115 		nl_dump(p, "indev %s ", f->cf_indev);
116 }
117 
fw_get_opts(struct rtnl_cls * cls,struct nl_msg * msg)118 static int fw_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
119 {
120 	struct rtnl_fw *f = rtnl_cls_data(cls);
121 
122 	if (f->cf_mask & FW_ATTR_CLASSID)
123 		NLA_PUT_U32(msg, TCA_FW_CLASSID, f->cf_classid);
124 
125 	if (f->cf_mask & FW_ATTR_ACTION)
126 		NLA_PUT_DATA(msg, TCA_FW_ACT, f->cf_act);
127 
128 	if (f->cf_mask & FW_ATTR_POLICE)
129 		NLA_PUT_DATA(msg, TCA_FW_POLICE, f->cf_police);
130 
131 	if (f->cf_mask & FW_ATTR_INDEV)
132 		NLA_PUT_STRING(msg, TCA_FW_INDEV, f->cf_indev);
133 
134 	return 0;
135 
136 nla_put_failure:
137 	return -NLE_NOMEM;
138 }
139 
140 /**
141  * @name Attribute Modifications
142  * @{
143  */
144 
rtnl_fw_set_classid(struct rtnl_cls * cls,uint32_t classid)145 int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
146 {
147 	struct rtnl_fw *f = rtnl_cls_data(cls);
148 
149 	f->cf_classid = classid;
150 	f->cf_mask |= FW_ATTR_CLASSID;
151 
152 	return 0;
153 }
154 
155 /** @} */
156 
157 static struct rtnl_cls_ops fw_ops = {
158 	.co_kind		= "fw",
159 	.co_size		= sizeof(struct rtnl_fw),
160 	.co_msg_parser		= fw_msg_parser,
161 	.co_free_data		= fw_free_data,
162 	.co_clone		= fw_clone,
163 	.co_get_opts		= fw_get_opts,
164 	.co_dump = {
165 	    [NL_DUMP_LINE]	= fw_dump_line,
166 	    [NL_DUMP_DETAILS]	= fw_dump_details,
167 	},
168 };
169 
fw_init(void)170 static void __init fw_init(void)
171 {
172 	rtnl_cls_register(&fw_ops);
173 }
174 
fw_exit(void)175 static void __exit fw_exit(void)
176 {
177 	rtnl_cls_unregister(&fw_ops);
178 }
179 
180 /** @} */
181