upload tizen1.0 source
[external/libnl2.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-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
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
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
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
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
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
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
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
170 static void __init fw_init(void)
171 {
172         rtnl_cls_register(&fw_ops);
173 }
174
175 static void __exit fw_exit(void)
176 {
177         rtnl_cls_unregister(&fw_ops);
178 }
179
180 /** @} */