socket.c 2.8 KB

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