VirtualBox

source: vbox/trunk/src/VBox/Main/NATEngineImpl.cpp@ 28787

Last change on this file since 28787 was 28787, checked in by vboxsync, 15 years ago

NAT: introduces management routines of NAT libalias core. (see xTracker/#4843 for details)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 17.3 KB
Line 
1/* $Id: NATEngineImpl.cpp 28787 2010-04-27 06:36:48Z vboxsync $ */
2/** @file
3 * Implementation of INATEngine in VBoxSVC.
4 */
5
6/*
7 * Copyright (C) 2010 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include "NATEngineImpl.h"
23#include "AutoCaller.h"
24#include "Logging.h"
25#include "MachineImpl.h"
26#include "GuestOSTypeImpl.h"
27
28#include <iprt/string.h>
29#include <iprt/cpp/utils.h>
30
31#include <VBox/err.h>
32#include <VBox/settings.h>
33
34
35// constructor / destructor
36////////////////////////////////////////////////////////////////////////////////
37
38NATEngine::NATEngine():mParent(NULL){}
39NATEngine::~NATEngine(){}
40
41HRESULT NATEngine::FinalConstruct()
42{
43 return S_OK;
44}
45
46HRESULT NATEngine::init(Machine *aParent)
47{
48 AutoInitSpan autoInitSpan(this);
49 AssertReturn(autoInitSpan.isOk(), E_FAIL);
50 autoInitSpan.setSucceeded();
51 m_fModified = false;
52 mData.allocate();
53 mData->mNetwork.setNull();
54 mData->mBindIP.setNull();
55 unconst(mParent) = aParent;
56 return S_OK;
57}
58
59HRESULT NATEngine::init(Machine *aParent, NATEngine *aThat)
60{
61 AutoInitSpan autoInitSpan(this);
62 AssertReturn(autoInitSpan.isOk(), E_FAIL);
63 Log(("init that:%p this:%p\n", aThat, this));
64
65 AutoCaller thatCaller (aThat);
66 AssertComRCReturnRC(thatCaller.rc());
67
68 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
69
70 mData.share(aThat->mData);
71 NATRuleMap::iterator it;
72 mNATRules.clear();
73 for (it = aThat->mNATRules.begin(); it != aThat->mNATRules.end(); ++it)
74 {
75 mNATRules.insert(std::make_pair(it->first, it->second));
76 }
77 unconst(mParent) = aParent;
78 unconst(mPeer) = aThat;
79 autoInitSpan.setSucceeded();
80 return S_OK;
81}
82
83HRESULT NATEngine::initCopy (Machine *aParent, NATEngine *aThat)
84{
85 AutoInitSpan autoInitSpan(this);
86 AssertReturn(autoInitSpan.isOk(), E_FAIL);
87
88 Log(("initCopy that:%p this:%p\n", aThat, this));
89
90 AutoCaller thatCaller (aThat);
91 AssertComRCReturnRC(thatCaller.rc());
92
93 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
94
95 mData.attachCopy(aThat->mData);
96 NATRuleMap::iterator it;
97 mNATRules.clear();
98 for (it = aThat->mNATRules.begin(); it != aThat->mNATRules.end(); ++it)
99 {
100 mNATRules.insert(std::make_pair(it->first, it->second));
101 }
102 unconst(mParent) = aParent;
103 autoInitSpan.setSucceeded();
104 return S_OK;
105}
106
107
108void NATEngine::FinalRelease()
109{
110 uninit();
111}
112
113void NATEngine::uninit()
114{
115 AutoUninitSpan autoUninitSpan(this);
116 if (autoUninitSpan.uninitDone())
117 return;
118
119 mNATRules.clear();
120 mData.free();
121 unconst(mPeer) = NULL;
122 unconst(mParent) = NULL;
123}
124
125bool NATEngine::isModified()
126{
127 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
128 bool fModified = m_fModified;
129 return fModified;
130}
131
132bool NATEngine::rollback()
133{
134 AutoCaller autoCaller(this);
135 AssertComRCReturn (autoCaller.rc(), false);
136
137 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
138 bool fChanged = m_fModified;
139
140 if (m_fModified)
141 {
142 /* we need to check all data to see whether anything will be changed
143 * after rollback */
144 mData.rollback();
145 }
146 m_fModified = false;
147 return fChanged;
148}
149
150void NATEngine::commit()
151{
152 AutoCaller autoCaller(this);
153 AssertComRCReturnVoid (autoCaller.rc());
154
155 /* sanity too */
156 AutoCaller peerCaller (mPeer);
157 AssertComRCReturnVoid (peerCaller.rc());
158
159 /* lock both for writing since we modify both (mPeer is "master" so locked
160 * first) */
161 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
162 if (m_fModified)
163 {
164 mData.commit();
165 if (mPeer)
166 {
167 mPeer->mData.attach (mData);
168 mPeer->mNATRules.clear();
169 NATRuleMap::iterator it;
170 for (it = mNATRules.begin(); it != mNATRules.end(); ++it)
171 {
172 mPeer->mNATRules.insert(std::make_pair(it->first, it->second));
173 }
174 }
175 }
176 m_fModified = false;
177}
178
179STDMETHODIMP
180NATEngine::GetNetworkSettings(ULONG *aMtu, ULONG *aSockSnd, ULONG *aSockRcv, ULONG *aTcpWndSnd, ULONG *aTcpWndRcv)
181{
182 AutoCaller autoCaller(this);
183 if (FAILED(autoCaller.rc())) return autoCaller.rc();
184
185 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
186 if (aMtu)
187 *aMtu = mData->mMtu;
188 if (aSockSnd)
189 *aSockSnd = mData->mSockSnd;
190 if (aSockRcv)
191 *aSockSnd = mData->mSockRcv;
192 if (aTcpWndSnd)
193 *aTcpWndSnd = mData->mTcpSnd;
194 if (aTcpWndRcv)
195 *aTcpWndRcv = mData->mTcpRcv;
196
197 return S_OK;
198}
199
200STDMETHODIMP
201NATEngine::SetNetworkSettings(ULONG aMtu, ULONG aSockSnd, ULONG aSockRcv, ULONG aTcpWndSnd, ULONG aTcpWndRcv)
202{
203 AutoCaller autoCaller(this);
204 if (FAILED(autoCaller.rc())) return autoCaller.rc();
205
206 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
207 if ( aMtu || aSockSnd || aSockRcv
208 || aTcpWndSnd || aTcpWndRcv)
209 {
210 mData.backup();
211 m_fModified = true;
212 }
213 if (aMtu)
214 mData->mMtu = aMtu;
215 if (aSockSnd)
216 mData->mSockSnd = aSockSnd;
217 if (aSockRcv)
218 mData->mSockRcv = aSockSnd;
219 if (aTcpWndSnd)
220 mData->mTcpSnd = aTcpWndSnd;
221 if (aTcpWndRcv)
222 mData->mTcpRcv = aTcpWndRcv;
223
224 if (m_fModified)
225 mParent->setModified(Machine::IsModified_NetworkAdapters);
226 return S_OK;
227}
228
229STDMETHODIMP
230NATEngine::COMGETTER(Redirects) (ComSafeArrayOut (BSTR , aNatRules))
231{
232 CheckComArgOutSafeArrayPointerValid(aNatRules);
233
234 AutoCaller autoCaller(this);
235 if (FAILED(autoCaller.rc())) return autoCaller.rc();
236
237 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
238
239
240 SafeArray<BSTR> sf(mNATRules.size());
241 size_t i = 0;
242 NATRuleMap::const_iterator it;
243 for (it = mNATRules.begin();
244 it != mNATRules.end(); ++it, ++i)
245 {
246 settings::NATRule r = it->second;
247 Utf8Str utf = Utf8StrFmt("%s,%d,%s,%d,%s,%d", r.strName.raw(), r.u32Proto,
248 r.strHostIP.raw(), r.u16HostPort, r.strGuestIP.raw(), r.u16GuestPort);
249 utf.cloneTo(&sf[i]);
250 }
251 sf.detachTo(ComSafeArrayOutArg(aNatRules));
252 return S_OK;
253}
254
255
256STDMETHODIMP
257NATEngine::AddRedirect(IN_BSTR aName, NATProtocol_T aProto, IN_BSTR aBindIp, USHORT aHostPort, IN_BSTR aGuestIP, USHORT aGuestPort)
258{
259
260 AutoCaller autoCaller(this);
261 if (FAILED(autoCaller.rc())) return autoCaller.rc();
262
263 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
264 Utf8Str name = aName;
265 settings::NATRule r;
266 if (name.isEmpty())
267 {
268 const char *proto;
269 switch (aProto)
270 {
271 case NATProtocol_TCP:
272 proto = "tcp";
273 break;
274 case NATProtocol_UDP:
275 proto = "udp";
276 break;
277 default:
278 return E_INVALIDARG;
279 }
280 name = Utf8StrFmt("%s_%d_%d", proto, aHostPort, aGuestPort);
281 }
282 r.strName = name.raw();
283 r.u32Proto = aProto;
284 r.strHostIP = aBindIp;
285 r.u16HostPort = aHostPort;
286 r.strGuestIP = aGuestIP;
287 r.u16GuestPort = aGuestPort;
288 mNATRules.insert(std::make_pair(name, r));
289 mParent->setModified(Machine::IsModified_NetworkAdapters);
290 m_fModified = true;
291 return S_OK;
292}
293
294STDMETHODIMP
295NATEngine::RemoveRedirect(IN_BSTR aName)
296{
297 AutoCaller autoCaller(this);
298 if (FAILED(autoCaller.rc())) return autoCaller.rc();
299
300 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
301 Utf8Str rule;
302 NATRuleMap::iterator it = mNATRules.find(aName);
303 if (it == mNATRules.end())
304 return E_INVALIDARG;
305 mData.backup();
306 mNATRules.erase(it);
307 mParent->setModified(Machine::IsModified_NetworkAdapters);
308 m_fModified = true;
309 return S_OK;
310}
311
312HRESULT NATEngine::loadSettings(const settings::NAT &data)
313{
314 AutoCaller autoCaller(this);
315 AssertComRCReturnRC(autoCaller.rc());
316
317 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
318 HRESULT rc = S_OK;
319 mData->mNetwork = data.strNetwork;
320 mData->mBindIP = data.strBindIP;
321 mData->mMtu = data.u32Mtu;
322 mData->mSockSnd = data.u32SockSnd;
323 mData->mTcpRcv = data.u32TcpRcv;
324 mData->mTcpSnd = data.u32TcpSnd;
325 /* TFTP */
326 mData->mTftpPrefix = data.strTftpPrefix;
327 mData->mTftpBootFile = data.strTftpBootFile;
328 mData->mTftpNextServer = data.strTftpNextServer;
329 /* DNS */
330 mData->mDnsPassDomain = data.fDnsPassDomain;
331 mData->mDnsProxy = data.fDnsProxy;
332 mData->mDnsUseHostResolver = data.fDnsUseHostResolver;
333 /* Alias */
334 mData->mAliasMode |= (data.fAliasLog ? NATAliasMode_AliasLog : 0);
335 mData->mAliasMode |= (data.fAliasProxyOnly ? NATAliasMode_AliasProxyOnly : 0);
336 mData->mAliasMode = (data.fAliasUseSamePorts ? NATAliasMode_AliasUseSamePorts : 0);
337 /* port forwarding */
338 mNATRules.clear();
339 for (settings::NATRuleList::const_iterator it = data.llRules.begin();
340 it != data.llRules.end(); ++it)
341 {
342 mNATRules.insert(std::make_pair(it->strName, *it));
343 }
344 m_fModified = false;
345 return rc;
346}
347
348
349HRESULT NATEngine::saveSettings(settings::NAT &data)
350{
351 AutoCaller autoCaller(this);
352 AssertComRCReturnRC(autoCaller.rc());
353
354 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
355 HRESULT rc = S_OK;
356 data.strNetwork = mData->mNetwork;
357 data.strBindIP = mData->mBindIP;
358 data.u32Mtu = mData->mMtu;
359 data.u32SockRcv = mData->mSockRcv;
360 data.u32SockSnd = mData->mSockSnd;
361 data.u32TcpRcv = mData->mTcpRcv;
362 data.u32TcpSnd = mData->mTcpSnd;
363 /* TFTP */
364 data.strTftpPrefix = mData->mTftpPrefix;
365 data.strTftpBootFile = mData->mTftpBootFile;
366 data.strTftpNextServer = mData->mTftpNextServer;
367 /* DNS */
368 data.fDnsPassDomain = mData->mDnsPassDomain;
369 data.fDnsProxy = mData->mDnsProxy;
370 data.fDnsUseHostResolver = mData->mDnsUseHostResolver;
371 /* Alias */
372 data.fAliasLog = mData->mAliasMode & NATAliasMode_AliasLog;
373 data.fAliasProxyOnly = mData->mAliasMode & NATAliasMode_AliasProxyOnly;
374 data.fAliasUseSamePorts = mData->mAliasMode & NATAliasMode_AliasUseSamePorts;
375
376 for (NATRuleMap::iterator it = mNATRules.begin();
377 it != mNATRules.end(); ++it)
378 data.llRules.push_back(it->second);
379 m_fModified = false;
380 return rc;
381}
382
383
384STDMETHODIMP
385NATEngine::COMSETTER(Network)(IN_BSTR aNetwork)
386{
387 AutoCaller autoCaller(this);
388 AssertComRCReturnRC (autoCaller.rc());
389 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
390 if (Bstr(mData->mNetwork) != aNetwork)
391 {
392 mData.backup();
393 mData->mNetwork = aNetwork;
394 mParent->setModified(Machine::IsModified_NetworkAdapters);
395 m_fModified = true;
396 }
397 return S_OK;
398}
399
400STDMETHODIMP
401NATEngine::COMGETTER(Network)(BSTR *aNetwork)
402{
403 CheckComArgNotNull(aNetwork);
404 AutoCaller autoCaller(this);
405 AssertComRCReturnRC(autoCaller.rc());
406
407 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
408 if (!mData->mNetwork.isEmpty())
409 {
410 mData->mNetwork.cloneTo(aNetwork);
411 Log(("Getter (this:%p) Network: %s\n", this, mData->mNetwork.raw()));
412 }
413 return S_OK;
414}
415
416STDMETHODIMP
417NATEngine::COMSETTER(HostIP) (IN_BSTR aBindIP)
418{
419 AutoCaller autoCaller(this);
420 AssertComRCReturnRC (autoCaller.rc());
421 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
422 if (Bstr(mData->mBindIP) != aBindIP)
423 {
424 mData.backup();
425 mData->mBindIP = aBindIP;
426 mParent->setModified(Machine::IsModified_NetworkAdapters);
427 m_fModified = true;
428 }
429 return S_OK;
430}
431STDMETHODIMP NATEngine::COMGETTER(HostIP) (BSTR *aBindIP)
432{
433 AutoCaller autoCaller(this);
434 AssertComRCReturnRC(autoCaller.rc());
435
436 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
437 if (!mData->mBindIP.isEmpty())
438 mData->mBindIP.cloneTo(aBindIP);
439 return S_OK;
440}
441
442
443STDMETHODIMP
444NATEngine::COMSETTER(TftpPrefix)(IN_BSTR aTftpPrefix)
445{
446 AutoCaller autoCaller(this);
447 AssertComRCReturnRC (autoCaller.rc());
448 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
449 if (Bstr(mData->mTftpPrefix) != aTftpPrefix)
450 {
451 mData.backup();
452 mData->mTftpPrefix = aTftpPrefix;
453 mParent->setModified(Machine::IsModified_NetworkAdapters);
454 m_fModified = true;
455 }
456 return S_OK;
457}
458
459STDMETHODIMP
460NATEngine::COMGETTER(TftpPrefix)(BSTR *aTftpPrefix)
461{
462 AutoCaller autoCaller(this);
463 AssertComRCReturnRC(autoCaller.rc());
464
465 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
466 if (!mData->mTftpPrefix.isEmpty())
467 {
468 mData->mTftpPrefix.cloneTo(aTftpPrefix);
469 Log(("Getter (this:%p) TftpPrefix: %s\n", this, mData->mTftpPrefix.raw()));
470 }
471 return S_OK;
472}
473
474STDMETHODIMP
475NATEngine::COMSETTER(TftpBootFile)(IN_BSTR aTftpBootFile)
476{
477 AutoCaller autoCaller(this);
478 AssertComRCReturnRC (autoCaller.rc());
479 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
480 if (Bstr(mData->mTftpBootFile) != aTftpBootFile)
481 {
482 mData.backup();
483 mData->mTftpBootFile = aTftpBootFile;
484 mParent->setModified(Machine::IsModified_NetworkAdapters);
485 m_fModified = true;
486 }
487 return S_OK;
488}
489
490STDMETHODIMP
491NATEngine::COMGETTER(TftpBootFile)(BSTR *aTftpBootFile)
492{
493 AutoCaller autoCaller(this);
494 AssertComRCReturnRC(autoCaller.rc());
495
496 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
497 if (!mData->mTftpBootFile.isEmpty())
498 {
499 mData->mTftpBootFile.cloneTo(aTftpBootFile);
500 Log(("Getter (this:%p) BootFile: %s\n", this, mData->mTftpBootFile.raw()));
501 }
502 return S_OK;
503}
504
505STDMETHODIMP
506NATEngine::COMSETTER(TftpNextServer)(IN_BSTR aTftpNextServer)
507{
508 AutoCaller autoCaller(this);
509 AssertComRCReturnRC (autoCaller.rc());
510 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
511 if (Bstr(mData->mTftpNextServer) != aTftpNextServer)
512 {
513 mData.backup();
514 mData->mTftpNextServer = aTftpNextServer;
515 mParent->setModified(Machine::IsModified_NetworkAdapters);
516 m_fModified = true;
517 }
518 return S_OK;
519}
520
521STDMETHODIMP
522NATEngine::COMGETTER(TftpNextServer)(BSTR *aTftpNextServer)
523{
524 AutoCaller autoCaller(this);
525 AssertComRCReturnRC(autoCaller.rc());
526
527 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
528 if (!mData->mTftpNextServer.isEmpty())
529 {
530 mData->mTftpNextServer.cloneTo(aTftpNextServer);
531 Log(("Getter (this:%p) NextServer: %s\n", this, mData->mTftpNextServer.raw()));
532 }
533 return S_OK;
534}
535/* DNS */
536STDMETHODIMP
537NATEngine::COMSETTER(DnsPassDomain) (BOOL aDnsPassDomain)
538{
539 AutoCaller autoCaller(this);
540 AssertComRCReturnRC (autoCaller.rc());
541 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
542
543 if (mData->mDnsPassDomain != aDnsPassDomain)
544 {
545 mData.backup();
546 mData->mDnsPassDomain = aDnsPassDomain;
547 mParent->setModified(Machine::IsModified_NetworkAdapters);
548 m_fModified = true;
549 }
550 return S_OK;
551}
552STDMETHODIMP
553NATEngine::COMGETTER(DnsPassDomain)(BOOL *aDnsPassDomain)
554{
555 AutoCaller autoCaller(this);
556 AssertComRCReturnRC(autoCaller.rc());
557
558 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
559 *aDnsPassDomain = mData->mDnsPassDomain;
560 return S_OK;
561}
562STDMETHODIMP
563NATEngine::COMSETTER(DnsProxy)(BOOL aDnsProxy)
564{
565 AutoCaller autoCaller(this);
566 AssertComRCReturnRC (autoCaller.rc());
567 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
568
569 if (mData->mDnsProxy != aDnsProxy)
570 {
571 mData.backup();
572 mData->mDnsProxy = aDnsProxy;
573 mParent->setModified(Machine::IsModified_NetworkAdapters);
574 m_fModified = true;
575 }
576 return S_OK;
577}
578STDMETHODIMP
579NATEngine::COMGETTER(DnsProxy)(BOOL *aDnsProxy)
580{
581 AutoCaller autoCaller(this);
582 AssertComRCReturnRC(autoCaller.rc());
583
584 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
585 *aDnsProxy = mData->mDnsProxy;
586 return S_OK;
587}
588STDMETHODIMP
589NATEngine::COMGETTER(DnsUseHostResolver)(BOOL *aDnsUseHostResolver)
590{
591 AutoCaller autoCaller(this);
592 AssertComRCReturnRC (autoCaller.rc());
593 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
594 *aDnsUseHostResolver = mData->mDnsUseHostResolver;
595 return S_OK;
596}
597STDMETHODIMP
598NATEngine::COMSETTER(DnsUseHostResolver)(BOOL aDnsUseHostResolver)
599{
600 AutoCaller autoCaller(this);
601 AssertComRCReturnRC(autoCaller.rc());
602
603 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
604
605 if (mData->mDnsUseHostResolver != aDnsUseHostResolver)
606 {
607 mData.backup();
608 mData->mDnsUseHostResolver = aDnsUseHostResolver;
609 mParent->setModified(Machine::IsModified_NetworkAdapters);
610 m_fModified = true;
611 }
612 return S_OK;
613}
614
615STDMETHODIMP NATEngine::COMSETTER(AliasMode) (ULONG aAliasMode)
616{
617 AutoCaller autoCaller(this);
618 AssertComRCReturnRC(autoCaller.rc());
619
620 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
621
622 if (mData->mAliasMode != aAliasMode)
623 {
624 mData.backup();
625 mData->mAliasMode = aAliasMode;
626 mParent->setModified(Machine::IsModified_NetworkAdapters);
627 m_fModified = true;
628 }
629 return S_OK;
630}
631
632STDMETHODIMP NATEngine::COMGETTER(AliasMode) (ULONG *aAliasMode)
633{
634 AutoCaller autoCaller(this);
635 AssertComRCReturnRC (autoCaller.rc());
636 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
637 *aAliasMode = mData->mAliasMode;
638 return S_OK;
639}
640
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