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-2013 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
     16  * @defgroup cls_fw Firewall Classifier
     17  *
     18  * @{
     19  */
     20 
     21 #include <netlink-private/netlink.h>
     22 #include <netlink-private/tc.h>
     23 #include <netlink/netlink.h>
     24 #include <netlink-private/route/tc-api.h>
     25 #include <netlink/route/classifier.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 #define FW_ATTR_MASK         0x010
     34 /** @endcond */
     35 
     36 static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
     37 	[TCA_FW_CLASSID]	= { .type = NLA_U32 },
     38 	[TCA_FW_INDEV]		= { .type = NLA_STRING,
     39 				    .maxlen = IFNAMSIZ },
     40 	[TCA_FW_MASK]		= { .type = NLA_U32 },
     41 };
     42 
     43 static int fw_msg_parser(struct rtnl_tc *tc, void *data)
     44 {
     45 	struct nlattr *tb[TCA_FW_MAX + 1];
     46 	struct rtnl_fw *f = data;
     47 	int err;
     48 
     49 	err = tca_parse(tb, TCA_FW_MAX, tc, fw_policy);
     50 	if (err < 0)
     51 		return err;
     52 
     53 	if (tb[TCA_FW_CLASSID]) {
     54 		f->cf_classid = nla_get_u32(tb[TCA_FW_CLASSID]);
     55 		f->cf_mask |= FW_ATTR_CLASSID;
     56 	}
     57 
     58 	if (tb[TCA_FW_ACT]) {
     59 		f->cf_act = nl_data_alloc_attr(tb[TCA_FW_ACT]);
     60 		if (!f->cf_act)
     61 			return -NLE_NOMEM;
     62 		f->cf_mask |= FW_ATTR_ACTION;
     63 	}
     64 
     65 	if (tb[TCA_FW_POLICE]) {
     66 		f->cf_police = nl_data_alloc_attr(tb[TCA_FW_POLICE]);
     67 		if (!f->cf_police)
     68 			return -NLE_NOMEM;
     69 		f->cf_mask |= FW_ATTR_POLICE;
     70 	}
     71 
     72 	if (tb[TCA_FW_INDEV]) {
     73 		nla_strlcpy(f->cf_indev, tb[TCA_FW_INDEV], IFNAMSIZ);
     74 		f->cf_mask |= FW_ATTR_INDEV;
     75 	}
     76 
     77 	if (tb[TCA_FW_MASK]) {
     78 		f->cf_fwmask = nla_get_u32(tb[TCA_FW_MASK]);
     79 		f->cf_mask |= FW_ATTR_MASK;
     80 	}
     81 
     82 	return 0;
     83 }
     84 
     85 static void fw_free_data(struct rtnl_tc *tc, void *data)
     86 {
     87 	struct rtnl_fw *f = data;
     88 
     89 	nl_data_free(f->cf_act);
     90 	nl_data_free(f->cf_police);
     91 }
     92 
     93 static int fw_clone(void *_dst, void *_src)
     94 {
     95 	struct rtnl_fw *dst = _dst, *src = _src;
     96 
     97 	if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act)))
     98 		return -NLE_NOMEM;
     99 
    100 	if (src->cf_police && !(dst->cf_police = nl_data_clone(src->cf_police)))
    101 		return -NLE_NOMEM;
    102 
    103 	return 0;
    104 }
    105 
    106 static void fw_dump_line(struct rtnl_tc *tc, void *data,
    107 			 struct nl_dump_params *p)
    108 {
    109 	struct rtnl_fw *f = data;
    110 
    111 	if (!f)
    112 		return;
    113 
    114 	if (f->cf_mask & FW_ATTR_CLASSID) {
    115 		char buf[32];
    116 
    117 		nl_dump(p, " target %s",
    118 			rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
    119 	}
    120 
    121 	if (f->cf_mask & FW_ATTR_MASK)
    122 		nl_dump(p, " mask 0x%x", f->cf_fwmask);
    123 }
    124 
    125 static void fw_dump_details(struct rtnl_tc *tc, void *data,
    126 			    struct nl_dump_params *p)
    127 {
    128 	struct rtnl_fw *f = data;
    129 
    130 	if (f && f->cf_mask & FW_ATTR_INDEV)
    131 		nl_dump(p, "indev %s ", f->cf_indev);
    132 }
    133 
    134 static int fw_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
    135 {
    136 	struct rtnl_fw *f = data;
    137 
    138 	if (!f)
    139 		return 0;
    140 
    141 	if (f->cf_mask & FW_ATTR_CLASSID)
    142 		NLA_PUT_U32(msg, TCA_FW_CLASSID, f->cf_classid);
    143 
    144 	if (f->cf_mask & FW_ATTR_ACTION)
    145 		NLA_PUT_DATA(msg, TCA_FW_ACT, f->cf_act);
    146 
    147 	if (f->cf_mask & FW_ATTR_POLICE)
    148 		NLA_PUT_DATA(msg, TCA_FW_POLICE, f->cf_police);
    149 
    150 	if (f->cf_mask & FW_ATTR_INDEV)
    151 		NLA_PUT_STRING(msg, TCA_FW_INDEV, f->cf_indev);
    152 
    153 	if (f->cf_mask & FW_ATTR_MASK)
    154 		NLA_PUT_U32(msg, TCA_FW_MASK, f->cf_fwmask);
    155 
    156 	return 0;
    157 
    158 nla_put_failure:
    159 	return -NLE_MSGSIZE;
    160 }
    161 
    162 /**
    163  * @name Attribute Modifications
    164  * @{
    165  */
    166 
    167 int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
    168 {
    169 	struct rtnl_fw *f;
    170 
    171 	if (!(f = rtnl_tc_data(TC_CAST(cls))))
    172 		return -NLE_NOMEM;
    173 
    174 	f->cf_classid = classid;
    175 	f->cf_mask |= FW_ATTR_CLASSID;
    176 
    177 	return 0;
    178 }
    179 
    180 int rtnl_fw_set_mask(struct rtnl_cls *cls, uint32_t mask)
    181 {
    182 	struct rtnl_fw *f;
    183 
    184 	if (!(f = rtnl_tc_data(TC_CAST(cls))))
    185 		return -NLE_NOMEM;
    186 
    187 	f->cf_fwmask = mask;
    188 	f->cf_mask |= FW_ATTR_MASK;
    189 
    190 	return 0;
    191 }
    192 
    193 /** @} */
    194 
    195 static struct rtnl_tc_ops fw_ops = {
    196 	.to_kind		= "fw",
    197 	.to_type		= RTNL_TC_TYPE_CLS,
    198 	.to_size		= sizeof(struct rtnl_fw),
    199 	.to_msg_parser		= fw_msg_parser,
    200 	.to_msg_fill		= fw_msg_fill,
    201 	.to_free_data		= fw_free_data,
    202 	.to_clone		= fw_clone,
    203 	.to_dump = {
    204 	    [NL_DUMP_LINE]	= fw_dump_line,
    205 	    [NL_DUMP_DETAILS]	= fw_dump_details,
    206 	},
    207 };
    208 
    209 static void __init fw_init(void)
    210 {
    211 	rtnl_tc_register(&fw_ops);
    212 }
    213 
    214 static void __exit fw_exit(void)
    215 {
    216 	rtnl_tc_unregister(&fw_ops);
    217 }
    218 
    219 /** @} */
    220