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