// SPDX-License-Identifier: GPL-2.0-or-later /* AFS vlserver list management. * * Copyright (C) 2018 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
val = (u16)*(*_b)++ << 0;
val |= (u16)*(*_b)++ << 8; return val;
}
/* * Build a VL server address list from a DNS queried server list.
*/ staticstruct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net, const u8 **_b, const u8 *end,
u8 nr_addrs, u16 port)
{ struct afs_addr_list *alist; const u8 *b = *_b; int ret = -EINVAL;
alist = afs_alloc_addrlist(nr_addrs); if (!alist) return ERR_PTR(-ENOMEM); if (nr_addrs == 0) return alist;
for (; nr_addrs > 0 && end - b >= nr_addrs; nr_addrs--) { struct dns_server_list_v1_address hdr;
__be32 x[4];
hdr.address_type = *b++;
switch (hdr.address_type) { case DNS_ADDRESS_IS_IPV4: if (end - b < 4) {
_leave(" = -EINVAL [short inet]"); goto error;
}
memcpy(x, b, 4);
ret = afs_merge_fs_addr4(net, alist, x[0], port); if (ret < 0) goto error;
b += 4; break;
case DNS_ADDRESS_IS_IPV6: if (end - b < 16) {
_leave(" = -EINVAL [short inet6]"); goto error;
}
memcpy(x, b, 16);
ret = afs_merge_fs_addr6(net, alist, x, port); if (ret < 0) goto error;
b += 16; break;
default:
_leave(" = -EADDRNOTAVAIL [unknown af %u]",
hdr.address_type);
ret = -EADDRNOTAVAIL; goto error;
}
}
/* Start with IPv6 if available. */ if (alist->nr_ipv4 < alist->nr_addrs)
alist->preferred = alist->nr_ipv4;
/* * Build a VL server list from a DNS queried server list.
*/ struct afs_vlserver_list *afs_extract_vlserver_list(struct afs_cell *cell, constvoid *buffer,
size_t buffer_size)
{ conststruct dns_server_list_v1_header *hdr = buffer; struct dns_server_list_v1_server bs; struct afs_vlserver_list *vllist, *previous; struct afs_addr_list *addrs; struct afs_vlserver *server; const u8 *b = buffer, *end = buffer + buffer_size; int ret = -ENOMEM, nr_servers, i, j;
_enter("");
/* Check that it's a server list, v1 */ if (end - b < sizeof(*hdr) ||
hdr->hdr.content != DNS_PAYLOAD_IS_SERVER_LIST ||
hdr->hdr.version != 1) {
pr_notice("kAFS: Got DNS record [%u,%u] len %zu\n",
hdr->hdr.content, hdr->hdr.version, end - b);
ret = -EDESTADDRREQ; goto dump;
}
nr_servers = hdr->nr_servers;
vllist = afs_alloc_vlserver_list(nr_servers); if (!vllist) return ERR_PTR(-ENOMEM);
if (bs.port == 0)
bs.port = AFS_VL_PORT; if (bs.source > NR__dns_record_source)
bs.source = NR__dns_record_source; if (bs.status > NR__dns_lookup_status)
bs.status = NR__dns_lookup_status;
/* See if we can update an old server record */
server = NULL; for (i = 0; i < previous->nr_servers; i++) { struct afs_vlserver *p = previous->servers[i].server;
if (!server) {
ret = -ENOMEM;
server = afs_alloc_vlserver(b, bs.name_len, bs.port); if (!server) goto error;
}
b += bs.name_len;
/* Extract the addresses - note that we can't skip this as we * have to advance the payload pointer.
*/
addrs = afs_extract_vl_addrs(cell->net, &b, end, bs.nr_addrs, bs.port); if (IS_ERR(addrs)) {
ret = PTR_ERR(addrs); goto error_2;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.