From fbea52f74a80268446f45936a0cf40400aba8565 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 2 May 2011 15:23:08 +1000 Subject: lib/util Move more network utility functions from source3 into lib/util This will help with the merge of the interfaces layer. Andrew Bartlett --- lib/util/system.c | 72 ++++++++++++++++++++++ lib/util/util.h | 14 ++++- lib/util/util_net.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++ lib/util/util_net.h | 35 +++++++++++ source3/include/proto.h | 10 ---- source3/lib/system.c | 71 ---------------------- source3/lib/util_sock.c | 156 ------------------------------------------------ 7 files changed, 275 insertions(+), 238 deletions(-) diff --git a/lib/util/system.c b/lib/util/system.c index 9bf5de1a83..17c0553102 100644 --- a/lib/util/system.c +++ b/lib/util/system.c @@ -117,3 +117,75 @@ _PUBLIC_ pid_t sys_getpid(void) return mypid; } + + +_PUBLIC_ int sys_getpeereid( int s, uid_t *uid) +{ +#if defined(HAVE_PEERCRED) + struct ucred cred; + socklen_t cred_len = sizeof(struct ucred); + int ret; + + ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); + if (ret != 0) { + return -1; + } + + if (cred_len != sizeof(struct ucred)) { + errno = EINVAL; + return -1; + } + + *uid = cred.uid; + return 0; +#else +#if defined(HAVE_GETPEEREID) + gid_t gid; + return getpeereid(s, uid, &gid); +#endif + errno = ENOSYS; + return -1; +#endif +} + +_PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, + int salen, + char *host, + size_t hostlen, + char *service, + size_t servlen, + int flags) +{ + /* + * For Solaris we must make sure salen is the + * correct length for the incoming sa_family. + */ + + if (salen == sizeof(struct sockaddr_storage)) { + salen = sizeof(struct sockaddr_in); +#if defined(HAVE_IPV6) + if (psa->sa_family == AF_INET6) { + salen = sizeof(struct sockaddr_in6); + } +#endif + } + return getnameinfo(psa, salen, host, hostlen, service, servlen, flags); +} + +_PUBLIC_ int sys_connect(int fd, const struct sockaddr * addr) +{ + socklen_t salen = (socklen_t)-1; + + if (addr->sa_family == AF_INET) { + salen = sizeof(struct sockaddr_in); + } else if (addr->sa_family == AF_UNIX) { + salen = sizeof(struct sockaddr_un); + } +#if defined(HAVE_IPV6) + else if (addr->sa_family == AF_INET6) { + salen = sizeof(struct sockaddr_in6); + } +#endif + + return connect(fd, addr, salen); +} diff --git a/lib/util/util.h b/lib/util/util.h index 8dffece0da..5ed8427498 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -131,8 +131,20 @@ _PUBLIC_ pid_t sys_fork(void); **/ _PUBLIC_ pid_t sys_getpid(void); -/* The following definitions come from lib/util/genrand.c */ +_PUBLIC_ int sys_getpeereid( int s, uid_t *uid); + +struct sockaddr; +_PUBLIC_ int sys_getnameinfo(const struct sockaddr *psa, + int salen, + char *host, + size_t hostlen, + char *service, + size_t servlen, + int flags); +_PUBLIC_ int sys_connect(int fd, const struct sockaddr * addr); + +/* The following definitions come from lib/util/genrand.c */ /** Copy any user given reseed data. **/ diff --git a/lib/util/util_net.c b/lib/util/util_net.c index 9c8f5c6d47..e80447128f 100644 --- a/lib/util/util_net.c +++ b/lib/util/util_net.c @@ -540,3 +540,158 @@ void set_sockaddr_port(struct sockaddr *psa, uint16_t port) } +/**************************************************************************** + Get a port number in host byte order from a sockaddr_storage. +****************************************************************************/ + +uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) +{ + uint16_t port = 0; + + if (pss->ss_family != AF_INET) { +#if defined(HAVE_IPV6) + /* IPv6 */ + const struct sockaddr_in6 *sa6 = + (const struct sockaddr_in6 *)pss; + port = ntohs(sa6->sin6_port); +#endif + } else { + const struct sockaddr_in *sa = + (const struct sockaddr_in *)pss; + port = ntohs(sa->sin_port); + } + return port; +} + +/**************************************************************************** + Print out an IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_sockaddr_len(char *dest, + size_t destlen, + const struct sockaddr *psa, + socklen_t psalen) +{ + if (destlen > 0) { + dest[0] = '\0'; + } + (void)sys_getnameinfo(psa, + psalen, + dest, destlen, + NULL, 0, + NI_NUMERICHOST); + return dest; +} + +/**************************************************************************** + Print out an IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_sockaddr(char *dest, + size_t destlen, + const struct sockaddr_storage *psa) +{ + return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa, + sizeof(struct sockaddr_storage)); +} + +/**************************************************************************** + Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage. +****************************************************************************/ + +char *print_canonical_sockaddr(TALLOC_CTX *ctx, + const struct sockaddr_storage *pss) +{ + char addr[INET6_ADDRSTRLEN]; + char *dest = NULL; + int ret; + + /* Linux getnameinfo() man pages says port is unitialized if + service name is NULL. */ + + ret = sys_getnameinfo((const struct sockaddr *)pss, + sizeof(struct sockaddr_storage), + addr, sizeof(addr), + NULL, 0, + NI_NUMERICHOST); + if (ret != 0) { + return NULL; + } + + if (pss->ss_family != AF_INET) { +#if defined(HAVE_IPV6) + dest = talloc_asprintf(ctx, "[%s]", addr); +#else + return NULL; +#endif + } else { + dest = talloc_asprintf(ctx, "%s", addr); + } + + return dest; +} + +/**************************************************************************** + Return the port number we've bound to on a socket. +****************************************************************************/ + +int get_socket_port(int fd) +{ + struct sockaddr_storage sa; + socklen_t length = sizeof(sa); + + if (fd == -1) { + return -1; + } + + if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { + int level = (errno == ENOTCONN) ? 2 : 0; + DEBUG(level, ("getsockname failed. Error was %s\n", + strerror(errno))); + return -1; + } + +#if defined(HAVE_IPV6) + if (sa.ss_family == AF_INET6) { + return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port); + } +#endif + if (sa.ss_family == AF_INET) { + return ntohs(((struct sockaddr_in *)&sa)->sin_port); + } + return -1; +} + +/**************************************************************************** + Return the string of an IP address (IPv4 or IPv6). +****************************************************************************/ + +static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len) +{ + struct sockaddr_storage sa; + socklen_t length = sizeof(sa); + + /* Ok, returning a hard coded IPv4 address + * is bogus, but it's just as bogus as a + * zero IPv6 address. No good choice here. + */ + + strlcpy(addr_buf, "0.0.0.0", addr_len); + + if (fd == -1) { + return addr_buf; + } + + if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { + DEBUG(0,("getsockname failed. Error was %s\n", + strerror(errno) )); + return addr_buf; + } + + return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length); +} + +const char *client_socket_addr(int fd, char *addr, size_t addr_len) +{ + return get_socket_addr(fd, addr, addr_len); +} diff --git a/lib/util/util_net.h b/lib/util/util_net.h index 530311e5c8..71d1d1a6bd 100644 --- a/lib/util/util_net.h +++ b/lib/util/util_net.h @@ -50,6 +50,15 @@ void set_sockaddr_port(struct sockaddr *psa, uint16_t port); **/ _PUBLIC_ bool is_zero_ip_v4(struct in_addr ip); +void in_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in_addr ip); +#if defined(HAVE_IPV6) +/** + * Convert an IPv6 struct in_addr to a struct sockaddr_storage. + */ +void in6_addr_to_sockaddr_storage(struct sockaddr_storage *ss, + struct in6_addr ip); +#endif /** Are two IPs on the same subnet? **/ @@ -60,6 +69,11 @@ _PUBLIC_ bool same_net_v4(struct in_addr ip1,struct in_addr ip2,struct in_addr m **/ _PUBLIC_ bool is_ipaddress(const char *str); +bool is_broadcast_addr(const struct sockaddr *pss); +bool is_loopback_ip_v4(struct in_addr ip); +bool is_loopback_addr(const struct sockaddr *pss); +bool is_zero_addr(const struct sockaddr_storage *pss); +void zero_ip_v4(struct in_addr *ip); /** Interpret an internet address or name into an IP address in 4 byte form. **/ @@ -72,5 +86,26 @@ _PUBLIC_ struct in_addr interpret_addr2(const char *str); _PUBLIC_ bool is_ipaddress_v4(const char *str); +bool is_address_any(const struct sockaddr *psa); +bool same_net(const struct sockaddr *ip1, + const struct sockaddr *ip2, + const struct sockaddr *mask); +bool sockaddr_equal(const struct sockaddr *ip1, + const struct sockaddr *ip2); + +bool is_address_any(const struct sockaddr *psa); +uint16_t get_sockaddr_port(const struct sockaddr_storage *pss); +char *print_sockaddr_len(char *dest, + size_t destlen, + const struct sockaddr *psa, + socklen_t psalen); +char *print_sockaddr(char *dest, + size_t destlen, + const struct sockaddr_storage *psa); +char *print_canonical_sockaddr(TALLOC_CTX *ctx, + const struct sockaddr_storage *pss); +const char *client_name(int fd); +int get_socket_port(int fd); +const char *client_socket_addr(int fd, char *addr, size_t addr_len); #endif /* _SAMBA_UTIL_NET_H_ */ diff --git a/source3/include/proto.h b/source3/include/proto.h index ebfa5e633a..3c2e30d6be 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -532,16 +532,6 @@ int sys_aio_cancel(int fd, SMB_STRUCT_AIOCB *aiocb); int sys_aio_error(const SMB_STRUCT_AIOCB *aiocb); int sys_aio_fsync(int op, SMB_STRUCT_AIOCB *aiocb); int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct timespec *timeout); -int sys_getpeereid( int s, uid_t *uid); -int sys_getnameinfo(const struct sockaddr *psa, - socklen_t salen, - char *host, - size_t hostlen, - char *service, - size_t servlen, - int flags); -int sys_connect(int fd, const struct sockaddr * addr); - /* The following definitions come from lib/system_smbd.c */ bool getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user, diff --git a/source3/lib/system.c b/source3/lib/system.c index 52b6477266..b6cc7a8b07 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -2633,74 +2633,3 @@ int sys_aio_suspend(const SMB_STRUCT_AIOCB * const cblist[], int n, const struct return -1; } #endif /* WITH_AIO */ - -int sys_getpeereid( int s, uid_t *uid) -{ -#if defined(HAVE_PEERCRED) - struct ucred cred; - socklen_t cred_len = sizeof(struct ucred); - int ret; - - ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); - if (ret != 0) { - return -1; - } - - if (cred_len != sizeof(struct ucred)) { - errno = EINVAL; - return -1; - } - - *uid = cred.uid; - return 0; -#else -#if defined(HAVE_GETPEEREID) - gid_t gid; - return getpeereid(s, uid, &gid); -#endif - errno = ENOSYS; - return -1; -#endif -} - -int sys_getnameinfo(const struct sockaddr *psa, - socklen_t salen, - char *host, - size_t hostlen, - char *service, - size_t servlen, - int flags) -{ - /* - * For Solaris we must make sure salen is the - * correct length for the incoming sa_family. - */ - - if (salen == sizeof(struct sockaddr_storage)) { - salen = sizeof(struct sockaddr_in); -#if defined(HAVE_IPV6) - if (psa->sa_family == AF_INET6) { - salen = sizeof(struct sockaddr_in6); - } -#endif - } - return getnameinfo(psa, salen, host, hostlen, service, servlen, flags); -} - -int sys_connect(int fd, const struct sockaddr * addr) -{ - socklen_t salen = (socklen_t)-1; - - if (addr->sa_family == AF_INET) { - salen = sizeof(struct sockaddr_in); - } else if (addr->sa_family == AF_UNIX) { - salen = sizeof(struct sockaddr_un); - } -#if defined(HAVE_IPV6) - else if (addr->sa_family == AF_INET6) { - salen = sizeof(struct sockaddr_in6); - } -#endif - - return connect(fd, addr, salen); -} diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index daf91fef03..fa718590d7 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -28,157 +28,6 @@ #include "../lib/util/tevent_unix.h" #include "../lib/util/tevent_ntstatus.h" -/**************************************************************************** - Get a port number in host byte order from a sockaddr_storage. -****************************************************************************/ - -uint16_t get_sockaddr_port(const struct sockaddr_storage *pss) -{ - uint16_t port = 0; - - if (pss->ss_family != AF_INET) { -#if defined(HAVE_IPV6) - /* IPv6 */ - const struct sockaddr_in6 *sa6 = - (const struct sockaddr_in6 *)pss; - port = ntohs(sa6->sin6_port); -#endif - } else { - const struct sockaddr_in *sa = - (const struct sockaddr_in *)pss; - port = ntohs(sa->sin_port); - } - return port; -} - -/**************************************************************************** - Print out an IPv4 or IPv6 address from a struct sockaddr_storage. -****************************************************************************/ - -static char *print_sockaddr_len(char *dest, - size_t destlen, - const struct sockaddr *psa, - socklen_t psalen) -{ - if (destlen > 0) { - dest[0] = '\0'; - } - (void)sys_getnameinfo(psa, - psalen, - dest, destlen, - NULL, 0, - NI_NUMERICHOST); - return dest; -} - -/**************************************************************************** - Print out an IPv4 or IPv6 address from a struct sockaddr_storage. -****************************************************************************/ - -char *print_sockaddr(char *dest, - size_t destlen, - const struct sockaddr_storage *psa) -{ - return print_sockaddr_len(dest, destlen, (struct sockaddr *)psa, - sizeof(struct sockaddr_storage)); -} - -/**************************************************************************** - Print out a canonical IPv4 or IPv6 address from a struct sockaddr_storage. -****************************************************************************/ - -char *print_canonical_sockaddr(TALLOC_CTX *ctx, - const struct sockaddr_storage *pss) -{ - char addr[INET6_ADDRSTRLEN]; - char *dest = NULL; - int ret; - - /* Linux getnameinfo() man pages says port is unitialized if - service name is NULL. */ - - ret = sys_getnameinfo((const struct sockaddr *)pss, - sizeof(struct sockaddr_storage), - addr, sizeof(addr), - NULL, 0, - NI_NUMERICHOST); - if (ret != 0) { - return NULL; - } - - if (pss->ss_family != AF_INET) { -#if defined(HAVE_IPV6) - dest = talloc_asprintf(ctx, "[%s]", addr); -#else - return NULL; -#endif - } else { - dest = talloc_asprintf(ctx, "%s", addr); - } - - return dest; -} - -/**************************************************************************** - Return the string of an IP address (IPv4 or IPv6). -****************************************************************************/ - -static const char *get_socket_addr(int fd, char *addr_buf, size_t addr_len) -{ - struct sockaddr_storage sa; - socklen_t length = sizeof(sa); - - /* Ok, returning a hard coded IPv4 address - * is bogus, but it's just as bogus as a - * zero IPv6 address. No good choice here. - */ - - strlcpy(addr_buf, "0.0.0.0", addr_len); - - if (fd == -1) { - return addr_buf; - } - - if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { - DEBUG(0,("getsockname failed. Error was %s\n", - strerror(errno) )); - return addr_buf; - } - - return print_sockaddr_len(addr_buf, addr_len, (struct sockaddr *)&sa, length); -} - -/**************************************************************************** - Return the port number we've bound to on a socket. -****************************************************************************/ - -int get_socket_port(int fd) -{ - struct sockaddr_storage sa; - socklen_t length = sizeof(sa); - - if (fd == -1) { - return -1; - } - - if (getsockname(fd, (struct sockaddr *)&sa, &length) < 0) { - int level = (errno == ENOTCONN) ? 2 : 0; - DEBUG(level, ("getsockname failed. Error was %s\n", - strerror(errno))); - return -1; - } - -#if defined(HAVE_IPV6) - if (sa.ss_family == AF_INET6) { - return ntohs(((struct sockaddr_in6 *)&sa)->sin6_port); - } -#endif - if (sa.ss_family == AF_INET) { - return ntohs(((struct sockaddr_in *)&sa)->sin_port); - } - return -1; -} - const char *client_name(int fd) { return get_peer_name(fd,false); @@ -189,11 +38,6 @@ const char *client_addr(int fd, char *addr, size_t addrlen) return get_peer_addr(fd,addr,addrlen); } -const char *client_socket_addr(int fd, char *addr, size_t addr_len) -{ - return get_socket_addr(fd, addr, addr_len); -} - #if 0 /* Not currently used. JRA. */ int client_socket_port(int fd) -- cgit