libnl 1.1

lib/route/cls/fw.c

00001 /*
00002  * lib/route/cls/fw.c           fw classifier
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
00010  * Copyright (c) 2006 Petr Gotthard <petr.gotthard@siemens.com>
00011  * Copyright (c) 2006 Siemens AG Oesterreich
00012  */
00013 
00014 /**
00015  * @ingroup cls_api
00016  * @defgroup fw Firewall Classifier
00017  *
00018  * @{
00019  */
00020 
00021 #include <netlink-local.h>
00022 #include <netlink-tc.h>
00023 #include <netlink/netlink.h>
00024 #include <netlink/route/classifier.h>
00025 #include <netlink/route/classifier-modules.h>
00026 #include <netlink/route/cls/fw.h>
00027 
00028 /** @cond SKIP */
00029 #define FW_ATTR_CLASSID      0x001
00030 #define FW_ATTR_ACTION       0x002
00031 #define FW_ATTR_POLICE       0x004
00032 #define FW_ATTR_INDEV        0x008
00033 /** @endcond */
00034 
00035 static inline struct rtnl_fw *fw_cls(struct rtnl_cls *cls)
00036 {
00037         return (struct rtnl_fw *) cls->c_subdata;
00038 }
00039 
00040 static inline struct rtnl_fw *fw_alloc(struct rtnl_cls *cls)
00041 {
00042         if (!cls->c_subdata)
00043                 cls->c_subdata = calloc(1, sizeof(struct rtnl_fw));
00044 
00045         return fw_cls(cls);
00046 }
00047 
00048 static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
00049         [TCA_FW_CLASSID]        = { .type = NLA_U32 },
00050         [TCA_FW_INDEV]          = { .type = NLA_STRING,
00051                                     .maxlen = IFNAMSIZ },
00052 };
00053 
00054 static int fw_msg_parser(struct rtnl_cls *cls)
00055 {
00056         int err;
00057         struct nlattr *tb[TCA_FW_MAX + 1];
00058         struct rtnl_fw *f;
00059 
00060         err = tca_parse(tb, TCA_FW_MAX, (struct rtnl_tca *) cls, fw_policy);
00061         if (err < 0)
00062                 return err;
00063 
00064         f = fw_alloc(cls);
00065         if (!f)
00066                 goto errout_nomem;
00067 
00068         if (tb[TCA_FW_CLASSID]) {
00069                 f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
00070                 f->cf_mask |= FW_ATTR_CLASSID;
00071         }
00072 
00073         if (tb[TCA_FW_ACT]) {
00074                 f->cf_act = nla_get_data(tb[TCA_FW_ACT]);
00075                 if (!f->cf_act)
00076                         goto errout_nomem;
00077                 f->cf_mask |= FW_ATTR_ACTION;
00078         }
00079 
00080         if (tb[TCA_FW_POLICE]) {
00081                 f->cf_police = nla_get_data(tb[TCA_FW_POLICE]);
00082                 if (!f->cf_police)
00083                         goto errout_nomem;
00084                 f->cf_mask |= FW_ATTR_POLICE;
00085         }
00086 
00087         if (tb[TCA_FW_INDEV]) {
00088                 nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
00089                 f->cf_mask |= FW_ATTR_INDEV;
00090         }
00091 
00092         return 0;
00093 
00094 errout_nomem:
00095         err = nl_errno(ENOMEM);
00096 
00097         return err;
00098 }
00099 
00100 static void fw_free_data(struct rtnl_cls *cls)
00101 {
00102         struct rtnl_fw *f = fw_cls(cls);
00103 
00104         if (!f)
00105                 return;
00106 
00107         nl_data_free(f->cf_act);
00108         nl_data_free(f->cf_police);
00109 
00110         free(cls->c_subdata);
00111 }
00112 
00113 static int fw_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
00114 {
00115         struct rtnl_fw *dst, *src = fw_cls(_src);
00116 
00117         if (!src)
00118                 return 0;
00119 
00120         dst = fw_alloc(_dst);
00121         if (!dst)
00122                 return nl_errno(ENOMEM);
00123 
00124         if (src->cf_act)
00125                 if (!(dst->cf_act = nl_data_clone(src->cf_act)))
00126                         goto errout;
00127         
00128         if (src->cf_police)
00129                 if (!(dst->cf_police = nl_data_clone(src->cf_police)))
00130                         goto errout;
00131 
00132         return 0;
00133 errout:
00134         return nl_get_errno();
00135 }
00136 
00137 static int fw_dump_brief(struct rtnl_cls *cls, struct nl_dump_params *p,
00138                           int line)
00139 {
00140         struct rtnl_fw *f = fw_cls(cls);
00141         char buf[32];
00142 
00143         if (!f)
00144                 goto ignore;
00145 
00146         if (f->cf_mask & FW_ATTR_CLASSID)
00147                 dp_dump(p, " target %s",
00148                         rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
00149 
00150 ignore:
00151         return line;
00152 }
00153 
00154 static int fw_dump_full(struct rtnl_cls *cls, struct nl_dump_params *p,
00155                          int line)
00156 {
00157         struct rtnl_fw *f = fw_cls(cls);
00158 
00159         if (!f)
00160                 goto ignore;
00161 
00162         if (f->cf_mask & FW_ATTR_INDEV)
00163                 dp_dump(p, "indev %s ", f->cf_indev);
00164 
00165 ignore:
00166         return line;
00167 }
00168 
00169 static int fw_dump_stats(struct rtnl_cls *cls, struct nl_dump_params *p,
00170                           int line)
00171 {
00172         struct rtnl_fw *f = fw_cls(cls);
00173 
00174         if (!f)
00175                 goto ignore;
00176 
00177 ignore:
00178         return line;
00179 }
00180 
00181 static struct nl_msg *fw_get_opts(struct rtnl_cls *cls)
00182 {
00183         struct rtnl_fw *f;
00184         struct nl_msg *msg;
00185         
00186         f = fw_cls(cls);
00187         if (!f)
00188                 return NULL;
00189 
00190         msg = nlmsg_alloc();
00191         if (!msg)
00192                 return NULL;
00193 
00194         if (f->cf_mask & FW_ATTR_CLASSID)
00195                 nla_put_u32(msg, TCA_FW_CLASSID, f->cf_classid);
00196 
00197         if (f->cf_mask & FW_ATTR_ACTION)
00198                 nla_put_data(msg, TCA_FW_ACT, f->cf_act);
00199 
00200         if (f->cf_mask & FW_ATTR_POLICE)
00201                 nla_put_data(msg, TCA_FW_POLICE, f->cf_police);
00202 
00203         if (f->cf_mask & FW_ATTR_INDEV)
00204                 nla_put_string(msg, TCA_FW_INDEV, f->cf_indev);
00205 
00206         return msg;
00207 }
00208 
00209 /**
00210  * @name Attribute Modifications
00211  * @{
00212  */
00213 
00214 int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
00215 {
00216         struct rtnl_fw *f;
00217         
00218         f = fw_alloc(cls);
00219         if (!f)
00220                 return nl_errno(ENOMEM);
00221 
00222         f->cf_classid = classid;
00223         f->cf_mask |= FW_ATTR_CLASSID;
00224 
00225         return 0;
00226 }
00227 
00228 /** @} */
00229 
00230 static struct rtnl_cls_ops fw_ops = {
00231         .co_kind                = "fw",
00232         .co_msg_parser          = fw_msg_parser,
00233         .co_free_data           = fw_free_data,
00234         .co_clone               = fw_clone,
00235         .co_get_opts            = fw_get_opts,
00236         .co_dump[NL_DUMP_BRIEF] = fw_dump_brief,
00237         .co_dump[NL_DUMP_FULL]  = fw_dump_full,
00238         .co_dump[NL_DUMP_STATS] = fw_dump_stats,
00239 };
00240 
00241 static void __init fw_init(void)
00242 {
00243         rtnl_cls_register(&fw_ops);
00244 }
00245 
00246 static void __exit fw_exit(void)
00247 {
00248         rtnl_cls_unregister(&fw_ops);
00249 }
00250 
00251 /** @} */