📄 mountd.c
字号:
} *naddrp = (char *)NULL; if (debug) fprintf(stderr, "got host %s\n", hp->h_name); return (0);}/* * Free up an exports list component */voidfree_exp(ep) struct exportlist *ep;{ if (ep->ex_defdir) { free_host(ep->ex_defdir->dp_hosts); free((caddr_t)ep->ex_defdir); } if (ep->ex_fsdir) free(ep->ex_fsdir); free_dir(ep->ex_dirl); free((caddr_t)ep);}/* * Free hosts. */voidfree_host(hp) struct hostlist *hp;{ struct hostlist *hp2; while (hp) { hp2 = hp; hp = hp->ht_next; free((caddr_t)hp2); }}struct hostlist *get_ht(){ struct hostlist *hp; hp = (struct hostlist *)malloc(sizeof (struct hostlist)); if (hp == (struct hostlist *)NULL) out_of_mem(); hp->ht_next = (struct hostlist *)NULL; return (hp);}#ifdef ISO/* * Translate an iso address. */get_isoaddr(cp, grp) char *cp; struct grouplist *grp;{ struct iso_addr *isop; struct sockaddr_iso *isoaddr; if (grp->gr_type != GT_NULL) return (1); if ((isop = iso_addr(cp)) == NULL) { syslog(LOG_ERR, "iso_addr failed, ignored"); return (1); } isoaddr = (struct sockaddr_iso *) malloc(sizeof (struct sockaddr_iso)); if (isoaddr == (struct sockaddr_iso *)NULL) out_of_mem(); bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso)); bcopy((caddr_t)isop, (caddr_t)&isoaddr->siso_addr, sizeof (struct iso_addr)); isoaddr->siso_len = sizeof (struct sockaddr_iso); isoaddr->siso_family = AF_ISO; grp->gr_type = GT_ISO; grp->gr_ptr.gt_isoaddr = isoaddr; return (0);}#endif /* ISO *//* * Out of memory, fatal */voidout_of_mem(){ syslog(LOG_ERR, "Out of memory"); exit(2);}/* * Do the mount syscall with the update flag to push the export info into * the kernel. */intdo_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb) struct exportlist *ep; struct grouplist *grp; int exflags; struct ucred *anoncrp; char *dirp; int dirplen; struct statfs *fsb;{ char *cp = (char *)NULL; u_long **addrp; int done; char savedc = '\0'; struct sockaddr_in sin, imask; union { struct ufs_args ua; struct iso_args ia; struct mfs_args ma; } args; u_long net; args.ua.fspec = 0; args.ua.export.ex_flags = exflags; args.ua.export.ex_anon = *anoncrp; bzero((char *)&sin, sizeof(sin)); bzero((char *)&imask, sizeof(imask)); sin.sin_family = AF_INET; sin.sin_len = sizeof(sin); imask.sin_family = AF_INET; imask.sin_len = sizeof(sin); if (grp->gr_type == GT_HOST) addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list; else addrp = (u_long **)NULL; done = FALSE; while (!done) { switch (grp->gr_type) { case GT_HOST: if (addrp) { sin.sin_addr.s_addr = **addrp; args.ua.export.ex_addrlen = sizeof(sin); } else args.ua.export.ex_addrlen = 0; args.ua.export.ex_addr = (struct sockaddr *)&sin; args.ua.export.ex_masklen = 0; break; case GT_NET: if (grp->gr_ptr.gt_net.nt_mask) imask.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_mask; else { net = ntohl(grp->gr_ptr.gt_net.nt_net); if (IN_CLASSA(net)) imask.sin_addr.s_addr = inet_addr("255.0.0.0"); else if (IN_CLASSB(net)) imask.sin_addr.s_addr = inet_addr("255.255.0.0"); else imask.sin_addr.s_addr = inet_addr("255.255.255.0"); grp->gr_ptr.gt_net.nt_mask = imask.sin_addr.s_addr; } sin.sin_addr.s_addr = grp->gr_ptr.gt_net.nt_net; args.ua.export.ex_addr = (struct sockaddr *)&sin; args.ua.export.ex_addrlen = sizeof (sin); args.ua.export.ex_mask = (struct sockaddr *)&imask; args.ua.export.ex_masklen = sizeof (imask); break;#ifdef ISO case GT_ISO: args.ua.export.ex_addr = (struct sockaddr *)grp->gr_ptr.gt_isoaddr; args.ua.export.ex_addrlen = sizeof(struct sockaddr_iso); args.ua.export.ex_masklen = 0; break;#endif /* ISO */ default: syslog(LOG_ERR, "Bad grouptype"); if (cp) *cp = savedc; return (1); }; /* * XXX: * Maybe I should just use the fsb->f_mntonname path instead * of looping back up the dirp to the mount point?? * Also, needs to know how to export all types of local * exportable file systems and not just MOUNT_UFS. */ while (mount(fsb->f_type, dirp, fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) { if (cp) *cp-- = savedc; else cp = dirp + dirplen - 1; if (errno == EPERM) { syslog(LOG_ERR, "Can't change attributes for %s.\n", dirp); return (1); } if (opt_flags & OP_ALLDIRS) { syslog(LOG_ERR, "Not root dir"); return (1); } /* back up over the last component */ while (*cp == '/' && cp > dirp) cp--; while (*(cp - 1) != '/' && cp > dirp) cp--; if (cp == dirp) { if (debug) fprintf(stderr,"mnt unsucc\n"); syslog(LOG_ERR, "Can't export %s", dirp); return (1); } savedc = *cp; *cp = '\0'; } if (addrp) { ++addrp; if (*addrp == (u_long *)NULL) done = TRUE; } else done = TRUE; } if (cp) *cp = savedc; return (0);}/* * Translate a net address. */intget_net(cp, net, maskflg) char *cp; struct netmsk *net; int maskflg;{ struct netent *np; long netaddr; struct in_addr inetaddr, inetaddr2; char *name; if (np = getnetbyname(cp)) inetaddr = inet_makeaddr(np->n_net, 0); else if (isdigit(*cp)) { if ((netaddr = inet_network(cp)) == -1) return (1); inetaddr = inet_makeaddr(netaddr, 0); /* * Due to arbritrary subnet masks, you don't know how many * bits to shift the address to make it into a network, * however you do know how to make a network address into * a host with host == 0 and then compare them. * (What a pest) */ if (!maskflg) { setnetent(0); while (np = getnetent()) { inetaddr2 = inet_makeaddr(np->n_net, 0); if (inetaddr2.s_addr == inetaddr.s_addr) break; } endnetent(); } } else return (1); if (maskflg) net->nt_mask = inetaddr.s_addr; else { if (np) name = np->n_name; else name = inet_ntoa(inetaddr); net->nt_name = (char *)malloc(strlen(name) + 1); if (net->nt_name == (char *)NULL) out_of_mem(); strcpy(net->nt_name, name); net->nt_net = inetaddr.s_addr; } return (0);}/* * Parse out the next white space separated field */voidnextfield(cp, endcp) char **cp; char **endcp;{ char *p; p = *cp; while (*p == ' ' || *p == '\t') p++; if (*p == '\n' || *p == '\0') *cp = *endcp = p; else { *cp = p++; while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') p++; *endcp = p; }}/* * Get an exports file line. Skip over blank lines and handle line * continuations. */intget_line(){ char *p, *cp; int len; int totlen, cont_line; /* * Loop around ignoring blank lines and getting all continuation lines. */ p = line; totlen = 0; do { if (fgets(p, LINESIZ - totlen, exp_file) == NULL) return (0); len = strlen(p); cp = p + len - 1; cont_line = 0; while (cp >= p && (*cp == ' ' || *cp == '\t' || *cp == '\n' || *cp == '\\')) { if (*cp == '\\') cont_line = 1; cp--; len--; } *++cp = '\0'; if (len > 0) { totlen += len; if (totlen >= LINESIZ) { syslog(LOG_ERR, "Exports line too long"); exit(2); } p = cp; } } while (totlen == 0 || cont_line); return (1);}/* * Parse a description of a credential. */voidparsecred(namelist, cr) char *namelist; struct ucred *cr;{ char *name; int cnt; char *names; struct passwd *pw; struct group *gr; int ngroups, groups[NGROUPS + 1]; /* * Set up the unpriviledged user. */ cr->cr_ref = 1; cr->cr_uid = -2; cr->cr_groups[0] = -2; cr->cr_ngroups = 1; /* * Get the user's password table entry. */ names = strsep(&namelist, " \t\n"); name = strsep(&names, ":"); if (isdigit(*name) || *name == '-') pw = getpwuid(atoi(name)); else pw = getpwnam(name); /* * Credentials specified as those of a user. */ if (names == NULL) { if (pw == NULL) { syslog(LOG_ERR, "Unknown user: %s", name); return; } cr->cr_uid = pw->pw_uid; ngroups = NGROUPS + 1; if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) syslog(LOG_ERR, "Too many groups"); /* * Convert from int's to gid_t's and compress out duplicate */ cr->cr_ngroups = ngroups - 1; cr->cr_groups[0] = groups[0]; for (cnt = 2; cnt < ngroups; cnt++) cr->cr_groups[cnt - 1] = groups[cnt]; return; } /* * Explicit credential specified as a colon separated list: * uid:gid:gid:... */ if (pw != NULL) cr->cr_uid = pw->pw_uid; else if (isdigit(*name) || *name == '-') cr->cr_uid = atoi(name); else { syslog(LOG_ERR, "Unknown user: %s", name); return; } cr->cr_ngroups = 0; while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) { name = strsep(&names, ":"); if (isdigit(*name) || *name == '-') { cr->cr_groups[cr->cr_ngroups++] = atoi(name); } else { if ((gr = getgrnam(name)) == NULL) { syslog(LOG_ERR, "Unknown group: %s", name); continue; } cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; } } if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS) syslog(LOG_ERR, "Too many groups");}#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)/* * Routines that maintain the remote mounttab */voidget_mountlist(){ struct mountlist *mlp, **mlpp; char *eos, *dirp; int len; char str[STRSIZ]; FILE *mlfile; if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) { syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST); return; } mlpp = &mlhead; while (fgets(str, STRSIZ, mlfile) != NULL) { if ((dirp = index(str, '\t')) == NULL && (dirp = index(str, ' ')) == NULL) continue; mlp = (struct mountlist *)malloc(sizeof (*mlp)); len = dirp-str; if (len > RPCMNT_NAMELEN) len = RPCMNT_NAMELEN; bcopy(str, mlp->ml_host, len); mlp->ml_host[len] = '\0'; while (*dirp == '\t' || *dirp == ' ') dirp++; if ((eos = index(dirp, '\t')) == NULL && (eos = index(dirp, ' ')) == NULL && (eos = index(dirp, '\n')) == NULL) len = strlen(dirp); else len = eos-dirp; if (len > RPCMNT_PATHLEN) len = RPCMNT_PATHLEN; bcopy(dirp, mlp->ml_dirp, len); mlp->ml_dirp[len] = '\0'; mlp->ml_next = (struct mountlist *)NULL; *mlpp = mlp; mlpp = &mlp->ml_next; } fclose(mlfile);}voiddel_mlist(hostp, dirp) char *hostp, *dirp;{ struct mountlist *mlp, **mlpp; struct mountlist *mlp2; FILE *mlfile; int fnd = 0; mlpp = &mlhead; mlp = mlhead; while (mlp) { if (!strcmp(mlp->ml_host, hostp) && (!dirp || !strcmp(mlp->ml_dirp, dirp))) { fnd = 1; mlp2 = mlp; *mlpp = mlp = mlp->ml_next; free((caddr_t)mlp2); } else { mlpp = &mlp->ml_next; mlp = mlp->ml_next; } } if (fnd) { if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { syslog(LOG_ERR,"Can't update %s", _PATH_RMOUNTLIST); return; } mlp = mlhead; while (mlp) { fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); mlp = mlp->ml_next; } fclose(mlfile); }}voidadd_mlist(hostp, dirp) char *hostp, *dirp;{ struct mountlist *mlp, **mlpp; FILE *mlfile; mlpp = &mlhead; mlp = mlhead; while (mlp) { if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) return; mlpp = &mlp->ml_next; mlp = mlp->ml_next; } mlp = (struct mountlist *)malloc(sizeof (*mlp)); strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); mlp->ml_host[RPCMNT_NAMELEN] = '\0'; strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; mlp->ml_next = (struct mountlist *)NULL; *mlpp = mlp; if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { syslog(LOG_ERR, "Can't update %s", _PATH_RMOUNTLIST); return; } fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); fclose(mlfile);}/* * This function is called via. SIGTERM when the system is going down. * It sends a broadcast RPCMNT_UMNTALL. */voidsend_umntall(){ (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); exit(0);}intumntall_each(resultsp, raddr) caddr_t resultsp; struct sockaddr_in *raddr;{ return (1);}/* * Free up a group list. */voidfree_grp(grp) struct grouplist *grp;{ char **addrp; if (grp->gr_type == GT_HOST) { if (grp->gr_ptr.gt_hostent->h_name) { addrp = grp->gr_ptr.gt_hostent->h_addr_list; while (addrp && *addrp) free(*addrp++); free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list); free(grp->gr_ptr.gt_hostent->h_name); } free((caddr_t)grp->gr_ptr.gt_hostent); } else if (grp->gr_type == GT_NET) { if (grp->gr_ptr.gt_net.nt_name) free(grp->gr_ptr.gt_net.nt_name); }#ifdef ISO else if (grp->gr_type == GT_ISO) free((caddr_t)grp->gr_ptr.gt_isoaddr);#endif free((caddr_t)grp);}#ifdef DEBUGvoidSYSLOG(int pri, const char *fmt, ...){ va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap);}#endif /* DEBUG *//* * Check options for consistency. */intcheck_options(dp) struct dirlist *dp;{ if (dp == (struct dirlist *)NULL) return (1); if ((opt_flags & (OP_MAPROOT | OP_MAPALL)) == (OP_MAPROOT | OP_MAPALL) || (opt_flags & (OP_MAPROOT | OP_KERB)) == (OP_MAPROOT | OP_KERB) || (opt_flags & (OP_MAPALL | OP_KERB)) == (OP_MAPALL | OP_KERB)) { syslog(LOG_ERR, "-mapall, -maproot and -kerb mutually exclusive"); return (1); } if ((opt_flags & OP_MASK) && (opt_flags & OP_NET) == 0) { syslog(LOG_ERR, "-mask requires -net"); return (1); } if ((opt_flags & (OP_NET | OP_ISO)) == (OP_NET | OP_ISO)) { syslog(LOG_ERR, "-net and -iso mutually exclusive"); return (1); } if ((opt_flags & OP_ALLDIRS) && dp->dp_left) { syslog(LOG_ERR, "-alldir has multiple directories"); return (1); } return (0);}/* * Check an absolute directory path for any symbolic links. Return true * if no symbolic links are found. */intcheck_dirpath(dirp) char *dirp;{ char *cp; int ret = 1; struct stat sb; cp = dirp + 1; while (*cp && ret) { if (*cp == '/') { *cp = '\0'; if (lstat(dirp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) ret = 0; *cp = '/'; } cp++; } if (lstat(dirp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) ret = 0; return (ret);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -