1 #include <sys/cdefs.h> 2 #include "namespace.h" 3 4 #include <errno.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <sys/ioctl.h> 8 #include <sys/socket.h> 9 #include <netinet/in.h> 10 11 #include <net/gen/in.h> 12 #include <net/gen/tcp.h> 13 #include <net/gen/tcp_io.h> 14 #include <net/gen/udp.h> 15 #include <net/gen/udp_io.h> 16 #include <sys/un.h> 17 18 #define DEBUG 0 19 20 static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 21 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp); 22 23 static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 24 socklen_t *__restrict address_len, nwio_udpopt_t *tcpconfp); 25 26 static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 27 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr); 28 29 int getpeername(int sock, struct sockaddr *__restrict address, 30 socklen_t *__restrict address_len) 31 { 32 int r; 33 nwio_tcpconf_t tcpconf; 34 nwio_udpopt_t udpopt; 35 struct sockaddr_un uds_addr; 36 37 r= ioctl(sock, NWIOGTCPCONF, &tcpconf); 38 if (r != -1 || errno != ENOTTY) 39 { 40 if (r == -1) 41 { 42 /* Bad file descriptor */ 43 return -1; 44 } 45 return _tcp_getpeername(sock, address, address_len, 46 &tcpconf); 47 } 48 49 r= ioctl(sock, NWIOGUDPOPT, &udpopt); 50 if (r != -1 || errno != ENOTTY) 51 { 52 if (r == -1) 53 { 54 /* Bad file descriptor */ 55 return -1; 56 } 57 return _udp_getpeername(sock, address, address_len, 58 &udpopt); 59 } 60 61 r= ioctl(sock, NWIOGUDSPADDR, &uds_addr); 62 if (r != -1 || errno != ENOTTY) 63 { 64 if (r == -1) 65 { 66 /* Bad file descriptor */ 67 return -1; 68 } 69 return _uds_getpeername(sock, address, address_len, 70 &uds_addr); 71 } 72 73 74 #if DEBUG 75 fprintf(stderr, "getpeername: not implemented for fd %d\n", sock); 76 #endif 77 errno= ENOSYS; 78 return -1; 79 } 80 81 static int _tcp_getpeername(int sock, struct sockaddr *__restrict address, 82 socklen_t *__restrict address_len, nwio_tcpconf_t *tcpconfp) 83 { 84 socklen_t len; 85 struct sockaddr_in sin; 86 87 if (tcpconfp->nwtc_remaddr == 0 || 88 tcpconfp->nwtc_remport == 0) 89 { 90 errno= ENOTCONN; 91 return -1; 92 } 93 94 memset(&sin, '\0', sizeof(sin)); 95 sin.sin_family= AF_INET; 96 sin.sin_addr.s_addr= tcpconfp->nwtc_remaddr; 97 sin.sin_port= tcpconfp->nwtc_remport; 98 sin.sin_len = sizeof(sin); 99 100 len= *address_len; 101 if (len > sizeof(sin)) 102 len= sizeof(sin); 103 memcpy(address, &sin, len); 104 *address_len= len; 105 106 return 0; 107 } 108 109 static int _udp_getpeername(int sock, struct sockaddr *__restrict address, 110 socklen_t *__restrict address_len, nwio_udpopt_t *udpopt) 111 { 112 socklen_t len; 113 struct sockaddr_in sin; 114 115 if (udpopt->nwuo_remaddr == 0 || 116 udpopt->nwuo_remport == 0) 117 { 118 errno= ENOTCONN; 119 return -1; 120 } 121 122 memset(&sin, '\0', sizeof(sin)); 123 sin.sin_family= AF_INET; 124 sin.sin_addr.s_addr= udpopt->nwuo_remaddr; 125 sin.sin_port= udpopt->nwuo_remport; 126 sin.sin_len = sizeof(sin); 127 128 len= *address_len; 129 if (len > sizeof(sin)) 130 len= sizeof(sin); 131 memcpy(address, &sin, len); 132 *address_len= len; 133 134 return 0; 135 } 136 137 static int _uds_getpeername(int sock, struct sockaddr *__restrict address, 138 socklen_t *__restrict address_len, struct sockaddr_un *uds_addr) 139 { 140 socklen_t len; 141 142 if (uds_addr->sun_family != AF_UNIX) 143 { 144 errno= ENOTCONN; 145 return -1; 146 } 147 148 len= *address_len; 149 if (len > sizeof(struct sockaddr_un)) 150 len = sizeof(struct sockaddr_un); 151 152 memcpy(address, uds_addr, len); 153 *address_len= len; 154 155 return 0; 156 } 157