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_net *net, 132 struct afs_addr_cursor *ac, 133 struct key *key, 134 const char *volname, 135 int volnamesz) 136 { 137 struct afs_vldb_entry *entry; 138 struct afs_call *call; 139 size_t reqsz, padsz; 140 __be32 *bp; 141 142 _enter(""); 143 144 padsz = (4 - (volnamesz & 3)) & 3; 145 reqsz = 8 + volnamesz + padsz; 146 147 entry = kzalloc(sizeof(struct afs_vldb_entry), GFP_KERNEL); 148 if (!entry) 149 return ERR_PTR(-ENOMEM); 150 151 call = afs_alloc_flat_call(net, &afs_RXVLGetEntryByNameU, reqsz, 152 sizeof(struct afs_uvldbentry__xdr)); 153 if (!call) { 154 kfree(entry); 155 return ERR_PTR(-ENOMEM); 156 } 157 158 call->key = key; 159 call->reply[0] = entry; 160 call->ret_reply0 = true; 161 162 /* Marshall the parameters */ 163 bp = call->request; 164 *bp++ = htonl(VLGETENTRYBYNAMEU); 165 *bp++ = htonl(volnamesz); 166 memcpy(bp, volname, volnamesz); 167 if (padsz > 0) 168 memset((void *)bp + volnamesz, 0, padsz); 169 170 trace_afs_make_vl_call(call); 171 return (struct afs_vldb_entry *)afs_make_call(ac, call, GFP_KERNEL, false); 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}", call->unmarshall, call->offset, call->count); 191 192 again: 193 switch (call->unmarshall) { 194 case 0: 195 call->offset = 0; 196 call->unmarshall++; 197 198 /* Extract the returned uuid, uniquifier, nentries and blkaddrs size */ 199 case 1: 200 ret = afs_extract_data(call, call->buffer, 201 sizeof(struct afs_uuid__xdr) + 3 * sizeof(__be32), 202 true); 203 if (ret < 0) 204 return ret; 205 206 bp = call->buffer + sizeof(struct afs_uuid__xdr); 207 uniquifier = ntohl(*bp++); 208 nentries = ntohl(*bp++); 209 count = ntohl(*bp); 210 211 nentries = min(nentries, count); 212 alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); 213 if (!alist) 214 return -ENOMEM; 215 alist->version = uniquifier; 216 call->reply[0] = alist; 217 call->count = count; 218 call->count2 = nentries; 219 call->offset = 0; 220 call->unmarshall++; 221 222 /* Extract entries */ 223 case 2: 224 count = min(call->count, 4U); 225 ret = afs_extract_data(call, call->buffer, 226 count * sizeof(__be32), 227 call->count > 4); 228 if (ret < 0) 229 return ret; 230 231 alist = call->reply[0]; 232 bp = call->buffer; 233 for (i = 0; i < count; i++) 234 if (alist->nr_addrs < call->count2) 235 afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); 236 237 call->count -= count; 238 if (call->count > 0) 239 goto again; 240 call->offset = 0; 241 call->unmarshall++; 242 break; 243 } 244 245 _leave(" = 0 [done]"); 246 return 0; 247 } 248 249 static void afs_vl_get_addrs_u_destructor(struct afs_call *call) 250 { 251 afs_put_server(call->net, (struct afs_server *)call->reply[0]); 252 kfree(call->reply[1]); 253 return afs_flat_call_destructor(call); 254 } 255 256 /* 257 * VL.GetAddrsU operation type. 258 */ 259 static const struct afs_call_type afs_RXVLGetAddrsU = { 260 .name = "VL.GetAddrsU", 261 .op = afs_VL_GetAddrsU, 262 .deliver = afs_deliver_vl_get_addrs_u, 263 .destructor = afs_vl_get_addrs_u_destructor, 264 }; 265 266 /* 267 * Dispatch an operation to get the addresses for a server, where the server is 268 * nominated by UUID. 269 */ 270 struct afs_addr_list *afs_vl_get_addrs_u(struct afs_net *net, 271 struct afs_addr_cursor *ac, 272 struct key *key, 273 const uuid_t *uuid) 274 { 275 struct afs_ListAddrByAttributes__xdr *r; 276 const struct afs_uuid *u = (const struct afs_uuid *)uuid; 277 struct afs_call *call; 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 = 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 return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); 311 } 312 313 /* 314 * Deliver reply data to an VL.GetCapabilities operation. 315 */ 316 static int afs_deliver_vl_get_capabilities(struct afs_call *call) 317 { 318 u32 count; 319 int ret; 320 321 _enter("{%u,%zu/%u}", call->unmarshall, call->offset, call->count); 322 323 again: 324 switch (call->unmarshall) { 325 case 0: 326 call->offset = 0; 327 call->unmarshall++; 328 329 /* Extract the capabilities word count */ 330 case 1: 331 ret = afs_extract_data(call, &call->tmp, 332 1 * sizeof(__be32), 333 true); 334 if (ret < 0) 335 return ret; 336 337 count = ntohl(call->tmp); 338 339 call->count = count; 340 call->count2 = count; 341 call->offset = 0; 342 call->unmarshall++; 343 344 /* Extract capabilities words */ 345 case 2: 346 count = min(call->count, 16U); 347 ret = afs_extract_data(call, call->buffer, 348 count * sizeof(__be32), 349 call->count > 16); 350 if (ret < 0) 351 return ret; 352 353 /* TODO: Examine capabilities */ 354 355 call->count -= count; 356 if (call->count > 0) 357 goto again; 358 call->offset = 0; 359 call->unmarshall++; 360 break; 361 } 362 363 call->reply[0] = (void *)(unsigned long)call->service_id; 364 365 _leave(" = 0 [done]"); 366 return 0; 367 } 368 369 /* 370 * VL.GetCapabilities operation type 371 */ 372 static const struct afs_call_type afs_RXVLGetCapabilities = { 373 .name = "VL.GetCapabilities", 374 .op = afs_VL_GetCapabilities, 375 .deliver = afs_deliver_vl_get_capabilities, 376 .destructor = afs_flat_call_destructor, 377 }; 378 379 /* 380 * Probe a fileserver for the capabilities that it supports. This can 381 * return up to 196 words. 382 * 383 * We use this to probe for service upgrade to determine what the server at the 384 * other end supports. 385 */ 386 int afs_vl_get_capabilities(struct afs_net *net, 387 struct afs_addr_cursor *ac, 388 struct key *key) 389 { 390 struct afs_call *call; 391 __be32 *bp; 392 393 _enter(""); 394 395 call = afs_alloc_flat_call(net, &afs_RXVLGetCapabilities, 1 * 4, 16 * 4); 396 if (!call) 397 return -ENOMEM; 398 399 call->key = key; 400 call->upgrade = true; /* Let's see if this is a YFS server */ 401 call->reply[0] = (void *)VLGETCAPABILITIES; 402 call->ret_reply0 = true; 403 404 /* marshall the parameters */ 405 bp = call->request; 406 *bp++ = htonl(VLGETCAPABILITIES); 407 408 /* Can't take a ref on server */ 409 trace_afs_make_vl_call(call); 410 return afs_make_call(ac, call, GFP_KERNEL, false); 411 } 412 413 /* 414 * Deliver reply data to a YFSVL.GetEndpoints call. 415 * 416 * GetEndpoints(IN yfsServerAttributes *attr, 417 * OUT opr_uuid *uuid, 418 * OUT afs_int32 *uniquifier, 419 * OUT endpoints *fsEndpoints, 420 * OUT endpoints *volEndpoints) 421 */ 422 static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) 423 { 424 struct afs_addr_list *alist; 425 __be32 *bp; 426 u32 uniquifier, size; 427 int ret; 428 429 _enter("{%u,%zu/%u,%u}", call->unmarshall, call->offset, call->count, call->count2); 430 431 again: 432 switch (call->unmarshall) { 433 case 0: 434 call->offset = 0; 435 call->unmarshall = 1; 436 437 /* Extract the returned uuid, uniquifier, fsEndpoints count and 438 * either the first fsEndpoint type or the volEndpoints 439 * count if there are no fsEndpoints. */ 440 case 1: 441 ret = afs_extract_data(call, call->buffer, 442 sizeof(uuid_t) + 443 3 * sizeof(__be32), 444 true); 445 if (ret < 0) 446 return ret; 447 448 bp = call->buffer + sizeof(uuid_t); 449 uniquifier = ntohl(*bp++); 450 call->count = ntohl(*bp++); 451 call->count2 = ntohl(*bp); /* Type or next count */ 452 453 if (call->count > YFS_MAXENDPOINTS) 454 return afs_protocol_error(call, -EBADMSG); 455 456 alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); 457 if (!alist) 458 return -ENOMEM; 459 alist->version = uniquifier; 460 call->reply[0] = alist; 461 call->offset = 0; 462 463 if (call->count == 0) 464 goto extract_volendpoints; 465 466 call->unmarshall = 2; 467 468 /* Extract fsEndpoints[] entries */ 469 case 2: 470 switch (call->count2) { 471 case YFS_ENDPOINT_IPV4: 472 size = sizeof(__be32) * (1 + 1 + 1); 473 break; 474 case YFS_ENDPOINT_IPV6: 475 size = sizeof(__be32) * (1 + 4 + 1); 476 break; 477 default: 478 return afs_protocol_error(call, -EBADMSG); 479 } 480 481 size += sizeof(__be32); 482 ret = afs_extract_data(call, call->buffer, size, true); 483 if (ret < 0) 484 return ret; 485 486 alist = call->reply[0]; 487 bp = call->buffer; 488 switch (call->count2) { 489 case YFS_ENDPOINT_IPV4: 490 if (ntohl(bp[0]) != sizeof(__be32) * 2) 491 return afs_protocol_error(call, -EBADMSG); 492 afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); 493 bp += 3; 494 break; 495 case YFS_ENDPOINT_IPV6: 496 if (ntohl(bp[0]) != sizeof(__be32) * 5) 497 return afs_protocol_error(call, -EBADMSG); 498 afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); 499 bp += 6; 500 break; 501 default: 502 return afs_protocol_error(call, -EBADMSG); 503 } 504 505 /* Got either the type of the next entry or the count of 506 * volEndpoints if no more fsEndpoints. 507 */ 508 call->count2 = ntohl(*bp++); 509 510 call->offset = 0; 511 call->count--; 512 if (call->count > 0) 513 goto again; 514 515 extract_volendpoints: 516 /* Extract the list of volEndpoints. */ 517 call->count = call->count2; 518 if (!call->count) 519 goto end; 520 if (call->count > YFS_MAXENDPOINTS) 521 return afs_protocol_error(call, -EBADMSG); 522 523 call->unmarshall = 3; 524 525 /* Extract the type of volEndpoints[0]. Normally we would 526 * extract the type of the next endpoint when we extract the 527 * data of the current one, but this is the first... 528 */ 529 case 3: 530 ret = afs_extract_data(call, call->buffer, sizeof(__be32), true); 531 if (ret < 0) 532 return ret; 533 534 bp = call->buffer; 535 call->count2 = ntohl(*bp++); 536 call->offset = 0; 537 call->unmarshall = 4; 538 539 /* Extract volEndpoints[] entries */ 540 case 4: 541 switch (call->count2) { 542 case YFS_ENDPOINT_IPV4: 543 size = sizeof(__be32) * (1 + 1 + 1); 544 break; 545 case YFS_ENDPOINT_IPV6: 546 size = sizeof(__be32) * (1 + 4 + 1); 547 break; 548 default: 549 return afs_protocol_error(call, -EBADMSG); 550 } 551 552 if (call->count > 1) 553 size += sizeof(__be32); 554 ret = afs_extract_data(call, call->buffer, size, true); 555 if (ret < 0) 556 return ret; 557 558 bp = call->buffer; 559 switch (call->count2) { 560 case YFS_ENDPOINT_IPV4: 561 if (ntohl(bp[0]) != sizeof(__be32) * 2) 562 return afs_protocol_error(call, -EBADMSG); 563 bp += 3; 564 break; 565 case YFS_ENDPOINT_IPV6: 566 if (ntohl(bp[0]) != sizeof(__be32) * 5) 567 return afs_protocol_error(call, -EBADMSG); 568 bp += 6; 569 break; 570 default: 571 return afs_protocol_error(call, -EBADMSG); 572 } 573 574 /* Got either the type of the next entry or the count of 575 * volEndpoints if no more fsEndpoints. 576 */ 577 call->offset = 0; 578 call->count--; 579 if (call->count > 0) { 580 call->count2 = ntohl(*bp++); 581 goto again; 582 } 583 584 end: 585 call->unmarshall = 5; 586 587 /* Done */ 588 case 5: 589 ret = afs_extract_data(call, call->buffer, 0, false); 590 if (ret < 0) 591 return ret; 592 call->unmarshall = 6; 593 594 case 6: 595 break; 596 } 597 598 alist = call->reply[0]; 599 600 /* Start with IPv6 if available. */ 601 if (alist->nr_ipv4 < alist->nr_addrs) 602 alist->index = alist->nr_ipv4; 603 604 _leave(" = 0 [done]"); 605 return 0; 606 } 607 608 /* 609 * YFSVL.GetEndpoints operation type. 610 */ 611 static const struct afs_call_type afs_YFSVLGetEndpoints = { 612 .name = "YFSVL.GetEndpoints", 613 .op = afs_YFSVL_GetEndpoints, 614 .deliver = afs_deliver_yfsvl_get_endpoints, 615 .destructor = afs_vl_get_addrs_u_destructor, 616 }; 617 618 /* 619 * Dispatch an operation to get the addresses for a server, where the server is 620 * nominated by UUID. 621 */ 622 struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_net *net, 623 struct afs_addr_cursor *ac, 624 struct key *key, 625 const uuid_t *uuid) 626 { 627 struct afs_call *call; 628 __be32 *bp; 629 630 _enter(""); 631 632 call = afs_alloc_flat_call(net, &afs_YFSVLGetEndpoints, 633 sizeof(__be32) * 2 + sizeof(*uuid), 634 sizeof(struct in6_addr) + sizeof(__be32) * 3); 635 if (!call) 636 return ERR_PTR(-ENOMEM); 637 638 call->key = key; 639 call->reply[0] = NULL; 640 call->ret_reply0 = true; 641 642 /* Marshall the parameters */ 643 bp = call->request; 644 *bp++ = htonl(YVLGETENDPOINTS); 645 *bp++ = htonl(YFS_SERVER_UUID); 646 memcpy(bp, uuid, sizeof(*uuid)); /* Type opr_uuid */ 647 648 trace_afs_make_vl_call(call); 649 return (struct afs_addr_list *)afs_make_call(ac, call, GFP_KERNEL, false); 650 } 651