+/*
+ * Build hash lists of net addresses and hang them off the mount point.
+ * Called by ufs_mount() to set up the lists of export addresses.
+ */
+ufs_hang_addrlist(mp, argp)
+ struct mount *mp;
+ struct ufs_args *argp;
+{
+ register struct netcred *np;
+ register struct radix_node_head *rnh;
+ register int i;
+ struct radix_node *rn;
+ struct ufsmount *ump;
+ struct sockaddr *saddr, *smask = 0;
+ struct domain *dom;
+ int error;
+
+ if (argp->slen == 0) {
+ if (mp->mnt_flag & MNT_DEFEXPORTED)
+ return (EPERM);
+ np = &ump->um_defexported;
+ np->netc_exflags = argp->exflags;
+ np->netc_anon = argp->anon;
+ np->netc_anon.cr_ref = 1;
+ mp->mnt_flag |= MNT_DEFEXPORTED;
+ return (0);
+ }
+ i = sizeof(struct netcred) + argp->slen + argp->msklen;
+ np = (struct netcred *)malloc(i, M_NETADDR, M_WAITOK);
+ bzero((caddr_t)np, i);
+ saddr = (struct sockaddr *)(np + 1);
+ if (error = copyin(argp->saddr, (caddr_t)saddr, argp->slen))
+ goto out;
+ if (saddr->sa_len > argp->slen)
+ saddr->sa_len = argp->slen;
+ if (argp->msklen) {
+ smask = (struct sockaddr *)((caddr_t)saddr + argp->slen);
+ if (error = copyin(argp->saddr, (caddr_t)smask, argp->msklen))
+ goto out;
+ if (smask->sa_len > argp->msklen)
+ smask->sa_len = argp->msklen;
+ }
+ ump = VFSTOUFS(mp);
+ i = saddr->sa_family;
+ if ((rnh = ump->um_rtable[i]) == 0) {
+ /*
+ * Seems silly to initialize every AF when most are not
+ * used, do so on demand here
+ */
+ for (dom = domains; dom; dom = dom->dom_next)
+ if (dom->dom_family == i && dom->dom_rtattach) {
+ dom->dom_rtattach((void **)&ump->um_rtable[i],
+ dom->dom_rtoffset);
+ break;
+ }
+ if ((rnh = ump->um_rtable[i]) == 0) {
+ error = ENOBUFS;
+ goto out;
+ }
+ }
+ rn = (*rnh->rnh_add)((caddr_t)saddr, (caddr_t)smask, rnh->rnh_treetop,
+ np->netc_rnodes);
+ if (rn == 0 || np != (struct netcred *)rn) { /* already exists */
+ error = EPERM;
+ goto out;
+ }
+ np->netc_exflags = argp->exflags;
+ np->netc_anon = argp->anon;
+ np->netc_anon.cr_ref = 1;
+ return (0);
+out:
+ free(np, M_NETADDR);
+ return (error);
+}
+
+/* ARGSUSED */
+static int
+ufs_free_netcred(rn, w)
+ struct radix_node *rn;
+ caddr_t w;
+{
+ free((caddr_t)rn, M_NETADDR);
+}
+