aboutsummaryrefslogtreecommitdiffstats
path: root/package/libs/libnl-tiny/src/genl_family.c
blob: 88aaad9b772903e88124a164e43a2d4e4d4984b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * 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>

struct nl_object_ops genl_family_ops;
/** @endcond */

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_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);
}

/** @} */


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 -NLE_NOMEM;

	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_compare		= family_compare,
	.oo_id_attrs		= FAMILY_ATTR_ID,
};
/** @endcond */

/** @} */