Logo Search packages:      
Sourcecode: libnl version File versions

family.c

/*
 * lib/genl/family.c          Generic Netlink Family
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation version 2.1
 *    of the License.
 *
 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
 */

/**
 * @ingroup genl
 * @defgroup genl_family Generic Netlink Family
 * @brief
 *
 * @{
 */

#include <netlink-generic.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/utils.h>

/** @cond SKIP */
#define FAMILY_ATTR_ID        0x01
#define FAMILY_ATTR_NAME      0x02
#define FAMILY_ATTR_VERSION   0x04
#define FAMILY_ATTR_HDRSIZE   0x08
#define FAMILY_ATTR_MAXATTR   0x10
#define FAMILY_ATTR_OPS       0x20

struct nl_object_ops genl_family_ops;
/** @endcond */

00037 static void family_constructor(struct nl_object *c)
{
      struct genl_family *family = (struct genl_family *) c;

      nl_init_list_head(&family->gf_ops);
}

static void family_free_data(struct nl_object *c)
{
      struct genl_family *family = (struct genl_family *) c;
      struct genl_family_op *ops, *tmp;

      if (family == NULL)
            return;

      nl_list_for_each_entry_safe(ops, tmp, &family->gf_ops, o_list) {
            nl_list_del(&ops->o_list);
            free(ops);
      }
}

static int family_clone(struct nl_object *_dst, struct nl_object *_src)
{
      struct genl_family *dst = nl_object_priv(_dst);
      struct genl_family *src = nl_object_priv(_src);
      struct genl_family_op *ops;
      int err;

      nl_list_for_each_entry(ops, &src->gf_ops, o_list) {
            err = genl_family_add_op(dst, ops->o_id, ops->o_flags);
            if (err < 0)
                  return err;
      }
      
      return 0;
}

static int family_dump_brief(struct nl_object *obj, struct nl_dump_params *p)
{
      struct genl_family *family = (struct genl_family *) obj;

      dp_dump(p, "0x%04x %s version %u\n",
            family->gf_id, family->gf_name, family->gf_version);

      return 1;
}

static struct trans_tbl ops_flags[] = {
      __ADD(GENL_ADMIN_PERM, admin-perm)
      __ADD(GENL_CMD_CAP_DO, has-doit)
      __ADD(GENL_CMD_CAP_DUMP, has-dump)
      __ADD(GENL_CMD_CAP_HASPOL, has-policy)
};

static char *ops_flags2str(int flags, char *buf, size_t len)
{
      return __flags2str(flags, buf, len, ops_flags, ARRAY_SIZE(ops_flags));
}

static int family_dump_full(struct nl_object *obj, struct nl_dump_params *p)
{
      struct genl_family *family = (struct genl_family *) obj;
      int line;

      line = family_dump_brief(obj, p);
      dp_dump_line(p, line++, "    hdrsize %u maxattr %u\n",
                 family->gf_hdrsize, family->gf_maxattr);

      if (family->ce_mask & FAMILY_ATTR_OPS) {
            struct genl_family_op *op;
            char buf[64];

            nl_list_for_each_entry(op, &family->gf_ops, o_list) {
                  ops_flags2str(op->o_flags, buf, sizeof(buf));

                  genl_op2name(family->gf_id, op->o_id, buf, sizeof(buf));

                  dp_dump_line(p, line++, "      op %s (0x%02x)",
                             buf, op->o_id);

                  if (op->o_flags)
                        dp_dump(p, " <%s>",
                              ops_flags2str(op->o_flags, buf,
                                          sizeof(buf)));

                  dp_dump(p, "\n");
            }
      }

      return line;
}

static int family_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
{
      return family_dump_full(obj, p);
}

static int family_compare(struct nl_object *_a, struct nl_object *_b,
                    uint32_t attrs, int flags)
{
      struct genl_family *a = (struct genl_family *) _a;
      struct genl_family *b = (struct genl_family *) _b;
      int diff = 0;

#define FAM_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, FAMILY_ATTR_##ATTR, a, b, EXPR)

      diff |= FAM_DIFF(ID,          a->gf_id != b->gf_id);
      diff |= FAM_DIFF(VERSION,     a->gf_version != b->gf_version);
      diff |= FAM_DIFF(HDRSIZE,     a->gf_hdrsize != b->gf_hdrsize);
      diff |= FAM_DIFF(MAXATTR,     a->gf_maxattr != b->gf_maxattr);
      diff |= FAM_DIFF(NAME,        strcmp(a->gf_name, b->gf_name));

#undef FAM_DIFF

      return diff;
}


