144d362409d5469aed47d19e7908d19bd194493aThomas Graf/*
244d362409d5469aed47d19e7908d19bd194493aThomas Graf * lib/data.c		Abstract Data
344d362409d5469aed47d19e7908d19bd194493aThomas Graf *
444d362409d5469aed47d19e7908d19bd194493aThomas Graf *	This library is free software; you can redistribute it and/or
544d362409d5469aed47d19e7908d19bd194493aThomas Graf *	modify it under the terms of the GNU Lesser General Public
644d362409d5469aed47d19e7908d19bd194493aThomas Graf *	License as published by the Free Software Foundation version 2.1
744d362409d5469aed47d19e7908d19bd194493aThomas Graf *	of the License.
844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Copyright (c) 2003-2012 Thomas Graf <tgraf@suug.ch>
1044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
1144d362409d5469aed47d19e7908d19bd194493aThomas Graf
1244d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
13054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * @ingroup core_types
1444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @defgroup data Abstract Data
15054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
16054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Abstract data type representing a binary data blob.
17054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
18054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Related sections in the development guide:
19054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * - @core_doc{_abstract_data, Abstract Data}
20054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
2144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
22054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart *
23054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * Header
24054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * ------
25054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * ~~~~{.c}
26054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * #include <netlink/data.h>
27054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart * ~~~~
2844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
2944d362409d5469aed47d19e7908d19bd194493aThomas Graf
30054c80d775f2ae9b8f50260bdfcb821e99c0da2aPaul Stewart#include <netlink-private/netlink.h>
3144d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/netlink.h>
3244d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <netlink/utils.h>
3344d362409d5469aed47d19e7908d19bd194493aThomas Graf#include <linux/socket.h>
3444d362409d5469aed47d19e7908d19bd194493aThomas Graf
3544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
3644d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name General
3744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
3844d362409d5469aed47d19e7908d19bd194493aThomas Graf */
3944d362409d5469aed47d19e7908d19bd194493aThomas Graf
4044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
4144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocate a new abstract data object.
4244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf		Data buffer containing the actual data.
4344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg size		Size of data buffer.
4444d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4544d362409d5469aed47d19e7908d19bd194493aThomas Graf * Allocates a new abstract data and copies the specified data
4644d362409d5469aed47d19e7908d19bd194493aThomas Graf * buffer into the new handle.
4744d362409d5469aed47d19e7908d19bd194493aThomas Graf *
4844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Newly allocated data handle or NULL
4944d362409d5469aed47d19e7908d19bd194493aThomas Graf */
5044d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_data *nl_data_alloc(void *buf, size_t size)
5144d362409d5469aed47d19e7908d19bd194493aThomas Graf{
5244d362409d5469aed47d19e7908d19bd194493aThomas Graf	struct nl_data *data;
5344d362409d5469aed47d19e7908d19bd194493aThomas Graf
5444d362409d5469aed47d19e7908d19bd194493aThomas Graf	data = calloc(1, sizeof(*data));
5544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!data)
5644d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
5744d362409d5469aed47d19e7908d19bd194493aThomas Graf
5844d362409d5469aed47d19e7908d19bd194493aThomas Graf	data->d_data = calloc(1, size);
5944d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (!data->d_data) {
6044d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(data);
6144d362409d5469aed47d19e7908d19bd194493aThomas Graf		goto errout;
6244d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
6344d362409d5469aed47d19e7908d19bd194493aThomas Graf
6444d362409d5469aed47d19e7908d19bd194493aThomas Graf	data->d_size = size;
6544d362409d5469aed47d19e7908d19bd194493aThomas Graf
6644d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (buf)
6744d362409d5469aed47d19e7908d19bd194493aThomas Graf		memcpy(data->d_data, buf, size);
6844d362409d5469aed47d19e7908d19bd194493aThomas Graf
6944d362409d5469aed47d19e7908d19bd194493aThomas Graf	return data;
7044d362409d5469aed47d19e7908d19bd194493aThomas Graferrout:
7144d362409d5469aed47d19e7908d19bd194493aThomas Graf	return NULL;
7244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
7344d362409d5469aed47d19e7908d19bd194493aThomas Graf
7444d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
753607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * Allocate abstract data object based on netlink attribute.
763607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * @arg nla		Netlink attribute of unspecific type.
773607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf *
783607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * Allocates a new abstract data and copies the payload of the
793607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * attribute to the abstract data object.
803607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf *
813607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * @see nla_data_alloc
823607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf * @return Newly allocated data handle or NULL
833607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf */
84eed2afaab7aa72fae393a395a8879b91a922ff5eThomas Grafstruct nl_data *nl_data_alloc_attr(struct nlattr *nla)
853607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf{
863607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf	return nl_data_alloc(nla_data(nla), nla_len(nla));
873607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf}
883607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf
893607dbfa54e7ca775a89078f64bdcb150ea9306bThomas Graf/**
9044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Clone an abstract data object.
9144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg src		Abstract data object
9244d362409d5469aed47d19e7908d19bd194493aThomas Graf *
9344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Cloned object or NULL
9444d362409d5469aed47d19e7908d19bd194493aThomas Graf */
9544d362409d5469aed47d19e7908d19bd194493aThomas Grafstruct nl_data *nl_data_clone(struct nl_data *src)
9644d362409d5469aed47d19e7908d19bd194493aThomas Graf{
9744d362409d5469aed47d19e7908d19bd194493aThomas Graf	return nl_data_alloc(src->d_data, src->d_size);
9844d362409d5469aed47d19e7908d19bd194493aThomas Graf}
9944d362409d5469aed47d19e7908d19bd194493aThomas Graf
10044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
10144d362409d5469aed47d19e7908d19bd194493aThomas Graf * Append data to an abstract data object.
10244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg data		Abstract data object.
10344d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg buf		Data buffer containing the data to be appended.
10444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg size		Size of data to be apppended.
10544d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Reallocates an abstract data and copies the specified data
10744d362409d5469aed47d19e7908d19bd194493aThomas Graf * buffer into the new handle.
10844d362409d5469aed47d19e7908d19bd194493aThomas Graf *
10944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return 0 on success or a negative error code
11044d362409d5469aed47d19e7908d19bd194493aThomas Graf */
11144d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_data_append(struct nl_data *data, void *buf, size_t size)
11244d362409d5469aed47d19e7908d19bd194493aThomas Graf{
11344d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (size > 0) {
11444d362409d5469aed47d19e7908d19bd194493aThomas Graf		data->d_data = realloc(data->d_data, data->d_size + size);
11544d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (!data->d_data)
1168a3efffa5b3fde252675239914118664d36a2c24Thomas Graf			return -NLE_NOMEM;
11744d362409d5469aed47d19e7908d19bd194493aThomas Graf
11844d362409d5469aed47d19e7908d19bd194493aThomas Graf		if (buf)
11944d362409d5469aed47d19e7908d19bd194493aThomas Graf			memcpy(data->d_data + data->d_size, buf, size);
12044d362409d5469aed47d19e7908d19bd194493aThomas Graf		else
12144d362409d5469aed47d19e7908d19bd194493aThomas Graf			memset(data->d_data + data->d_size, 0, size);
12244d362409d5469aed47d19e7908d19bd194493aThomas Graf
12344d362409d5469aed47d19e7908d19bd194493aThomas Graf		data->d_size += size;
12444d362409d5469aed47d19e7908d19bd194493aThomas Graf	}
12544d362409d5469aed47d19e7908d19bd194493aThomas Graf
12644d362409d5469aed47d19e7908d19bd194493aThomas Graf	return 0;
12744d362409d5469aed47d19e7908d19bd194493aThomas Graf}
12844d362409d5469aed47d19e7908d19bd194493aThomas Graf
12944d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
13044d362409d5469aed47d19e7908d19bd194493aThomas Graf * Free an abstract data object.
13144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg data		Abstract data object.
13244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
13344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid nl_data_free(struct nl_data *data)
13444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
13544d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (data)
13644d362409d5469aed47d19e7908d19bd194493aThomas Graf		free(data->d_data);
13744d362409d5469aed47d19e7908d19bd194493aThomas Graf
13844d362409d5469aed47d19e7908d19bd194493aThomas Graf	free(data);
13944d362409d5469aed47d19e7908d19bd194493aThomas Graf}
14044d362409d5469aed47d19e7908d19bd194493aThomas Graf
14144d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
14244d362409d5469aed47d19e7908d19bd194493aThomas Graf
14344d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
14444d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Attribute Access
14544d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
14644d362409d5469aed47d19e7908d19bd194493aThomas Graf */
14744d362409d5469aed47d19e7908d19bd194493aThomas Graf
14844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
14944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get data buffer of abstract data object.
15044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg data		Abstract data object.
15144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Data buffer or NULL if empty.
15244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
15344d362409d5469aed47d19e7908d19bd194493aThomas Grafvoid *nl_data_get(struct nl_data *data)
15444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
15544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return data->d_size > 0 ? data->d_data : NULL;
15644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
15744d362409d5469aed47d19e7908d19bd194493aThomas Graf
15844d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
15944d362409d5469aed47d19e7908d19bd194493aThomas Graf * Get size of data buffer of abstract data object.
16044d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg data		Abstract data object.
16144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return Size of data buffer.
16244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
16344d362409d5469aed47d19e7908d19bd194493aThomas Grafsize_t nl_data_get_size(struct nl_data *data)
16444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
16544d362409d5469aed47d19e7908d19bd194493aThomas Graf	return data->d_size;
16644d362409d5469aed47d19e7908d19bd194493aThomas Graf}
16744d362409d5469aed47d19e7908d19bd194493aThomas Graf
16844d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
16944d362409d5469aed47d19e7908d19bd194493aThomas Graf
17044d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
17144d362409d5469aed47d19e7908d19bd194493aThomas Graf * @name Misc
17244d362409d5469aed47d19e7908d19bd194493aThomas Graf * @{
17344d362409d5469aed47d19e7908d19bd194493aThomas Graf */
17444d362409d5469aed47d19e7908d19bd194493aThomas Graf
17544d362409d5469aed47d19e7908d19bd194493aThomas Graf/**
17644d362409d5469aed47d19e7908d19bd194493aThomas Graf * Compare two abstract data objects.
17744d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg a		Abstract data object.
17844d362409d5469aed47d19e7908d19bd194493aThomas Graf * @arg b		Another abstract data object.
17944d362409d5469aed47d19e7908d19bd194493aThomas Graf * @return An integer less than, equal to, or greater than zero if
18044d362409d5469aed47d19e7908d19bd194493aThomas Graf *         a is found, respectively, to be less than, to match, or
18144d362409d5469aed47d19e7908d19bd194493aThomas Graf *         be greater than b.
18244d362409d5469aed47d19e7908d19bd194493aThomas Graf */
18344d362409d5469aed47d19e7908d19bd194493aThomas Grafint nl_data_cmp(struct nl_data *a, struct nl_data *b)
18444d362409d5469aed47d19e7908d19bd194493aThomas Graf{
18544d362409d5469aed47d19e7908d19bd194493aThomas Graf	void *a_ = nl_data_get(a);
18644d362409d5469aed47d19e7908d19bd194493aThomas Graf	void *b_ = nl_data_get(b);
18744d362409d5469aed47d19e7908d19bd194493aThomas Graf
18844d362409d5469aed47d19e7908d19bd194493aThomas Graf	if (a_ && b_)
18944d362409d5469aed47d19e7908d19bd194493aThomas Graf		return memcmp(a_, b_, nl_data_get_size(a));
19044d362409d5469aed47d19e7908d19bd194493aThomas Graf	else
19144d362409d5469aed47d19e7908d19bd194493aThomas Graf		return -1;
19244d362409d5469aed47d19e7908d19bd194493aThomas Graf}
19344d362409d5469aed47d19e7908d19bd194493aThomas Graf
19444d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
19544d362409d5469aed47d19e7908d19bd194493aThomas Graf/** @} */
196