akaros/tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/socket.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 <errno.h>
  15#include <string.h>
  16#include <fcntl.h>
  17#include <sys/stat.h>
  18#include <sys/close_cb.h>
  19#include <ros/common.h>
  20#include <parlib/parlib.h>
  21
  22/* bsd extensions */
  23#include <sys/uio.h>
  24#include <sys/socket.h>
  25#include <netinet/in.h>
  26
  27#include <sys/plan9_helpers.h>
  28
  29static void socket_init(void *arg)
  30{
  31        static struct close_cb _sock_close_cb = {.func = _sock_fd_closed};
  32
  33        register_close_cb(&_sock_close_cb);
  34}
  35
  36/* Create a new socket of type TYPE in domain DOMAIN, using
  37   protocol PROTOCOL.  If PROTOCOL is zero, one is chosen automatically.
  38   Returns a file descriptor for the new socket, or -1 for errors.  */
  39int __socket(int domain, int type, int protocol)
  40{
  41        Rock *r;
  42        int cfd, n;
  43        int pfd[2];
  44        const char *net;
  45        char msg[128];
  46        int open_flags;
  47        static parlib_once_t once = PARLIB_ONCE_INIT;
  48
  49        parlib_run_once(&once, socket_init, NULL);
  50
  51        switch (domain) {
  52        case PF_INET:
  53                open_flags = O_RDWR;
  54                open_flags |= (type & SOCK_CLOEXEC ? O_CLOEXEC : 0);
  55                /* get a free network directory */
  56                switch (_sock_strip_opts(type)) {
  57                case SOCK_DGRAM:
  58                        net = "udp";
  59                        cfd = open("/net/udp/clone", open_flags);
  60                        /* All BSD UDP sockets are in 'headers' mode, where each
  61                         * packet has the remote addr:port, local addr:port and
  62                         * other info. */
  63                        if (!(cfd < 0)) {
  64                                n = snprintf(msg, sizeof(msg), "headers");
  65                                n = write(cfd, msg, n);
  66                                if (n < 0) {
  67                                        perror("UDP socket headers failed");
  68                                        return -1;
  69                                }
  70                                if (lseek(cfd, 0, SEEK_SET) != 0) {
  71                                        perror("UDP socket seek failed");
  72                                        return -1;
  73                                }
  74                        }
  75                        break;
  76                case SOCK_STREAM:
  77                        net = "tcp";
  78                        cfd = open("/net/tcp/clone", open_flags);
  79                        break;
  80                default:
  81                        errno = EPROTONOSUPPORT;
  82                        return -1;
  83                }
  84                if (cfd < 0) {
  85                        return -1;
  86                }
  87                return _sock_data(cfd, net, domain, type, protocol, 0);
  88        case PF_UNIX:
  89                open_flags = 0;
  90                open_flags |= (type & SOCK_CLOEXEC ? O_CLOEXEC : 0);
  91                open_flags |= (type & SOCK_NONBLOCK ? O_CLOEXEC : 0);
  92                if (pipe2(pfd, open_flags) < 0)
  93                        return -1;
  94                r = _sock_newrock(pfd[0]);
  95                r->domain = domain;
  96                r->stype = _sock_strip_opts(type);
  97                r->sopts = _sock_get_opts(type);
  98                r->protocol = protocol;
  99                r->other = pfd[1];
 100                return pfd[0];
 101        default:
 102                errno = EPROTONOSUPPORT;
 103                return -1;
 104        }
 105}
 106
 107weak_alias(__socket, socket)
 108