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