libnl 1.1
|
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 /** @} */