1433d6423SLionel Sambuc #include <sys/cdefs.h> 2433d6423SLionel Sambuc #include "namespace.h" 3*c38dbb97SDavid van Moolenbroek #include <lib.h> 4433d6423SLionel Sambuc 5433d6423SLionel Sambuc #include <errno.h> 6433d6423SLionel Sambuc #include <stdio.h> 7433d6423SLionel Sambuc #include <string.h> 8433d6423SLionel Sambuc #include <sys/ioctl.h> 9433d6423SLionel Sambuc #include <sys/socket.h> 10433d6423SLionel Sambuc #include <netinet/in.h> 11433d6423SLionel Sambuc 12433d6423SLionel Sambuc #include <net/gen/in.h> 13433d6423SLionel Sambuc #include <net/gen/tcp.h> 14433d6423SLionel Sambuc #include <net/gen/tcp_io.h> 15433d6423SLionel Sambuc #include <net/gen/udp.h> 16433d6423SLionel Sambuc #include <net/gen/udp_io.h> 17433d6423SLionel Sambuc #include <sys/un.h> 18433d6423SLionel Sambuc 19433d6423SLionel Sambuc static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 20433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp); 21433d6423SLionel Sambuc 22433d6423SLionel Sambuc static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 23433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_udpopt_t *tcpconfp); 24433d6423SLionel Sambuc 25433d6423SLionel Sambuc static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 26433d6423SLionel Sambuc socklen_t *__restrict address_len, struct sockaddr_un *uds_addr); 27433d6423SLionel Sambuc 28*c38dbb97SDavid van Moolenbroek /* 29*c38dbb97SDavid van Moolenbroek * Get the remote address of a socket. 30*c38dbb97SDavid van Moolenbroek */ 31*c38dbb97SDavid van Moolenbroek static int 32*c38dbb97SDavid van Moolenbroek __getpeername(int fd, struct sockaddr * __restrict address, 33*c38dbb97SDavid van Moolenbroek socklen_t * __restrict address_len) 34*c38dbb97SDavid van Moolenbroek { 35*c38dbb97SDavid van Moolenbroek message m; 36*c38dbb97SDavid van Moolenbroek 37*c38dbb97SDavid van Moolenbroek if (address_len == NULL) { 38*c38dbb97SDavid van Moolenbroek errno = EFAULT; 39*c38dbb97SDavid van Moolenbroek return -1; 40*c38dbb97SDavid van Moolenbroek } 41*c38dbb97SDavid van Moolenbroek 42*c38dbb97SDavid van Moolenbroek memset(&m, 0, sizeof(m)); 43*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.fd = fd; 44*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr = (vir_bytes)address; 45*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr_len = *address_len; 46*c38dbb97SDavid van Moolenbroek 47*c38dbb97SDavid van Moolenbroek if (_syscall(VFS_PROC_NR, VFS_GETPEERNAME, &m) < 0) 48*c38dbb97SDavid van Moolenbroek return -1; 49*c38dbb97SDavid van Moolenbroek 50*c38dbb97SDavid van Moolenbroek *address_len = m.m_vfs_lc_socklen.len; 51*c38dbb97SDavid van Moolenbroek return 0; 52*c38dbb97SDavid van Moolenbroek } 53*c38dbb97SDavid van Moolenbroek 54433d6423SLionel Sambuc int getpeername(int sock, struct sockaddr *__restrict address, 55433d6423SLionel Sambuc socklen_t *__restrict address_len) 56433d6423SLionel Sambuc { 57433d6423SLionel Sambuc int r; 58433d6423SLionel Sambuc nwio_tcpconf_t tcpconf; 59433d6423SLionel Sambuc nwio_udpopt_t udpopt; 60433d6423SLionel Sambuc struct sockaddr_un uds_addr; 61433d6423SLionel Sambuc 62*c38dbb97SDavid van Moolenbroek r = __getpeername(sock, address, address_len); 63*c38dbb97SDavid van Moolenbroek if (r != -1 || errno != ENOTSOCK) 64*c38dbb97SDavid van Moolenbroek return r; 65*c38dbb97SDavid van Moolenbroek 66433d6423SLionel Sambuc r= ioctl(sock, NWIOGTCPCONF, &tcpconf); 67433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 68433d6423SLionel Sambuc { 69433d6423SLionel Sambuc if (r == -1) 70433d6423SLionel Sambuc { 71433d6423SLionel Sambuc /* Bad file descriptor */ 72433d6423SLionel Sambuc return -1; 73433d6423SLionel Sambuc } 74433d6423SLionel Sambuc return _tcp_getpeername(sock, address, address_len, 75433d6423SLionel Sambuc &tcpconf); 76433d6423SLionel Sambuc } 77433d6423SLionel Sambuc 78433d6423SLionel Sambuc r= ioctl(sock, NWIOGUDPOPT, &udpopt); 79433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 80433d6423SLionel Sambuc { 81433d6423SLionel Sambuc if (r == -1) 82433d6423SLionel Sambuc { 83433d6423SLionel Sambuc /* Bad file descriptor */ 84433d6423SLionel Sambuc return -1; 85433d6423SLionel Sambuc } 86433d6423SLionel Sambuc return _udp_getpeername(sock, address, address_len, 87433d6423SLionel Sambuc &udpopt); 88433d6423SLionel Sambuc } 89433d6423SLionel Sambuc 90433d6423SLionel Sambuc r= ioctl(sock, NWIOGUDSPADDR, &uds_addr); 91433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 92433d6423SLionel Sambuc { 93433d6423SLionel Sambuc if (r == -1) 94433d6423SLionel Sambuc { 95433d6423SLionel Sambuc /* Bad file descriptor */ 96433d6423SLionel Sambuc return -1; 97433d6423SLionel Sambuc } 98433d6423SLionel Sambuc return _uds_getpeername(sock, address, address_len, 99433d6423SLionel Sambuc &uds_addr); 100433d6423SLionel Sambuc } 101433d6423SLionel Sambuc 102*c38dbb97SDavid van Moolenbroek errno = ENOTSOCK; 103433d6423SLionel Sambuc return -1; 104433d6423SLionel Sambuc } 105433d6423SLionel Sambuc 106433d6423SLionel Sambuc static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 107433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp) 108433d6423SLionel Sambuc { 109433d6423SLionel Sambuc socklen_t len; 110433d6423SLionel Sambuc struct sockaddr_in sin; 111433d6423SLionel Sambuc 112433d6423SLionel Sambuc if (tcpconfp->nwtc_remaddr == 0 || 113433d6423SLionel Sambuc tcpconfp->nwtc_remport == 0) 114433d6423SLionel Sambuc { 115433d6423SLionel Sambuc errno= ENOTCONN; 116433d6423SLionel Sambuc return -1; 117433d6423SLionel Sambuc } 118433d6423SLionel Sambuc 119433d6423SLionel Sambuc memset(&sin, '\0', sizeof(sin)); 120433d6423SLionel Sambuc sin.sin_family= AF_INET; 121433d6423SLionel Sambuc sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr; 122433d6423SLionel Sambuc sin.sin_port= tcpconfp->nwtc_remport; 123433d6423SLionel Sambuc sin.sin_len = sizeof(sin); 124433d6423SLionel Sambuc 125433d6423SLionel Sambuc len= *address_len; 126433d6423SLionel Sambuc if (len > sizeof(sin)) 127433d6423SLionel Sambuc len= sizeof(sin); 128433d6423SLionel Sambuc memcpy(address, &sin, len); 129433d6423SLionel Sambuc *address_len= len; 130433d6423SLionel Sambuc 131433d6423SLionel Sambuc return 0; 132433d6423SLionel Sambuc } 133433d6423SLionel Sambuc 134433d6423SLionel Sambuc static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 135433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_udpopt_t *udpopt) 136433d6423SLionel Sambuc { 137433d6423SLionel Sambuc socklen_t len; 138433d6423SLionel Sambuc struct sockaddr_in sin; 139433d6423SLionel Sambuc 140433d6423SLionel Sambuc if (udpopt->nwuo_remaddr == 0 || 141433d6423SLionel Sambuc udpopt->nwuo_remport == 0) 142433d6423SLionel Sambuc { 143433d6423SLionel Sambuc errno= ENOTCONN; 144433d6423SLionel Sambuc return -1; 145433d6423SLionel Sambuc } 146433d6423SLionel Sambuc 147433d6423SLionel Sambuc memset(&sin, '\0', sizeof(sin)); 148433d6423SLionel Sambuc sin.sin_family= AF_INET; 149433d6423SLionel Sambuc sin.sin_addr.s_addr= udpopt->nwuo_remaddr; 150433d6423SLionel Sambuc sin.sin_port= udpopt->nwuo_remport; 151433d6423SLionel Sambuc sin.sin_len = sizeof(sin); 152433d6423SLionel Sambuc 153433d6423SLionel Sambuc len= *address_len; 154433d6423SLionel Sambuc if (len > sizeof(sin)) 155433d6423SLionel Sambuc len= sizeof(sin); 156433d6423SLionel Sambuc memcpy(address, &sin, len); 157433d6423SLionel Sambuc *address_len= len; 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc return 0; 160433d6423SLionel Sambuc } 161433d6423SLionel Sambuc 162433d6423SLionel Sambuc static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 163433d6423SLionel Sambuc socklen_t *__restrict address_len, struct sockaddr_un *uds_addr) 164433d6423SLionel Sambuc { 165433d6423SLionel Sambuc socklen_t len; 166433d6423SLionel Sambuc 167433d6423SLionel Sambuc if (uds_addr->sun_family != AF_UNIX) 168433d6423SLionel Sambuc { 169433d6423SLionel Sambuc errno= ENOTCONN; 170433d6423SLionel Sambuc return -1; 171433d6423SLionel Sambuc } 172433d6423SLionel Sambuc 173433d6423SLionel Sambuc len= *address_len; 174433d6423SLionel Sambuc if (len > sizeof(struct sockaddr_un)) 175433d6423SLionel Sambuc len = sizeof(struct sockaddr_un); 176433d6423SLionel Sambuc 177433d6423SLionel Sambuc memcpy(address, uds_addr, len); 178433d6423SLionel Sambuc *address_len= len; 179433d6423SLionel Sambuc 180433d6423SLionel Sambuc return 0; 181433d6423SLionel Sambuc } 182