1*433d6423SLionel Sambuc #include <sys/cdefs.h> 2*433d6423SLionel Sambuc #include "namespace.h" 3*433d6423SLionel Sambuc 4*433d6423SLionel Sambuc #include <unistd.h> 5*433d6423SLionel Sambuc #include <stdint.h> 6*433d6423SLionel Sambuc #include <stdlib.h> 7*433d6423SLionel Sambuc #include <limits.h> 8*433d6423SLionel Sambuc #include <errno.h> 9*433d6423SLionel Sambuc #include <stdio.h> 10*433d6423SLionel Sambuc #include <string.h> 11*433d6423SLionel Sambuc #include <sys/ioctl.h> 12*433d6423SLionel Sambuc #include <sys/socket.h> 13*433d6423SLionel Sambuc #include <sys/types.h> 14*433d6423SLionel Sambuc #include <sys/stat.h> 15*433d6423SLionel Sambuc #include <netinet/in.h> 16*433d6423SLionel Sambuc 17*433d6423SLionel Sambuc #include <net/gen/in.h> 18*433d6423SLionel Sambuc #include <net/gen/tcp.h> 19*433d6423SLionel Sambuc #include <net/gen/tcp_io.h> 20*433d6423SLionel Sambuc #include <net/gen/udp.h> 21*433d6423SLionel Sambuc #include <net/gen/udp_io.h> 22*433d6423SLionel Sambuc #include <sys/un.h> 23*433d6423SLionel Sambuc 24*433d6423SLionel Sambuc #include <minix/config.h> 25*433d6423SLionel Sambuc #include <minix/const.h> 26*433d6423SLionel Sambuc 27*433d6423SLionel Sambuc #define DEBUG 0 28*433d6423SLionel Sambuc 29*433d6423SLionel Sambuc static int _tcp_bind(int sock, const struct sockaddr *address, 30*433d6423SLionel Sambuc socklen_t address_len, nwio_tcpconf_t *tcpconfp); 31*433d6423SLionel Sambuc static int _udp_bind(int sock, const struct sockaddr *address, 32*433d6423SLionel Sambuc socklen_t address_len, nwio_udpopt_t *udpoptp); 33*433d6423SLionel Sambuc static int _uds_bind(int sock, const struct sockaddr *address, 34*433d6423SLionel Sambuc socklen_t address_len, struct sockaddr_un *uds_addr); 35*433d6423SLionel Sambuc 36*433d6423SLionel Sambuc int bind(int sock, const struct sockaddr *address, socklen_t address_len) 37*433d6423SLionel Sambuc { 38*433d6423SLionel Sambuc int r; 39*433d6423SLionel Sambuc nwio_tcpconf_t tcpconf; 40*433d6423SLionel Sambuc nwio_udpopt_t udpopt; 41*433d6423SLionel Sambuc struct sockaddr_un uds_addr; 42*433d6423SLionel Sambuc 43*433d6423SLionel Sambuc r= ioctl(sock, NWIOGTCPCONF, &tcpconf); 44*433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 45*433d6423SLionel Sambuc { 46*433d6423SLionel Sambuc if (r == -1) 47*433d6423SLionel Sambuc return r; 48*433d6423SLionel Sambuc r= _tcp_bind(sock, address, address_len, &tcpconf); 49*433d6423SLionel Sambuc #if DEBUG 50*433d6423SLionel Sambuc if (r == -1) 51*433d6423SLionel Sambuc { 52*433d6423SLionel Sambuc int t_errno= errno; 53*433d6423SLionel Sambuc fprintf(stderr, "bind(tcp) failed: %s\n", 54*433d6423SLionel Sambuc strerror(errno)); 55*433d6423SLionel Sambuc errno= t_errno; 56*433d6423SLionel Sambuc } 57*433d6423SLionel Sambuc #endif 58*433d6423SLionel Sambuc return r; 59*433d6423SLionel Sambuc } 60*433d6423SLionel Sambuc 61*433d6423SLionel Sambuc r= ioctl(sock, NWIOGUDPOPT, &udpopt); 62*433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 63*433d6423SLionel Sambuc { 64*433d6423SLionel Sambuc if (r == -1) 65*433d6423SLionel Sambuc return r; 66*433d6423SLionel Sambuc return _udp_bind(sock, address, address_len, &udpopt); 67*433d6423SLionel Sambuc } 68*433d6423SLionel Sambuc 69*433d6423SLionel Sambuc r= ioctl(sock, NWIOGUDSADDR, &uds_addr); 70*433d6423SLionel Sambuc if (r != -1 || errno != ENOTTY) 71*433d6423SLionel Sambuc { 72*433d6423SLionel Sambuc if (r == -1) 73*433d6423SLionel Sambuc return r; 74*433d6423SLionel Sambuc return _uds_bind(sock, address, address_len, &uds_addr); 75*433d6423SLionel Sambuc } 76*433d6423SLionel Sambuc 77*433d6423SLionel Sambuc #if DEBUG 78*433d6423SLionel Sambuc fprintf(stderr, "bind: not implemented for fd %d\n", sock); 79*433d6423SLionel Sambuc #endif 80*433d6423SLionel Sambuc errno= ENOSYS; 81*433d6423SLionel Sambuc return -1; 82*433d6423SLionel Sambuc } 83*433d6423SLionel Sambuc 84*433d6423SLionel Sambuc static int _tcp_bind(int sock, const struct sockaddr *address, 85*433d6423SLionel Sambuc socklen_t address_len, nwio_tcpconf_t *tcpconfp) 86*433d6423SLionel Sambuc { 87*433d6423SLionel Sambuc int r; 88*433d6423SLionel Sambuc nwio_tcpconf_t tcpconf; 89*433d6423SLionel Sambuc struct sockaddr_in *sinp; 90*433d6423SLionel Sambuc 91*433d6423SLionel Sambuc sinp= (struct sockaddr_in *) __UNCONST(address); 92*433d6423SLionel Sambuc if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp)) 93*433d6423SLionel Sambuc { 94*433d6423SLionel Sambuc #if DEBUG 95*433d6423SLionel Sambuc fprintf(stderr, "bind(tcp): sin_family = %d, len = %d\n", 96*433d6423SLionel Sambuc sinp->sin_family, address_len); 97*433d6423SLionel Sambuc #endif 98*433d6423SLionel Sambuc errno= EAFNOSUPPORT; 99*433d6423SLionel Sambuc return -1; 100*433d6423SLionel Sambuc } 101*433d6423SLionel Sambuc 102*433d6423SLionel Sambuc if (sinp->sin_addr.s_addr != INADDR_ANY && 103*433d6423SLionel Sambuc sinp->sin_addr.s_addr != tcpconfp->nwtc_locaddr) 104*433d6423SLionel Sambuc { 105*433d6423SLionel Sambuc errno= EADDRNOTAVAIL; 106*433d6423SLionel Sambuc return -1; 107*433d6423SLionel Sambuc } 108*433d6423SLionel Sambuc 109*433d6423SLionel Sambuc tcpconf.nwtc_flags= 0; 110*433d6423SLionel Sambuc 111*433d6423SLionel Sambuc if (sinp->sin_port == 0) 112*433d6423SLionel Sambuc tcpconf.nwtc_flags |= NWTC_LP_SEL; 113*433d6423SLionel Sambuc else 114*433d6423SLionel Sambuc { 115*433d6423SLionel Sambuc tcpconf.nwtc_flags |= NWTC_LP_SET; 116*433d6423SLionel Sambuc tcpconf.nwtc_locport= sinp->sin_port; 117*433d6423SLionel Sambuc } 118*433d6423SLionel Sambuc 119*433d6423SLionel Sambuc r= ioctl(sock, NWIOSTCPCONF, &tcpconf); 120*433d6423SLionel Sambuc return r; 121*433d6423SLionel Sambuc } 122*433d6423SLionel Sambuc 123*433d6423SLionel Sambuc static int _udp_bind(int sock, const struct sockaddr *address, 124*433d6423SLionel Sambuc socklen_t address_len, nwio_udpopt_t *udpoptp) 125*433d6423SLionel Sambuc { 126*433d6423SLionel Sambuc int r; 127*433d6423SLionel Sambuc unsigned long curr_flags; 128*433d6423SLionel Sambuc nwio_udpopt_t udpopt; 129*433d6423SLionel Sambuc struct sockaddr_in *sinp; 130*433d6423SLionel Sambuc 131*433d6423SLionel Sambuc sinp= (struct sockaddr_in *) __UNCONST(address); 132*433d6423SLionel Sambuc if (sinp->sin_family != AF_INET || address_len < sizeof(*sinp)) 133*433d6423SLionel Sambuc { 134*433d6423SLionel Sambuc #if DEBUG 135*433d6423SLionel Sambuc fprintf(stderr, "bind(udp): sin_family = %d, len = %d\n", 136*433d6423SLionel Sambuc sinp->sin_family, address_len); 137*433d6423SLionel Sambuc #endif 138*433d6423SLionel Sambuc errno= EAFNOSUPPORT; 139*433d6423SLionel Sambuc return -1; 140*433d6423SLionel Sambuc } 141*433d6423SLionel Sambuc 142*433d6423SLionel Sambuc if (sinp->sin_addr.s_addr != INADDR_ANY && 143*433d6423SLionel Sambuc sinp->sin_addr.s_addr != udpoptp->nwuo_locaddr) 144*433d6423SLionel Sambuc { 145*433d6423SLionel Sambuc errno= EADDRNOTAVAIL; 146*433d6423SLionel Sambuc return -1; 147*433d6423SLionel Sambuc } 148*433d6423SLionel Sambuc 149*433d6423SLionel Sambuc udpopt.nwuo_flags= 0; 150*433d6423SLionel Sambuc 151*433d6423SLionel Sambuc if (sinp->sin_port == 0) 152*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_LP_SEL; 153*433d6423SLionel Sambuc else 154*433d6423SLionel Sambuc { 155*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_LP_SET; 156*433d6423SLionel Sambuc udpopt.nwuo_locport= sinp->sin_port; 157*433d6423SLionel Sambuc } 158*433d6423SLionel Sambuc 159*433d6423SLionel Sambuc curr_flags= udpoptp->nwuo_flags; 160*433d6423SLionel Sambuc if (!(curr_flags & NWUO_ACC_MASK)) 161*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_EXCL; 162*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_EN_LOC|NWUO_DI_LOC))) 163*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_EN_LOC; 164*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_EN_BROAD|NWUO_DI_BROAD))) 165*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_EN_BROAD; 166*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_RP_SET|NWUO_RP_ANY))) 167*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_RP_ANY; 168*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_RA_SET|NWUO_RA_ANY))) 169*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_RA_ANY; 170*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_RWDATONLY|NWUO_RWDATALL))) 171*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_RWDATALL; 172*433d6423SLionel Sambuc if (!(curr_flags & (NWUO_EN_IPOPT|NWUO_DI_IPOPT))) 173*433d6423SLionel Sambuc udpopt.nwuo_flags |= NWUO_DI_IPOPT; 174*433d6423SLionel Sambuc 175*433d6423SLionel Sambuc r= ioctl(sock, NWIOSUDPOPT, &udpopt); 176*433d6423SLionel Sambuc return r; 177*433d6423SLionel Sambuc } 178*433d6423SLionel Sambuc 179*433d6423SLionel Sambuc static int _uds_bind(int sock, const struct sockaddr *address, 180*433d6423SLionel Sambuc socklen_t address_len, struct sockaddr_un *uds_addr) 181*433d6423SLionel Sambuc { 182*433d6423SLionel Sambuc int r; 183*433d6423SLionel Sambuc int did_mknod; 184*433d6423SLionel Sambuc 185*433d6423SLionel Sambuc if (address == NULL) { 186*433d6423SLionel Sambuc errno = EFAULT; 187*433d6423SLionel Sambuc return -1; 188*433d6423SLionel Sambuc } 189*433d6423SLionel Sambuc 190*433d6423SLionel Sambuc did_mknod = 0; 191*433d6423SLionel Sambuc 192*433d6423SLionel Sambuc r = mknod(((struct sockaddr_un *) __UNCONST(address))->sun_path, 193*433d6423SLionel Sambuc S_IFSOCK|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH, 0); 194*433d6423SLionel Sambuc 195*433d6423SLionel Sambuc if (r == -1 && errno != EEXIST) { 196*433d6423SLionel Sambuc return -1; 197*433d6423SLionel Sambuc } else if (r == 0) { 198*433d6423SLionel Sambuc did_mknod = 1; 199*433d6423SLionel Sambuc } 200*433d6423SLionel Sambuc 201*433d6423SLionel Sambuc /* perform the bind */ 202*433d6423SLionel Sambuc r= ioctl(sock, NWIOSUDSADDR, (void *) __UNCONST(address)); 203*433d6423SLionel Sambuc 204*433d6423SLionel Sambuc if (r == -1 && did_mknod) { 205*433d6423SLionel Sambuc 206*433d6423SLionel Sambuc /* bind() failed in pfs, so we roll back the 207*433d6423SLionel Sambuc * file system change 208*433d6423SLionel Sambuc */ 209*433d6423SLionel Sambuc unlink(((struct sockaddr_un *) __UNCONST(address))->sun_path); 210*433d6423SLionel Sambuc } 211*433d6423SLionel Sambuc 212*433d6423SLionel Sambuc return r; 213*433d6423SLionel Sambuc } 214