b9077a3dc1ac841ab1e268369fcb836b07010e27
[reactos.git] / dll / win32 / rpcrt4 / rpc_transport.c
1 /*
2 * RPC transport layer
3 *
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
5 * Copyright 2003 Mike Hearn
6 * Copyright 2004 Filip Navara
7 * Copyright 2006 Mike McCormack
8 * Copyright 2006 Damjan Jovanovic
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 *
24 */
25
26 #include "config.h"
27
28 #include <stdarg.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <sys/types.h>
34
35 #if defined(__MINGW32__) || defined (_MSC_VER)
36 # include <ws2tcpip.h>
37 # ifndef EADDRINUSE
38 # define EADDRINUSE WSAEADDRINUSE
39 # endif
40 # ifndef EAGAIN
41 # define EAGAIN WSAEWOULDBLOCK
42 # endif
43 #else
44 # include <errno.h>
45 # ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 # endif
48 # include <fcntl.h>
49 # ifdef HAVE_SYS_SOCKET_H
50 # include <sys/socket.h>
51 # endif
52 # ifdef HAVE_NETINET_IN_H
53 # include <netinet/in.h>
54 # endif
55 # ifdef HAVE_NETINET_TCP_H
56 # include <netinet/tcp.h>
57 # endif
58 # ifdef HAVE_ARPA_INET_H
59 # include <arpa/inet.h>
60 # endif
61 # ifdef HAVE_NETDB_H
62 # include <netdb.h>
63 # endif
64 # ifdef HAVE_SYS_POLL_H
65 # include <sys/poll.h>
66 # endif
67 # define closesocket close
68 #endif /* defined(__MINGW32__) || defined (_MSC_VER) */
69
70 #include <winsock2.h>
71 #include <ws2tcpip.h>
72
73 #include "windef.h"
74 #include "winbase.h"
75 #include "winnls.h"
76 #include "winerror.h"
77 #include "winternl.h"
78 #include "wine/unicode.h"
79
80 #include "rpc.h"
81 #include "rpcndr.h"
82
83 #include "wine/debug.h"
84
85 #include "rpc_binding.h"
86 #include "rpc_message.h"
87 #include "rpc_server.h"
88 #include "epm_towers.h"
89
90 #include "unix_func.h"
91
92 #ifndef SOL_TCP
93 # define SOL_TCP IPPROTO_TCP
94 #endif
95
96 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
97
98 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection);
99
100 /**** ncacn_np support ****/
101
102 typedef struct _RpcConnection_np
103 {
104 RpcConnection common;
105 HANDLE pipe;
106 OVERLAPPED ovl[2];
107 BOOL listening;
108 } RpcConnection_np;
109
110 static RpcConnection *rpcrt4_conn_np_alloc(void)
111 {
112 RpcConnection_np *npc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_np));
113 if (npc)
114 {
115 npc->pipe = NULL;
116 memset(&npc->ovl, 0, sizeof(npc->ovl));
117 npc->listening = FALSE;
118 }
119 return &npc->common;
120 }
121
122 static RPC_STATUS rpcrt4_conn_listen_pipe(RpcConnection_np *npc)
123 {
124 if (npc->listening)
125 return RPC_S_OK;
126
127 npc->listening = TRUE;
128 for (;;)
129 {
130 if (ConnectNamedPipe(npc->pipe, &npc->ovl[0]))
131 return RPC_S_OK;
132
133 switch(GetLastError())
134 {
135 case ERROR_PIPE_CONNECTED:
136 SetEvent(npc->ovl[0].hEvent);
137 return RPC_S_OK;
138 case ERROR_IO_PENDING:
139 /* will be completed in rpcrt4_protseq_np_wait_for_new_connection */
140 return RPC_S_OK;
141 case ERROR_NO_DATA_DETECTED:
142 /* client has disconnected, retry */
143 DisconnectNamedPipe( npc->pipe );
144 break;
145 default:
146 npc->listening = FALSE;
147 WARN("Couldn't ConnectNamedPipe (error was %d)\n", GetLastError());
148 return RPC_S_OUT_OF_RESOURCES;
149 }
150 }
151 }
152
153 static RPC_STATUS rpcrt4_conn_create_pipe(RpcConnection *Connection, LPCSTR pname)
154 {
155 RpcConnection_np *npc = (RpcConnection_np *) Connection;
156 TRACE("listening on %s\n", pname);
157
158 npc->pipe = CreateNamedPipeA(pname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
159 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
160 PIPE_UNLIMITED_INSTANCES,
161 RPC_MAX_PACKET_SIZE, RPC_MAX_PACKET_SIZE, 5000, NULL);
162 if (npc->pipe == INVALID_HANDLE_VALUE) {
163 WARN("CreateNamedPipe failed with error %d\n", GetLastError());
164 if (GetLastError() == ERROR_FILE_EXISTS)
165 return RPC_S_DUPLICATE_ENDPOINT;
166 else
167 return RPC_S_CANT_CREATE_ENDPOINT;
168 }
169
170 memset(&npc->ovl, 0, sizeof(npc->ovl));
171 npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
172 npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
173
174 /* Note: we don't call ConnectNamedPipe here because it must be done in the
175 * server thread as the thread must be alertable */
176 return RPC_S_OK;
177 }
178
179 static RPC_STATUS rpcrt4_conn_open_pipe(RpcConnection *Connection, LPCSTR pname, BOOL wait)
180 {
181 RpcConnection_np *npc = (RpcConnection_np *) Connection;
182 HANDLE pipe;
183 DWORD err, dwMode;
184
185 TRACE("connecting to %s\n", pname);
186
187 while (TRUE) {
188 DWORD dwFlags = 0;
189 if (Connection->QOS)
190 {
191 dwFlags = SECURITY_SQOS_PRESENT;
192 switch (Connection->QOS->qos->ImpersonationType)
193 {
194 case RPC_C_IMP_LEVEL_DEFAULT:
195 /* FIXME: what to do here? */
196 break;
197 case RPC_C_IMP_LEVEL_ANONYMOUS:
198 dwFlags |= SECURITY_ANONYMOUS;
199 break;
200 case RPC_C_IMP_LEVEL_IDENTIFY:
201 dwFlags |= SECURITY_IDENTIFICATION;
202 break;
203 case RPC_C_IMP_LEVEL_IMPERSONATE:
204 dwFlags |= SECURITY_IMPERSONATION;
205 break;
206 case RPC_C_IMP_LEVEL_DELEGATE:
207 dwFlags |= SECURITY_DELEGATION;
208 break;
209 }
210 if (Connection->QOS->qos->IdentityTracking == RPC_C_QOS_IDENTITY_DYNAMIC)
211 dwFlags |= SECURITY_CONTEXT_TRACKING;
212 }
213 pipe = CreateFileA(pname, GENERIC_READ|GENERIC_WRITE, 0, NULL,
214 OPEN_EXISTING, dwFlags, 0);
215 if (pipe != INVALID_HANDLE_VALUE) break;
216 err = GetLastError();
217 if (err == ERROR_PIPE_BUSY) {
218 TRACE("connection failed, error=%x\n", err);
219 return RPC_S_SERVER_TOO_BUSY;
220 }
221 if (!wait || !WaitNamedPipeA(pname, NMPWAIT_WAIT_FOREVER)) {
222 err = GetLastError();
223 WARN("connection failed, error=%x\n", err);
224 return RPC_S_SERVER_UNAVAILABLE;
225 }
226 }
227
228 /* success */
229 memset(&npc->ovl, 0, sizeof(npc->ovl));
230 /* pipe is connected; change to message-read mode. */
231 dwMode = PIPE_READMODE_MESSAGE;
232 SetNamedPipeHandleState(pipe, &dwMode, NULL, NULL);
233 npc->ovl[0].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
234 npc->ovl[1].hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
235 npc->pipe = pipe;
236
237 return RPC_S_OK;
238 }
239
240 static RPC_STATUS rpcrt4_ncalrpc_open(RpcConnection* Connection)
241 {
242 RpcConnection_np *npc = (RpcConnection_np *) Connection;
243 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
244 RPC_STATUS r;
245 LPSTR pname;
246
247 /* already connected? */
248 if (npc->pipe)
249 return RPC_S_OK;
250
251 /* protseq=ncalrpc: supposed to use NT LPC ports,
252 * but we'll implement it with named pipes for now */
253 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
254 strcat(strcpy(pname, prefix), Connection->Endpoint);
255 r = rpcrt4_conn_open_pipe(Connection, pname, TRUE);
256 I_RpcFree(pname);
257
258 return r;
259 }
260
261 static RPC_STATUS rpcrt4_protseq_ncalrpc_open_endpoint(RpcServerProtseq* protseq, LPSTR endpoint)
262 {
263 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
264 RPC_STATUS r;
265 LPSTR pname;
266 RpcConnection *Connection;
267
268 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
269 endpoint, NULL, NULL, NULL);
270 if (r != RPC_S_OK)
271 return r;
272
273 /* protseq=ncalrpc: supposed to use NT LPC ports,
274 * but we'll implement it with named pipes for now */
275 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
276 strcat(strcpy(pname, prefix), Connection->Endpoint);
277 r = rpcrt4_conn_create_pipe(Connection, pname);
278 I_RpcFree(pname);
279
280 EnterCriticalSection(&protseq->cs);
281 Connection->Next = protseq->conn;
282 protseq->conn = Connection;
283 LeaveCriticalSection(&protseq->cs);
284
285 return r;
286 }
287
288 static RPC_STATUS rpcrt4_ncacn_np_open(RpcConnection* Connection)
289 {
290 RpcConnection_np *npc = (RpcConnection_np *) Connection;
291 static const char prefix[] = "\\\\.";
292 RPC_STATUS r;
293 LPSTR pname;
294
295 /* already connected? */
296 if (npc->pipe)
297 return RPC_S_OK;
298
299 /* protseq=ncacn_np: named pipes */
300 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
301 strcat(strcpy(pname, prefix), Connection->Endpoint);
302 r = rpcrt4_conn_open_pipe(Connection, pname, FALSE);
303 I_RpcFree(pname);
304
305 return r;
306 }
307
308 static RPC_STATUS rpcrt4_protseq_ncacn_np_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
309 {
310 static const char prefix[] = "\\\\.";
311 RPC_STATUS r;
312 LPSTR pname;
313 RpcConnection *Connection;
314
315 r = RPCRT4_CreateConnection(&Connection, TRUE, protseq->Protseq, NULL,
316 endpoint, NULL, NULL, NULL);
317 if (r != RPC_S_OK)
318 return r;
319
320 /* protseq=ncacn_np: named pipes */
321 pname = I_RpcAllocate(strlen(prefix) + strlen(Connection->Endpoint) + 1);
322 strcat(strcpy(pname, prefix), Connection->Endpoint);
323 r = rpcrt4_conn_create_pipe(Connection, pname);
324 I_RpcFree(pname);
325
326 EnterCriticalSection(&protseq->cs);
327 Connection->Next = protseq->conn;
328 protseq->conn = Connection;
329 LeaveCriticalSection(&protseq->cs);
330
331 return r;
332 }
333
334 static void rpcrt4_conn_np_handoff(RpcConnection_np *old_npc, RpcConnection_np *new_npc)
335 {
336 /* because of the way named pipes work, we'll transfer the connected pipe
337 * to the child, then reopen the server binding to continue listening */
338
339 new_npc->pipe = old_npc->pipe;
340 new_npc->ovl[0] = old_npc->ovl[0];
341 new_npc->ovl[1] = old_npc->ovl[1];
342 old_npc->pipe = 0;
343 memset(&old_npc->ovl, 0, sizeof(old_npc->ovl));
344 old_npc->listening = FALSE;
345 }
346
347 static RPC_STATUS rpcrt4_ncacn_np_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
348 {
349 RPC_STATUS status;
350 LPSTR pname;
351 static const char prefix[] = "\\\\.";
352
353 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
354
355 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
356 strcat(strcpy(pname, prefix), old_conn->Endpoint);
357 status = rpcrt4_conn_create_pipe(old_conn, pname);
358 I_RpcFree(pname);
359
360 return status;
361 }
362
363 static RPC_STATUS rpcrt4_ncalrpc_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
364 {
365 RPC_STATUS status;
366 LPSTR pname;
367 static const char prefix[] = "\\\\.\\pipe\\lrpc\\";
368
369 TRACE("%s\n", old_conn->Endpoint);
370
371 rpcrt4_conn_np_handoff((RpcConnection_np *)old_conn, (RpcConnection_np *)new_conn);
372
373 pname = I_RpcAllocate(strlen(prefix) + strlen(old_conn->Endpoint) + 1);
374 strcat(strcpy(pname, prefix), old_conn->Endpoint);
375 status = rpcrt4_conn_create_pipe(old_conn, pname);
376 I_RpcFree(pname);
377
378 return status;
379 }
380
381 static int rpcrt4_conn_np_read(RpcConnection *Connection,
382 void *buffer, unsigned int count)
383 {
384 RpcConnection_np *npc = (RpcConnection_np *) Connection;
385 char *buf = buffer;
386 BOOL ret = TRUE;
387 unsigned int bytes_left = count;
388
389 while (bytes_left)
390 {
391 DWORD bytes_read;
392 ret = ReadFile(npc->pipe, buf, bytes_left, &bytes_read, &npc->ovl[0]);
393 if ((!ret || !bytes_read) && (GetLastError() != ERROR_IO_PENDING))
394 break;
395
396 ret = GetOverlappedResult(npc->pipe, &npc->ovl[0], &bytes_read, TRUE);
397 if (!ret && (GetLastError() != ERROR_MORE_DATA))
398 break;
399
400 bytes_left -= bytes_read;
401 buf += bytes_read;
402 }
403 return ret ? count : -1;
404 }
405
406 static int rpcrt4_conn_np_write(RpcConnection *Connection,
407 const void *buffer, unsigned int count)
408 {
409 RpcConnection_np *npc = (RpcConnection_np *) Connection;
410 const char *buf = buffer;
411 BOOL ret = TRUE;
412 unsigned int bytes_left = count;
413
414 while (bytes_left)
415 {
416 DWORD bytes_written;
417 ret = WriteFile(npc->pipe, buf, bytes_left, &bytes_written, &npc->ovl[1]);
418 if ((!ret || !bytes_written) && (GetLastError() != ERROR_IO_PENDING))
419 break;
420
421 ret = GetOverlappedResult(npc->pipe, &npc->ovl[1], &bytes_written, TRUE);
422 if (!ret && (GetLastError() != ERROR_MORE_DATA))
423 break;
424
425 bytes_left -= bytes_written;
426 buf += bytes_written;
427 }
428 return ret ? count : -1;
429 }
430
431 static int rpcrt4_conn_np_close(RpcConnection *Connection)
432 {
433 RpcConnection_np *npc = (RpcConnection_np *) Connection;
434 if (npc->pipe) {
435 FlushFileBuffers(npc->pipe);
436 CloseHandle(npc->pipe);
437 npc->pipe = 0;
438 }
439 if (npc->ovl[0].hEvent) {
440 CloseHandle(npc->ovl[0].hEvent);
441 npc->ovl[0].hEvent = 0;
442 }
443 if (npc->ovl[1].hEvent) {
444 CloseHandle(npc->ovl[1].hEvent);
445 npc->ovl[1].hEvent = 0;
446 }
447 return 0;
448 }
449
450 static void rpcrt4_conn_np_cancel_call(RpcConnection *Connection)
451 {
452 /* FIXME: implement when named pipe writes use overlapped I/O */
453 }
454
455 static int rpcrt4_conn_np_wait_for_incoming_data(RpcConnection *Connection)
456 {
457 /* FIXME: implement when named pipe writes use overlapped I/O */
458 return -1;
459 }
460
461 static size_t rpcrt4_ncacn_np_get_top_of_tower(unsigned char *tower_data,
462 const char *networkaddr,
463 const char *endpoint)
464 {
465 twr_empty_floor_t *smb_floor;
466 twr_empty_floor_t *nb_floor;
467 size_t size;
468 size_t networkaddr_size;
469 size_t endpoint_size;
470
471 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
472
473 networkaddr_size = networkaddr ? strlen(networkaddr) + 1 : 1;
474 endpoint_size = endpoint ? strlen(endpoint) + 1 : 1;
475 size = sizeof(*smb_floor) + endpoint_size + sizeof(*nb_floor) + networkaddr_size;
476
477 if (!tower_data)
478 return size;
479
480 smb_floor = (twr_empty_floor_t *)tower_data;
481
482 tower_data += sizeof(*smb_floor);
483
484 smb_floor->count_lhs = sizeof(smb_floor->protid);
485 smb_floor->protid = EPM_PROTOCOL_SMB;
486 smb_floor->count_rhs = endpoint_size;
487
488 if (endpoint)
489 memcpy(tower_data, endpoint, endpoint_size);
490 else
491 tower_data[0] = 0;
492 tower_data += endpoint_size;
493
494 nb_floor = (twr_empty_floor_t *)tower_data;
495
496 tower_data += sizeof(*nb_floor);
497
498 nb_floor->count_lhs = sizeof(nb_floor->protid);
499 nb_floor->protid = EPM_PROTOCOL_NETBIOS;
500 nb_floor->count_rhs = networkaddr_size;
501
502 if (networkaddr)
503 memcpy(tower_data, networkaddr, networkaddr_size);
504 else
505 tower_data[0] = 0;
506
507 return size;
508 }
509
510 static RPC_STATUS rpcrt4_ncacn_np_parse_top_of_tower(const unsigned char *tower_data,
511 size_t tower_size,
512 char **networkaddr,
513 char **endpoint)
514 {
515 const twr_empty_floor_t *smb_floor = (const twr_empty_floor_t *)tower_data;
516 const twr_empty_floor_t *nb_floor;
517
518 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
519
520 if (tower_size < sizeof(*smb_floor))
521 return EPT_S_NOT_REGISTERED;
522
523 tower_data += sizeof(*smb_floor);
524 tower_size -= sizeof(*smb_floor);
525
526 if ((smb_floor->count_lhs != sizeof(smb_floor->protid)) ||
527 (smb_floor->protid != EPM_PROTOCOL_SMB) ||
528 (smb_floor->count_rhs > tower_size) ||
529 (tower_data[smb_floor->count_rhs - 1] != '\0'))
530 return EPT_S_NOT_REGISTERED;
531
532 if (endpoint)
533 {
534 *endpoint = I_RpcAllocate(smb_floor->count_rhs);
535 if (!*endpoint)
536 return RPC_S_OUT_OF_RESOURCES;
537 memcpy(*endpoint, tower_data, smb_floor->count_rhs);
538 }
539 tower_data += smb_floor->count_rhs;
540 tower_size -= smb_floor->count_rhs;
541
542 if (tower_size < sizeof(*nb_floor))
543 return EPT_S_NOT_REGISTERED;
544
545 nb_floor = (const twr_empty_floor_t *)tower_data;
546
547 tower_data += sizeof(*nb_floor);
548 tower_size -= sizeof(*nb_floor);
549
550 if ((nb_floor->count_lhs != sizeof(nb_floor->protid)) ||
551 (nb_floor->protid != EPM_PROTOCOL_NETBIOS) ||
552 (nb_floor->count_rhs > tower_size) ||
553 (tower_data[nb_floor->count_rhs - 1] != '\0'))
554 return EPT_S_NOT_REGISTERED;
555
556 if (networkaddr)
557 {
558 *networkaddr = I_RpcAllocate(nb_floor->count_rhs);
559 if (!*networkaddr)
560 {
561 if (endpoint)
562 {
563 I_RpcFree(*endpoint);
564 *endpoint = NULL;
565 }
566 return RPC_S_OUT_OF_RESOURCES;
567 }
568 memcpy(*networkaddr, tower_data, nb_floor->count_rhs);
569 }
570
571 return RPC_S_OK;
572 }
573
574 typedef struct _RpcServerProtseq_np
575 {
576 RpcServerProtseq common;
577 HANDLE mgr_event;
578 } RpcServerProtseq_np;
579
580 static RpcServerProtseq *rpcrt4_protseq_np_alloc(void)
581 {
582 RpcServerProtseq_np *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
583 if (ps)
584 ps->mgr_event = CreateEventW(NULL, FALSE, FALSE, NULL);
585 return &ps->common;
586 }
587
588 static void rpcrt4_protseq_np_signal_state_changed(RpcServerProtseq *protseq)
589 {
590 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
591 SetEvent(npps->mgr_event);
592 }
593
594 static void *rpcrt4_protseq_np_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
595 {
596 HANDLE *objs = prev_array;
597 RpcConnection_np *conn;
598 RpcServerProtseq_np *npps = CONTAINING_RECORD(protseq, RpcServerProtseq_np, common);
599
600 EnterCriticalSection(&protseq->cs);
601
602 /* open and count connections */
603 *count = 1;
604 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
605 while (conn) {
606 rpcrt4_conn_listen_pipe(conn);
607 if (conn->ovl[0].hEvent)
608 (*count)++;
609 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
610 }
611
612 /* make array of connections */
613 if (objs)
614 objs = HeapReAlloc(GetProcessHeap(), 0, objs, *count*sizeof(HANDLE));
615 else
616 objs = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(HANDLE));
617 if (!objs)
618 {
619 ERR("couldn't allocate objs\n");
620 LeaveCriticalSection(&protseq->cs);
621 return NULL;
622 }
623
624 objs[0] = npps->mgr_event;
625 *count = 1;
626 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
627 while (conn) {
628 if ((objs[*count] = conn->ovl[0].hEvent))
629 (*count)++;
630 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
631 }
632 LeaveCriticalSection(&protseq->cs);
633 return objs;
634 }
635
636 static void rpcrt4_protseq_np_free_wait_array(RpcServerProtseq *protseq, void *array)
637 {
638 HeapFree(GetProcessHeap(), 0, array);
639 }
640
641 static int rpcrt4_protseq_np_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
642 {
643 HANDLE b_handle;
644 HANDLE *objs = wait_array;
645 DWORD res;
646 RpcConnection *cconn;
647 RpcConnection_np *conn;
648
649 if (!objs)
650 return -1;
651
652 do
653 {
654 /* an alertable wait isn't strictly necessary, but due to our
655 * overlapped I/O implementation in Wine we need to free some memory
656 * by the file user APC being called, even if no completion routine was
657 * specified at the time of starting the async operation */
658 res = WaitForMultipleObjectsEx(count, objs, FALSE, INFINITE, TRUE);
659 } while (res == WAIT_IO_COMPLETION);
660
661 if (res == WAIT_OBJECT_0)
662 return 0;
663 else if (res == WAIT_FAILED)
664 {
665 ERR("wait failed with error %d\n", GetLastError());
666 return -1;
667 }
668 else
669 {
670 b_handle = objs[res - WAIT_OBJECT_0];
671 /* find which connection got a RPC */
672 EnterCriticalSection(&protseq->cs);
673 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_np, common);
674 while (conn) {
675 if (b_handle == conn->ovl[0].hEvent) break;
676 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_np, common);
677 }
678 cconn = NULL;
679 if (conn)
680 RPCRT4_SpawnConnection(&cconn, &conn->common);
681 else
682 ERR("failed to locate connection for handle %p\n", b_handle);
683 LeaveCriticalSection(&protseq->cs);
684 if (cconn)
685 {
686 RPCRT4_new_client(cconn);
687 return 1;
688 }
689 else return -1;
690 }
691 }
692
693 static size_t rpcrt4_ncalrpc_get_top_of_tower(unsigned char *tower_data,
694 const char *networkaddr,
695 const char *endpoint)
696 {
697 twr_empty_floor_t *pipe_floor;
698 size_t size;
699 size_t endpoint_size;
700
701 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
702
703 endpoint_size = strlen(endpoint) + 1;
704 size = sizeof(*pipe_floor) + endpoint_size;
705
706 if (!tower_data)
707 return size;
708
709 pipe_floor = (twr_empty_floor_t *)tower_data;
710
711 tower_data += sizeof(*pipe_floor);
712
713 pipe_floor->count_lhs = sizeof(pipe_floor->protid);
714 pipe_floor->protid = EPM_PROTOCOL_PIPE;
715 pipe_floor->count_rhs = endpoint_size;
716
717 memcpy(tower_data, endpoint, endpoint_size);
718
719 return size;
720 }
721
722 static RPC_STATUS rpcrt4_ncalrpc_parse_top_of_tower(const unsigned char *tower_data,
723 size_t tower_size,
724 char **networkaddr,
725 char **endpoint)
726 {
727 const twr_empty_floor_t *pipe_floor = (const twr_empty_floor_t *)tower_data;
728
729 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
730
731 if (tower_size < sizeof(*pipe_floor))
732 return EPT_S_NOT_REGISTERED;
733
734 tower_data += sizeof(*pipe_floor);
735 tower_size -= sizeof(*pipe_floor);
736
737 if ((pipe_floor->count_lhs != sizeof(pipe_floor->protid)) ||
738 (pipe_floor->protid != EPM_PROTOCOL_PIPE) ||
739 (pipe_floor->count_rhs > tower_size) ||
740 (tower_data[pipe_floor->count_rhs - 1] != '\0'))
741 return EPT_S_NOT_REGISTERED;
742
743 if (networkaddr)
744 *networkaddr = NULL;
745
746 if (endpoint)
747 {
748 *endpoint = I_RpcAllocate(pipe_floor->count_rhs);
749 if (!*endpoint)
750 return RPC_S_OUT_OF_RESOURCES;
751 memcpy(*endpoint, tower_data, pipe_floor->count_rhs);
752 }
753
754 return RPC_S_OK;
755 }
756
757 /**** ncacn_ip_tcp support ****/
758
759 #ifdef HAVE_SOCKETPAIR
760
761 typedef struct _RpcConnection_tcp
762 {
763 RpcConnection common;
764 int sock;
765 int cancel_fds[2];
766 } RpcConnection_tcp;
767
768 static RpcConnection *rpcrt4_conn_tcp_alloc(void)
769 {
770 RpcConnection_tcp *tcpc;
771 tcpc = HeapAlloc(GetProcessHeap(), 0, sizeof(RpcConnection_tcp));
772 if (tcpc == NULL)
773 return NULL;
774 tcpc->sock = -1;
775 if (socketpair(PF_UNIX, SOCK_STREAM, 0, tcpc->cancel_fds) < 0)
776 {
777 ERR("socketpair() failed: %s\n", strerror(errno));
778 HeapFree(GetProcessHeap(), 0, tcpc);
779 return NULL;
780 }
781 return &tcpc->common;
782 }
783
784 static RPC_STATUS rpcrt4_ncacn_ip_tcp_open(RpcConnection* Connection)
785 {
786 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
787 int sock;
788 int ret;
789 struct addrinfo *ai;
790 struct addrinfo *ai_cur;
791 struct addrinfo hints;
792
793 TRACE("(%s, %s)\n", Connection->NetworkAddr, Connection->Endpoint);
794
795 if (tcpc->sock != -1)
796 return RPC_S_OK;
797
798 hints.ai_flags = 0;
799 hints.ai_family = PF_UNSPEC;
800 hints.ai_socktype = SOCK_STREAM;
801 hints.ai_protocol = IPPROTO_TCP;
802 hints.ai_addrlen = 0;
803 hints.ai_addr = NULL;
804 hints.ai_canonname = NULL;
805 hints.ai_next = NULL;
806
807 ret = getaddrinfo(Connection->NetworkAddr, Connection->Endpoint, &hints, &ai);
808 if (ret)
809 {
810 ERR("getaddrinfo for %s:%s failed: %s\n", Connection->NetworkAddr,
811 Connection->Endpoint, gai_strerror(ret));
812 return RPC_S_SERVER_UNAVAILABLE;
813 }
814
815 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
816 {
817 int val;
818
819 if (TRACE_ON(rpc))
820 {
821 char host[256];
822 char service[256];
823 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
824 host, sizeof(host), service, sizeof(service),
825 NI_NUMERICHOST | NI_NUMERICSERV);
826 TRACE("trying %s:%s\n", host, service);
827 }
828
829 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
830 if (sock == -1)
831 {
832 WARN("socket() failed: %s\n", strerror(errno));
833 continue;
834 }
835
836 if (0>connect(sock, ai_cur->ai_addr, ai_cur->ai_addrlen))
837 {
838 WARN("connect() failed: %s\n", strerror(errno));
839 closesocket(sock);
840 continue;
841 }
842
843 /* RPC depends on having minimal latency so disable the Nagle algorithm */
844 val = 1;
845 setsockopt(sock, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
846 fcntl(sock, F_SETFL, O_NONBLOCK); /* make socket nonblocking */
847
848 tcpc->sock = sock;
849
850 freeaddrinfo(ai);
851 TRACE("connected\n");
852 return RPC_S_OK;
853 }
854
855 freeaddrinfo(ai);
856 ERR("couldn't connect to %s:%s\n", Connection->NetworkAddr, Connection->Endpoint);
857 return RPC_S_SERVER_UNAVAILABLE;
858 }
859
860 static RPC_STATUS rpcrt4_protseq_ncacn_ip_tcp_open_endpoint(RpcServerProtseq *protseq, LPSTR endpoint)
861 {
862 RPC_STATUS status = RPC_S_CANT_CREATE_ENDPOINT;
863 int sock;
864 int ret;
865 struct addrinfo *ai;
866 struct addrinfo *ai_cur;
867 struct addrinfo hints;
868 RpcConnection *first_connection = NULL;
869
870 TRACE("(%p, %s)\n", protseq, endpoint);
871
872 hints.ai_flags = AI_PASSIVE /* for non-localhost addresses */;
873 hints.ai_family = PF_UNSPEC;
874 hints.ai_socktype = SOCK_STREAM;
875 hints.ai_protocol = IPPROTO_TCP;
876 hints.ai_addrlen = 0;
877 hints.ai_addr = NULL;
878 hints.ai_canonname = NULL;
879 hints.ai_next = NULL;
880
881 ret = getaddrinfo(NULL, endpoint, &hints, &ai);
882 if (ret)
883 {
884 ERR("getaddrinfo for port %s failed: %s\n", endpoint,
885 gai_strerror(ret));
886 if ((ret == EAI_SERVICE) || (ret == EAI_NONAME))
887 return RPC_S_INVALID_ENDPOINT_FORMAT;
888 return RPC_S_CANT_CREATE_ENDPOINT;
889 }
890
891 for (ai_cur = ai; ai_cur; ai_cur = ai_cur->ai_next)
892 {
893 RpcConnection_tcp *tcpc;
894 RPC_STATUS create_status;
895
896 if (TRACE_ON(rpc))
897 {
898 char host[256];
899 char service[256];
900 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
901 host, sizeof(host), service, sizeof(service),
902 NI_NUMERICHOST | NI_NUMERICSERV);
903 TRACE("trying %s:%s\n", host, service);
904 }
905
906 sock = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
907 if (sock == -1)
908 {
909 WARN("socket() failed: %s\n", strerror(errno));
910 status = RPC_S_CANT_CREATE_ENDPOINT;
911 continue;
912 }
913
914 ret = bind(sock, ai_cur->ai_addr, ai_cur->ai_addrlen);
915 if (ret < 0)
916 {
917 WARN("bind failed: %s\n", strerror(errno));
918 closesocket(sock);
919 if (errno == EADDRINUSE)
920 status = RPC_S_DUPLICATE_ENDPOINT;
921 else
922 status = RPC_S_CANT_CREATE_ENDPOINT;
923 continue;
924 }
925 create_status = RPCRT4_CreateConnection((RpcConnection **)&tcpc, TRUE,
926 protseq->Protseq, NULL,
927 endpoint, NULL, NULL, NULL);
928 if (create_status != RPC_S_OK)
929 {
930 closesocket(sock);
931 status = create_status;
932 continue;
933 }
934
935 tcpc->sock = sock;
936 ret = listen(sock, protseq->MaxCalls);
937 if (ret < 0)
938 {
939 WARN("listen failed: %s\n", strerror(errno));
940 RPCRT4_DestroyConnection(&tcpc->common);
941 status = RPC_S_OUT_OF_RESOURCES;
942 continue;
943 }
944 /* need a non-blocking socket, otherwise accept() has a potential
945 * race-condition (poll() says it is readable, connection drops,
946 * and accept() blocks until the next connection comes...)
947 */
948 ret = fcntl(sock, F_SETFL, O_NONBLOCK);
949 if (ret < 0)
950 {
951 WARN("couldn't make socket non-blocking, error %d\n", ret);
952 RPCRT4_DestroyConnection(&tcpc->common);
953 status = RPC_S_OUT_OF_RESOURCES;
954 continue;
955 }
956
957 tcpc->common.Next = first_connection;
958 first_connection = &tcpc->common;
959 }
960
961 freeaddrinfo(ai);
962
963 /* if at least one connection was created for an endpoint then
964 * return success */
965 if (first_connection)
966 {
967 RpcConnection *conn;
968
969 /* find last element in list */
970 for (conn = first_connection; conn->Next; conn = conn->Next)
971 ;
972
973 EnterCriticalSection(&protseq->cs);
974 conn->Next = protseq->conn;
975 protseq->conn = first_connection;
976 LeaveCriticalSection(&protseq->cs);
977
978 TRACE("listening on %s\n", endpoint);
979 return RPC_S_OK;
980 }
981
982 ERR("couldn't listen on port %s\n", endpoint);
983 return status;
984 }
985
986 static RPC_STATUS rpcrt4_conn_tcp_handoff(RpcConnection *old_conn, RpcConnection *new_conn)
987 {
988 int ret;
989 struct sockaddr_in address;
990 socklen_t addrsize;
991 RpcConnection_tcp *server = (RpcConnection_tcp*) old_conn;
992 RpcConnection_tcp *client = (RpcConnection_tcp*) new_conn;
993
994 addrsize = sizeof(address);
995 ret = accept(server->sock, (struct sockaddr*) &address, &addrsize);
996 if (ret < 0)
997 {
998 ERR("Failed to accept a TCP connection: error %d\n", ret);
999 return RPC_S_OUT_OF_RESOURCES;
1000 }
1001 /* reset to blocking behaviour */
1002 fcntl(ret, F_SETFL, 0);
1003 client->sock = ret;
1004 TRACE("Accepted a new TCP connection\n");
1005 return RPC_S_OK;
1006 }
1007
1008 static int rpcrt4_conn_tcp_read(RpcConnection *Connection,
1009 void *buffer, unsigned int count)
1010 {
1011 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1012 int bytes_read = 0;
1013 do
1014 {
1015 int r = recv(tcpc->sock, (char *)buffer + bytes_read, count - bytes_read, 0);
1016 if (!r)
1017 return -1;
1018 else if (r > 0)
1019 bytes_read += r;
1020 else if (errno != EAGAIN)
1021 {
1022 WARN("recv() failed: %s\n", strerror(errno));
1023 return -1;
1024 }
1025 else
1026 {
1027 struct pollfd pfds[2];
1028 pfds[0].fd = tcpc->sock;
1029 pfds[0].events = POLLIN;
1030 pfds[1].fd = tcpc->cancel_fds[0];
1031 pfds[1].events = POLLIN;
1032 if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1033 {
1034 ERR("poll() failed: %s\n", strerror(errno));
1035 return -1;
1036 }
1037 if (pfds[1].revents & POLLIN) /* canceled */
1038 {
1039 char dummy;
1040 read(pfds[1].fd, &dummy, sizeof(dummy));
1041 return -1;
1042 }
1043 }
1044 } while (bytes_read != count);
1045 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_read);
1046 return bytes_read;
1047 }
1048
1049 static int rpcrt4_conn_tcp_write(RpcConnection *Connection,
1050 const void *buffer, unsigned int count)
1051 {
1052 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1053 int bytes_written = 0;
1054 do
1055 {
1056 int r = send(tcpc->sock, (const char *)buffer + bytes_written, count - bytes_written, 0);
1057 if (r >= 0)
1058 bytes_written += r;
1059 else if (errno != EAGAIN)
1060 return -1;
1061 else
1062 {
1063 struct pollfd pfd;
1064 pfd.fd = tcpc->sock;
1065 pfd.events = POLLOUT;
1066 if (poll(&pfd, 1, -1 /* infinite */) == -1 && errno != EINTR)
1067 {
1068 ERR("poll() failed: %s\n", strerror(errno));
1069 return -1;
1070 }
1071 }
1072 } while (bytes_written != count);
1073 TRACE("%d %p %u -> %d\n", tcpc->sock, buffer, count, bytes_written);
1074 return bytes_written;
1075 }
1076
1077 static int rpcrt4_conn_tcp_close(RpcConnection *Connection)
1078 {
1079 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1080
1081 TRACE("%d\n", tcpc->sock);
1082
1083 if (tcpc->sock != -1)
1084 closesocket(tcpc->sock);
1085 tcpc->sock = -1;
1086 close(tcpc->cancel_fds[0]);
1087 close(tcpc->cancel_fds[1]);
1088 return 0;
1089 }
1090
1091 static void rpcrt4_conn_tcp_cancel_call(RpcConnection *Connection)
1092 {
1093 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1094 char dummy = 1;
1095
1096 TRACE("%p\n", Connection);
1097
1098 write(tcpc->cancel_fds[1], &dummy, 1);
1099 }
1100
1101 static int rpcrt4_conn_tcp_wait_for_incoming_data(RpcConnection *Connection)
1102 {
1103 RpcConnection_tcp *tcpc = (RpcConnection_tcp *) Connection;
1104 struct pollfd pfds[2];
1105
1106 TRACE("%p\n", Connection);
1107
1108 pfds[0].fd = tcpc->sock;
1109 pfds[0].events = POLLIN;
1110 pfds[1].fd = tcpc->cancel_fds[0];
1111 pfds[1].events = POLLIN;
1112 if (poll(pfds, 2, -1 /* infinite */) == -1 && errno != EINTR)
1113 {
1114 ERR("poll() failed: %s\n", strerror(errno));
1115 return -1;
1116 }
1117 if (pfds[1].revents & POLLIN) /* canceled */
1118 {
1119 char dummy;
1120 read(pfds[1].fd, &dummy, sizeof(dummy));
1121 return -1;
1122 }
1123
1124 return 0;
1125 }
1126
1127 static size_t rpcrt4_ncacn_ip_tcp_get_top_of_tower(unsigned char *tower_data,
1128 const char *networkaddr,
1129 const char *endpoint)
1130 {
1131 twr_tcp_floor_t *tcp_floor;
1132 twr_ipv4_floor_t *ipv4_floor;
1133 struct addrinfo *ai;
1134 struct addrinfo hints;
1135 int ret;
1136 size_t size = sizeof(*tcp_floor) + sizeof(*ipv4_floor);
1137
1138 TRACE("(%p, %s, %s)\n", tower_data, networkaddr, endpoint);
1139
1140 if (!tower_data)
1141 return size;
1142
1143 tcp_floor = (twr_tcp_floor_t *)tower_data;
1144 tower_data += sizeof(*tcp_floor);
1145
1146 ipv4_floor = (twr_ipv4_floor_t *)tower_data;
1147
1148 tcp_floor->count_lhs = sizeof(tcp_floor->protid);
1149 tcp_floor->protid = EPM_PROTOCOL_TCP;
1150 tcp_floor->count_rhs = sizeof(tcp_floor->port);
1151
1152 ipv4_floor->count_lhs = sizeof(ipv4_floor->protid);
1153 ipv4_floor->protid = EPM_PROTOCOL_IP;
1154 ipv4_floor->count_rhs = sizeof(ipv4_floor->ipv4addr);
1155
1156 hints.ai_flags = AI_NUMERICHOST;
1157 /* FIXME: only support IPv4 at the moment. how is IPv6 represented by the EPM? */
1158 hints.ai_family = PF_INET;
1159 hints.ai_socktype = SOCK_STREAM;
1160 hints.ai_protocol = IPPROTO_TCP;
1161 hints.ai_addrlen = 0;
1162 hints.ai_addr = NULL;
1163 hints.ai_canonname = NULL;
1164 hints.ai_next = NULL;
1165
1166 ret = getaddrinfo(networkaddr, endpoint, &hints, &ai);
1167 if (ret)
1168 {
1169 ret = getaddrinfo("0.0.0.0", endpoint, &hints, &ai);
1170 if (ret)
1171 {
1172 ERR("getaddrinfo failed: %s\n", gai_strerror(ret));
1173 return 0;
1174 }
1175 }
1176
1177 if (ai->ai_family == PF_INET)
1178 {
1179 const struct sockaddr_in *sin = (const struct sockaddr_in *)ai->ai_addr;
1180 tcp_floor->port = sin->sin_port;
1181 ipv4_floor->ipv4addr = sin->sin_addr.s_addr;
1182 }
1183 else
1184 {
1185 ERR("unexpected protocol family %d\n", ai->ai_family);
1186 return 0;
1187 }
1188
1189 freeaddrinfo(ai);
1190
1191 return size;
1192 }
1193
1194 static RPC_STATUS rpcrt4_ncacn_ip_tcp_parse_top_of_tower(const unsigned char *tower_data,
1195 size_t tower_size,
1196 char **networkaddr,
1197 char **endpoint)
1198 {
1199 const twr_tcp_floor_t *tcp_floor = (const twr_tcp_floor_t *)tower_data;
1200 const twr_ipv4_floor_t *ipv4_floor;
1201 struct in_addr in_addr;
1202
1203 TRACE("(%p, %d, %p, %p)\n", tower_data, (int)tower_size, networkaddr, endpoint);
1204
1205 if (tower_size < sizeof(*tcp_floor))
1206 return EPT_S_NOT_REGISTERED;
1207
1208 tower_data += sizeof(*tcp_floor);
1209 tower_size -= sizeof(*tcp_floor);
1210
1211 if (tower_size < sizeof(*ipv4_floor))
1212 return EPT_S_NOT_REGISTERED;
1213
1214 ipv4_floor = (const twr_ipv4_floor_t *)tower_data;
1215
1216 if ((tcp_floor->count_lhs != sizeof(tcp_floor->protid)) ||
1217 (tcp_floor->protid != EPM_PROTOCOL_TCP) ||
1218 (tcp_floor->count_rhs != sizeof(tcp_floor->port)) ||
1219 (ipv4_floor->count_lhs != sizeof(ipv4_floor->protid)) ||
1220 (ipv4_floor->protid != EPM_PROTOCOL_IP) ||
1221 (ipv4_floor->count_rhs != sizeof(ipv4_floor->ipv4addr)))
1222 return EPT_S_NOT_REGISTERED;
1223
1224 if (endpoint)
1225 {
1226 *endpoint = I_RpcAllocate(6 /* sizeof("65535") + 1 */);
1227 if (!*endpoint)
1228 return RPC_S_OUT_OF_RESOURCES;
1229 sprintf(*endpoint, "%u", ntohs(tcp_floor->port));
1230 }
1231
1232 if (networkaddr)
1233 {
1234 *networkaddr = I_RpcAllocate(INET_ADDRSTRLEN);
1235 if (!*networkaddr)
1236 {
1237 if (endpoint)
1238 {
1239 I_RpcFree(*endpoint);
1240 *endpoint = NULL;
1241 }
1242 return RPC_S_OUT_OF_RESOURCES;
1243 }
1244 in_addr.s_addr = ipv4_floor->ipv4addr;
1245 if (!inet_ntop(AF_INET, &in_addr, *networkaddr, INET_ADDRSTRLEN))
1246 {
1247 ERR("inet_ntop: %s\n", strerror(errno));
1248 I_RpcFree(*networkaddr);
1249 *networkaddr = NULL;
1250 if (endpoint)
1251 {
1252 I_RpcFree(*endpoint);
1253 *endpoint = NULL;
1254 }
1255 return EPT_S_NOT_REGISTERED;
1256 }
1257 }
1258
1259 return RPC_S_OK;
1260 }
1261
1262 typedef struct _RpcServerProtseq_sock
1263 {
1264 RpcServerProtseq common;
1265 int mgr_event_rcv;
1266 int mgr_event_snd;
1267 } RpcServerProtseq_sock;
1268
1269 static RpcServerProtseq *rpcrt4_protseq_sock_alloc(void)
1270 {
1271 RpcServerProtseq_sock *ps = HeapAlloc(GetProcessHeap(), 0, sizeof(*ps));
1272 if (ps)
1273 {
1274 int fds[2];
1275 if (!socketpair(PF_UNIX, SOCK_DGRAM, 0, fds))
1276 {
1277 fcntl(fds[0], F_SETFL, O_NONBLOCK);
1278 fcntl(fds[1], F_SETFL, O_NONBLOCK);
1279 ps->mgr_event_rcv = fds[0];
1280 ps->mgr_event_snd = fds[1];
1281 }
1282 else
1283 {
1284 ERR("socketpair failed with error %s\n", strerror(errno));
1285 HeapFree(GetProcessHeap(), 0, ps);
1286 return NULL;
1287 }
1288 }
1289 return &ps->common;
1290 }
1291
1292 static void rpcrt4_protseq_sock_signal_state_changed(RpcServerProtseq *protseq)
1293 {
1294 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1295 char dummy = 1;
1296 write(sockps->mgr_event_snd, &dummy, sizeof(dummy));
1297 }
1298
1299 static void *rpcrt4_protseq_sock_get_wait_array(RpcServerProtseq *protseq, void *prev_array, unsigned int *count)
1300 {
1301 struct pollfd *poll_info = prev_array;
1302 RpcConnection_tcp *conn;
1303 RpcServerProtseq_sock *sockps = CONTAINING_RECORD(protseq, RpcServerProtseq_sock, common);
1304
1305 EnterCriticalSection(&protseq->cs);
1306
1307 /* open and count connections */
1308 *count = 1;
1309 conn = (RpcConnection_tcp *)protseq->conn;
1310 while (conn) {
1311 if (conn->sock != -1)
1312 (*count)++;
1313 conn = (RpcConnection_tcp *)conn->common.Next;
1314 }
1315
1316 /* make array of connections */
1317 if (poll_info)
1318 poll_info = HeapReAlloc(GetProcessHeap(), 0, poll_info, *count*sizeof(*poll_info));
1319 else
1320 poll_info = HeapAlloc(GetProcessHeap(), 0, *count*sizeof(*poll_info));
1321 if (!poll_info)
1322 {
1323 ERR("couldn't allocate poll_info\n");
1324 LeaveCriticalSection(&protseq->cs);
1325 return NULL;
1326 }
1327
1328 poll_info[0].fd = sockps->mgr_event_rcv;
1329 poll_info[0].events = POLLIN;
1330 *count = 1;
1331 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1332 while (conn) {
1333 if (conn->sock != -1)
1334 {
1335 poll_info[*count].fd = conn->sock;
1336 poll_info[*count].events = POLLIN;
1337 (*count)++;
1338 }
1339 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1340 }
1341 LeaveCriticalSection(&protseq->cs);
1342 return poll_info;
1343 }
1344
1345 static void rpcrt4_protseq_sock_free_wait_array(RpcServerProtseq *protseq, void *array)
1346 {
1347 HeapFree(GetProcessHeap(), 0, array);
1348 }
1349
1350 static int rpcrt4_protseq_sock_wait_for_new_connection(RpcServerProtseq *protseq, unsigned int count, void *wait_array)
1351 {
1352 struct pollfd *poll_info = wait_array;
1353 int ret;
1354 unsigned int i;
1355 RpcConnection *cconn;
1356 RpcConnection_tcp *conn;
1357
1358 if (!poll_info)
1359 return -1;
1360
1361 ret = poll(poll_info, count, -1);
1362 if (ret < 0)
1363 {
1364 ERR("poll failed with error %d\n", ret);
1365 return -1;
1366 }
1367
1368 for (i = 0; i < count; i++)
1369 if (poll_info[i].revents & POLLIN)
1370 {
1371 /* RPC server event */
1372 if (i == 0)
1373 {
1374 char dummy;
1375 read(poll_info[0].fd, &dummy, sizeof(dummy));
1376 return 0;
1377 }
1378
1379 /* find which connection got a RPC */
1380 EnterCriticalSection(&protseq->cs);
1381 conn = CONTAINING_RECORD(protseq->conn, RpcConnection_tcp, common);
1382 while (conn) {
1383 if (poll_info[i].fd == conn->sock) break;
1384 conn = CONTAINING_RECORD(conn->common.Next, RpcConnection_tcp, common);
1385 }
1386 cconn = NULL;
1387 if (conn)
1388 RPCRT4_SpawnConnection(&cconn, &conn->common);
1389 else
1390 ERR("failed to locate connection for fd %d\n", poll_info[i].fd);
1391 LeaveCriticalSection(&protseq->cs);
1392 if (cconn)
1393 RPCRT4_new_client(cconn);
1394 else
1395 return -1;
1396 }
1397
1398 return 1;
1399 }
1400
1401 #endif /* HAVE_SOCKETPAIR */
1402
1403 static const struct connection_ops conn_protseq_list[] = {
1404 { "ncacn_np",
1405 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_SMB },
1406 rpcrt4_conn_np_alloc,
1407 rpcrt4_ncacn_np_open,
1408 rpcrt4_ncacn_np_handoff,
1409 rpcrt4_conn_np_read,
1410 rpcrt4_conn_np_write,
1411 rpcrt4_conn_np_close,
1412 rpcrt4_conn_np_cancel_call,
1413 rpcrt4_conn_np_wait_for_incoming_data,
1414 rpcrt4_ncacn_np_get_top_of_tower,
1415 rpcrt4_ncacn_np_parse_top_of_tower,
1416 },
1417 { "ncalrpc",
1418 { EPM_PROTOCOL_NCALRPC, EPM_PROTOCOL_PIPE },
1419 rpcrt4_conn_np_alloc,
1420 rpcrt4_ncalrpc_open,
1421 rpcrt4_ncalrpc_handoff,
1422 rpcrt4_conn_np_read,
1423 rpcrt4_conn_np_write,
1424 rpcrt4_conn_np_close,
1425 rpcrt4_conn_np_cancel_call,
1426 rpcrt4_conn_np_wait_for_incoming_data,
1427 rpcrt4_ncalrpc_get_top_of_tower,
1428 rpcrt4_ncalrpc_parse_top_of_tower,
1429 },
1430 #ifdef HAVE_SOCKETPAIR
1431 { "ncacn_ip_tcp",
1432 { EPM_PROTOCOL_NCACN, EPM_PROTOCOL_TCP },
1433 rpcrt4_conn_tcp_alloc,
1434 rpcrt4_ncacn_ip_tcp_open,
1435 rpcrt4_conn_tcp_handoff,
1436 rpcrt4_conn_tcp_read,
1437 rpcrt4_conn_tcp_write,
1438 rpcrt4_conn_tcp_close,
1439 rpcrt4_conn_tcp_cancel_call,
1440 rpcrt4_conn_tcp_wait_for_incoming_data,
1441 rpcrt4_ncacn_ip_tcp_get_top_of_tower,
1442 rpcrt4_ncacn_ip_tcp_parse_top_of_tower,
1443 }
1444 #endif
1445 };
1446
1447
1448 static const struct protseq_ops protseq_list[] =
1449 {
1450 {
1451 "ncacn_np",
1452 rpcrt4_protseq_np_alloc,
1453 rpcrt4_protseq_np_signal_state_changed,
1454 rpcrt4_protseq_np_get_wait_array,
1455 rpcrt4_protseq_np_free_wait_array,
1456 rpcrt4_protseq_np_wait_for_new_connection,
1457 rpcrt4_protseq_ncacn_np_open_endpoint,
1458 },
1459 {
1460 "ncalrpc",
1461 rpcrt4_protseq_np_alloc,
1462 rpcrt4_protseq_np_signal_state_changed,
1463 rpcrt4_protseq_np_get_wait_array,
1464 rpcrt4_protseq_np_free_wait_array,
1465 rpcrt4_protseq_np_wait_for_new_connection,
1466 rpcrt4_protseq_ncalrpc_open_endpoint,
1467 },
1468 #ifdef HAVE_SOCKETPAIR
1469 {
1470 "ncacn_ip_tcp",
1471 rpcrt4_protseq_sock_alloc,
1472 rpcrt4_protseq_sock_signal_state_changed,
1473 rpcrt4_protseq_sock_get_wait_array,
1474 rpcrt4_protseq_sock_free_wait_array,
1475 rpcrt4_protseq_sock_wait_for_new_connection,
1476 rpcrt4_protseq_ncacn_ip_tcp_open_endpoint,
1477 },
1478 #endif
1479 };
1480
1481 #define ARRAYSIZE(a) (sizeof((a)) / sizeof((a)[0]))
1482
1483 const struct protseq_ops *rpcrt4_get_protseq_ops(const char *protseq)
1484 {
1485 unsigned int i;
1486 for(i=0; i<ARRAYSIZE(protseq_list); i++)
1487 if (!strcmp(protseq_list[i].name, protseq))
1488 return &protseq_list[i];
1489 return NULL;
1490 }
1491
1492 static const struct connection_ops *rpcrt4_get_conn_protseq_ops(const char *protseq)
1493 {
1494 unsigned int i;
1495 for(i=0; i<ARRAYSIZE(conn_protseq_list); i++)
1496 if (!strcmp(conn_protseq_list[i].name, protseq))
1497 return &conn_protseq_list[i];
1498 return NULL;
1499 }
1500
1501 /**** interface to rest of code ****/
1502
1503 RPC_STATUS RPCRT4_OpenClientConnection(RpcConnection* Connection)
1504 {
1505 TRACE("(Connection == ^%p)\n", Connection);
1506
1507 assert(!Connection->server);
1508 return Connection->ops->open_connection_client(Connection);
1509 }
1510
1511 RPC_STATUS RPCRT4_CloseConnection(RpcConnection* Connection)
1512 {
1513 TRACE("(Connection == ^%p)\n", Connection);
1514 if (SecIsValidHandle(&Connection->ctx))
1515 {
1516 DeleteSecurityContext(&Connection->ctx);
1517 SecInvalidateHandle(&Connection->ctx);
1518 }
1519 rpcrt4_conn_close(Connection);
1520 return RPC_S_OK;
1521 }
1522
1523 RPC_STATUS RPCRT4_CreateConnection(RpcConnection** Connection, BOOL server,
1524 LPCSTR Protseq, LPCSTR NetworkAddr, LPCSTR Endpoint,
1525 LPCWSTR NetworkOptions, RpcAuthInfo* AuthInfo, RpcQualityOfService *QOS)
1526 {
1527 const struct connection_ops *ops;
1528 RpcConnection* NewConnection;
1529
1530 ops = rpcrt4_get_conn_protseq_ops(Protseq);
1531 if (!ops)
1532 {
1533 FIXME("not supported for protseq %s\n", Protseq);
1534 return RPC_S_PROTSEQ_NOT_SUPPORTED;
1535 }
1536
1537 NewConnection = ops->alloc();
1538 NewConnection->Next = NULL;
1539 NewConnection->server_binding = NULL;
1540 NewConnection->server = server;
1541 NewConnection->ops = ops;
1542 NewConnection->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
1543 NewConnection->Endpoint = RPCRT4_strdupA(Endpoint);
1544 NewConnection->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
1545 NewConnection->MaxTransmissionSize = RPC_MAX_PACKET_SIZE;
1546 memset(&NewConnection->ActiveInterface, 0, sizeof(NewConnection->ActiveInterface));
1547 NewConnection->NextCallId = 1;
1548
1549 SecInvalidateHandle(&NewConnection->ctx);
1550 memset(&NewConnection->exp, 0, sizeof(NewConnection->exp));
1551 NewConnection->attr = 0;
1552 if (AuthInfo) RpcAuthInfo_AddRef(AuthInfo);
1553 NewConnection->AuthInfo = AuthInfo;
1554 NewConnection->encryption_auth_len = 0;
1555 NewConnection->signature_auth_len = 0;
1556 if (QOS) RpcQualityOfService_AddRef(QOS);
1557 NewConnection->QOS = QOS;
1558
1559 list_init(&NewConnection->conn_pool_entry);
1560 NewConnection->async_state = NULL;
1561
1562 TRACE("connection: %p\n", NewConnection);
1563 *Connection = NewConnection;
1564
1565 return RPC_S_OK;
1566 }
1567
1568 static RPC_STATUS RPCRT4_SpawnConnection(RpcConnection** Connection, RpcConnection* OldConnection)
1569 {
1570 RPC_STATUS err;
1571
1572 err = RPCRT4_CreateConnection(Connection, OldConnection->server,
1573 rpcrt4_conn_get_name(OldConnection),
1574 OldConnection->NetworkAddr,
1575 OldConnection->Endpoint, NULL,
1576 OldConnection->AuthInfo, OldConnection->QOS);
1577 if (err == RPC_S_OK)
1578 rpcrt4_conn_handoff(OldConnection, *Connection);
1579 return err;
1580 }
1581
1582 RPC_STATUS RPCRT4_DestroyConnection(RpcConnection* Connection)
1583 {
1584 TRACE("connection: %p\n", Connection);
1585
1586 RPCRT4_CloseConnection(Connection);
1587 RPCRT4_strfree(Connection->Endpoint);
1588 RPCRT4_strfree(Connection->NetworkAddr);
1589 HeapFree(GetProcessHeap(), 0, Connection->NetworkOptions);
1590 if (Connection->AuthInfo) RpcAuthInfo_Release(Connection->AuthInfo);
1591 if (Connection->QOS) RpcQualityOfService_Release(Connection->QOS);
1592
1593 /* server-only */
1594 if (Connection->server_binding) RPCRT4_ReleaseBinding(Connection->server_binding);
1595
1596 HeapFree(GetProcessHeap(), 0, Connection);
1597 return RPC_S_OK;
1598 }
1599
1600 RPC_STATUS RpcTransport_GetTopOfTower(unsigned char *tower_data,
1601 size_t *tower_size,
1602 const char *protseq,
1603 const char *networkaddr,
1604 const char *endpoint)
1605 {
1606 twr_empty_floor_t *protocol_floor;
1607 const struct connection_ops *protseq_ops = rpcrt4_get_conn_protseq_ops(protseq);
1608
1609 *tower_size = 0;
1610
1611 if (!protseq_ops)
1612 return RPC_S_INVALID_RPC_PROTSEQ;
1613
1614 if (!tower_data)
1615 {
1616 *tower_size = sizeof(*protocol_floor);
1617 *tower_size += protseq_ops->get_top_of_tower(NULL, networkaddr, endpoint);
1618 return RPC_S_OK;
1619 }
1620
1621 protocol_floor = (twr_empty_floor_t *)tower_data;
1622 protocol_floor->count_lhs = sizeof(protocol_floor->protid);
1623 protocol_floor->protid = protseq_ops->epm_protocols[0];
1624 protocol_floor->count_rhs = 0;
1625
1626 tower_data += sizeof(*protocol_floor);
1627
1628 *tower_size = protseq_ops->get_top_of_tower(tower_data, networkaddr, endpoint);
1629 if (!*tower_size)
1630 return EPT_S_NOT_REGISTERED;
1631
1632 *tower_size += sizeof(*protocol_floor);
1633
1634 return RPC_S_OK;
1635 }
1636
1637 RPC_STATUS RpcTransport_ParseTopOfTower(const unsigned char *tower_data,
1638 size_t tower_size,
1639 char **protseq,
1640 char **networkaddr,
1641 char **endpoint)
1642 {
1643 const twr_empty_floor_t *protocol_floor;
1644 const twr_empty_floor_t *floor4;
1645 const struct connection_ops *protseq_ops = NULL;
1646 RPC_STATUS status;
1647 unsigned int i;
1648
1649 if (tower_size < sizeof(*protocol_floor))
1650 return EPT_S_NOT_REGISTERED;
1651
1652 protocol_floor = (const twr_empty_floor_t *)tower_data;
1653 tower_data += sizeof(*protocol_floor);
1654 tower_size -= sizeof(*protocol_floor);
1655 if ((protocol_floor->count_lhs != sizeof(protocol_floor->protid)) ||
1656 (protocol_floor->count_rhs > tower_size))
1657 return EPT_S_NOT_REGISTERED;
1658 tower_data += protocol_floor->count_rhs;
1659 tower_size -= protocol_floor->count_rhs;
1660
1661 floor4 = (const twr_empty_floor_t *)tower_data;
1662 if ((tower_size < sizeof(*floor4)) ||
1663 (floor4->count_lhs != sizeof(floor4->protid)))
1664 return EPT_S_NOT_REGISTERED;
1665
1666 for(i = 0; i < ARRAYSIZE(conn_protseq_list); i++)
1667 if ((protocol_floor->protid == conn_protseq_list[i].epm_protocols[0]) &&
1668 (floor4->protid == conn_protseq_list[i].epm_protocols[1]))
1669 {
1670 protseq_ops = &conn_protseq_list[i];
1671 break;
1672 }
1673
1674 if (!protseq_ops)
1675 return EPT_S_NOT_REGISTERED;
1676
1677 status = protseq_ops->parse_top_of_tower(tower_data, tower_size, networkaddr, endpoint);
1678
1679 if ((status == RPC_S_OK) && protseq)
1680 {
1681 *protseq = I_RpcAllocate(strlen(protseq_ops->name) + 1);
1682 strcpy(*protseq, protseq_ops->name);
1683 }
1684
1685 return status;
1686 }
1687
1688 /***********************************************************************
1689 * RpcNetworkIsProtseqValidW (RPCRT4.@)
1690 *
1691 * Checks if the given protocol sequence is known by the RPC system.
1692 * If it is, returns RPC_S_OK, otherwise RPC_S_PROTSEQ_NOT_SUPPORTED.
1693 *
1694 */
1695 RPC_STATUS WINAPI RpcNetworkIsProtseqValidW(RPC_WSTR protseq)
1696 {
1697 char ps[0x10];
1698
1699 WideCharToMultiByte(CP_ACP, 0, protseq, -1,
1700 ps, sizeof ps, NULL, NULL);
1701 if (rpcrt4_get_conn_protseq_ops(ps))
1702 return RPC_S_OK;
1703
1704 FIXME("Unknown protseq %s\n", debugstr_w(protseq));
1705
1706 return RPC_S_INVALID_RPC_PROTSEQ;
1707 }
1708
1709 /***********************************************************************
1710 * RpcNetworkIsProtseqValidA (RPCRT4.@)
1711 */
1712 RPC_STATUS WINAPI RpcNetworkIsProtseqValidA(RPC_CSTR protseq)
1713 {
1714 UNICODE_STRING protseqW;
1715
1716 if (RtlCreateUnicodeStringFromAsciiz(&protseqW, (char*)protseq))
1717 {
1718 RPC_STATUS ret = RpcNetworkIsProtseqValidW(protseqW.Buffer);
1719 RtlFreeUnicodeString(&protseqW);
1720 return ret;
1721 }
1722 return RPC_S_OUT_OF_MEMORY;
1723 }