Home | History | Annotate | Download | only in cls
      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 (at) suug.ch>
     10  * Copyright (c) 2006 Petr Gotthard <petr.gotthard (at) 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 /** @} */
    181