attr.c revision 64f17e85b4783b1a34f6d46dd8aed2745ed0c583
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 6964f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidtint nla_padlen(int payload) 7064f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt{ 7164f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt return NLA_ALIGN(payload) - payload; 7264f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt} 7364f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt 74ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Start a new level of nested attributes. */ 75ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nlattr *nla_nest_start(struct nl_msg *msg, int attrtype) 76ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 7764f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt struct nlattr *start = (struct nlattr *)nlmsg_tail(msg->nm_nlh); 7864f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt int rc; 79ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 8064f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt rc = nla_put(msg, attrtype, 0, NULL); 8164f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt if (rc < 0) 82ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return NULL; 83ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 8464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt return start; 85ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 86ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 87ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Finalize nesting of attributes. */ 88ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_nest_end(struct nl_msg *msg, struct nlattr *start) 89ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 9064f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt /* Set attribute size */ 9164f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt start->nla_len = (unsigned char *)nlmsg_tail(nlmsg_hdr(msg)) - 9264f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt (unsigned char *)start; 93ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 94ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 95ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 96ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return next attribute in a stream of attributes. */ 97ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerstruct nlattr *nla_next(const struct nlattr *nla, int *remaining) 98ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 99ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *next_nla = NULL; 100ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker if (nla->nla_len >= sizeof(struct nlattr) && 101ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len <= *remaining){ 102ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker next_nla = (struct nlattr *) \ 103ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker ((char *) nla + NLA_ALIGN(nla->nla_len)); 104ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker *remaining = *remaining - NLA_ALIGN(nla->nla_len); 105ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker } 106ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 107ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return next_nla; 108ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 109ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 110ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 111ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Check if the attribute header and payload can be accessed safely. */ 112ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_ok(const struct nlattr *nla, int remaining) 113ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 114ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return remaining > 0 && 115ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len >= sizeof(struct nlattr) && 116ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker sizeof(struct nlattr) <= (unsigned int) remaining && 117ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla->nla_len <= remaining; 118ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 119ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 120ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Create attribute index based on a stream of attributes. */ 121ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* NOTE: Policy not used ! */ 122ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_parse(struct nlattr *tb[], int maxtype, struct nlattr *head, 123ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int len, struct nla_policy *policy) 124ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 125ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *pos; 126ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker int rem; 127ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 128ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* First clear table */ 12964f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt memset(tb, 0, (maxtype + 1) * sizeof(struct nlattr *)); 130ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 131ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker nla_for_each_attr(pos, head, len, rem) { 13264f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt int type = nla_type(pos); 133ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 13464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt if ((type <= maxtype) && (type != 0)) 135ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker tb[type] = pos; 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); 1571b53483949c0ff11ef78bcf67196f0ef4db0aeb4Frank Maker if (nla) { 158ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker memcpy(nla_data(nla), data, datalen); 1591b53483949c0ff11ef78bcf67196f0ef4db0aeb4Frank Maker return 0; 1601b53483949c0ff11ef78bcf67196f0ef4db0aeb4Frank Maker } 161ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 1621b53483949c0ff11ef78bcf67196f0ef4db0aeb4Frank Maker return -EINVAL; 163ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 164ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 165ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 166ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 167ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Add nested attributes to netlink message. */ 168ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Takes the attributes found in the nested message and appends them 169ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * to the message msg nested in a container of the type attrtype. The 170ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * nested message may not have a family specific header */ 171ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_put_nested(struct nl_msg *msg, int attrtype, struct nl_msg *nested) 172ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 17364f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt int rc; 174ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 17564f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt rc = nla_put(msg, attrtype, nlmsg_attrlen(nlmsg_hdr(nested), 0), 17664f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt nlmsg_attrdata(nlmsg_hdr(nested), 0)); 177ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return rc; 178ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 179ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 180ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 181ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Return type of the attribute. */ 182ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_type(const struct nlattr *nla) 183ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 18464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt return (int)nla->nla_type & NLA_TYPE_MASK; 185ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 186ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 187ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Reserves room for an attribute in specified netlink message and fills 188ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker * in the attribute header (type,length). Return NULL if insufficient space */ 18964f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidtstruct nlattr *nla_reserve(struct nl_msg *msg, int attrtype, int data_len) 190ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 191ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 192ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker struct nlattr *nla; 19364f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt const unsigned int NEW_SIZE = NLMSG_ALIGN(msg->nm_nlh->nlmsg_len) + 19464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt NLA_ALIGN(NLA_HDRLEN + data_len); 195ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 196ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker /* Check enough space for attribute */ 19764f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt if (NEW_SIZE > msg->nm_size) 19864f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt return NULL; 199ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 20064f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt nla = (struct nlattr *)nlmsg_tail(msg->nm_nlh); 20164f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt nla->nla_type = attrtype; 20264f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt nla->nla_len = NLA_HDRLEN + data_len; 20364f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(data_len)); 20464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt msg->nm_nlh->nlmsg_len = NEW_SIZE; 205ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return nla; 206ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 207ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker 208ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker/* Copy attribute payload to another memory area. */ 209ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Makerint nla_memcpy(void *dest, struct nlattr *src, int count) 210ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker{ 21164f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt if (!src || !dest) 212ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker return 0; 21364f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt if (count > nla_len(src)) 21464f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt count = nla_len(src); 21564f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt memcpy(dest, nla_data(src), count); 21664f17e85b4783b1a34f6d46dd8aed2745ed0c583Dmitry Shmidt return count; 217ed6b39cc7746fabdd0d01c96afcf60b9544913d3Frank Maker} 218