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