| File: | .build-ci/../libnvme/src/nvme/nbft.c |
| Warning: | line 770, column 13 Value of 'errno' was not checked and may be overwritten by function 'malloc' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | // SPDX-License-Identifier: LGPL-2.1-or-later | |||
| 2 | /* | |||
| 3 | * This file is part of libnvme. | |||
| 4 | * Copyright (c) 2021-2022, Dell Inc. or its subsidiaries. All Rights Reserved. | |||
| 5 | * | |||
| 6 | * Authors: Stuart Hayes <Stuart_Hayes@Dell.com> | |||
| 7 | * | |||
| 8 | */ | |||
| 9 | ||||
| 10 | #include <stdio.h> | |||
| 11 | #include <stdlib.h> | |||
| 12 | ||||
| 13 | #include <arpa/inet.h> | |||
| 14 | ||||
| 15 | #include <ccan/endian/endian.h> | |||
| 16 | ||||
| 17 | #include <libnvme.h> | |||
| 18 | ||||
| 19 | #include "private.h" | |||
| 20 | #include "compiler-attributes.h" | |||
| 21 | ||||
| 22 | static __u8 csum(const __u8 *buffer, ssize_t length) | |||
| 23 | { | |||
| 24 | int n; | |||
| 25 | __u8 sum = 0; | |||
| 26 | ||||
| 27 | for (n = 0; n < length; n++) | |||
| 28 | sum = (__u8)(sum + ((__u8 *)buffer)[n]); | |||
| 29 | return sum; | |||
| 30 | } | |||
| 31 | ||||
| 32 | static void format_ip_addr(char *buf, size_t buflen, __u8 *addr) | |||
| 33 | { | |||
| 34 | struct in6_addr addr_ipv6; | |||
| 35 | ||||
| 36 | memcpy(&addr_ipv6, addr, sizeof(addr_ipv6)); | |||
| 37 | if (IN6_IS_ADDR_V4MAPPED(&addr_ipv6)(__extension__ ({ const struct in6_addr *__a = (const struct in6_addr *) (&addr_ipv6); __a->__in6_u.__u6_addr32[0] == 0 && __a->__in6_u.__u6_addr32[1] == 0 && __a->__in6_u .__u6_addr32[2] == __bswap_32 (0xffff); }))) | |||
| 38 | /* ipv4 */ | |||
| 39 | inet_ntop(AF_INET2, &addr_ipv6.s6_addr32__in6_u.__u6_addr32[3], buf, buflen); | |||
| 40 | else | |||
| 41 | /* ipv6 */ | |||
| 42 | inet_ntop(AF_INET610, &addr_ipv6, buf, buflen); | |||
| 43 | } | |||
| 44 | ||||
| 45 | static bool_Bool in_heap(struct nbft_header *header, struct nbft_heap_obj obj) | |||
| 46 | { | |||
| 47 | if (le16_to_cpu(obj.length) == 0) | |||
| 48 | return true1; | |||
| 49 | if (le32_to_cpu(obj.offset) < le32_to_cpu(header->heap_offset)) | |||
| 50 | return false0; | |||
| 51 | if (le32_to_cpu(obj.offset) > | |||
| 52 | le32_to_cpu(header->heap_offset) + le32_to_cpu(header->heap_length)) | |||
| 53 | return false0; | |||
| 54 | if (le32_to_cpu(obj.offset) + le16_to_cpu(obj.length) > | |||
| 55 | le32_to_cpu(header->heap_offset) + le32_to_cpu(header->heap_length)) | |||
| 56 | return false0; | |||
| 57 | return true1; | |||
| 58 | } | |||
| 59 | ||||
| 60 | /* | |||
| 61 | * Return transport_type string (NBFT Table 2) | |||
| 62 | */ | |||
| 63 | static char *trtype_to_string(__u8 transport_type) | |||
| 64 | { | |||
| 65 | switch (transport_type) { | |||
| 66 | case 3: | |||
| 67 | return "tcp"; | |||
| 68 | default: | |||
| 69 | return "invalid"; | |||
| 70 | } | |||
| 71 | } | |||
| 72 | ||||
| 73 | #define verify(ctx, condition, message)do { if (!(condition)) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG , ((void*)0), "file %s: " message "\n", nbft->filename); return -22; } } while (0) \ | |||
| 74 | do { \ | |||
| 75 | if (!(condition)) { \ | |||
| 76 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG, "file %s: " message "\n", \__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " message "\n", nbft->filename) | |||
| 77 | nbft->filename)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " message "\n", nbft->filename); \ | |||
| 78 | return -EINVAL22; \ | |||
| 79 | } \ | |||
| 80 | } while (0) | |||
| 81 | ||||
| 82 | static int __get_heap_obj(struct libnvme_global_ctx *ctx, | |||
| 83 | struct nbft_header *header, const char *filename, | |||
| 84 | const char *descriptorname, const char *fieldname, | |||
| 85 | struct nbft_heap_obj obj, bool_Bool is_string, | |||
| 86 | char **output) | |||
| 87 | { | |||
| 88 | if (le16_to_cpu(obj.length) == 0) | |||
| 89 | return -ENOENT2; | |||
| 90 | ||||
| 91 | if (!in_heap(header, obj)) { | |||
| 92 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: field '%s' in descriptor '%s' has invalid offset or length\n" , filename, fieldname, descriptorname) | |||
| 93 | "file %s: field '%s' in descriptor '%s' has invalid offset or length\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: field '%s' in descriptor '%s' has invalid offset or length\n" , filename, fieldname, descriptorname) | |||
| 94 | filename, fieldname, descriptorname)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: field '%s' in descriptor '%s' has invalid offset or length\n" , filename, fieldname, descriptorname); | |||
| 95 | return -EINVAL22; | |||
| 96 | } | |||
| 97 | ||||
| 98 | /* check that string is zero terminated correctly */ | |||
| 99 | *output = (char *)header + le32_to_cpu(obj.offset); | |||
| 100 | ||||
| 101 | if (is_string) { | |||
| 102 | if (strnlen(*output, le16_to_cpu(obj.length) + 1) < | |||
| 103 | le16_to_cpu(obj.length)) { | |||
| 104 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n" , filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu (obj.length) + 1), le16_to_cpu(obj.length)) | |||
| 105 | "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n" , filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu (obj.length) + 1), le16_to_cpu(obj.length)) | |||
| 106 | filename, fieldname, descriptorname,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n" , filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu (obj.length) + 1), le16_to_cpu(obj.length)) | |||
| 107 | strnlen(*output, le16_to_cpu(obj.length) + 1),__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n" , filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu (obj.length) + 1), le16_to_cpu(obj.length)) | |||
| 108 | le16_to_cpu(obj.length))__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is shorter (%zd) than specified length (%d)\n" , filename, fieldname, descriptorname, strnlen(*output, le16_to_cpu (obj.length) + 1), le16_to_cpu(obj.length)); | |||
| 109 | } else if (strnlen(*output, le16_to_cpu(obj.length) + 1) > | |||
| 110 | le16_to_cpu(obj.length)) { | |||
| 111 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is not zero terminated\n" , filename, fieldname, descriptorname) | |||
| 112 | "file %s: string '%s' in descriptor '%s' is not zero terminated\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is not zero terminated\n" , filename, fieldname, descriptorname) | |||
| 113 | filename, fieldname, descriptorname)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: string '%s' in descriptor '%s' is not zero terminated\n" , filename, fieldname, descriptorname); | |||
| 114 | return -EINVAL22; | |||
| 115 | } | |||
| 116 | } | |||
| 117 | ||||
| 118 | return 0; | |||
| 119 | } | |||
| 120 | ||||
| 121 | #define get_heap_obj(ctx, descriptor, obj, is_string, output)__get_heap_obj(ctx, header, nbft->filename, "descriptor", "obj" , descriptor->obj, is_string, output) \ | |||
| 122 | __get_heap_obj(ctx, header, nbft->filename, \ | |||
| 123 | stringify(descriptor)"descriptor", stringify(obj)"obj", \ | |||
| 124 | descriptor->obj, is_string, \ | |||
| 125 | output) | |||
| 126 | ||||
| 127 | static struct libnbft_discovery *discovery_from_index(struct libnbft_info *nbft, | |||
| 128 | int i) | |||
| 129 | { | |||
| 130 | struct libnbft_discovery **d; | |||
| 131 | ||||
| 132 | for (d = nbft->discovery_list; d && *d; d++) { | |||
| 133 | if ((*d)->index == i) | |||
| 134 | return *d; | |||
| 135 | } | |||
| 136 | return NULL((void*)0); | |||
| 137 | } | |||
| 138 | ||||
| 139 | static struct libnbft_hfi *hfi_from_index(struct libnbft_info *nbft, int i) | |||
| 140 | { | |||
| 141 | struct libnbft_hfi **h; | |||
| 142 | ||||
| 143 | for (h = nbft->hfi_list; h && *h; h++) { | |||
| 144 | if ((*h)->index == i) | |||
| 145 | return *h; | |||
| 146 | } | |||
| 147 | return NULL((void*)0); | |||
| 148 | } | |||
| 149 | ||||
| 150 | static struct libnbft_security *security_from_index(struct libnbft_info *nbft, | |||
| 151 | int i) | |||
| 152 | { | |||
| 153 | struct libnbft_security **s; | |||
| 154 | ||||
| 155 | for (s = nbft->security_list; s && *s; s++) { | |||
| 156 | if ((*s)->index == i) | |||
| 157 | return *s; | |||
| 158 | } | |||
| 159 | return NULL((void*)0); | |||
| 160 | } | |||
| 161 | ||||
| 162 | static int read_ssns_exended_info(struct libnvme_global_ctx *ctx, | |||
| 163 | struct libnbft_info *nbft, struct libnbft_subsystem_ns *ssns, | |||
| 164 | struct nbft_ssns_ext_info *raw_ssns_ei) | |||
| 165 | { | |||
| 166 | struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; | |||
| 167 | ||||
| 168 | verify(ctx, raw_ssns_ei->structure_id == NBFT_DESC_SSNS_EXT_INFO,do { if (!(raw_ssns_ei->structure_id == NBFT_DESC_SSNS_EXT_INFO )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in SSNS extended info descriptor" "\n", nbft-> filename); return -22; } } while (0) | |||
| 169 | "invalid ID in SSNS extended info descriptor")do { if (!(raw_ssns_ei->structure_id == NBFT_DESC_SSNS_EXT_INFO )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in SSNS extended info descriptor" "\n", nbft-> filename); return -22; } } while (0); | |||
| 170 | verify(ctx, raw_ssns_ei->version == 1,do { if (!(raw_ssns_ei->version == 1)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid version in SSNS extended info descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 171 | "invalid version in SSNS extended info descriptor")do { if (!(raw_ssns_ei->version == 1)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid version in SSNS extended info descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 172 | verify(ctx, le16_to_cpu(raw_ssns_ei->ssns_index) == ssns->index,do { if (!(le16_to_cpu(raw_ssns_ei->ssns_index) == ssns-> index)) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "SSNS index doesn't match extended info descriptor index" "\n" , nbft->filename); return -22; } } while (0) | |||
| 173 | "SSNS index doesn't match extended info descriptor index")do { if (!(le16_to_cpu(raw_ssns_ei->ssns_index) == ssns-> index)) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "SSNS index doesn't match extended info descriptor index" "\n" , nbft->filename); return -22; } } while (0); | |||
| 174 | ||||
| 175 | if (!(le32_to_cpu(raw_ssns_ei->flags) & NBFT_SSNS_EXT_INFO_VALID)) | |||
| 176 | return -EINVAL22; | |||
| 177 | ||||
| 178 | if (le32_to_cpu(raw_ssns_ei->flags) & NBFT_SSNS_EXT_INFO_ADMIN_ASQSZ) | |||
| 179 | ssns->asqsz = le16_to_cpu(raw_ssns_ei->asqsz); | |||
| 180 | ssns->controller_id = le16_to_cpu(raw_ssns_ei->cntlid); | |||
| 181 | get_heap_obj(ctx, raw_ssns_ei, dhcp_root_path_str_obj, 1,__get_heap_obj(ctx, header, nbft->filename, "raw_ssns_ei", "dhcp_root_path_str_obj", raw_ssns_ei->dhcp_root_path_str_obj , 1, &ssns->dhcp_root_path_string) | |||
| 182 | &ssns->dhcp_root_path_string)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns_ei", "dhcp_root_path_str_obj", raw_ssns_ei->dhcp_root_path_str_obj , 1, &ssns->dhcp_root_path_string); | |||
| 183 | ||||
| 184 | return 0; | |||
| 185 | } | |||
| 186 | ||||
| 187 | static int read_ssns(struct libnvme_global_ctx *ctx, | |||
| 188 | struct libnbft_info *nbft, struct nbft_ssns *raw_ssns, | |||
| 189 | struct libnbft_subsystem_ns **s) | |||
| 190 | { | |||
| 191 | struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; | |||
| 192 | struct libnbft_subsystem_ns *ssns; | |||
| 193 | __u8 *ss_hfi_indexes = NULL((void*)0); | |||
| 194 | __u8 *tmp = NULL((void*)0); | |||
| 195 | int i, ret; | |||
| 196 | ||||
| 197 | if (!(le16_to_cpu(raw_ssns->flags) & NBFT_SSNS_VALID)) | |||
| 198 | return -EINVAL22; | |||
| 199 | ||||
| 200 | verify(ctx, raw_ssns->structure_id == NBFT_DESC_SSNS,do { if (!(raw_ssns->structure_id == NBFT_DESC_SSNS)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in SSNS descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 201 | "invalid ID in SSNS descriptor")do { if (!(raw_ssns->structure_id == NBFT_DESC_SSNS)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in SSNS descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 202 | ||||
| 203 | /* verify transport type */ | |||
| 204 | verify(ctx, raw_ssns->trtype == NBFT_TRTYPE_TCP,do { if (!(raw_ssns->trtype == NBFT_TRTYPE_TCP)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid transport type in SSNS descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 205 | "invalid transport type in SSNS descriptor")do { if (!(raw_ssns->trtype == NBFT_TRTYPE_TCP)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid transport type in SSNS descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 206 | ||||
| 207 | ssns = calloc(1, sizeof(*ssns)); | |||
| 208 | if (!ssns) | |||
| 209 | return -ENOMEM12; | |||
| 210 | ||||
| 211 | ssns->index = le16_to_cpu(raw_ssns->index); | |||
| 212 | strncpy(ssns->transport, trtype_to_string(raw_ssns->trtype), | |||
| 213 | sizeof(ssns->transport)); | |||
| 214 | ||||
| 215 | /* transport specific flags */ | |||
| 216 | if (raw_ssns->trtype == NBFT_TRTYPE_TCP) { | |||
| 217 | if (le16_to_cpu(raw_ssns->trflags) & | |||
| 218 | NBFT_SSNS_PDU_HEADER_DIGEST) | |||
| 219 | ssns->pdu_header_digest_required = true1; | |||
| 220 | if (le16_to_cpu(raw_ssns->trflags) & | |||
| 221 | NBFT_SSNS_DATA_DIGEST) | |||
| 222 | ssns->data_digest_required = true1; | |||
| 223 | } | |||
| 224 | ||||
| 225 | /* primary discovery controller */ | |||
| 226 | if (raw_ssns->primary_discovery_ctrl_index) { | |||
| 227 | ssns->discovery = discovery_from_index(nbft, | |||
| 228 | raw_ssns->primary_discovery_ctrl_index); | |||
| 229 | if (!ssns->discovery) | |||
| 230 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d discovery controller not found\n" , nbft->filename, ssns->index) | |||
| 231 | "file %s: namespace %d discovery controller not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d discovery controller not found\n" , nbft->filename, ssns->index) | |||
| 232 | nbft->filename, ssns->index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d discovery controller not found\n" , nbft->filename, ssns->index); | |||
| 233 | } | |||
| 234 | ||||
| 235 | /* subsystem transport address */ | |||
| 236 | ret = get_heap_obj(ctx, raw_ssns, subsys_traddr_obj, 0, (char **)&tmp)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "subsys_traddr_obj" , raw_ssns->subsys_traddr_obj, 0, (char **)&tmp); | |||
| 237 | if (ret) | |||
| 238 | goto fail; | |||
| 239 | ||||
| 240 | format_ip_addr(ssns->traddr, sizeof(ssns->traddr), tmp); | |||
| 241 | ||||
| 242 | /* subsystem transport service identifier */ | |||
| 243 | ret = get_heap_obj(ctx, raw_ssns, subsys_trsvcid_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "subsys_trsvcid_obj" , raw_ssns->subsys_trsvcid_obj, 1, &ssns->trsvcid) | |||
| 244 | 1, &ssns->trsvcid)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "subsys_trsvcid_obj" , raw_ssns->subsys_trsvcid_obj, 1, &ssns->trsvcid); | |||
| 245 | if (ret) | |||
| 246 | goto fail; | |||
| 247 | ||||
| 248 | /* subsystem port ID */ | |||
| 249 | ssns->subsys_port_id = le16_to_cpu(raw_ssns->subsys_port_id); | |||
| 250 | ||||
| 251 | /* NSID, NID type, & NID */ | |||
| 252 | ssns->nsid = le32_to_cpu(raw_ssns->nsid); | |||
| 253 | ssns->nid_type = raw_ssns->nidt; | |||
| 254 | ssns->nid = raw_ssns->nid; | |||
| 255 | ||||
| 256 | /* flags */ | |||
| 257 | ssns->unavailable = !!(le16_to_cpu(raw_ssns->flags) & | |||
| 258 | NBFT_SSNS_UNAVAIL_NAMESPACE_UNAVAIL); | |||
| 259 | ssns->discovered = !!(le16_to_cpu(raw_ssns->flags) & | |||
| 260 | NBFT_SSNS_DISCOVERED_NAMESPACE); | |||
| 261 | ||||
| 262 | /* security profile */ | |||
| 263 | if (raw_ssns->security_desc_index) { | |||
| 264 | ssns->security = security_from_index(nbft, | |||
| 265 | raw_ssns->security_desc_index); | |||
| 266 | if (!ssns->security) | |||
| 267 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d security controller not found\n" , nbft->filename, ssns->index) | |||
| 268 | "file %s: namespace %d security controller not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d security controller not found\n" , nbft->filename, ssns->index) | |||
| 269 | nbft->filename, ssns->index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: namespace %d security controller not found\n" , nbft->filename, ssns->index); | |||
| 270 | } | |||
| 271 | ||||
| 272 | /* HFI descriptors */ | |||
| 273 | ret = get_heap_obj(ctx, raw_ssns, secondary_hfi_assoc_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "secondary_hfi_assoc_obj" , raw_ssns->secondary_hfi_assoc_obj, 0, (char **)&ss_hfi_indexes ) | |||
| 274 | 0, (char **)&ss_hfi_indexes)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "secondary_hfi_assoc_obj" , raw_ssns->secondary_hfi_assoc_obj, 0, (char **)&ss_hfi_indexes ); | |||
| 275 | if (ret) | |||
| 276 | goto fail; | |||
| 277 | ||||
| 278 | ssns->hfis = | |||
| 279 | calloc(le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length) + | |||
| 280 | 2, sizeof(*ssns->hfis)); | |||
| 281 | if (!ssns->hfis) { | |||
| 282 | ret = -ENOMEM12; | |||
| 283 | goto fail; | |||
| 284 | } | |||
| 285 | ssns->hfis[0] = hfi_from_index(nbft, raw_ssns->primary_hfi_desc_index); | |||
| 286 | if (!ssns->hfis[0]) { | |||
| 287 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d: HFI %d not found\n" , nbft->filename, ssns->index, raw_ssns->primary_hfi_desc_index ) | |||
| 288 | "file %s: SSNS %d: HFI %d not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d: HFI %d not found\n" , nbft->filename, ssns->index, raw_ssns->primary_hfi_desc_index ) | |||
| 289 | nbft->filename, ssns->index,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d: HFI %d not found\n" , nbft->filename, ssns->index, raw_ssns->primary_hfi_desc_index ) | |||
| 290 | raw_ssns->primary_hfi_desc_index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d: HFI %d not found\n" , nbft->filename, ssns->index, raw_ssns->primary_hfi_desc_index ); | |||
| 291 | ret = -EINVAL22; | |||
| 292 | goto fail; | |||
| 293 | } | |||
| 294 | ssns->num_hfis = 1; | |||
| 295 | for (i = 0; i < le16_to_cpu(raw_ssns->secondary_hfi_assoc_obj.length); | |||
| 296 | i++) { | |||
| 297 | bool_Bool duplicate = false0; | |||
| 298 | int j; | |||
| 299 | ||||
| 300 | for (j = 0; j < i; j++) { | |||
| 301 | if (ss_hfi_indexes[i] == ss_hfi_indexes[j]) { | |||
| 302 | duplicate = true1; | |||
| 303 | break; | |||
| 304 | } | |||
| 305 | } | |||
| 306 | ||||
| 307 | if (!duplicate && | |||
| 308 | ss_hfi_indexes[i] == raw_ssns->primary_hfi_desc_index) | |||
| 309 | duplicate = true1; | |||
| 310 | ||||
| 311 | if (duplicate) { | |||
| 312 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d skipping duplicate HFI index %d\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]) | |||
| 313 | "file %s: SSNS %d skipping duplicate HFI index %d\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d skipping duplicate HFI index %d\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]) | |||
| 314 | nbft->filename, ssns->index, ss_hfi_indexes[i])__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d skipping duplicate HFI index %d\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]); | |||
| 315 | continue; | |||
| 316 | } | |||
| 317 | ||||
| 318 | ssns->hfis[i + 1] = hfi_from_index(nbft, ss_hfi_indexes[i]); | |||
| 319 | if (ss_hfi_indexes[i] && !ssns->hfis[i + 1]) | |||
| 320 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d HFI %d not found\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]) | |||
| 321 | "file %s: SSNS %d HFI %d not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d HFI %d not found\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]) | |||
| 322 | nbft->filename, ssns->index, ss_hfi_indexes[i])__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: SSNS %d HFI %d not found\n" , nbft->filename, ssns->index, ss_hfi_indexes[i]); | |||
| 323 | else | |||
| 324 | ssns->num_hfis++; | |||
| 325 | } | |||
| 326 | ||||
| 327 | /* SSNS NQN */ | |||
| 328 | ret = get_heap_obj(ctx, raw_ssns, subsys_ns_nqn_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "subsys_ns_nqn_obj" , raw_ssns->subsys_ns_nqn_obj, 1, &ssns->subsys_nqn ) | |||
| 329 | 1, &ssns->subsys_nqn)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "subsys_ns_nqn_obj" , raw_ssns->subsys_ns_nqn_obj, 1, &ssns->subsys_nqn ); | |||
| 330 | if (ret) | |||
| 331 | goto fail; | |||
| 332 | ||||
| 333 | /* SSNS extended info */ | |||
| 334 | if (le16_to_cpu(raw_ssns->flags) & NBFT_SSNS_EXTENDED_INFO_IN_USE) { | |||
| 335 | struct nbft_ssns_ext_info *ssns_extended_info; | |||
| 336 | ||||
| 337 | if (!get_heap_obj(ctx, raw_ssns, ssns_extended_info_desc_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "ssns_extended_info_desc_obj" , raw_ssns->ssns_extended_info_desc_obj, 0, (char **)& ssns_extended_info) | |||
| 338 | 0, (char **)&ssns_extended_info)__get_heap_obj(ctx, header, nbft->filename, "raw_ssns", "ssns_extended_info_desc_obj" , raw_ssns->ssns_extended_info_desc_obj, 0, (char **)& ssns_extended_info)) { | |||
| 339 | read_ssns_exended_info(ctx, nbft, ssns, | |||
| 340 | ssns_extended_info); | |||
| 341 | } | |||
| 342 | } | |||
| 343 | ||||
| 344 | *s = ssns; | |||
| 345 | return 0; | |||
| 346 | ||||
| 347 | fail: | |||
| 348 | free(ssns); | |||
| 349 | return ret; | |||
| 350 | } | |||
| 351 | ||||
| 352 | static int read_hfi_info_tcp(struct libnvme_global_ctx *ctx, | |||
| 353 | struct libnbft_info *nbft, | |||
| 354 | struct nbft_hfi_info_tcp *raw_hfi_info_tcp, | |||
| 355 | struct libnbft_hfi *hfi) | |||
| 356 | { | |||
| 357 | struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; | |||
| 358 | ||||
| 359 | if ((raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_VALID) == 0) | |||
| 360 | return -EINVAL22; | |||
| 361 | ||||
| 362 | verify(ctx, raw_hfi_info_tcp->structure_id == NBFT_DESC_HFI_TRINFO,do { if (!(raw_hfi_info_tcp->structure_id == NBFT_DESC_HFI_TRINFO )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HFI transport descriptor" "\n", nbft->filename ); return -22; } } while (0) | |||
| 363 | "invalid ID in HFI transport descriptor")do { if (!(raw_hfi_info_tcp->structure_id == NBFT_DESC_HFI_TRINFO )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HFI transport descriptor" "\n", nbft->filename ); return -22; } } while (0); | |||
| 364 | verify(ctx, raw_hfi_info_tcp->version == 1,do { if (!(raw_hfi_info_tcp->version == 1)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid version in HFI transport descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 365 | "invalid version in HFI transport descriptor")do { if (!(raw_hfi_info_tcp->version == 1)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid version in HFI transport descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 366 | if (le16_to_cpu(raw_hfi_info_tcp->hfi_index) != hfi->index) | |||
| 367 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n" , nbft->filename, hfi->index) | |||
| 368 | "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n" , nbft->filename, hfi->index) | |||
| 369 | nbft->filename, hfi->index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: HFI descriptor index %d does not match index in HFI transport descriptor\n" , nbft->filename, hfi->index); | |||
| 370 | ||||
| 371 | hfi->tcp_info.pci_sbdf = le32_to_cpu(raw_hfi_info_tcp->pci_sbdf); | |||
| 372 | memcpy(hfi->tcp_info.mac_addr, raw_hfi_info_tcp->mac_addr, | |||
| 373 | sizeof(raw_hfi_info_tcp->mac_addr)); | |||
| 374 | hfi->tcp_info.vlan = le16_to_cpu(raw_hfi_info_tcp->vlan); | |||
| 375 | hfi->tcp_info.ip_origin = raw_hfi_info_tcp->ip_origin; | |||
| 376 | format_ip_addr(hfi->tcp_info.ipaddr, sizeof(hfi->tcp_info.ipaddr), | |||
| 377 | raw_hfi_info_tcp->ip_address); | |||
| 378 | hfi->tcp_info.subnet_mask_prefix = raw_hfi_info_tcp->subnet_mask_prefix; | |||
| 379 | format_ip_addr(hfi->tcp_info.gateway_ipaddr, | |||
| 380 | sizeof(hfi->tcp_info.ipaddr), raw_hfi_info_tcp->ip_gateway); | |||
| 381 | hfi->tcp_info.route_metric = | |||
| 382 | le16_to_cpu(raw_hfi_info_tcp->route_metric); | |||
| 383 | format_ip_addr(hfi->tcp_info.primary_dns_ipaddr, | |||
| 384 | sizeof(hfi->tcp_info.primary_dns_ipaddr), | |||
| 385 | raw_hfi_info_tcp->primary_dns); | |||
| 386 | format_ip_addr(hfi->tcp_info.secondary_dns_ipaddr, | |||
| 387 | sizeof(hfi->tcp_info.secondary_dns_ipaddr), | |||
| 388 | raw_hfi_info_tcp->secondary_dns); | |||
| 389 | if (raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_DHCP_OVERRIDE) { | |||
| 390 | hfi->tcp_info.dhcp_override = true1; | |||
| 391 | format_ip_addr(hfi->tcp_info.dhcp_server_ipaddr, | |||
| 392 | sizeof(hfi->tcp_info.dhcp_server_ipaddr), | |||
| 393 | raw_hfi_info_tcp->dhcp_server); | |||
| 394 | } | |||
| 395 | get_heap_obj(ctx, raw_hfi_info_tcp, host_name_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_hfi_info_tcp" , "host_name_obj", raw_hfi_info_tcp->host_name_obj, 1, & hfi->tcp_info.host_name) | |||
| 396 | 1, &hfi->tcp_info.host_name)__get_heap_obj(ctx, header, nbft->filename, "raw_hfi_info_tcp" , "host_name_obj", raw_hfi_info_tcp->host_name_obj, 1, & hfi->tcp_info.host_name); | |||
| 397 | if (raw_hfi_info_tcp->flags & NBFT_HFI_INFO_TCP_GLOBAL_ROUTE) | |||
| 398 | hfi->tcp_info.this_hfi_is_default_route = true1; | |||
| 399 | ||||
| 400 | return 0; | |||
| 401 | } | |||
| 402 | ||||
| 403 | static int read_hfi(struct libnvme_global_ctx *ctx, struct libnbft_info *nbft, | |||
| 404 | struct nbft_hfi *raw_hfi, struct libnbft_hfi **h) | |||
| 405 | { | |||
| 406 | int ret; | |||
| 407 | struct libnbft_hfi *hfi; | |||
| 408 | struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; | |||
| 409 | ||||
| 410 | if (!(raw_hfi->flags & NBFT_HFI_VALID)) | |||
| 411 | return -EINVAL22; | |||
| 412 | ||||
| 413 | verify(ctx, raw_hfi->structure_id == NBFT_DESC_HFI,do { if (!(raw_hfi->structure_id == NBFT_DESC_HFI)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HFI descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 414 | "invalid ID in HFI descriptor")do { if (!(raw_hfi->structure_id == NBFT_DESC_HFI)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HFI descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 415 | ||||
| 416 | hfi = calloc(1, sizeof(struct libnbft_hfi)); | |||
| 417 | if (!hfi) | |||
| 418 | return -ENOMEM12; | |||
| 419 | ||||
| 420 | hfi->index = raw_hfi->index; | |||
| 421 | ||||
| 422 | /* | |||
| 423 | * read HFI transport descriptor for this HFI | |||
| 424 | */ | |||
| 425 | if (raw_hfi->trtype == NBFT_TRTYPE_TCP) { | |||
| 426 | /* TCP */ | |||
| 427 | struct nbft_hfi_info_tcp *raw_hfi_info_tcp; | |||
| 428 | ||||
| 429 | strncpy(hfi->transport, trtype_to_string(raw_hfi->trtype), | |||
| 430 | sizeof(hfi->transport)); | |||
| 431 | ||||
| 432 | ret = get_heap_obj(ctx, raw_hfi, trinfo_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_hfi", "trinfo_obj" , raw_hfi->trinfo_obj, 0, (char **)&raw_hfi_info_tcp) | |||
| 433 | 0, (char **)&raw_hfi_info_tcp)__get_heap_obj(ctx, header, nbft->filename, "raw_hfi", "trinfo_obj" , raw_hfi->trinfo_obj, 0, (char **)&raw_hfi_info_tcp); | |||
| 434 | if (ret) | |||
| 435 | goto fail; | |||
| 436 | ||||
| 437 | ret = read_hfi_info_tcp(ctx, nbft, raw_hfi_info_tcp, hfi); | |||
| 438 | if (ret) | |||
| 439 | goto fail; | |||
| 440 | } else { | |||
| 441 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: invalid transport type %d\n" , nbft->filename, raw_hfi->trtype) | |||
| 442 | "file %s: invalid transport type %d\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: invalid transport type %d\n" , nbft->filename, raw_hfi->trtype) | |||
| 443 | nbft->filename, raw_hfi->trtype)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: invalid transport type %d\n" , nbft->filename, raw_hfi->trtype); | |||
| 444 | ret = -EINVAL22; | |||
| 445 | goto fail; | |||
| 446 | } | |||
| 447 | ||||
| 448 | *h = hfi; | |||
| 449 | return 0; | |||
| 450 | ||||
| 451 | fail: | |||
| 452 | free(hfi); | |||
| 453 | return ret; | |||
| 454 | } | |||
| 455 | ||||
| 456 | static int read_discovery(struct libnvme_global_ctx *ctx, | |||
| 457 | struct libnbft_info *nbft, | |||
| 458 | struct nbft_discovery *raw_discovery, | |||
| 459 | struct libnbft_discovery **d) | |||
| 460 | { | |||
| 461 | struct libnbft_discovery *discovery = NULL((void*)0); | |||
| 462 | struct nbft_header *header = (struct nbft_header *)nbft->raw_nbft; | |||
| 463 | int r = -EINVAL22; | |||
| 464 | ||||
| 465 | if (!(raw_discovery->flags & NBFT_DISCOVERY_VALID)) | |||
| 466 | goto error; | |||
| 467 | ||||
| 468 | verify(ctx, raw_discovery->structure_id == NBFT_DESC_DISCOVERY,do { if (!(raw_discovery->structure_id == NBFT_DESC_DISCOVERY )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in discovery descriptor" "\n", nbft->filename ); return -22; } } while (0) | |||
| 469 | "invalid ID in discovery descriptor")do { if (!(raw_discovery->structure_id == NBFT_DESC_DISCOVERY )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in discovery descriptor" "\n", nbft->filename ); return -22; } } while (0); | |||
| 470 | ||||
| 471 | discovery = calloc(1, sizeof(struct libnbft_discovery)); | |||
| 472 | if (!discovery) { | |||
| 473 | r = -ENOMEM12; | |||
| 474 | goto error; | |||
| 475 | } | |||
| 476 | ||||
| 477 | discovery->index = raw_discovery->index; | |||
| 478 | ||||
| 479 | if (get_heap_obj(ctx, raw_discovery, discovery_ctrl_addr_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_discovery" , "discovery_ctrl_addr_obj", raw_discovery->discovery_ctrl_addr_obj , 1, &discovery->uri) | |||
| 480 | 1, &discovery->uri)__get_heap_obj(ctx, header, nbft->filename, "raw_discovery" , "discovery_ctrl_addr_obj", raw_discovery->discovery_ctrl_addr_obj , 1, &discovery->uri)) | |||
| 481 | goto error; | |||
| 482 | ||||
| 483 | if (get_heap_obj(ctx, raw_discovery, discovery_ctrl_nqn_obj,__get_heap_obj(ctx, header, nbft->filename, "raw_discovery" , "discovery_ctrl_nqn_obj", raw_discovery->discovery_ctrl_nqn_obj , 1, &discovery->nqn) | |||
| 484 | 1, &discovery->nqn)__get_heap_obj(ctx, header, nbft->filename, "raw_discovery" , "discovery_ctrl_nqn_obj", raw_discovery->discovery_ctrl_nqn_obj , 1, &discovery->nqn)) | |||
| 485 | goto error; | |||
| 486 | ||||
| 487 | discovery->hfi = hfi_from_index(nbft, raw_discovery->hfi_index); | |||
| 488 | if (raw_discovery->hfi_index && !discovery->hfi) | |||
| 489 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d HFI not found\n" , nbft->filename, discovery->index) | |||
| 490 | "file %s: discovery %d HFI not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d HFI not found\n" , nbft->filename, discovery->index) | |||
| 491 | nbft->filename, discovery->index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d HFI not found\n" , nbft->filename, discovery->index); | |||
| 492 | ||||
| 493 | discovery->security = | |||
| 494 | security_from_index(nbft, raw_discovery->sec_index); | |||
| 495 | if (raw_discovery->sec_index && !discovery->security) | |||
| 496 | libnvme_msg(ctx, LIBNVME_LOG_DEBUG,__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d security descriptor not found\n" , nbft->filename, discovery->index) | |||
| 497 | "file %s: discovery %d security descriptor not found\n",__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d security descriptor not found\n" , nbft->filename, discovery->index) | |||
| 498 | nbft->filename, discovery->index)__libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: discovery %d security descriptor not found\n" , nbft->filename, discovery->index); | |||
| 499 | ||||
| 500 | *d = discovery; | |||
| 501 | r = 0; | |||
| 502 | ||||
| 503 | error: | |||
| 504 | if (r) | |||
| 505 | free(discovery); | |||
| 506 | return r; | |||
| 507 | } | |||
| 508 | ||||
| 509 | static int read_security(struct libnvme_global_ctx *ctx, struct libnbft_info *nbft, | |||
| 510 | struct nbft_security *raw_security, | |||
| 511 | struct libnbft_security **s) | |||
| 512 | { | |||
| 513 | return -EINVAL22; | |||
| 514 | } | |||
| 515 | ||||
| 516 | static void read_hfi_descriptors(struct libnvme_global_ctx *ctx, | |||
| 517 | struct libnbft_info *nbft, int num_hfi, | |||
| 518 | struct nbft_hfi *raw_hfi_array, int hfi_len) | |||
| 519 | { | |||
| 520 | int i, cnt; | |||
| 521 | ||||
| 522 | nbft->hfi_list = calloc(num_hfi + 1, sizeof(struct libnbft_hfi *)); | |||
| 523 | for (i = 0, cnt = 0; i < num_hfi; i++) { | |||
| 524 | if (read_hfi(ctx, nbft, &raw_hfi_array[i], | |||
| 525 | &nbft->hfi_list[cnt]) == 0) | |||
| 526 | cnt++; | |||
| 527 | } | |||
| 528 | } | |||
| 529 | ||||
| 530 | static void read_security_descriptors(struct libnvme_global_ctx *ctx, | |||
| 531 | struct libnbft_info *nbft, int num_sec, | |||
| 532 | struct nbft_security *raw_sec_array, int sec_len) | |||
| 533 | { | |||
| 534 | int i, cnt; | |||
| 535 | ||||
| 536 | nbft->security_list = calloc(num_sec + 1, | |||
| 537 | sizeof(struct libnbft_security *)); | |||
| 538 | for (i = 0, cnt = 0; i < num_sec; i++) { | |||
| 539 | if (read_security(ctx, nbft, &raw_sec_array[i], | |||
| 540 | &nbft->security_list[cnt]) == 0) | |||
| 541 | cnt++; | |||
| 542 | } | |||
| 543 | } | |||
| 544 | ||||
| 545 | static void read_discovery_descriptors(struct libnvme_global_ctx *ctx, | |||
| 546 | struct libnbft_info *nbft, int num_disc, | |||
| 547 | struct nbft_discovery *raw_disc_array, int disc_len) | |||
| 548 | { | |||
| 549 | int i, cnt; | |||
| 550 | ||||
| 551 | nbft->discovery_list = | |||
| 552 | calloc(num_disc + 1, sizeof(struct libnbft_discovery *)); | |||
| 553 | for (i = 0, cnt = 0; i < num_disc; i++) { | |||
| 554 | if (read_discovery(ctx, nbft, &raw_disc_array[i], | |||
| 555 | &nbft->discovery_list[cnt]) == 0) | |||
| 556 | cnt++; | |||
| 557 | } | |||
| 558 | } | |||
| 559 | ||||
| 560 | static void read_ssns_descriptors(struct libnvme_global_ctx *ctx, | |||
| 561 | struct libnbft_info *nbft, int num_ssns, | |||
| 562 | struct nbft_ssns *raw_ssns_array, int ssns_len) | |||
| 563 | { | |||
| 564 | int i, cnt; | |||
| 565 | ||||
| 566 | nbft->subsystem_ns_list = | |||
| 567 | calloc(num_ssns + 1, sizeof(struct libnbft_subsystem_ns *)); | |||
| 568 | for (i = 0, cnt = 0; i < num_ssns; i++) { | |||
| 569 | if (read_ssns(ctx, nbft, &raw_ssns_array[i], | |||
| 570 | &nbft->subsystem_ns_list[cnt]) == 0) | |||
| 571 | cnt++; | |||
| 572 | } | |||
| 573 | } | |||
| 574 | ||||
| 575 | /** | |||
| 576 | * parse_raw_nbft - parses raw ACPI NBFT table and fill in abstracted libnbft_info structure | |||
| 577 | * @nbft: libnbft_info struct containing only raw_nbft and raw_nbft_size | |||
| 578 | * | |||
| 579 | * Returns 0 on success, errno otherwise. | |||
| 580 | */ | |||
| 581 | static int parse_raw_nbft(struct libnvme_global_ctx *ctx, struct libnbft_info *nbft) | |||
| 582 | { | |||
| 583 | __u8 *raw_nbft = nbft->raw_nbft; | |||
| 584 | int raw_nbft_size = nbft->raw_nbft_size; | |||
| 585 | ||||
| 586 | struct nbft_header *header; | |||
| 587 | struct nbft_control *control; | |||
| 588 | struct nbft_host *host; | |||
| 589 | ||||
| 590 | verify(ctx, raw_nbft_size >=do { if (!(raw_nbft_size >= sizeof(struct nbft_header) + sizeof (struct nbft_control))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG , ((void*)0), "file %s: " "table is too short" "\n", nbft-> filename); return -22; } } while (0) | |||
| 591 | sizeof(struct nbft_header) + sizeof(struct nbft_control),do { if (!(raw_nbft_size >= sizeof(struct nbft_header) + sizeof (struct nbft_control))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG , ((void*)0), "file %s: " "table is too short" "\n", nbft-> filename); return -22; } } while (0) | |||
| 592 | "table is too short")do { if (!(raw_nbft_size >= sizeof(struct nbft_header) + sizeof (struct nbft_control))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG , ((void*)0), "file %s: " "table is too short" "\n", nbft-> filename); return -22; } } while (0); | |||
| 593 | verify(ctx, csum(raw_nbft, raw_nbft_size) == 0, "invalid checksum")do { if (!(csum(raw_nbft, raw_nbft_size) == 0)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid checksum" "\n", nbft->filename); return -22; } } while (0); | |||
| 594 | ||||
| 595 | /* | |||
| 596 | * header | |||
| 597 | */ | |||
| 598 | header = (struct nbft_header *)raw_nbft; | |||
| 599 | ||||
| 600 | verify(ctx, strncmp(header->signature, NBFT_HEADER_SIG, 4) == 0,do { if (!(strncmp(header->signature, "NBFT", 4) == 0)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid signature" "\n", nbft->filename); return -22; } } while (0) | |||
| 601 | "invalid signature")do { if (!(strncmp(header->signature, "NBFT", 4) == 0)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid signature" "\n", nbft->filename); return -22; } } while (0); | |||
| 602 | verify(ctx, le32_to_cpu(header->length) <= raw_nbft_size,do { if (!(le32_to_cpu(header->length) <= raw_nbft_size )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "length in header exceeds table length" "\n", nbft->filename ); return -22; } } while (0) | |||
| 603 | "length in header exceeds table length")do { if (!(le32_to_cpu(header->length) <= raw_nbft_size )) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "length in header exceeds table length" "\n", nbft->filename ); return -22; } } while (0); | |||
| 604 | verify(ctx, header->major_revision == 1,do { if (!(header->major_revision == 1)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "unsupported major revision" "\n", nbft->filename); return -22; } } while (0) | |||
| 605 | "unsupported major revision")do { if (!(header->major_revision == 1)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "unsupported major revision" "\n", nbft->filename); return -22; } } while (0); | |||
| 606 | verify(ctx, header->minor_revision == 0,do { if (!(header->minor_revision == 0)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "unsupported minor revision" "\n", nbft->filename); return -22; } } while (0) | |||
| 607 | "unsupported minor revision")do { if (!(header->minor_revision == 0)) { __libnvme_msg(ctx , LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "unsupported minor revision" "\n", nbft->filename); return -22; } } while (0); | |||
| 608 | verify(ctx, le32_to_cpu(header->heap_length) +do { if (!(le32_to_cpu(header->heap_length) + le32_to_cpu( header->heap_offset) <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "heap exceeds table length" "\n", nbft->filename); return -22; } } while (0) | |||
| 609 | le32_to_cpu(header->heap_offset) <= le32_to_cpu(header->length),do { if (!(le32_to_cpu(header->heap_length) + le32_to_cpu( header->heap_offset) <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "heap exceeds table length" "\n", nbft->filename); return -22; } } while (0) | |||
| 610 | "heap exceeds table length")do { if (!(le32_to_cpu(header->heap_length) + le32_to_cpu( header->heap_offset) <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "heap exceeds table length" "\n", nbft->filename); return -22; } } while (0); | |||
| 611 | ||||
| 612 | /* | |||
| 613 | * control | |||
| 614 | */ | |||
| 615 | control = | |||
| 616 | (struct nbft_control *)(raw_nbft + sizeof(struct nbft_header)); | |||
| 617 | ||||
| 618 | if ((control->flags & NBFT_CONTROL_VALID) == 0) | |||
| 619 | return 0; | |||
| 620 | verify(ctx, control->structure_id == NBFT_DESC_CONTROL,do { if (!(control->structure_id == NBFT_DESC_CONTROL)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in control structure" "\n", nbft->filename); return -22; } } while (0) | |||
| 621 | "invalid ID in control structure")do { if (!(control->structure_id == NBFT_DESC_CONTROL)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in control structure" "\n", nbft->filename); return -22; } } while (0); | |||
| 622 | ||||
| 623 | /* | |||
| 624 | * host | |||
| 625 | */ | |||
| 626 | verify(ctx, le32_to_cpu(control->hdesc.offset) +do { if (!(le32_to_cpu(control->hdesc.offset) + sizeof(struct nbft_host) <= le32_to_cpu(header->length) && le32_to_cpu (control->hdesc.offset) >= sizeof(struct nbft_host))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor offset/length is invalid" "\n", nbft->filename ); return -22; } } while (0) | |||
| 627 | sizeof(struct nbft_host) <= le32_to_cpu(header->length) &&do { if (!(le32_to_cpu(control->hdesc.offset) + sizeof(struct nbft_host) <= le32_to_cpu(header->length) && le32_to_cpu (control->hdesc.offset) >= sizeof(struct nbft_host))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor offset/length is invalid" "\n", nbft->filename ); return -22; } } while (0) | |||
| 628 | le32_to_cpu(control->hdesc.offset) >= sizeof(struct nbft_host),do { if (!(le32_to_cpu(control->hdesc.offset) + sizeof(struct nbft_host) <= le32_to_cpu(header->length) && le32_to_cpu (control->hdesc.offset) >= sizeof(struct nbft_host))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor offset/length is invalid" "\n", nbft->filename ); return -22; } } while (0) | |||
| 629 | "host descriptor offset/length is invalid")do { if (!(le32_to_cpu(control->hdesc.offset) + sizeof(struct nbft_host) <= le32_to_cpu(header->length) && le32_to_cpu (control->hdesc.offset) >= sizeof(struct nbft_host))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor offset/length is invalid" "\n", nbft->filename ); return -22; } } while (0); | |||
| 630 | host = (struct nbft_host *)(raw_nbft + | |||
| 631 | le32_to_cpu(control->hdesc.offset)); | |||
| 632 | ||||
| 633 | verify(ctx, host->flags & NBFT_HOST_VALID,do { if (!(host->flags & NBFT_HOST_VALID)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor valid flag not set" "\n", nbft->filename); return -22; } } while (0) | |||
| 634 | "host descriptor valid flag not set")do { if (!(host->flags & NBFT_HOST_VALID)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "host descriptor valid flag not set" "\n", nbft->filename); return -22; } } while (0); | |||
| 635 | verify(ctx, host->structure_id == NBFT_DESC_HOST,do { if (!(host->structure_id == NBFT_DESC_HOST)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HOST descriptor" "\n", nbft->filename); return -22; } } while (0) | |||
| 636 | "invalid ID in HOST descriptor")do { if (!(host->structure_id == NBFT_DESC_HOST)) { __libnvme_msg (ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid ID in HOST descriptor" "\n", nbft->filename); return -22; } } while (0); | |||
| 637 | nbft->host.id = (unsigned char *) &(host->host_id); | |||
| 638 | if (get_heap_obj(ctx, host, host_nqn_obj, 1, &nbft->host.nqn)__get_heap_obj(ctx, header, nbft->filename, "host", "host_nqn_obj" , host->host_nqn_obj, 1, &nbft->host.nqn) != 0) | |||
| 639 | return -EINVAL22; | |||
| 640 | nbft->host.host_id_configured = | |||
| 641 | host->flags & NBFT_HOST_HOSTID_CONFIGURED; | |||
| 642 | nbft->host.host_nqn_configured = | |||
| 643 | host->flags & NBFT_HOST_HOSTNQN_CONFIGURED; | |||
| 644 | ||||
| 645 | /* | |||
| 646 | * HFI | |||
| 647 | */ | |||
| 648 | if (control->num_hfi > 0) { | |||
| 649 | struct nbft_hfi *raw_hfi_array; | |||
| 650 | ||||
| 651 | verify(ctx, le32_to_cpu(control->hfio) +do { if (!(le32_to_cpu(control->hfio) + sizeof(struct nbft_hfi ) * control->num_hfi <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid hfi descriptor list offset" "\n", nbft->filename ); return -22; } } while (0) | |||
| 652 | sizeof(struct nbft_hfi) * control->num_hfi <=do { if (!(le32_to_cpu(control->hfio) + sizeof(struct nbft_hfi ) * control->num_hfi <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid hfi descriptor list offset" "\n", nbft->filename ); return -22; } } while (0) | |||
| 653 | le32_to_cpu(header->length),do { if (!(le32_to_cpu(control->hfio) + sizeof(struct nbft_hfi ) * control->num_hfi <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid hfi descriptor list offset" "\n", nbft->filename ); return -22; } } while (0) | |||
| 654 | "invalid hfi descriptor list offset")do { if (!(le32_to_cpu(control->hfio) + sizeof(struct nbft_hfi ) * control->num_hfi <= le32_to_cpu(header->length)) ) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid hfi descriptor list offset" "\n", nbft->filename ); return -22; } } while (0); | |||
| 655 | raw_hfi_array = (struct nbft_hfi *)(raw_nbft + | |||
| 656 | le32_to_cpu(control->hfio)); | |||
| 657 | read_hfi_descriptors(ctx, nbft, control->num_hfi, raw_hfi_array, | |||
| 658 | le16_to_cpu(control->hfil)); | |||
| 659 | } | |||
| 660 | ||||
| 661 | /* | |||
| 662 | * security | |||
| 663 | */ | |||
| 664 | if (control->num_sec > 0) { | |||
| 665 | struct nbft_security *raw_security_array; | |||
| 666 | ||||
| 667 | verify(ctx, le32_to_cpu(control->seco) +do { if (!(le32_to_cpu(control->seco) + le16_to_cpu(control ->secl) * control->num_sec <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid security profile desciptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 668 | le16_to_cpu(control->secl) * control->num_sec <=do { if (!(le32_to_cpu(control->seco) + le16_to_cpu(control ->secl) * control->num_sec <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid security profile desciptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 669 | le32_to_cpu(header->length),do { if (!(le32_to_cpu(control->seco) + le16_to_cpu(control ->secl) * control->num_sec <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid security profile desciptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 670 | "invalid security profile desciptor list offset")do { if (!(le32_to_cpu(control->seco) + le16_to_cpu(control ->secl) * control->num_sec <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid security profile desciptor list offset" "\n", nbft->filename); return -22; } } while (0); | |||
| 671 | raw_security_array = (struct nbft_security *)(raw_nbft + | |||
| 672 | le32_to_cpu(control->seco)); | |||
| 673 | read_security_descriptors(ctx, nbft, control->num_sec, | |||
| 674 | raw_security_array, | |||
| 675 | le16_to_cpu(control->secl)); | |||
| 676 | } | |||
| 677 | ||||
| 678 | /* | |||
| 679 | * discovery | |||
| 680 | */ | |||
| 681 | if (control->num_disc > 0) { | |||
| 682 | struct nbft_discovery *raw_discovery_array; | |||
| 683 | ||||
| 684 | verify(ctx, le32_to_cpu(control->disco) +do { if (!(le32_to_cpu(control->disco) + le16_to_cpu(control ->discl) * control->num_disc <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid discovery profile descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 685 | le16_to_cpu(control->discl) * control->num_disc <=do { if (!(le32_to_cpu(control->disco) + le16_to_cpu(control ->discl) * control->num_disc <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid discovery profile descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 686 | le32_to_cpu(header->length),do { if (!(le32_to_cpu(control->disco) + le16_to_cpu(control ->discl) * control->num_disc <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid discovery profile descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 687 | "invalid discovery profile descriptor list offset")do { if (!(le32_to_cpu(control->disco) + le16_to_cpu(control ->discl) * control->num_disc <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid discovery profile descriptor list offset" "\n", nbft->filename); return -22; } } while (0); | |||
| 688 | raw_discovery_array = (struct nbft_discovery *)(raw_nbft + | |||
| 689 | le32_to_cpu(control->disco)); | |||
| 690 | read_discovery_descriptors(ctx, nbft, control->num_disc, | |||
| 691 | raw_discovery_array, le16_to_cpu(control->discl)); | |||
| 692 | } | |||
| 693 | ||||
| 694 | /* | |||
| 695 | * subsystem namespace | |||
| 696 | */ | |||
| 697 | if (control->num_ssns > 0) { | |||
| 698 | struct nbft_ssns *raw_ssns_array; | |||
| 699 | ||||
| 700 | verify(ctx, le32_to_cpu(control->ssnso) +do { if (!(le32_to_cpu(control->ssnso) + le16_to_cpu(control ->ssnsl) * control->num_ssns <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid subsystem namespace descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 701 | le16_to_cpu(control->ssnsl) * control->num_ssns <=do { if (!(le32_to_cpu(control->ssnso) + le16_to_cpu(control ->ssnsl) * control->num_ssns <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid subsystem namespace descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 702 | le32_to_cpu(header->length),do { if (!(le32_to_cpu(control->ssnso) + le16_to_cpu(control ->ssnsl) * control->num_ssns <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid subsystem namespace descriptor list offset" "\n", nbft->filename); return -22; } } while (0) | |||
| 703 | "invalid subsystem namespace descriptor list offset")do { if (!(le32_to_cpu(control->ssnso) + le16_to_cpu(control ->ssnsl) * control->num_ssns <= le32_to_cpu(header-> length))) { __libnvme_msg(ctx, LIBNVME_LOG_DEBUG, ((void*)0), "file %s: " "invalid subsystem namespace descriptor list offset" "\n", nbft->filename); return -22; } } while (0); | |||
| 704 | raw_ssns_array = (struct nbft_ssns *)(raw_nbft + | |||
| 705 | le32_to_cpu(control->ssnso)); | |||
| 706 | read_ssns_descriptors(ctx, nbft, control->num_ssns, | |||
| 707 | raw_ssns_array, le16_to_cpu(control->ssnsl)); | |||
| 708 | } | |||
| 709 | ||||
| 710 | return 0; | |||
| 711 | } | |||
| 712 | ||||
| 713 | __libnvme_public__attribute__((visibility("default"))) void libnvmf_free_nbft( | |||
| 714 | struct libnvme_global_ctx *ctx, struct libnbft_info *nbft) | |||
| 715 | { | |||
| 716 | struct libnbft_hfi **hfi; | |||
| 717 | struct libnbft_security **sec; | |||
| 718 | struct libnbft_discovery **disc; | |||
| 719 | struct libnbft_subsystem_ns **ns; | |||
| 720 | ||||
| 721 | for (hfi = nbft->hfi_list; hfi && *hfi; hfi++) | |||
| 722 | free(*hfi); | |||
| 723 | free(nbft->hfi_list); | |||
| 724 | for (disc = nbft->discovery_list; disc && *disc; disc++) | |||
| 725 | free(*disc); | |||
| 726 | free(nbft->discovery_list); | |||
| 727 | for (sec = nbft->security_list; sec && *sec; sec++) | |||
| 728 | free(*sec); | |||
| 729 | free(nbft->security_list); | |||
| 730 | for (ns = nbft->subsystem_ns_list; ns && *ns; ns++) { | |||
| 731 | free((*ns)->hfis); | |||
| 732 | free(*ns); | |||
| 733 | } | |||
| 734 | free(nbft->subsystem_ns_list); | |||
| 735 | free(nbft->raw_nbft); | |||
| 736 | free(nbft->filename); | |||
| 737 | free(nbft); | |||
| 738 | } | |||
| 739 | ||||
| 740 | __libnvme_public__attribute__((visibility("default"))) int libnvmf_read_nbft( | |||
| 741 | struct libnvme_global_ctx *ctx, struct libnbft_info **nbft, | |||
| 742 | const char *filename) | |||
| 743 | { | |||
| 744 | __u8 *raw_nbft = NULL((void*)0); | |||
| 745 | size_t raw_nbft_size; | |||
| 746 | FILE *raw_nbft_fp = NULL((void*)0); | |||
| 747 | int i; | |||
| 748 | ||||
| 749 | /* | |||
| 750 | * read in raw nbft file | |||
| 751 | */ | |||
| 752 | raw_nbft_fp = fopen(filename, "rb"); | |||
| 753 | if (raw_nbft_fp
| |||
| ||||
| 754 | libnvme_msg(ctx, LIBNVME_LOG_ERR, "Failed to open %s: %s\n",__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to open %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))) | |||
| 755 | filename, libnvme_strerror(errno))__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to open %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))); | |||
| 756 | return -EINVAL22; | |||
| 757 | } | |||
| 758 | ||||
| 759 | i = fseek(raw_nbft_fp, 0L, SEEK_END2); | |||
| 760 | if (i
| |||
| 761 | libnvme_msg(ctx, LIBNVME_LOG_ERR, "Failed to read from %s: %s\n",__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to read from %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))) | |||
| 762 | filename, libnvme_strerror(errno))__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to read from %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))); | |||
| 763 | fclose(raw_nbft_fp); | |||
| 764 | return -EINVAL22; | |||
| 765 | } | |||
| 766 | ||||
| 767 | raw_nbft_size = ftell(raw_nbft_fp); | |||
| 768 | rewind(raw_nbft_fp); | |||
| 769 | ||||
| 770 | raw_nbft = malloc(raw_nbft_size); | |||
| ||||
| 771 | if (!raw_nbft) { | |||
| 772 | libnvme_msg(ctx, LIBNVME_LOG_ERR,__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to allocate memory for NBFT table" ) | |||
| 773 | "Failed to allocate memory for NBFT table")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to allocate memory for NBFT table" ); | |||
| 774 | fclose(raw_nbft_fp); | |||
| 775 | return -ENOMEM12; | |||
| 776 | } | |||
| 777 | ||||
| 778 | i = fread(raw_nbft, sizeof(*raw_nbft), raw_nbft_size, raw_nbft_fp); | |||
| 779 | if (i != raw_nbft_size) { | |||
| 780 | libnvme_msg(ctx, LIBNVME_LOG_ERR, "Failed to read from %s: %s\n",__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to read from %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))) | |||
| 781 | filename, libnvme_strerror(errno))__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to read from %s: %s\n" , filename, libnvme_strerror((*__errno_location ()))); | |||
| 782 | fclose(raw_nbft_fp); | |||
| 783 | free(raw_nbft); | |||
| 784 | return -EINVAL22; | |||
| 785 | } | |||
| 786 | fclose(raw_nbft_fp); | |||
| 787 | ||||
| 788 | /* | |||
| 789 | * alloc new struct libnbft_info, add raw nbft & filename to it, | |||
| 790 | * and add it to the list | |||
| 791 | */ | |||
| 792 | *nbft = calloc(1, sizeof(struct libnbft_info)); | |||
| 793 | if (!*nbft) { | |||
| 794 | libnvme_msg(ctx, LIBNVME_LOG_ERR, "Could not allocate memory for NBFT\n")__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Could not allocate memory for NBFT\n" ); | |||
| 795 | free(raw_nbft); | |||
| 796 | return -ENOMEM12; | |||
| 797 | } | |||
| 798 | ||||
| 799 | (*nbft)->filename = strdup(filename); | |||
| 800 | (*nbft)->raw_nbft = raw_nbft; | |||
| 801 | (*nbft)->raw_nbft_size = raw_nbft_size; | |||
| 802 | ||||
| 803 | if (parse_raw_nbft(ctx, *nbft)) { | |||
| 804 | libnvme_msg(ctx, LIBNVME_LOG_ERR, "Failed to parse %s\n", filename)__libnvme_msg(ctx, LIBNVME_LOG_ERR, ((void*)0), "Failed to parse %s\n" , filename); | |||
| 805 | libnvmf_free_nbft(ctx, *nbft); | |||
| 806 | return -EINVAL22; | |||
| 807 | } | |||
| 808 | return 0; | |||
| 809 | } |