~ubuntu-branches/ubuntu/saucy/nfs-utils/saucy-proposed

« back to all changes in this revision

Viewing changes to utils/mountd/cache.c

  • Committer: Bazaar Package Importer
  • Author(s): Luk Claes
  • Date: 2011-07-09 16:28:32 UTC
  • mfrom: (1.2.20 upstream)
  • mto: (71.1.1 ubuntu)
  • mto: This revision was merged to the branch mainline in revision 41.
  • Revision ID: james.westby@ubuntu.com-20110709162832-ovaehe77pm3hyy35
Tags: 1:1.2.4-1
* New upstream version
  - Fix host_reliable_addrinfo (Closes: #633155)
  - Allow multiple RPC listeners to share listener port number
  (Closes: #619877)
  - Add --enable-libmount-mount (Closes: #626478)
  - 12-svcgssd-document-n-option.patch applied upstream
  - Refresh 19-exports.man-Fix-comment-syntax.patch
  - 21-anticipate-RLIMIT_FSIZE.patch applied upstream
  - Add nfsidmap binary and manpage
  - Use autoreconf to avoid build failure

Show diffs side-by-side

added added

removed removed

Lines of Context:
64
64
 */
65
65
static int cache_export_ent(char *domain, struct exportent *exp, char *p);
66
66
 
 
67
#define INITIAL_MANAGED_GROUPS 100
67
68
 
68
69
char *lbuf  = NULL;
69
70
int lbuflen = 0;
114
115
 
115
116
        qword_print(f, "nfsd");
116
117
        qword_print(f, ipaddr);
117
 
        qword_printint(f, time(0)+30*60);
 
118
        qword_printuint(f, time(0) + DEFAULT_TTL);
118
119
        if (use_ipaddr)
119
120
                qword_print(f, ipaddr);
120
121
        else if (client)
134
135
         */
135
136
        uid_t uid;
136
137
        struct passwd *pw;
137
 
        gid_t glist[100], *groups = glist;
138
 
        int ngroups = 100;
 
138
        static gid_t *groups = NULL;
 
139
        static int groups_len = 0;
 
140
        gid_t *more_groups;
 
141
        int ngroups;
139
142
        int rv, i;
140
143
        char *cp;
141
144
 
 
145
        if (groups_len == 0) {
 
146
                groups = malloc(sizeof(gid_t) * INITIAL_MANAGED_GROUPS);
 
147
                if (!groups)
 
148
                        return;
 
149
 
 
150
                groups_len = INITIAL_MANAGED_GROUPS;
 
151
        }
 
152
 
 
153
        ngroups = groups_len;
 
154
 
142
155
        if (readline(fileno(f), &lbuf, &lbuflen) != 1)
143
156
                return;
144
157
 
151
164
                rv = -1;
152
165
        else {
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);
156
 
                        if (!groups)
 
167
                if (rv == -1 && ngroups >= groups_len) {
 
168
                        more_groups = realloc(groups, sizeof(gid_t)*ngroups);
 
169
                        if (!more_groups)
157
170
                                rv = -1;
158
 
                        else
 
171
                        else {
 
172
                                groups = more_groups;
 
173
                                groups_len = ngroups;
159
174
                                rv = getgrouplist(pw->pw_name, pw->pw_gid,
160
175
                                                  groups, &ngroups);
 
176
                        }
161
177
                }
162
178
        }
163
179
        qword_printuint(f, uid);
164
 
        qword_printuint(f, time(0)+30*60);
 
180
        qword_printuint(f, time(0) + DEFAULT_TTL);
165
181
        if (rv >= 0) {
166
182
                qword_printuint(f, ngroups);
167
183
                for (i=0; i<ngroups; i++)
169
185
        } else
170
186
                qword_printuint(f, 0);
171
187
        qword_eol(f);
172
 
 
173
 
        if (groups != glist)
174
 
                free(groups);
175
188
}
176
189
 
177
190
#if USE_BLKID
328
341
        return me->mnt_dir;
329
342
}
330
343
 
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)
332
346
{
333
 
        /* request are:
334
 
         *  domain fsidtype fsid
335
 
         * interpret fsid, find export point and options, and write:
336
 
         *  domain fsidtype fsid expiry path
337
 
         */
338
 
        char *cp;
339
 
        char *dom;
 
347
        char *p1 = e1->e_path, *p2 = e2->e_path;
 
348
        int l2 = strlen(p2);
 
349
 
 
350
        return e2->e_flags & NFSEXP_CROSSMOUNT
 
351
               && strncmp(p1, p2, l2) == 0
 
352
               && p1[l2] == '/';
 
353
}
 
354
 
 
355
struct parsed_fsid {
340
356
        int fsidtype;
341
 
