VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageNATNetwork.cpp@ 45733

Last change on this file since 45733 was 45560, checked in by vboxsync, 12 years ago

NAT/LWIP service: nits. (cosmetic).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: VBoxManageNATNetwork.cpp 45560 2013-04-16 08:02:19Z vboxsync $ */
2/** @file
3 * VBoxManage - Implementation of NAT Network command command.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#ifndef VBOX_ONLY_DOCS
22
23
24#include <VBox/com/com.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/EventQueue.h>
29
30#include <VBox/com/VirtualBox.h>
31#endif /* !VBOX_ONLY_DOCS */
32
33#include <netinet/in.h>
34
35#define IPv6
36
37#include <iprt/cdefs.h>
38#include <iprt/cidr.h>
39#include <iprt/param.h>
40#include <iprt/path.h>
41#include <iprt/stream.h>
42#include <iprt/string.h>
43#include <iprt/net.h>
44#include <iprt/getopt.h>
45#include <iprt/ctype.h>
46
47#include <VBox/log.h>
48
49#include <vector>
50
51#include "VBoxManage.h"
52#include "VBoxPortForwardString.h"
53
54#ifndef VBOX_ONLY_DOCS
55
56using namespace com;
57
58typedef enum enMainOpCodes
59{
60 OP_ADD = 1000,
61 OP_REMOVE,
62 OP_MODIFY,
63 OP_START,
64 OP_STOP
65} OPCODE;
66
67static const RTGETOPTDEF g_aNATNetworkIPOptions[]
68 = {
69 { "--netname", 't', RTGETOPT_REQ_STRING },
70 { "--network", 'n', RTGETOPT_REQ_STRING },
71 { "--dhcp", 'h', RTGETOPT_REQ_BOOL },
72 { "--ipv6", '6', RTGETOPT_REQ_BOOL},
73 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
74 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
75 { "--port-forward-4", 'p', RTGETOPT_REQ_STRING },
76 { "--port-forward-6", 'P', RTGETOPT_REQ_STRING },
77 };
78
79typedef struct PFNAME2DELETE
80{
81 char aszName[PF_NAMELEN];
82 bool fIPv6;
83} PFNAME2DELETE, *PPFNAME2DELETE;
84
85typedef std::vector<PFNAME2DELETE> VPF2DELETE;
86typedef VPF2DELETE::const_iterator VPF2DELETEITERATOR;
87
88typedef std::vector<PORTFORWARDRULE> VPF2ADD;
89typedef VPF2ADD::const_iterator VPF2ADDITERATOR;
90
91
92static int handleOp(HandlerArg *a, OPCODE enmCode, int iStart, int *pcProcessed)
93{
94 if (a->argc - iStart < 2)
95 return errorSyntax(USAGE_NATNETWORK, "Not enough parameters");
96
97 int index = iStart;
98 HRESULT rc;
99
100 const char *pNetName = NULL;
101 const char *pNetworkCidr = NULL;
102 int enable = -1;
103 int dhcp = -1;
104 int ipv6 = -1;
105
106 VPF2DELETE vPfName2Delete;
107 VPF2ADD vPf2Add;
108
109 int c;
110 RTGETOPTUNION ValueUnion;
111 RTGETOPTSTATE GetState;
112
113 RTGetOptInit(&GetState,
114 a->argc,
115 a->argv,
116 g_aNATNetworkIPOptions,
117 enmCode != OP_REMOVE ? RT_ELEMENTS(g_aNATNetworkIPOptions) : 4, /* we use only --netname and --ifname for remove*/
118 index,
119 RTGETOPTINIT_FLAGS_NO_STD_OPTS);
120 while ((c = RTGetOpt(&GetState, &ValueUnion)))
121 {
122 switch (c)
123 {
124 case 't': // --netname
125 if (pNetName)
126 return errorSyntax(USAGE_NATNETWORK, "You can only specify --netname once.");
127 else
128 {
129 pNetName = ValueUnion.psz;
130 }
131 break;
132
133 case 'n': // --network
134 if (pNetworkCidr)
135 return errorSyntax(USAGE_NATNETWORK, "You can only specify --network once.");
136 else
137 {
138 pNetworkCidr = ValueUnion.psz;
139 }
140 break;
141
142 case 'e': // --enable
143 if(enable >= 0)
144 return errorSyntax(USAGE_NATNETWORK, "You can specify either --enable or --disable once.");
145 else
146 {
147 enable = 1;
148 }
149 break;
150
151 case 'd': // --disable
152 if (enable >= 0)
153 return errorSyntax(USAGE_NATNETWORK, "You can specify either --enable or --disable once.");
154 else
155 {
156 enable = 0;
157 }
158 break;
159
160 case 'h':
161 if (dhcp != -1)
162 return errorSyntax(USAGE_NATNETWORK, "You can specify --dhcp once.");
163 dhcp = ValueUnion.f;
164 break;
165
166 case '6':
167 if (ipv6 != -1)
168 return errorSyntax(USAGE_NATNETWORK, "You can specify --ipv6 once.");
169 ipv6 = ValueUnion.f;
170 break;
171
172 case 'P': /* ipv6 portforwarding*/
173 case 'p': /* ipv4 portforwarding */
174 {
175 if (RTStrCmp(ValueUnion.psz, "delete") != 0)
176 {
177 PORTFORWARDRULE Pfr;
178
179 /* netPfStrToPf will clean up the Pfr */
180 int irc = netPfStrToPf(ValueUnion.psz, (c == 'P'), &Pfr);
181 if (RT_FAILURE(irc))
182 return errorSyntax(USAGE_NATNETWORK,
183 "Invalid port-forward rule %s\n",
184 ValueUnion.psz);
185
186 vPf2Add.push_back(Pfr);
187 }
188 else
189 {
190 int vrc;
191 RTGETOPTUNION NamePf2DeleteUnion;
192 PFNAME2DELETE Name2Delete;
193
194 if (enmCode != OP_MODIFY)
195 return errorSyntax(USAGE_NATNETWORK,
196 "Port-forward could be deleted on modify \n");
197
198 vrc = RTGetOptFetchValue(&GetState,
199 &NamePf2DeleteUnion,
200 RTGETOPT_REQ_STRING);
201 if (RT_FAILURE(vrc))
202 return errorSyntax(USAGE_NATNETWORK,
203 "Not enough parmaters\n");
204
205 if (strlen(NamePf2DeleteUnion.psz) > PF_NAMELEN)
206 return errorSyntax(USAGE_NATNETWORK,
207 "Port-forward rule name is too long\n");
208
209 RT_ZERO(Name2Delete);
210 RTStrCopy(Name2Delete.aszName,
211 PF_NAMELEN,
212 NamePf2DeleteUnion.psz);
213 Name2Delete.fIPv6 = (c == 'P');
214
215 vPfName2Delete.push_back(Name2Delete);
216 }
217 break;
218 }
219
220 case VINF_GETOPT_NOT_OPTION:
221 return errorSyntax(USAGE_NATNETWORK,
222 "unhandled parameter: %s",
223 ValueUnion.psz);
224 break;
225
226 default:
227 if (c > 0)
228 {
229 if (RT_C_IS_GRAPH(c))
230 return errorSyntax(USAGE_NATNETWORK,
231 "unhandled option: -%c", c);
232 else
233 return errorSyntax(USAGE_NATNETWORK,
234 "unhandled option: %i", c);
235 }
236 else if (c == VERR_GETOPT_UNKNOWN_OPTION)
237 return errorSyntax(USAGE_NATNETWORK,
238 "unknown option: %s", ValueUnion.psz);
239 else if (ValueUnion.pDef)
240 return errorSyntax(USAGE_NATNETWORK,
241 "%s: %Rrs", ValueUnion.pDef->pszLong, c);
242 else
243 return errorSyntax(USAGE_NATNETWORK, "%Rrs", c);
244 }
245 }
246
247 if (!pNetName)
248 return errorSyntax(USAGE_NATNETWORK,
249 "You need to specify --netname option");
250 /* verification */
251 switch (enmCode)
252 {
253 case OP_ADD:
254 if (!pNetworkCidr)
255 return errorSyntax(USAGE_NATNETWORK,
256 "You need to specify --network option");
257 break;
258 case OP_MODIFY:
259 case OP_REMOVE:
260 case OP_START:
261 case OP_STOP:
262 break;
263 default:
264 AssertMsgFailedReturn(("Unknown operation (:%d)", enmCode), VERR_NOT_IMPLEMENTED);
265 }
266
267 Bstr NetName;
268 NetName = Bstr(pNetName);
269
270
271 ComPtr<INATNetwork> net;
272 rc = a->virtualBox->FindNATNetworkByName(NetName.mutableRaw(), net.asOutParam());
273 if(enmCode == OP_ADD)
274 {
275 if (SUCCEEDED(rc))
276 return errorArgument("NATNetwork server already exists");
277
278 CHECK_ERROR(a->virtualBox, CreateNATNetwork(NetName.raw(), net.asOutParam()));
279 if (FAILED(rc))
280 return errorArgument("Failed to create the NAT network service");
281 }
282 else if (FAILED(rc))
283 {
284 return errorArgument("NATNetwork server does not exist");
285 }
286
287 switch (enmCode)
288 {
289 case OP_ADD:
290 case OP_MODIFY:
291 {
292 if (pNetworkCidr)
293 {
294 CHECK_ERROR(net, COMSETTER(Network)(Bstr(pNetworkCidr).raw()));
295 if(FAILED(rc))
296 return errorArgument("Failed to set configuration");
297 }
298 if (dhcp >= 0)
299 {
300 CHECK_ERROR(net, COMSETTER(NeedDhcpServer) ((BOOL)dhcp));
301 if(FAILED(rc))
302 return errorArgument("Failed to set configuration");
303 }
304
305 if (ipv6 >= 0)
306 {
307 CHECK_ERROR(net, COMSETTER(IPv6Enabled) ((BOOL)ipv6));
308 if(FAILED(rc))
309 return errorArgument("Failed to set configuration");
310 }
311
312 if (!vPfName2Delete.empty())
313 {
314 VPF2DELETEITERATOR it;
315 for (it = vPfName2Delete.begin(); it != vPfName2Delete.end(); ++it)
316 {
317 CHECK_ERROR(net, RemovePortForwardRule((BOOL)(*it).fIPv6,
318 Bstr((*it).aszName).raw()));
319 if(FAILED(rc))
320 return errorArgument("Failed to delete pf");
321
322 }
323 }
324
325 if (!vPf2Add.empty())
326 {
327 VPF2ADDITERATOR it;
328 for(it = vPf2Add.begin(); it != vPf2Add.end(); ++it)
329 {
330 NATProtocol_T proto = NATProtocol_TCP;
331 if ((*it).iPfrProto == IPPROTO_TCP)
332 proto = NATProtocol_TCP;
333 else if ((*it).iPfrProto == IPPROTO_UDP)
334 proto = NATProtocol_UDP;
335 else
336 continue; /* XXX: warning here. */
337
338 CHECK_ERROR(net, AddPortForwardRule(
339 (BOOL)(*it).fPfrIPv6,
340 Bstr((*it).aszPfrName).raw(),
341 proto,
342 Bstr((*it).aszPfrHostAddr).raw(),
343 (*it).u16PfrHostPort,
344 Bstr((*it).aszPfrGuestAddr).raw(),
345 (*it).u16PfrGuestPort));
346 if(FAILED(rc))
347 return errorArgument("Failed to add pf");
348
349 }
350 }
351
352 if(enable >= 0)
353 {
354 CHECK_ERROR(net, COMSETTER(Enabled) ((BOOL)enable));
355 if(FAILED(rc))
356 return errorArgument("Failed to set configuration");
357
358 }
359 break;
360 }
361 case OP_REMOVE:
362 {
363 CHECK_ERROR(a->virtualBox, RemoveNATNetwork(net));
364 if(FAILED(rc))
365 return errorArgument("Failed to remove nat network");
366 break;
367 }
368 case OP_START:
369 {
370 CHECK_ERROR(net, Start(Bstr("whatever").raw()));
371 if(FAILED(rc))
372 return errorArgument("Failed to start network");
373 break;
374 }
375 case OP_STOP:
376 {
377 CHECK_ERROR(net, Stop());
378 if(FAILED(rc))
379 return errorArgument("Failed to start network");
380 break;
381 }
382 default:;
383 }
384 return 0;
385}
386
387
388int handleNATNetwork(HandlerArg *a)
389{
390 if (a->argc < 1)
391 return errorSyntax(USAGE_NATNETWORK, "Not enough parameters");
392
393 int result;
394 int cProcessed;
395 if (strcmp(a->argv[0], "modify") == 0)
396 result = handleOp(a, OP_MODIFY, 1, &cProcessed);
397 else if (strcmp(a->argv[0], "add") == 0)
398 result = handleOp(a, OP_ADD, 1, &cProcessed);
399 else if (strcmp(a->argv[0], "remove") == 0)
400 result = handleOp(a, OP_REMOVE, 1, &cProcessed);
401 else if (strcmp(a->argv[0], "start") == 0)
402 result = handleOp(a, OP_START, 1, &cProcessed);
403 else if (strcmp(a->argv[0], "stop") == 0)
404 result = handleOp(a, OP_STOP, 1, &cProcessed);
405 else
406 result = errorSyntax(USAGE_NATNETWORK, "Invalid parameter '%s'", Utf8Str(a->argv[0]).c_str());
407
408 return result;
409}
410
411#endif /* !VBOX_ONLY_DOCS */
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