Home | History | Annotate | Download | only in socket_utils
      1 /*
      2  * Copyright 2006, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <netinet/in.h>
     19 #include <stddef.h>
     20 #include <stdlib.h>
     21 #include <string.h>
     22 #include <sys/select.h>
     23 #include <sys/socket.h>
     24 #include <sys/types.h>
     25 #include <sys/un.h>
     26 #include <unistd.h>
     27 
     28 #include "osi/include/socket_utils/socket_local.h"
     29 #include "osi/include/socket_utils/sockets.h"
     30 
     31 #define LISTEN_BACKLOG 4
     32 
     33 /* Only the bottom bits are really the socket type; there are flags too. */
     34 #define SOCK_TYPE_MASK 0xf
     35 
     36 /**
     37  * Binds a pre-created socket(AF_LOCAL) 's' to 'name'
     38  * returns 's' on success, -1 on fail
     39  *
     40  * Does not call listen()
     41  */
     42 int osi_socket_local_server_bind(int s, const char* name, int namespaceId) {
     43   struct sockaddr_un addr;
     44   socklen_t alen;
     45   int n;
     46   int err;
     47 
     48   err = osi_socket_make_sockaddr_un(name, namespaceId, &addr, &alen);
     49 
     50   if (err < 0) {
     51     return -1;
     52   }
     53 
     54 /* basically: if this is a filesystem path, unlink first */
     55 #if !defined(__linux__)
     56   if (1) {
     57 #else
     58   if (namespaceId == ANDROID_SOCKET_NAMESPACE_RESERVED ||
     59       namespaceId == ANDROID_SOCKET_NAMESPACE_FILESYSTEM) {
     60 #endif
     61     /*ignore ENOENT*/
     62     unlink(addr.sun_path);
     63   }
     64 
     65   n = 1;
     66   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n));
     67 
     68   if (bind(s, (struct sockaddr*)&addr, alen) < 0) {
     69     return -1;
     70   }
     71 
     72   return s;
     73 }
     74 
     75 /** Open a server-side UNIX domain datagram socket in the Linux non-filesystem
     76  *  namespace
     77  *
     78  *  Returns fd on success, -1 on fail
     79  */
     80 int osi_socket_local_server(const char* name, int namespaceId, int type) {
     81   int err;
     82   int s;
     83 
     84   s = socket(AF_LOCAL, type, 0);
     85   if (s < 0) return -1;
     86 
     87   err = osi_socket_local_server_bind(s, name, namespaceId);
     88 
     89   if (err < 0) {
     90     close(s);
     91     return -1;
     92   }
     93 
     94   if ((type & SOCK_TYPE_MASK) == SOCK_STREAM) {
     95     int ret;
     96 
     97     ret = listen(s, LISTEN_BACKLOG);
     98 
     99     if (ret < 0) {
    100       close(s);
    101       return -1;
    102     }
    103   }
    104 
    105   return s;
    106 }
    107