summaryrefslogtreecommitdiff
path: root/lib/tsocket
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2010-10-21 23:26:14 +0200
committerStefan Metzmacher <metze@samba.org>2010-10-23 08:49:29 +0200
commitd2c653629cdc3df8549c6faabfcdbe3045cd013c (patch)
treecf3a3f418356220ab0c52e077f2cf7044f0c03bd /lib/tsocket
parent96601cab1cb0bd47051cd9fb30f0464c0734cb8a (diff)
downloadsamba-d2c653629cdc3df8549c6faabfcdbe3045cd013c.tar.gz
tsocket: ask the kernel for the specific local address after a tcp connect
metze
Diffstat (limited to 'lib/tsocket')
-rw-r--r--lib/tsocket/tsocket_bsd.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index bc7cfe3fe9e..f544e8672e2 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -1973,6 +1973,7 @@ struct tstream_bsd_connect_state {
int fd;
struct tevent_fd *fde;
struct tstream_conext *stream;
+ struct tsocket_address *local;
};
static int tstream_bsd_connect_destructor(struct tstream_bsd_connect_state *state)
@@ -1991,7 +1992,7 @@ static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
uint16_t flags,
void *private_data);
-static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
+static struct tevent_req *tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
int sys_errno,
const struct tsocket_address *local,
@@ -2002,6 +2003,7 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
struct tsocket_address_bsd *lbsda =
talloc_get_type_abort(local->private_data,
struct tsocket_address_bsd);
+ struct tsocket_address_bsd *lrbsda = NULL;
struct tsocket_address_bsd *rbsda =
talloc_get_type_abort(remote->private_data,
struct tsocket_address_bsd);
@@ -2081,6 +2083,20 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
}
}
+ if (is_inet) {
+ state->local = tsocket_address_create(state,
+ &tsocket_address_bsd_ops,
+ &lrbsda,
+ struct tsocket_address_bsd,
+ __location__ "bsd_connect");
+ if (tevent_req_nomem(state->local, req)) {
+ goto post;
+ }
+
+ ZERO_STRUCTP(lrbsda);
+ lrbsda->sa_socklen = sizeof(lrbsda->u.ss);
+ }
+
state->fd = socket(sa_fam, SOCK_STREAM, 0);
if (state->fd == -1) {
tevent_req_error(req, errno);
@@ -2140,6 +2156,17 @@ static struct tevent_req * tstream_bsd_connect_send(TALLOC_CTX *mem_ctx,
goto post;
}
+ if (!state->local) {
+ tevent_req_done(req);
+ goto post;
+ }
+
+ ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen);
+ if (ret == -1) {
+ tevent_req_error(req, errno);
+ goto post;
+ }
+
tevent_req_done(req);
goto post;
@@ -2169,6 +2196,7 @@ static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
struct tevent_req);
struct tstream_bsd_connect_state *state = tevent_req_data(req,
struct tstream_bsd_connect_state);
+ struct tsocket_address_bsd *lrbsda = NULL;
int ret;
int error=0;
socklen_t len = sizeof(error);
@@ -2191,6 +2219,20 @@ static void tstream_bsd_connect_fde_handler(struct tevent_context *ev,
return;
}
+ if (!state->local) {
+ tevent_req_done(req);
+ return;
+ }
+
+ lrbsda = talloc_get_type_abort(state->local->private_data,
+ struct tsocket_address_bsd);
+
+ ret = getsockname(state->fd, &lrbsda->u.sa, &lrbsda->sa_socklen);
+ if (ret == -1) {
+ tevent_req_error(req, errno);
+ return;
+ }
+
tevent_req_done(req);
}
@@ -2198,6 +2240,7 @@ static int tstream_bsd_connect_recv(struct tevent_req *req,
int *perrno,
TALLOC_CTX *mem_ctx,
struct tstream_context **stream,
+ struct tsocket_address **local,
const char *location)
{
struct tstream_bsd_connect_state *state = tevent_req_data(req,
@@ -2216,6 +2259,10 @@ static int tstream_bsd_connect_recv(struct tevent_req *req,
}
TALLOC_FREE(state->fde);
state->fd = -1;
+
+ if (local) {
+ *local = talloc_move(mem_ctx, &state->local);
+ }
}
done:
@@ -2257,7 +2304,9 @@ int _tstream_inet_tcp_connect_recv(struct tevent_req *req,
struct tstream_context **stream,
const char *location)
{
- return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
+ return tstream_bsd_connect_recv(req, perrno,
+ mem_ctx, stream, NULL,
+ location);
}
struct tevent_req * tstream_unix_connect_send(TALLOC_CTX *mem_ctx,
@@ -2290,7 +2339,9 @@ int _tstream_unix_connect_recv(struct tevent_req *req,
struct tstream_context **stream,
const char *location)
{
- return tstream_bsd_connect_recv(req, perrno, mem_ctx, stream, location);
+ return tstream_bsd_connect_recv(req, perrno,
+ mem_ctx, stream, NULL,
+ location);
}
int _tstream_unix_socketpair(TALLOC_CTX *mem_ctx1,