rootbind.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:5k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * rootbind.c: bind to reserved ports through the root wrapper
  3.  *****************************************************************************
  4.  * Copyright © 2005-2008 Rémi Denis-Courmont
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2 of the License, or
  9.  * (at your option) any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  19.  *****************************************************************************/
  20. #if HAVE_CONFIG_H
  21. # include <config.h>
  22. #endif
  23. #if !defined (WIN32) && !defined (SYS_BEOS)
  24. # define ENABLE_ROOTWRAP 1
  25. #endif
  26. #include <stddef.h>
  27. struct sockaddr;
  28. int rootwrap_bind (int, int, int, const struct sockaddr *, size_t);
  29. #include <errno.h>
  30. #ifdef ENABLE_ROOTWRAP
  31. #include <string.h>
  32. #include <stdlib.h>
  33. #include <sys/types.h>
  34. #include <unistd.h>
  35. #include <sys/socket.h>
  36. #include <sys/uio.h>
  37. #include <sys/un.h>
  38. #include <netinet/in.h>
  39. #include <pthread.h>
  40. /* Required yet non-standard cmsg functions */
  41. #ifndef CMSG_ALIGN
  42. # define CMSG_ALIGN(len) (((len) + sizeof(intptr_t)-1) & ~(sizeof(intptr_t)-1))
  43. #endif
  44. #ifndef CMSG_SPACE
  45. # define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
  46. #endif
  47. #ifndef CMSG_LEN
  48. # define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
  49. #endif
  50. /**
  51.  * Receive a file descriptor from another process
  52.  */
  53. static int recv_fd (int p)
  54. {
  55.     struct msghdr hdr;
  56.     struct iovec iov;
  57.     struct cmsghdr *cmsg;
  58.     int val, fd;
  59.     char buf[CMSG_SPACE (sizeof (fd))];
  60.     hdr.msg_name = NULL;
  61.     hdr.msg_namelen = 0;
  62.     hdr.msg_iov = &iov;
  63.     hdr.msg_iovlen = 1;
  64.     hdr.msg_control = buf;
  65.     hdr.msg_controllen = sizeof (buf);
  66.     iov.iov_base = &val;
  67.     iov.iov_len = sizeof (val);
  68.     if (recvmsg (p, &hdr, 0) != sizeof (val))
  69.         return -1;
  70.     for (cmsg = CMSG_FIRSTHDR (&hdr); cmsg != NULL;
  71.          cmsg = CMSG_NXTHDR (&hdr, cmsg))
  72.     {
  73.         if ((cmsg->cmsg_level == SOL_SOCKET)
  74.          && (cmsg->cmsg_type = SCM_RIGHTS)
  75.          && (cmsg->cmsg_len >= CMSG_LEN (sizeof (fd))))
  76.         {
  77.             memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd));
  78.             return fd;
  79.         }
  80.     }
  81.     errno = val;
  82.     return -1;
  83. }
  84. /**
  85.  * Tries to obtain a bound TCP socket from the root process
  86.  */
  87. int rootwrap_bind (int family, int socktype, int protocol,
  88.                    const struct sockaddr *addr, size_t alen)
  89. {
  90.     /* can't use libvlc */
  91.     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  92.     struct sockaddr_storage ss;
  93.     int fd, sock = -1;
  94.     const char *sockenv = getenv ("VLC_ROOTWRAP_SOCK");
  95.     if (sockenv != NULL)
  96.         sock = atoi (sockenv);
  97.     if (sock == -1)
  98.     {
  99.         errno = EACCES;
  100.         return -1;
  101.     }
  102.     switch (family)
  103.     {
  104.         case AF_INET:
  105.             if (alen < sizeof (struct sockaddr_in))
  106.             {
  107.                 errno = EINVAL;
  108.                 return -1;
  109.             }
  110.             break;
  111. #ifdef AF_INET6
  112.         case AF_INET6:
  113.             if (alen < sizeof (struct sockaddr_in6))
  114.             {
  115.                 errno = EINVAL;
  116.                 return -1;
  117.             }
  118.             break;
  119. #endif
  120.         default:
  121.             errno = EAFNOSUPPORT;
  122.             return -1;
  123.     }
  124.     if (family != addr->sa_family)
  125.     {
  126.         errno = EAFNOSUPPORT;
  127.         return -1;
  128.     }
  129.     /* Only TCP is implemented at the moment */
  130.     if ((socktype != SOCK_STREAM)
  131.      || (protocol && (protocol != IPPROTO_TCP)))
  132.     {
  133.         errno = EACCES;
  134.         return -1;
  135.     }
  136.     memset (&ss, 0, sizeof (ss));
  137.     memcpy (&ss, addr, (alen > sizeof (ss)) ? sizeof (ss) : alen);
  138.     pthread_mutex_lock (&mutex);
  139.     if (send (sock, &ss, sizeof (ss), 0) != sizeof (ss))
  140.         return -1;
  141.     fd = recv_fd (sock);
  142.     pthread_mutex_unlock (&mutex);
  143.     return fd;
  144. }
  145. #else
  146. int rootwrap_bind (int family, int socktype, int protocol,
  147.                    const struct sockaddr *addr, size_t alen)
  148. {
  149.     (void)family;
  150.     (void)socktype;
  151.     (void)protocol;
  152.     (void)addr;
  153.     (void)alen;
  154.     errno = EACCES;
  155.     return -1;
  156. }
  157. #endif /* ENABLE_ROOTWRAP */