1 /* AFS Volume Location Service client 2 * 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #include <linux/gfp.h> 13 #include <linux/init.h> 14 #include <linux/sched.h> 15 #include "afs_fs.h" 16 #include "internal.h" 17 18 /* 19 * Deliver reply data to a VL.GetEntryByNameU call. 20 */ 21 static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) 22 { 23 struct afs_uvldbentry__xdr *uvldb; 24 struct afs_vldb_entry *entry; 25 bool new_only = false; 26 u32 tmp, nr_servers, vlflags; 27 int i, ret; 28 29 _enter(""); 30 31 ret = afs_transfer_reply(call); 32 if (ret < 0) 33 return ret; 34 35 /* unmarshall the reply once we've received all of it */ 36 uvldb = call->buffer; 37 entry = call->reply[0]; 38 39 nr_servers = ntohl(uvldb->nServers); 40 if (nr_servers > AFS_NMAXNSERVERS) 41 nr_servers = AFS_NMAXNSERVERS; 42 43 for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++) 44 entry->name[i] = (u8)ntohl(uvldb->name[i]); 45 entry->name[i] = 0; 46 entry->name_len = strlen(entry->name); 47 48 /* If there is a new replication site that we can use, ignore all the 49 * sites that aren't marked as new. 50 */ 51 for (i = 0; i < nr_servers; i++) { 52 tmp = ntohl(uvldb->serverFlags[i]); 53 if (!(tmp & AFS_VLSF_DONTUSE) && 54 (tmp & AFS_VLSF_NEWREPSITE)) 55 new_only = true; 56 } 57 58 vlflags = ntohl(uvldb->flags); 59 for (i = 0; i < nr_servers; i++) { 60 struct afs_uuid__xdr *xdr; 61 struct afs_uuid *uuid; 62 int j; 63 64 tmp = ntohl(uvldb->serverFlags[i]); 65 if (tmp & AFS_VLSF_DONTUSE || 66 (new_only && !(tmp & AFS_VLSF_NEWREPSITE))) 67 continue; 68 if (tmp & AFS_VLSF_RWVOL) { 69 entry->fs_mask[i] |= AFS_VOL_VTM_RW; 70 if (vlflags & AFS_VLF_BACKEXISTS) 71 entry->fs_mask[i] |= AFS_VOL_VTM_BAK; 72 } 73 if (tmp & AFS_VLSF_ROVOL) 74 entry->fs_mask[i] |= AFS_VOL_VTM_RO; 75 if (!entry->fs_mask[i]) 76 continue; 77 78 xdr = &uvldb->serverNumber[i]; 79 uuid = (struct afs_uuid *)&entry->fs_server[i]; 80 uuid->time_low = xdr->time_low; 81 uuid->time_mid = htons(ntohl(xdr->time_mid)); 82 uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version)); 83 uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved); 84 uuid->clock_seq_low = (u8)ntohl(xdr->clock_seq_low); 85 for (j = 0; j < 6; j++) 86 uuid->node[j] = (u8)ntohl(xdr->node[j]); 87 88 entry->nr_servers++; 89 } 90 91 for (i = 0; i < AFS_MAXTYPES; i++) 92 entry->vid[i] = ntohl(uvldb->volumeId[i]); 93 94 if (vlflags & AFS_VLF_RWEXISTS) 95 __set_bit(AFS_VLDB_HAS_RW, &entry->flags); 96 if (vlflags & AFS_VLF_ROEXISTS) 97 __set_bit(AFS_VLDB_HAS_RO, &entry->flags); 98 if (vlflags & AFS_VLF_BACKEXISTS) 99 __set_bit(AFS_VLDB_HAS_BAK, &entry->flags); 100 101 if (!(vlflags & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) { 102 entry->error = -ENOMEDIUM; 103 __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags); 104 } 105 106 __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags); 107 _leave(" = 0 [done]"); 108 return 0; 109 } 110 111 static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call) 112 { 113 kfree(call->reply[0]); 114 afs_flat_call_destructor(call); 115 } 116 117 /* 118 * VL.GetEntryByNameU operation type. 119 */ 120 static const struct afs_call_type afs_RXVLGetEntryByNameU = { 121 .name = "VL.GetEntryByNameU", 122 .op = afs_VL_GetEntryByNameU, 123 .deliver = afs_deliver_vl_get_entry_by_name_u, 124 .destructor = afs_destroy_vl_get_entry_by_name_u, 125 }; 126 127 /* 128 * Dispatch a get volume entry by name or ID operation (uuid variant). If the 129 * volname is a decimal number then it's a volume ID not a volume name. 130 */ 131 struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc, 132 const char *volname, 133 int volnamesz) 134 { 135 struct afs_vldb_entry *entry; 136 struct afs_call *call; 137 struct afs_net *net = vc->cell->net; 138 size_t reqsz, padsz; 139 __be32 *bp; 140 141 _enter(""); 142 143 padsz = (4 - (volnamesz & 3)) & 3; 144 reqsz = 8 + volnamesz + padsz; 145 146 entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL); 147 if (!entry) 148 return ERR_PTR(-ENOMEM); 149 150 call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz, 151 sizeof(struct afs_uvldbentry__xdr)); 152 if (!call) { 153 kfree(entry); 154 return ERR_PTR(-ENOMEM); 155 } 156 157 call->key = vc->key; 158 call->reply[0] = entry; 159 call->ret_reply0 = true; 160 161 /* Marshall the parameters */ 162 bp = call->request; 163 *bp++ = htonl(VLGETENTRYBYNAMEU); 164 *bp++ = htonl(volnamesz); 165 memcpy(bp, volname, volnamesz); 166 if (padsz > 0) 167 memset((void *)bp + volnamesz, 0, padsz); 168 169 trace_afs_make_vl_call(call); 170 afs_make_call(&vc->ac, call, GFP_KERNEL); 171 return (struct afs_vldb_entry *)afs_wait_for_call_to_complete(call, &vc->ac); 172 } 173 174 /* 175 * Deliver reply data to a VL.GetAddrsU call. 176 * 177 * GetAddrsU(IN ListAddrByAttributes *inaddr, 178 * OUT afsUUID *uuidp1, 179 * OUT uint32_t *uniquifier, 180 * OUT uint32_t *nentries, 181 * OUT bulkaddrs *blkaddrs); 182 */ 183 static int afs_deliver_vl_get_addrs_u(struct afs_call *call) 184 { 185 struct afs_addr_list *alist; 186 __be32 *bp; 187 u32 uniquifier, nentries, count; 188 int i, ret; 189 190 _enter("{%u,%zu/%u}", 191 call->unmarshall, iov_iter_count(call->_iter), call->count); 192 193 switch (call->unmarshall) { 194 case 0: 195 afs_extract_to_buf(call, 196 sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); 197 call->unmarshall++; 198 199 /* Extract the returned uuid, uniquifier, nentries and 200 * blkaddrs size */ 201 /* Fall through */ 202 case 1: 203 ret = afs_extract_data(call, true); 204 if (ret < 0) 205 return ret; 206 207 bp = call->buffer + sizeof(struct afs_uuid__xdr); 208 uniquifier = ntohl(*bp++); 209 nentries = ntohl(*bp++); 210 count = ntohl(*bp); 211 212 nentries = min(nentries, count); 213 alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); 214 if (!alist) 215 return -ENOMEM; 216 alist->version = uniquifier; 217 call->reply[0] = alist; 218 call->count = count; 219 call->count2 = nentries; 220 call->unmarshall++; 221 222 more_entries: 223 count = min(call->count, 4U); 224 afs_extract_to_buf(call, count * sizeof(__be32)); 225 226 /* Fall through - and extract entries */ 227 case 2: 228 ret = afs_extract_data(call, call->count > 4); 229 if (ret < 0) 230 return ret; 231 232 alist = call->reply[0]; 233 bp = call->buffer; 234 count = min(call->count, 4U); 235 for (i = 0; i < count; i++) 236 if (alist->nr_addrs < call->count2) 237 afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); 238 239 call->count -= count; 240 if (call->count > 0) 241 goto more_entries; 242 call->unmarshall++; 243 break; 244 } 245 246 _leave(" = 0 [done]"); 247 return 0; 248 } 249 250 static void afs_vl_get_addrs_u_destructor(struct afs_call *call) 251 { 252 afs_put_server(call->net, (struct afs_server *)call->reply[0]); 253 kfree(call->reply[1]); 254 return afs_flat_call_destructor(call); 255 } 256 257 /* 258 * VL.GetAddrsU operation type. 259 */ 260 static const struct afs_call_type afs_RXVLGetAddrsU = { 261 .name = "VL.GetAddrsU", 262 .op = afs_VL_GetAddrsU, 263 .deliver = afs_deliver_vl_get_addrs_u, 264 .destructor = afs_vl_get_addrs_u_destructor, 265 }; 266 267 /* 268 * Dispatch an operation to get the addresses for a server, where the server is 269 * nominated by UUID. 270 */ 271 struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc, 272 const uuid_t *uuid) 273 { 274 struct afs_ListAddrByAttributes__xdr *r; 275 const struct afs_uuid *u = (const struct afs_uuid *)uuid; 276 struct afs_call *call; 277 struct afs_net *net = vc->cell->net; 278 __be32 *bp; 279 int i; 280 281 _enter(""); 282 283 call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU, 284 sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr), 285 sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); 286 if (!call) 287 return ERR_PTR(-ENOMEM); 288 289 call->key = vc->key; 290 call->reply[0] = NULL; 291 call->ret_reply0 = true; 292 293 /* Marshall the parameters */ 294 bp = call->request; 295 *bp++ = htonl(VLGETADDRSU); 296 r = (struct afs_ListAddrByAttributes__xdr *)bp; 297 r->Mask = htonl(AFS_VLADDR_UUID); 298 r->ipaddr = 0; 299 r->index = 0; 300 r->spare = 0; 301 r->uuid.time_low = u->time_low; 302 r->uuid.time_mid = htonl(ntohs(u->time_mid)); 303 r->uuid.time_hi_and_version = htonl(ntohs(u->time_hi_and_version)); 304 r->uuid.clock_seq_hi_and_reserved = htonl(u->clock_seq_hi_and_reserved); 305 r->uuid.clock_seq_low = htonl(u->clock_seq_low); 306 for (i = 0; i < 6; i++) 307 r->uuid.node[i] = htonl(u->node[i]); 308 309 trace_afs_make_vl_call(call); 310 afs_make_call(&vc->ac, call, GFP_KERNEL); 311 return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac); 312 } 313 314 /* 315 * Deliver reply data to an VL.GetCapabilities operation. 316 */ 317 static int afs_deliver_vl_get_capabilities(struct afs_call *call) 318 { 319 u32 count; 320 int ret; 321 322 _enter("{%u,%zu/%u}", 323 call->unmarshall, iov_iter_count(call->_iter), call->count); 324 325 switch (call->unmarshall) { 326 case 0: 327 afs_extract_to_tmp(call); 328 call->unmarshall++; 329 330 /* Fall through - and extract the capabilities word count */ 331 case 1: 332 ret = afs_extract_data(call, true); 333 if (ret < 0) 334 return ret; 335 336 count = ntohl(call->tmp); 337 call->count = count; 338 call->count2 = count; 339 340 call->unmarshall++; 341 afs_extract_discard(call, count * sizeof(__be32)); 342 343 /* Fall through - and extract capabilities words */ 344 case 2: 345 ret = afs_extract_data(call, false); 346 if (ret < 0) 347 return ret; 348 349 /* TODO: Examine capabilities */ 350 351 call->unmarshall++; 352 break; 353 } 354 355 _leave(" = 0 [done]"); 356 return 0; 357 } 358 359 static void afs_destroy_vl_get_capabilities(struct afs_call *call) 360 { 361 struct afs_vlserver *server = call->reply[0]; 362 363 afs_put_vlserver(call->net, server); 364 afs_flat_call_destructor(call); 365 } 366 367 /* 368 * VL.GetCapabilities operation type 369 */ 370 static const struct afs_call_type afs_RXVLGetCapabilities = { 371 .name = "VL.GetCapabilities", 372 .op = afs_VL_GetCapabilities, 373 .deliver = afs_deliver_vl_get_capabilities, 374 .done = afs_vlserver_probe_result, 375 .destructor = afs_destroy_vl_get_capabilities, 376 }; 377 378 /* 379 * Probe a volume server for the capabilities that it supports. This can 380 * return up to 196 words. 381 * 382 * We use this to probe for service upgrade to determine what the server at the 383 * other end supports. 384 */ 385 struct afs_call *afs_vl_get_capabilities(struct afs_net *net, 386 struct afs_addr_cursor *ac, 387 struct key *key, 388 struct afs_vlserver *server, 389 unsigned int server_index) 390 { 391 struct afs_call *call; 392 __be32 *bp; 393 394 _enter(""); 395 396 call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4); 397 if (!call) 398 return ERR_PTR(-ENOMEM); 399 400 call->key = key; 401 call->reply[0] = afs_get_vlserver(server); 402 call->reply[1] = (void *)(long)server_index; 403 call->upgrade = true; 404 call->want_reply_time = true; 405 call->async = true; 406 407 /* marshall the parameters */ 408 bp = call->request; 409 *bp++ = htonl(VLGETCAPABILITIES); 410 411 /* Can't take a ref on server */ 412 trace_afs_make_vl_call(call); 413 afs_make_call(ac, call, GFP_KERNEL); 414 return call; 415 } 416 417 /* 418 * Deliver reply data to a YFSVL.GetEndpoints call. 419 * 420 * GetEndpoints(IN yfsServerAttributes *attr, 421 * OUT opr_uuid *uuid, 422 * OUT afs_int32 *uniquifier, 423 * OUT endpoints *fsEndpoints, 424 * OUT endpoints *volEndpoints) 425 */ 426 static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) 427 { 428 struct afs_addr_list *alist; 429 __be32 *bp; 430 u32 uniquifier, size; 431 int ret; 432 433 _enter("{%u,%zu,%u}", 434 call->unmarshall, iov_iter_count(call->_iter), call->count2); 435 436 switch (call->unmarshall) { 437 case 0: 438 afs_extract_to_buf(call, sizeof(uuid_t) + 3 * sizeof(__be32)); 439 call->unmarshall = 1; 440 441 /* Extract the returned uuid, uniquifier, fsEndpoints count and 442 * either the first fsEndpoint type or the volEndpoints 443 * count if there are no fsEndpoints. */ 444 /* Fall through */ 445 case 1: 446 ret = afs_extract_data(call, true); 447 if (ret < 0) 448 return ret; 449 450 bp = call->buffer + sizeof(uuid_t); 451 uniquifier = ntohl(*bp++); 452 call->count = ntohl(*bp++); 453 call->count2 = ntohl(*bp); /* Type or next count */ 454 455 if (call->count > YFS_MAXENDPOINTS) 456 return afs_protocol_error(call, -EBADMSG, 457 afs_eproto_yvl_fsendpt_num); 458 459 alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); 460 if (!alist) 461 return -ENOMEM; 462 alist->version = uniquifier; 463 call->reply[0] = alist; 464 465 if (call->count == 0) 466 goto extract_volendpoints; 467 468 next_fsendpoint: 469 switch (call->count2) { 470 case YFS_ENDPOINT_IPV4: 471 size = sizeof(__be32) * (1 + 1 + 1); 472 break; 473 case YFS_ENDPOINT_IPV6: 474 size = sizeof(__be32) * (1 + 4 + 1); 475 break; 476 default: 477 return afs_protocol_error(call, -EBADMSG, 478 afs_eproto_yvl_fsendpt_type); 479 } 480 481 size += sizeof(__be32); 482 afs_extract_to_buf(call, size); 483 call->unmarshall = 2; 484 485 /* Fall through - and extract fsEndpoints[] entries */ 486 case 2: 487 ret = afs_extract_data(call, true); 488 if (ret < 0) 489 return ret; 490 491 alist = call->reply[0]; 492 bp = call->buffer; 493 switch (call->count2) { 494 case YFS_ENDPOINT_IPV4: 495 if (ntohl(bp[0]) != sizeof(__be32) * 2) 496 return afs_protocol_error(call, -EBADMSG, 497 afs_eproto_yvl_fsendpt4_len); 498 afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); 499 bp += 3; 500 break; 501 case YFS_ENDPOINT_IPV6: 502 if (ntohl(bp[0]) != sizeof(__be32) * 5) 503 return afs_protocol_error(call, -EBADMSG, 504 afs_eproto_yvl_fsendpt6_len); 505 afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); 506 bp += 6; 507 break; 508 default: 509 return afs_protocol_error(call, -EBADMSG, 510 afs_eproto_yvl_fsendpt_type); 511 } 512 513 /* Got either the type of the next entry or the count of 514 * volEndpoints if no more fsEndpoints. 515 */ 516 call->count2 = ntohl(*bp++); 517 518 call->count--; 519 if (call->count > 0) 520 goto next_fsendpoint; 521 522 extract_volendpoints: 523 /* Extract the list of volEndpoints. */ 524 call->count = call->count2; 525 if (!call->count) 526 goto end; 527 if (call->count > YFS_MAXENDPOINTS) 528 return afs_protocol_error(call, -EBADMSG, 529 afs_eproto_yvl_vlendpt_type); 530 531 afs_extract_to_buf(call, 1 * sizeof(__be32)); 532 call->unmarshall = 3; 533 534 /* Extract the type of volEndpoints[0]. Normally we would 535 * extract the type of the next endpoint when we extract the 536 * data of the current one, but this is the first... 537 */ 538 /* Fall through */ 539 case 3: 540 ret = afs_extract_data(call, true); 541 if (ret < 0) 542 return ret; 543 544 bp = call->buffer; 545 546 next_volendpoint: 547 call->count2 = ntohl(*bp++); 548 switch (call->count2) { 549 case YFS_ENDPOINT_IPV4: 550 size = sizeof(__be32) * (1 + 1 + 1); 551 break; 552 case YFS_ENDPOINT_IPV6: 553 size = sizeof(__be32) * (1 + 4 + 1); 554 break; 555 default: 556 return afs_protocol_error(call, -EBADMSG, 557 afs_eproto_yvl_vlendpt_type); 558 } 559 560 if (call->count > 1) 561 size += sizeof(__be32); /* Get next type too */ 562 afs_extract_to_buf(call, size); 563 call->unmarshall = 4; 564 565 /* Fall through - and extract volEndpoints[] entries */ 566 case 4: 567 ret = afs_extract_data(call, true); 568 if (ret < 0) 569 return ret; 570 571 bp = call->buffer; 572 switch (call->count2) { 573 case YFS_ENDPOINT_IPV4: 574 if (ntohl(bp[0]) != sizeof(__be32) * 2) 575 return afs_protocol_error(call, -EBADMSG, 576 afs_eproto_yvl_vlendpt4_len); 577 bp += 3; 578 break; 579 case YFS_ENDPOINT_IPV6: 580 if (ntohl(bp[0]) != sizeof(__be32) * 5) 581 return afs_protocol_error(call, -EBADMSG, 582 afs_eproto_yvl_vlendpt6_len); 583 bp += 6; 584 break; 585 default: 586 return afs_protocol_error(call, -EBADMSG, 587 afs_eproto_yvl_vlendpt_type); 588 } 589 590 /* Got either the type of the next entry or the count of 591 * volEndpoints if no more fsEndpoints. 592 */ 593 call->count--; 594 if (call->count > 0) 595 goto next_volendpoint; 596 597 end: 598 afs_extract_discard(call, 0); 599 call->unmarshall = 5; 600 601 /* Fall through - Done */ 602 case 5: 603 ret = afs_extract_data(call, false); 604 if (ret < 0) 605 return ret; 606 call->unmarshall = 6; 607 608 case 6: 609 break; 610 } 611 612 alist = call->reply[0]; 613 _leave(" = 0 [done]"); 614 return 0; 615 } 616 617 /* 618 * YFSVL.GetEndpoints operation type. 619 */ 620 static const struct afs_call_type afs_YFSVLGetEndpoints = { 621 .name = "YFSVL.GetEndpoints", 622 .op = afs_YFSVL_GetEndpoints, 623 .deliver = afs_deliver_yfsvl_get_endpoints, 624 .destructor = afs_vl_get_addrs_u_destructor, 625 }; 626 627 /* 628 * Dispatch an operation to get the addresses for a server, where the server is 629 * nominated by UUID. 630 */ 631 struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc, 632 const uuid_t *uuid) 633 { 634 struct afs_call *call; 635 struct afs_net *net = vc->cell->net; 636 __be32 *bp; 637 638 _enter(""); 639 640 call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints, 641 sizeof(__be32) * 2 + sizeof(*uuid), 642 sizeof(struct in6_addr) + sizeof(__be32) * 3); 643 if (!call) 644 return ERR_PTR(-ENOMEM); 645 646 call->key = vc->key; 647 call->reply[0] = NULL; 648 call->ret_reply0 = true; 649 650 /* Marshall the parameters */ 651 bp = call->request; 652 *bp++ = htonl(YVLGETENDPOINTS); 653 *bp++ = htonl(YFS_SERVER_UUID); 654 memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ 655 656 trace_afs_make_vl_call(call); 657 afs_make_call(&vc->ac, call, GFP_KERNEL); 658 return (struct afs_addr_list *)afs_wait_for_call_to_complete(call, &vc->ac); 659 } 660