akaros/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/connect.c
<<
>>
Prefs
   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 <sys/plan9_helpers.h>
  26
  27/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
  28   For connectionless socket types, just set the default address to send to
  29   and the only address from which to accept transmissions.
  30   Return 0 on success, -1 for errors.  */
  31int __connect(int fd, __CONST_SOCKADDR_ARG addr, socklen_t alen)
  32{
  33        Rock *r;
  34        int n, nfd;
  35        char msg[8 + 256 + 1], file[8 + 256 + 1];
  36        struct sockaddr_in *lip, *rip;
  37        struct sockaddr_un *runix;
  38        static int vers;
  39        int open_flags;
  40
  41        r = _sock_findrock(fd, 0);
  42        if (r == 0) {
  43                errno = ENOTSOCK;
  44                return -1;
  45        }
  46        if (alen > sizeof(r->raddr_stor)) {
  47                errno = ENAMETOOLONG;
  48                return -1;
  49        }
  50        memmove(&r->raddr, addr.__sockaddr__, alen);
  51
  52        switch (r->domain) {
  53        case PF_INET:
  54                /* UDP sockets are already announced (during bind), so we can't
  55                 * issue a connect message.  Either connect or announce, not
  56                 * both.  All sends will later do a sendto, based off the
  57                 * contents of r->raddr, so we're already done here */
  58                if (r->stype == SOCK_DGRAM)
  59                        return 0;
  60                /* whatever .. */
  61                rip = (struct sockaddr_in *)addr.__sockaddr_in__;
  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" : "", ntohs(lip->sin_port));
  67                else
  68                        snprintf(msg, sizeof msg, "connect %s!%d%s",
  69                                 inet_ntoa(rip->sin_addr), ntohs(rip->sin_port),
  70                                 r->reserved ? "!r" : "");
  71                n = write(r->ctl_fd, msg, strlen(msg));
  72                if (n < 0)
  73                        return -1;
  74                return 0;
  75        case PF_UNIX:
  76                /* null terminate the address */
  77                if (alen == sizeof(r->raddr))
  78                        alen--;
  79                *(((char *)&r->raddr) + alen) = 0;
  80
  81                if (r->other < 0) {
  82                        errno = EINVAL; //EGREG;
  83                        return -1;
  84                }
  85
  86                /* put far end of our pipe in /srv */
  87                snprintf(msg, sizeof msg, "UD.%d.%d", getpid(), vers++);
  88                if (_sock_srv(msg, r->other) < 0) {
  89                        r->other = -1;
  90                        return -1;
  91                }
  92                r->other = -1;
  93
  94                /* tell server the /srv file to open */
  95                runix = (struct sockaddr_un *)&r->raddr;
  96                _sock_srvname(file, runix->sun_path);
  97                open_flags = O_RDWR;
  98                open_flags |= (r->sopts & SOCK_CLOEXEC ? O_CLOEXEC : 0);
  99                nfd = open(file, open_flags);
 100                if (nfd < 0) {
 101                        unlink(msg);
 102                        return -1;
 103                }
 104                if (write(nfd, msg, strlen(msg)) < 0) {
 105                        close(nfd);
 106                        unlink(msg);
 107                        return -1;
 108                }
 109                close(nfd);
 110
 111                /* wait for server to open it and then remove it */
 112                read(fd, file, sizeof(file));
 113                _sock_srvname(file, msg);
 114                unlink(file);
 115                return 0;
 116        default:
 117                errno = EAFNOSUPPORT;
 118                return -1;
 119        }
 120}
 121weak_alias(__connect, connect)
 122libc_hidden_def(__connect)
 123