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]; 257e125112SDavid du Colombier char file[8+Ctlsize+1]; 26*781103c4SDavid du Colombier char *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; 43*781103c4SDavid du Colombier default: 44*781103c4SDavid du Colombier net = "gok"; 45*781103c4SDavid du Colombier break; 46219b2ee8SDavid du Colombier } 47219b2ee8SDavid du Colombier 48219b2ee8SDavid du Colombier /* get control file name from listener process */ 49219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name)-1); 50219b2ee8SDavid du Colombier if(n <= 0){ 51219b2ee8SDavid du Colombier _syserrno(); 52219b2ee8SDavid du Colombier return -1; 53219b2ee8SDavid du Colombier } 54219b2ee8SDavid du Colombier name[n] = 0; 55219b2ee8SDavid du Colombier cfd = open(name, O_RDWR); 56219b2ee8SDavid du Colombier if(cfd < 0){ 57219b2ee8SDavid du Colombier _syserrno(); 58219b2ee8SDavid du Colombier return -1; 59219b2ee8SDavid du Colombier } 60219b2ee8SDavid du Colombier 61219b2ee8SDavid du Colombier nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr); 62219b2ee8SDavid du Colombier if(nfd < 0){ 63219b2ee8SDavid du Colombier _syserrno(); 64219b2ee8SDavid du Colombier return -1; 65219b2ee8SDavid du Colombier } 66219b2ee8SDavid du Colombier 67219b2ee8SDavid du Colombier if(write(fd, "OK", 2) < 0){ 68219b2ee8SDavid du Colombier close(nfd); 69219b2ee8SDavid du Colombier _syserrno(); 70219b2ee8SDavid du Colombier return -1; 71219b2ee8SDavid du Colombier } 72219b2ee8SDavid du Colombier 73219b2ee8SDavid du Colombier /* get remote address */ 749a747e4fSDavid du Colombier ip = (struct sockaddr_in*)&nr->raddr; 75219b2ee8SDavid du Colombier _sock_ingetaddr(nr, ip, &n, "remote"); 76219b2ee8SDavid du Colombier if(a){ 77219b2ee8SDavid du Colombier memmove(a, ip, sizeof(struct sockaddr_in)); 78219b2ee8SDavid du Colombier *alen = sizeof(struct sockaddr_in); 79219b2ee8SDavid du Colombier } 80219b2ee8SDavid du Colombier 81219b2ee8SDavid du Colombier return nfd; 82219b2ee8SDavid du Colombier case PF_UNIX: 83219b2ee8SDavid du Colombier if(r->other >= 0){ 84219b2ee8SDavid du Colombier errno = EGREG; 85219b2ee8SDavid du Colombier return -1; 86219b2ee8SDavid du Colombier } 87219b2ee8SDavid du Colombier 88219b2ee8SDavid du Colombier for(;;){ 89219b2ee8SDavid du Colombier /* read path to new connection */ 90219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name) - 1); 91219b2ee8SDavid du Colombier if(n < 0) 92219b2ee8SDavid du Colombier return -1; 93219b2ee8SDavid du Colombier if(n == 0) 94219b2ee8SDavid du Colombier continue; 95219b2ee8SDavid du Colombier name[n] = 0; 96219b2ee8SDavid du Colombier 97219b2ee8SDavid du Colombier /* open new connection */ 98219b2ee8SDavid du Colombier _sock_srvname(file, name); 99219b2ee8SDavid du Colombier nfd = open(file, O_RDWR); 100219b2ee8SDavid du Colombier if(nfd < 0) 101219b2ee8SDavid du Colombier continue; 102219b2ee8SDavid du Colombier 103219b2ee8SDavid du Colombier /* confirm opening on new connection */ 104219b2ee8SDavid du Colombier if(write(nfd, name, strlen(name)) > 0) 105219b2ee8SDavid du Colombier break; 106219b2ee8SDavid du Colombier 107219b2ee8SDavid du Colombier close(nfd); 108219b2ee8SDavid du Colombier } 109219b2ee8SDavid du Colombier 110219b2ee8SDavid du Colombier nr = _sock_newrock(nfd); 111219b2ee8SDavid du Colombier if(nr == 0){ 112219b2ee8SDavid du Colombier close(nfd); 113219b2ee8SDavid du Colombier return -1; 114219b2ee8SDavid du Colombier } 115219b2ee8SDavid du Colombier nr->domain = r->domain; 116219b2ee8SDavid du Colombier nr->stype = r->stype; 117219b2ee8SDavid du Colombier nr->protocol = r->protocol; 118219b2ee8SDavid du Colombier 119219b2ee8SDavid du Colombier return nfd; 120219b2ee8SDavid du Colombier default: 121219b2ee8SDavid du Colombier errno = EOPNOTSUPP; 122219b2ee8SDavid du Colombier return -1; 123219b2ee8SDavid du Colombier } 124219b2ee8SDavid du Colombier } 125