Coverage Report

Created: 2026-04-01 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source4/lib/socket/connect.c
Line
Count
Source
1
/* 
2
   Unix SMB/CIFS implementation.
3
4
   implements a non-blocking connect operation that is aware of the samba4
5
   events system
6
7
   Copyright (C) Andrew Tridgell 2005
8
   Copyright (C) Volker Lendecke 2005
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/socket/socket.h"
26
#include "lib/events/events.h"
27
#include "libcli/composite/composite.h"
28
29
30
struct connect_state {
31
  struct socket_context *sock;
32
  const struct socket_address *my_address;
33
  const struct socket_address *server_address;
34
  uint32_t flags;
35
};
36
37
static void socket_connect_handler(struct tevent_context *ev,
38
           struct tevent_fd *fde, 
39
           uint16_t flags, void *private_data);
40
41
/*
42
  call the real socket_connect() call, and setup event handler
43
*/
44
static void socket_send_connect(struct composite_context *result)
45
0
{
46
0
  struct tevent_fd *fde;
47
0
  struct connect_state *state = talloc_get_type(result->private_data, 
48
0
                  struct connect_state);
49
50
0
  result->status = socket_connect(state->sock,
51
0
          state->my_address,
52
0
          state->server_address,
53
0
          state->flags);
54
0
  if (NT_STATUS_IS_ERR(result->status) && 
55
0
      !NT_STATUS_EQUAL(result->status,
56
0
           NT_STATUS_MORE_PROCESSING_REQUIRED)) {
57
0
    composite_error(result, result->status);
58
0
    return;
59
0
  }
60
61
0
  fde = tevent_add_fd(result->event_ctx, result,
62
0
         socket_get_fd(state->sock),
63
0
         TEVENT_FD_READ|TEVENT_FD_WRITE,
64
0
         socket_connect_handler, result);
65
0
  composite_nomem(fde, result);
66
0
}
67
68
69
/*
70
  send a socket connect, potentially doing some name resolution first
71
*/
72
struct composite_context *socket_connect_send(struct socket_context *sock,
73
                struct socket_address *my_address,
74
                struct socket_address *server_address, 
75
                uint32_t flags,
76
                struct tevent_context *event_ctx)
77
0
{
78
0
  struct composite_context *result;
79
0
  struct connect_state *state;
80
81
0
  result = composite_create(sock, event_ctx);
82
0
  if (result == NULL) return NULL;
83
84
0
  state = talloc_zero(result, struct connect_state);
85
0
  if (composite_nomem(state, result)) return result;
86
0
  result->private_data = state;
87
88
0
  state->sock = talloc_reference(state, sock);
89
0
  if (composite_nomem(state->sock, result)) return result;
90
91
0
  if (my_address) {
92
0
    void *ref = talloc_reference(state, my_address);
93
0
    if (composite_nomem(ref, result)) {
94
0
      return result;
95
0
    }
96
0
    state->my_address = my_address;
97
0
  }
98
99
0
  {
100
0
    void *ref = talloc_reference(state, server_address);
101
0
    if (composite_nomem(ref, result)) {
102
0
      return result;
103
0
    }
104
0
    state->server_address = server_address;
105
0
  }
106
107
0
  state->flags = flags;
108
109
0
  set_blocking(socket_get_fd(sock), false);
110
111
0
  socket_send_connect(result);
112
113
0
  return result;
114
0
}
115
116
/*
117
  handle write events on connect completion
118
*/
119
static void socket_connect_handler(struct tevent_context *ev,
120
           struct tevent_fd *fde, 
121
           uint16_t flags, void *private_data)
122
0
{
123
0
  struct composite_context *result =
124
0
    talloc_get_type(private_data, struct composite_context);
125
0
  struct connect_state *state = talloc_get_type(result->private_data,
126
0
                  struct connect_state);
127
128
0
  result->status = socket_connect_complete(state->sock, state->flags);
129
0
  if (!composite_is_ok(result)) return;
130
131
0
  composite_done(result);
132
0
}
133
134
/*
135
  wait for a socket_connect_send() to finish
136
*/
137
NTSTATUS socket_connect_recv(struct composite_context *result)
138
0
{
139
0
  NTSTATUS status = composite_wait(result);
140
0
  talloc_free(result);
141
0
  return status;
142
0
}
143
144
145
/*
146
  like socket_connect() but takes an event context, doing a semi-async connect
147
*/
148
NTSTATUS socket_connect_ev(struct socket_context *sock,
149
         struct socket_address *my_address,
150
         struct socket_address *server_address, 
151
         uint32_t flags,
152
         struct tevent_context *ev)
153
0
{
154
0
  struct composite_context *ctx;
155
0
  ctx = socket_connect_send(sock, my_address, 
156
0
          server_address, flags, ev);
157
0
  return socket_connect_recv(ctx);
158
0
}