xref: /minix3/minix/lib/libc/sys/getsockname.c (revision 84ed480ef770e26a28565a26c8ef94ba01312a41)
1433d6423SLionel Sambuc #include <sys/cdefs.h>
2433d6423SLionel Sambuc #include "namespace.h"
3c38dbb97SDavid van Moolenbroek #include <lib.h>
4c38dbb97SDavid 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 
30c38dbb97SDavid van Moolenbroek /*
31c38dbb97SDavid van Moolenbroek  * Get the local address of a socket.
32c38dbb97SDavid van Moolenbroek  */
33c38dbb97SDavid van Moolenbroek static int
__getsockname(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len)34c38dbb97SDavid van Moolenbroek __getsockname(int fd, struct sockaddr * __restrict address,
35c38dbb97SDavid van Moolenbroek 	socklen_t * __restrict address_len)
36c38dbb97SDavid van Moolenbroek {
37c38dbb97SDavid van Moolenbroek 	message m;
38c38dbb97SDavid van Moolenbroek 
39c38dbb97SDavid van Moolenbroek 	if (address_len == NULL) {
40c38dbb97SDavid van Moolenbroek 		errno = EFAULT;
41c38dbb97SDavid van Moolenbroek 		return -1;
42c38dbb97SDavid van Moolenbroek 	}
43c38dbb97SDavid van Moolenbroek 
44c38dbb97SDavid van Moolenbroek 	memset(&m, 0, sizeof(m));
45c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_sockaddr.fd = fd;
46c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
47c38dbb97SDavid van Moolenbroek 	m.m_lc_vfs_sockaddr.addr_len = *address_len;
48c38dbb97SDavid van Moolenbroek 
49c38dbb97SDavid van Moolenbroek 	if (_syscall(VFS_PROC_NR, VFS_GETSOCKNAME, &m) < 0)
50c38dbb97SDavid van Moolenbroek 		return -1;
51c38dbb97SDavid van Moolenbroek 
52c38dbb97SDavid van Moolenbroek 	*address_len = m.m_vfs_lc_socklen.len;
53c38dbb97SDavid van Moolenbroek 	return 0;
54c38dbb97SDavid van Moolenbroek }
55c38dbb97SDavid van Moolenbroek 
getsockname(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len)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 
64c38dbb97SDavid van Moolenbroek 	r = __getsockname(fd, address, address_len);
65*84ed480eSDavid van Moolenbroek 	if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
66c38dbb97SDavid van Moolenbroek 		return r;
67c38dbb97SDavid van Moolenbroek 
68c38dbb97SDavid 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 
108c38dbb97SDavid van Moolenbroek 	errno = ENOTSOCK;
109433d6423SLionel Sambuc 	return -1;
110433d6423SLionel Sambuc }
111433d6423SLionel Sambuc 
112433d6423SLionel Sambuc 
_tcp_getsockname(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len,nwio_tcpconf_t * tcpconf)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 
_udp_getsockname(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len,nwio_udpopt_t * udpopt)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 
_uds_getsockname(int fd,struct sockaddr * __restrict address,socklen_t * __restrict address_len,struct sockaddr_un * uds_addr)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