        int fsidlen;
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? */
 
359
        unsigned int inode;
 
360
        unsigned int minor;
 
361
        unsigned int major;
 
362
        unsigned int fsidnum;
 
363
        int uuidlen;
 
364
        char *fhuuid;
 
365
};
 
366
 
 
367
int parse_fsid(int fsidtype, int fsidlen, char *fsid, struct parsed_fsid *parsed)
 
368
{
 
369
        unsigned int dev;
344
370
        unsigned long long inode64;
345
 
        unsigned int fsidnum=0;
346
 
        char fsid[32];
347
 
        struct exportent *found = NULL;
348
 
        struct addrinfo *ai = NULL;
349
 
        char *found_path = NULL;
350
 
        nfs_export *exp;
351
 
        int i;
352
 
        int dev_missing = 0;
353
 
        int uuidlen = 0;
354
 
        char *fhuuid = NULL;
355
 
 
356
 
        if (readline(fileno(f), &lbuf, &lbuflen) != 1)
357
 
                return;
358
 
 
359
 
        xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
360
 
 
361
 
        cp = lbuf;
362
 
        
363
 
        dom = malloc(strlen(cp));
364
 
        if (dom == NULL)
365
 
                return;
366
 
        if (qword_get(&cp, dom, strlen(cp)) <= 0)
367
 
                goto out;
368
 
        if (qword_get_int(&cp, &fsidtype) != 0)
369
 
                goto out;
370
 
        if (fsidtype < 0 || fsidtype > 7)
371
 
                goto out; /* unknown type */
372
 
        if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
373
 
                goto out;
 
371
 
 
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)
377
 
                        goto out;
 
376
                        return -1;
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;
382
381
                break;
383
382
 
384
383
        case FSID_NUM: /* 4 bytes - fsid */
385
384
                if (fsidlen != 4)
386
 
                        goto out;
387
 
                memcpy(&fsidnum, fsid, 4);
 
385
                        return -1;
 
386
                memcpy(&parsed->fsidnum, fsid, 4);
388
387
                break;
389
388
 
390
389
        case FSID_MAJOR_MINOR: /* 12 bytes: 4 major, 4 minor, 4 inode 
392
391
                 * an historical accident
393
392
                 */
394
393
                if (fsidlen != 12)
395
 
                        goto out;
396
 
                memcpy(&dev, fsid, 4); major = ntohl(dev);
397
 
                memcpy(&dev, fsid+4, 4); minor = ntohl(dev);
398
 
                memcpy(&inode, fsid+8, 4);
 
394
                        return -1;
 
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);
399
400
                break;
400
401
 
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
404
405
                 */
405
406
                if (fsidlen != 8)
406
 
                        goto out;
 
407
                        return -1;
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);
411
412
                break;
412
413
 
413
414
        case FSID_UUID4_INUM: /* 4 byte inode number and 4 byte uuid */
414
415
                if (fsidlen != 8)
415
 
                        goto out;
416
 
                memcpy(&inode, fsid, 4);
417
 
                uuidlen = 4;
418
 
                fhuuid = fsid+4;
 
416
                        return -1;
 
417
                memcpy(&parsed->inode, fsid, 4);
 
418
                parsed->uuidlen = 4;
 
419
                parsed->fhuuid = fsid+4;
419
420
                break;
420
421
        case FSID_UUID8: /* 8 byte uuid */
421
422
                if (fsidlen != 8)
422
 
                        goto out;
423
 
                uuidlen = 8;
424
 
                fhuuid = fsid;
 
423
                        return -1;
 
424
                parsed->uuidlen = 8;
 
425
                parsed->fhuuid = fsid;
425
426
                break;
426
427
        case FSID_UUID16: /* 16 byte uuid */
427
428
                if (fsidlen != 16)
428
 
                        goto out;
429
 
                uuidlen = 16;
430
 
                fhuuid = fsid;
 
429
                        return -1;
 
430
                parsed->uuidlen = 16;
 
431
                parsed->fhuuid = fsid;
431
432
                break;
432
433
        case FSID_UUID16_INUM: /* 8 byte inode number and 16 byte uuid */
433
434
                if (fsidlen != 24)
434
 
                        goto out;
 
435
                        return -1;
435
436
                memcpy(&inode64, fsid, 8);
436
 
                inode = inode64;
437
 
                uuidlen = 16;
438
 
                fhuuid = fsid+8;
 
437
                parsed->inode = inode64;
 
438
                parsed->uuidlen = 16;
 
439
                parsed->fhuuid = fsid+8;
439
440
                break;
440
441
        }
 
442
        return 0;
 
443
}
 
444
 
 
445
static bool match_fsid(struct parsed_fsid *parsed, nfs_export *exp, char *path)
 
