ReactOS  0.4.12-dev-43-g63b00d8
nfs41_server.c
Go to the documentation of this file.
1 /* NFSv4.1 client for Windows
2  * Copyright 2012 The Regents of the University of Michigan
3  *
4  * Olga Kornievskaia <aglo@umich.edu>
5  * Casey Bodley <cbodley@umich.edu>
6  *
7  * This library is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * without any warranty; without even the implied warranty of merchantability
14  * or fitness for a particular purpose. See the GNU Lesser General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this library; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20  */
21 
22 #include <windows.h>
23 #include <strsafe.h>
24 #include <stdio.h>
25 
26 #include "wintirpc.h"
27 #include "rpc/rpc.h"
28 
29 #include "name_cache.h"
30 #include "daemon_debug.h"
31 #include "nfs41.h"
32 #include "util.h"
33 
34 
35 #define SRVLVL 2 /* dprintf level for server logging */
36 
37 
38 /* nfs41_server_list */
39 struct server_list {
40  struct list_entry head;
42 };
43 static struct server_list g_server_list;
44 
45 #define server_entry(pos) list_container(pos, nfs41_server, entry)
46 
47 
49 {
50  list_init(&g_server_list.head);
52 }
53 
54 /* http://tools.ietf.org/html/rfc5661#section-1.6
55  * 1.6. General Definitions: Server Owner:
56  * "When the client has two connections each to a peer with the same major
57  * identifier, the client assumes that both peers are the same server (the
58  * server namespace is the same via each connection)" */
59 
60 /* http://tools.ietf.org/html/rfc5661#section-2.10.4
61  * 2.10.4. Server Scope
62  * "When the server scope values are the same, server owner value may be
63  * validly compared. In cases where the server scope values are different,
64  * server owner values are treated as different even if they contain all
65  * identical bytes." */
66 
67 /* given these definitions, we require that both the server_owner.major_id
68  * and server_scope are identical when matching instances of nfs41_server */
69 
70 struct server_info {
71  const char *scope;
72  const char *owner;
73 };
74 
75 static int server_compare(
76  const struct list_entry *entry,
77  const void *value)
78 {
79  const nfs41_server *server = server_entry(entry);
80  const struct server_info *info = (const struct server_info*)value;
81  const int diff = strncmp(server->scope, info->scope, NFS4_OPAQUE_LIMIT);
82  return diff ? diff : strncmp(server->owner, info->owner, NFS4_OPAQUE_LIMIT);
83 }
84 
85 static int server_entry_find(
86  IN struct server_list *servers,
87  IN const struct server_info *info,
88  OUT struct list_entry **entry_out)
89 {
90  *entry_out = list_search(&servers->head, info, server_compare);
91  return *entry_out ? NO_ERROR : ERROR_FILE_NOT_FOUND;
92 }
93 
94 static int server_create(
95  IN const struct server_info *info,
96  OUT nfs41_server **server_out)
97 {
98  int status = NO_ERROR;
100 
101  server = calloc(1, sizeof(nfs41_server));
102  if (server == NULL) {
103  status = GetLastError();
104  eprintf("failed to allocate server %s\n", info->owner);
105  goto out;
106  }
107 
108  StringCchCopyA(server->scope, NFS4_OPAQUE_LIMIT, info->scope);
109  StringCchCopyA(server->owner, NFS4_OPAQUE_LIMIT, info->owner);
110  InitializeSRWLock(&server->addrs.lock);
112 
113  status = nfs41_name_cache_create(&server->name_cache);
114  if (status) {
115  eprintf("nfs41_name_cache_create() failed with %d\n", status);
116  goto out_free;
117  }
118 out:
119  *server_out = server;
120  return status;
121 
122 out_free:
123  free(server);
124  server = NULL;
125  goto out;
126 }
127 
128 static void server_free(
130 {
131  dprintf(SRVLVL, "server_free(%s)\n", server->owner);
132  nfs41_superblock_list_free(&server->superblocks);
133  nfs41_name_cache_free(&server->name_cache);
134  free(server);
135 }
136 
137 static __inline void server_ref_locked(
139 {
140  server->ref_count++;
141  dprintf(SRVLVL, "nfs41_server_ref(%s) count %d\n",
142  server->owner, server->ref_count);
143 }
144 
147 {
149 
150  server_ref_locked(server);
151 
153 }
154 
157 {
159 
160  server->ref_count--;
161  dprintf(SRVLVL, "nfs41_server_deref(%s) count %d\n",
162  server->owner, server->ref_count);
163  if (server->ref_count == 0) {
164  list_remove(&server->entry);
165  server_free(server);
166  }
167 
169 }
170 
171 static void server_addrs_add(
172  IN OUT struct server_addrs *addrs,
173  IN const netaddr4 *addr)
174 {
175  /* we keep a list of addrs used to connect to each server. once it gets
176  * bigger than NFS41_ADDRS_PER_SERVER, overwrite the oldest addrs. use
177  * server_addrs.next_index to implement a circular array */
178 
179  AcquireSRWLockExclusive(&addrs->lock);
180 
181  if (multi_addr_find(&addrs->addrs, addr, NULL)) {
182  dprintf(SRVLVL, "server_addrs_add() found existing addr '%s'.\n",
183  addr->uaddr);
184  } else {
185  /* overwrite the address at 'next_index' */
186  StringCchCopyA(addrs->addrs.arr[addrs->next_index].netid,
187  NFS41_NETWORK_ID_LEN+1, addr->netid);
188  StringCchCopyA(addrs->addrs.arr[addrs->next_index].uaddr,
189  NFS41_UNIVERSAL_ADDR_LEN+1, addr->uaddr);
190 
191  /* increment/wrap next_index */
192  addrs->next_index = (addrs->next_index + 1) % NFS41_ADDRS_PER_SERVER;
193  /* update addrs.count if necessary */
194  if (addrs->addrs.count < addrs->next_index)
195  addrs->addrs.count = addrs->next_index;
196 
197  dprintf(SRVLVL, "server_addrs_add() added new addr '%s'.\n",
198  addr->uaddr);
199  }
200  ReleaseSRWLockExclusive(&addrs->lock);
201 }
202 
205  OUT multi_addr4 *addrs)
206 {
207  struct server_addrs *saddrs = &server->addrs;
208  uint32_t i, j;
209 
210  /* make a copy of the server's addrs, with most recent first */
211  AcquireSRWLockShared(&saddrs->lock);
212  j = saddrs->next_index;
213  for (i = 0; i < saddrs->addrs.count; i++) {
214  /* decrement/wrap j */
216  memcpy(&addrs->arr[i], &saddrs->addrs.arr[j], sizeof(netaddr4));
217  }
218  ReleaseSRWLockShared(&saddrs->lock);
219 }
220 
222  IN const char *server_owner_major_id,
223  IN const char *server_scope,
224  IN const netaddr4 *addr,
225  OUT nfs41_server **server_out)
226 {
227  struct server_info info;
228  struct list_entry *entry;
230  int status;
231 
232  info.owner = server_owner_major_id;
233  info.scope = server_scope;
234 
235  dprintf(SRVLVL, "--> nfs41_server_find_or_create(%s)\n", info.owner);
236 
238 
239  /* search for an existing server */
240  entry = list_search(&g_server_list.head, &info, server_compare);
241  if (entry == NULL) {
242  /* create a new server */
243  status = server_create(&info, &server);
244  if (status == NO_ERROR) {
245  /* add it to the list */
246  list_add_tail(&g_server_list.head, &server->entry);
247  *server_out = server;
248 
249  dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
250  "returning new server %p\n", server);
251  } else {
252  dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
253  "returning %d\n", status);
254  }
255  } else {
256  server = server_entry(entry);
257  status = NO_ERROR;
258 
259  dprintf(SRVLVL, "<-- nfs41_server_find_or_create() "
260  "returning existing server %p\n", server);
261  }
262 
263  if (server) {
264  /* register the address used to connect */
265  server_addrs_add(&server->addrs, addr);
266 
267  server_ref_locked(server);
268  }
269 
270  *server_out = server;
272  return status;
273 }
274 
276  IN const char *hostname,
277  IN unsigned short port,
278  OUT multi_addr4 *addrs)
279 {
281  char service[16];
282  struct addrinfo hints = { 0 }, *res, *info;
283  struct netconfig *nconf;
284  struct netbuf addr;
285  char *netid, *uaddr;
286 
287  dprintf(SRVLVL, "--> nfs41_server_resolve(%s:%u)\n",
288  hostname, port);
289 
290  addrs->count = 0;
291 
292  StringCchPrintfA(service, 16, "%u", port);
293 
294  /* request a list of tcp addrs for the given hostname,port */
295  hints.ai_family = AF_UNSPEC;
296  hints.ai_socktype = SOCK_STREAM;
297  hints.ai_protocol = IPPROTO_TCP;
298 
299  if (getaddrinfo(hostname, service, &hints, &res) != 0)
300  goto out;
301 
302  for (info = res; info != NULL; info = info->ai_next) {
303  /* find the appropriate entry in /etc/netconfig */
304  switch (info->ai_family) {
305  case AF_INET: netid = "tcp"; break;
306  case AF_INET6: netid = "tcp6"; break;
307  default: continue;
308  }
309 
310  nconf = getnetconfigent(netid);
311  if (nconf == NULL)
312  continue;
313 
314  /* convert to a transport-independent universal address */
315  addr.buf = info->ai_addr;
316  addr.maxlen = addr.len = (unsigned int)info->ai_addrlen;
317 
318  uaddr = taddr2uaddr(nconf, &addr);
319  freenetconfigent(nconf);
320 
321  if (uaddr == NULL)
322  continue;
323 
324  StringCchCopyA(addrs->arr[addrs->count].netid,
325  NFS41_NETWORK_ID_LEN+1, netid);
326  StringCchCopyA(addrs->arr[addrs->count].uaddr,
327  NFS41_UNIVERSAL_ADDR_LEN+1, uaddr);
328  freeuaddr(uaddr);
329 
330  status = NO_ERROR;
331  if (++addrs->count >= NFS41_ADDRS_PER_SERVER)
332  break;
333  }
334  freeaddrinfo(res);
335 out:
336  if (status)
337  dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
338  "error %d\n", hostname, port, status);
339  else
340  dprintf(SRVLVL, "<-- nfs41_server_resolve(%s:%u) returning "
341  "%s\n", hostname, port, addrs->arr[0].uaddr);
342  return status;
343 }
char owner[NFS4_OPAQUE_LIMIT]
Definition: nfs41.h:81
VOID WINAPI AcquireSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:54
#define IN
Definition: typedefs.h:38
CRITICAL_SECTION lock
Definition: nfs41_server.c:41
static int server_create(IN const struct server_info *info, OUT nfs41_server **server_out)
Definition: nfs41_server.c:94
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble const GLfloat const GLdouble const GLfloat GLenum GLint GLint GLint GLint GLint GLint j
Definition: glfuncs.h:98
Definition: get.c:139
static rfbScreenInfoPtr server
Definition: vnc.c:74
#define freeaddrinfo
Definition: wspiapi.h:46
struct list_entry head
Definition: nfs41_server.c:40
void nfs41_server_ref(IN nfs41_server *server)
Definition: nfs41_server.c:145
int nfs41_name_cache_free(IN struct nfs41_name_cache **cache_out)
Definition: name_cache.c:796
static void server_addrs_add(IN OUT struct server_addrs *addrs, IN const netaddr4 *addr)
Definition: nfs41_server.c:171
#define ERROR_BAD_NET_NAME
Definition: winerror.h:159
#define free
Definition: debug_ros.c:5
multi_addr4 addrs
Definition: nfs41.h:74
uint8_t entry
Definition: isohybrid.c:63
static __inline void server_ref_locked(IN nfs41_server *server)
Definition: nfs41_server.c:137
const char * owner
Definition: nfs41_server.c:72
int nfs41_server_resolve(IN const char *hostname, IN unsigned short port, OUT multi_addr4 *addrs)
Definition: nfs41_server.c:275
void nfs41_superblock_list_init(IN nfs41_superblock_list *superblocks)
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
struct server_addrs addrs
Definition: nfs41.h:82
void * buf
Definition: types.h:147
void eprintf(LPCSTR format,...)
Definition: daemon_debug.c:86
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define NO_ERROR
Definition: dderror.h:5
struct _test_info info[]
Definition: SetCursorPos.c:19
char * hostname
Definition: ftp.c:88
static struct server_list g_server_list
Definition: nfs41_server.c:43
__WINE_SERVER_LIST_INLINE void list_add_tail(struct list *list, struct list *elem)
Definition: list.h:102
void freeuaddr(char *uaddr)
Definition: rpc_generic.c:628
GLenum GLclampf GLint i
Definition: glfuncs.h:14
struct nfs41_name_cache * name_cache
Definition: nfs41.h:84
struct list_entry entry
Definition: nfs41.h:85
#define dprintf
Definition: regdump.c:33
void freenetconfigent(struct netconfig *netconfigp)
Definition: getnetconfig.c:530
STRSAFEAPI StringCchPrintfA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszFormat,...)
Definition: strsafe.h:520
#define NFS4_OPAQUE_LIMIT
Definition: nfs41_const.h:31
VOID WINAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection)
Definition: synch.c:697
smooth NULL
Definition: ftsmooth.c:416
struct netconfig * getnetconfigent(char *netid) const
Definition: getnetconfig.c:432
#define AF_INET6
Definition: winsock.h:369
#define AF_UNSPEC
Definition: winsock.h:344
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static void server_free(IN nfs41_server *server)
Definition: nfs41_server.c:128
SRWLOCK lock
Definition: nfs41.h:76
__WINE_SERVER_LIST_INLINE void list_remove(struct list *elem)
Definition: list.h:108
void nfs41_server_deref(IN nfs41_server *server)
Definition: nfs41_server.c:155
void nfs41_server_addrs(IN nfs41_server *server, OUT multi_addr4 *addrs)
Definition: nfs41_server.c:203
#define NFS41_ADDRS_PER_SERVER
Definition: nfs41_const.h:49
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static FILE * out
Definition: regtests2xml.c:44
unsigned int maxlen
Definition: types.h:145
const char * scope
Definition: nfs41_server.c:71
unsigned int len
Definition: types.h:146
#define NFS41_UNIVERSAL_ADDR_LEN
Definition: nfs41_const.h:53
GLenum const GLvoid * addr
Definition: glext.h:9621
VOID WINAPI ReleaseSRWLockExclusive(PSRWLOCK Lock)
Definition: sync.c:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
uint32_t count
Definition: nfs41_types.h:92
VOID WINAPI InitializeSRWLock(PSRWLOCK Lock)
Definition: sync.c:75
char scope[NFS4_OPAQUE_LIMIT]
Definition: nfs41.h:80
void nfs41_server_list_init()
Definition: nfs41_server.c:48
int ai_protocol
Definition: ws2def.h:668
static struct list_entry * list_search(const struct list_entry *head, const void *value, list_compare_fn compare)
Definition: list.h:102
nfs41_superblock_list superblocks
Definition: nfs41.h:83
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
int ai_socktype
Definition: ws2def.h:667
Definition: list.h:27
UINT32 uint32_t
Definition: types.h:75
static int server_entry_find(IN struct server_list *servers, IN const struct server_info *info, OUT struct list_entry **entry_out)
Definition: nfs41_server.c:85
Definition: types.h:144
#define NFS41_NETWORK_ID_LEN
Definition: nfs41_const.h:56
#define calloc
Definition: rosglue.h:14
#define OUT
Definition: typedefs.h:39
GLuint res
Definition: glext.h:9613
__WINE_SERVER_LIST_INLINE void list_init(struct list *list)
Definition: list.h:149
uint32_t next_index
Definition: nfs41.h:75
#define AF_INET
Definition: tcpip.h:117
#define SRVLVL
Definition: nfs41_server.c:35
netaddr4 arr[NFS41_ADDRS_PER_SERVER]
Definition: nfs41_types.h:91
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
char * taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
Definition: rpc_generic.c:609
#define SOCK_STREAM
Definition: tcpip.h:118
int nfs41_server_find_or_create(IN const char *server_owner_major_id, IN const char *server_scope, IN const netaddr4 *addr, OUT nfs41_server **server_out)
Definition: nfs41_server.c:221
USHORT port
Definition: uri.c:227
static SERVICE_STATUS status
Definition: service.c:31
bool_t multi_addr_find(IN const multi_addr4 *addrs, IN const netaddr4 *addr, OUT OPTIONAL uint32_t *index_out)
Definition: util.c:218
void nfs41_superblock_list_free(IN nfs41_superblock_list *superblocks)
static int server_compare(const struct list_entry *entry, const void *value)
Definition: nfs41_server.c:75
VOID WINAPI AcquireSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:61
VOID WINAPI ReleaseSRWLockShared(PSRWLOCK Lock)
Definition: sync.c:89
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29
#define server_entry(pos)
Definition: nfs41_server.c:45
#define getaddrinfo
Definition: wspiapi.h:44
Definition: ps.c:97
int nfs41_name_cache_create(OUT struct nfs41_name_cache **cache_out)
Definition: name_cache.c:752
int ai_family
Definition: ws2def.h:666