X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=src%2Fsocket.c;h=f1fcccd502b4f0689e77e2d450d80979b6f55060;hb=6420774b3b2e1658fa7f3d788e81d2305d6f10c3;hp=bd4914fd3645af1057fbf9dd37e963e75a7f2904;hpb=33cb71ac91fb870702dbb71595dba4a554001e3c;p=osmocom-bb.git diff --git a/src/socket.c b/src/socket.c index bd4914f..f1fcccd 100644 --- a/src/socket.c +++ b/src/socket.c @@ -1,13 +1,14 @@ #include "../config.h" +#ifdef HAVE_SYS_SOCKET_H + #include #include #include -#include +#include #include #include -#include #include #include @@ -18,12 +19,16 @@ #include int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, - const char *host, uint16_t port, int connect0_bind1) + const char *host, uint16_t port, unsigned int flags) { struct addrinfo hints, *result, *rp; - int sfd, rc; + int sfd, rc, on = 1; char portbuf[16]; + if ((flags & (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) == + (OSMO_SOCK_F_BIND | OSMO_SOCK_F_CONNECT)) + return -EINVAL; + sprintf(portbuf, "%u", port); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = family; @@ -31,6 +36,9 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, hints.ai_flags = 0; hints.ai_protocol = proto; + if (flags & OSMO_SOCK_F_BIND) + hints.ai_flags |= AI_PASSIVE; + rc = getaddrinfo(host, portbuf, &hints, &result); if (rc != 0) { perror("getaddrinfo returned NULL"); @@ -41,10 +49,24 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd == -1) continue; - if (connect0_bind1 == 0) { - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + if (flags & OSMO_SOCK_F_NONBLOCK) { + if (ioctl(sfd, FIONBIO, (unsigned char *)&on) < 0) { + perror("cannot set this socket unblocking"); + close(sfd); + return -EINVAL; + } + } + if (flags & OSMO_SOCK_F_CONNECT) { + rc = connect(sfd, rp->ai_addr, rp->ai_addrlen); + if (rc != -1 || (rc == -1 && errno == EINPROGRESS)) break; } else { + rc = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)); + if (rc < 0) { + perror("cannot setsockopt socket"); + break; + } if (bind(sfd, rp->ai_addr, rp->ai_addrlen) != -1) break; } @@ -56,11 +78,44 @@ int osmo_sock_init(uint16_t family, uint16_t type, uint8_t proto, perror("unable to connect/bind socket"); return -ENODEV; } + + setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + + /* Make sure to call 'listen' on a bound, connection-oriented sock */ + if (flags & OSMO_SOCK_F_BIND) { + switch (type) { + case SOCK_STREAM: + case SOCK_SEQPACKET: + listen(sfd, 10); + break; + } + } + return sfd; +} + +int osmo_sock_init_ofd(struct osmo_fd *ofd, int family, int type, int proto, + const char *host, uint16_t port, unsigned int flags) +{ + int sfd, rc; + + sfd = osmo_sock_init(family, type, proto, host, port, flags); + if (sfd < 0) + return sfd; + + ofd->fd = sfd; + ofd->when = BSC_FD_READ; + + rc = osmo_fd_register(ofd); + if (rc < 0) { + close(sfd); + return rc; + } + return sfd; } int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type, - uint8_t proto, int connect0_bind1) + uint8_t proto, unsigned int flags) { char host[NI_MAXHOST]; uint16_t port; @@ -83,7 +138,6 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type, default: return -EINVAL; } - fprintf(stderr, "==> PORT = %u\n", port); s = getnameinfo(ss, sa_len, host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); @@ -92,12 +146,11 @@ int osmo_sock_init_sa(struct sockaddr *ss, uint16_t type, return s; } - return osmo_sock_init(ss->sa_family, type, proto, host, - port, connect0_bind1); + return osmo_sock_init(ss->sa_family, type, proto, host, port, flags); } static int sockaddr_equal(const struct sockaddr *a, - const struct sockaddr *b, socklen_t len) + const struct sockaddr *b, unsigned int len) { struct sockaddr_in *sin_a, *sin_b; struct sockaddr_in6 *sin6_a, *sin6_b; @@ -135,9 +188,13 @@ int osmo_sockaddr_is_local(struct sockaddr *addr, socklen_t addrlen) } for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) + continue; if (sockaddr_equal(ifa->ifa_addr, addr, addrlen)) return 1; } return 0; } + +#endif /* HAVE_SYS_SOCKET_H */