Home | History | Annotate | Download | only in fib_lookup
      1 /*
      2  * lib/fib_lookup/request.c	FIB Lookup Request
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2003-2008 Thomas Graf <tgraf (at) suug.ch>
     10  */
     11 
     12 /**
     13  * @ingroup fib_lookup
     14  * @defgroup flreq Request
     15  * @brief
     16  * @{
     17  */
     18 
     19 #include <netlink-local.h>
     20 #include <netlink/netlink.h>
     21 #include <netlink/attr.h>
     22 #include <netlink/utils.h>
     23 #include <netlink/object.h>
     24 #include <netlink/fib_lookup/request.h>
     25 
     26 static struct nl_object_ops request_obj_ops;
     27 
     28 /** @cond SKIP */
     29 #define REQUEST_ATTR_ADDR	0x01
     30 #define REQUEST_ATTR_FWMARK	0x02
     31 #define REQUEST_ATTR_TOS	0x04
     32 #define REQUEST_ATTR_SCOPE	0x08
     33 #define REQUEST_ATTR_TABLE	0x10
     34 /** @endcond */
     35 
     36 static void request_free_data(struct nl_object *obj)
     37 {
     38 	struct flnl_request *req = REQUEST_CAST(obj);
     39 
     40 	if (req)
     41 		nl_addr_put(req->lr_addr);
     42 }
     43 
     44 static int request_clone(struct nl_object *_dst, struct nl_object *_src)
     45 {
     46 	struct flnl_request *dst = nl_object_priv(_dst);
     47 	struct flnl_request *src = nl_object_priv(_src);
     48 
     49 	if (src->lr_addr)
     50 		if (!(dst->lr_addr = nl_addr_clone(src->lr_addr)))
     51 			return -NLE_NOMEM;
     52 
     53 	return 0;
     54 }
     55 
     56 static int request_compare(struct nl_object *_a, struct nl_object *_b,
     57 			   uint32_t attrs, int flags)
     58 {
     59 	struct flnl_request *a = (struct flnl_request *) _a;
     60 	struct flnl_request *b = (struct flnl_request *) _b;
     61 	int diff = 0;
     62 
     63 #define REQ_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, REQUEST_ATTR_##ATTR, a, b, EXPR)
     64 
     65 	diff |= REQ_DIFF(FWMARK,	a->lr_fwmark != b->lr_fwmark);
     66 	diff |= REQ_DIFF(TOS,		a->lr_tos != b->lr_tos);
     67 	diff |= REQ_DIFF(SCOPE,		a->lr_scope != b->lr_scope);
     68 	diff |= REQ_DIFF(TABLE,		a->lr_table != b->lr_table);
     69 	diff |= REQ_DIFF(ADDR,		nl_addr_cmp(a->lr_addr, b->lr_addr));
     70 
     71 #undef REQ_DIFF
     72 
     73 	return diff;
     74 }
     75 
     76 
     77 /**
     78  * @name Lookup Request Creation/Deletion
     79  * @{
     80  */
     81 
     82 struct flnl_request *flnl_request_alloc(void)
     83 {
     84 	return REQUEST_CAST(nl_object_alloc(&request_obj_ops));
     85 }
     86 
     87 /** @} */
     88 
     89 /**
     90  * @name Attributes
     91  * @{
     92  */
     93 
     94 void flnl_request_set_fwmark(struct flnl_request *req, uint64_t fwmark)
     95 {
     96 	req->lr_fwmark = fwmark;
     97 	req->ce_mask |= REQUEST_ATTR_FWMARK;
     98 }
     99 
    100 uint64_t flnl_request_get_fwmark(struct flnl_request *req)
    101 {
    102 	if (req->ce_mask & REQUEST_ATTR_FWMARK)
    103 		return req->lr_fwmark;
    104 	else
    105 		return UINT_LEAST64_MAX;
    106 }
    107 
    108 void flnl_request_set_tos(struct flnl_request *req, int tos)
    109 {
    110 	req->lr_tos = tos;
    111 	req->ce_mask |= REQUEST_ATTR_TOS;
    112 }
    113 
    114 int flnl_request_get_tos(struct flnl_request *req)
    115 {
    116 	if (req->ce_mask & REQUEST_ATTR_TOS)
    117 		return req->lr_tos;
    118 	else
    119 		return -1;
    120 }
    121 
    122 void flnl_request_set_scope(struct flnl_request *req, int scope)
    123 {
    124 	req->lr_scope = scope;
    125 	req->ce_mask |= REQUEST_ATTR_SCOPE;
    126 }
    127 
    128 int flnl_request_get_scope(struct flnl_request *req)
    129 {
    130 	if (req->ce_mask & REQUEST_ATTR_SCOPE)
    131 		return req->lr_scope;
    132 	else
    133 		return -1;
    134 }
    135 
    136 void flnl_request_set_table(struct flnl_request *req, int table)
    137 {
    138 	req->lr_table = table;
    139 	req->ce_mask |= REQUEST_ATTR_TABLE;
    140 }
    141 
    142 int flnl_request_get_table(struct flnl_request *req)
    143 {
    144 	if (req->ce_mask & REQUEST_ATTR_TABLE)
    145 		return req->lr_table;
    146 	else
    147 		return -1;
    148 }
    149 
    150 int flnl_request_set_addr(struct flnl_request *req, struct nl_addr *addr)
    151 {
    152 	if (addr->a_family != AF_INET)
    153 		return -NLE_AF_NOSUPPORT;
    154 
    155 	if (req->lr_addr)
    156 		nl_addr_put(req->lr_addr);
    157 
    158 	nl_addr_get(addr);
    159 	req->lr_addr = addr;
    160 
    161 	req->ce_mask |= REQUEST_ATTR_ADDR;
    162 
    163 	return 0;
    164 }
    165 
    166 struct nl_addr *flnl_request_get_addr(struct flnl_request *req)
    167 {
    168 	if (req->ce_mask & REQUEST_ATTR_ADDR)
    169 		return req->lr_addr;
    170 	else
    171 		return NULL;
    172 }
    173 
    174 /** @} */
    175 
    176 static struct nl_object_ops request_obj_ops = {
    177 	.oo_name		= "fib_lookup/request",
    178 	.oo_size		= sizeof(struct flnl_request),
    179 	.oo_free_data		= request_free_data,
    180 	.oo_clone		= request_clone,
    181 	.oo_compare		= request_compare,
    182 	.oo_id_attrs		= ~0,
    183 };
    184 
    185 /** @} */
    186