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 static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 20 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp); 21 22 static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 23 socklen_t *__restrict address_len, nwio_udpopt_t *tcpconfp); 24 25 static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 26 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr); 27 28 /* 29 * Get the remote address of a socket. 30 */ 31 static int 32 __getpeername(int fd, struct sockaddr * __restrict address, 33 socklen_t * __restrict address_len) 34 { 35 message m; 36 37 if (address_len == NULL) { 38 errno = EFAULT; 39 return -1; 40 } 41 42 memset(&m, 0, sizeof(m)); 43 m.m_lc_vfs_sockaddr.fd = fd; 44 m.m_lc_vfs_sockaddr.addr = (vir_bytes)address; 45 m.m_lc_vfs_sockaddr.addr_len = *address_len; 46 47 if (_syscall(VFS_PROC_NR, VFS_GETPEERNAME, &m) < 0) 48 return -1; 49 50 *address_len = m.m_vfs_lc_socklen.len; 51 return 0; 52 } 53 54 int getpeername(int sock, struct sockaddr *__restrict address, 55 socklen_t *__restrict address_len) 56 { 57 int r; 58 nwio_tcpconf_t tcpconf; 59 nwio_udpopt_t udpopt; 60 struct sockaddr_un uds_addr; 61 62 r = __getpeername(sock, address, address_len); 63 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS)) 64 return r; 65 66 r= ioctl(sock, NWIOGTCPCONF, &tcpconf); 67 if (r != -1 || errno != ENOTTY) 68 { 69 if (r == -1) 70 { 71 /* Bad file descriptor */ 72 return -1; 73 } 74 return _tcp_getpeername(sock, address, address_len, 75 &tcpconf); 76 } 77 78 r= ioctl(sock, NWIOGUDPOPT, &udpopt); 79 if (r != -1 || errno != ENOTTY) 80 { 81 if (r == -1) 82 { 83 /* Bad file descriptor */ 84 return -1; 85 } 86 return _udp_getpeername(sock, address, address_len, 87 &udpopt); 88 } 89 90 r= ioctl(sock, NWIOGUDSPADDR, &uds_addr); 91 if (r != -1 || errno != ENOTTY) 92 { 93 if (r == -1) 94 { 95 /* Bad file descriptor */ 96 return -1; 97 } 98 return _uds_getpeername(sock, address, address_len, 99 &uds_addr); 100 } 101 102 errno = ENOTSOCK; 103 return -1; 104 } 105 106 static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 107 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp) 108 { 109 socklen_t len; 110 struct sockaddr_in sin; 111 112 if (tcpconfp->nwtc_remaddr == 0 || 113 tcpconfp->nwtc_remport == 0) 114 { 115 errno= ENOTCONN; 116 return -1; 117 } 118 119 memset(&sin, '\0', sizeof(sin)); 120 sin.sin_family= AF_INET; 121 sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr; 122 sin.sin_port= tcpconfp->nwtc_remport; 123 sin.sin_len = sizeof(sin); 124 125 len= *address_len; 126 if (len > sizeof(sin)) 127 len= sizeof(sin); 128 memcpy(address, &sin, len); 129 *address_len= len; 130 131 return 0; 132 } 133 134 static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 135 socklen_t *__restrict address_len, nwio_udpopt_t *udpopt) 136 { 137 socklen_t len; 138 struct sockaddr_in sin; 139 140 if (udpopt->nwuo_remaddr == 0 || 141 udpopt->nwuo_remport == 0) 142 { 143 errno= ENOTCONN; 144 return -1; 145 } 146 147 memset(&sin, '\0', sizeof(sin)); 148 sin.sin_family= AF_INET; 149 sin.sin_addr.s_addr= udpopt->nwuo_remaddr; 150 sin.sin_port= udpopt->nwuo_remport; 151 sin.sin_len = sizeof(sin); 152 153 len= *address_len; 154 if (len > sizeof(sin)) 155 len= sizeof(sin); 156 memcpy(address, &sin, len); 157 *address_len= len; 158 159 return 0; 160 } 161 162 static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 163 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr) 164 { 165 socklen_t len; 166 167 if (uds_addr->sun_family != AF_UNIX) 168 { 169 errno= ENOTCONN; 170 return -1; 171 } 172 173 len= *address_len; 174 if (len > sizeof(struct sockaddr_un)) 175 len = sizeof(struct sockaddr_un); 176 177 memcpy(address, uds_addr, len); 178 *address_len= len; 179 180 return 0; 181 } 182