From: Pablo Neira Ayuso <pablo(a)gnumonks.org>
This patch adds make_sock_stream_connect() which allows to perform
a non-blocking connect to some host and port.
This only support TCP by now, but it could be easily extensible
to support other stream-based layer 4 protocols.
---
openbsc/include/openbsc/socket.h | 2 +
openbsc/src/libcommon/socket.c | 54 ++++++++++++++++++++++++++++++++++++++
2 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/openbsc/include/openbsc/socket.h b/openbsc/include/openbsc/socket.h
index 87ef37f..af5f729 100644
--- a/openbsc/include/openbsc/socket.h
+++ b/openbsc/include/openbsc/socket.h
@@ -11,4 +11,6 @@ int make_sock(struct bsc_fd *bfd, int proto,
uint32_t ip, uint16_t port, int priv_nr,
int (*cb)(struct bsc_fd *fd, unsigned int what), void *data);
+int make_sock_stream_connect(struct bsc_fd *bfd, int proto, struct in_addr addr, uint16_t
port, int priv_nr, int (*cb)(struct bsc_fd *fd, unsigned int what), void *data);
+
#endif /* _BSC_SOCKET_H */
diff --git a/openbsc/src/libcommon/socket.c b/openbsc/src/libcommon/socket.c
index dd25dd7..f4a533d 100644
--- a/openbsc/src/libcommon/socket.c
+++ b/openbsc/src/libcommon/socket.c
@@ -107,3 +107,57 @@ int make_sock(struct bsc_fd *bfd, int proto,
}
return 0;
}
+
+/* this function performs a non-blocking stream connect. */
+int make_sock_stream_connect(struct bsc_fd *bfd, int proto,
+ struct in_addr addr, uint16_t port, int priv_nr,
+ int (*cb)(struct bsc_fd *fd, unsigned int what),
+ void *data)
+{
+ int ret, flags, type;
+ struct sockaddr_in saddr;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ type = SOCK_STREAM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ bfd->fd = socket(AF_INET, type, proto);
+ bfd->cb = cb;
+ /* non-blocking connect() confirms by setting BSC_FD_READ. */
+ bfd->when = BSC_FD_READ | BSC_FD_WRITE;
+ bfd->data = data;
+ bfd->priv_nr = priv_nr;
+
+ if (bfd->fd < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not create socket.\n");
+ return -EIO;
+ }
+ flags = fcntl(bfd->fd, F_GETFL, 0);
+ if (fcntl(bfd->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
+ LOGP(DINP, LOGL_ERROR, "could not fcntl.\n");
+ return -EIO;
+ }
+ memset(&saddr, 0, sizeof(addr));
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = port;
+ memcpy(&saddr.sin_addr, &addr, sizeof(struct in_addr));
+
+ ret = connect(bfd->fd, (struct sockaddr *) &saddr, sizeof(saddr));
+ if (ret < 0 && errno != EINPROGRESS) {
+ LOGP(DINP, LOGL_ERROR, "could not connect socket %s\n",
+ strerror(errno));
+ close(bfd->fd);
+ return -EIO;
+ }
+ ret = bsc_register_fd(bfd);
+ if (ret < 0) {
+ perror("register_listen_fd");
+ close(bfd->fd);
+ return ret;
+ }
+ return 0;
+}
--
1.7.2.3