VirtualBox

source: vbox/trunk/src/VBox/NetworkServices/NAT/getrawsock.c@ 78034

Last change on this file since 78034 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 3.6 KB
Line 
1/* $Id: getrawsock.c 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * Obtain raw-sockets from a server when debugging unprivileged.
4 */
5
6/*
7 * Copyright (C) 2013-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include <sys/types.h>
19#include <sys/socket.h>
20#include <sys/un.h>
21#include <netinet/in.h>
22#include <errno.h>
23#include <pwd.h>
24#include <signal.h>
25#include <stdio.h>
26#include <string.h>
27#include <unistd.h>
28
29/* XXX: this should be in a header, but isn't. naughty me. :( */
30int getrawsock(int type);
31
32
33int
34getrawsock(int type)
35{
36 struct sockaddr_un sux; /* because solaris */
37 struct passwd *pw;
38 size_t pathlen;
39 int rawsock, server;
40 struct msghdr mh;
41 struct iovec iov[1];
42 char buf[1];
43 struct cmsghdr *cmh;
44 char cmsg[CMSG_SPACE(sizeof(int))];
45 ssize_t nread, nsent;
46 int status;
47
48 server = -1;
49 rawsock = -1;
50
51 memset(&sux, 0, sizeof(sux));
52 sux.sun_family = AF_UNIX;
53
54 if (geteuid() == 0) {
55 return -1;
56 }
57
58 if (type == AF_INET) {
59 buf[0] = '4';
60 }
61 else if (type == AF_INET6) {
62 buf[0] = '6';
63 }
64 else {
65 return -1;
66 }
67
68 errno = 0;
69 pw = getpwuid(getuid());
70 if (pw == NULL) {
71 perror("getpwuid");
72 return -1;
73 }
74
75 pathlen = snprintf(sux.sun_path, sizeof(sux.sun_path),
76 "/tmp/.vbox-%s-aux/mkrawsock", pw->pw_name);
77 if (pathlen > sizeof(sux.sun_path)) {
78 fprintf(stderr, "socket pathname truncated\n");
79 return -1;
80 }
81
82 server = socket(PF_UNIX, SOCK_STREAM, 0);
83 if (server < 0) {
84 perror("socket");
85 return -1;
86 }
87
88 status = connect(server, (struct sockaddr *)&sux,
89 (sizeof(sux) - sizeof(sux.sun_path)
90 + strlen(sux.sun_path) + 1));
91 if (status < 0) {
92 perror(sux.sun_path);
93 goto out;
94 }
95
96 nsent = send(server, buf, 1, 0);
97 if (nsent != 1) {
98 if (nsent < 0) {
99 perror("send");
100 }
101 else {
102 fprintf(stderr, "failed to contact mkrawsock\n");
103 }
104 goto out;
105 }
106
107 buf[0] = '\0';
108
109 iov[0].iov_base = buf;
110 iov[0].iov_len = 1;
111
112 memset(&mh, 0, sizeof(mh));
113 mh.msg_iov = iov;
114 mh.msg_iovlen = 1;
115 mh.msg_control = cmsg;
116 mh.msg_controllen = sizeof(cmsg);
117
118 nread = recvmsg(server, &mh, 0);
119 if (nread != 1) {
120 if (nread < 0) {
121 perror("recvmsg");
122 }
123 else {
124 fprintf(stderr, "EOF from mkrawsock\n");
125 }
126 goto out;
127 }
128
129 if ((type == AF_INET && buf[0] != '4')
130 || (type == AF_INET6 && buf[0] != '6')
131 || mh.msg_controllen == 0)
132 {
133 goto out;
134 }
135
136 for (cmh = CMSG_FIRSTHDR(&mh); cmh != NULL; cmh = CMSG_NXTHDR(&mh, cmh)) {
137 if ((cmh->cmsg_level == SOL_SOCKET)
138 && (cmh->cmsg_type == SCM_RIGHTS)
139 && (cmh->cmsg_len == CMSG_LEN(sizeof(rawsock))))
140 {
141 rawsock = *((int *)CMSG_DATA(cmh));
142 break;
143 }
144 }
145
146 out:
147 if (server != -1) {
148 close(server);
149 }
150 if (rawsock != -1) {
151 printf("%s: got ICMPv%c socket %d\n",
152 __func__, type == AF_INET ? '4' : '6', rawsock);
153 }
154 return rawsock;
155}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette