root/source3/rpc_client/rpc_transport_smbd.c

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

DEFINITIONS

This source file includes following definitions.
  1. rpc_cli_smbd_stdout_reader
  2. rpc_cli_smbd_conn_destructor
  3. get_anon_ipc_send
  4. get_anon_ipc_negprot_done
  5. get_anon_ipc_sesssetup_done
  6. get_anon_ipc_tcon_done
  7. get_anon_ipc_recv
  8. rpc_cli_smbd_conn_init_send
  9. rpc_cli_smbd_conn_init_done
  10. rpc_cli_smbd_conn_init_recv
  11. rpc_cli_smbd_conn_init
  12. rpc_smbd_write_send
  13. rpc_smbd_write_done
  14. rpc_smbd_write_recv
  15. rpc_smbd_read_send
  16. rpc_smbd_read_done
  17. rpc_smbd_read_recv
  18. rpc_transport_smbd_init_send
  19. rpc_transport_smbd_init_done
  20. rpc_transport_smbd_init_recv
  21. rpc_transport_smbd_init
  22. rpc_pipe_smbd_smb_conn

   1 /*
   2  *  Unix SMB/CIFS implementation.
   3  *  RPC client transport over named pipes to a child smbd
   4  *  Copyright (C) Volker Lendecke 2009
   5  *
   6  *  This program is free software; you can redistribute it and/or modify
   7  *  it under the terms of the GNU General Public License as published by
   8  *  the Free Software Foundation; either version 3 of the License, or
   9  *  (at your option) any later version.
  10  *
  11  *  This program is distributed in the hope that it will be useful,
  12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  *  GNU General Public License for more details.
  15  *
  16  *  You should have received a copy of the GNU General Public License
  17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
  18  */
  19 
  20 #include "includes.h"
  21 
  22 #undef DBGC_CLASS
  23 #define DBGC_CLASS DBGC_RPC_CLI
  24 
  25 /**
  26  * struct rpc_cli_smbd_conn represents a forked smbd. This structure should
  27  * exist only once per process which does the rpc calls.
  28  *
  29  * RPC pipe handles can be attached to this smbd connection with
  30  * rpc_pipe_open_local().
  31  *
  32  * For this to work right, we can not use rpc_transport_np directly, because
  33  * the child smbd wants to write its DEBUG output somewhere. We redirect the
  34  * child's output to rpc_cli_smbd_conn->stdout_fd. While the RPC calls are
  35  * active, we have an event context available and attach a fd event to the
  36  * stdout_df.
  37  */
  38 
  39 struct rpc_cli_smbd_conn {
  40         /**
  41          * The smb connection to handle the named pipe traffic over
  42          */
  43         struct cli_state *cli;
  44 
  45         /**
  46          * Attached to stdout in the forked smbd, this is where smbd will
  47          * print its DEBUG.
  48          */
  49         int stdout_fd;
  50 
  51         /**
  52          * Custom callback provided by the owner of the
  53          * rpc_cli_smbd_conn. Here we send the smbd DEBUG output. Can be NULL.
  54          */
  55         struct {
  56                 void (*fn)(char *buf, size_t len, void *priv);
  57                 void *priv;
  58         } stdout_callback ;
  59 };
  60 
  61 /**
  62  * Event handler to be called whenever the forked smbd prints debugging
  63  * output.
  64  */
  65 
  66 static void rpc_cli_smbd_stdout_reader(struct event_context *ev,
     /* [<][>][^][v][top][bottom][index][help] */
  67                                        struct fd_event *fde,
  68                                        uint16_t flags, void *priv)
  69 {
  70         struct rpc_cli_smbd_conn *conn = talloc_get_type_abort(
  71                 priv, struct rpc_cli_smbd_conn);
  72         char buf[1024];
  73         ssize_t nread;
  74 
  75         if ((flags & EVENT_FD_READ) == 0) {
  76                 return;
  77         }
  78 
  79         nread = read(conn->stdout_fd, buf, sizeof(buf)-1);
  80         if (nread < 0) {
  81                 DEBUG(0, ("Could not read from smbd stdout: %s\n",
  82                           strerror(errno)));
  83                 TALLOC_FREE(fde);
  84                 return;
  85         }
  86         if (nread == 0) {
  87                 DEBUG(0, ("EOF from smbd stdout\n"));
  88                 TALLOC_FREE(fde);
  89                 return;
  90         }
  91         buf[nread] = '\0';
  92 
  93         if (conn->stdout_callback.fn != NULL) {
  94                 conn->stdout_callback.fn(buf, nread,
  95                                          conn->stdout_callback.priv);
  96         }
  97 }
  98 
  99 /**
 100  * struct rpc_transport_smbd_state is the link from a struct rpc_pipe_client
 101  * to the rpc_cli_smbd_conn. We use a named pipe transport as a subtransport.
 102  */
 103 
 104 struct rpc_transport_smbd_state {
 105         struct rpc_cli_smbd_conn *conn;
 106         struct rpc_cli_transport *sub_transp;
 107 };
 108 
 109 static int rpc_cli_smbd_conn_destructor(struct rpc_cli_smbd_conn *conn)
     /* [<][>][^][v][top][bottom][index][help] */
 110 {
 111         if (conn->cli != NULL) {
 112                 cli_shutdown(conn->cli);
 113                 conn->cli = NULL;
 114         }
 115         if (conn->stdout_fd != -1) {
 116                 close(conn->stdout_fd);
 117                 conn->stdout_fd = -1;
 118         }
 119         return 0;
 120 }
 121 
 122 /*
 123  * Do the negprot/sesssetup/tcon to an anonymous ipc$ connection
 124  */
 125 
 126 struct get_anon_ipc_state {
 127         struct event_context *ev;
 128         struct cli_state *cli;
 129 };
 130 
 131 static void get_anon_ipc_negprot_done(struct async_req *subreq);
 132 static void get_anon_ipc_sesssetup_done(struct async_req *subreq);
 133 static void get_anon_ipc_tcon_done(struct async_req *subreq);
 134 
 135 static struct async_req *get_anon_ipc_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 136                                            struct event_context *ev,
 137                                            struct cli_state *cli)
 138 {
 139         struct async_req *result, *subreq;
 140         struct get_anon_ipc_state *state;
 141 
 142         if (!async_req_setup(mem_ctx, &result, &state,
 143                              struct get_anon_ipc_state)) {
 144                 return NULL;
 145         }
 146 
 147         state->ev = ev;
 148         state->cli = cli;
 149 
 150         subreq = cli_negprot_send(state, ev, cli);
 151         if (subreq == NULL) {
 152                 goto fail;
 153         }
 154         subreq->async.fn = get_anon_ipc_negprot_done;
 155         subreq->async.priv = result;
 156         return result;
 157  fail:
 158         TALLOC_FREE(result);
 159         return NULL;
 160 }
 161 
 162 static void get_anon_ipc_negprot_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 163 {
 164         struct async_req *req = talloc_get_type_abort(
 165                 subreq->async.priv, struct async_req);
 166         struct get_anon_ipc_state *state = talloc_get_type_abort(
 167                 req->private_data, struct get_anon_ipc_state);
 168         NTSTATUS status;
 169 
 170         status = cli_negprot_recv(subreq);
 171         TALLOC_FREE(subreq);
 172         if (!NT_STATUS_IS_OK(status)) {
 173                 async_req_nterror(req, status);
 174                 return;
 175         }
 176 
 177         subreq = cli_session_setup_guest_send(state, state->ev, state->cli);
 178         if (async_req_nomem(subreq, req)) {
 179                 return;
 180         }
 181         subreq->async.fn = get_anon_ipc_sesssetup_done;
 182         subreq->async.priv = req;
 183 }
 184 
 185 static void get_anon_ipc_sesssetup_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 186 {
 187         struct async_req *req = talloc_get_type_abort(
 188                 subreq->async.priv, struct async_req);
 189         struct get_anon_ipc_state *state = talloc_get_type_abort(
 190                 req->private_data, struct get_anon_ipc_state);
 191         NTSTATUS status;
 192 
 193         status = cli_session_setup_guest_recv(subreq);
 194         TALLOC_FREE(subreq);
 195         if (!NT_STATUS_IS_OK(status)) {
 196                 async_req_nterror(req, status);
 197                 return;
 198         }
 199 
 200         subreq = cli_tcon_andx_send(state, state->ev, state->cli,
 201                                     "IPC$", "IPC", NULL, 0);
 202         if (async_req_nomem(subreq, req)) {
 203                 return;
 204         }
 205         subreq->async.fn = get_anon_ipc_tcon_done;
 206         subreq->async.priv = req;
 207 }
 208 
 209 static void get_anon_ipc_tcon_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 210 {
 211         struct async_req *req = talloc_get_type_abort(
 212                 subreq->async.priv, struct async_req);
 213         NTSTATUS status;
 214 
 215         status = cli_tcon_andx_recv(subreq);
 216         TALLOC_FREE(subreq);
 217         if (!NT_STATUS_IS_OK(status)) {
 218                 async_req_nterror(req, status);
 219                 return;
 220         }
 221         async_req_done(req);
 222 }
 223 
 224 static NTSTATUS get_anon_ipc_recv(struct async_req *req)
     /* [<][>][^][v][top][bottom][index][help] */
 225 {
 226         return async_req_simple_recv_ntstatus(req);
 227 }
 228 
 229 struct rpc_cli_smbd_conn_init_state {
 230         struct event_context *ev;
 231         struct rpc_cli_smbd_conn *conn;
 232 };
 233 
 234 static void rpc_cli_smbd_conn_init_done(struct async_req *subreq);
 235 
 236 struct async_req *rpc_cli_smbd_conn_init_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 237                                               struct event_context *ev,
 238                                               void (*stdout_callback)(char *buf,
 239                                                                       size_t len,
 240                                                                       void *priv),
 241                                               void *priv)
 242 {
 243         struct async_req *result, *subreq;
 244         struct rpc_cli_smbd_conn_init_state *state;
 245         int smb_sock[2];
 246         int stdout_pipe[2];
 247         NTSTATUS status;
 248         pid_t pid;
 249         int ret;
 250 
 251         smb_sock[0] = smb_sock[1] = stdout_pipe[0] = stdout_pipe[1] = -1;
 252 
 253         if (!async_req_setup(mem_ctx, &result, &state,
 254                              struct rpc_cli_smbd_conn_init_state)) {
 255                 return NULL;
 256         }
 257         state->ev = ev;
 258 
 259         state->conn = talloc(state, struct rpc_cli_smbd_conn);
 260         if (state->conn == NULL) {
 261                 goto nomem;
 262         }
 263 
 264         state->conn->cli = cli_initialise();
 265         if (state->conn->cli == NULL) {
 266                 goto nomem;
 267         }
 268         state->conn->stdout_fd = -1;
 269         state->conn->stdout_callback.fn = stdout_callback;
 270         state->conn->stdout_callback.priv = priv;
 271         talloc_set_destructor(state->conn, rpc_cli_smbd_conn_destructor);
 272 
 273         ret = socketpair(AF_UNIX, SOCK_STREAM, 0, smb_sock);
 274         if (ret == -1) {
 275                 status = map_nt_error_from_unix(errno);
 276                 goto post_status;
 277         }
 278         ret = pipe(stdout_pipe);
 279         if (ret == -1) {
 280                 status = map_nt_error_from_unix(errno);
 281                 goto post_status;
 282         }
 283 
 284         pid = sys_fork();
 285         if (pid == -1) {
 286                 status = map_nt_error_from_unix(errno);
 287                 goto post_status;
 288         }
 289         if (pid == 0) {
 290                 char *smbd_cmd;
 291 
 292                 close(smb_sock[0]);
 293                 close(stdout_pipe[0]);
 294                 close(0);
 295                 if (dup(smb_sock[1]) == -1) {
 296                         exit(1);
 297                 }
 298                 close(smb_sock[1]);
 299                 close(1);
 300                 if (dup(stdout_pipe[1]) == -1) {
 301                         exit(1);
 302                 }
 303                 close(stdout_pipe[1]);
 304 
 305                 smbd_cmd = getenv("SMB_PATH");
 306 
 307                 if ((smbd_cmd == NULL)
 308                     && (asprintf(&smbd_cmd, "%s/smbd", get_dyn_SBINDIR())
 309                         == -1)) {
 310                         printf("no memory");
 311                         exit(1);
 312                 }
 313                 if (asprintf(&smbd_cmd, "%s -F -S -d %d", smbd_cmd,
 314                              DEBUGLEVEL) == -1) {
 315                         printf("no memory");
 316                         exit(1);
 317                 }
 318 
 319                 exit(system(smbd_cmd));
 320         }
 321 
 322         state->conn->cli->fd = smb_sock[0];
 323         smb_sock[0] = -1;
 324         close(smb_sock[1]);
 325         smb_sock[1] = -1;
 326 
 327         state->conn->stdout_fd = stdout_pipe[0];
 328         stdout_pipe[0] = -1;
 329         close(stdout_pipe[1]);
 330         stdout_pipe[1] = -1;
 331 
 332         subreq = get_anon_ipc_send(state, ev, state->conn->cli);
 333         if (subreq == NULL) {
 334                 goto nomem;
 335         }
 336 
 337         if (event_add_fd(ev, state, state->conn->stdout_fd, EVENT_FD_READ,
 338                          rpc_cli_smbd_stdout_reader, state->conn) == NULL) {
 339                 goto nomem;
 340         }
 341 
 342         subreq->async.fn = rpc_cli_smbd_conn_init_done;
 343         subreq->async.priv = result;
 344         return result;
 345 
 346  nomem:
 347         status = NT_STATUS_NO_MEMORY;
 348  post_status:
 349         if (smb_sock[0] != -1) {
 350                 close(smb_sock[0]);
 351         }
 352         if (smb_sock[1] != -1) {
 353                 close(smb_sock[1]);
 354         }
 355         if (stdout_pipe[0] != -1) {
 356                 close(stdout_pipe[0]);
 357         }
 358         if (stdout_pipe[1] != -1) {
 359                 close(stdout_pipe[1]);
 360         }
 361         if (async_post_ntstatus(result, ev, status)) {
 362                 return result;
 363         }
 364         TALLOC_FREE(result);
 365         return NULL;
 366 }
 367 
 368 static void rpc_cli_smbd_conn_init_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 369 {
 370         struct async_req *req = talloc_get_type_abort(
 371                 subreq->async.priv, struct async_req);
 372         NTSTATUS status;
 373 
 374         status = get_anon_ipc_recv(subreq);
 375         TALLOC_FREE(subreq);
 376         if (!NT_STATUS_IS_OK(status)) {
 377                 async_req_nterror(req, status);
 378                 return;
 379         }
 380         async_req_done(req);
 381 }
 382 
 383 NTSTATUS rpc_cli_smbd_conn_init_recv(struct async_req *req,
     /* [<][>][^][v][top][bottom][index][help] */
 384                                      TALLOC_CTX *mem_ctx,
 385                                      struct rpc_cli_smbd_conn **pconn)
 386 {
 387         struct rpc_cli_smbd_conn_init_state *state = talloc_get_type_abort(
 388                 req->private_data, struct rpc_cli_smbd_conn_init_state);
 389         NTSTATUS status;
 390 
 391         if (async_req_is_nterror(req, &status)) {
 392                 return status;
 393         }
 394         *pconn = talloc_move(mem_ctx, &state->conn);
 395         return NT_STATUS_OK;
 396 }
 397 
 398 NTSTATUS rpc_cli_smbd_conn_init(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 399                                 struct rpc_cli_smbd_conn **pconn,
 400                                 void (*stdout_callback)(char *buf,
 401                                                         size_t len,
 402                                                         void *priv),
 403                                 void *priv)
 404 {
 405         TALLOC_CTX *frame = talloc_stackframe();
 406         struct event_context *ev;
 407         struct async_req *req;
 408         NTSTATUS status;
 409 
 410         ev = event_context_init(frame);
 411         if (ev == NULL) {
 412                 status = NT_STATUS_NO_MEMORY;
 413                 goto fail;
 414         }
 415 
 416         req = rpc_cli_smbd_conn_init_send(frame, ev, stdout_callback, priv);
 417         if (req == NULL) {
 418                 status = NT_STATUS_NO_MEMORY;
 419                 goto fail;
 420         }
 421 
 422         while (req->state < ASYNC_REQ_DONE) {
 423                 event_loop_once(ev);
 424         }
 425 
 426         status = rpc_cli_smbd_conn_init_recv(req, mem_ctx, pconn);
 427  fail:
 428         TALLOC_FREE(frame);
 429         return status;
 430 }
 431 
 432 struct rpc_smbd_write_state {
 433         struct rpc_cli_transport *sub_transp;
 434         ssize_t written;
 435 };
 436 
 437 static void rpc_smbd_write_done(struct async_req *subreq);
 438 
 439 static struct async_req *rpc_smbd_write_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 440                                              struct event_context *ev,
 441                                              const uint8_t *data, size_t size,
 442                                              void *priv)
 443 {
 444         struct rpc_transport_smbd_state *transp = talloc_get_type_abort(
 445                 priv, struct rpc_transport_smbd_state);
 446         struct async_req *result, *subreq;
 447         struct rpc_smbd_write_state *state;
 448 
 449         if (!async_req_setup(mem_ctx, &result, &state,
 450                              struct rpc_smbd_write_state)) {
 451                 return NULL;
 452         }
 453         state->sub_transp = transp->sub_transp;
 454 
 455         subreq = transp->sub_transp->write_send(state, ev, data, size,
 456                                                 transp->sub_transp->priv);
 457         if (subreq == NULL) {
 458                 goto fail;
 459         }
 460 
 461         if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ,
 462                          rpc_cli_smbd_stdout_reader, transp->conn) == NULL) {
 463                 goto fail;
 464         }
 465 
 466         subreq->async.fn = rpc_smbd_write_done;
 467         subreq->async.priv = result;
 468         return result;
 469 
 470  fail:
 471         TALLOC_FREE(result);
 472         return NULL;
 473 }
 474 
 475 static void rpc_smbd_write_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 476 {
 477         struct async_req *req = talloc_get_type_abort(
 478                 subreq->async.priv, struct async_req);
 479         struct rpc_smbd_write_state *state = talloc_get_type_abort(
 480                 req->private_data, struct rpc_smbd_write_state);
 481         NTSTATUS status;
 482 
 483         status = state->sub_transp->write_recv(subreq, &state->written);
 484         TALLOC_FREE(subreq);
 485         if (!NT_STATUS_IS_OK(status)) {
 486                 async_req_nterror(req, status);
 487                 return;
 488         }
 489         async_req_done(req);
 490 }
 491 
 492 static NTSTATUS rpc_smbd_write_recv(struct async_req *req, ssize_t *pwritten)
     /* [<][>][^][v][top][bottom][index][help] */
 493 {
 494         struct rpc_smbd_write_state *state = talloc_get_type_abort(
 495                 req->private_data, struct rpc_smbd_write_state);
 496         NTSTATUS status;
 497 
 498         if (async_req_is_nterror(req, &status)) {
 499                 return status;
 500         }
 501         *pwritten = state->written;
 502         return NT_STATUS_OK;
 503 }
 504 
 505 struct rpc_smbd_read_state {
 506         struct rpc_cli_transport *sub_transp;
 507         ssize_t received;
 508 };
 509 
 510 static void rpc_smbd_read_done(struct async_req *subreq);
 511 
 512 static struct async_req *rpc_smbd_read_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 513                                             struct event_context *ev,
 514                                             uint8_t *data, size_t size,
 515                                             void *priv)
 516 {
 517         struct rpc_transport_smbd_state *transp = talloc_get_type_abort(
 518                 priv, struct rpc_transport_smbd_state);
 519         struct async_req *result, *subreq;
 520         struct rpc_smbd_read_state *state;
 521 
 522         if (!async_req_setup(mem_ctx, &result, &state,
 523                              struct rpc_smbd_read_state)) {
 524                 return NULL;
 525         }
 526         state->sub_transp = transp->sub_transp;
 527 
 528         subreq = transp->sub_transp->read_send(state, ev, data, size,
 529                                                 transp->sub_transp->priv);
 530         if (subreq == NULL) {
 531                 goto fail;
 532         }
 533 
 534         if (event_add_fd(ev, state, transp->conn->stdout_fd, EVENT_FD_READ,
 535                          rpc_cli_smbd_stdout_reader, transp->conn) == NULL) {
 536                 goto fail;
 537         }
 538 
 539         subreq->async.fn = rpc_smbd_read_done;
 540         subreq->async.priv = result;
 541         return result;
 542 
 543  fail:
 544         TALLOC_FREE(result);
 545         return NULL;
 546 }
 547 
 548 static void rpc_smbd_read_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 549 {
 550         struct async_req *req = talloc_get_type_abort(
 551                 subreq->async.priv, struct async_req);
 552         struct rpc_smbd_read_state *state = talloc_get_type_abort(
 553                 req->private_data, struct rpc_smbd_read_state);
 554         NTSTATUS status;
 555 
 556         status = state->sub_transp->read_recv(subreq, &state->received);
 557         TALLOC_FREE(subreq);
 558         if (!NT_STATUS_IS_OK(status)) {
 559                 async_req_nterror(req, status);
 560                 return;
 561         }
 562         async_req_done(req);
 563 }
 564 
 565 static NTSTATUS rpc_smbd_read_recv(struct async_req *req, ssize_t *preceived)
     /* [<][>][^][v][top][bottom][index][help] */
 566 {
 567         struct rpc_smbd_read_state *state = talloc_get_type_abort(
 568                 req->private_data, struct rpc_smbd_read_state);
 569         NTSTATUS status;
 570 
 571         if (async_req_is_nterror(req, &status)) {
 572                 return status;
 573         }
 574         *preceived = state->received;
 575         return NT_STATUS_OK;
 576 }
 577 
 578 struct rpc_transport_smbd_init_state {
 579         struct rpc_cli_transport *transport;
 580         struct rpc_transport_smbd_state *transport_smbd;
 581 };
 582 
 583 static void rpc_transport_smbd_init_done(struct async_req *subreq);
 584 
 585 struct async_req *rpc_transport_smbd_init_send(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 586                                                struct event_context *ev,
 587                                                struct rpc_cli_smbd_conn *conn,
 588                                                const struct ndr_syntax_id *abstract_syntax)
 589 {
 590         struct async_req *result, *subreq;
 591         struct rpc_transport_smbd_init_state *state;
 592 
 593         if (!async_req_setup(mem_ctx, &result, &state,
 594                              struct rpc_transport_smbd_init_state)) {
 595                 return NULL;
 596         }
 597 
 598         state->transport = talloc(state, struct rpc_cli_transport);
 599         if (state->transport == NULL) {
 600                 goto fail;
 601         }
 602         state->transport_smbd = talloc(state->transport,
 603                                        struct rpc_transport_smbd_state);
 604         if (state->transport_smbd == NULL) {
 605                 goto fail;
 606         }
 607         state->transport_smbd->conn = conn;
 608         state->transport->priv = state->transport_smbd;
 609 
 610         if (event_add_fd(ev, state, conn->stdout_fd, EVENT_FD_READ,
 611                          rpc_cli_smbd_stdout_reader, conn) == NULL) {
 612                 goto fail;
 613         }
 614 
 615         subreq = rpc_transport_np_init_send(state, ev, conn->cli,
 616                                             abstract_syntax);
 617         if (subreq == NULL) {
 618                 goto fail;
 619         }
 620         subreq->async.fn = rpc_transport_smbd_init_done;
 621         subreq->async.priv = result;
 622         return result;
 623 
 624  fail:
 625         TALLOC_FREE(result);
 626         return NULL;
 627 }
 628 
 629 static void rpc_transport_smbd_init_done(struct async_req *subreq)
     /* [<][>][^][v][top][bottom][index][help] */
 630 {
 631         struct async_req *req = talloc_get_type_abort(
 632                 subreq->async.priv, struct async_req);
 633         struct rpc_transport_smbd_init_state *state = talloc_get_type_abort(
 634                 req->private_data, struct rpc_transport_smbd_init_state);
 635         NTSTATUS status;
 636 
 637         status = rpc_transport_np_init_recv(
 638                 subreq, state->transport_smbd,
 639                 &state->transport_smbd->sub_transp);
 640         TALLOC_FREE(subreq);
 641         if (!NT_STATUS_IS_OK(status)) {
 642                 async_req_nterror(req, status);
 643                 return;
 644         }
 645         async_req_done(req);
 646 }
 647 
 648 NTSTATUS rpc_transport_smbd_init_recv(struct async_req *req,
     /* [<][>][^][v][top][bottom][index][help] */
 649                                       TALLOC_CTX *mem_ctx,
 650                                       struct rpc_cli_transport **presult)
 651 {
 652         struct rpc_transport_smbd_init_state *state = talloc_get_type_abort(
 653                 req->private_data, struct rpc_transport_smbd_init_state);
 654         NTSTATUS status;
 655 
 656         if (async_req_is_nterror(req, &status)) {
 657                 return status;
 658         }
 659 
 660         state->transport->write_send = rpc_smbd_write_send;
 661         state->transport->write_recv = rpc_smbd_write_recv;
 662         state->transport->read_send = rpc_smbd_read_send;
 663         state->transport->read_recv = rpc_smbd_read_recv;
 664         state->transport->trans_send = NULL;
 665         state->transport->trans_recv = NULL;
 666 
 667         *presult = talloc_move(mem_ctx, &state->transport);
 668         return NT_STATUS_OK;
 669 }
 670 
 671 NTSTATUS rpc_transport_smbd_init(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 672                                  struct rpc_cli_smbd_conn *conn,
 673                                  const struct ndr_syntax_id *abstract_syntax,
 674                                  struct rpc_cli_transport **presult)
 675 {
 676         TALLOC_CTX *frame = talloc_stackframe();
 677         struct event_context *ev;
 678         struct async_req *req;
 679         NTSTATUS status;
 680 
 681         ev = event_context_init(frame);
 682         if (ev == NULL) {
 683                 status = NT_STATUS_NO_MEMORY;
 684                 goto fail;
 685         }
 686 
 687         req = rpc_transport_smbd_init_send(frame, ev, conn, abstract_syntax);
 688         if (req == NULL) {
 689                 status = NT_STATUS_NO_MEMORY;
 690                 goto fail;
 691         }
 692 
 693         while (req->state < ASYNC_REQ_DONE) {
 694                 event_loop_once(ev);
 695         }
 696 
 697         status = rpc_transport_smbd_init_recv(req, mem_ctx, presult);
 698  fail:
 699         TALLOC_FREE(frame);
 700         return status;
 701 }
 702 
 703 struct cli_state *rpc_pipe_smbd_smb_conn(struct rpc_pipe_client *p)
     /* [<][>][^][v][top][bottom][index][help] */
 704 {
 705         struct rpc_transport_smbd_state *state = talloc_get_type(p->transport->priv,
 706                 struct rpc_transport_smbd_state);
 707         if (!state || !state->conn) {
 708                 return NULL;
 709         }
 710         return state->conn->cli;
 711 }

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