connect.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /* posix */
  2. #include <sys/types.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <fcntl.h>
  7. #include <string.h>
  8. #include <errno.h>
  9. /* bsd extensions */
  10. #include <sys/uio.h>
  11. #include <sys/socket.h>
  12. #include <netinet/in.h>
  13. #include <sys/un.h>
  14. #include "priv.h"
  15. int
  16. connect(int fd, void *a, int alen)
  17. {
  18. Rock *r;
  19. int n, cfd, nfd;
  20. char msg[8+256+1], file[8+256+1];
  21. struct sockaddr_in *lip, *rip;
  22. struct sockaddr_un *runix;
  23. static int vers;
  24. r = _sock_findrock(fd, 0);
  25. if(r == 0){
  26. errno = ENOTSOCK;
  27. return -1;
  28. }
  29. if(alen > sizeof(r->raddr)){
  30. errno = ENAMETOOLONG;
  31. return -1;
  32. }
  33. memmove(&r->raddr, a, alen);
  34. switch(r->domain){
  35. case PF_INET:
  36. /* set up a tcp or udp connection */
  37. cfd = open(r->ctl, O_RDWR);
  38. if(cfd < 0){
  39. _syserrno();
  40. return -1;
  41. }
  42. rip = a;
  43. lip = (struct sockaddr_in*)&r->addr;
  44. if(lip->sin_port)
  45. snprintf(msg, sizeof msg, "connect %s!%d%s %d",
  46. inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
  47. r->reserved ? "!r" : "",
  48. ntohs(lip->sin_port));
  49. else
  50. snprintf(msg, sizeof msg, "connect %s!%d%s",
  51. inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
  52. r->reserved ? "!r" : "");
  53. n = write(cfd, msg, strlen(msg));
  54. if(n < 0){
  55. _syserrno();
  56. close(cfd);
  57. return -1;
  58. }
  59. close(cfd);
  60. return 0;
  61. case PF_UNIX:
  62. /* null terminate the address */
  63. if(alen == sizeof(r->raddr))
  64. alen--;
  65. *(((char*)&r->raddr)+alen) = 0;
  66. if(r->other < 0){
  67. errno = EGREG;
  68. return -1;
  69. }
  70. /* put far end of our pipe in /srv */
  71. snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
  72. if(_sock_srv(msg, r->other) < 0){
  73. r->other = -1;
  74. return -1;
  75. }
  76. r->other = -1;
  77. /* tell server the /srv file to open */
  78. runix = (struct sockaddr_un*)&r->raddr;
  79. _sock_srvname(file, runix->sun_path);
  80. nfd = open(file, O_RDWR);
  81. if(nfd < 0){
  82. _syserrno();
  83. unlink(msg);
  84. return -1;
  85. }
  86. if(write(nfd, msg, strlen(msg)) < 0){
  87. _syserrno();
  88. close(nfd);
  89. unlink(msg);
  90. return -1;
  91. }
  92. close(nfd);
  93. /* wait for server to open it and then remove it */
  94. read(fd, file, sizeof(file));
  95. _sock_srvname(file, msg);
  96. unlink(file);
  97. return 0;
  98. default:
  99. errno = EAFNOSUPPORT;
  100. return -1;
  101. }
  102. }