[PATCH 2/2] Adds some resolv functionality (XCC)
[akaros.git] / user / bsd / connect.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 /* posix */
10 #include <sys/types.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <string.h>
16 #include <errno.h>
17
18 /* bsd extensions */
19 #include <sys/uio.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <sys/un.h>
23 #include <arpa/inet.h>
24
25 #include "priv.h"
26
27 int connect (int fd, __CONST_SOCKADDR_ARG a, socklen_t alen)
28 {
29         Rock *r;
30         int n, cfd, nfd;
31         char msg[8+256+1], file[8+256+1];
32         struct sockaddr_in *lip, *rip;
33         struct sockaddr_un *runix;
34         static int vers;
35
36         r = _sock_findrock(fd, 0);
37         if(r == 0){
38                 errno = ENOTSOCK;
39                 return -1;
40         }
41         if(alen > sizeof(r->raddr)){
42                 errno = ENAMETOOLONG;
43                 return -1;
44         }
45         memmove(&r->raddr, a, alen);
46
47         switch(r->domain){
48         case PF_INET:
49                 /* UDP sockets are already announced (during bind), so we can't issue
50                  * a connect message.  Either connect or announce, not both.  All sends
51                  * will later do a sendto, based off the contents of r->raddr, so we're
52                  * already done here */
53                 if (r->stype == SOCK_DGRAM)
54                         return 0;
55                 /* set up a tcp or udp connection */
56                 cfd = open(r->ctl, O_RDWR);
57                 if(cfd < 0){
58                         return -1;
59                 }
60                 /* whatever .. */
61                 rip = (void *)a;
62                 lip = (struct sockaddr_in*)&r->addr;
63                 if(lip->sin_port)
64                         snprintf(msg, sizeof msg, "connect %s!%d%s %d",
65                                 inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
66                                 r->reserved ? "!r" : "",
67                                 ntohs(lip->sin_port));
68                 else
69                         snprintf(msg, sizeof msg, "connect %s!%d%s",
70                                 inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
71                                 r->reserved ? "!r" : "");
72                 n = write(cfd, msg, strlen(msg));
73                 if(n < 0){
74                         close(cfd);
75                         return -1;
76                 }
77                 close(cfd);
78                 return 0;
79         case PF_UNIX:
80                 /* null terminate the address */
81                 if(alen == sizeof(r->raddr))
82                         alen--;
83                 *(((char*)&r->raddr)+alen) = 0;
84
85                 if(r->other < 0){
86                         errno = EINVAL; //EGREG;
87                         return -1;
88                 }
89
90                 /* put far end of our pipe in /srv */
91                 snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
92                 if(_sock_srv(msg, r->other) < 0){
93                         r->other = -1;
94                         return -1;
95                 }
96                 r->other = -1;
97
98                 /* tell server the /srv file to open */
99                 runix = (struct sockaddr_un*)&r->raddr;
100                 _sock_srvname(file, runix->sun_path);
101                 nfd = open(file, O_RDWR);
102                 if(nfd < 0){
103                         unlink(msg);
104                         return -1;
105                 }
106                 if(write(nfd, msg, strlen(msg)) < 0){
107                         close(nfd);
108                         unlink(msg);
109                         return -1;
110                 }
111                 close(nfd);
112
113                 /* wait for server to open it and then remove it */
114                 read(fd, file, sizeof(file));
115                 _sock_srvname(file, msg);
116                 unlink(file);
117                 return 0;
118         default:
119                 errno = EAFNOSUPPORT;
120                 return -1;
121         }
122 }