xref: /minix3/minix/lib/libc/sys/getsockname.c (revision 03de4d97b49f6be0f827bcf030d487febfc78953)
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