some coverity fixes.
[minix.git] / lib / libc / sys-minix / bind.c
blob47c90d8cd228b4ddaeff057e5b3229ffdcf52abb
1 #include <sys/cdefs.h>
2 #include "namespace.h"
4 #ifdef __weak_alias
5 __weak_alias(bind, _bind)
6 #endif
8 #include <unistd.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <limits.h>
12 #include <errno.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <netinet/in.h>
21 #include <net/gen/in.h>
22 #include <net/gen/tcp.h>
23 #include <net/gen/tcp_io.h>
24 #include <net/gen/udp.h>
25 #include <net/gen/udp_io.h>
26 #include <sys/un.h>
28 #include <minix/config.h>
29 #include <minix/const.h>
31 #define DEBUG 0
33 static int _tcp_bind(int sock, const struct sockaddr *address,
34 socklen_t address_len, nwio_tcpconf_t *tcpconfp);
35 static int _udp_bind(int sock, const struct sockaddr *address,
36 socklen_t address_len, nwio_udpopt_t *udpoptp);
37 static int _uds_bind(int sock, const struct sockaddr *address,
38 socklen_t address_len, struct sockaddr_un *uds_addr);
40 int bind(int sock, const struct sockaddr *address, socklen_t address_len)
42 int r;
43 nwio_tcpconf_t tcpconf;
44 nwio_udpopt_t udpopt;
45 struct sockaddr_un uds_addr;
47 r= ioctl(sock, NWIOGTCPCONF, &tcpconf);
48 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
50 if (r == -1)
51 return r;
52 r= _tcp_bind(sock, address, address_len, &tcpconf);
53 #if DEBUG
54 if (r == -1)
56 int t_errno= errno;
57 fprintf(stderr, "bind(tcp) failed: %s\n",
58 strerror(errno));
59 errno= t_errno;
61 #endif
62 return r;
65 r= ioctl(sock, NWIOGUDPOPT, &udpopt);
66 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
68 if (r == -1)
69 return r;
70 return _udp_bind(sock, address, address_len, &udpopt);
73 r= ioctl(sock, NWIOGUDSADDR, &uds_addr);
74 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
76 if (r == -1)
77 return r;
78 return _uds_bind(sock, address, address_len, &uds_addr);
81 #if DEBUG
82 fprintf(stderr, "bind: not implemented for fd %d\n", sock);
83 #endif
84 errno= ENOSYS;
85 return -1;
88 static int _tcp_bind(int sock, const struct sockaddr *address,
89 socklen_t address_len, nwio_tcpconf_t *tcpconfp)
91 int r;
92 nwio_tcpconf_t tcpconf;
93 struct sockaddr_in *sinp;
95 sinp= (struct sockaddr_in *) __UNCONST(address);
96 if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp))
98 #if DEBUG
99 fprintf(stderr, "bind(tcp): sin_family = %d, len = %d\n",
100 sinp->sin_family, address_len);
101 #endif
102 errno= EAFNOSUPPORT;
103 return -1;
106 if (sinp->sin_addr.s_addr != INADDR_ANY &&
107 sinp->sin_addr.s_addr != tcpconfp->nwtc_locaddr)
109 errno= EADDRNOTAVAIL;
110 return -1;
113 tcpconf.nwtc_flags= 0;
115 if (sinp->sin_port == 0)
116 tcpconf.nwtc_flags |= NWTC_LP_SEL;
117 else
119 tcpconf.nwtc_flags |= NWTC_LP_SET;
120 tcpconf.nwtc_locport= sinp->sin_port;
123 r= ioctl(sock, NWIOSTCPCONF, &tcpconf);
124 return r;
127 static int _udp_bind(int sock, const struct sockaddr *address,
128 socklen_t address_len, nwio_udpopt_t *udpoptp)
130 int r;
131 unsigned long curr_flags;
132 nwio_udpopt_t udpopt;
133 struct sockaddr_in *sinp;
135 sinp= (struct sockaddr_in *) __UNCONST(address);
136 if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp))
138 #if DEBUG
139 fprintf(stderr, "bind(udp): sin_family = %d, len = %d\n",
140 sinp->sin_family, address_len);
141 #endif
142 errno= EAFNOSUPPORT;
143 return -1;
146 if (sinp->sin_addr.s_addr != INADDR_ANY &&
147 sinp->sin_addr.s_addr != udpoptp->nwuo_locaddr)
149 errno= EADDRNOTAVAIL;
150 return -1;
153 udpopt.nwuo_flags= 0;
155 if (sinp->sin_port == 0)
156 udpopt.nwuo_flags |= NWUO_LP_SEL;
157 else
159 udpopt.nwuo_flags |= NWUO_LP_SET;
160 udpopt.nwuo_locport= sinp->sin_port;
163 curr_flags= udpoptp->nwuo_flags;
164 if (!(curr_flags & NWUO_ACC_MASK))
165 udpopt.nwuo_flags |= NWUO_EXCL;
166 if (!(curr_flags & (NWUO_EN_LOC|NWUO_DI_LOC)))
167 udpopt.nwuo_flags |= NWUO_EN_LOC;
168 if (!(curr_flags & (NWUO_EN_BROAD|NWUO_DI_BROAD)))
169 udpopt.nwuo_flags |= NWUO_EN_BROAD;
170 if (!(curr_flags & (NWUO_RP_SET|NWUO_RP_ANY)))
171 udpopt.nwuo_flags |= NWUO_RP_ANY;
172 if (!(curr_flags & (NWUO_RA_SET|NWUO_RA_ANY)))
173 udpopt.nwuo_flags |= NWUO_RA_ANY;
174 if (!(curr_flags & (NWUO_RWDATONLY|NWUO_RWDATALL)))
175 udpopt.nwuo_flags |= NWUO_RWDATALL;
176 if (!(curr_flags & (NWUO_EN_IPOPT|NWUO_DI_IPOPT)))
177 udpopt.nwuo_flags |= NWUO_DI_IPOPT;
179 r= ioctl(sock, NWIOSUDPOPT, &udpopt);
180 return r;
183 static int _uds_bind(int sock, const struct sockaddr *address,
184 socklen_t address_len, struct sockaddr_un *uds_addr)
186 int r;
187 int did_mknod;
189 if (address == NULL) {
190 errno = EFAULT;
191 return -1;
194 did_mknod = 0;
196 r = mknod(((struct sockaddr_un *) __UNCONST(address))->sun_path,
197 S_IFSOCK|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0);
199 if (r == -1 && errno != EEXIST) {
200 return -1;
201 } else if (r == 0) {
202 did_mknod = 1;
205 /* perform the bind */
206 r= ioctl(sock, NWIOSUDSADDR, (void *) __UNCONST(address));
208 if (r == -1 && did_mknod) {
210 /* bind() failed in pfs, so we roll back the
211 * file system change
213 unlink(((struct sockaddr_un *) __UNCONST(address))->sun_path);
216 return r;