xref: /minix/minix/lib/libc/sys/getpeername.c (revision 7f5f010b)
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