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