12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <sys/types.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>
25 #include <minix/config.h>
26 #include <minix/const.h>
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.
41 __bind(int fd
, const struct sockaddr
* address
, socklen_t address_len
)
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
)
56 nwio_tcpconf_t tcpconf
;
58 struct sockaddr_un uds_addr
;
60 r
= __bind(sock
, address
, address_len
);
61 if (r
!= -1 || (errno
!= ENOTSOCK
&& errno
!= ENOSYS
))
64 r
= ioctl(sock
, NWIOGTCPCONF
, &tcpconf
);
65 if (r
!= -1 || errno
!= ENOTTY
)
69 r
= _tcp_bind(sock
, address
, address_len
, &tcpconf
);
74 fprintf(stderr
, "bind(tcp) failed: %s\n",
82 r
= ioctl(sock
, NWIOGUDPOPT
, &udpopt
);
83 if (r
!= -1 || errno
!= ENOTTY
)
87 return _udp_bind(sock
, address
, address_len
, &udpopt
);
90 r
= ioctl(sock
, NWIOGUDSADDR
, &uds_addr
);
91 if (r
!= -1 || errno
!= ENOTTY
)
95 return _uds_bind(sock
, address
, address_len
, &uds_addr
);
102 static int _tcp_bind(int sock
, const struct sockaddr
*address
,
103 socklen_t address_len
, nwio_tcpconf_t
*tcpconfp
)
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
))
113 fprintf(stderr
, "bind(tcp): sin_family = %d, len = %d\n",
114 sinp
->sin_family
, address_len
);
120 if (sinp
->sin_addr
.s_addr
!= INADDR_ANY
&&
121 sinp
->sin_addr
.s_addr
!= tcpconfp
->nwtc_locaddr
)
123 errno
= EADDRNOTAVAIL
;
127 tcpconf
.nwtc_flags
= 0;
129 if (sinp
->sin_port
== 0)
130 tcpconf
.nwtc_flags
|= NWTC_LP_SEL
;
133 tcpconf
.nwtc_flags
|= NWTC_LP_SET
;
134 tcpconf
.nwtc_locport
= sinp
->sin_port
;
137 r
= ioctl(sock
, NWIOSTCPCONF
, &tcpconf
);
141 static int _udp_bind(int sock
, const struct sockaddr
*address
,
142 socklen_t address_len
, nwio_udpopt_t
*udpoptp
)
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
))
153 fprintf(stderr
, "bind(udp): sin_family = %d, len = %d\n",
154 sinp
->sin_family
, address_len
);
160 if (sinp
->sin_addr
.s_addr
!= INADDR_ANY
&&
161 sinp
->sin_addr
.s_addr
!= udpoptp
->nwuo_locaddr
)
163 errno
= EADDRNOTAVAIL
;
167 udpopt
.nwuo_flags
= 0;
169 if (sinp
->sin_port
== 0)
170 udpopt
.nwuo_flags
|= NWUO_LP_SEL
;
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
);
197 static int _uds_bind(int sock
, const struct sockaddr
*address
,
198 socklen_t address_len
, struct sockaddr_un
*uds_addr
)
203 if (address
== NULL
) {
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
) {
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
227 unlink(((struct sockaddr_un
*) __UNCONST(address
))->sun_path
);