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