1433d6423SLionel Sambuc #include <sys/cdefs.h> 2433d6423SLionel Sambuc #include "namespace.h" 3*c38dbb97SDavid van Moolenbroek #include <lib.h> 4*c38dbb97SDavid van Moolenbroek 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 #define DEBUG 0 20433d6423SLionel Sambuc 21433d6423SLionel Sambuc static int _tcp_getsockname(int fd, struct sockaddr *__restrict address, 22433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp); 23433d6423SLionel Sambuc 24433d6423SLionel Sambuc static int _udp_getsockname(int fd, struct sockaddr *__restrict address, 25433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_udpopt_t *udpopt); 26433d6423SLionel Sambuc 27433d6423SLionel Sambuc static int _uds_getsockname(int fd, struct sockaddr *__restrict address, 28433d6423SLionel Sambuc socklen_t *__restrict address_len, struct sockaddr_un *uds_addr); 29433d6423SLionel Sambuc 30*c38dbb97SDavid van Moolenbroek /* 31*c38dbb97SDavid van Moolenbroek * Get the local address of a socket. 32*c38dbb97SDavid van Moolenbroek */ 33*c38dbb97SDavid van Moolenbroek static int 34*c38dbb97SDavid van Moolenbroek __getsockname(int fd, struct sockaddr * __restrict address, 35*c38dbb97SDavid van Moolenbroek socklen_t * __restrict address_len) 36*c38dbb97SDavid van Moolenbroek { 37*c38dbb97SDavid van Moolenbroek message m; 38*c38dbb97SDavid van Moolenbroek 39*c38dbb97SDavid van Moolenbroek if (address_len == NULL) { 40*c38dbb97SDavid van Moolenbroek errno = EFAULT; 41*c38dbb97SDavid van Moolenbroek return -1; 42*c38dbb97SDavid van Moolenbroek } 43*c38dbb97SDavid van Moolenbroek 44*c38dbb97SDavid van Moolenbroek memset(&m, 0, sizeof(m)); 45*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.fd = fd; 46*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr = (vir_bytes)address; 47*c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr_len = *address_len; 48*c38dbb97SDavid van Moolenbroek 49*c38dbb97SDavid van Moolenbroek if (_syscall(VFS_PROC_NR, VFS_GETSOCKNAME, &m) < 0) 50*c38dbb97SDavid van Moolenbroek return -1; 51*c38dbb97SDavid van Moolenbroek 52*c38dbb97SDavid van Moolenbroek *address_len = m.m_vfs_lc_socklen.len; 53*c38dbb97SDavid van Moolenbroek return 0; 54*c38dbb97SDavid van Moolenbroek } 55*c38dbb97SDavid van Moolenbroek 56433d6423SLionel Sambuc int getsockname(int fd, struct sockaddr *__restrict address, 57433d6423SLionel Sambuc socklen_t *__restrict address_len) 58433d6423SLionel Sambuc { 59433d6423SLionel Sambuc int r; 60433d6423SLionel Sambuc nwio_tcpconf_t tcpconf; 61433d6423SLionel Sambuc nwio_udpopt_t udpopt; 62433d6423SLionel Sambuc struct sockaddr_un uds_addr; 63433d6423SLionel Sambuc 64*c38dbb97SDavid van Moolenbroek r = __getsockname(fd, address, address_len); 65*c38dbb97SDavid van Moolenbroek if (r != -1 || errno != ENOTSOCK) 66*c38dbb97SDavid van Moolenbroek return r; 67*c38dbb97SDavid van Moolenbroek 68*c38dbb97SDavid van Moolenbroek #if DEBUG 69433d6423SLionel Sambuc fprintf(stderr,"mnx_getsockname: ioctl fd %d.\n", fd); 70433d6423SLionel Sambuc #endif 71433d6423SLionel Sambuc 72433d6423SLionel Sambuc r= ioctl(fd, NWIOGTCPCONF, &tcpconf); 73433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 74433d6423SLionel Sambuc { 75433d6423SLionel Sambuc if (r == -1) 76433d6423SLionel Sambuc { 77433d6423SLionel Sambuc /* Bad file descriptor */ 78433d6423SLionel Sambuc return -1; 79433d6423SLionel Sambuc } 80433d6423SLionel Sambuc 81433d6423SLionel Sambuc return _tcp_getsockname(fd, address, address_len, &tcpconf); 82433d6423SLionel Sambuc } 83433d6423SLionel Sambuc 84433d6423SLionel Sambuc r= ioctl(fd, NWIOGUDPOPT, &udpopt); 85433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 86433d6423SLionel Sambuc { 87433d6423SLionel Sambuc if (r == -1) 88433d6423SLionel Sambuc { 89433d6423SLionel Sambuc /* Bad file descriptor */ 90433d6423SLionel Sambuc return -1; 91433d6423SLionel Sambuc } 92433d6423SLionel Sambuc 93433d6423SLionel Sambuc return _udp_getsockname(fd, address, address_len, &udpopt); 94433d6423SLionel Sambuc } 95433d6423SLionel Sambuc 96433d6423SLionel Sambuc r= ioctl(fd, NWIOGUDSADDR, &uds_addr); 97433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 98433d6423SLionel Sambuc { 99433d6423SLionel Sambuc if (r == -1) 100433d6423SLionel Sambuc { 101433d6423SLionel Sambuc /* Bad file descriptor */ 102433d6423SLionel Sambuc return -1; 103433d6423SLionel Sambuc } 104433d6423SLionel Sambuc 105433d6423SLionel Sambuc return _uds_getsockname(fd, address, address_len, &uds_addr); 106433d6423SLionel Sambuc } 107433d6423SLionel Sambuc 108*c38dbb97SDavid van Moolenbroek errno = ENOTSOCK; 109433d6423SLionel Sambuc return -1; 110433d6423SLionel Sambuc } 111433d6423SLionel Sambuc 112433d6423SLionel Sambuc 113433d6423SLionel Sambuc static int _tcp_getsockname(int fd, struct sockaddr *__restrict address, 114433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconf) 115433d6423SLionel Sambuc { 116433d6423SLionel Sambuc socklen_t len; 117433d6423SLionel Sambuc struct sockaddr_in sin; 118433d6423SLionel Sambuc 119433d6423SLionel Sambuc #ifdef DEBUG1 120433d6423SLionel Sambuc fprintf(stderr, "mnx_getsockname: from %s, %u", 121433d6423SLionel Sambuc inet_ntoa(tcpconf->nwtc_remaddr), 122433d6423SLionel Sambuc ntohs(tcpconf->nwtc_remport)); 123433d6423SLionel Sambuc fprintf(stderr," for %s, %u\n", 124433d6423SLionel Sambuc inet_ntoa(tcpconf->nwtc_locaddr), 125433d6423SLionel Sambuc ntohs(tcpconf->nwtc_locport)); 126433d6423SLionel Sambuc #endif 127433d6423SLionel Sambuc 128433d6423SLionel Sambuc memset(&sin, '\0', sizeof(sin)); 129433d6423SLionel Sambuc sin.sin_family= AF_INET; 130433d6423SLionel Sambuc sin.sin_addr.s_addr= tcpconf->nwtc_locaddr ; 131433d6423SLionel Sambuc sin.sin_port= tcpconf->nwtc_locport; 132433d6423SLionel Sambuc sin.sin_len= sizeof(sin); 133433d6423SLionel Sambuc 134433d6423SLionel Sambuc len= *address_len; 135433d6423SLionel Sambuc if (len > sizeof(sin)) 136433d6423SLionel Sambuc len= sizeof(sin); 137433d6423SLionel Sambuc memcpy(address, &sin, len); 138433d6423SLionel Sambuc *address_len= len; 139433d6423SLionel Sambuc 140433d6423SLionel Sambuc return 0; 141433d6423SLionel Sambuc } 142433d6423SLionel Sambuc 143433d6423SLionel Sambuc static int _udp_getsockname(int fd, struct sockaddr *__restrict address, 144433d6423SLionel Sambuc socklen_t *__restrict address_len, nwio_udpopt_t *udpopt) 145433d6423SLionel Sambuc { 146433d6423SLionel Sambuc socklen_t len; 147433d6423SLionel Sambuc struct sockaddr_in sin; 148433d6423SLionel Sambuc 149433d6423SLionel Sambuc #ifdef DEBUG1 150433d6423SLionel Sambuc fprintf(stderr, "mnx_getsockname: from %s, %u", 151433d6423SLionel Sambuc inet_ntoa(udpopt->nwuo_remaddr), 152433d6423SLionel Sambuc ntohs(udpopt->nwuo_remport)); 153433d6423SLionel Sambuc fprintf(stderr," for %s, %u\n", 154433d6423SLionel Sambuc inet_ntoa(udpopt->nwuo_locaddr), 155433d6423SLionel Sambuc ntohs(udpopt->nwuo_locport)); 156433d6423SLionel Sambuc #endif 157433d6423SLionel Sambuc 158433d6423SLionel Sambuc memset(&sin, '\0', sizeof(sin)); 159433d6423SLionel Sambuc sin.sin_family= AF_INET; 160433d6423SLionel Sambuc sin.sin_addr.s_addr= udpopt->nwuo_locaddr ; 161433d6423SLionel Sambuc sin.sin_port= udpopt->nwuo_locport; 162433d6423SLionel Sambuc sin.sin_len= sizeof(sin); 163433d6423SLionel Sambuc 164433d6423SLionel Sambuc len= *address_len; 165433d6423SLionel Sambuc if (len > sizeof(sin)) 166433d6423SLionel Sambuc len= sizeof(sin); 167433d6423SLionel Sambuc memcpy(address, &sin, len); 168433d6423SLionel Sambuc *address_len= len; 169433d6423SLionel Sambuc 170433d6423SLionel Sambuc return 0; 171433d6423SLionel Sambuc } 172433d6423SLionel Sambuc 173433d6423SLionel Sambuc static int _uds_getsockname(int fd, struct sockaddr *__restrict address, 174433d6423SLionel Sambuc socklen_t *__restrict address_len, struct sockaddr_un *uds_addr) 175433d6423SLionel Sambuc { 176433d6423SLionel Sambuc socklen_t len; 177433d6423SLionel Sambuc 178433d6423SLionel Sambuc if (uds_addr->sun_family != AF_UNIX) 179433d6423SLionel Sambuc { 180433d6423SLionel Sambuc errno= EINVAL; 181433d6423SLionel Sambuc return -1; 182433d6423SLionel Sambuc } 183433d6423SLionel Sambuc 184433d6423SLionel Sambuc len= *address_len; 185433d6423SLionel Sambuc if (len > sizeof(struct sockaddr_un)) 186433d6423SLionel Sambuc len = sizeof(struct sockaddr_un); 187433d6423SLionel Sambuc 188433d6423SLionel Sambuc memcpy(address, uds_addr, len); 189433d6423SLionel Sambuc *address_len= len; 190433d6423SLionel Sambuc 191433d6423SLionel Sambuc return 0; 192433d6423SLionel Sambuc } 193