957                 ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL);
 958         }
 959 
 960         if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
 961                 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
 962 
 963         ddp->dd_prop_loaded = B_FALSE;
 964         ddp->dd_linkid = DATALINK_INVALID_LINKID;
 965         ddp->dd_flags = 0;
 966         mutex_exit(&ddp->dd_mutex);
 967         kmem_cache_free(i_dls_devnet_cachep, ddp);
 968 
 969         return (0);
 970 }
 971 
 972 static int
 973 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
 974     boolean_t tmp_hold)
 975 {
 976         dls_devnet_t            *ddp;
 977         dev_t                   phydev = 0;
 978         dls_dev_handle_t        ddh = NULL;
 979         int                     err;
 980 
 981         /*
 982          * Hold this link to prevent it being detached in case of a
 983          * physical link.
 984          */
 985         if (dls_mgmt_get_phydev(linkid, &phydev) == 0)
 986                 (void) softmac_hold_device(phydev, &ddh);
 987 
 988         rw_enter(&i_dls_devnet_lock, RW_READER);
 989         if ((err = mod_hash_find(i_dls_devnet_id_hash,
 990             (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
 991                 ASSERT(err == MH_ERR_NOTFOUND);
 992                 rw_exit(&i_dls_devnet_lock);
 993                 softmac_rele_device(ddh);
 994                 return (ENOENT);
 995         }
 996 
 997         mutex_enter(&ddp->dd_mutex);
 998         ASSERT(ddp->dd_ref > 0);
 999         if (ddp->dd_flags & DD_CONDEMNED) {
1000                 mutex_exit(&ddp->dd_mutex);
1001                 rw_exit(&i_dls_devnet_lock);
1002                 softmac_rele_device(ddh);
1003                 return (ENOENT);
1004         }
1005         if (tmp_hold)
1006                 ddp->dd_tref++;
1007         else
1008                 ddp->dd_ref++;
1009         mutex_exit(&ddp->dd_mutex);
1010         rw_exit(&i_dls_devnet_lock);
1011 
1012         softmac_rele_device(ddh);
1013 
1014         *ddpp = ddp;
1015         return (0);
1016 }
1017 
1018 int
1019 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1020 {
1021         return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1022 }
1023 
1024 /*
1025  * Hold the vanity naming structure (dls_devnet_t) temporarily.  The request to
1026  * delete the dls_devnet_t will wait until the temporary reference is released.
1027  */
1028 int
1029 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1030 {
1031         return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1032 }
1033 
1034 /*
1035  * This funtion is called when a DLS client tries to open a device node.
1036  * This dev_t could a result of a /dev/net node access (returned by
1037  * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1038  * In both cases, this function bumps up the reference count of the
1039  * dls_devnet_t structure. The reference is held as long as the device node
1040  * is open. In the case of /dev/net while it is true that the initial reference
1041  * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1042  * initial reference is released immediately in devnet_inactive_callback ->
1043  * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1044  * after dld_open completes, not when the /dev/net node is being closed).
1045  * To undo this function, call dls_devnet_rele()
1046  */
1047 int
1048 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1049 {
1050         char                    name[MAXNAMELEN];
1051         char                    *drv;
1052         dls_dev_handle_t        ddh = NULL;
1053         dls_devnet_t            *ddp;
1054         int                     err;
1055 
1056         if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1057                 return (EINVAL);
1058 
1059         (void) snprintf(name, sizeof (name), "%s%d", drv,
1060             DLS_MINOR2INST(getminor(dev)));
1061 
1062         /*
1063          * Hold this link to prevent it being detached in case of a
1064          * GLDv3 physical link.
1065          */
1066         if (DLS_MINOR2INST(getminor(dev)) <= DLS_MAX_PPA)
1067                 (void) softmac_hold_device(dev, &ddh);
1068 
1069         rw_enter(&i_dls_devnet_lock, RW_READER);
1070         if ((err = mod_hash_find(i_dls_devnet_hash,
1071             (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1072                 ASSERT(err == MH_ERR_NOTFOUND);
1073                 rw_exit(&i_dls_devnet_lock);
1074                 softmac_rele_device(ddh);
1075                 return (ENOENT);
1076         }
1077         mutex_enter(&ddp->dd_mutex);
1078         ASSERT(ddp->dd_ref > 0);
1079         if (ddp->dd_flags & DD_CONDEMNED) {
1080                 mutex_exit(&ddp->dd_mutex);
1081                 rw_exit(&i_dls_devnet_lock);
1082                 softmac_rele_device(ddh);
1083                 return (ENOENT);
1084         }
1085         ddp->dd_ref++;
1086         mutex_exit(&ddp->dd_mutex);
1087         rw_exit(&i_dls_devnet_lock);
1088 
1089         softmac_rele_device(ddh);
1090 
1091         *ddhp = ddp;
1092         return (0);
1093 }
1094 
1095 void
1096 dls_devnet_rele(dls_devnet_t *ddp)
1097 {
1098         mutex_enter(&ddp->dd_mutex);
1099         ASSERT(ddp->dd_ref > 1);
1100         ddp->dd_ref--;
1101         if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1102                 mutex_exit(&ddp->dd_mutex);
1103                 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1104                         ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1105                 return;
1106         }
1107         mutex_exit(&ddp->dd_mutex);
1108 }
1109 
1110 static int
 
1115         major_t                 major;
1116         dev_t                   phy_dev, tmp_dev;
1117         datalink_id_t           linkid;
1118         dls_dev_handle_t        ddh;
1119         int                     err;
1120 
1121         if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0)
1122                 return (dls_devnet_hold(linkid, ddpp));
1123 
1124         /*
1125          * If we failed to get the link's linkid because the dlmgmtd daemon
1126          * has not been started, return ENOENT so that the application can
1127          * fallback to open the /dev node.
1128          */
1129         if (err == EBADF)
1130                 return (ENOENT);
1131 
1132         if (err != ENOENT)
1133                 return (err);
1134 
1135         if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1136                 return (ENOENT);
1137 
1138         if (IS_IPTUN_LINK(drv)) {
1139                 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1140                         return (err);
1141                 /*
1142                  * At this point, an IP tunnel MAC has registered, which
1143                  * resulted in a link being created.
1144                  */
1145                 err = dls_devnet_hold(linkid, ddpp);
1146                 ASSERT(err == 0);
1147                 if (err != 0) {
1148                         VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1149                         return (err);
1150                 }
1151                 /*
1152                  * dls_devnet_rele() will know to destroy the implicit IP
1153                  * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1154                  * set.
1155                  */
1156                 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1157                 return (0);
1158         }
1159 
1160         /*
1161          * If this link:
1162          * (a) is a physical device, (b) this is the first boot, (c) the MAC
1163          * is not registered yet, and (d) we cannot find its linkid, then the
1164          * linkname is the same as the devname.
1165          *
1166          * First filter out invalid names.
 
 | 
 
 
 957                 ASSERT(ddp->dd_tref == 0 && ddp->dd_prop_taskid == NULL);
 958         }
 959 
 960         if (ddp->dd_linkid != DATALINK_INVALID_LINKID)
 961                 dls_devnet_stat_destroy(ddp, ddp->dd_owner_zid);
 962 
 963         ddp->dd_prop_loaded = B_FALSE;
 964         ddp->dd_linkid = DATALINK_INVALID_LINKID;
 965         ddp->dd_flags = 0;
 966         mutex_exit(&ddp->dd_mutex);
 967         kmem_cache_free(i_dls_devnet_cachep, ddp);
 968 
 969         return (0);
 970 }
 971 
 972 static int
 973 dls_devnet_hold_common(datalink_id_t linkid, dls_devnet_t **ddpp,
 974     boolean_t tmp_hold)
 975 {
 976         dls_devnet_t            *ddp;
 977         int                     err;
 978 
 979         rw_enter(&i_dls_devnet_lock, RW_READER);
 980         if ((err = mod_hash_find(i_dls_devnet_id_hash,
 981             (mod_hash_key_t)(uintptr_t)linkid, (mod_hash_val_t *)&ddp)) != 0) {
 982                 ASSERT(err == MH_ERR_NOTFOUND);
 983                 rw_exit(&i_dls_devnet_lock);
 984                 return (ENOENT);
 985         }
 986 
 987         mutex_enter(&ddp->dd_mutex);
 988         ASSERT(ddp->dd_ref > 0);
 989         if (ddp->dd_flags & DD_CONDEMNED) {
 990                 mutex_exit(&ddp->dd_mutex);
 991                 rw_exit(&i_dls_devnet_lock);
 992                 return (ENOENT);
 993         }
 994         if (tmp_hold)
 995                 ddp->dd_tref++;
 996         else
 997                 ddp->dd_ref++;
 998         mutex_exit(&ddp->dd_mutex);
 999         rw_exit(&i_dls_devnet_lock);
1000 
1001         *ddpp = ddp;
1002         return (0);
1003 }
1004 
1005 int
1006 dls_devnet_hold(datalink_id_t linkid, dls_devnet_t **ddpp)
1007 {
1008         return (dls_devnet_hold_common(linkid, ddpp, B_FALSE));
1009 }
1010 
1011 /*
1012  * Hold the vanity naming structure (dls_devnet_t) temporarily.  The request to
1013  * delete the dls_devnet_t will wait until the temporary reference is released.
1014  */
1015 int
1016 dls_devnet_hold_tmp(datalink_id_t linkid, dls_devnet_t **ddpp)
1017 {
1018         return (dls_devnet_hold_common(linkid, ddpp, B_TRUE));
1019 }
1020 
1021 /*
1022  * This funtion is called when a DLS client tries to open a device node.
1023  * This dev_t could be a result of a /dev/net node access (returned by
1024  * devnet_create_rvp->dls_devnet_open()) or a direct /dev node access.
1025  * In both cases, this function bumps up the reference count of the
1026  * dls_devnet_t structure. The reference is held as long as the device node
1027  * is open. In the case of /dev/net while it is true that the initial reference
1028  * is held when the devnet_create_rvp->dls_devnet_open call happens, this
1029  * initial reference is released immediately in devnet_inactive_callback ->
1030  * dls_devnet_close(). (Note that devnet_inactive_callback() is called right
1031  * after dld_open completes, not when the /dev/net node is being closed).
1032  * To undo this function, call dls_devnet_rele()
1033  */
1034 int
1035 dls_devnet_hold_by_dev(dev_t dev, dls_dl_handle_t *ddhp)
1036 {
1037         char                    name[MAXNAMELEN];
1038         char                    *drv;
1039         dls_devnet_t            *ddp;
1040         int                     err;
1041 
1042         if ((drv = ddi_major_to_name(getmajor(dev))) == NULL)
1043                 return (EINVAL);
1044 
1045         (void) snprintf(name, sizeof (name), "%s%d", drv,
1046             DLS_MINOR2INST(getminor(dev)));
1047 
1048         rw_enter(&i_dls_devnet_lock, RW_READER);
1049         if ((err = mod_hash_find(i_dls_devnet_hash,
1050             (mod_hash_key_t)name, (mod_hash_val_t *)&ddp)) != 0) {
1051                 ASSERT(err == MH_ERR_NOTFOUND);
1052                 rw_exit(&i_dls_devnet_lock);
1053                 return (ENOENT);
1054         }
1055         mutex_enter(&ddp->dd_mutex);
1056         ASSERT(ddp->dd_ref > 0);
1057         if (ddp->dd_flags & DD_CONDEMNED) {
1058                 mutex_exit(&ddp->dd_mutex);
1059                 rw_exit(&i_dls_devnet_lock);
1060                 return (ENOENT);
1061         }
1062         ddp->dd_ref++;
1063         mutex_exit(&ddp->dd_mutex);
1064         rw_exit(&i_dls_devnet_lock);
1065 
1066         *ddhp = ddp;
1067         return (0);
1068 }
1069 
1070 void
1071 dls_devnet_rele(dls_devnet_t *ddp)
1072 {
1073         mutex_enter(&ddp->dd_mutex);
1074         ASSERT(ddp->dd_ref > 1);
1075         ddp->dd_ref--;
1076         if ((ddp->dd_flags & DD_IMPLICIT_IPTUN) && ddp->dd_ref == 1) {
1077                 mutex_exit(&ddp->dd_mutex);
1078                 if (i_dls_devnet_destroy_iptun(ddp->dd_linkid) != 0)
1079                         ddp->dd_flags |= DD_IMPLICIT_IPTUN;
1080                 return;
1081         }
1082         mutex_exit(&ddp->dd_mutex);
1083 }
1084 
1085 static int
 
1090         major_t                 major;
1091         dev_t                   phy_dev, tmp_dev;
1092         datalink_id_t           linkid;
1093         dls_dev_handle_t        ddh;
1094         int                     err;
1095 
1096         if ((err = dls_mgmt_get_linkid(link, &linkid)) == 0)
1097                 return (dls_devnet_hold(linkid, ddpp));
1098 
1099         /*
1100          * If we failed to get the link's linkid because the dlmgmtd daemon
1101          * has not been started, return ENOENT so that the application can
1102          * fallback to open the /dev node.
1103          */
1104         if (err == EBADF)
1105                 return (ENOENT);
1106 
1107         if (err != ENOENT)
1108                 return (err);
1109 
1110         /*
1111          * If we reach this point it means dlmgmtd is up but has no
1112          * mapping for the link name.
1113          */
1114         if (ddi_parse(link, drv, &ppa) != DDI_SUCCESS)
1115                 return (ENOENT);
1116 
1117         if (IS_IPTUN_LINK(drv)) {
1118                 if ((err = i_dls_devnet_create_iptun(link, drv, &linkid)) != 0)
1119                         return (err);
1120                 /*
1121                  * At this point, an IP tunnel MAC has registered, which
1122                  * resulted in a link being created.
1123                  */
1124                 err = dls_devnet_hold(linkid, ddpp);
1125                 if (err != 0) {
1126                         VERIFY(i_dls_devnet_destroy_iptun(linkid) == 0);
1127                         return (err);
1128                 }
1129                 /*
1130                  * dls_devnet_rele() will know to destroy the implicit IP
1131                  * tunnel on last reference release if DD_IMPLICIT_IPTUN is
1132                  * set.
1133                  */
1134                 (*ddpp)->dd_flags |= DD_IMPLICIT_IPTUN;
1135                 return (0);
1136         }
1137 
1138         /*
1139          * If this link:
1140          * (a) is a physical device, (b) this is the first boot, (c) the MAC
1141          * is not registered yet, and (d) we cannot find its linkid, then the
1142          * linkname is the same as the devname.
1143          *
1144          * First filter out invalid names.
 
 |