move-fd.c (3258B)
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20#include "config.h" 21#include "move-fd.h" 22 23/* Required for CMSG_* macros on BSD */ 24#define __BSD_VISIBLE 1 25 26#include <errno.h> 27#include <fcntl.h> 28#include <string.h> 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <sys/wait.h> 32#include <unistd.h> 33 34int guacd_send_fd(int sock, int fd) { 35 36 struct msghdr message = {0}; 37 char message_data[] = {'G'}; 38 39 /* Assign data buffer */ 40 struct iovec io_vector[1]; 41 io_vector[0].iov_base = message_data; 42 io_vector[0].iov_len = sizeof(message_data); 43 message.msg_iov = io_vector; 44 message.msg_iovlen = 1; 45 46 /* Assign ancillary data buffer */ 47 char buffer[CMSG_SPACE(sizeof(fd))] = {0}; 48 message.msg_control = buffer; 49 message.msg_controllen = sizeof(buffer); 50 51 /* Set fields of control message header */ 52 struct cmsghdr* control = CMSG_FIRSTHDR(&message); 53 control->cmsg_level = SOL_SOCKET; 54 control->cmsg_type = SCM_RIGHTS; 55 control->cmsg_len = CMSG_LEN(sizeof(fd)); 56 57 /* Add file descriptor to message data */ 58 memcpy(CMSG_DATA(control), &fd, sizeof(fd)); 59 60 /* Send file descriptor */ 61 return (sendmsg(sock, &message, 0) == sizeof(message_data)); 62 63} 64 65int guacd_recv_fd(int sock) { 66 67 int fd; 68 69 struct msghdr message = {0}; 70 char message_data[1]; 71 72 /* Assign data buffer */ 73 struct iovec io_vector[1]; 74 io_vector[0].iov_base = message_data; 75 io_vector[0].iov_len = sizeof(message_data); 76 message.msg_iov = io_vector; 77 message.msg_iovlen = 1; 78 79 80 /* Assign ancillary data buffer */ 81 char buffer[CMSG_SPACE(sizeof(fd))]; 82 message.msg_control = buffer; 83 message.msg_controllen = sizeof(buffer); 84 85 /* Receive file descriptor */ 86 if (recvmsg(sock, &message, 0) == sizeof(message_data)) { 87 88 /* Validate payload */ 89 if (message_data[0] != 'G') { 90 errno = EPROTO; 91 return -1; 92 } 93 94 /* Iterate control headers, looking for the sent file descriptor */ 95 struct cmsghdr* control; 96 for (control = CMSG_FIRSTHDR(&message); control != NULL; control = CMSG_NXTHDR(&message, control)) { 97 98 /* Pull file descriptor from data */ 99 if (control->cmsg_level == SOL_SOCKET && control->cmsg_type == SCM_RIGHTS) { 100 memcpy(&fd, CMSG_DATA(control), sizeof(fd)); 101 return fd; 102 } 103 104 } 105 106 } /* end if recvmsg() success */ 107 108 /* Failed to receive file descriptor */ 109 return -1; 110 111} 112