1a6a5580cSJeff Kirsher /* 2a6a5580cSJeff Kirsher * Copyright 2010 Cisco Systems, Inc. All rights reserved. 3a6a5580cSJeff Kirsher * 4a6a5580cSJeff Kirsher * This program is free software; you may redistribute it and/or modify 5a6a5580cSJeff Kirsher * it under the terms of the GNU General Public License as published by 6a6a5580cSJeff Kirsher * the Free Software Foundation; version 2 of the License. 7a6a5580cSJeff Kirsher * 8a6a5580cSJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 9a6a5580cSJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 10a6a5580cSJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 11a6a5580cSJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 12a6a5580cSJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 13a6a5580cSJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14a6a5580cSJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 15a6a5580cSJeff Kirsher * SOFTWARE. 16a6a5580cSJeff Kirsher * 17a6a5580cSJeff Kirsher */ 18a6a5580cSJeff Kirsher 19a6a5580cSJeff Kirsher #include <linux/kernel.h> 20a6a5580cSJeff Kirsher #include <linux/errno.h> 21a6a5580cSJeff Kirsher #include <linux/types.h> 22a6a5580cSJeff Kirsher #include <linux/slab.h> 23a6a5580cSJeff Kirsher 24a6a5580cSJeff Kirsher #include "vnic_vic.h" 25a6a5580cSJeff Kirsher 26a6a5580cSJeff Kirsher struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui, 27a6a5580cSJeff Kirsher const u8 type) 28a6a5580cSJeff Kirsher { 29a6a5580cSJeff Kirsher struct vic_provinfo *vp; 30a6a5580cSJeff Kirsher 31a6a5580cSJeff Kirsher if (!oui) 32a6a5580cSJeff Kirsher return NULL; 33a6a5580cSJeff Kirsher 34a6a5580cSJeff Kirsher vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags); 35a6a5580cSJeff Kirsher if (!vp) 36a6a5580cSJeff Kirsher return NULL; 37a6a5580cSJeff Kirsher 38a6a5580cSJeff Kirsher memcpy(vp->oui, oui, sizeof(vp->oui)); 39a6a5580cSJeff Kirsher vp->type = type; 40a6a5580cSJeff Kirsher vp->length = htonl(sizeof(vp->num_tlvs)); 41a6a5580cSJeff Kirsher 42a6a5580cSJeff Kirsher return vp; 43a6a5580cSJeff Kirsher } 44a6a5580cSJeff Kirsher 45a6a5580cSJeff Kirsher void vic_provinfo_free(struct vic_provinfo *vp) 46a6a5580cSJeff Kirsher { 47a6a5580cSJeff Kirsher kfree(vp); 48a6a5580cSJeff Kirsher } 49a6a5580cSJeff Kirsher 50a6a5580cSJeff Kirsher int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, 51a6a5580cSJeff Kirsher const void *value) 52a6a5580cSJeff Kirsher { 53a6a5580cSJeff Kirsher struct vic_provinfo_tlv *tlv; 54a6a5580cSJeff Kirsher 55a6a5580cSJeff Kirsher if (!vp || !value) 56a6a5580cSJeff Kirsher return -EINVAL; 57a6a5580cSJeff Kirsher 58a6a5580cSJeff Kirsher if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) + 59a6a5580cSJeff Kirsher length > VIC_PROVINFO_MAX_TLV_DATA) 60a6a5580cSJeff Kirsher return -ENOMEM; 61a6a5580cSJeff Kirsher 62a6a5580cSJeff Kirsher tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv + 63a6a5580cSJeff Kirsher ntohl(vp->length) - sizeof(vp->num_tlvs)); 64a6a5580cSJeff Kirsher 65a6a5580cSJeff Kirsher tlv->type = htons(type); 66a6a5580cSJeff Kirsher tlv->length = htons(length); 67a6a5580cSJeff Kirsher memcpy(tlv->value, value, length); 68a6a5580cSJeff Kirsher 69a6a5580cSJeff Kirsher vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1); 70a6a5580cSJeff Kirsher vp->length = htonl(ntohl(vp->length) + 71a6a5580cSJeff Kirsher offsetof(struct vic_provinfo_tlv, value) + length); 72a6a5580cSJeff Kirsher 73a6a5580cSJeff Kirsher return 0; 74a6a5580cSJeff Kirsher } 75a6a5580cSJeff Kirsher 76a6a5580cSJeff Kirsher size_t vic_provinfo_size(struct vic_provinfo *vp) 77a6a5580cSJeff Kirsher { 78a6a5580cSJeff Kirsher return vp ? ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0; 79a6a5580cSJeff Kirsher } 80