xref: /plan9-contrib/sys/src/ape/lib/bsd/connect.c (revision 781103c4074deb8af160e8a0da2742ba6b29dc2b)
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