801 sip->next = NULL;
802 sip->prev = NULL;
803
804 rw_init(&sip->oldstate_lock, NULL, RW_DEFAULT, NULL);
805 /*
806 * This initial dummy entry is required to setup for insque/remque.
807 * It must be skipped over whenever the list is traversed.
808 */
809 oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
810 /* insque/remque require initial list entry to be self-terminated */
811 oldstate->next = oldstate;
812 oldstate->prev = oldstate;
813 sip->oldstate = oldstate;
814
815
816 sip->dss_npaths = dss_npaths;
817 sip->dss_paths = kmem_alloc(dss_npaths *
818 sizeof (rfs4_dss_path_t *), KM_SLEEP);
819
820 for (i = 0; i < dss_npaths; i++) {
821 /* CSTYLED */
822 sip->dss_paths[i] = rfs4_dss_newpath(nsrv4, sip, dss_paths[i], i);
823 }
824
825 mutex_enter(&nsrv4->servinst_lock);
826 if (nsrv4->nfs4_cur_servinst != NULL) {
827 /* add to linked list */
828 sip->prev = nsrv4->nfs4_cur_servinst;
829 nsrv4->nfs4_cur_servinst->next = sip;
830 }
831 if (start_grace)
832 rfs4_grace_start(sip);
833 /* make the new instance "current" */
834 nsrv4->nfs4_cur_servinst = sip;
835
836 mutex_exit(&nsrv4->servinst_lock);
837 }
838
839 /*
840 * In future, we might add a rfs4_servinst_destroy(sip) but, for now, destroy
841 * all instances directly.
842 */
843 void
844 rfs4_servinst_destroy_all(nfs4_srv_t *nsrv4)
845 {
846 rfs4_servinst_t *sip, *prev, *current;
847 #ifdef DEBUG
848 int n = 0;
849 #endif
850
851 mutex_enter(&nsrv4->servinst_lock);
852 ASSERT(nsrv4->nfs4_cur_servinst != NULL);
853 current = nsrv4->nfs4_cur_servinst;
854 nsrv4->nfs4_cur_servinst = NULL;
855 for (sip = current; sip != NULL; sip = prev) {
856 prev = sip->prev;
857 rw_destroy(&sip->rwlock);
858 if (sip->oldstate)
859 kmem_free(sip->oldstate, sizeof (rfs4_oldstate_t));
860 if (sip->dss_paths)
861 kmem_free(sip->dss_paths,
862 sip->dss_npaths * sizeof (rfs4_dss_path_t *));
863 kmem_free(sip, sizeof (rfs4_servinst_t));
864 #ifdef DEBUG
865 n++;
866 #endif
867 }
868 mutex_exit(&nsrv4->servinst_lock);
869 }
870
871 /*
872 * Assign the current server instance to a client_t.
873 * Should be called with cp->rc_dbe held.
874 */
875 void
876 rfs4_servinst_assign(nfs4_srv_t *nsrv4, rfs4_client_t *cp,
877 rfs4_servinst_t *sip)
878 {
879 ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
880
881 /*
882 * The lock ensures that if the current instance is in the process
920 {
921 int i;
922
923 for (i = 0; i < count; i++) {
924 if (nfsnum == flavor_list[i])
925 return (TRUE);
926 }
927 return (FALSE);
928 }
929
930 /*
931 * Used by rfs4_op_secinfo to get the security information from the
932 * export structure associated with the component.
933 */
934 /* ARGSUSED */
935 static nfsstat4
936 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
937 {
938 int error, different_export = 0;
939 vnode_t *dvp, *vp;
940 struct exportinfo *exi = NULL;
941 fid_t fid;
942 uint_t count, i;
943 secinfo4 *resok_val;
944 struct secinfo *secp;
945 seconfig_t *si;
946 bool_t did_traverse = FALSE;
947 int dotdot, walk;
948 nfs_export_t *ne = nfs_get_export();
949
950 dvp = cs->vp;
951 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
952
953 /*
954 * If dotdotting, then need to check whether it's above the
955 * root of a filesystem, or above an export point.
956 */
957 if (dotdot) {
958
959 /*
960 * If dotdotting at the root of a filesystem, then
961 * need to traverse back to the mounted-on filesystem
962 * and do the dotdot lookup there.
963 */
964 if (cs->vp->v_flag & VROOT) {
965
966 /*
967 * If at the system root, then can
968 * go up no further.
969 */
970 if (VN_CMP(dvp, ZONE_ROOTVP()))
971 return (puterrno4(ENOENT));
972
973 /*
974 * Traverse back to the mounted-on filesystem
975 */
976 dvp = untraverse(cs->vp);
977
978 /*
979 * Set the different_export flag so we remember
980 * to pick up a new exportinfo entry for
981 * this new filesystem.
982 */
983 different_export = 1;
984 } else {
985
986 /*
987 * If dotdotting above an export point then set
988 * the different_export to get new export info.
989 */
990 different_export = nfs_exported(cs->exi, cs->vp);
991 }
992 }
993
994 /*
995 * Get the vnode for the component "nm".
996 */
997 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
998 NULL, NULL, NULL);
999 if (error)
1000 return (puterrno4(error));
1001
1002 /*
1003 * If the vnode is in a pseudo filesystem, or if the security flavor
1004 * used in the request is valid but not an explicitly shared flavor,
1005 * or the access bit indicates that this is a limited access,
1006 * check whether this vnode is visible.
1007 */
1008 if (!different_export &&
1009 (PSEUDO(cs->exi) || ! is_exported_sec(cs->nfsflavor, cs->exi) ||
1010 cs->access & CS_ACCESS_LIMITED)) {
1011 if (! nfs_visible(cs->exi, vp, &different_export)) {
1012 VN_RELE(vp);
1013 return (puterrno4(ENOENT));
1014 }
1015 }
1016
1017 /*
1018 * If it's a mountpoint, then traverse it.
1019 */
1020 if (vn_ismntpt(vp)) {
1021 if ((error = traverse(&vp)) != 0) {
1022 VN_RELE(vp);
1023 return (puterrno4(error));
1024 }
1025 /* remember that we had to traverse mountpoint */
1026 did_traverse = TRUE;
1027 different_export = 1;
1028 } else if (vp->v_vfsp != dvp->v_vfsp) {
1029 /*
1030 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
1031 * then vp is probably an LOFS object. We don't need the
1033 * a server fs boundary and need to call checkexport4.
1034 * (LOFS lookup hides server fs mountpoints, and actually calls
1035 * traverse)
1036 */
1037 different_export = 1;
1038 }
1039
1040 /*
1041 * Get the export information for it.
1042 */
1043 if (different_export) {
1044
1045 bzero(&fid, sizeof (fid));
1046 fid.fid_len = MAXFIDSZ;
1047 error = vop_fid_pseudo(vp, &fid);
1048 if (error) {
1049 VN_RELE(vp);
1050 return (puterrno4(error));
1051 }
1052
1053 if (dotdot)
1054 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1055 else
1056 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
1057
1058 if (exi == NULL) {
1059 if (did_traverse == TRUE) {
1060 /*
1061 * If this vnode is a mounted-on vnode,
1062 * but the mounted-on file system is not
1063 * exported, send back the secinfo for
1064 * the exported node that the mounted-on
1065 * vnode lives in.
1066 */
1067 exi = cs->exi;
1068 } else {
1069 VN_RELE(vp);
1070 return (puterrno4(EACCES));
1071 }
1072 }
1073 } else {
1074 exi = cs->exi;
1075 }
1076 ASSERT(exi != NULL);
1077
1078
1079 /*
1080 * Create the secinfo result based on the security information
1081 * from the exportinfo structure (exi).
1082 *
1083 * Return all flavors for a pseudo node.
1084 * For a real export node, return the flavor that the client
1085 * has access with.
1086 */
1087 ASSERT(RW_LOCK_HELD(&ne->exported_lock));
1088 if (PSEUDO(exi)) {
1089 count = exi->exi_export.ex_seccnt; /* total sec count */
1090 resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1091 secp = exi->exi_export.ex_secinfo;
1092
1093 for (i = 0; i < count; i++) {
1094 si = &secp[i].s_secinfo;
2685 fid_t fid;
2686 int attrdir, dotdot, walk;
2687 bool_t is_newvp = FALSE;
2688
2689 if (cs->vp->v_flag & V_XATTRDIR) {
2690 attrdir = 1;
2691 ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2692 } else {
2693 attrdir = 0;
2694 ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2695 }
2696
2697 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2698
2699 /*
2700 * If dotdotting, then need to check whether it's
2701 * above the root of a filesystem, or above an
2702 * export point.
2703 */
2704 if (dotdot) {
2705
2706 /*
2707 * If dotdotting at the root of a filesystem, then
2708 * need to traverse back to the mounted-on filesystem
2709 * and do the dotdot lookup there.
2710 */
2711 if (cs->vp->v_flag & VROOT) {
2712
2713 /*
2714 * If at the system root, then can
2715 * go up no further.
2716 */
2717 if (VN_CMP(cs->vp, ZONE_ROOTVP()))
2718 return (puterrno4(ENOENT));
2719
2720 /*
2721 * Traverse back to the mounted-on filesystem
2722 */
2723 cs->vp = untraverse(cs->vp);
2724
2725 /*
2726 * Set the different_export flag so we remember
2727 * to pick up a new exportinfo entry for
2728 * this new filesystem.
2729 */
2730 different_export = 1;
2731 } else {
|
801 sip->next = NULL;
802 sip->prev = NULL;
803
804 rw_init(&sip->oldstate_lock, NULL, RW_DEFAULT, NULL);
805 /*
806 * This initial dummy entry is required to setup for insque/remque.
807 * It must be skipped over whenever the list is traversed.
808 */
809 oldstate = kmem_alloc(sizeof (rfs4_oldstate_t), KM_SLEEP);
810 /* insque/remque require initial list entry to be self-terminated */
811 oldstate->next = oldstate;
812 oldstate->prev = oldstate;
813 sip->oldstate = oldstate;
814
815
816 sip->dss_npaths = dss_npaths;
817 sip->dss_paths = kmem_alloc(dss_npaths *
818 sizeof (rfs4_dss_path_t *), KM_SLEEP);
819
820 for (i = 0; i < dss_npaths; i++) {
821 sip->dss_paths[i] =
822 rfs4_dss_newpath(nsrv4, sip, dss_paths[i], i);
823 }
824
825 mutex_enter(&nsrv4->servinst_lock);
826 if (nsrv4->nfs4_cur_servinst != NULL) {
827 /* add to linked list */
828 sip->prev = nsrv4->nfs4_cur_servinst;
829 nsrv4->nfs4_cur_servinst->next = sip;
830 }
831 if (start_grace)
832 rfs4_grace_start(sip);
833 /* make the new instance "current" */
834 nsrv4->nfs4_cur_servinst = sip;
835
836 mutex_exit(&nsrv4->servinst_lock);
837 }
838
839 /*
840 * In future, we might add a rfs4_servinst_destroy(sip) but, for now, destroy
841 * all instances directly.
842 */
843 void
844 rfs4_servinst_destroy_all(nfs4_srv_t *nsrv4)
845 {
846 rfs4_servinst_t *sip, *prev, *current;
847 #ifdef DEBUG
848 int n = 0;
849 #endif
850
851 mutex_enter(&nsrv4->servinst_lock);
852 ASSERT(nsrv4->nfs4_cur_servinst != NULL);
853 current = nsrv4->nfs4_cur_servinst;
854 nsrv4->nfs4_cur_servinst = NULL;
855 for (sip = current; sip != NULL; sip = prev) {
856 prev = sip->prev;
857 rw_destroy(&sip->rwlock);
858 if (sip->oldstate)
859 kmem_free(sip->oldstate, sizeof (rfs4_oldstate_t));
860 if (sip->dss_paths) {
861 int i = sip->dss_npaths;
862
863 while (i > 0) {
864 i--;
865 if (sip->dss_paths[i] != NULL) {
866 char *path = sip->dss_paths[i]->path;
867
868 if (path != NULL) {
869 kmem_free(path,
870 strlen(path) + 1);
871 }
872 kmem_free(sip->dss_paths[i],
873 sizeof (rfs4_dss_path_t));
874 }
875 }
876 kmem_free(sip->dss_paths,
877 sip->dss_npaths * sizeof (rfs4_dss_path_t *));
878 }
879 kmem_free(sip, sizeof (rfs4_servinst_t));
880 #ifdef DEBUG
881 n++;
882 #endif
883 }
884 mutex_exit(&nsrv4->servinst_lock);
885 }
886
887 /*
888 * Assign the current server instance to a client_t.
889 * Should be called with cp->rc_dbe held.
890 */
891 void
892 rfs4_servinst_assign(nfs4_srv_t *nsrv4, rfs4_client_t *cp,
893 rfs4_servinst_t *sip)
894 {
895 ASSERT(rfs4_dbe_refcnt(cp->rc_dbe) > 0);
896
897 /*
898 * The lock ensures that if the current instance is in the process
936 {
937 int i;
938
939 for (i = 0; i < count; i++) {
940 if (nfsnum == flavor_list[i])
941 return (TRUE);
942 }
943 return (FALSE);
944 }
945
946 /*
947 * Used by rfs4_op_secinfo to get the security information from the
948 * export structure associated with the component.
949 */
950 /* ARGSUSED */
951 static nfsstat4
952 do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
953 {
954 int error, different_export = 0;
955 vnode_t *dvp, *vp;
956 struct exportinfo *exi;
957 fid_t fid;
958 uint_t count, i;
959 secinfo4 *resok_val;
960 struct secinfo *secp;
961 seconfig_t *si;
962 bool_t did_traverse = FALSE;
963 int dotdot, walk;
964 nfs_export_t *ne = nfs_get_export();
965
966 dvp = cs->vp;
967 exi = cs->exi;
968 ASSERT(exi != NULL);
969 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
970
971 /*
972 * If dotdotting, then need to check whether it's above the
973 * root of a filesystem, or above an export point.
974 */
975 if (dotdot) {
976 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
977 /*
978 * If dotdotting at the root of a filesystem, then
979 * need to traverse back to the mounted-on filesystem
980 * and do the dotdot lookup there.
981 */
982 if ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp)) {
983
984 /*
985 * If at the system root, then can
986 * go up no further.
987 */
988 if (VN_CMP(dvp, ZONE_ROOTVP()))
989 return (puterrno4(ENOENT));
990
991 /*
992 * Traverse back to the mounted-on filesystem
993 */
994 dvp = untraverse(dvp);
995
996 /*
997 * Set the different_export flag so we remember
998 * to pick up a new exportinfo entry for
999 * this new filesystem.
1000 */
1001 different_export = 1;
1002 } else {
1003
1004 /*
1005 * If dotdotting above an export point then set
1006 * the different_export to get new export info.
1007 */
1008 different_export = nfs_exported(exi, dvp);
1009 }
1010 }
1011
1012 /*
1013 * Get the vnode for the component "nm".
1014 */
1015 error = VOP_LOOKUP(dvp, nm, &vp, NULL, 0, NULL, cs->cr,
1016 NULL, NULL, NULL);
1017 if (error)
1018 return (puterrno4(error));
1019
1020 /*
1021 * If the vnode is in a pseudo filesystem, or if the security flavor
1022 * used in the request is valid but not an explicitly shared flavor,
1023 * or the access bit indicates that this is a limited access,
1024 * check whether this vnode is visible.
1025 */
1026 if (!different_export &&
1027 (PSEUDO(exi) || !is_exported_sec(cs->nfsflavor, exi) ||
1028 cs->access & CS_ACCESS_LIMITED)) {
1029 if (! nfs_visible(exi, vp, &different_export)) {
1030 VN_RELE(vp);
1031 return (puterrno4(ENOENT));
1032 }
1033 }
1034
1035 /*
1036 * If it's a mountpoint, then traverse it.
1037 */
1038 if (vn_ismntpt(vp)) {
1039 if ((error = traverse(&vp)) != 0) {
1040 VN_RELE(vp);
1041 return (puterrno4(error));
1042 }
1043 /* remember that we had to traverse mountpoint */
1044 did_traverse = TRUE;
1045 different_export = 1;
1046 } else if (vp->v_vfsp != dvp->v_vfsp) {
1047 /*
1048 * If vp isn't a mountpoint and the vfs ptrs aren't the same,
1049 * then vp is probably an LOFS object. We don't need the
1051 * a server fs boundary and need to call checkexport4.
1052 * (LOFS lookup hides server fs mountpoints, and actually calls
1053 * traverse)
1054 */
1055 different_export = 1;
1056 }
1057
1058 /*
1059 * Get the export information for it.
1060 */
1061 if (different_export) {
1062
1063 bzero(&fid, sizeof (fid));
1064 fid.fid_len = MAXFIDSZ;
1065 error = vop_fid_pseudo(vp, &fid);
1066 if (error) {
1067 VN_RELE(vp);
1068 return (puterrno4(error));
1069 }
1070
1071 /* We'll need to reassign "exi". */
1072 if (dotdot)
1073 exi = nfs_vptoexi(NULL, vp, cs->cr, &walk, NULL, TRUE);
1074 else
1075 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
1076
1077 if (exi == NULL) {
1078 if (did_traverse == TRUE) {
1079 /*
1080 * If this vnode is a mounted-on vnode,
1081 * but the mounted-on file system is not
1082 * exported, send back the secinfo for
1083 * the exported node that the mounted-on
1084 * vnode lives in.
1085 */
1086 exi = cs->exi;
1087 } else {
1088 VN_RELE(vp);
1089 return (puterrno4(EACCES));
1090 }
1091 }
1092 }
1093 ASSERT(exi != NULL);
1094
1095
1096 /*
1097 * Create the secinfo result based on the security information
1098 * from the exportinfo structure (exi).
1099 *
1100 * Return all flavors for a pseudo node.
1101 * For a real export node, return the flavor that the client
1102 * has access with.
1103 */
1104 ASSERT(RW_LOCK_HELD(&ne->exported_lock));
1105 if (PSEUDO(exi)) {
1106 count = exi->exi_export.ex_seccnt; /* total sec count */
1107 resok_val = kmem_alloc(count * sizeof (secinfo4), KM_SLEEP);
1108 secp = exi->exi_export.ex_secinfo;
1109
1110 for (i = 0; i < count; i++) {
1111 si = &secp[i].s_secinfo;
2702 fid_t fid;
2703 int attrdir, dotdot, walk;
2704 bool_t is_newvp = FALSE;
2705
2706 if (cs->vp->v_flag & V_XATTRDIR) {
2707 attrdir = 1;
2708 ASSERT(get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2709 } else {
2710 attrdir = 0;
2711 ASSERT(! get_fh4_flag(&cs->fh, FH4_ATTRDIR));
2712 }
2713
2714 dotdot = (nm[0] == '.' && nm[1] == '.' && nm[2] == '\0');
2715
2716 /*
2717 * If dotdotting, then need to check whether it's
2718 * above the root of a filesystem, or above an
2719 * export point.
2720 */
2721 if (dotdot) {
2722 ASSERT(cs->exi != NULL);
2723 ASSERT3U(cs->exi->exi_zoneid, ==, curzone->zone_id);
2724 /*
2725 * If dotdotting at the root of a filesystem, then
2726 * need to traverse back to the mounted-on filesystem
2727 * and do the dotdot lookup there.
2728 */
2729 if ((cs->vp->v_flag & VROOT) || VN_IS_CURZONEROOT(cs->vp)) {
2730
2731 /*
2732 * If at the system root, then can
2733 * go up no further.
2734 */
2735 if (VN_CMP(cs->vp, ZONE_ROOTVP()))
2736 return (puterrno4(ENOENT));
2737
2738 /*
2739 * Traverse back to the mounted-on filesystem
2740 */
2741 cs->vp = untraverse(cs->vp);
2742
2743 /*
2744 * Set the different_export flag so we remember
2745 * to pick up a new exportinfo entry for
2746 * this new filesystem.
2747 */
2748 different_export = 1;
2749 } else {
|