84
69
if (!NT_STATUS_IS_OK(status)) {
85
70
/* w2k just ignores invalid packets, so we do */
86
71
DEBUG(10,("Received WINS-Replication packet was invalid, we just ignore it\n"));
88
74
return NT_STATUS_OK;
91
77
/* and now encode the reply */
92
78
packet_out_wrap.packet = call->rep_packet;
93
ndr_err = ndr_push_struct_blob(&packet_out_blob, call,
94
lp_iconv_convenience(wreplconn->service->task->lp_ctx),
79
ndr_err = ndr_push_struct_blob(&call->out, call,
96
(ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
81
(ndr_push_flags_fn_t) ndr_push_wrepl_wrap);
97
82
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
98
83
return ndr_map_error2ntstatus(ndr_err);
101
86
if (DEBUGLVL(10)) {
102
DEBUG(10,("Sending WINS-Replication packet of length %d\n", (int)packet_out_blob.length));
87
DEBUG(10,("Sending WINS-Replication packet of length %u\n",
88
(unsigned int) call->out.length));
103
89
NDR_PRINT_DEBUG(wrepl_packet, &call->rep_packet);
95
static void wreplsrv_call_loop(struct tevent_req *subreq);
98
called when we get a new connection
100
static void wreplsrv_accept(struct stream_connection *conn)
102
struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service);
103
struct wreplsrv_in_connection *wrepl_conn;
104
struct tsocket_address *peer_addr;
106
struct tevent_req *subreq;
109
wrepl_conn = talloc_zero(conn, struct wreplsrv_in_connection);
110
if (wrepl_conn == NULL) {
111
stream_terminate_connection(conn,
112
"wreplsrv_accept: out of memory");
116
wrepl_conn->send_queue = tevent_queue_create(conn, "wrepl_accept");
117
if (wrepl_conn->send_queue == NULL) {
118
stream_terminate_connection(conn,
119
"wrepl_accept: out of memory");
123
TALLOC_FREE(conn->event.fde);
125
rc = tstream_bsd_existing_socket(wrepl_conn,
126
socket_get_fd(conn->socket),
127
&wrepl_conn->tstream);
129
stream_terminate_connection(conn,
130
"wrepl_accept: out of memory");
133
socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE);
135
wrepl_conn->conn = conn;
136
wrepl_conn->service = service;
138
peer_addr = conn->remote_address;
140
if (!tsocket_address_is_inet(peer_addr, "ipv4")) {
141
DEBUG(0,("wreplsrv_accept: non ipv4 peer addr '%s'\n",
142
tsocket_address_string(peer_addr, wrepl_conn)));
143
wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
148
peer_ip = tsocket_address_inet_addr_string(peer_addr, wrepl_conn);
149
if (peer_ip == NULL) {
150
wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: "
151
"could not convert peer IP into a string");
155
wrepl_conn->partner = wreplsrv_find_partner(service, peer_ip);
156
irpc_add_name(conn->msg_ctx, "wreplsrv_connection");
159
* The wrepl pdu's has the length as 4 byte (initial_read_size),
160
* packet_full_request_u32 provides the pdu length then.
162
subreq = tstream_read_pdu_blob_send(wrepl_conn,
163
wrepl_conn->conn->event.ctx,
165
4, /* initial_read_size */
166
packet_full_request_u32,
168
if (subreq == NULL) {
169
wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_accept: "
170
"no memory for tstream_read_pdu_blob_send");
173
tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn);
176
static void wreplsrv_call_writev_done(struct tevent_req *subreq);
178
static void wreplsrv_call_loop(struct tevent_req *subreq)
180
struct wreplsrv_in_connection *wrepl_conn = tevent_req_callback_data(subreq,
181
struct wreplsrv_in_connection);
182
struct wreplsrv_in_call *call;
185
call = talloc_zero(wrepl_conn, struct wreplsrv_in_call);
187
wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
188
"no memory for wrepl_samba3_call");
191
call->wreplconn = wrepl_conn;
193
status = tstream_read_pdu_blob_recv(subreq,
197
if (!NT_STATUS_IS_OK(status)) {
200
reason = talloc_asprintf(call, "wreplsrv_call_loop: "
201
"tstream_read_pdu_blob_recv() - %s",
204
reason = nt_errstr(status);
207
wreplsrv_terminate_in_connection(wrepl_conn, reason);
211
DEBUG(10,("Received wrepl packet of length %lu from %s\n",
212
(long) call->in.length,
213
tsocket_address_string(wrepl_conn->conn->remote_address, call)));
215
/* skip length header */
217
call->in.length -= 4;
219
status = wreplsrv_process(wrepl_conn, &call);
220
if (!NT_STATUS_IS_OK(status)) {
223
reason = talloc_asprintf(call, "wreplsrv_call_loop: "
224
"tstream_read_pdu_blob_recv() - %s",
226
if (reason == NULL) {
227
reason = nt_errstr(status);
230
wreplsrv_terminate_in_connection(wrepl_conn, reason);
234
/* We handed over the connection so we're done here */
235
if (wrepl_conn->tstream == NULL) {
239
/* Invalid WINS-Replication packet, we just ignore it */
244
call->out_iov[0].iov_base = (char *) call->out.data;
245
call->out_iov[0].iov_len = call->out.length;
247
subreq = tstream_writev_queue_send(call,
248
wrepl_conn->conn->event.ctx,
250
wrepl_conn->send_queue,
252
if (subreq == NULL) {
253
wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
254
"no memory for tstream_writev_queue_send");
257
tevent_req_set_callback(subreq, wreplsrv_call_writev_done, call);
261
* The wrepl pdu's has the length as 4 byte (initial_read_size),
262
* provides the pdu length then.
264
subreq = tstream_read_pdu_blob_send(wrepl_conn,
265
wrepl_conn->conn->event.ctx,
267
4, /* initial_read_size */
268
packet_full_request_u32,
270
if (subreq == NULL) {
271
wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: "
272
"no memory for tstream_read_pdu_blob_send");
275
tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn);
278
static void wreplsrv_call_writev_done(struct tevent_req *subreq)
280
struct wreplsrv_in_call *call = tevent_req_callback_data(subreq,
281
struct wreplsrv_in_call);
285
rc = tstream_writev_queue_recv(subreq, &sys_errno);
290
reason = talloc_asprintf(call, "wreplsrv_call_writev_done: "
291
"tstream_writev_queue_recv() - %d:%s",
292
sys_errno, strerror(sys_errno));
293
if (reason == NULL) {
294
reason = "wreplsrv_call_writev_done: "
295
"tstream_writev_queue_recv() failed";
298
wreplsrv_terminate_in_connection(call->wreplconn, reason);
106
302
if (call->terminate_after_send) {
107
struct wreplsrv_in_connection **tas;
108
tas = talloc(packet_out_blob.data, struct wreplsrv_in_connection *);
109
NT_STATUS_HAVE_NO_MEMORY(tas);
111
talloc_set_destructor(tas, terminate_after_send_destructor);
303
wreplsrv_terminate_in_connection(call->wreplconn,
304
"wreplsrv_in_connection: terminate_after_send");
114
status = packet_send(wreplconn->packet, packet_out_blob);
115
NT_STATUS_NOT_OK_RETURN(status);
117
308
talloc_free(call);
122
called when the socket becomes readable
124
314
static void wreplsrv_recv(struct stream_connection *conn, uint16_t flags)
126
struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private_data,
127
struct wreplsrv_in_connection);
129
packet_recv(wreplconn->packet);
316
struct wreplsrv_in_connection *wrepl_conn = talloc_get_type(conn->private_data,
317
struct wreplsrv_in_connection);
318
/* this should never be triggered! */
319
DEBUG(0,("Terminating connection - '%s'\n", "wrepl_recv: called"));
320
wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_recv: called");
133
called when the socket becomes writable
324
called when we can write to a connection
135
326
static void wreplsrv_send(struct stream_connection *conn, uint16_t flags)
137
struct wreplsrv_in_connection *wreplconn = talloc_get_type(conn->private_data,
138
struct wreplsrv_in_connection);
139
packet_queue_run(wreplconn->packet);
143
handle socket recv errors
145
static void wreplsrv_recv_error(void *private_data, NTSTATUS status)
147
struct wreplsrv_in_connection *wreplconn = talloc_get_type(private_data,
148
struct wreplsrv_in_connection);
149
wreplsrv_terminate_in_connection(wreplconn, nt_errstr(status));
153
called when we get a new connection
155
static void wreplsrv_accept(struct stream_connection *conn)
157
struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service);
158
struct wreplsrv_in_connection *wreplconn;
159
struct socket_address *peer_ip;
161
wreplconn = talloc_zero(conn, struct wreplsrv_in_connection);
163
stream_terminate_connection(conn, "wreplsrv_accept: out of memory");
167
wreplconn->packet = packet_init(wreplconn);
168
if (!wreplconn->packet) {
169
wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory");
172
packet_set_private(wreplconn->packet, wreplconn);
173
packet_set_socket(wreplconn->packet, conn->socket);
174
packet_set_callback(wreplconn->packet, wreplsrv_recv_request);
175
packet_set_full_request(wreplconn->packet, packet_full_request_u32);
176
packet_set_error_handler(wreplconn->packet, wreplsrv_recv_error);
177
packet_set_event_context(wreplconn->packet, conn->event.ctx);
178
packet_set_fde(wreplconn->packet, conn->event.fde);
179
packet_set_serialise(wreplconn->packet);
181
wreplconn->conn = conn;
182
wreplconn->service = service;
184
peer_ip = socket_get_peer_addr(conn->socket, wreplconn);
186
wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: could not obtain peer IP from kernel");
190
wreplconn->partner = wreplsrv_find_partner(service, peer_ip->addr);
192
conn->private_data = wreplconn;
194
irpc_add_name(conn->msg_ctx, "wreplsrv_connection");
328
struct wreplsrv_in_connection *wrepl_conn = talloc_get_type(conn->private_data,
329
struct wreplsrv_in_connection);
330
/* this should never be triggered! */
331
DEBUG(0,("Terminating connection - '%s'\n", "wrepl_send: called"));
332
wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_send: called");
197
335
static const struct stream_server_ops wreplsrv_stream_ops = {