/**
 * @name Family Object
 * @{
 */

struct genl_family *genl_family_alloc(void)
{
      return (struct genl_family *) nl_object_alloc(&genl_family_ops);
}

void genl_family_put(struct genl_family *family)
{
      nl_object_put((struct nl_object *) family);
}

/** @} */

/**
 * @name Attributes
 * @{
 */

unsigned int genl_family_get_id(struct genl_family *family)
{
      if (family->ce_mask & FAMILY_ATTR_ID)
            return family->gf_id;
      else
            return GENL_ID_GENERATE;
}

void genl_family_set_id(struct genl_family *family, unsigned int id)
{
      family->gf_id = id;
      family->ce_mask |= FAMILY_ATTR_ID;
}

char *genl_family_get_name(struct genl_family *family)
{
      if (family->ce_mask & FAMILY_ATTR_NAME)
            return family->gf_name;
      else
            return NULL;
}

void genl_family_set_name(struct genl_family *family, const char *name)
{
      strncpy(family->gf_name, name, GENL_NAMSIZ-1);
      family->ce_mask |= FAMILY_ATTR_NAME;
}

uint8_t genl_family_get_version(struct genl_family *family)
{
      if (family->ce_mask & FAMILY_ATTR_VERSION)
            return family->gf_version;
      else
            return 0;
}

void genl_family_set_version(struct genl_family *family, uint8_t version)
{
      family->gf_version = version;
      family->ce_mask |= FAMILY_ATTR_VERSION;
}

uint32_t genl_family_get_hdrsize(struct genl_family *family)
{
      if (family->ce_mask & FAMILY_ATTR_HDRSIZE)
            return family->gf_hdrsize;
      else
            return 0;
}

void genl_family_set_hdrsize(struct genl_family *family, uint32_t hdrsize)
{
      family->gf_hdrsize = hdrsize;
      family->ce_mask |= FAMILY_ATTR_HDRSIZE;
}

uint32_t genl_family_get_maxattr(struct genl_family *family)
{
      if (family->ce_mask & FAMILY_ATTR_MAXATTR)
            return family->gf_maxattr;
      else
            return family->gf_maxattr;
}

void genl_family_set_maxattr(struct genl_family *family, uint32_t maxattr)
{
      family->gf_maxattr = maxattr;
      family->ce_mask |= FAMILY_ATTR_MAXATTR;
}

int genl_family_add_op(struct genl_family *family, int id, int flags)
{
      struct genl_family_op *op;

      op = calloc(1, sizeof(*op));
      if (op == NULL)
            return nl_errno(ENOMEM);

      op->o_id = id;
      op->o_flags = flags;

      nl_list_add_tail(&op->o_list, &family->gf_ops);
      family->ce_mask |= FAMILY_ATTR_OPS;

      return 0;
}

/** @} */

/** @cond SKIP */
struct nl_object_ops genl_family_ops = {
      .oo_name          = "genl/family",
      .oo_size          = sizeof(struct genl_family),
      .oo_constructor         = family_constructor,
      .oo_free_data           = family_free_data,
      .oo_clone         = family_clone,
      .oo_dump[NL_DUMP_BRIEF] = family_dump_brief,
      .oo_dump[NL_DUMP_FULL]  = family_dump_full,
      .oo_dump[NL_DUMP_STATS] = family_dump_stats,
#if 0
      .oo_dump[NL_DUMP_XML]   = addr_dump_xml,
      .oo_dump[NL_DUMP_ENV]   = addr_dump_env,
#endif
      .oo_compare       = family_compare,
      .oo_id_attrs            = FAMILY_ATTR_ID,
};
/** @endcond */

/** @} */

Generated by  Doxygen 1.6.0   Back to index