1433d6423SLionel Sambuc #include <sys/cdefs.h>
2433d6423SLionel Sambuc #include "namespace.h"
3c38dbb97SDavid 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
28c38dbb97SDavid van Moolenbroek /*
29c38dbb97SDavid van Moolenbroek * Get the remote address of a socket.
30c38dbb97SDavid van Moolenbroek */
31c38dbb97SDavid van Moolenbroek static int
__getpeername(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len)32c38dbb97SDavid van Moolenbroek __getpeername(int fd, struct sockaddr * __restrict address,
33c38dbb97SDavid van Moolenbroek socklen_t * __restrict address_len)
34c38dbb97SDavid van Moolenbroek {
35c38dbb97SDavid van Moolenbroek message m;
36c38dbb97SDavid van Moolenbroek
37c38dbb97SDavid van Moolenbroek if (address_len == NULL) {
38c38dbb97SDavid van Moolenbroek errno = EFAULT;
39c38dbb97SDavid van Moolenbroek return -1;
40c38dbb97SDavid van Moolenbroek }
41c38dbb97SDavid van Moolenbroek
42c38dbb97SDavid van Moolenbroek memset(&m, 0, sizeof(m));
43c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.fd = fd;
44c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
45c38dbb97SDavid van Moolenbroek m.m_lc_vfs_sockaddr.addr_len = *address_len;
46c38dbb97SDavid van Moolenbroek
47c38dbb97SDavid van Moolenbroek if (_syscall(VFS_PROC_NR, VFS_GETPEERNAME, &m) < 0)
48c38dbb97SDavid van Moolenbroek return -1;
49c38dbb97SDavid van Moolenbroek
50c38dbb97SDavid van Moolenbroek *address_len = m.m_vfs_lc_socklen.len;
51c38dbb97SDavid van Moolenbroek return 0;
52c38dbb97SDavid van Moolenbroek }
53c38dbb97SDavid van Moolenbroek
getpeername(int sock,struct sockaddr * __restrict address,socklen_t * __restrict address_len)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
62c38dbb97SDavid van Moolenbroek r = __getpeername(sock, address, address_len);
63*84ed480eSDavid van Moolenbroek if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
64c38dbb97SDavid van Moolenbroek return r;
65c38dbb97SDavid 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
102c38dbb97SDavid van Moolenbroek errno = ENOTSOCK;
103433d6423SLionel Sambuc return -1;
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc
_tcp_getpeername(int sock,struct sockaddr * __restrict address,socklen_t * __restrict address_len,nwio_tcpconf_t * tcpconfp)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
_udp_getpeername(int sock,struct sockaddr * __restrict address,socklen_t * __restrict address_len,nwio_udpopt_t * udpopt)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
_uds_getpeername(int sock,struct sockaddr * __restrict address,socklen_t * __restrict address_len,struct sockaddr_un * uds_addr)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