153
166
rv = getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups);
154
if (rv == -1 && ngroups >= 100) {
155
groups = malloc(sizeof(gid_t)*ngroups);
167
if (rv == -1 && ngroups >= groups_len) {
168
more_groups = realloc(groups, sizeof(gid_t)*ngroups);
172
groups = more_groups;
173
groups_len = ngroups;
159
174
rv = getgrouplist(pw->pw_name, pw->pw_gid,
160
175
groups, &ngroups);
163
179
qword_printuint(f, uid);
164
qword_printuint(f, time(0)+30*60);
180
qword_printuint(f, time(0) + DEFAULT_TTL);
166
182
qword_printuint(f, ngroups);
167
183
for (i=0; i<ngroups; i++)
328
341
return me->mnt_dir;
331
static void nfsd_fh(FILE *f)
344
/* True iff e1 is a child of e2 and e2 has crossmnt set: */
345
static bool subexport(struct exportent *e1, struct exportent *e2)
334
* domain fsidtype fsid
335
* interpret fsid, find export point and options, and write:
336
* domain fsidtype fsid expiry path
347
char *p1 = e1->e_path, *p2 = e2->e_path;
350
return e2->e_flags & NFSEXP_CROSSMOUNT
351
&& strncmp(p1, p2, l2) == 0
342
unsigned int dev, major=0, minor=0;
343
unsigned int inode=0;
357
/* We could use a union for this, but it would be more
358
* complicated; why bother? */
362
unsigned int fsidnum;
367
int parse_fsid(int fsidtype, int fsidlen, char *fsid, struct parsed_fsid *parsed)
344
370
unsigned long long inode64;
345
unsigned int fsidnum=0;
347
struct exportent *found = NULL;
348
struct addrinfo *ai = NULL;
349
char *found_path = NULL;
356
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
359
xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
363
dom = malloc(strlen(cp));
366
if (qword_get(&cp, dom, strlen(cp)) <= 0)
368
if (qword_get_int(&cp, &fsidtype) != 0)
370
if (fsidtype < 0 || fsidtype > 7)
371
goto out; /* unknown type */
372
if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
372
parsed->fsidtype = fsidtype;
374
373
switch(fsidtype) {
375
374
case FSID_DEV: /* 4 bytes: 2 major, 2 minor, 4 inode */
376
375
if (fsidlen != 8)
378
377
memcpy(&dev, fsid, 4);
379
memcpy(&inode, fsid+4, 4);
380
major = ntohl(dev)>>16;
381
minor = ntohl(dev) & 0xFFFF;
378
memcpy(&parsed->inode, fsid+4, 4);
379
parsed->major = ntohl(dev)>>16;
380
parsed->minor = ntohl(dev) & 0xFFFF;
384
383
case FSID_NUM: /* 4 bytes - fsid */
385
384
if (fsidlen != 4)
387
memcpy(&fsidnum, fsid, 4);
386
memcpy(&parsed->fsidnum, fsid, 4);
390
389
case FSID_MAJOR_MINOR: /* 12 bytes: 4 major, 4 minor, 4 inode
392
391
* an historical accident
394
393
if (fsidlen != 12)
396
memcpy(&dev, fsid, 4); major = ntohl(dev);
397
memcpy(&dev, fsid+4, 4); minor = ntohl(dev);
398
memcpy(&inode, fsid+8, 4);
395
memcpy(&dev, fsid, 4);
396
parsed->major = ntohl(dev);
397
memcpy(&dev, fsid+4, 4);
398
parsed->minor = ntohl(dev);
399
memcpy(&parsed->inode, fsid+8, 4);
401
402
case FSID_ENCODE_DEV: /* 8 bytes: 4 byte packed device number, 4 inode */
403
404
* no-one outside this host has any business interpreting it
405
406
if (fsidlen != 8)
407
408
memcpy(&dev, fsid, 4);
408
memcpy(&inode, fsid+4, 4);
409
major = (dev & 0xfff00) >> 8;
410
minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
409
memcpy(&parsed->inode, fsid+4, 4);
410
parsed->major = (dev & 0xfff00) >> 8;
411
parsed->minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
413
414
case FSID_UUID4_INUM: /* 4 byte inode number and 4 byte uuid */
414
415
if (fsidlen != 8)
416
memcpy(&inode, fsid, 4);
417
memcpy(&parsed->inode, fsid, 4);
419
parsed->fhuuid = fsid+4;
420
421
case FSID_UUID8: /* 8 byte uuid */
421
422
if (fsidlen != 8)
425
parsed->fhuuid = fsid;
426
427
case FSID_UUID16: /* 16 byte uuid */
427
428
if (fsidlen != 16)
430
parsed->uuidlen = 16;
431
parsed->fhuuid = fsid;
432
433
case FSID_UUID16_INUM: /* 8 byte inode number and 16 byte uuid */
433
434
if (fsidlen != 24)
435
436
memcpy(&inode64, fsid, 8);
437
parsed->inode = inode64;
438
parsed->uuidlen = 16;
439
parsed->fhuuid = fsid+8;
445
static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
451
if (stat(path, &stb) != 0)
453
if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode))
456
switch (parsed->fsidtype) {
458
case FSID_MAJOR_MINOR:
459
case FSID_ENCODE_DEV:
460
if (stb.st_ino != parsed->inode)
462
if (parsed->major != major(stb.st_dev) ||
463
parsed->minor != minor(stb.st_dev))
467
if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
468
exp->m_export.e_fsid != parsed->fsidnum))
471
case FSID_UUID4_INUM:
472
case FSID_UUID16_INUM:
473
if (stb.st_ino != parsed->inode)
478
if (!is_mountpoint(path))
481
if (exp->m_export.e_uuid)
482
get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
485
uuid_by_path(path, type, parsed->uuidlen, u);
487
if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
490
if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
494
/* Well, unreachable, actually: */
498
static void nfsd_fh(FILE *f)
501
* domain fsidtype fsid
502
* interpret fsid, find export point and options, and write:
503
* domain fsidtype fsid expiry path
510
struct parsed_fsid parsed;
511
struct exportent *found = NULL;
512
struct addrinfo *ai = NULL;
513
char *found_path = NULL;
518
if (readline(fileno(f), &lbuf, &lbuflen) != 1)
521
xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
525
dom = malloc(strlen(cp));
528
if (qword_get(&cp, dom, strlen(cp)) <= 0)
530
if (qword_get_int(&cp, &fsidtype) != 0)
532
if (fsidtype < 0 || fsidtype > 7)
533
goto out; /* unknown type */
534
if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
536
if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
481
575
exp->m_export.e_mountpoint:
482
576
exp->m_export.e_path))
484
if (stat(path, &stb) != 0)
486
if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
491
case FSID_MAJOR_MINOR:
492
case FSID_ENCODE_DEV:
493
if (stb.st_ino != inode)
495
if (major != major(stb.st_dev) ||
496
minor != minor(stb.st_dev))
500
if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
501
exp->m_export.e_fsid != fsidnum))
504
case FSID_UUID4_INUM:
505
case FSID_UUID16_INUM:
506
if (stb.st_ino != inode)
511
if (!is_mountpoint(path))
514
if (exp->m_export.e_uuid)
515
get_uuid(exp->m_export.e_uuid,
519
uuid_by_path(path, type, uuidlen, u);
521
if (memcmp(u, fhuuid, uuidlen) == 0)
524
if (memcmp(u, fhuuid, uuidlen) != 0)
579
if (!match_fsid(&parsed, exp, path))
528
581
if (use_ipaddr) {
529
582
if (ai == NULL) {
530
583
struct addrinfo *tmp;
537
590
if (!client_check(exp->m_client, ai))
540
/* It's a match !! */
593
if (!found || subexport(&exp->m_export, found)) {
542
594
found = &exp->m_export;
543
596
found_path = strdup(path);
544
597
if (found_path == NULL)
546
} else if (strcmp(found->e_path, exp->m_export.e_path)!= 0)
599
} else if (strcmp(found->e_path, exp->m_export.e_path)
600
&& !subexport(found, &exp->m_export))
548
602
xlog(L_WARNING, "%s and %s have same filehandle for %s, using first",
549
603
found_path, path, dom);
645
699
qword_print(f, domain);
646
700
qword_print(f, path);
647
qword_printint(f, time(0)+30*60);
649
702
int different_fs = strcmp(path, exp->e_path) != 0;
650
703
int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
705
qword_printuint(f, time(0) + exp->e_ttl);
652
706
qword_printint(f, exp->e_flags & flag_mask);
653
707
qword_printint(f, exp->e_anonuid);
654
708
qword_printint(f, exp->e_anongid);
813
868
char *cache_name;
814
869
void (*cache_handle)(FILE *f);
871
char vbuf[RPC_CHAN_BUF_SIZE];
816
872
} cachelist[] = {
817
{ "auth.unix.ip", auth_unix_ip, NULL},
818
{ "auth.unix.gid", auth_unix_gid, NULL},
819
{ "nfsd.export", nfsd_export, NULL},
820
{ "nfsd.fh", nfsd_fh, NULL},
873
{ "auth.unix.ip", auth_unix_ip, NULL, ""},
874
{ "auth.unix.gid", auth_unix_gid, NULL, ""},
875
{ "nfsd.export", nfsd_export, NULL, ""},
876
{ "nfsd.fh", nfsd_fh, NULL, ""},
877
{ NULL, NULL, NULL, ""}
824
880
extern int manage_gids;