etc/services - sync with NetBSD-8
[minix.git] / minix / lib / libc / sys / bind.c
blobd7c9a749518ba4be7c2fcb62f536e0f5d47bc039
1 #include <sys/cdefs.h>
2 #include "namespace.h"
3 #include <lib.h>
5 #include <unistd.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <limits.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <sys/types.h>
15 #include <sys/stat.h>
16 #include <netinet/in.h>
18 #include <net/gen/in.h>
19 #include <net/gen/tcp.h>
20 #include <net/gen/tcp_io.h>
21 #include <net/gen/udp.h>
22 #include <net/gen/udp_io.h>
23 #include <sys/un.h>
25 #include <minix/config.h>
26 #include <minix/const.h>
28 #define DEBUG 0
30 static int _tcp_bind(int sock, const struct sockaddr *address,
31 socklen_t address_len, nwio_tcpconf_t *tcpconfp);
32 static int _udp_bind(int sock, const struct sockaddr *address,
33 socklen_t address_len, nwio_udpopt_t *udpoptp);
34 static int _uds_bind(int sock, const struct sockaddr *address,
35 socklen_t address_len, struct sockaddr_un *uds_addr);
38 * Bind a socket to a local address.
40 static int
41 __bind(int fd, const struct sockaddr * address, socklen_t address_len)
43 message m;
45 memset(&m, 0, sizeof(m));
46 m.m_lc_vfs_sockaddr.fd = fd;
47 m.m_lc_vfs_sockaddr.addr = (vir_bytes)address;
48 m.m_lc_vfs_sockaddr.addr_len = address_len;
50 return _syscall(VFS_PROC_NR, VFS_BIND, &m);
53 int bind(int sock, const struct sockaddr *address, socklen_t address_len)
55 int r;
56 nwio_tcpconf_t tcpconf;
57 nwio_udpopt_t udpopt;
58 struct sockaddr_un uds_addr;
60 r = __bind(sock, address, address_len);
61 if (r != -1 || (errno != ENOTSOCK && errno != ENOSYS))
62 return r;
64 r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
65 if (r != -1 || errno != ENOTTY)
67 if (r == -1)
68 return r;
69 r= _tcp_bind(sock, address, address_len, &tcpconf);
70 #if DEBUG
71 if (r == -1)
73 int t_errno= errno;
74 fprintf(stderr, "bind(tcp) failed: %s\n",
75 strerror(errno));
76 errno= t_errno;
78 #endif
79 return r;
82 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
83 if (r != -1 || errno != ENOTTY)
85 if (r == -1)
86 return r;
87 return _udp_bind(sock, address, address_len, &udpopt);
90 r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
91 if (r != -1 || errno != ENOTTY)
93 if (r == -1)
94 return r;
95 return _uds_bind(sock, address, address_len, &uds_addr);
98 errno = ENOTSOCK;
99 return -1;
102 static int _tcp_bind(int sock, const struct sockaddr *address,
103 socklen_t address_len, nwio_tcpconf_t *tcpconfp)
105 int r;
106 nwio_tcpconf_t tcpconf;
107 struct sockaddr_in *sinp;
109 sinp= (struct sockaddr_in *) __UNCONST(address);
110 if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp))
112 #if DEBUG
113 fprintf(stderr, "bind(tcp): sin_family = %d, len = %d\n",
114 sinp->sin_family, address_len);
115 #endif
116 errno= EAFNOSUPPORT;
117 return -1;
120 if (sinp->sin_addr.s_addr != INADDR_ANY &&
121 sinp->sin_addr.s_addr != tcpconfp->nwtc_locaddr)
123 errno= EADDRNOTAVAIL;
124 return -1;
127 tcpconf.nwtc_flags= 0;
129 if (sinp->sin_port == 0)
130 tcpconf.nwtc_flags |= NWTC_LP_SEL;
131 else
133 tcpconf.nwtc_flags |= NWTC_LP_SET;
134 tcpconf.nwtc_locport= sinp->sin_port;
137 r= ioctl(sock, NWIOSTCPCONF, &tcpconf);
138 return r;
141 static int _udp_bind(int sock, const struct sockaddr *address,
142 socklen_t address_len, nwio_udpopt_t *udpoptp)
144 int r;
145 unsigned long curr_flags;
146 nwio_udpopt_t udpopt;
147 struct sockaddr_in *sinp;
149 sinp= (struct sockaddr_in *) __UNCONST(address);
150 if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp))
152 #if DEBUG
153 fprintf(stderr, "bind(udp): sin_family = %d, len = %d\n",
154 sinp->sin_family, address_len);
155 #endif
156 errno= EAFNOSUPPORT;
157 return -1;
160 if (sinp->sin_addr.s_addr != INADDR_ANY &&
161 sinp->sin_addr.s_addr != udpoptp->nwuo_locaddr)
163 errno= EADDRNOTAVAIL;
164 return -1;
167 udpopt.nwuo_flags= 0;
169 if (sinp->sin_port == 0)
170 udpopt.nwuo_flags |= NWUO_LP_SEL;
171 else
173 udpopt.nwuo_flags |= NWUO_LP_SET;
174 udpopt.nwuo_locport= sinp->sin_port;
177 curr_flags= udpoptp->nwuo_flags;
178 if (!(curr_flags & NWUO_ACC_MASK))
179 udpopt.nwuo_flags |= NWUO_EXCL;
180 if (!(curr_flags & (NWUO_EN_LOC|NWUO_DI_LOC)))
181 udpopt.nwuo_flags |= NWUO_EN_LOC;
182 if (!(curr_flags & (NWUO_EN_BROAD|NWUO_DI_BROAD)))
183 udpopt.nwuo_flags |= NWUO_EN_BROAD;
184 if (!(curr_flags & (NWUO_RP_SET|NWUO_RP_ANY)))
185 udpopt.nwuo_flags |= NWUO_RP_ANY;
186 if (!(curr_flags & (NWUO_RA_SET|NWUO_RA_ANY)))
187 udpopt.nwuo_flags |= NWUO_RA_ANY;
188 if (!(curr_flags & (NWUO_RWDATONLY|NWUO_RWDATALL)))
189 udpopt.nwuo_flags |= NWUO_RWDATALL;
190 if (!(curr_flags & (NWUO_EN_IPOPT|NWUO_DI_IPOPT)))
191 udpopt.nwuo_flags |= NWUO_DI_IPOPT;
193 r= ioctl(sock, NWIOSUDPOPT, &udpopt);
194 return r;
197 static int _uds_bind(int sock, const struct sockaddr *address,
198 socklen_t address_len, struct sockaddr_un *uds_addr)
200 int r;
201 int did_mknod;
203 if (address == NULL) {
204 errno = EFAULT;
205 return -1;
208 did_mknod = 0;
210 r = mknod(((struct sockaddr_un *) __UNCONST(address))->sun_path,
211 S_IFSOCK|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0);
213 if (r == -1 && errno != EEXIST) {
214 return -1;
215 } else if (r == 0) {
216 did_mknod = 1;
219 /* perform the bind */
220 r= ioctl(sock, NWIOSUDSADDR, (void *) __UNCONST(address));
222 if (r == -1 && did_mknod) {
224 /* bind() failed in pfs, so we roll back the
225 * file system change
227 unlink(((struct sockaddr_un *) __UNCONST(address))->sun_path);
230 return r;