/* SPDX-License-Identifier: LGPL-2.1-only */ /* * 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 */ /** * @ingroup fib_lookup * @defgroup flreq Request * @brief * @{ */ #include #include #include #include #include #include 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 uint64_t request_compare(struct nl_object *_a, struct nl_object *_b, uint64_t attrs, int flags) { struct flnl_request *a = (struct flnl_request *) _a; struct flnl_request *b = (struct flnl_request *) _b; uint64_t 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, }; /** @} */