1 #include <sys/cdefs.h> 2 #include "namespace.h" 3 #include <lib.h> 4 5 #include <errno.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <sys/ioctl.h> 9 #include <sys/socket.h> 10 #include <netinet/in.h> 11 12 #include <net/gen/in.h> 13 #include <net/gen/tcp.h> 14 #include <net/gen/tcp_io.h> 15 #include <net/gen/udp.h> 16 #include <net/gen/udp_io.h> 17 #include <sys/un.h> 18 19 #define DEBUG 0 20 21 static int _tcp_getsockname(int fd, struct sockaddr *__restrict address, 22 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp); 23 24 static int _udp_getsockname(int fd, struct sockaddr *__restrict address, 25 socklen_t *__restrict address_len, nwio_udpopt_t *udpopt); 26 27 static int _uds_getsockname(int fd, struct sockaddr *__restrict address, 28 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr); 29 30 /* 31 * Get the local address of a socket. 32 */ 33 static int 34 __getsockname(int fd, struct sockaddr * __restrict address, 35 socklen_t * __restrict address_len) 36 { 37 message m; 38 39 if (address_len == NULL) { 40 errno = EFAULT; 41 return -1; 42 } 43 44 memset(&m, 0, sizeof(m)); 45 m.m_lc_vfs_sockaddr.fd = fd; 46 m.m_lc_vfs_sockaddr.addr = (vir_bytes)address; 47 m.m_lc_vfs_sockaddr.addr_len = *address_len; 48 49 if (_syscall(VFS_PROC_NR, VFS_GETSOCKNAME, &m) < 0) 50 return -1; 51 52 *address_len = m.m_vfs_lc_socklen.len; 53 return 0; 54 } 55 56 int getsockname(int fd, struct sockaddr *__restrict address, 57 socklen_t *__restrict address_len) 58 { 59 int r; 60 nwio_tcpconf_t tcpconf; 61 nwio_udpopt_t udpopt; 62 struct sockaddr_un uds_addr; 63 64 r = __getsockname(fd, address, address_len); 65 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS)) 66 return r; 67 68 #if DEBUG 69 fprintf(stderr,"mnx_getsockname: ioctl fd %d.\n", fd); 70 #endif 71 72 r= ioctl(fd, NWIOGTCPCONF, &tcpconf); 73 if (r != -1 || errno != ENOTTY) 74 { 75 if (r == -1) 76 { 77 /* Bad file descriptor */ 78 return -1; 79 } 80 81 return _tcp_getsockname(fd, address, address_len, &tcpconf); 82 } 83 84 r= ioctl(fd, NWIOGUDPOPT, &udpopt); 85 if (r != -1 || errno != ENOTTY) 86 { 87 if (r == -1) 88 { 89 /* Bad file descriptor */ 90 return -1; 91 } 92 93 return _udp_getsockname(fd, address, address_len, &udpopt); 94 } 95 96 r= ioctl(fd, NWIOGUDSADDR, &uds_addr); 97 if (r != -1 || errno != ENOTTY) 98 { 99 if (r == -1) 100 { 101 /* Bad file descriptor */ 102 return -1; 103 } 104 105 return _uds_getsockname(fd, address, address_len, &uds_addr); 106 } 107 108 errno = ENOTSOCK; 109 return -1; 110 } 111 112 113 static int _tcp_getsockname(int fd, struct sockaddr *__restrict address, 114 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconf) 115 { 116 socklen_t len; 117 struct sockaddr_in sin; 118 119 #ifdef DEBUG1 120 fprintf(stderr, "mnx_getsockname: from %s, %u", 121 inet_ntoa(tcpconf->nwtc_remaddr), 122 ntohs(tcpconf->nwtc_remport)); 123 fprintf(stderr," for %s, %u\n", 124 inet_ntoa(tcpconf->nwtc_locaddr), 125 ntohs(tcpconf->nwtc_locport)); 126 #endif 127 128 memset(&sin, '\0', sizeof(sin)); 129 sin.sin_family= AF_INET; 130 sin.sin_addr.s_addr= tcpconf->nwtc_locaddr ; 131 sin.sin_port= tcpconf->nwtc_locport; 132 sin.sin_len= sizeof(sin); 133 134 len= *address_len; 135 if (len > sizeof(sin)) 136 len= sizeof(sin); 137 memcpy(address, &sin, len); 138 *address_len= len; 139 140 return 0; 141 } 142 143 static int _udp_getsockname(int fd, struct sockaddr *__restrict address, 144 socklen_t *__restrict address_len, nwio_udpopt_t *udpopt) 145 { 146 socklen_t len; 147 struct sockaddr_in sin; 148 149 #ifdef DEBUG1 150 fprintf(stderr, "mnx_getsockname: from %s, %u", 151 inet_ntoa(udpopt->nwuo_remaddr), 152 ntohs(udpopt->nwuo_remport)); 153 fprintf(stderr," for %s, %u\n", 154 inet_ntoa(udpopt->nwuo_locaddr), 155 ntohs(udpopt->nwuo_locport)); 156 #endif 157 158 memset(&sin, '\0', sizeof(sin)); 159 sin.sin_family= AF_INET; 160 sin.sin_addr.s_addr= udpopt->nwuo_locaddr ; 161 sin.sin_port= udpopt->nwuo_locport; 162 sin.sin_len= sizeof(sin); 163 164 len= *address_len; 165 if (len > sizeof(sin)) 166 len= sizeof(sin); 167 memcpy(address, &sin, len); 168 *address_len= len; 169 170 return 0; 171 } 172 173 static int _uds_getsockname(int fd, struct sockaddr *__restrict address, 174 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr) 175 { 176 socklen_t len; 177 178 if (uds_addr->sun_family != AF_UNIX) 179 { 180 errno= EINVAL; 181 return -1; 182 } 183 184 len= *address_len; 185 if (len > sizeof(struct sockaddr_un)) 186 len = sizeof(struct sockaddr_un); 187 188 memcpy(address, uds_addr, len); 189 *address_len= len; 190 191 return 0; 192 } 193