nexmon – Rev 1

Subversion Repositories:
Rev:
/*
 * lib/fib_lookup/request.c     FIB Lookup Request
 *
 *      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-2008 Thomas Graf <tgraf@suug.ch>
 */

/**
 * @ingroup fib_lookup
 * @defgroup flreq Request
 * @brief
 * @{
 */

#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/fib_lookup/request.h>

static struct nl_object_ops request_obj_ops;

/** @cond SKIP */
#define REQUEST_ATTR_ADDR       0x01
#define REQUEST_ATTR_FWMARK     0x02
#define REQUEST_ATTR_TOS        0x04
#define REQUEST_ATTR_SCOPE      0x08
#define REQUEST_ATTR_TABLE      0x10
/** @endcond */

static void request_free_data(struct nl_object *obj)
{
        struct flnl_request *req = REQUEST_CAST(obj);

        if (req)
                nl_addr_put(req->lr_addr);
}

static int request_clone(struct nl_object *_dst, struct nl_object *_src)
{
        struct flnl_request *dst = nl_object_priv(_dst);
        struct flnl_request *src = nl_object_priv(_src);

        if (src->lr_addr)
                if (!(dst->lr_addr = nl_addr_clone(src->lr_addr)))
                        return -NLE_NOMEM;

        return 0;
}

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

#define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)

        diff |= REQ_DIFF(FWMARK,        a->lr_fwmark != b->lr_fwmark);
        diff |= REQ_DIFF(TOS,           a->lr_tos != b->lr_tos);
        diff |= REQ_DIFF(SCOPE,         a->lr_scope != b->lr_scope);
        diff |= REQ_DIFF(TABLE,         a->lr_table != b->lr_table);
        diff |= REQ_DIFF(ADDR,          nl_addr_cmp(a->lr_addr, b->lr_addr));

#undef REQ_DIFF

        return diff;
}


/**
 * @name Lookup Request Creation/Deletion
 * @{
 */

struct flnl_request *flnl_request_alloc(void)
{
        return REQUEST_CAST(nl_object_alloc(&request_obj_ops));
}

/** @} */

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

void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark)
{
        req->lr_fwmark = fwmark;
        req->ce_mask |= REQUEST_ATTR_FWMARK;
}

uint64_t flnl_request_get_fwmark(struct flnl_request *req)
{
        if (req->ce_mask & REQUEST_ATTR_FWMARK)
                return req->lr_fwmark;
        else
                return UINT_LEAST64_MAX;
}

void flnl_request_set_tos(struct flnl_request *req, int tos)
{
        req->lr_tos = tos;
        req->ce_mask |= REQUEST_ATTR_TOS;
}

int flnl_request_get_tos(struct flnl_request *req)
{
        if (req->ce_mask & REQUEST_ATTR_TOS)
                return req->lr_tos;
        else
                return -1;
}

void flnl_request_set_scope(struct flnl_request *req, int scope)
{
        req->lr_scope = scope;
        req->ce_mask |= REQUEST_ATTR_SCOPE;
}

int flnl_request_get_scope(struct flnl_request *req)
{
        if (req->ce_mask & REQUEST_ATTR_SCOPE)
                return req->lr_scope;
        else
                return -1;
}

void flnl_request_set_table(struct flnl_request *req, int table)
{
        req->lr_table = table;
        req->ce_mask |= REQUEST_ATTR_TABLE;
}

int flnl_request_get_table(struct flnl_request *req)
{
        if (req->ce_mask & REQUEST_ATTR_TABLE)
                return req->lr_table;
        else
                return -1;
}

int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr)
{
        if (addr->a_family != AF_INET)
                return -NLE_AF_NOSUPPORT;

        if (req->lr_addr)
                nl_addr_put(req->lr_addr);

        nl_addr_get(addr);
        req->lr_addr = addr;

        req->ce_mask |= REQUEST_ATTR_ADDR;

        return 0;
}

struct nl_addr *flnl_request_get_addr(struct flnl_request *req)
{
        if (req->ce_mask & REQUEST_ATTR_ADDR)
                return req->lr_addr;
        else
                return NULL;
}

/** @} */

static struct nl_object_ops request_obj_ops = {
        .oo_name                = "fib_lookup/request",
        .oo_size                = sizeof(struct flnl_request),
        .oo_free_data           = request_free_data,
        .oo_clone               = request_clone,
        .oo_compare             = request_compare,
        .oo_id_attrs            = ~0,
};

/** @} */