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> 15219b2ee8SDavid du Colombier 16219b2ee8SDavid du Colombier #include "priv.h" 17219b2ee8SDavid du Colombier 18219b2ee8SDavid du Colombier int 19219b2ee8SDavid du Colombier connect(int fd, void *a, int alen) 20219b2ee8SDavid du Colombier { 21219b2ee8SDavid du Colombier Rock *r; 22219b2ee8SDavid du Colombier int n, cfd, nfd; 23219b2ee8SDavid du Colombier char msg[128]; 24219b2ee8SDavid du Colombier char file[128]; 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) 51219b2ee8SDavid du Colombier sprintf(msg, "connect %s!%d%s %d", 52*7dd7cddfSDavid du Colombier inet_ntoa(rip->sin_addr), ntohs(rip->sin_port), 53219b2ee8SDavid du Colombier r->reserved ? "!r" : "", 54*7dd7cddfSDavid du Colombier ntohs(lip->sin_port)); 55219b2ee8SDavid du Colombier else 56219b2ee8SDavid du Colombier sprintf(msg, "connect %s!%d%s", inet_ntoa(rip->sin_addr), 57*7dd7cddfSDavid du Colombier 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 */ 79219b2ee8SDavid du Colombier sprintf(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