nbyte.c

00001 /*
00002  * lib/route/cls/ematch/nbyte.c         Nbyte comparison
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) 2010 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup ematch
00014  * @defgroup em_nbyte N-Byte Comparison
00015  *
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink-tc.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/route/cls/ematch.h>
00023 #include <netlink/route/cls/ematch/nbyte.h>
00024 
00025 struct nbyte_data
00026 {
00027         struct tcf_em_nbyte     cfg;
00028         uint8_t *               pattern;
00029 };
00030 
00031 void rtnl_ematch_nbyte_set_offset(struct rtnl_ematch *e, uint8_t layer,
00032                                   uint16_t offset)
00033 {
00034         struct nbyte_data *n = rtnl_ematch_data(e);
00035         n->cfg.off = offset;
00036         n->cfg.layer = layer;
00037 }
00038 
00039 uint16_t rtnl_ematch_nbyte_get_offset(struct rtnl_ematch *e)
00040 {
00041         return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.off;
00042 }
00043 
00044 uint8_t rtnl_ematch_nbyte_get_layer(struct rtnl_ematch *e)
00045 {
00046         return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.layer;
00047 }
00048 
00049 void rtnl_ematch_nbyte_set_pattern(struct rtnl_ematch *e,
00050                                    uint8_t *pattern, size_t len)
00051 {
00052         struct nbyte_data *n = rtnl_ematch_data(e);
00053 
00054         if (n->pattern)
00055                 free(n->pattern);
00056 
00057         n->pattern = pattern;
00058         n->cfg.len = len;
00059 }
00060 
00061 uint8_t *rtnl_ematch_nbyte_get_pattern(struct rtnl_ematch *e)
00062 {
00063         return ((struct nbyte_data *) rtnl_ematch_data(e))->pattern;
00064 }
00065 
00066 size_t rtnl_ematch_nbyte_get_len(struct rtnl_ematch *e)
00067 {
00068         return ((struct nbyte_data *) rtnl_ematch_data(e))->cfg.len;
00069 }
00070 
00071 static const char *layer_txt(struct tcf_em_nbyte *nbyte)
00072 {
00073         switch (nbyte->layer) {
00074         case TCF_LAYER_LINK:
00075                 return "link";
00076         case TCF_LAYER_NETWORK:
00077                 return "net";
00078         case TCF_LAYER_TRANSPORT:
00079                 return "trans";
00080         default:
00081                 return "?";
00082         }
00083 }
00084 
00085 static int nbyte_parse(struct rtnl_ematch *e, void *data, size_t len)
00086 {
00087         struct nbyte_data *n = rtnl_ematch_data(e);
00088         size_t hdrlen = sizeof(struct tcf_em_nbyte);
00089         size_t plen = len - hdrlen;
00090 
00091         memcpy(&n->cfg, data, hdrlen);
00092         if (plen > 0) {
00093                 if (!(n->pattern = calloc(1, plen)))
00094                         return -NLE_NOMEM;
00095 
00096                 memcpy(n->pattern, data + hdrlen, plen);
00097         }
00098 
00099         return 0;
00100 }
00101 
00102 static void nbyte_dump(struct rtnl_ematch *e, struct nl_dump_params *p)
00103 {
00104         struct nbyte_data *n = rtnl_ematch_data(e);
00105         int i;
00106 
00107         nl_dump(p, "pattern(%u:[", n->cfg.len);
00108 
00109         for (i = 0; i < n->cfg.len; i++) {
00110                 nl_dump(p, "%02x", n->pattern[i]);
00111                 if (i+1 < n->cfg.len)
00112                         nl_dump(p, " ");
00113         }
00114 
00115         nl_dump(p, "] at %s+%u)", layer_txt(&n->cfg), n->cfg.off);
00116 }
00117 
00118 static void nbyte_free(struct rtnl_ematch *e)
00119 {
00120         struct nbyte_data *n = rtnl_ematch_data(e);
00121         free(n->pattern);
00122 }
00123 
00124 static struct rtnl_ematch_ops nbyte_ops = {
00125         .eo_kind        = TCF_EM_NBYTE,
00126         .eo_name        = "nbyte",
00127         .eo_minlen      = sizeof(struct tcf_em_nbyte),
00128         .eo_datalen     = sizeof(struct nbyte_data),
00129         .eo_parse       = nbyte_parse,
00130         .eo_dump        = nbyte_dump,
00131         .eo_free        = nbyte_free,
00132 };
00133 
00134 static void __init nbyte_init(void)
00135 {
00136         rtnl_ematch_register(&nbyte_ops);
00137 }
00138 
00139 /** @} */