Commit | Line | Data |
---|---|---|
f8bd9091 SF |
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 | ||
756462f3 RP |
26 | struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, const u8 *oui, |
27 | const u8 type) | |
f8bd9091 | 28 | { |
fc0ba8e8 | 29 | struct vic_provinfo *vp; |
f8bd9091 | 30 | |
29046f9b VK |
31 | if (!oui) |
32 | return NULL; | |
33 | ||
fc0ba8e8 DC |
34 | vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags); |
35 | if (!vp) | |
f8bd9091 SF |
36 | return NULL; |
37 | ||
38 | memcpy(vp->oui, oui, sizeof(vp->oui)); | |
39 | vp->type = type; | |
40 | vp->length = htonl(sizeof(vp->num_tlvs)); | |
41 | ||
42 | return vp; | |
43 | } | |
44 | ||
45 | void vic_provinfo_free(struct vic_provinfo *vp) | |
46 | { | |
47 | kfree(vp); | |
48 | } | |
49 | ||
50 | int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length, | |
756462f3 | 51 | const void *value) |
f8bd9091 SF |
52 | { |
53 | struct vic_provinfo_tlv *tlv; | |
54 | ||
55 | if (!vp || !value) | |
56 | return -EINVAL; | |
57 | ||
7c46835e RP |
58 | if (ntohl(vp->length) + offsetof(struct vic_provinfo_tlv, value) + |
59 | length > VIC_PROVINFO_MAX_TLV_DATA) | |
f8bd9091 SF |
60 | return -ENOMEM; |
61 | ||
62 | tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv + | |
63 | ntohl(vp->length) - sizeof(vp->num_tlvs)); | |
64 | ||
65 | tlv->type = htons(type); | |
66 | tlv->length = htons(length); | |
67 | memcpy(tlv->value, value, length); | |
68 | ||
69 | vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1); | |
7c46835e RP |
70 | vp->length = htonl(ntohl(vp->length) + |
71 | offsetof(struct vic_provinfo_tlv, value) + length); | |
f8bd9091 SF |
72 | |
73 | return 0; | |
74 | } | |
75 | ||
76 | size_t vic_provinfo_size(struct vic_provinfo *vp) | |
77 | { | |
78 | return vp ? ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0; | |
79 | } |