1219b2ee8SDavid du Colombier /* posix */ 2219b2ee8SDavid du Colombier #include <sys/types.h> 3219b2ee8SDavid du Colombier #include <unistd.h> 4219b2ee8SDavid du Colombier #include <stdlib.h> 5219b2ee8SDavid du Colombier #include <stdio.h> 6219b2ee8SDavid du Colombier #include <fcntl.h> 7219b2ee8SDavid du Colombier #include <errno.h> 8219b2ee8SDavid du Colombier #include <string.h> 9219b2ee8SDavid du Colombier 10219b2ee8SDavid du Colombier /* bsd extensions */ 11219b2ee8SDavid du Colombier #include <sys/uio.h> 12219b2ee8SDavid du Colombier #include <sys/socket.h> 13219b2ee8SDavid du Colombier #include <netinet/in.h> 14219b2ee8SDavid du Colombier #include <sys/un.h> 15219b2ee8SDavid du Colombier 16219b2ee8SDavid du Colombier #include "priv.h" 17219b2ee8SDavid du Colombier 18219b2ee8SDavid du Colombier int 19219b2ee8SDavid du Colombier accept(int fd, void *a, int *alen) 20219b2ee8SDavid du Colombier { 21219b2ee8SDavid du Colombier int n, nfd, cfd; 22219b2ee8SDavid du Colombier Rock *r, *nr; 23219b2ee8SDavid du Colombier struct sockaddr_in *ip; 24219b2ee8SDavid du Colombier char name[Ctlsize]; 25219b2ee8SDavid du Colombier char file[Ctlsize]; 26219b2ee8SDavid du Colombier char *p, *net; 27219b2ee8SDavid du Colombier 28219b2ee8SDavid du Colombier r = _sock_findrock(fd, 0); 29219b2ee8SDavid du Colombier if(r == 0){ 30219b2ee8SDavid du Colombier errno = ENOTSOCK; 31219b2ee8SDavid du Colombier return -1; 32219b2ee8SDavid du Colombier } 33219b2ee8SDavid du Colombier 34219b2ee8SDavid du Colombier switch(r->domain){ 35219b2ee8SDavid du Colombier case PF_INET: 36219b2ee8SDavid du Colombier switch(r->stype){ 37219b2ee8SDavid du Colombier case SOCK_DGRAM: 38219b2ee8SDavid du Colombier net = "udp"; 39219b2ee8SDavid du Colombier break; 40219b2ee8SDavid du Colombier case SOCK_STREAM: 41219b2ee8SDavid du Colombier net = "tcp"; 42219b2ee8SDavid du Colombier break; 43219b2ee8SDavid du Colombier } 44219b2ee8SDavid du Colombier 45219b2ee8SDavid du Colombier /* get control file name from listener process */ 46219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name)-1); 47219b2ee8SDavid du Colombier if(n <= 0){ 48219b2ee8SDavid du Colombier _syserrno(); 49219b2ee8SDavid du Colombier return -1; 50219b2ee8SDavid du Colombier } 51219b2ee8SDavid du Colombier name[n] = 0; 52219b2ee8SDavid du Colombier cfd = open(name, O_RDWR); 53219b2ee8SDavid du Colombier if(cfd < 0){ 54219b2ee8SDavid du Colombier _syserrno(); 55219b2ee8SDavid du Colombier return -1; 56219b2ee8SDavid du Colombier } 57219b2ee8SDavid du Colombier 58219b2ee8SDavid du Colombier nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr); 59219b2ee8SDavid du Colombier if(nfd < 0){ 60219b2ee8SDavid du Colombier _syserrno(); 61219b2ee8SDavid du Colombier return -1; 62219b2ee8SDavid du Colombier } 63219b2ee8SDavid du Colombier 64219b2ee8SDavid du Colombier if(write(fd, "OK", 2) < 0){ 65219b2ee8SDavid du Colombier close(nfd); 66219b2ee8SDavid du Colombier _syserrno(); 67219b2ee8SDavid du Colombier return -1; 68219b2ee8SDavid du Colombier } 69219b2ee8SDavid du Colombier 70219b2ee8SDavid du Colombier /* get remote address */ 71*9a747e4fSDavid du Colombier ip = (struct sockaddr_in*)&nr->raddr; 72219b2ee8SDavid du Colombier _sock_ingetaddr(nr, ip, &n, "remote"); 73219b2ee8SDavid du Colombier if(a){ 74219b2ee8SDavid du Colombier memmove(a, ip, sizeof(struct sockaddr_in)); 75219b2ee8SDavid du Colombier *alen = sizeof(struct sockaddr_in); 76219b2ee8SDavid du Colombier } 77219b2ee8SDavid du Colombier 78219b2ee8SDavid du Colombier return nfd; 79219b2ee8SDavid du Colombier case PF_UNIX: 80219b2ee8SDavid du Colombier if(r->other >= 0){ 81219b2ee8SDavid du Colombier errno = EGREG; 82219b2ee8SDavid du Colombier return -1; 83219b2ee8SDavid du Colombier } 84219b2ee8SDavid du Colombier 85219b2ee8SDavid du Colombier for(;;){ 86219b2ee8SDavid du Colombier /* read path to new connection */ 87219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name) - 1); 88219b2ee8SDavid du Colombier if(n < 0) 89219b2ee8SDavid du Colombier return -1; 90219b2ee8SDavid du Colombier if(n == 0) 91219b2ee8SDavid du Colombier continue; 92219b2ee8SDavid du Colombier name[n] = 0; 93219b2ee8SDavid du Colombier 94219b2ee8SDavid du Colombier /* open new connection */ 95219b2ee8SDavid du Colombier _sock_srvname(file, name); 96219b2ee8SDavid du Colombier nfd = open(file, O_RDWR); 97219b2ee8SDavid du Colombier if(nfd < 0) 98219b2ee8SDavid du Colombier continue; 99219b2ee8SDavid du Colombier 100219b2ee8SDavid du Colombier /* confirm opening on new connection */ 101219b2ee8SDavid du Colombier if(write(nfd, name, strlen(name)) > 0) 102219b2ee8SDavid du Colombier break; 103219b2ee8SDavid du Colombier 104219b2ee8SDavid du Colombier close(nfd); 105219b2ee8SDavid du Colombier } 106219b2ee8SDavid du Colombier 107219b2ee8SDavid du Colombier nr = _sock_newrock(nfd); 108219b2ee8SDavid du Colombier if(nr == 0){ 109219b2ee8SDavid du Colombier close(nfd); 110219b2ee8SDavid du Colombier return -1; 111219b2ee8SDavid du Colombier } 112219b2ee8SDavid du Colombier nr->domain = r->domain; 113219b2ee8SDavid du Colombier nr->stype = r->stype; 114219b2ee8SDavid du Colombier nr->protocol = r->protocol; 115219b2ee8SDavid du Colombier 116219b2ee8SDavid du Colombier return nfd; 117219b2ee8SDavid du Colombier default: 118219b2ee8SDavid du Colombier errno = EOPNOTSUPP; 119219b2ee8SDavid du Colombier return -1; 120219b2ee8SDavid du Colombier } 121219b2ee8SDavid du Colombier } 122