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; 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 for (i = 0; i < nr_servers; i++) { 59 struct afs_uuid__xdr *xdr; 60 struct afs_uuid *uuid; 61 int j; 62 63 tmp = ntohl(uvldb->serverFlags[i]); 64 if (tmp & AFS_VLSF_DONTUSE || 65 (new_only && !(tmp & AFS_VLSF_NEWREPSITE))) 66 continue; 67 if (tmp & AFS_VLSF_RWVOL) 68 entry->fs_mask[i] |= AFS_VOL_VTM_RW; 69 if (tmp & AFS_VLSF_ROVOL) 70 entry->fs_mask[i] |= AFS_VOL_VTM_RO; 71 if (tmp & AFS_VLSF_BACKVOL) 72 entry->fs_mask[i] |= AFS_VOL_VTM_BAK; 73 if (!entry->fs_mask[i]) 74 continue; 75 76 xdr = &uvldb->serverNumber[i]; 77 uuid = (struct afs_uuid *)&entry->fs_server[i]; 78 uuid->time_low = xdr->time_low; 79 uuid->time_mid = htons(ntohl(xdr->time_mid)); 80 uuid->time_hi_and_version = htons(ntohl(xdr->time_hi_and_version)); 81 uuid->clock_seq_hi_and_reserved = (u8)ntohl(xdr->clock_seq_hi_and_reserved); 82 uuid->clock_seq_low = (u8)ntohl(xdr->clock_seq_low); 83 for (j = 0; j < 6; j++) 84 uuid->node[j] = (u8)ntohl(xdr->node[j]); 85 86 entry->nr_servers++; 87 } 88 89 for (i = 0; i < AFS_MAXTYPES; i++) 90 entry->vid[i] = ntohl(uvldb->volumeId[i]); 91 92 tmp = ntohl(uvldb->flags); 93 if (tmp & AFS_VLF_RWEXISTS) 94 __set_bit(AFS_VLDB_HAS_RW, &entry->flags); 95 if (tmp & AFS_VLF_ROEXISTS) 96 __set_bit(AFS_VLDB_HAS_RO, &entry->flags); 97 if (tmp & AFS_VLF_BACKEXISTS) 98 __set_bit(AFS_VLDB_HAS_BAK, &entry->flags); 99 100 if (!(tmp & (AFS_VLF_RWEXISTS | AFS_VLF_ROEXISTS | AFS_VLF_BACKEXISTS))) { 101 entry->error = -ENOMEDIUM; 102 __set_bit(AFS_VLDB_QUERY_ERROR, &entry->flags); 103 } 104 105 __set_bit(AFS_VLDB_QUERY_VALID, &entry->flags); 106 _leave(" = 0 [done]"); 107 return 0; 108 } 109 110 static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call) 111 { 112 kfree(call->reply[0]); 113 afs_flat_call_destructor(call); 114 } 115 116 /* 117 * VL.GetEntryByNameU operation type. 118 */ 119 static const struct afs_call_type afs_RXVLGetEntryByNameU = { 120 .name = "VL.GetEntryByNameU", 121 .op = afs_VL_GetEntryByNameU, 122 .deliver = afs_deliver_vl_get_entry_by_name_u, 123 .destructor = afs_destroy_vl_get_entry_by_name_u, 124 }; 125 126 /* 127 * Dispatch a get volume entry by name or ID operation (uuid variant). If the 128 * volname is a decimal number then it's a volume ID not a volume name. 129 */ 130 struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_net *net, 131 struct afs_addr_cursor *ac, 132 struct key *key, 133 const char *volname, 134 int volnamesz) 135 { 136 struct afs_vldb_entry *entry; 137 struct afs_call *call; 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 = 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 return (struct afs_vldb_entry *)afs_make_call(ac, call, GFP_KERNEL, false); 171 } 172 173 /* 174 * Deliver reply data to a VL.GetAddrsU call. 175 * 176 * GetAddrsU(IN ListAddrByAttributes *inaddr, 177 * OUT afsUUID *uuidp1, 178 * OUT uint32_t *uniquifier, 179 * OUT uint32_t *nentries, 180 * OUT bulkaddrs *blkaddrs); 181 */ 182 static int afs_deliver_vl_get_addrs_u(struct afs_call *call) 183 { 184 struct afs_addr_list *alist; 185 __be32 *bp; 186 u32 uniquifier, nentries, count; 187 int i, ret; 188 189 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); 190 191 again: 192 switch (call->unmarshall) { 193 case 0: 194 call->offset = 0; 195 call->unmarshall++; 196 197 /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */ 198 case 1: 199 ret = afs_extract_data(call, call->buffer, 200 sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32), 201 true); 202 if (ret < 0) 203 return ret; 204 205 bp = call->buffer + sizeof(struct afs_uuid__xdr); 206 uniquifier = ntohl(*bp++); 207 nentries = ntohl(*bp++); 208 count = ntohl(*bp); 209 210 nentries = min(nentries, count); 211 alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); 212 if (!alist) 213 return -ENOMEM; 214 alist->version = uniquifier; 215 call->reply[0] = alist; 216 call->count = count; 217 call->count2 = nentries; 218 call->offset = 0; 219 call->unmarshall++; 220 221 /* Extract entries */ 222 case 2: 223 count = min(call->count, 4U); 224 ret = afs_extract_data(call, call->buffer, 225 count * sizeof(__be32), 226 call->count > 4); 227 if (ret < 0) 228 return ret; 229 230 alist = call->reply[0]; 231 bp = call->buffer; 232 for (i = 0; i < count; i++) 233 if (alist->nr_addrs < call->count2) 234 afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); 235 236 call->count -= count; 237 if (call->count > 0) 238 goto again; 239 call->offset = 0; 240 call->unmarshall++; 241 break; 242 } 243 244 _leave(" = 0 [done]"); 245 return 0; 246 } 247 248 static void afs_vl_get_addrs_u_destructor(struct afs_call *call) 249 { 250 afs_put_server(call->net, (struct afs_server *)call->reply[0]); 251 kfree(call->reply[1]); 252 return afs_flat_call_destructor(call); 253 } 254 255 /* 256 * VL.GetAddrsU operation type. 257 */ 258 static const struct afs_call_type afs_RXVLGetAddrsU = { 259 .name = "VL.GetAddrsU", 260 .op = afs_VL_GetAddrsU, 261 .deliver = afs_deliver_vl_get_addrs_u, 262 .destructor = afs_vl_get_addrs_u_destructor, 263 }; 264 265 /* 266 * Dispatch an operation to get the addresses for a server, where the server is 267 * nominated by UUID. 268 */ 269 struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net, 270 struct afs_addr_cursor *ac, 271 struct key *key, 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 __be32 *bp; 278 int i; 279 280 _enter(""); 281 282 call = afs_alloc_flat_call(net, &afs_RXVLGetAddrsU, 283 sizeof(__be32) + sizeof(struct afs_ListAddrByAttributes__xdr), 284 sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32)); 285 if (!call) 286 return ERR_PTR(-ENOMEM); 287 288 call->key = key; 289 call->reply[0] = NULL; 290 call->ret_reply0 = true; 291 292 /* Marshall the parameters */ 293 bp = call->request; 294 *bp++ = htonl(VLGETADDRSU); 295 r = (struct afs_ListAddrByAttributes__xdr *)bp; 296 r->Mask = htonl(AFS_VLADDR_UUID); 297 r->ipaddr = 0; 298 r->index = 0; 299 r->spare = 0; 300 r->uuid.time_low = u->time_low; 301 r->uuid.time_mid = htonl(ntohs(u->time_mid)); 302 r->uuid.time_hi_and_version = htonl(ntohs(u->time_hi_and_version)); 303 r->uuid.clock_seq_hi_and_reserved = htonl(u->clock_seq_hi_and_reserved); 304 r->uuid.clock_seq_low = htonl(u->clock_seq_low); 305 for (i = 0; i < 6; i++) 306 r->uuid.node[i] = ntohl(u->node[i]); 307 308 trace_afs_make_vl_call(call); 309 return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); 310 } 311 312 /* 313 * Deliver reply data to an VL.GetCapabilities operation. 314 */ 315 static int afs_deliver_vl_get_capabilities(struct afs_call *call) 316 { 317 u32 count; 318 int ret; 319 320 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); 321 322 again: 323 switch (call->unmarshall) { 324 case 0: 325 call->offset = 0; 326 call->unmarshall++; 327 328 /* Extract the capabilities word count */ 329 case 1: 330 ret = afs_extract_data(call, &call->tmp, 331 1 * sizeof(__be32), 332 true); 333 if (ret < 0) 334 return ret; 335 336 count = ntohl(call->tmp); 337 338 call->count = count; 339 call->count2 = count; 340 call->offset = 0; 341 call->unmarshall++; 342 343 /* Extract capabilities words */ 344 case 2: 345 count = min(call->count, 16U); 346 ret = afs_extract_data(call, call->buffer, 347 count * sizeof(__be32), 348 call->count > 16); 349 if (ret < 0) 350 return ret; 351 352 /* TODO: Examine capabilities */ 353 354 call->count -= count; 355 if (call->count > 0) 356 goto again; 357 call->offset = 0; 358 call->unmarshall++; 359 break; 360 } 361 362 call->reply[0] = (void *)(unsigned long)call->service_id; 363 364 _leave(" = 0 [done]"); 365 return 0; 366 } 367 368 /* 369 * VL.GetCapabilities operation type 370 */ 371 static const struct afs_call_type afs_RXVLGetCapabilities = { 372 .name = "VL.GetCapabilities", 373 .op = afs_VL_GetCapabilities, 374 .deliver = afs_deliver_vl_get_capabilities, 375 .destructor = afs_flat_call_destructor, 376 }; 377 378 /* 379 * Probe a fileserver 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 int afs_vl_get_capabilities(struct afs_net *net, 386 struct afs_addr_cursor *ac, 387 struct key *key) 388 { 389 struct afs_call *call; 390 __be32 *bp; 391 392 _enter(""); 393 394 call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4); 395 if (!call) 396 return -ENOMEM; 397 398 call->key = key; 399 call->upgrade = true; /* Let's see if this is a YFS server */ 400 call->reply[0] = (void *)VLGETCAPABILITIES; 401 call->ret_reply0 = true; 402 403 /* marshall the parameters */ 404 bp = call->request; 405 *bp++ = htonl(VLGETCAPABILITIES); 406 407 /* Can't take a ref on server */ 408 trace_afs_make_vl_call(call); 409 return afs_make_call(ac, call, GFP_KERNEL, false); 410 } 411 412 /* 413 * Deliver reply data to a YFSVL.GetEndpoints call. 414 * 415 * GetEndpoints(IN yfsServerAttributes *attr, 416 * OUT opr_uuid *uuid, 417 * OUT afs_int32 *uniquifier, 418 * OUT endpoints *fsEndpoints, 419 * OUT endpoints *volEndpoints) 420 */ 421 static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) 422 { 423 struct afs_addr_list *alist; 424 __be32 *bp; 425 u32 uniquifier, size; 426 int ret; 427 428 _enter("{%u,%zu/%u,%u}", call->unmarshall, call->offset, call->count, call->count2); 429 430 again: 431 switch (call->unmarshall) { 432 case 0: 433 call->offset = 0; 434 call->unmarshall = 1; 435 436 /* Extract the returned uuid, uniquifier, fsEndpoints count and 437 * either the first fsEndpoint type or the volEndpoints 438 * count if there are no fsEndpoints. */ 439 case 1: 440 ret = afs_extract_data(call, call->buffer, 441 sizeof(uuid_t) + 442 3 * sizeof(__be32), 443 true); 444 if (ret < 0) 445 return ret; 446 447 bp = call->buffer + sizeof(uuid_t); 448 uniquifier = ntohl(*bp++); 449 call->count = ntohl(*bp++); 450 call->count2 = ntohl(*bp); /* Type or next count */ 451 452 if (call->count > YFS_MAXENDPOINTS) 453 return -EBADMSG; 454 455 alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); 456 if (!alist) 457 return -ENOMEM; 458 alist->version = uniquifier; 459 call->reply[0] = alist; 460 call->offset = 0; 461 462 if (call->count == 0) 463 goto extract_volendpoints; 464 465 call->unmarshall = 2; 466 467 /* Extract fsEndpoints[] entries */ 468 case 2: 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 -EBADMSG; 478 } 479 480 size += sizeof(__be32); 481 ret = afs_extract_data(call, call->buffer, size, true); 482 if (ret < 0) 483 return ret; 484 485 alist = call->reply[0]; 486 bp = call->buffer; 487 switch (call->count2) { 488 case YFS_ENDPOINT_IPV4: 489 if (ntohl(bp[0]) != sizeof(__be32) * 2) 490 return -EBADMSG; 491 afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); 492 bp += 3; 493 break; 494 case YFS_ENDPOINT_IPV6: 495 if (ntohl(bp[0]) != sizeof(__be32) * 5) 496 return -EBADMSG; 497 afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); 498 bp += 6; 499 break; 500 default: 501 return -EBADMSG; 502 } 503 504 /* Got either the type of the next entry or the count of 505 * volEndpoints if no more fsEndpoints. 506 */ 507 call->count2 = htonl(*bp++); 508 509 call->offset = 0; 510 call->count--; 511 if (call->count > 0) 512 goto again; 513 514 extract_volendpoints: 515 /* Extract the list of volEndpoints. */ 516 call->count = call->count2; 517 if (!call->count) 518 goto end; 519 if (call->count > YFS_MAXENDPOINTS) 520 return -EBADMSG; 521 522 call->unmarshall = 3; 523 524 /* Extract the type of volEndpoints[0]. Normally we would 525 * extract the type of the next endpoint when we extract the 526 * data of the current one, but this is the first... 527 */ 528 case 3: 529 ret = afs_extract_data(call, call->buffer, sizeof(__be32), true); 530 if (ret < 0) 531 return ret; 532 533 bp = call->buffer; 534 call->count2 = htonl(*bp++); 535 call->offset = 0; 536 call->unmarshall = 4; 537 538 /* Extract volEndpoints[] entries */ 539 case 4: 540 switch (call->count2) { 541 case YFS_ENDPOINT_IPV4: 542 size = sizeof(__be32) * (1 + 1 + 1); 543 break; 544 case YFS_ENDPOINT_IPV6: 545 size = sizeof(__be32) * (1 + 4 + 1); 546 break; 547 default: 548 return -EBADMSG; 549 } 550 551 if (call->count > 1) 552 size += sizeof(__be32); 553 ret = afs_extract_data(call, call->buffer, size, true); 554 if (ret < 0) 555 return ret; 556 557 bp = call->buffer; 558 switch (call->count2) { 559 case YFS_ENDPOINT_IPV4: 560 if (ntohl(bp[0]) != sizeof(__be32) * 2) 561 return -EBADMSG; 562 bp += 3; 563 break; 564 case YFS_ENDPOINT_IPV6: 565 if (ntohl(bp[0]) != sizeof(__be32) * 5) 566 return -EBADMSG; 567 bp += 6; 568 break; 569 default: 570 return -EBADMSG; 571 } 572 573 /* Got either the type of the next entry or the count of 574 * volEndpoints if no more fsEndpoints. 575 */ 576 call->offset = 0; 577 call->count--; 578 if (call->count > 0) { 579 call->count2 = htonl(*bp++); 580 goto again; 581 } 582 583 end: 584 call->unmarshall = 5; 585 586 /* Done */ 587 case 5: 588 ret = afs_extract_data(call, call->buffer, 0, false); 589 if (ret < 0) 590 return ret; 591 call->unmarshall = 6; 592 593 case 6: 594 break; 595 } 596 597 alist = call->reply[0]; 598 599 /* Start with IPv6 if available. */ 600 if (alist->nr_ipv4 < alist->nr_addrs) 601 alist->index = alist->nr_ipv4; 602 603 _leave(" = 0 [done]"); 604 return 0; 605 } 606 607 /* 608 * YFSVL.GetEndpoints operation type. 609 */ 610 static const struct afs_call_type afs_YFSVLGetEndpoints = { 611 .name = "YFSVL.GetEndpoints", 612 .op = afs_YFSVL_GetEndpoints, 613 .deliver = afs_deliver_yfsvl_get_endpoints, 614 .destructor = afs_vl_get_addrs_u_destructor, 615 }; 616 617 /* 618 * Dispatch an operation to get the addresses for a server, where the server is 619 * nominated by UUID. 620 */ 621 struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net, 622 struct afs_addr_cursor *ac, 623 struct key *key, 624 const uuid_t *uuid) 625 { 626 struct afs_call *call; 627 __be32 *bp; 628 629 _enter(""); 630 631 call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints, 632 sizeof(__be32) * 2 + sizeof(*uuid), 633 sizeof(struct in6_addr) + sizeof(__be32) * 3); 634 if (!call) 635 return ERR_PTR(-ENOMEM); 636 637 call->key = key; 638 call->reply[0] = NULL; 639 call->ret_reply0 = true; 640 641 /* Marshall the parameters */ 642 bp = call->request; 643 *bp++ = htonl(YVLGETENDPOINTS); 644 *bp++ = htonl(YFS_SERVER_UUID); 645 memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ 646 647 trace_afs_make_vl_call(call); 648 return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); 649 } 650