446
{
 
447
        struct stat stb;
 
448
        int type;
 
449
        char u[16];
 
450
 
 
451
        if (stat(path, &stb) != 0)
 
452
                return false;
 
453
        if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode))
 
454
                return false;
 
455
 
 
456
        switch (parsed->fsidtype) {
 
457
        case FSID_DEV:
 
458
        case FSID_MAJOR_MINOR:
 
459
        case FSID_ENCODE_DEV:
 
460
                if (stb.st_ino != parsed->inode)
 
461
                        return false;
 
462
                if (parsed->major != major(stb.st_dev) ||
 
463
                    parsed->minor != minor(stb.st_dev))
 
464
                        return false;
 
465
                return true;
 
466
        case FSID_NUM:
 
467
                if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
 
468
                     exp->m_export.e_fsid != parsed->fsidnum))
 
469
                        return false;
 
470
                return true;
 
471
        case FSID_UUID4_INUM:
 
472
        case FSID_UUID16_INUM:
 
473
                if (stb.st_ino != parsed->inode)
 
474
                        return false;
 
475
                goto check_uuid;
 
476
        case FSID_UUID8:
 
477
        case FSID_UUID16:
 
478
                if (!is_mountpoint(path))
 
479
                        return false;
 
480
        check_uuid:
 
481
                if (exp->m_export.e_uuid)
 
482
                        get_uuid(exp->m_export.e_uuid, parsed->uuidlen, u);
 
483
                else
 
484
                        for (type = 0;
 
485
                             uuid_by_path(path, type, parsed->uuidlen, u);
 
486
                             type++)
 
487
                                if (memcmp(u, parsed->fhuuid, parsed->uuidlen) == 0)
 
488
                                        return true;
 
489
 
 
490
                if (memcmp(u, parsed->fhuuid, parsed->uuidlen) != 0)
 
491
                        return false;
 
492
                return true;
 
493
        }
 
494
        /* Well, unreachable, actually: */
 
495
        return false;
 
496
}
 
497
 
 
498
static void nfsd_fh(FILE *f)
 
499
{
 
500
        /* request are:
 
501
         *  domain fsidtype fsid
 
502
         * interpret fsid, find export point and options, and write:
 
503
         *  domain fsidtype fsid expiry path
 
504
         */
 
505
        char *cp;
 
506
        char *dom;
 
507
        int fsidtype;
 
508
        int fsidlen;
 
509
        char fsid[32];
 
510
        struct parsed_fsid parsed;
 
511
        struct exportent *found = NULL;
 
512
        struct addrinfo *ai = NULL;
 
513
        char *found_path = NULL;
 
514
        nfs_export *exp;
 
515
        int i;
 
516
        int dev_missing = 0;
 
517
 
 
518
        if (readline(fileno(f), &lbuf, &lbuflen) != 1)
 
519
                return;
 
520
 
 
521
        xlog(D_CALL, "nfsd_fh: inbuf '%s'", lbuf);
 
522
 
 
523
        cp = lbuf;
 
524
 
 
525
        dom = malloc(strlen(cp));
 
526
        if (dom == NULL)
 
527
                return;
 
528
        if (qword_get(&cp, dom, strlen(cp)) <= 0)
 
529
                goto out;
 
530
        if (qword_get_int(&cp, &fsidtype) != 0)
 
531
                goto out;
 
532
        if (fsidtype < 0 || fsidtype > 7)
 
533
                goto out; /* unknown type */
 
534
        if ((fsidlen = qword_get(&cp, fsid, 32)) <= 0)
 
535
                goto out;
 
536
        if (parse_fsid(fsidtype, fsidlen, fsid, &parsed))
 
537
                goto out;
441
538
 
442
539
        auth_reload();
443
540
 
445
542
        for (i=0 ; i < MCL_MAXTYPES; i++) {
446
543
                nfs_export *next_exp;
447
544
                for (exp = exportlist[i].p_head; exp; exp = next_exp) {
448
 
                        struct stat stb;
449
 
                        char u[16];
450
545
                        char *path;
451
 
                        int type;
452
546
 
453
547
                        if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) {
454
548
                                static nfs_export *prev = NULL;
481
575
                                           exp->m_export.e_mountpoint:
482
576
                                           exp->m_export.e_path))
483
577
                                dev_missing ++;
484
 
                        if (stat(path, &stb) != 0)
485
 
                                continue;
486
 
                        if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) {
487
 
                                continue;
488
 
                        }
