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 <errno.h>
8219b2ee8SDavid du Colombier #include <string.h>
9*6ca6a3e7SDavid du Colombier #include <sys/stat.h>
10219b2ee8SDavid du Colombier
11219b2ee8SDavid du Colombier /* bsd extensions */
12219b2ee8SDavid du Colombier #include <sys/uio.h>
13219b2ee8SDavid du Colombier #include <sys/socket.h>
14219b2ee8SDavid du Colombier #include <netinet/in.h>
15219b2ee8SDavid du Colombier #include <sys/un.h>
16219b2ee8SDavid du Colombier
17219b2ee8SDavid du Colombier #include "priv.h"
18219b2ee8SDavid du Colombier
19219b2ee8SDavid du Colombier int
accept(int fd,void * a,int * alen)20219b2ee8SDavid du Colombier accept(int fd, void *a, int *alen)
21219b2ee8SDavid du Colombier {
22219b2ee8SDavid du Colombier int n, nfd, cfd;
23219b2ee8SDavid du Colombier Rock *r, *nr;
24219b2ee8SDavid du Colombier struct sockaddr_in *ip;
25219b2ee8SDavid du Colombier char name[Ctlsize];
267e125112SDavid du Colombier char file[8+Ctlsize+1];
27781103c4SDavid du Colombier char *net;
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
35219b2ee8SDavid du Colombier switch(r->domain){
36219b2ee8SDavid du Colombier case PF_INET:
37219b2ee8SDavid du Colombier switch(r->stype){
38219b2ee8SDavid du Colombier case SOCK_DGRAM:
39219b2ee8SDavid du Colombier net = "udp";
40219b2ee8SDavid du Colombier break;
41219b2ee8SDavid du Colombier case SOCK_STREAM:
42219b2ee8SDavid du Colombier net = "tcp";
43219b2ee8SDavid du Colombier break;
44781103c4SDavid du Colombier default:
45781103c4SDavid du Colombier net = "gok";
46781103c4SDavid du Colombier break;
47219b2ee8SDavid du Colombier }
48219b2ee8SDavid du Colombier
49219b2ee8SDavid du Colombier /* get control file name from listener process */
50219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name)-1);
51219b2ee8SDavid du Colombier if(n <= 0){
52219b2ee8SDavid du Colombier _syserrno();
53219b2ee8SDavid du Colombier return -1;
54219b2ee8SDavid du Colombier }
55219b2ee8SDavid du Colombier name[n] = 0;
56219b2ee8SDavid du Colombier cfd = open(name, O_RDWR);
57219b2ee8SDavid du Colombier if(cfd < 0){
58219b2ee8SDavid du Colombier _syserrno();
59219b2ee8SDavid du Colombier return -1;
60219b2ee8SDavid du Colombier }
61219b2ee8SDavid du Colombier
62219b2ee8SDavid du Colombier nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
63219b2ee8SDavid du Colombier if(nfd < 0){
64219b2ee8SDavid du Colombier _syserrno();
65219b2ee8SDavid du Colombier return -1;
66219b2ee8SDavid du Colombier }
67219b2ee8SDavid du Colombier
68219b2ee8SDavid du Colombier if(write(fd, "OK", 2) < 0){
69219b2ee8SDavid du Colombier close(nfd);
70219b2ee8SDavid du Colombier _syserrno();
71219b2ee8SDavid du Colombier return -1;
72219b2ee8SDavid du Colombier }
73219b2ee8SDavid du Colombier
74219b2ee8SDavid du Colombier /* get remote address */
759a747e4fSDavid du Colombier ip = (struct sockaddr_in*)&nr->raddr;
76219b2ee8SDavid du Colombier _sock_ingetaddr(nr, ip, &n, "remote");
77219b2ee8SDavid du Colombier if(a){
78219b2ee8SDavid du Colombier memmove(a, ip, sizeof(struct sockaddr_in));
79219b2ee8SDavid du Colombier *alen = sizeof(struct sockaddr_in);
80219b2ee8SDavid du Colombier }
81219b2ee8SDavid du Colombier
82219b2ee8SDavid du Colombier return nfd;
83219b2ee8SDavid du Colombier case PF_UNIX:
84219b2ee8SDavid du Colombier if(r->other >= 0){
85219b2ee8SDavid du Colombier errno = EGREG;
86219b2ee8SDavid du Colombier return -1;
87219b2ee8SDavid du Colombier }
88219b2ee8SDavid du Colombier
89219b2ee8SDavid du Colombier for(;;){
90219b2ee8SDavid du Colombier /* read path to new connection */
91219b2ee8SDavid du Colombier n = read(fd, name, sizeof(name) - 1);
92219b2ee8SDavid du Colombier if(n < 0)
93219b2ee8SDavid du Colombier return -1;
94219b2ee8SDavid du Colombier if(n == 0)
95219b2ee8SDavid du Colombier continue;
96219b2ee8SDavid du Colombier name[n] = 0;
97219b2ee8SDavid du Colombier
98219b2ee8SDavid du Colombier /* open new connection */
99219b2ee8SDavid du Colombier _sock_srvname(file, name);
100219b2ee8SDavid du Colombier nfd = open(file, O_RDWR);
101219b2ee8SDavid du Colombier if(nfd < 0)
102219b2ee8SDavid du Colombier continue;
103219b2ee8SDavid du Colombier
104219b2ee8SDavid du Colombier /* confirm opening on new connection */
105219b2ee8SDavid du Colombier if(write(nfd, name, strlen(name)) > 0)
106219b2ee8SDavid du Colombier break;
107219b2ee8SDavid du Colombier
108219b2ee8SDavid du Colombier close(nfd);
109219b2ee8SDavid du Colombier }
110219b2ee8SDavid du Colombier
111219b2ee8SDavid du Colombier nr = _sock_newrock(nfd);
112219b2ee8SDavid du Colombier if(nr == 0){
113219b2ee8SDavid du Colombier close(nfd);
114219b2ee8SDavid du Colombier return -1;
115219b2ee8SDavid du Colombier }
116219b2ee8SDavid du Colombier nr->domain = r->domain;
117219b2ee8SDavid du Colombier nr->stype = r->stype;
118219b2ee8SDavid du Colombier nr->protocol = r->protocol;
119219b2ee8SDavid du Colombier
120219b2ee8SDavid du Colombier return nfd;
121219b2ee8SDavid du Colombier default:
122219b2ee8SDavid du Colombier errno = EOPNOTSUPP;
123219b2ee8SDavid du Colombier return -1;
124219b2ee8SDavid du Colombier }
125219b2ee8SDavid du Colombier }
126