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