489
 
                        switch(fsidtype){
490
 
                        case FSID_DEV:
491
 
                        case FSID_MAJOR_MINOR:
492
 
                        case FSID_ENCODE_DEV:
493
 
                                if (stb.st_ino != inode)
494
 
                                        continue;
495
 
                                if (major != major(stb.st_dev) ||
496
 
                                    minor != minor(stb.st_dev))
497
 
                                        continue;
498
 
                                break;
499
 
                        case FSID_NUM:
500
 
                                if (((exp->m_export.e_flags & NFSEXP_FSID) == 0 ||
501
 
                                     exp->m_export.e_fsid != fsidnum))
502
 
                                        continue;
503
 
                                break;
504
 
                        case FSID_UUID4_INUM:
505
 
                        case FSID_UUID16_INUM:
506
 
                                if (stb.st_ino != inode)
507
 
                                        continue;
508
 
                                goto check_uuid;
509
 
                        case FSID_UUID8:
510
 
                        case FSID_UUID16:
511
 
                                if (!is_mountpoint(path))
512
 
                                        continue;
513
 
                        check_uuid:
514
 
                                if (exp->m_export.e_uuid)
515
 
                                        get_uuid(exp->m_export.e_uuid,
516
 
                                                 uuidlen, u);
517
 
                                else
518
 
                                        for (type = 0;
519
 
                                             uuid_by_path(path, type, uuidlen, u);
520
 
                                             type++)
521
 
                                                if (memcmp(u, fhuuid, uuidlen) == 0)
522
 
                                                        break;
523
578
 
524
 
                                if (memcmp(u, fhuuid, uuidlen) != 0)
525
 
                                        continue;
526
 
                                break;
527
 
                        }
 
579
                        if (!match_fsid(&parsed, exp, path))
 
580
                                continue;
528
581
                        if (use_ipaddr) {
529
582
                                if (ai == NULL) {
530
583
                                        struct addrinfo *tmp;
537
590
                                if (!client_check(exp->m_client, ai))
538
591
                                        continue;
539
592
                        }
540
 
                        /* It's a match !! */
541
 
                        if (!found) {
 
593
                        if (!found || subexport(&exp->m_export, found)) {
542
594
                                found = &exp->m_export;
 
595
                                free(found_path);
543
596
                                found_path = strdup(path);
544
597
                                if (found_path == NULL)
545
598
                                        goto out;
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))
547
601
                        {
548
602
                                xlog(L_WARNING, "%s and %s have same filehandle for %s, using first",
549
603
                                     found_path, path, dom);
644
698
{
645
699
        qword_print(f, domain);
646
700
        qword_print(f, path);
647
 
        qword_printint(f, time(0)+30*60);
648
701
        if (exp) {
649
702
                int different_fs = strcmp(path, exp->e_path) != 0;
650
703
                int flag_mask = different_fs ? ~NFSEXP_FSID : ~0;
651
704
 
 
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);
667
721
                        qword_print(f, "uuid");
668
722
                        qword_printhex(f, u, 16);
669
723
                }
670
 
        }
 
724
        } else
 
725
                qword_printuint(f, time(0) + DEFAULT_TTL);
671
726
        return qword_eol(f);
672
727
}
673
728
 
813
868
        char *cache_name;
814
869
        void (*cache_handle)(FILE *f);
815
870
        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},
821
 
        { NULL, NULL, 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, ""}
822
878
};
823
879
 
824
880
extern int manage_gids;
836
892
                        continue;
837
893
                sprintf(path, "/proc/net/rpc/%s/channel", cachelist[i].cache_name);
838
894
                cachelist[i].f = fopen(path, "r+");
 
895
                if (cachelist[i].f != NULL) {
 
896
                        setvbuf(cachelist[i].f, cachelist[i].vbuf, _IOLBF, 
 
897
                                RPC_CHAN_BUF_SIZE);
 
898
                }
839
899
        }
840
900
}
841
901
 
874
934
 
875
935
/*
876
936
 * Give IP->domain and domain+path->options to kernel
877
 
 * % echo nfsd $IP  $[now+30*60] $domain > /proc/net/rpc/auth.unix.ip/channel
878
 
 * % echo $domain $path $[now+30*60] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
 
937
 * % echo nfsd $IP  $[now+DEFAULT_TTL] $domain > /proc/net/rpc/auth.unix.ip/channel
 
938
 * % echo $domain $path $[now+DEFAULT_TTL] $options $anonuid $anongid $fsid > /proc/net/rpc/nfsd.export/channel
879
939
 */
880
940
 
881
941
static int cache_export_ent(char *domain, struct exportent *exp, char *path)
955
1015
        qword_print(f, "nfsd");
956
1016
        qword_print(f,
957
1017
                host_ntop(get_addrlist(exp->m_client, 0), buf, sizeof(buf)));
958
 
        qword_printint(f, time(0)+30*60);
 
1018
        qword_printuint(f, time(0) + exp->m_export.e_ttl);
959
1019
        qword_print(f, exp->m_client->m_hostname);
960
1020
        err = qword_eol(f);
961
1021