1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* 2 /* 3 * Witness Service client for CIFS 3 * Witness Service client for CIFS 4 * 4 * 5 * Copyright (c) 2020 Samuel Cabrero <scabrero 5 * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de> 6 */ 6 */ 7 7 8 #include <linux/kref.h> 8 #include <linux/kref.h> 9 #include <net/genetlink.h> 9 #include <net/genetlink.h> 10 #include <uapi/linux/cifs/cifs_netlink.h> 10 #include <uapi/linux/cifs/cifs_netlink.h> 11 11 12 #include "cifs_swn.h" 12 #include "cifs_swn.h" 13 #include "cifsglob.h" 13 #include "cifsglob.h" 14 #include "cifsproto.h" 14 #include "cifsproto.h" 15 #include "fscache.h" 15 #include "fscache.h" 16 #include "cifs_debug.h" 16 #include "cifs_debug.h" 17 #include "netlink.h" 17 #include "netlink.h" 18 18 19 static DEFINE_IDR(cifs_swnreg_idr); 19 static DEFINE_IDR(cifs_swnreg_idr); 20 static DEFINE_MUTEX(cifs_swnreg_idr_mutex); 20 static DEFINE_MUTEX(cifs_swnreg_idr_mutex); 21 21 22 struct cifs_swn_reg { 22 struct cifs_swn_reg { 23 int id; 23 int id; 24 struct kref ref_count; 24 struct kref ref_count; 25 25 26 const char *net_name; 26 const char *net_name; 27 const char *share_name; 27 const char *share_name; 28 bool net_name_notify; 28 bool net_name_notify; 29 bool share_name_notify; 29 bool share_name_notify; 30 bool ip_notify; 30 bool ip_notify; 31 31 32 struct cifs_tcon *tcon; 32 struct cifs_tcon *tcon; 33 }; 33 }; 34 34 35 static int cifs_swn_auth_info_krb(struct cifs_ 35 static int cifs_swn_auth_info_krb(struct cifs_tcon *tcon, struct sk_buff *skb) 36 { 36 { 37 int ret; 37 int ret; 38 38 39 ret = nla_put_flag(skb, CIFS_GENL_ATTR 39 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_KRB_AUTH); 40 if (ret < 0) 40 if (ret < 0) 41 return ret; 41 return ret; 42 42 43 return 0; 43 return 0; 44 } 44 } 45 45 46 static int cifs_swn_auth_info_ntlm(struct cifs 46 static int cifs_swn_auth_info_ntlm(struct cifs_tcon *tcon, struct sk_buff *skb) 47 { 47 { 48 int ret; 48 int ret; 49 49 50 if (tcon->ses->user_name != NULL) { 50 if (tcon->ses->user_name != NULL) { 51 ret = nla_put_string(skb, CIFS 51 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_USER_NAME, tcon->ses->user_name); 52 if (ret < 0) 52 if (ret < 0) 53 return ret; 53 return ret; 54 } 54 } 55 55 56 if (tcon->ses->password != NULL) { 56 if (tcon->ses->password != NULL) { 57 ret = nla_put_string(skb, CIFS 57 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_PASSWORD, tcon->ses->password); 58 if (ret < 0) 58 if (ret < 0) 59 return ret; 59 return ret; 60 } 60 } 61 61 62 if (tcon->ses->domainName != NULL) { 62 if (tcon->ses->domainName != NULL) { 63 ret = nla_put_string(skb, CIFS 63 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_DOMAIN_NAME, tcon->ses->domainName); 64 if (ret < 0) 64 if (ret < 0) 65 return ret; 65 return ret; 66 } 66 } 67 67 68 return 0; 68 return 0; 69 } 69 } 70 70 71 /* 71 /* 72 * Sends a register message to the userspace d 72 * Sends a register message to the userspace daemon based on the registration. 73 * The authentication information to connect t 73 * The authentication information to connect to the witness service is bundled 74 * into the message. 74 * into the message. 75 */ 75 */ 76 static int cifs_swn_send_register_message(stru 76 static int cifs_swn_send_register_message(struct cifs_swn_reg *swnreg) 77 { 77 { 78 struct sk_buff *skb; 78 struct sk_buff *skb; 79 struct genlmsghdr *hdr; 79 struct genlmsghdr *hdr; 80 enum securityEnum authtype; 80 enum securityEnum authtype; 81 struct sockaddr_storage *addr; 81 struct sockaddr_storage *addr; 82 int ret; 82 int ret; 83 83 84 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, 84 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 85 if (skb == NULL) { 85 if (skb == NULL) { 86 ret = -ENOMEM; 86 ret = -ENOMEM; 87 goto fail; 87 goto fail; 88 } 88 } 89 89 90 hdr = genlmsg_put(skb, 0, 0, &cifs_gen 90 hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_REGISTER); 91 if (hdr == NULL) { 91 if (hdr == NULL) { 92 ret = -ENOMEM; 92 ret = -ENOMEM; 93 goto nlmsg_fail; 93 goto nlmsg_fail; 94 } 94 } 95 95 96 ret = nla_put_u32(skb, CIFS_GENL_ATTR_ 96 ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id); 97 if (ret < 0) 97 if (ret < 0) 98 goto nlmsg_fail; 98 goto nlmsg_fail; 99 99 100 ret = nla_put_string(skb, CIFS_GENL_AT 100 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name); 101 if (ret < 0) 101 if (ret < 0) 102 goto nlmsg_fail; 102 goto nlmsg_fail; 103 103 104 ret = nla_put_string(skb, CIFS_GENL_AT 104 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name); 105 if (ret < 0) 105 if (ret < 0) 106 goto nlmsg_fail; 106 goto nlmsg_fail; 107 107 108 /* 108 /* 109 * If there is an address stored use i 109 * If there is an address stored use it instead of the server address, because we are 110 * in the process of reconnecting to i 110 * in the process of reconnecting to it after a share has been moved or we have been 111 * told to switch to it (client move m 111 * told to switch to it (client move message). In these cases we unregister from the 112 * server address and register to the 112 * server address and register to the new address when we receive the notification. 113 */ 113 */ 114 if (swnreg->tcon->ses->server->use_swn 114 if (swnreg->tcon->ses->server->use_swn_dstaddr) 115 addr = &swnreg->tcon->ses->ser 115 addr = &swnreg->tcon->ses->server->swn_dstaddr; 116 else 116 else 117 addr = &swnreg->tcon->ses->ser 117 addr = &swnreg->tcon->ses->server->dstaddr; 118 118 119 ret = nla_put(skb, CIFS_GENL_ATTR_SWN_ 119 ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), addr); 120 if (ret < 0) 120 if (ret < 0) 121 goto nlmsg_fail; 121 goto nlmsg_fail; 122 122 123 if (swnreg->net_name_notify) { 123 if (swnreg->net_name_notify) { 124 ret = nla_put_flag(skb, CIFS_G 124 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY); 125 if (ret < 0) 125 if (ret < 0) 126 goto nlmsg_fail; 126 goto nlmsg_fail; 127 } 127 } 128 128 129 if (swnreg->share_name_notify) { 129 if (swnreg->share_name_notify) { 130 ret = nla_put_flag(skb, CIFS_G 130 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY); 131 if (ret < 0) 131 if (ret < 0) 132 goto nlmsg_fail; 132 goto nlmsg_fail; 133 } 133 } 134 134 135 if (swnreg->ip_notify) { 135 if (swnreg->ip_notify) { 136 ret = nla_put_flag(skb, CIFS_G 136 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY); 137 if (ret < 0) 137 if (ret < 0) 138 goto nlmsg_fail; 138 goto nlmsg_fail; 139 } 139 } 140 140 141 authtype = cifs_select_sectype(swnreg- 141 authtype = cifs_select_sectype(swnreg->tcon->ses->server, swnreg->tcon->ses->sectype); 142 switch (authtype) { 142 switch (authtype) { 143 case Kerberos: 143 case Kerberos: 144 ret = cifs_swn_auth_info_krb(s 144 ret = cifs_swn_auth_info_krb(swnreg->tcon, skb); 145 if (ret < 0) { 145 if (ret < 0) { 146 cifs_dbg(VFS, "%s: Fai 146 cifs_dbg(VFS, "%s: Failed to get kerberos auth info: %d\n", __func__, ret); 147 goto nlmsg_fail; 147 goto nlmsg_fail; 148 } 148 } 149 break; 149 break; 150 case NTLMv2: 150 case NTLMv2: 151 case RawNTLMSSP: 151 case RawNTLMSSP: 152 ret = cifs_swn_auth_info_ntlm( 152 ret = cifs_swn_auth_info_ntlm(swnreg->tcon, skb); 153 if (ret < 0) { 153 if (ret < 0) { 154 cifs_dbg(VFS, "%s: Fai 154 cifs_dbg(VFS, "%s: Failed to get NTLM auth info: %d\n", __func__, ret); 155 goto nlmsg_fail; 155 goto nlmsg_fail; 156 } 156 } 157 break; 157 break; 158 default: 158 default: 159 cifs_dbg(VFS, "%s: secType %d 159 cifs_dbg(VFS, "%s: secType %d not supported!\n", __func__, authtype); 160 ret = -EINVAL; 160 ret = -EINVAL; 161 goto nlmsg_fail; 161 goto nlmsg_fail; 162 } 162 } 163 163 164 genlmsg_end(skb, hdr); 164 genlmsg_end(skb, hdr); 165 genlmsg_multicast(&cifs_genl_family, s 165 genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC); 166 166 167 cifs_dbg(FYI, "%s: Message to register 167 cifs_dbg(FYI, "%s: Message to register for network name %s with id %d sent\n", __func__, 168 swnreg->net_name, swnr 168 swnreg->net_name, swnreg->id); 169 169 170 return 0; 170 return 0; 171 171 172 nlmsg_fail: 172 nlmsg_fail: 173 genlmsg_cancel(skb, hdr); 173 genlmsg_cancel(skb, hdr); 174 nlmsg_free(skb); 174 nlmsg_free(skb); 175 fail: 175 fail: 176 return ret; 176 return ret; 177 } 177 } 178 178 179 /* 179 /* 180 * Sends an uregister message to the userspace 180 * Sends an uregister message to the userspace daemon based on the registration 181 */ 181 */ 182 static int cifs_swn_send_unregister_message(st 182 static int cifs_swn_send_unregister_message(struct cifs_swn_reg *swnreg) 183 { 183 { 184 struct sk_buff *skb; 184 struct sk_buff *skb; 185 struct genlmsghdr *hdr; 185 struct genlmsghdr *hdr; 186 int ret; 186 int ret; 187 187 188 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, 188 skb = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 189 if (skb == NULL) 189 if (skb == NULL) 190 return -ENOMEM; 190 return -ENOMEM; 191 191 192 hdr = genlmsg_put(skb, 0, 0, &cifs_gen 192 hdr = genlmsg_put(skb, 0, 0, &cifs_genl_family, 0, CIFS_GENL_CMD_SWN_UNREGISTER); 193 if (hdr == NULL) { 193 if (hdr == NULL) { 194 ret = -ENOMEM; 194 ret = -ENOMEM; 195 goto nlmsg_fail; 195 goto nlmsg_fail; 196 } 196 } 197 197 198 ret = nla_put_u32(skb, CIFS_GENL_ATTR_ 198 ret = nla_put_u32(skb, CIFS_GENL_ATTR_SWN_REGISTRATION_ID, swnreg->id); 199 if (ret < 0) 199 if (ret < 0) 200 goto nlmsg_fail; 200 goto nlmsg_fail; 201 201 202 ret = nla_put_string(skb, CIFS_GENL_AT 202 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_NET_NAME, swnreg->net_name); 203 if (ret < 0) 203 if (ret < 0) 204 goto nlmsg_fail; 204 goto nlmsg_fail; 205 205 206 ret = nla_put_string(skb, CIFS_GENL_AT 206 ret = nla_put_string(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME, swnreg->share_name); 207 if (ret < 0) 207 if (ret < 0) 208 goto nlmsg_fail; 208 goto nlmsg_fail; 209 209 210 ret = nla_put(skb, CIFS_GENL_ATTR_SWN_ 210 ret = nla_put(skb, CIFS_GENL_ATTR_SWN_IP, sizeof(struct sockaddr_storage), 211 &swnreg->tcon->ses->se 211 &swnreg->tcon->ses->server->dstaddr); 212 if (ret < 0) 212 if (ret < 0) 213 goto nlmsg_fail; 213 goto nlmsg_fail; 214 214 215 if (swnreg->net_name_notify) { 215 if (swnreg->net_name_notify) { 216 ret = nla_put_flag(skb, CIFS_G 216 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY); 217 if (ret < 0) 217 if (ret < 0) 218 goto nlmsg_fail; 218 goto nlmsg_fail; 219 } 219 } 220 220 221 if (swnreg->share_name_notify) { 221 if (swnreg->share_name_notify) { 222 ret = nla_put_flag(skb, CIFS_G 222 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY); 223 if (ret < 0) 223 if (ret < 0) 224 goto nlmsg_fail; 224 goto nlmsg_fail; 225 } 225 } 226 226 227 if (swnreg->ip_notify) { 227 if (swnreg->ip_notify) { 228 ret = nla_put_flag(skb, CIFS_G 228 ret = nla_put_flag(skb, CIFS_GENL_ATTR_SWN_IP_NOTIFY); 229 if (ret < 0) 229 if (ret < 0) 230 goto nlmsg_fail; 230 goto nlmsg_fail; 231 } 231 } 232 232 233 genlmsg_end(skb, hdr); 233 genlmsg_end(skb, hdr); 234 genlmsg_multicast(&cifs_genl_family, s 234 genlmsg_multicast(&cifs_genl_family, skb, 0, CIFS_GENL_MCGRP_SWN, GFP_ATOMIC); 235 235 236 cifs_dbg(FYI, "%s: Message to unregist 236 cifs_dbg(FYI, "%s: Message to unregister for network name %s with id %d sent\n", __func__, 237 swnreg->net_name, swnr 237 swnreg->net_name, swnreg->id); 238 238 239 return 0; 239 return 0; 240 240 241 nlmsg_fail: 241 nlmsg_fail: 242 genlmsg_cancel(skb, hdr); 242 genlmsg_cancel(skb, hdr); 243 nlmsg_free(skb); 243 nlmsg_free(skb); 244 return ret; 244 return ret; 245 } 245 } 246 246 247 /* 247 /* 248 * Try to find a matching registration for the 248 * Try to find a matching registration for the tcon's server name and share name. 249 * Calls to this function must be protected by 249 * Calls to this function must be protected by cifs_swnreg_idr_mutex. 250 * TODO Try to avoid memory allocations 250 * TODO Try to avoid memory allocations 251 */ 251 */ 252 static struct cifs_swn_reg *cifs_find_swn_reg( 252 static struct cifs_swn_reg *cifs_find_swn_reg(struct cifs_tcon *tcon) 253 { 253 { 254 struct cifs_swn_reg *swnreg; 254 struct cifs_swn_reg *swnreg; 255 int id; 255 int id; 256 const char *share_name; 256 const char *share_name; 257 const char *net_name; 257 const char *net_name; 258 258 259 net_name = extract_hostname(tcon->tree 259 net_name = extract_hostname(tcon->tree_name); 260 if (IS_ERR(net_name)) { 260 if (IS_ERR(net_name)) { 261 int ret; 261 int ret; 262 262 263 ret = PTR_ERR(net_name); 263 ret = PTR_ERR(net_name); 264 cifs_dbg(VFS, "%s: failed to e 264 cifs_dbg(VFS, "%s: failed to extract host name from target '%s': %d\n", 265 __func__, tcon 265 __func__, tcon->tree_name, ret); 266 return ERR_PTR(-EINVAL); 266 return ERR_PTR(-EINVAL); 267 } 267 } 268 268 269 share_name = extract_sharename(tcon->t 269 share_name = extract_sharename(tcon->tree_name); 270 if (IS_ERR(share_name)) { 270 if (IS_ERR(share_name)) { 271 int ret; 271 int ret; 272 272 273 ret = PTR_ERR(share_name); 273 ret = PTR_ERR(share_name); 274 cifs_dbg(VFS, "%s: failed to e 274 cifs_dbg(VFS, "%s: failed to extract share name from target '%s': %d\n", 275 __func__, tcon 275 __func__, tcon->tree_name, ret); 276 kfree(net_name); 276 kfree(net_name); 277 return ERR_PTR(-EINVAL); 277 return ERR_PTR(-EINVAL); 278 } 278 } 279 279 280 idr_for_each_entry(&cifs_swnreg_idr, s 280 idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) { 281 if (strcasecmp(swnreg->net_nam 281 if (strcasecmp(swnreg->net_name, net_name) != 0 282 || strcasecmp(swnreg->shar 282 || strcasecmp(swnreg->share_name, share_name) != 0) { 283 continue; 283 continue; 284 } 284 } 285 285 286 cifs_dbg(FYI, "Existing swn re 286 cifs_dbg(FYI, "Existing swn registration for %s:%s found\n", swnreg->net_name, 287 swnreg->share_ 287 swnreg->share_name); 288 288 289 kfree(net_name); 289 kfree(net_name); 290 kfree(share_name); 290 kfree(share_name); 291 291 292 return swnreg; 292 return swnreg; 293 } 293 } 294 294 295 kfree(net_name); 295 kfree(net_name); 296 kfree(share_name); 296 kfree(share_name); 297 297 298 return ERR_PTR(-EEXIST); 298 return ERR_PTR(-EEXIST); 299 } 299 } 300 300 301 /* 301 /* 302 * Get a registration for the tcon's server an 302 * Get a registration for the tcon's server and share name, allocating a new one if it does not 303 * exists 303 * exists 304 */ 304 */ 305 static struct cifs_swn_reg *cifs_get_swn_reg(s 305 static struct cifs_swn_reg *cifs_get_swn_reg(struct cifs_tcon *tcon) 306 { 306 { 307 struct cifs_swn_reg *reg = NULL; 307 struct cifs_swn_reg *reg = NULL; 308 int ret; 308 int ret; 309 309 310 mutex_lock(&cifs_swnreg_idr_mutex); 310 mutex_lock(&cifs_swnreg_idr_mutex); 311 311 312 /* Check if we are already registered 312 /* Check if we are already registered for this network and share names */ 313 reg = cifs_find_swn_reg(tcon); 313 reg = cifs_find_swn_reg(tcon); 314 if (!IS_ERR(reg)) { 314 if (!IS_ERR(reg)) { 315 kref_get(®->ref_count); 315 kref_get(®->ref_count); 316 mutex_unlock(&cifs_swnreg_idr_ 316 mutex_unlock(&cifs_swnreg_idr_mutex); 317 return reg; 317 return reg; 318 } else if (PTR_ERR(reg) != -EEXIST) { 318 } else if (PTR_ERR(reg) != -EEXIST) { 319 mutex_unlock(&cifs_swnreg_idr_ 319 mutex_unlock(&cifs_swnreg_idr_mutex); 320 return reg; 320 return reg; 321 } 321 } 322 322 323 reg = kmalloc(sizeof(struct cifs_swn_r 323 reg = kmalloc(sizeof(struct cifs_swn_reg), GFP_ATOMIC); 324 if (reg == NULL) { 324 if (reg == NULL) { 325 mutex_unlock(&cifs_swnreg_idr_ 325 mutex_unlock(&cifs_swnreg_idr_mutex); 326 return ERR_PTR(-ENOMEM); 326 return ERR_PTR(-ENOMEM); 327 } 327 } 328 328 329 kref_init(®->ref_count); 329 kref_init(®->ref_count); 330 330 331 reg->id = idr_alloc(&cifs_swnreg_idr, 331 reg->id = idr_alloc(&cifs_swnreg_idr, reg, 1, 0, GFP_ATOMIC); 332 if (reg->id < 0) { 332 if (reg->id < 0) { 333 cifs_dbg(FYI, "%s: failed to a 333 cifs_dbg(FYI, "%s: failed to allocate registration id\n", __func__); 334 ret = reg->id; 334 ret = reg->id; 335 goto fail; 335 goto fail; 336 } 336 } 337 337 338 reg->net_name = extract_hostname(tcon- 338 reg->net_name = extract_hostname(tcon->tree_name); 339 if (IS_ERR(reg->net_name)) { 339 if (IS_ERR(reg->net_name)) { 340 ret = PTR_ERR(reg->net_name); 340 ret = PTR_ERR(reg->net_name); 341 cifs_dbg(VFS, "%s: failed to e 341 cifs_dbg(VFS, "%s: failed to extract host name from target: %d\n", __func__, ret); 342 goto fail_idr; 342 goto fail_idr; 343 } 343 } 344 344 345 reg->share_name = extract_sharename(tc 345 reg->share_name = extract_sharename(tcon->tree_name); 346 if (IS_ERR(reg->share_name)) { 346 if (IS_ERR(reg->share_name)) { 347 ret = PTR_ERR(reg->share_name) 347 ret = PTR_ERR(reg->share_name); 348 cifs_dbg(VFS, "%s: failed to e 348 cifs_dbg(VFS, "%s: failed to extract share name from target: %d\n", __func__, ret); 349 goto fail_net_name; 349 goto fail_net_name; 350 } 350 } 351 351 352 reg->net_name_notify = true; 352 reg->net_name_notify = true; 353 reg->share_name_notify = true; 353 reg->share_name_notify = true; 354 reg->ip_notify = (tcon->capabilities & 354 reg->ip_notify = (tcon->capabilities & SMB2_SHARE_CAP_SCALEOUT); 355 355 356 reg->tcon = tcon; 356 reg->tcon = tcon; 357 357 358 mutex_unlock(&cifs_swnreg_idr_mutex); 358 mutex_unlock(&cifs_swnreg_idr_mutex); 359 359 360 return reg; 360 return reg; 361 361 362 fail_net_name: 362 fail_net_name: 363 kfree(reg->net_name); 363 kfree(reg->net_name); 364 fail_idr: 364 fail_idr: 365 idr_remove(&cifs_swnreg_idr, reg->id); 365 idr_remove(&cifs_swnreg_idr, reg->id); 366 fail: 366 fail: 367 kfree(reg); 367 kfree(reg); 368 mutex_unlock(&cifs_swnreg_idr_mutex); 368 mutex_unlock(&cifs_swnreg_idr_mutex); 369 return ERR_PTR(ret); 369 return ERR_PTR(ret); 370 } 370 } 371 371 372 static void cifs_swn_reg_release(struct kref * 372 static void cifs_swn_reg_release(struct kref *ref) 373 { 373 { 374 struct cifs_swn_reg *swnreg = containe 374 struct cifs_swn_reg *swnreg = container_of(ref, struct cifs_swn_reg, ref_count); 375 int ret; 375 int ret; 376 376 377 ret = cifs_swn_send_unregister_message 377 ret = cifs_swn_send_unregister_message(swnreg); 378 if (ret < 0) 378 if (ret < 0) 379 cifs_dbg(VFS, "%s: Failed to s 379 cifs_dbg(VFS, "%s: Failed to send unregister message: %d\n", __func__, ret); 380 380 381 idr_remove(&cifs_swnreg_idr, swnreg->i 381 idr_remove(&cifs_swnreg_idr, swnreg->id); 382 kfree(swnreg->net_name); 382 kfree(swnreg->net_name); 383 kfree(swnreg->share_name); 383 kfree(swnreg->share_name); 384 kfree(swnreg); 384 kfree(swnreg); 385 } 385 } 386 386 387 static void cifs_put_swn_reg(struct cifs_swn_r 387 static void cifs_put_swn_reg(struct cifs_swn_reg *swnreg) 388 { 388 { 389 mutex_lock(&cifs_swnreg_idr_mutex); 389 mutex_lock(&cifs_swnreg_idr_mutex); 390 kref_put(&swnreg->ref_count, cifs_swn_ 390 kref_put(&swnreg->ref_count, cifs_swn_reg_release); 391 mutex_unlock(&cifs_swnreg_idr_mutex); 391 mutex_unlock(&cifs_swnreg_idr_mutex); 392 } 392 } 393 393 394 static int cifs_swn_resource_state_changed(str 394 static int cifs_swn_resource_state_changed(struct cifs_swn_reg *swnreg, const char *name, int state) 395 { 395 { 396 switch (state) { 396 switch (state) { 397 case CIFS_SWN_RESOURCE_STATE_UNAVAILAB 397 case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE: 398 cifs_dbg(FYI, "%s: resource na 398 cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name); 399 cifs_signal_cifsd_for_reconnec 399 cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true); 400 break; 400 break; 401 case CIFS_SWN_RESOURCE_STATE_AVAILABLE 401 case CIFS_SWN_RESOURCE_STATE_AVAILABLE: 402 cifs_dbg(FYI, "%s: resource na 402 cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name); 403 cifs_signal_cifsd_for_reconnec 403 cifs_signal_cifsd_for_reconnect(swnreg->tcon->ses->server, true); 404 break; 404 break; 405 case CIFS_SWN_RESOURCE_STATE_UNKNOWN: 405 case CIFS_SWN_RESOURCE_STATE_UNKNOWN: 406 cifs_dbg(FYI, "%s: resource na 406 cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name); 407 break; 407 break; 408 } 408 } 409 return 0; 409 return 0; 410 } 410 } 411 411 412 static bool cifs_sockaddr_equal(struct sockadd 412 static bool cifs_sockaddr_equal(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2) 413 { 413 { 414 if (addr1->ss_family != addr2->ss_fami 414 if (addr1->ss_family != addr2->ss_family) 415 return false; 415 return false; 416 416 417 if (addr1->ss_family == AF_INET) { 417 if (addr1->ss_family == AF_INET) { 418 return (memcmp(&((const struct 418 return (memcmp(&((const struct sockaddr_in *)addr1)->sin_addr, 419 &((const struc 419 &((const struct sockaddr_in *)addr2)->sin_addr, 420 sizeof(struct 420 sizeof(struct in_addr)) == 0); 421 } 421 } 422 422 423 if (addr1->ss_family == AF_INET6) { 423 if (addr1->ss_family == AF_INET6) { 424 return (memcmp(&((const struct 424 return (memcmp(&((const struct sockaddr_in6 *)addr1)->sin6_addr, 425 &((const struc 425 &((const struct sockaddr_in6 *)addr2)->sin6_addr, 426 sizeof(struct 426 sizeof(struct in6_addr)) == 0); 427 } 427 } 428 428 429 return false; 429 return false; 430 } 430 } 431 431 432 static int cifs_swn_store_swn_addr(const struc 432 static int cifs_swn_store_swn_addr(const struct sockaddr_storage *new, 433 const struc 433 const struct sockaddr_storage *old, 434 struct sock 434 struct sockaddr_storage *dst) 435 { 435 { 436 __be16 port = cpu_to_be16(CIFS_PORT); 436 __be16 port = cpu_to_be16(CIFS_PORT); 437 437 438 if (old->ss_family == AF_INET) { 438 if (old->ss_family == AF_INET) { 439 struct sockaddr_in *ipv4 = (st 439 struct sockaddr_in *ipv4 = (struct sockaddr_in *)old; 440 440 441 port = ipv4->sin_port; 441 port = ipv4->sin_port; 442 } else if (old->ss_family == AF_INET6) 442 } else if (old->ss_family == AF_INET6) { 443 struct sockaddr_in6 *ipv6 = (s 443 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)old; 444 444 445 port = ipv6->sin6_port; 445 port = ipv6->sin6_port; 446 } 446 } 447 447 448 if (new->ss_family == AF_INET) { 448 if (new->ss_family == AF_INET) { 449 struct sockaddr_in *ipv4 = (st 449 struct sockaddr_in *ipv4 = (struct sockaddr_in *)new; 450 450 451 ipv4->sin_port = port; 451 ipv4->sin_port = port; 452 } else if (new->ss_family == AF_INET6) 452 } else if (new->ss_family == AF_INET6) { 453 struct sockaddr_in6 *ipv6 = (s 453 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)new; 454 454 455 ipv6->sin6_port = port; 455 ipv6->sin6_port = port; 456 } 456 } 457 457 458 *dst = *new; 458 *dst = *new; 459 459 460 return 0; 460 return 0; 461 } 461 } 462 462 463 static int cifs_swn_reconnect(struct cifs_tcon 463 static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *addr) 464 { 464 { 465 int ret = 0; 465 int ret = 0; 466 466 467 /* Store the reconnect address */ 467 /* Store the reconnect address */ 468 cifs_server_lock(tcon->ses->server); 468 cifs_server_lock(tcon->ses->server); 469 if (cifs_sockaddr_equal(&tcon->ses->se 469 if (cifs_sockaddr_equal(&tcon->ses->server->dstaddr, addr)) 470 goto unlock; 470 goto unlock; 471 471 472 ret = cifs_swn_store_swn_addr(addr, &t 472 ret = cifs_swn_store_swn_addr(addr, &tcon->ses->server->dstaddr, 473 &tcon->s 473 &tcon->ses->server->swn_dstaddr); 474 if (ret < 0) { 474 if (ret < 0) { 475 cifs_dbg(VFS, "%s: failed to s 475 cifs_dbg(VFS, "%s: failed to store address: %d\n", __func__, ret); 476 goto unlock; 476 goto unlock; 477 } 477 } 478 tcon->ses->server->use_swn_dstaddr = t 478 tcon->ses->server->use_swn_dstaddr = true; 479 479 480 /* 480 /* 481 * Unregister to stop receiving notifi 481 * Unregister to stop receiving notifications for the old IP address. 482 */ 482 */ 483 ret = cifs_swn_unregister(tcon); 483 ret = cifs_swn_unregister(tcon); 484 if (ret < 0) { 484 if (ret < 0) { 485 cifs_dbg(VFS, "%s: Failed to u 485 cifs_dbg(VFS, "%s: Failed to unregister for witness notifications: %d\n", 486 __func__, ret); 486 __func__, ret); 487 goto unlock; 487 goto unlock; 488 } 488 } 489 489 490 /* 490 /* 491 * And register to receive notificatio 491 * And register to receive notifications for the new IP address now that we have 492 * stored the new address. 492 * stored the new address. 493 */ 493 */ 494 ret = cifs_swn_register(tcon); 494 ret = cifs_swn_register(tcon); 495 if (ret < 0) { 495 if (ret < 0) { 496 cifs_dbg(VFS, "%s: Failed to r 496 cifs_dbg(VFS, "%s: Failed to register for witness notifications: %d\n", 497 __func__, ret); 497 __func__, ret); 498 goto unlock; 498 goto unlock; 499 } 499 } 500 500 501 cifs_signal_cifsd_for_reconnect(tcon-> 501 cifs_signal_cifsd_for_reconnect(tcon->ses->server, false); 502 502 503 unlock: 503 unlock: 504 cifs_server_unlock(tcon->ses->server); 504 cifs_server_unlock(tcon->ses->server); 505 505 506 return ret; 506 return ret; 507 } 507 } 508 508 509 static int cifs_swn_client_move(struct cifs_sw 509 static int cifs_swn_client_move(struct cifs_swn_reg *swnreg, struct sockaddr_storage *addr) 510 { 510 { 511 struct sockaddr_in *ipv4 = (struct soc 511 struct sockaddr_in *ipv4 = (struct sockaddr_in *)addr; 512 struct sockaddr_in6 *ipv6 = (struct so 512 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)addr; 513 513 514 if (addr->ss_family == AF_INET) 514 if (addr->ss_family == AF_INET) 515 cifs_dbg(FYI, "%s: move to %pI 515 cifs_dbg(FYI, "%s: move to %pI4\n", __func__, &ipv4->sin_addr); 516 else if (addr->ss_family == AF_INET6) 516 else if (addr->ss_family == AF_INET6) 517 cifs_dbg(FYI, "%s: move to %pI 517 cifs_dbg(FYI, "%s: move to %pI6\n", __func__, &ipv6->sin6_addr); 518 518 519 return cifs_swn_reconnect(swnreg->tcon 519 return cifs_swn_reconnect(swnreg->tcon, addr); 520 } 520 } 521 521 522 int cifs_swn_notify(struct sk_buff *skb, struc 522 int cifs_swn_notify(struct sk_buff *skb, struct genl_info *info) 523 { 523 { 524 struct cifs_swn_reg *swnreg; 524 struct cifs_swn_reg *swnreg; 525 char name[256]; 525 char name[256]; 526 int type; 526 int type; 527 527 528 if (info->attrs[CIFS_GENL_ATTR_SWN_REG 528 if (info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]) { 529 int swnreg_id; 529 int swnreg_id; 530 530 531 swnreg_id = nla_get_u32(info-> 531 swnreg_id = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]); 532 mutex_lock(&cifs_swnreg_idr_mu 532 mutex_lock(&cifs_swnreg_idr_mutex); 533 swnreg = idr_find(&cifs_swnreg 533 swnreg = idr_find(&cifs_swnreg_idr, swnreg_id); 534 mutex_unlock(&cifs_swnreg_idr_ 534 mutex_unlock(&cifs_swnreg_idr_mutex); 535 if (swnreg == NULL) { 535 if (swnreg == NULL) { 536 cifs_dbg(FYI, "%s: reg 536 cifs_dbg(FYI, "%s: registration id %d not found\n", __func__, swnreg_id); 537 return -EINVAL; 537 return -EINVAL; 538 } 538 } 539 } else { 539 } else { 540 cifs_dbg(FYI, "%s: missing reg 540 cifs_dbg(FYI, "%s: missing registration id attribute\n", __func__); 541 return -EINVAL; 541 return -EINVAL; 542 } 542 } 543 543 544 if (info->attrs[CIFS_GENL_ATTR_SWN_NOT 544 if (info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]) { 545 type = nla_get_u32(info->attrs 545 type = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]); 546 } else { 546 } else { 547 cifs_dbg(FYI, "%s: missing not 547 cifs_dbg(FYI, "%s: missing notification type attribute\n", __func__); 548 return -EINVAL; 548 return -EINVAL; 549 } 549 } 550 550 551 switch (type) { 551 switch (type) { 552 case CIFS_SWN_NOTIFICATION_RESOURCE_CH 552 case CIFS_SWN_NOTIFICATION_RESOURCE_CHANGE: { 553 int state; 553 int state; 554 554 555 if (info->attrs[CIFS_GENL_ATTR 555 if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]) { 556 nla_strscpy(name, info 556 nla_strscpy(name, info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_NAME], 557 sizeof 557 sizeof(name)); 558 } else { 558 } else { 559 cifs_dbg(FYI, "%s: mis 559 cifs_dbg(FYI, "%s: missing resource name attribute\n", __func__); 560 return -EINVAL; 560 return -EINVAL; 561 } 561 } 562 if (info->attrs[CIFS_GENL_ATTR 562 if (info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]) { 563 state = nla_get_u32(in 563 state = nla_get_u32(info->attrs[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]); 564 } else { 564 } else { 565 cifs_dbg(FYI, "%s: mis 565 cifs_dbg(FYI, "%s: missing resource state attribute\n", __func__); 566 return -EINVAL; 566 return -EINVAL; 567 } 567 } 568 return cifs_swn_resource_state 568 return cifs_swn_resource_state_changed(swnreg, name, state); 569 } 569 } 570 case CIFS_SWN_NOTIFICATION_CLIENT_MOVE 570 case CIFS_SWN_NOTIFICATION_CLIENT_MOVE: { 571 struct sockaddr_storage addr; 571 struct sockaddr_storage addr; 572 572 573 if (info->attrs[CIFS_GENL_ATTR 573 if (info->attrs[CIFS_GENL_ATTR_SWN_IP]) { 574 nla_memcpy(&addr, info 574 nla_memcpy(&addr, info->attrs[CIFS_GENL_ATTR_SWN_IP], sizeof(addr)); 575 } else { 575 } else { 576 cifs_dbg(FYI, "%s: mis 576 cifs_dbg(FYI, "%s: missing IP address attribute\n", __func__); 577 return -EINVAL; 577 return -EINVAL; 578 } 578 } 579 return cifs_swn_client_move(sw 579 return cifs_swn_client_move(swnreg, &addr); 580 } 580 } 581 default: 581 default: 582 cifs_dbg(FYI, "%s: unknown not 582 cifs_dbg(FYI, "%s: unknown notification type %d\n", __func__, type); 583 break; 583 break; 584 } 584 } 585 585 586 return 0; 586 return 0; 587 } 587 } 588 588 589 int cifs_swn_register(struct cifs_tcon *tcon) 589 int cifs_swn_register(struct cifs_tcon *tcon) 590 { 590 { 591 struct cifs_swn_reg *swnreg; 591 struct cifs_swn_reg *swnreg; 592 int ret; 592 int ret; 593 593 594 swnreg = cifs_get_swn_reg(tcon); 594 swnreg = cifs_get_swn_reg(tcon); 595 if (IS_ERR(swnreg)) 595 if (IS_ERR(swnreg)) 596 return PTR_ERR(swnreg); 596 return PTR_ERR(swnreg); 597 597 598 ret = cifs_swn_send_register_message(s 598 ret = cifs_swn_send_register_message(swnreg); 599 if (ret < 0) { 599 if (ret < 0) { 600 cifs_dbg(VFS, "%s: Failed to s 600 cifs_dbg(VFS, "%s: Failed to send swn register message: %d\n", __func__, ret); 601 /* Do not put the swnreg or re 601 /* Do not put the swnreg or return error, the echo task will retry */ 602 } 602 } 603 603 604 return 0; 604 return 0; 605 } 605 } 606 606 607 int cifs_swn_unregister(struct cifs_tcon *tcon 607 int cifs_swn_unregister(struct cifs_tcon *tcon) 608 { 608 { 609 struct cifs_swn_reg *swnreg; 609 struct cifs_swn_reg *swnreg; 610 610 611 mutex_lock(&cifs_swnreg_idr_mutex); 611 mutex_lock(&cifs_swnreg_idr_mutex); 612 612 613 swnreg = cifs_find_swn_reg(tcon); 613 swnreg = cifs_find_swn_reg(tcon); 614 if (IS_ERR(swnreg)) { 614 if (IS_ERR(swnreg)) { 615 mutex_unlock(&cifs_swnreg_idr_ 615 mutex_unlock(&cifs_swnreg_idr_mutex); 616 return PTR_ERR(swnreg); 616 return PTR_ERR(swnreg); 617 } 617 } 618 618 619 mutex_unlock(&cifs_swnreg_idr_mutex); 619 mutex_unlock(&cifs_swnreg_idr_mutex); 620 620 621 cifs_put_swn_reg(swnreg); 621 cifs_put_swn_reg(swnreg); 622 622 623 return 0; 623 return 0; 624 } 624 } 625 625 626 void cifs_swn_dump(struct seq_file *m) 626 void cifs_swn_dump(struct seq_file *m) 627 { 627 { 628 struct cifs_swn_reg *swnreg; 628 struct cifs_swn_reg *swnreg; 629 struct sockaddr_in *sa; 629 struct sockaddr_in *sa; 630 struct sockaddr_in6 *sa6; 630 struct sockaddr_in6 *sa6; 631 int id; 631 int id; 632 632 633 seq_puts(m, "Witness registrations:"); 633 seq_puts(m, "Witness registrations:"); 634 634 635 mutex_lock(&cifs_swnreg_idr_mutex); 635 mutex_lock(&cifs_swnreg_idr_mutex); 636 idr_for_each_entry(&cifs_swnreg_idr, s 636 idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) { 637 seq_printf(m, "\nId: %u Refs: 637 seq_printf(m, "\nId: %u Refs: %u Network name: '%s'%s Share name: '%s'%s Ip address: ", 638 id, kref_read( 638 id, kref_read(&swnreg->ref_count), 639 swnreg->net_na 639 swnreg->net_name, swnreg->net_name_notify ? "(y)" : "(n)", 640 swnreg->share_ 640 swnreg->share_name, swnreg->share_name_notify ? "(y)" : "(n)"); 641 switch (swnreg->tcon->ses->ser 641 switch (swnreg->tcon->ses->server->dstaddr.ss_family) { 642 case AF_INET: 642 case AF_INET: 643 sa = (struct sockaddr_ 643 sa = (struct sockaddr_in *) &swnreg->tcon->ses->server->dstaddr; 644 seq_printf(m, "%pI4", 644 seq_printf(m, "%pI4", &sa->sin_addr.s_addr); 645 break; 645 break; 646 case AF_INET6: 646 case AF_INET6: 647 sa6 = (struct sockaddr 647 sa6 = (struct sockaddr_in6 *) &swnreg->tcon->ses->server->dstaddr; 648 seq_printf(m, "%pI6", 648 seq_printf(m, "%pI6", &sa6->sin6_addr.s6_addr); 649 if (sa6->sin6_scope_id 649 if (sa6->sin6_scope_id) 650 seq_printf(m, 650 seq_printf(m, "%%%u", sa6->sin6_scope_id); 651 break; 651 break; 652 default: 652 default: 653 seq_puts(m, "(unknown) 653 seq_puts(m, "(unknown)"); 654 } 654 } 655 seq_printf(m, "%s", swnreg->ip 655 seq_printf(m, "%s", swnreg->ip_notify ? "(y)" : "(n)"); 656 } 656 } 657 mutex_unlock(&cifs_swnreg_idr_mutex); 657 mutex_unlock(&cifs_swnreg_idr_mutex); 658 seq_puts(m, "\n"); 658 seq_puts(m, "\n"); 659 } 659 } 660 660 661 void cifs_swn_check(void) 661 void cifs_swn_check(void) 662 { 662 { 663 struct cifs_swn_reg *swnreg; 663 struct cifs_swn_reg *swnreg; 664 int id; 664 int id; 665 int ret; 665 int ret; 666 666 667 mutex_lock(&cifs_swnreg_idr_mutex); 667 mutex_lock(&cifs_swnreg_idr_mutex); 668 idr_for_each_entry(&cifs_swnreg_idr, s 668 idr_for_each_entry(&cifs_swnreg_idr, swnreg, id) { 669 ret = cifs_swn_send_register_m 669 ret = cifs_swn_send_register_message(swnreg); 670 if (ret < 0) 670 if (ret < 0) 671 cifs_dbg(FYI, "%s: Fai 671 cifs_dbg(FYI, "%s: Failed to send register message: %d\n", __func__, ret); 672 } 672 } 673 mutex_unlock(&cifs_swnreg_idr_mutex); 673 mutex_unlock(&cifs_swnreg_idr_mutex); 674 } 674 } 675 675
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.