root/source4/librpc/rpc/dcerpc_sock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sock_dead
  2. sock_error_handler
  3. sock_complete_packet
  4. sock_process_recv
  5. sock_io_handler
  6. sock_send_read
  7. sock_send_request
  8. sock_shutdown_pipe
  9. sock_peer_name
  10. sock_target_hostname
  11. continue_socket_connect
  12. dcerpc_pipe_open_socket_send
  13. dcerpc_pipe_open_socket_recv
  14. continue_ip_resolve_name
  15. continue_ipv6_open_socket
  16. continue_ipv4_open_socket
  17. dcerpc_pipe_open_tcp_send
  18. dcerpc_pipe_open_tcp_recv
  19. continue_unix_open_socket
  20. dcerpc_pipe_open_unix_stream_send
  21. dcerpc_pipe_open_unix_stream_recv
  22. continue_np_open_socket
  23. dcerpc_pipe_open_pipe_send
  24. dcerpc_pipe_open_pipe_recv
  25. dcerpc_pipe_open_pipe
  26. dcerpc_unix_socket_path
  27. dcerpc_socket_peer_addr

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    dcerpc over standard sockets transport
   5 
   6    Copyright (C) Andrew Tridgell 2003
   7    Copyright (C) Jelmer Vernooij 2004
   8    Copyright (C) Rafal Szczesniak 2006
   9    
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program 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
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "lib/events/events.h"
  26 #include "lib/socket/socket.h"
  27 #include "lib/stream/packet.h"
  28 #include "libcli/composite/composite.h"
  29 #include "librpc/rpc/dcerpc.h"
  30 #include "librpc/rpc/dcerpc_proto.h"
  31 #include "libcli/resolve/resolve.h"
  32 
  33 /* transport private information used by general socket pipe transports */
  34 struct sock_private {
  35         struct tevent_fd *fde;
  36         struct socket_context *sock;
  37         char *server_name;
  38 
  39         struct packet_context *packet;
  40         uint32_t pending_reads;
  41 
  42         const char *path; /* For ncacn_unix_sock and ncalrpc */
  43 };
  44 
  45 
  46 /*
  47   mark the socket dead
  48 */
  49 static void sock_dead(struct dcerpc_connection *p, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
  50 {
  51         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
  52 
  53         if (!sock) return;
  54 
  55         if (sock->packet) {
  56                 packet_recv_disable(sock->packet);
  57                 packet_set_fde(sock->packet, NULL);
  58                 packet_set_socket(sock->packet, NULL);
  59         }
  60 
  61         if (sock->fde) {
  62                 talloc_free(sock->fde);
  63                 sock->fde = NULL;
  64         }
  65 
  66         if (sock->sock) {
  67                 talloc_free(sock->sock);
  68                 sock->sock = NULL;
  69         }
  70 
  71         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
  72                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
  73         }
  74 
  75         if (NT_STATUS_EQUAL(NT_STATUS_OK, status)) {
  76                 status = NT_STATUS_END_OF_FILE;
  77         }
  78 
  79         if (p->transport.recv_data) {
  80                 p->transport.recv_data(p, NULL, status);
  81         }
  82 }
  83 
  84 
  85 /*
  86   handle socket recv errors
  87 */
  88 static void sock_error_handler(void *private_data, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
  89 {
  90         struct dcerpc_connection *p = talloc_get_type(private_data,
  91                                                       struct dcerpc_connection);
  92         sock_dead(p, status);
  93 }
  94 
  95 /*
  96   check if a blob is a complete packet
  97 */
  98 static NTSTATUS sock_complete_packet(void *private_data, DATA_BLOB blob, size_t *size)
     /* [<][>][^][v][top][bottom][index][help] */
  99 {
 100         if (blob.length < DCERPC_FRAG_LEN_OFFSET+2) {
 101                 return STATUS_MORE_ENTRIES;
 102         }
 103         *size = dcerpc_get_frag_length(&blob);
 104         if (*size > blob.length) {
 105                 return STATUS_MORE_ENTRIES;
 106         }
 107         return NT_STATUS_OK;
 108 }
 109 
 110 /*
 111   process recv requests
 112 */
 113 static NTSTATUS sock_process_recv(void *private_data, DATA_BLOB blob)
     /* [<][>][^][v][top][bottom][index][help] */
 114 {
 115         struct dcerpc_connection *p = talloc_get_type(private_data,
 116                                                       struct dcerpc_connection);
 117         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 118         sock->pending_reads--;
 119         if (sock->pending_reads == 0) {
 120                 packet_recv_disable(sock->packet);
 121         }
 122         p->transport.recv_data(p, &blob, NT_STATUS_OK);
 123         return NT_STATUS_OK;
 124 }
 125 
 126 /*
 127   called when a IO is triggered by the events system
 128 */
 129 static void sock_io_handler(struct tevent_context *ev, struct tevent_fd *fde, 
     /* [<][>][^][v][top][bottom][index][help] */
 130                             uint16_t flags, void *private_data)
 131 {
 132         struct dcerpc_connection *p = talloc_get_type(private_data,
 133                                                       struct dcerpc_connection);
 134         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 135 
 136         if (flags & EVENT_FD_WRITE) {
 137                 packet_queue_run(sock->packet);
 138                 return;
 139         }
 140 
 141         if (sock->sock == NULL) {
 142                 return;
 143         }
 144 
 145         if (flags & EVENT_FD_READ) {
 146                 packet_recv(sock->packet);
 147         }
 148 }
 149 
 150 /* 
 151    initiate a read request - not needed for dcerpc sockets
 152 */
 153 static NTSTATUS sock_send_read(struct dcerpc_connection *p)
     /* [<][>][^][v][top][bottom][index][help] */
 154 {
 155         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 156         sock->pending_reads++;
 157         if (sock->pending_reads == 1) {
 158                 packet_recv_enable(sock->packet);
 159         }
 160         return NT_STATUS_OK;
 161 }
 162 
 163 /* 
 164    send an initial pdu in a multi-pdu sequence
 165 */
 166 static NTSTATUS sock_send_request(struct dcerpc_connection *p, DATA_BLOB *data, 
     /* [<][>][^][v][top][bottom][index][help] */
 167                                   bool trigger_read)
 168 {
 169         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 170         DATA_BLOB blob;
 171         NTSTATUS status;
 172 
 173         if (sock->sock == NULL) {
 174                 return NT_STATUS_CONNECTION_DISCONNECTED;
 175         }
 176 
 177         blob = data_blob_talloc(sock->packet, data->data, data->length);
 178         if (blob.data == NULL) {
 179                 return NT_STATUS_NO_MEMORY;
 180         }
 181 
 182         status = packet_send(sock->packet, blob);
 183         if (!NT_STATUS_IS_OK(status)) {
 184                 return status;
 185         }
 186 
 187         if (trigger_read) {
 188                 sock_send_read(p);
 189         }
 190 
 191         return NT_STATUS_OK;
 192 }
 193 
 194 /* 
 195    shutdown sock pipe connection
 196 */
 197 static NTSTATUS sock_shutdown_pipe(struct dcerpc_connection *p, NTSTATUS status)
     /* [<][>][^][v][top][bottom][index][help] */
 198 {
 199         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 200 
 201         if (sock && sock->sock) {
 202                 sock_dead(p, status);
 203         }
 204 
 205         return status;
 206 }
 207 
 208 /*
 209   return sock server name
 210 */
 211 static const char *sock_peer_name(struct dcerpc_connection *p)
     /* [<][>][^][v][top][bottom][index][help] */
 212 {
 213         struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);
 214         return sock->server_name;
 215 }
 216 
 217 /*
 218   return remote name we make the actual connection (good for kerberos) 
 219 */
 220 static const char *sock_target_hostname(struct dcerpc_connection *p)
     /* [<][>][^][v][top][bottom][index][help] */
 221 {
 222         struct sock_private *sock = talloc_get_type(p->transport.private_data, struct sock_private);
 223         return sock->server_name;
 224 }
 225 
 226 
 227 struct pipe_open_socket_state {
 228         struct dcerpc_connection *conn;
 229         struct socket_context *socket_ctx;
 230         struct sock_private *sock;
 231         struct socket_address *server;
 232         const char *target_hostname;
 233         enum dcerpc_transport_t transport;
 234 };
 235 
 236 
 237 static void continue_socket_connect(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 238 {
 239         struct dcerpc_connection *conn;
 240         struct sock_private *sock;
 241         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 242                                                       struct composite_context);
 243         struct pipe_open_socket_state *s = talloc_get_type(c->private_data,
 244                                                            struct pipe_open_socket_state);
 245 
 246         /* make it easier to write a function calls */
 247         conn = s->conn;
 248         sock = s->sock;
 249 
 250         c->status = socket_connect_recv(ctx);
 251         if (!NT_STATUS_IS_OK(c->status)) {
 252                 DEBUG(0, ("Failed to connect host %s on port %d - %s\n", 
 253                           s->server->addr, s->server->port,
 254                           nt_errstr(c->status)));
 255                 composite_error(c, c->status);
 256                 return;
 257         }
 258 
 259         /*
 260           fill in the transport methods
 261         */
 262         conn->transport.transport       = s->transport;
 263         conn->transport.private_data    = NULL;
 264 
 265         conn->transport.send_request    = sock_send_request;
 266         conn->transport.send_read       = sock_send_read;
 267         conn->transport.recv_data       = NULL;
 268 
 269         conn->transport.shutdown_pipe   = sock_shutdown_pipe;
 270         conn->transport.peer_name       = sock_peer_name;
 271         conn->transport.target_hostname = sock_target_hostname;
 272 
 273         sock->sock          = s->socket_ctx;
 274         sock->pending_reads = 0;
 275         sock->server_name   = strupper_talloc(sock, s->target_hostname);
 276 
 277         sock->fde = event_add_fd(conn->event_ctx, sock->sock, socket_get_fd(sock->sock),
 278                                  EVENT_FD_READ, sock_io_handler, conn);
 279         
 280         conn->transport.private_data = sock;
 281 
 282         sock->packet = packet_init(sock);
 283         if (sock->packet == NULL) {
 284                 composite_error(c, NT_STATUS_NO_MEMORY);
 285                 talloc_free(sock);
 286                 return;
 287         }
 288 
 289         packet_set_private(sock->packet, conn);
 290         packet_set_socket(sock->packet, sock->sock);
 291         packet_set_callback(sock->packet, sock_process_recv);
 292         packet_set_full_request(sock->packet, sock_complete_packet);
 293         packet_set_error_handler(sock->packet, sock_error_handler);
 294         packet_set_event_context(sock->packet, conn->event_ctx);
 295         packet_set_fde(sock->packet, sock->fde);
 296         packet_set_serialise(sock->packet);
 297         packet_set_initial_read(sock->packet, 16);
 298 
 299         /* ensure we don't get SIGPIPE */
 300         BlockSignals(true, SIGPIPE);
 301 
 302         composite_done(c);
 303 }
 304 
 305 
 306 static struct composite_context *dcerpc_pipe_open_socket_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 307                                                        struct dcerpc_connection *cn,
 308                                                        struct socket_address *server,
 309                                                        const char *target_hostname,
 310                                                        const char *full_path,
 311                                                        enum dcerpc_transport_t transport)
 312 {
 313         struct composite_context *c;
 314         struct pipe_open_socket_state *s;
 315         struct composite_context *conn_req;
 316 
 317         c = composite_create(mem_ctx, cn->event_ctx);
 318         if (c == NULL) return NULL;
 319 
 320         s = talloc_zero(c, struct pipe_open_socket_state);
 321         if (composite_nomem(s, c)) return c;
 322         c->private_data = s;
 323 
 324         s->conn      = cn;
 325         s->transport = transport;
 326         s->server    = talloc_reference(c, server);
 327         if (composite_nomem(s->server, c)) return c;
 328         s->target_hostname = talloc_reference(s, target_hostname);
 329 
 330         s->sock = talloc(cn, struct sock_private);
 331         if (composite_nomem(s->sock, c)) return c;
 332 
 333         c->status = socket_create(server->family, SOCKET_TYPE_STREAM, &s->socket_ctx, 0);
 334         if (!composite_is_ok(c)) return c;
 335 
 336         talloc_steal(s->sock, s->socket_ctx);
 337 
 338         s->sock->path = talloc_reference(s->sock, full_path);
 339 
 340         conn_req = socket_connect_send(s->socket_ctx, NULL, s->server, 0, 
 341                                        c->event_ctx);
 342         composite_continue(c, conn_req, continue_socket_connect, c);
 343         return c;
 344 }
 345 
 346 
 347 static NTSTATUS dcerpc_pipe_open_socket_recv(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 349         NTSTATUS status = composite_wait(c);
 350 
 351         talloc_free(c);
 352         return status;
 353 }
 354 
 355 struct pipe_tcp_state {
 356         const char *server;
 357         const char *target_hostname;
 358         const char *address;
 359         uint32_t port;
 360         struct socket_address *srvaddr;
 361         struct resolve_context *resolve_ctx;
 362         struct dcerpc_connection *conn;
 363 };
 364 
 365 
 366 #if 0 /* disabled till we can resolve names to ipv6 addresses */
 367 static void continue_ipv6_open_socket(struct composite_context *ctx);
 368 #endif
 369 static void continue_ipv4_open_socket(struct composite_context *ctx);
 370 static void continue_ip_resolve_name(struct composite_context *ctx);
 371 
 372 static void continue_ip_resolve_name(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 373 {
 374         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 375                                                       struct composite_context);
 376         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
 377                                                    struct pipe_tcp_state);
 378         struct composite_context *sock_ipv4_req;
 379 
 380         c->status = resolve_name_recv(ctx, s, &s->address);
 381         if (!composite_is_ok(c)) return;
 382 
 383         /* prepare server address using host ip:port and transport name */
 384         s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port);
 385         if (composite_nomem(s->srvaddr, c)) return;
 386 
 387         /* resolve_nbt_name gives only ipv4 ... - send socket open request */
 388         sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn,
 389                                                      s->srvaddr, s->target_hostname,
 390                                                      NULL,
 391                                                      NCACN_IP_TCP);
 392         composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
 393 }
 394 
 395 /*
 396   Stage 2 of dcerpc_pipe_open_tcp_send: receive result of pipe open request
 397   on IPv6 and send the request on IPv4 unless IPv6 transport succeeded.
 398 */
 399 #if 0 /* disabled till we can resolve names to ipv6 addresses */
 400 static void continue_ipv6_open_socket(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 401 {
 402         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 403                                                       struct composite_context);
 404         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
 405                                                    struct pipe_tcp_state);
 406         struct composite_context *sock_ipv4_req;
 407 
 408         /* receive result of socket open request */
 409         c->status = dcerpc_pipe_open_socket_recv(ctx);
 410         if (NT_STATUS_IS_OK(c->status)) {
 411                 composite_done(c);
 412                 return;
 413         }
 414 
 415         talloc_free(s->srvaddr);
 416 
 417         /* prepare server address using host:ip and transport name */
 418         s->srvaddr = socket_address_from_strings(s->conn, "ipv4", s->address, s->port);
 419         if (composite_nomem(s->srvaddr, c)) return;
 420 
 421         /* try IPv4 if IPv6 fails */
 422         sock_ipv4_req = dcerpc_pipe_open_socket_send(c, s->conn, 
 423                                                      s->srvaddr, s->target_hostname, 
 424                                                      NCACN_IP_TCP);
 425         composite_continue(c, sock_ipv4_req, continue_ipv4_open_socket, c);
 426 }
 427 #endif
 428 
 429 /*
 430   Stage 2 of dcerpc_pipe_open_tcp_send: receive result of pipe open request
 431   on IPv4 transport.
 432 */
 433 static void continue_ipv4_open_socket(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 434 {
 435         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 436                                                       struct composite_context);
 437         struct pipe_tcp_state *s = talloc_get_type(c->private_data,
 438                                                    struct pipe_tcp_state);
 439         
 440         /* receive result socket open request */
 441         c->status = dcerpc_pipe_open_socket_recv(ctx);
 442         if (!NT_STATUS_IS_OK(c->status)) {
 443                 /* something went wrong... */
 444                 DEBUG(0, ("Failed to connect host %s (%s) on port %d - %s.\n",
 445                           s->address, s->target_hostname, 
 446                           s->port, nt_errstr(c->status)));
 447 
 448                 composite_error(c, c->status);
 449                 return;
 450         }
 451 
 452         composite_done(c);
 453 }
 454 
 455 
 456 /*
 457   Send rpc pipe open request to given host:port using
 458   tcp/ip transport
 459 */
 460 struct composite_context* dcerpc_pipe_open_tcp_send(struct dcerpc_connection *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 461                                                     const char *server,
 462                                                     const char *target_hostname,
 463                                                     uint32_t port,
 464                                                     struct resolve_context *resolve_ctx)
 465 {
 466         struct composite_context *c;
 467         struct pipe_tcp_state *s;
 468         struct composite_context *resolve_req;
 469         struct nbt_name name;
 470 
 471         /* composite context allocation and setup */
 472         c = composite_create(conn, conn->event_ctx);
 473         if (c == NULL) return NULL;
 474 
 475         s = talloc_zero(c, struct pipe_tcp_state);
 476         if (composite_nomem(s, c)) return c;
 477         c->private_data = s;
 478 
 479         /* store input parameters in state structure */
 480         s->server          = talloc_strdup(c, server);
 481         if (composite_nomem(s->server, c)) return c;
 482         if (target_hostname) {
 483                 s->target_hostname = talloc_strdup(c, target_hostname);
 484                 if (composite_nomem(s->target_hostname, c)) return c;
 485         }
 486         s->port            = port;
 487         s->conn            = conn;
 488         s->resolve_ctx     = resolve_ctx;
 489 
 490         make_nbt_name_server(&name, server);
 491         resolve_req = resolve_name_send(resolve_ctx, &name, c->event_ctx);
 492         composite_continue(c, resolve_req, continue_ip_resolve_name, c);
 493         return c;
 494 }
 495 
 496 /*
 497   Receive result of pipe open request on tcp/ip
 498 */
 499 NTSTATUS dcerpc_pipe_open_tcp_recv(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 500 {
 501         NTSTATUS status;
 502         status = composite_wait(c);
 503 
 504         talloc_free(c);
 505         return status;
 506 }
 507 
 508 
 509 struct pipe_unix_state {
 510         const char *path;
 511         struct socket_address *srvaddr;
 512         struct dcerpc_connection *conn;
 513 };
 514 
 515 
 516 /*
 517   Stage 2 of dcerpc_pipe_open_unix_stream_send: receive result of pipe open
 518   request on unix socket.
 519 */
 520 static void continue_unix_open_socket(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 521 {
 522         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 523                                                       struct composite_context);
 524 
 525         c->status = dcerpc_pipe_open_socket_recv(ctx);
 526         if (NT_STATUS_IS_OK(c->status)) {
 527                 composite_done(c);
 528                 return;
 529         }
 530 
 531         composite_error(c, c->status);
 532 }
 533 
 534 
 535 /*
 536   Send pipe open request on unix socket
 537 */
 538 struct composite_context *dcerpc_pipe_open_unix_stream_send(struct dcerpc_connection *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 539                                                             const char *path)
 540 {
 541         struct composite_context *c;
 542         struct composite_context *sock_unix_req;
 543         struct pipe_unix_state *s;
 544 
 545         /* composite context allocation and setup */
 546         c = composite_create(conn, conn->event_ctx);
 547         if (c == NULL) return NULL;
 548 
 549         s = talloc_zero(c, struct pipe_unix_state);
 550         if (composite_nomem(s, c)) return c;
 551         c->private_data = s;
 552 
 553         /* store parameters in state structure */
 554         s->path = talloc_strdup(c, path);
 555         if (composite_nomem(s->path, c)) return c;
 556         s->conn = conn;
 557 
 558         /* prepare server address using socket path and transport name */
 559         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
 560         if (composite_nomem(s->srvaddr, c)) return c;
 561 
 562         /* send socket open request */
 563         sock_unix_req = dcerpc_pipe_open_socket_send(c, s->conn, 
 564                                                      s->srvaddr, NULL,
 565                                                      s->path,
 566                                                      NCALRPC);
 567         composite_continue(c, sock_unix_req, continue_unix_open_socket, c);
 568         return c;
 569 }
 570 
 571 
 572 /*
 573   Receive result of pipe open request on unix socket
 574 */
 575 NTSTATUS dcerpc_pipe_open_unix_stream_recv(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 576 {
 577         NTSTATUS status = composite_wait(c);
 578 
 579         talloc_free(c);
 580         return status;
 581 }
 582 
 583 
 584 /*
 585   Stage 2 of dcerpc_pipe_open_pipe_send: receive socket open request
 586 */
 587 static void continue_np_open_socket(struct composite_context *ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 588 {
 589         struct composite_context *c = talloc_get_type(ctx->async.private_data,
 590                                                       struct composite_context);
 591 
 592         c->status = dcerpc_pipe_open_socket_recv(ctx);
 593         if (!composite_is_ok(c)) return;
 594 
 595         composite_done(c);
 596 }
 597 
 598 
 599 /*
 600   Send pipe open request on ncalrpc
 601 */
 602 struct composite_context* dcerpc_pipe_open_pipe_send(struct dcerpc_connection *conn,
     /* [<][>][^][v][top][bottom][index][help] */
 603                                                      const char *ncalrpc_dir,
 604                                                      const char *identifier)
 605 {
 606         char *canon = NULL;
 607 
 608         struct composite_context *c;
 609         struct composite_context *sock_np_req;
 610         struct pipe_unix_state *s;
 611 
 612         /* composite context allocation and setup */
 613         c = composite_create(conn, conn->event_ctx);
 614         if (c == NULL) return NULL;
 615 
 616         s = talloc_zero(c, struct pipe_unix_state);
 617         if (composite_nomem(s, c)) return c;
 618         c->private_data = s;
 619 
 620         /* store parameters in state structure */
 621         canon = talloc_strdup(s, identifier);
 622         if (composite_nomem(canon, c)) return c;
 623         s->conn = conn;
 624 
 625         string_replace(canon, '/', '\\');
 626         s->path = talloc_asprintf(canon, "%s/%s", ncalrpc_dir, canon);
 627         if (composite_nomem(s->path, c)) return c;
 628 
 629         /* prepare server address using path and transport name */
 630         s->srvaddr = socket_address_from_strings(conn, "unix", s->path, 0);
 631         if (composite_nomem(s->srvaddr, c)) return c;
 632 
 633         /* send socket open request */
 634         sock_np_req = dcerpc_pipe_open_socket_send(c, s->conn, s->srvaddr, NULL, s->path, NCALRPC);
 635         composite_continue(c, sock_np_req, continue_np_open_socket, c);
 636         return c;
 637 }
 638 
 639 
 640 /*
 641   Receive result of pipe open request on ncalrpc
 642 */
 643 NTSTATUS dcerpc_pipe_open_pipe_recv(struct composite_context *c)
     /* [<][>][^][v][top][bottom][index][help] */
 644 {
 645         NTSTATUS status = composite_wait(c);
 646         
 647         talloc_free(c);
 648         return status;
 649 }
 650 
 651 
 652 /*
 653   Open a rpc pipe on a named pipe - sync version
 654 */
 655 NTSTATUS dcerpc_pipe_open_pipe(struct dcerpc_connection *conn, const char *ncalrpc_dir, const char *identifier)
     /* [<][>][^][v][top][bottom][index][help] */
 656 {
 657         struct composite_context *c = dcerpc_pipe_open_pipe_send(conn, ncalrpc_dir, identifier);
 658         return dcerpc_pipe_open_pipe_recv(c);
 659 }
 660 
 661 const char *dcerpc_unix_socket_path(struct dcerpc_connection *p)
     /* [<][>][^][v][top][bottom][index][help] */
 662 {
 663         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 664         return sock->path;
 665 }
 666 
 667 struct socket_address *dcerpc_socket_peer_addr(struct dcerpc_connection *p, TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 668 {
 669         struct sock_private *sock = (struct sock_private *)p->transport.private_data;
 670         return socket_get_peer_addr(sock->sock, mem_ctx);
 671 }
 672 

/* [<][>][^][v][top][bottom][index][help] */