This commit was generated by cvs2svn to compensate for changes in r786,
[libnl.git] / lib / route / cls / fw.c
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-2006 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 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 inline struct rtnl_fw *fw_cls(struct rtnl_cls *cls)
36 {
37         return (struct rtnl_fw *) cls->c_subdata;
38 }
39
40 static inline struct rtnl_fw *fw_alloc(struct rtnl_cls *cls)
41 {
42         if (!cls->c_subdata)
43                 cls->c_subdata = calloc(1, sizeof(struct rtnl_fw));
44
45         return fw_cls(cls);
46 }
47
48 static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
49         [TCA_FW_CLASSID]        = { .type = NLA_U32 },
50         [TCA_FW_INDEV]          = { .type = NLA_STRING,
51                                     .maxlen = IFNAMSIZ },
52 };
53
54 static int fw_msg_parser(struct rtnl_cls *cls)
55 {
56         int err;
57         struct nlattr *tb[TCA_FW_MAX + 1];
58         struct rtnl_fw *f;
59
60         err = tca_parse(tb, TCA_FW_MAX, (struct rtnl_tca *) cls, fw_policy);
61         if (err < 0)
62                 return err;
63
64         f = fw_alloc(cls);
65         if (!f)
66                 goto errout_nomem;
67
68         if (tb[TCA_FW_CLASSID]) {
69                 f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
70                 f->cf_mask |= FW_ATTR_CLASSID;
71         }
72
73         if (tb[TCA_FW_ACT]) {
74                 f->cf_act = nla_get_data(tb[TCA_FW_ACT]);
75                 if (!f->cf_act)
76                         goto errout_nomem;
77                 f->cf_mask |= FW_ATTR_ACTION;
78         }
79
80         if (tb[TCA_FW_POLICE]) {
81                 f->cf_police = nla_get_data(tb[TCA_FW_POLICE]);
82                 if (!f->cf_police)
83                         goto errout_nomem;
84                 f->cf_mask |= FW_ATTR_POLICE;
85         }
86
87         if (tb[TCA_FW_INDEV]) {
88                 nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
89                 f->cf_mask |= FW_ATTR_INDEV;
90         }
91
92         return 0;
93
94 errout_nomem:
95         err = nl_errno(ENOMEM);
96
97         return err;
98 }
99
100 static void fw_free_data(struct rtnl_cls *cls)
101 {
102         struct rtnl_fw *f = fw_cls(cls);
103
104         if (!f)
105                 return;
106
107         nl_data_free(f->cf_act);
108         nl_data_free(f->cf_police);
109
110         free(cls->c_subdata);
111 }
112
113 static int fw_dump_brief(struct rtnl_cls *cls, struct nl_dump_params *p,
114                           int line)
115 {
116         struct rtnl_fw *f = fw_cls(cls);
117         char buf[32];
118
119         if (!f)
120                 goto ignore;
121
122         if (f->cf_mask & FW_ATTR_CLASSID)
123                 dp_dump(p, " target %s",
124                         rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
125
126 ignore:
127         return line;
128 }
129
130 static int fw_dump_full(struct rtnl_cls *cls, struct nl_dump_params *p,
131                          int line)
132 {
133         struct rtnl_fw *f = fw_cls(cls);
134
135         if (!f)
136                 goto ignore;
137
138         if (f->cf_mask & FW_ATTR_INDEV)
139                 dp_dump(p, "indev %s ", f->cf_indev);
140
141 ignore:
142         return line;
143 }
144
145 static int fw_dump_stats(struct rtnl_cls *cls, struct nl_dump_params *p,
146                           int line)
147 {
148         struct rtnl_fw *f = fw_cls(cls);
149
150         if (!f)
151                 goto ignore;
152
153 ignore:
154         return line;
155 }
156
157 static struct nl_msg *fw_get_opts(struct rtnl_cls *cls)
158 {
159         struct rtnl_fw *f;
160         struct nl_msg *msg;
161         
162         f = fw_cls(cls);
163         if (!f)
164                 return NULL;
165
166         msg = nlmsg_build_no_hdr();
167         if (!msg)
168                 return NULL;
169
170         if (f->cf_mask & FW_ATTR_CLASSID)
171                 nla_put_u32(msg, TCA_FW_CLASSID, f->cf_classid);
172
173         if (f->cf_mask & FW_ATTR_ACTION)
174                 nla_put_data(msg, TCA_FW_ACT, f->cf_act);
175
176         if (f->cf_mask & FW_ATTR_POLICE)
177                 nla_put_data(msg, TCA_FW_POLICE, f->cf_police);
178
179         if (f->cf_mask & FW_ATTR_INDEV)
180                 nla_put_string(msg, TCA_FW_INDEV, f->cf_indev);
181
182         return msg;
183 }
184
185 /**
186  * @name Attribute Modifications
187  * @{
188  */
189
190 int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
191 {
192         struct rtnl_fw *f;
193         
194         f = fw_alloc(cls);
195         if (!f)
196                 return nl_errno(ENOMEM);
197
198         f->cf_classid = classid;
199         f->cf_mask |= FW_ATTR_CLASSID;
200
201         return 0;
202 }
203
204 /** @} */
205
206 static struct rtnl_cls_ops fw_ops = {
207         .co_kind                = "fw",
208         .co_msg_parser          = fw_msg_parser,
209         .co_free_data           = fw_free_data,
210         .co_get_opts            = fw_get_opts,
211         .co_dump[NL_DUMP_BRIEF] = fw_dump_brief,
212         .co_dump[NL_DUMP_FULL]  = fw_dump_full,
213         .co_dump[NL_DUMP_STATS] = fw_dump_stats,
214 };
215
216 static void __init fw_init(void)
217 {
218         rtnl_cls_register(&fw_ops);
219 }
220
221 static void __exit fw_exit(void)
222 {
223         rtnl_cls_unregister(&fw_ops);
224 }
225
226 /** @} */