attr.c revision ed6b39cc7746fabdd0d01c96afcf60b9544913d3
1ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* 2ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Copyright (C) 2011 The Android Open Source Project 3ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 4ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Licensed under the Apache License, Version 2.0 (the "License"); 5ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * you may not use this file except in compliance with the License. 6ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * You may obtain a copy of the License at 7ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 8ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * http://www.apache.org/licenses/LICENSE-2.0 9ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * 10ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * Unless required by applicable law or agreed to in writing, software 11ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * distributed under the License is distributed on an "AS IS" BASIS, 12ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * See the License for the specific language governing permissions and 14ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * limitations under the License. 15ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker */ 16ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 17ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* NOTICE: This is a clean room re-implementation of libnl */ 18ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 19ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include <errno.h> 20ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include "netlink/netlink.h" 21ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include "netlink/msg.h" 22ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include "netlink/attr.h" 23ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker#include "netlink-types.h" 24ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 25ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return payload of string attribute. */ 26ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerchar *nla_get_string(struct nlattr *nla) 27ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 28ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return (char *) nla_data(nla); 29ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 30ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 31ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return payload of 16 bit integer attribute. */ 32ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makeruint16_t nla_get_u16(struct nlattr *nla) 33ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 34ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return *((uint16_t *) nla_data(nla)); 35ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 36ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 37ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return payload of 32 bit integer attribute. */ 38ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makeruint32_t nla_get_u32(struct nlattr *nla) 39ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 40ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return *((uint32_t *) nla_data(nla)); 41ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 42ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 43ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return value of 8 bit integer attribute. */ 44ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makeruint8_t nla_get_u8(struct nlattr *nla) 45ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 46ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return *((uint8_t *) nla_data(nla)); 47ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 48ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 49ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return payload of uint64_t attribute. */ 50ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makeruint64_t nla_get_u64(struct nlattr *nla) 51ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 52ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker uint64_t tmp; 53ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla_memcpy(&tmp, nla, sizeof(tmp)); 54ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return tmp; 55ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 56ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 57ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Head of payload */ 58ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makervoid *nla_data(const struct nlattr *nla) 59ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 60ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return (void *) ((char *) nla + NLA_HDRLEN); 61ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 62ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 63ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return length of the payload . */ 64ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_len(const struct nlattr *nla) 65ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 66ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return nla->nla_len - NLA_HDRLEN; 67ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 68ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 69ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Start a new level of nested attributes. */ 70ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) 71ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 72ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (!nla_put(msg, attrtype, 0, NULL)) { 73ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Get ref to last (nested start) attr */ 74ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int padding; 75ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *nla; 76ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 77ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker padding = nlmsg_padlen(nlmsg_datalen(nlmsg_hdr(msg))); 78ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla = (struct nlattr *) \ 79ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker ((char *) nlmsg_tail(msg->nm_nlh) - padding); 80ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return nla; 81ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 82ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker } else 83ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return NULL; 84ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 85ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 86ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 87ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Finalize nesting of attributes. */ 88ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_nest_end(struct nl_msg *msg, struct nlattr *start) 89ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 90ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker start->nla_len = (unsigned char *) \ 91ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nlmsg_tail(nlmsg_hdr(msg)) - (unsigned char *)start; 92ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 93ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 94ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 95ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return next attribute in a stream of attributes. */ 96ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nlattr *nla_next(const struct nlattr *nla, int *remaining) 97ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 98ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *next_nla = NULL; 99ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (nla->nla_len >= sizeof(struct nlattr) && 100ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len <= *remaining){ 101ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker next_nla = (struct nlattr *) \ 102ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker ((char *) nla + NLA_ALIGN(nla->nla_len)); 103ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker *remaining = *remaining - NLA_ALIGN(nla->nla_len); 104ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker } 105ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 106ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return next_nla; 107ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 108ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 109ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 110ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Check if the attribute header and payload can be accessed safely. */ 111ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_ok(const struct nlattr *nla, int remaining) 112ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 113ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return remaining > 0 && 114ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len >= sizeof(struct nlattr) && 115ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sizeof(struct nlattr) <= (unsigned int) remaining && 116ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len <= remaining; 117ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 118ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 119ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Create attribute index based on a stream of attributes. */ 120ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* NOTE: Policy not used ! */ 121ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 122ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int len, struct nla_policy *policy) 123ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 124ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *pos; 125ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int rem; 126ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 127ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* First clear table */ 128ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker memset(tb, 0, (maxtype+1) * sizeof(struct nlattr *)); 129ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 130ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla_for_each_attr(pos, head, len, rem) { 131ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker const int type = nla_type(pos); 132ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 133ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (type <= maxtype) 134ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker tb[type] = pos; 135ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 136ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker } 137ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 138ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 139ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 140ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 141ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 142ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Create attribute index based on nested attribute. */ 143ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_parse_nested(struct nlattr *tb[], int maxtype, 144ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *nla, struct nla_policy *policy) 145ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 146ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy); 147ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 148ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 149ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 150ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Add a unspecific attribute to netlink message. */ 151ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_put(struct nl_msg *msg, int attrtype, int datalen, const void *data) 152ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 153ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *nla; 154ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 155ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Reserve space and init nla header */ 156ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla = nla_reserve(msg, attrtype, datalen); 157ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (nla) 158ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker memcpy(nla_data(nla), data, datalen); 159ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 160ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return -errno; 161ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 162ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 163ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 164ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 165ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Add nested attributes to netlink message. */ 166ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Takes the attributes found in the nested message and appends them 167ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * to the message msg nested in a container of the type attrtype. The 168ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * nested message may not have a family specific header */ 169ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) 170ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 171ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int rc = -1; 172ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker const int NO_HEADER = 0; 173ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 174ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker rc = nla_put( 175ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker msg, 176ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker attrtype, 177ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nlmsg_attrlen(nlmsg_hdr(nested), NO_HEADER), 178ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker (const void *) nlmsg_attrdata(nlmsg_hdr(nested), NO_HEADER) 179ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker ); 180ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return rc; 181ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 182ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 183ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 184ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return type of the attribute. */ 185ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_type(const struct nlattr *nla) 186ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 187ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return (int) nla->nla_type; 188ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 189ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 190ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Reserves room for an attribute in specified netlink message and fills 191ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * in the attribute header (type,length). Return NULL if insufficient space */ 192ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nlattr *nla_reserve(struct nl_msg * msg, int attrtype, int data_len) 193ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 194ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 195ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *nla; 196ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker const unsigned int NEW_SIZE = \ 197ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker msg->nm_nlh->nlmsg_len + NLA_ALIGN(NLA_HDRLEN + data_len); 198ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 199ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Check enough space for attribute */ 200ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (NEW_SIZE <= msg->nm_size) { 201ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker const int fam_hdrlen = msg->nm_nlh->nlmsg_len - NLMSG_HDRLEN; 202ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker msg->nm_nlh->nlmsg_len = NEW_SIZE; 203ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla = nlmsg_attrdata(msg->nm_nlh, fam_hdrlen); 204ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_type = attrtype; 205ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len = NLA_HDRLEN + data_len; 206ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker } else 207ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker goto fail; 208ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 209ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return nla; 210ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerfail: 211ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return NULL; 212ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 213ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 214ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 215ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Copy attribute payload to another memory area. */ 216ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_memcpy(void *dest, struct nlattr *src, int count) 217ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 218ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int rc; 219ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker void *ret_dest = memcpy(dest, nla_data(src), count); 220ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (!ret_dest) 221ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return count; 222ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker else 223ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 224ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 225ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 226ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 227