1*219b2ee8SDavid du Colombier /* posix */ 2*219b2ee8SDavid du Colombier #include <sys/types.h> 3*219b2ee8SDavid du Colombier #include <unistd.h> 4*219b2ee8SDavid du Colombier #include <stdlib.h> 5*219b2ee8SDavid du Colombier #include <stdio.h> 6*219b2ee8SDavid du Colombier #include <errno.h> 7*219b2ee8SDavid du Colombier #include <string.h> 8*219b2ee8SDavid du Colombier #include <fcntl.h> 9*219b2ee8SDavid du Colombier #include <sys/stat.h> 10*219b2ee8SDavid du Colombier 11*219b2ee8SDavid du Colombier /* bsd extensions */ 12*219b2ee8SDavid du Colombier #include <sys/uio.h> 13*219b2ee8SDavid du Colombier #include <sys/socket.h> 14*219b2ee8SDavid du Colombier 15*219b2ee8SDavid du Colombier #include "priv.h" 16*219b2ee8SDavid du Colombier 17*219b2ee8SDavid du Colombier Rock *_sock_rock; 18*219b2ee8SDavid du Colombier 19*219b2ee8SDavid du Colombier Rock* 20*219b2ee8SDavid du Colombier _sock_findrock(int fd, struct stat *dp) 21*219b2ee8SDavid du Colombier { 22*219b2ee8SDavid du Colombier Rock *r; 23*219b2ee8SDavid du Colombier struct stat d; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier if(dp == 0) 26*219b2ee8SDavid du Colombier dp = &d; 27*219b2ee8SDavid du Colombier fstat(fd, dp); 28*219b2ee8SDavid du Colombier for(r = _sock_rock; r; r = r->next){ 29*219b2ee8SDavid du Colombier if(r->inode == dp->st_ino 30*219b2ee8SDavid du Colombier && r->dev == dp->st_dev) 31*219b2ee8SDavid du Colombier break; 32*219b2ee8SDavid du Colombier } 33*219b2ee8SDavid du Colombier return r; 34*219b2ee8SDavid du Colombier } 35*219b2ee8SDavid du Colombier 36*219b2ee8SDavid du Colombier Rock* 37*219b2ee8SDavid du Colombier _sock_newrock(int fd) 38*219b2ee8SDavid du Colombier { 39*219b2ee8SDavid du Colombier Rock *r; 40*219b2ee8SDavid du Colombier struct stat d; 41*219b2ee8SDavid du Colombier 42*219b2ee8SDavid du Colombier r = _sock_findrock(fd, &d); 43*219b2ee8SDavid du Colombier if(r == 0){ 44*219b2ee8SDavid du Colombier r = malloc(sizeof(Rock)); 45*219b2ee8SDavid du Colombier if(r == 0) 46*219b2ee8SDavid du Colombier return 0; 47*219b2ee8SDavid du Colombier r->dev = d.st_dev; 48*219b2ee8SDavid du Colombier r->inode = d.st_ino; 49*219b2ee8SDavid du Colombier r->other = -1; 50*219b2ee8SDavid du Colombier r->next = _sock_rock; 51*219b2ee8SDavid du Colombier _sock_rock = r; 52*219b2ee8SDavid du Colombier } 53*219b2ee8SDavid du Colombier memset(&r->raddr, 0, sizeof(r->raddr)); 54*219b2ee8SDavid du Colombier memset(&r->addr, 0, sizeof(r->addr)); 55*219b2ee8SDavid du Colombier r->reserved = 0; 56*219b2ee8SDavid du Colombier r->dev = d.st_dev; 57*219b2ee8SDavid du Colombier r->inode = d.st_ino; 58*219b2ee8SDavid du Colombier r->other = -1; 59*219b2ee8SDavid du Colombier return r; 60*219b2ee8SDavid du Colombier } 61*219b2ee8SDavid du Colombier 62*219b2ee8SDavid du Colombier int 63*219b2ee8SDavid du Colombier _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp) 64*219b2ee8SDavid du Colombier { 65*219b2ee8SDavid du Colombier int n, fd; 66*219b2ee8SDavid du Colombier Rock *r; 67*219b2ee8SDavid du Colombier char name[Ctlsize]; 68*219b2ee8SDavid du Colombier 69*219b2ee8SDavid du Colombier /* get the data file name */ 70*219b2ee8SDavid du Colombier n = read(cfd, name, sizeof(name)-1); 71*219b2ee8SDavid du Colombier if(n < 0){ 72*219b2ee8SDavid du Colombier close(cfd); 73*219b2ee8SDavid du Colombier errno = ENOBUFS; 74*219b2ee8SDavid du Colombier return -1; 75*219b2ee8SDavid du Colombier } 76*219b2ee8SDavid du Colombier name[n] = 0; 77*219b2ee8SDavid du Colombier n = strtoul(name, 0, 0); 78*219b2ee8SDavid du Colombier sprintf(name, "/net/%s/%d/data", net, n); 79*219b2ee8SDavid du Colombier 80*219b2ee8SDavid du Colombier /* open data file */ 81*219b2ee8SDavid du Colombier fd = open(name, O_RDWR); 82*219b2ee8SDavid du Colombier close(cfd); 83*219b2ee8SDavid du Colombier if(fd < 0){ 84*219b2ee8SDavid du Colombier close(cfd); 85*219b2ee8SDavid du Colombier errno = ENOBUFS; 86*219b2ee8SDavid du Colombier return -1; 87*219b2ee8SDavid du Colombier } 88*219b2ee8SDavid du Colombier 89*219b2ee8SDavid du Colombier /* hide stuff under the rock */ 90*219b2ee8SDavid du Colombier sprintf(name, "/net/%s/%d/ctl", net, n); 91*219b2ee8SDavid du Colombier r = _sock_newrock(fd); 92*219b2ee8SDavid du Colombier if(r == 0){ 93*219b2ee8SDavid du Colombier errno = ENOBUFS; 94*219b2ee8SDavid du Colombier close(fd); 95*219b2ee8SDavid du Colombier return -1; 96*219b2ee8SDavid du Colombier } 97*219b2ee8SDavid du Colombier if(rp) 98*219b2ee8SDavid du Colombier *rp = r; 99*219b2ee8SDavid du Colombier memset(&r->raddr, 0, sizeof(r->raddr)); 100*219b2ee8SDavid du Colombier memset(&r->addr, 0, sizeof(r->addr)); 101*219b2ee8SDavid du Colombier r->domain = domain; 102*219b2ee8SDavid du Colombier r->stype = stype; 103*219b2ee8SDavid du Colombier r->protocol = protocol; 104*219b2ee8SDavid du Colombier strcpy(r->ctl, name); 105*219b2ee8SDavid du Colombier return fd; 106*219b2ee8SDavid du Colombier } 107*219b2ee8SDavid du Colombier 108*219b2ee8SDavid du Colombier int 109*219b2ee8SDavid du Colombier socket(int domain, int stype, int protocol) 110*219b2ee8SDavid du Colombier { 111*219b2ee8SDavid du Colombier Rock *r; 112*219b2ee8SDavid du Colombier int cfd, fd, n; 113*219b2ee8SDavid du Colombier int pfd[2]; 114*219b2ee8SDavid du Colombier char *net; 115*219b2ee8SDavid du Colombier 116*219b2ee8SDavid du Colombier switch(domain){ 117*219b2ee8SDavid du Colombier case PF_INET: 118*219b2ee8SDavid du Colombier /* get a free network directory */ 119*219b2ee8SDavid du Colombier switch(stype){ 120*219b2ee8SDavid du Colombier case SOCK_DGRAM: 121*219b2ee8SDavid du Colombier net = "udp"; 122*219b2ee8SDavid du Colombier cfd = open("/net/udp/clone", O_RDWR); 123*219b2ee8SDavid du Colombier break; 124*219b2ee8SDavid du Colombier case SOCK_STREAM: 125*219b2ee8SDavid du Colombier net = "tcp"; 126*219b2ee8SDavid du Colombier cfd = open("/net/tcp/clone", O_RDWR); 127*219b2ee8SDavid du Colombier break; 128*219b2ee8SDavid du Colombier default: 129*219b2ee8SDavid du Colombier errno = EPROTONOSUPPORT; 130*219b2ee8SDavid du Colombier return -1; 131*219b2ee8SDavid du Colombier } 132*219b2ee8SDavid du Colombier if(cfd < 0){ 133*219b2ee8SDavid du Colombier _syserrno(); 134*219b2ee8SDavid du Colombier return -1; 135*219b2ee8SDavid du Colombier } 136*219b2ee8SDavid du Colombier return _sock_data(cfd, net, domain, stype, protocol, 0); 137*219b2ee8SDavid du Colombier case PF_UNIX: 138*219b2ee8SDavid du Colombier if(pipe(pfd) < 0){ 139*219b2ee8SDavid du Colombier _syserrno(); 140*219b2ee8SDavid du Colombier return -1; 141*219b2ee8SDavid du Colombier } 142*219b2ee8SDavid du Colombier r = _sock_newrock(pfd[0]); 143*219b2ee8SDavid du Colombier r->domain = domain; 144*219b2ee8SDavid du Colombier r->stype = stype; 145*219b2ee8SDavid du Colombier r->protocol = protocol; 146*219b2ee8SDavid du Colombier r->other = pfd[1]; 147*219b2ee8SDavid du Colombier return pfd[0]; 148*219b2ee8SDavid du Colombier default: 149*219b2ee8SDavid du Colombier errno = EPROTONOSUPPORT; 150*219b2ee8SDavid du Colombier return -1; 151*219b2ee8SDavid du Colombier } 152*219b2ee8SDavid du Colombier } 153*219b2ee8SDavid du Colombier 154*219b2ee8SDavid du Colombier int 155*219b2ee8SDavid du Colombier issocket(int fd) 156*219b2ee8SDavid du Colombier { 157*219b2ee8SDavid du Colombier Rock *r; 158*219b2ee8SDavid du Colombier 159*219b2ee8SDavid du Colombier r = _sock_findrock(fd, 0); 160*219b2ee8SDavid du Colombier return (r != 0); 161*219b2ee8SDavid du Colombier } 162