Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : /* 3 : : * linux/include/linux/lockd/lockd.h 4 : : * 5 : : * General-purpose lockd include file. 6 : : * 7 : : * Copyright (C) 1996 Olaf Kirch <okir@monad.swb.de> 8 : : */ 9 : : 10 : : #ifndef LINUX_LOCKD_LOCKD_H 11 : : #define LINUX_LOCKD_LOCKD_H 12 : : 13 : : #ifdef __KERNEL__ 14 : : 15 : : #include <linux/in.h> 16 : : #include <linux/in6.h> 17 : : #include <net/ipv6.h> 18 : : #include <linux/fs.h> 19 : : #include <linux/kref.h> 20 : : #include <linux/refcount.h> 21 : : #include <linux/utsname.h> 22 : : #include <linux/lockd/bind.h> 23 : : #include <linux/lockd/xdr.h> 24 : : #ifdef CONFIG_LOCKD_V4 25 : : #include <linux/lockd/xdr4.h> 26 : : #endif 27 : : #include <linux/lockd/debug.h> 28 : : #include <linux/sunrpc/svc.h> 29 : : 30 : : /* 31 : : * Version string 32 : : */ 33 : : #define LOCKD_VERSION "0.5" 34 : : 35 : : /* 36 : : * Default timeout for RPC calls (seconds) 37 : : */ 38 : : #define LOCKD_DFLT_TIMEO 10 39 : : 40 : : /* 41 : : * Lockd host handle (used both by the client and server personality). 42 : : */ 43 : : struct nlm_host { 44 : : struct hlist_node h_hash; /* doubly linked list */ 45 : : struct sockaddr_storage h_addr; /* peer address */ 46 : : size_t h_addrlen; 47 : : struct sockaddr_storage h_srcaddr; /* our address (optional) */ 48 : : size_t h_srcaddrlen; 49 : : struct rpc_clnt *h_rpcclnt; /* RPC client to talk to peer */ 50 : : char *h_name; /* remote hostname */ 51 : : u32 h_version; /* interface version */ 52 : : unsigned short h_proto; /* transport proto */ 53 : : unsigned short h_reclaiming : 1, 54 : : h_server : 1, /* server side, not client side */ 55 : : h_noresvport : 1, 56 : : h_inuse : 1; 57 : : wait_queue_head_t h_gracewait; /* wait while reclaiming */ 58 : : struct rw_semaphore h_rwsem; /* Reboot recovery lock */ 59 : : u32 h_state; /* pseudo-state counter */ 60 : : u32 h_nsmstate; /* true remote NSM state */ 61 : : u32 h_pidcount; /* Pseudopids */ 62 : : refcount_t h_count; /* reference count */ 63 : : struct mutex h_mutex; /* mutex for pmap binding */ 64 : : unsigned long h_nextrebind; /* next portmap call */ 65 : : unsigned long h_expires; /* eligible for GC */ 66 : : struct list_head h_lockowners; /* Lockowners for the client */ 67 : : spinlock_t h_lock; 68 : : struct list_head h_granted; /* Locks in GRANTED state */ 69 : : struct list_head h_reclaim; /* Locks in RECLAIM state */ 70 : : struct nsm_handle *h_nsmhandle; /* NSM status handle */ 71 : : char *h_addrbuf; /* address eyecatcher */ 72 : : struct net *net; /* host net */ 73 : : const struct cred *h_cred; 74 : : char nodename[UNX_MAXNODENAME + 1]; 75 : : const struct nlmclnt_operations *h_nlmclnt_ops; /* Callback ops for NLM users */ 76 : : }; 77 : : 78 : : /* 79 : : * The largest string sm_addrbuf should hold is a full-size IPv6 address 80 : : * (no "::" anywhere) with a scope ID. The buffer size is computed to 81 : : * hold eight groups of colon-separated four-hex-digit numbers, a 82 : : * percent sign, a scope id (at most 32 bits, in decimal), and NUL. 83 : : */ 84 : : #define NSM_ADDRBUF ((8 * 4 + 7) + (1 + 10) + 1) 85 : : 86 : : struct nsm_handle { 87 : : struct list_head sm_link; 88 : : refcount_t sm_count; 89 : : char *sm_mon_name; 90 : : char *sm_name; 91 : : struct sockaddr_storage sm_addr; 92 : : size_t sm_addrlen; 93 : : unsigned int sm_monitored : 1, 94 : : sm_sticky : 1; /* don't unmonitor */ 95 : : struct nsm_private sm_priv; 96 : : char sm_addrbuf[NSM_ADDRBUF]; 97 : : }; 98 : : 99 : : /* 100 : : * Rigorous type checking on sockaddr type conversions 101 : : */ 102 : : static inline struct sockaddr_in *nlm_addr_in(const struct nlm_host *host) 103 : : { 104 : : return (struct sockaddr_in *)&host->h_addr; 105 : : } 106 : : 107 : : static inline struct sockaddr *nlm_addr(const struct nlm_host *host) 108 : : { 109 : 0 : return (struct sockaddr *)&host->h_addr; 110 : : } 111 : : 112 : : static inline struct sockaddr_in *nlm_srcaddr_in(const struct nlm_host *host) 113 : : { 114 : : return (struct sockaddr_in *)&host->h_srcaddr; 115 : : } 116 : : 117 : : static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) 118 : : { 119 : 0 : return (struct sockaddr *)&host->h_srcaddr; 120 : : } 121 : : 122 : : /* 123 : : * Map an fl_owner_t into a unique 32-bit "pid" 124 : : */ 125 : : struct nlm_lockowner { 126 : : struct list_head list; 127 : : refcount_t count; 128 : : 129 : : struct nlm_host *host; 130 : : fl_owner_t owner; 131 : : uint32_t pid; 132 : : }; 133 : : 134 : : struct nlm_wait; 135 : : 136 : : /* 137 : : * Memory chunk for NLM client RPC request. 138 : : */ 139 : : #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u) 140 : : struct nlm_rqst { 141 : : refcount_t a_count; 142 : : unsigned int a_flags; /* initial RPC task flags */ 143 : : struct nlm_host * a_host; /* host handle */ 144 : : struct nlm_args a_args; /* arguments */ 145 : : struct nlm_res a_res; /* result */ 146 : : struct nlm_block * a_block; 147 : : unsigned int a_retries; /* Retry count */ 148 : : u8 a_owner[NLMCLNT_OHSIZE]; 149 : : void * a_callback_data; /* sent to nlmclnt_operations callbacks */ 150 : : }; 151 : : 152 : : /* 153 : : * This struct describes a file held open by lockd on behalf of 154 : : * an NFS client. 155 : : */ 156 : : struct nlm_file { 157 : : struct hlist_node f_list; /* linked list */ 158 : : struct nfs_fh f_handle; /* NFS file handle */ 159 : : struct file * f_file; /* VFS file pointer */ 160 : : struct nlm_share * f_shares; /* DOS shares */ 161 : : struct list_head f_blocks; /* blocked locks */ 162 : : unsigned int f_locks; /* guesstimate # of locks */ 163 : : unsigned int f_count; /* reference count */ 164 : : struct mutex f_mutex; /* avoid concurrent access */ 165 : : }; 166 : : 167 : : /* 168 : : * This is a server block (i.e. a lock requested by some client which 169 : : * couldn't be granted because of a conflicting lock). 170 : : */ 171 : : #define NLM_NEVER (~(unsigned long) 0) 172 : : /* timeout on non-blocking call: */ 173 : : #define NLM_TIMEOUT (7 * HZ) 174 : : 175 : : struct nlm_block { 176 : : struct kref b_count; /* Reference count */ 177 : : struct list_head b_list; /* linked list of all blocks */ 178 : : struct list_head b_flist; /* linked list (per file) */ 179 : : struct nlm_rqst * b_call; /* RPC args & callback info */ 180 : : struct svc_serv * b_daemon; /* NLM service */ 181 : : struct nlm_host * b_host; /* host handle for RPC clnt */ 182 : : unsigned long b_when; /* next re-xmit */ 183 : : unsigned int b_id; /* block id */ 184 : : unsigned char b_granted; /* VFS granted lock */ 185 : : struct nlm_file * b_file; /* file in question */ 186 : : struct cache_req * b_cache_req; /* deferred request handling */ 187 : : struct cache_deferred_req * b_deferred_req; 188 : : unsigned int b_flags; /* block flags */ 189 : : #define B_QUEUED 1 /* lock queued */ 190 : : #define B_GOT_CALLBACK 2 /* got lock or conflicting lock */ 191 : : #define B_TIMED_OUT 4 /* filesystem too slow to respond */ 192 : : }; 193 : : 194 : : /* 195 : : * Global variables 196 : : */ 197 : : extern const struct rpc_program nlm_program; 198 : : extern const struct svc_procedure nlmsvc_procedures[]; 199 : : #ifdef CONFIG_LOCKD_V4 200 : : extern const struct svc_procedure nlmsvc_procedures4[]; 201 : : #endif 202 : : extern int nlmsvc_grace_period; 203 : : extern unsigned long nlmsvc_timeout; 204 : : extern bool nsm_use_hostnames; 205 : : extern u32 nsm_local_state; 206 : : 207 : : /* 208 : : * Lockd client functions 209 : : */ 210 : : struct nlm_rqst * nlm_alloc_call(struct nlm_host *host); 211 : : int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); 212 : : int nlm_async_reply(struct nlm_rqst *, u32, const struct rpc_call_ops *); 213 : : void nlmclnt_release_call(struct nlm_rqst *); 214 : : struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); 215 : : void nlmclnt_finish_block(struct nlm_wait *block); 216 : : int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); 217 : : __be32 nlmclnt_grant(const struct sockaddr *addr, 218 : : const struct nlm_lock *lock); 219 : : void nlmclnt_recovery(struct nlm_host *); 220 : : int nlmclnt_reclaim(struct nlm_host *, struct file_lock *, 221 : : struct nlm_rqst *); 222 : : void nlmclnt_next_cookie(struct nlm_cookie *); 223 : : 224 : : /* 225 : : * Host cache 226 : : */ 227 : : struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, 228 : : const size_t salen, 229 : : const unsigned short protocol, 230 : : const u32 version, 231 : : const char *hostname, 232 : : int noresvport, 233 : : struct net *net, 234 : : const struct cred *cred); 235 : : void nlmclnt_release_host(struct nlm_host *); 236 : : struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, 237 : : const char *hostname, 238 : : const size_t hostname_len); 239 : : void nlmsvc_release_host(struct nlm_host *); 240 : : struct rpc_clnt * nlm_bind_host(struct nlm_host *); 241 : : void nlm_rebind_host(struct nlm_host *); 242 : : struct nlm_host * nlm_get_host(struct nlm_host *); 243 : : void nlm_shutdown_hosts(void); 244 : : void nlm_shutdown_hosts_net(struct net *net); 245 : : void nlm_host_rebooted(const struct net *net, 246 : : const struct nlm_reboot *); 247 : : 248 : : /* 249 : : * Host monitoring 250 : : */ 251 : : int nsm_monitor(const struct nlm_host *host); 252 : : void nsm_unmonitor(const struct nlm_host *host); 253 : : 254 : : struct nsm_handle *nsm_get_handle(const struct net *net, 255 : : const struct sockaddr *sap, 256 : : const size_t salen, 257 : : const char *hostname, 258 : : const size_t hostname_len); 259 : : struct nsm_handle *nsm_reboot_lookup(const struct net *net, 260 : : const struct nlm_reboot *info); 261 : : void nsm_release(struct nsm_handle *nsm); 262 : : 263 : : /* 264 : : * This is used in garbage collection and resource reclaim 265 : : * A return value != 0 means destroy the lock/block/share 266 : : */ 267 : : typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); 268 : : 269 : : /* 270 : : * Server-side lock handling 271 : : */ 272 : : __be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, 273 : : struct nlm_host *, struct nlm_lock *, int, 274 : : struct nlm_cookie *, int); 275 : : __be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *); 276 : : __be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, 277 : : struct nlm_host *, struct nlm_lock *, 278 : : struct nlm_lock *, struct nlm_cookie *); 279 : : __be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *); 280 : : unsigned long nlmsvc_retry_blocked(void); 281 : : void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, 282 : : nlm_host_match_fn_t match); 283 : : void nlmsvc_grant_reply(struct nlm_cookie *, __be32); 284 : : void nlmsvc_release_call(struct nlm_rqst *); 285 : : void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t); 286 : : 287 : : /* 288 : : * File handling for the server personality 289 : : */ 290 : : __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, 291 : : struct nfs_fh *); 292 : : void nlm_release_file(struct nlm_file *); 293 : : void nlmsvc_release_lockowner(struct nlm_lock *); 294 : : void nlmsvc_mark_resources(struct net *); 295 : : void nlmsvc_free_host_resources(struct nlm_host *); 296 : : void nlmsvc_invalidate_all(void); 297 : : 298 : : /* 299 : : * Cluster failover support 300 : : */ 301 : : int nlmsvc_unlock_all_by_sb(struct super_block *sb); 302 : : int nlmsvc_unlock_all_by_ip(struct sockaddr *server_addr); 303 : : 304 : : static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) 305 : : { 306 : 0 : return locks_inode(file->f_file); 307 : : } 308 : : 309 : : static inline int __nlm_privileged_request4(const struct sockaddr *sap) 310 : : { 311 : : const struct sockaddr_in *sin = (struct sockaddr_in *)sap; 312 : : 313 : 0 : if (ntohs(sin->sin_port) > 1023) 314 : : return 0; 315 : : 316 : 0 : return ipv4_is_loopback(sin->sin_addr.s_addr); 317 : : } 318 : : 319 : : #if IS_ENABLED(CONFIG_IPV6) 320 : 0 : static inline int __nlm_privileged_request6(const struct sockaddr *sap) 321 : : { 322 : : const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap; 323 : : 324 : 0 : if (ntohs(sin6->sin6_port) > 1023) 325 : : return 0; 326 : : 327 : 0 : if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_MAPPED) 328 : 0 : return ipv4_is_loopback(sin6->sin6_addr.s6_addr32[3]); 329 : : 330 : 0 : return ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LOOPBACK; 331 : : } 332 : : #else /* IS_ENABLED(CONFIG_IPV6) */ 333 : : static inline int __nlm_privileged_request6(const struct sockaddr *sap) 334 : : { 335 : : return 0; 336 : : } 337 : : #endif /* IS_ENABLED(CONFIG_IPV6) */ 338 : : 339 : : /* 340 : : * Ensure incoming requests are from local privileged callers. 341 : : * 342 : : * Return TRUE if sender is local and is connecting via a privileged port; 343 : : * otherwise return FALSE. 344 : : */ 345 : 0 : static inline int nlm_privileged_requester(const struct svc_rqst *rqstp) 346 : : { 347 : : const struct sockaddr *sap = svc_addr(rqstp); 348 : : 349 : 0 : switch (sap->sa_family) { 350 : : case AF_INET: 351 : 0 : return __nlm_privileged_request4(sap); 352 : : case AF_INET6: 353 : 0 : return __nlm_privileged_request6(sap); 354 : : default: 355 : : return 0; 356 : : } 357 : : } 358 : : 359 : : /* 360 : : * Compare two NLM locks. 361 : : * When the second lock is of type F_UNLCK, this acts like a wildcard. 362 : : */ 363 : 0 : static inline int nlm_compare_locks(const struct file_lock *fl1, 364 : : const struct file_lock *fl2) 365 : : { 366 : 0 : return locks_inode(fl1->fl_file) == locks_inode(fl2->fl_file) 367 : 0 : && fl1->fl_pid == fl2->fl_pid 368 : 0 : && fl1->fl_owner == fl2->fl_owner 369 : 0 : && fl1->fl_start == fl2->fl_start 370 : 0 : && fl1->fl_end == fl2->fl_end 371 : 0 : &&(fl1->fl_type == fl2->fl_type || fl2->fl_type == F_UNLCK); 372 : : } 373 : : 374 : : extern const struct lock_manager_operations nlmsvc_lock_operations; 375 : : 376 : : #endif /* __KERNEL__ */ 377 : : 378 : : #endif /* LINUX_LOCKD_LOCKD_H */