xref: /plan9/sys/src/ape/lib/bsd/connect.c (revision 6ca6a3e703ee2ec4aed99c2177f71d7f127da6d9)
1219b2ee8SDavid du Colombier /* posix */
2219b2ee8SDavid du Colombier #include <sys/types.h>
3219b2ee8SDavid du Colombier #include <unistd.h>
4219b2ee8SDavid du Colombier #include <stdlib.h>
5219b2ee8SDavid du Colombier #include <stdio.h>
6219b2ee8SDavid du Colombier #include <fcntl.h>
7219b2ee8SDavid du Colombier #include <string.h>
8219b2ee8SDavid du Colombier #include <errno.h>
9219b2ee8SDavid du Colombier 
10219b2ee8SDavid du Colombier /* bsd extensions */
11219b2ee8SDavid du Colombier #include <sys/uio.h>
12219b2ee8SDavid du Colombier #include <sys/socket.h>
13219b2ee8SDavid du Colombier #include <netinet/in.h>
14219b2ee8SDavid du Colombier #include <sys/un.h>
15*6ca6a3e7SDavid du Colombier #include <sys/stat.h>
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier #include "priv.h"
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier int
connect(int fd,void * a,int alen)20219b2ee8SDavid du Colombier connect(int fd, void *a, int alen)
21219b2ee8SDavid du Colombier {
22219b2ee8SDavid du Colombier 	Rock *r;
23219b2ee8SDavid du Colombier 	int n, cfd, nfd;
247e125112SDavid du Colombier 	char msg[8+256+1], file[8+256+1];
25219b2ee8SDavid du Colombier 	struct sockaddr_in *lip, *rip;
26219b2ee8SDavid du Colombier 	struct sockaddr_un *runix;
27219b2ee8SDavid du Colombier 	static int vers;
28219b2ee8SDavid du Colombier 
29219b2ee8SDavid du Colombier 	r = _sock_findrock(fd, 0);
30219b2ee8SDavid du Colombier 	if(r == 0){
31219b2ee8SDavid du Colombier 		errno = ENOTSOCK;
32219b2ee8SDavid du Colombier 		return -1;
33219b2ee8SDavid du Colombier 	}
34219b2ee8SDavid du Colombier 	if(alen > sizeof(r->raddr)){
35219b2ee8SDavid du Colombier 		errno = ENAMETOOLONG;
36219b2ee8SDavid du Colombier 		return -1;
37219b2ee8SDavid du Colombier 	}
38219b2ee8SDavid du Colombier 	memmove(&r->raddr, a, alen);
39219b2ee8SDavid du Colombier 
40219b2ee8SDavid du Colombier 	switch(r->domain){
41219b2ee8SDavid du Colombier 	case PF_INET:
42219b2ee8SDavid du Colombier 		/* set up a tcp or udp connection */
43219b2ee8SDavid du Colombier 		cfd = open(r->ctl, O_RDWR);
44219b2ee8SDavid du Colombier 		if(cfd < 0){
45219b2ee8SDavid du Colombier 			_syserrno();
46219b2ee8SDavid du Colombier 			return -1;
47219b2ee8SDavid du Colombier 		}
48219b2ee8SDavid du Colombier 		rip = a;
49219b2ee8SDavid du Colombier 		lip = (struct sockaddr_in*)&r->addr;
50219b2ee8SDavid du Colombier 		if(lip->sin_port)
517e125112SDavid du Colombier 			snprintf(msg, sizeof msg, "connect %s!%d%s %d",
527dd7cddfSDavid du Colombier 				inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
53219b2ee8SDavid du Colombier 				r->reserved ? "!r" : "",
547dd7cddfSDavid du Colombier 				ntohs(lip->sin_port));
55219b2ee8SDavid du Colombier 		else
567e125112SDavid du Colombier 			snprintf(msg, sizeof msg, "connect %s!%d%s",
577e125112SDavid du Colombier 				inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
58219b2ee8SDavid du Colombier 				r->reserved ? "!r" : "");
59219b2ee8SDavid du Colombier 		n = write(cfd, msg, strlen(msg));
60219b2ee8SDavid du Colombier 		if(n < 0){
61219b2ee8SDavid du Colombier 			_syserrno();
62219b2ee8SDavid du Colombier 			close(cfd);
63219b2ee8SDavid du Colombier 			return -1;
64219b2ee8SDavid du Colombier 		}
65219b2ee8SDavid du Colombier 		close(cfd);
66219b2ee8SDavid du Colombier 		return 0;
67219b2ee8SDavid du Colombier 	case PF_UNIX:
68219b2ee8SDavid du Colombier 		/* null terminate the address */
69219b2ee8SDavid du Colombier 		if(alen == sizeof(r->raddr))
70219b2ee8SDavid du Colombier 			alen--;
71219b2ee8SDavid du Colombier 		*(((char*)&r->raddr)+alen) = 0;
72219b2ee8SDavid du Colombier 
73219b2ee8SDavid du Colombier 		if(r->other < 0){
74219b2ee8SDavid du Colombier 			errno = EGREG;
75219b2ee8SDavid du Colombier 			return -1;
76219b2ee8SDavid du Colombier 		}
77219b2ee8SDavid du Colombier 
78219b2ee8SDavid du Colombier 		/* put far end of our pipe in /srv */
797e125112SDavid du Colombier 		snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
80219b2ee8SDavid du Colombier 		if(_sock_srv(msg, r->other) < 0){
81219b2ee8SDavid du Colombier 			r->other = -1;
82219b2ee8SDavid du Colombier 			return -1;
83219b2ee8SDavid du Colombier 		}
84219b2ee8SDavid du Colombier 		r->other = -1;
85219b2ee8SDavid du Colombier 
86219b2ee8SDavid du Colombier 		/* tell server the /srv file to open */
87219b2ee8SDavid du Colombier 		runix = (struct sockaddr_un*)&r->raddr;
88219b2ee8SDavid du Colombier 		_sock_srvname(file, runix->sun_path);
89219b2ee8SDavid du Colombier 		nfd = open(file, O_RDWR);
90219b2ee8SDavid du Colombier 		if(nfd < 0){
91219b2ee8SDavid du Colombier 			_syserrno();
92219b2ee8SDavid du Colombier 			unlink(msg);
93219b2ee8SDavid du Colombier 			return -1;
94219b2ee8SDavid du Colombier 		}
95219b2ee8SDavid du Colombier 		if(write(nfd, msg, strlen(msg)) < 0){
96219b2ee8SDavid du Colombier 			_syserrno();
97219b2ee8SDavid du Colombier 			close(nfd);
98219b2ee8SDavid du Colombier 			unlink(msg);
99219b2ee8SDavid du Colombier 			return -1;
100219b2ee8SDavid du Colombier 		}
101219b2ee8SDavid du Colombier 		close(nfd);
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier 		/* wait for server to open it and then remove it */
104219b2ee8SDavid du Colombier 		read(fd, file, sizeof(file));
105219b2ee8SDavid du Colombier 		_sock_srvname(file, msg);
106219b2ee8SDavid du Colombier 		unlink(file);
107219b2ee8SDavid du Colombier 		return 0;
108219b2ee8SDavid du Colombier 	default:
109219b2ee8SDavid du Colombier 		errno = EAFNOSUPPORT;
110219b2ee8SDavid du Colombier 		return -1;
111219b2ee8SDavid du Colombier 	}
112219b2ee8SDavid du Colombier }
113