libnl  3.2.3
/build/buildd/libnl3-3.2.3/lib/route/cls/basic.c
00001 /*
00002  * lib/route/cls/basic.c        Basic 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) 2008-2011 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup cls
00014  * @defgroup cls_basic Basic Classifier
00015  *
00016  * @par Introduction
00017  * The basic classifier is the simplest form of a classifier. It does
00018  * not have any special classification capabilities, instead it can be
00019  * used to classify exclusively based on extended matches or to
00020  * create a "catch-all" filter.
00021  *
00022  * @{
00023  */
00024 
00025 #include <netlink-local.h>
00026 #include <netlink-tc.h>
00027 #include <netlink/netlink.h>
00028 #include <netlink/route/tc-api.h>
00029 #include <netlink/route/classifier.h>
00030 #include <netlink/route/cls/basic.h>
00031 #include <netlink/route/cls/ematch.h>
00032 
00033 struct rtnl_basic
00034 {
00035         uint32_t                        b_target;
00036         struct rtnl_ematch_tree *       b_ematch;
00037         int                             b_mask;
00038 };
00039 
00040 /** @cond SKIP */
00041 #define BASIC_ATTR_TARGET       0x001
00042 #define BASIC_ATTR_EMATCH       0x002
00043 /** @endcond */
00044 
00045 static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
00046         [TCA_BASIC_CLASSID]     = { .type = NLA_U32 },
00047         [TCA_BASIC_EMATCHES]    = { .type = NLA_NESTED },
00048 };
00049 
00050 static int basic_clone(void *_dst, void *_src)
00051 {
00052         return -NLE_OPNOTSUPP;
00053 }
00054 
00055 static void basic_free_data(struct rtnl_tc *tc, void *data)
00056 {
00057         struct rtnl_basic *b = data;
00058 
00059         if (!b)
00060                 return;
00061 
00062         rtnl_ematch_tree_free(b->b_ematch);
00063 }
00064 
00065 static int basic_msg_parser(struct rtnl_tc *tc, void *data)
00066 {
00067         struct nlattr *tb[TCA_BASIC_MAX + 1];
00068         struct rtnl_basic *b = data;
00069         int err;
00070 
00071         err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
00072         if (err < 0)
00073                 return err;
00074 
00075         if (tb[TCA_BASIC_CLASSID]) {
00076                 b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
00077                 b->b_mask |= BASIC_ATTR_TARGET;
00078         }
00079 
00080         if (tb[TCA_BASIC_EMATCHES]) {
00081                 if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
00082                                              &b->b_ematch)) < 0)
00083                         return err;
00084 
00085                 if (b->b_ematch)
00086                         b->b_mask |= BASIC_ATTR_EMATCH;
00087         }
00088 
00089         return 0;
00090 }
00091 
00092 static void basic_dump_line(struct rtnl_tc *tc, void *data,
00093                             struct nl_dump_params *p)
00094 {
00095         struct rtnl_basic *b = data;
00096         char buf[32];
00097 
00098         if (!b)
00099                 return;
00100 
00101         if (b->b_mask & BASIC_ATTR_EMATCH)
00102                 nl_dump(p, " ematch");
00103         else
00104                 nl_dump(p, " match-all");
00105 
00106         if (b->b_mask & BASIC_ATTR_TARGET)
00107                 nl_dump(p, " target %s",
00108                         rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
00109 }
00110 
00111 static void basic_dump_details(struct rtnl_tc *tc, void *data,
00112                                struct nl_dump_params *p)
00113 {
00114         struct rtnl_basic *b = data;
00115 
00116         if (!b)
00117                 return;
00118 
00119         if (b->b_mask & BASIC_ATTR_EMATCH) {
00120                 nl_dump_line(p, "    ematch ");
00121                 rtnl_ematch_tree_dump(b->b_ematch, p);
00122         } else
00123                 nl_dump(p, "no options.\n");
00124 }
00125 
00126 static int basic_msg_fill(struct rtnl_tc *tc, void *data,
00127                           struct nl_msg *msg)
00128 {
00129         struct rtnl_basic *b = data;
00130 
00131         if (!b)
00132                 return 0;
00133 
00134         if (!(b->b_mask & BASIC_ATTR_TARGET))
00135                 return -NLE_MISSING_ATTR;
00136 
00137         NLA_PUT_U32(msg, TCA_BASIC_CLASSID, b->b_target);
00138 
00139         if (b->b_mask & BASIC_ATTR_EMATCH &&
00140             rtnl_ematch_fill_attr(msg, TCA_BASIC_EMATCHES, b->b_ematch) < 0)
00141                 goto nla_put_failure;
00142         
00143         return 0;
00144 
00145 nla_put_failure:
00146         return -NLE_NOMEM;
00147 }
00148 
00149 /**
00150  * @name Attribute Modifications
00151  * @{
00152  */
00153 
00154 void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
00155 {
00156         struct rtnl_basic *b;
00157 
00158         if (!(b = rtnl_tc_data(TC_CAST(cls))))
00159                 return;
00160 
00161         b->b_target = target;
00162         b->b_mask |= BASIC_ATTR_TARGET;
00163 }
00164 
00165 uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
00166 {
00167         struct rtnl_basic *b;
00168 
00169         if (!(b = rtnl_tc_data(TC_CAST(cls))))
00170                 return 0;
00171 
00172         return b->b_target;
00173 }
00174 
00175 void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
00176 {
00177         struct rtnl_basic *b;
00178 
00179         if (!(b = rtnl_tc_data(TC_CAST(cls))))
00180                 return;
00181 
00182         if (b->b_ematch) {
00183                 rtnl_ematch_tree_free(b->b_ematch);
00184                 b->b_mask &= ~BASIC_ATTR_EMATCH;
00185         }
00186 
00187         b->b_ematch = tree;
00188 
00189         if (tree)
00190                 b->b_mask |= BASIC_ATTR_EMATCH;
00191 }
00192 
00193 struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
00194 {
00195         struct rtnl_basic *b;
00196 
00197         if (!(b = rtnl_tc_data(TC_CAST(cls))))
00198                 return NULL;
00199 
00200         return b->b_ematch;
00201 }
00202 
00203 /** @} */
00204 
00205 static struct rtnl_tc_ops basic_ops = {
00206         .to_kind                = "basic",
00207         .to_type                = RTNL_TC_TYPE_CLS,
00208         .to_size                = sizeof(struct rtnl_basic),
00209         .to_msg_parser          = basic_msg_parser,
00210         .to_clone               = basic_clone,
00211         .to_free_data           = basic_free_data,
00212         .to_msg_fill            = basic_msg_fill,
00213         .to_dump = {
00214             [NL_DUMP_LINE]      = basic_dump_line,
00215             [NL_DUMP_DETAILS]   = basic_dump_details,
00216         },
00217 };
00218 
00219 static void __init basic_init(void)
00220 {
00221         rtnl_tc_register(&basic_ops);
00222 }
00223 
00224 static void __exit basic_exit(void)
00225 {
00226         rtnl_tc_unregister(&basic_ops);
00227 }
00228 
00229 /** @} */