add norp v0.1b5
parent
120989e3d6
commit
c9ed6bd04f
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
|
||||||
|
The basic NORP server state machine is in place and pretty much ready for testing. There are some details that need to be wrapped up:
|
||||||
|
|
||||||
|
1) Implement ACK-based flow control using double-buffer markers, explict positive acknowledgement, (DONE) 1a) Add option to NORM to
|
||||||
|
only ACK after application has read stream data. (DONE)
|
||||||
|
|
||||||
|
2) Clean up debugging messages. (SOME)
|
||||||
|
|
||||||
|
3) Provide NORM congestion control options (DONE - CCE added)
|
||||||
|
|
||||||
|
4) Session configuration options (ouch!) 4a) Src/Dst based proxy methods and parameters
|
||||||
|
|
||||||
|
5) Implement auto handoff to TCP direct connnect on port unreachable (what about NORP request timeout, too?) (both DONE)
|
||||||
|
|
||||||
|
6) Use protolibd for "safer" socket state
|
||||||
|
|
||||||
|
7) norm_rx_stream can hangup shutdown - fix it (DONE)
|
||||||
|
|
||||||
|
8) Win32 build and test
|
||||||
|
|
||||||
|
8a) Win32 NORM-CCE support that's not WinPcap dependent
|
||||||
|
|
||||||
|
9) Send / handle negative SOCKS replies
|
||||||
|
|
||||||
|
|
||||||
|
10) IMPORTANT: Detect remote "norp" failure _or_ make sure that we can _always_ detect when our local TCP socket (originator client, or
|
||||||
|
correspondent remote) closes. Right now, we stop TCP socket input notification upon NORM flow control block condition (e.g. failed
|
||||||
|
watermark) ... we probably should have some failed watermark timeout condition, perhaps in conjunction with using an
|
||||||
|
application-defined command as a "keep-alive" mechanism. For example, have each NORM sender send a "keep-alive" heart beat
|
||||||
|
periodically, but upon multiple periods of failed watermark ACK _and_ missing "keep-alive", initiate session teardown? Otherwise, this
|
||||||
|
creates a condition of persistent requests of ACK indefinitely.
|
||||||
|
|
||||||
|
|
||||||
|
11) To provide easier firewall traversal, should we split the "correspondent" norm tx & rx sessions so that it can "talk back" to the
|
||||||
|
originator source port. Can also use the NORP messaging to signal the norm ports to use.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
NORP Version History
|
||||||
|
|
||||||
|
Version 0.1b3
|
||||||
|
=============
|
||||||
|
- Added "correspondent <remoteNorpAddr>" command to allow 'routing'
|
||||||
|
of proxied connections through specified remote 'norp' peer
|
||||||
|
instead of directly to connection destination address.
|
||||||
|
- Includes fix to NORM source code of receiver rate estimation
|
||||||
|
measured during 'slow start' phase of congestion control
|
||||||
|
|
||||||
|
Version 0.1b2
|
||||||
|
=============
|
||||||
|
- Adopted NORM_SYNC_STREAM policy to guarantee synchronization
|
||||||
|
of stream start at byte offset zero of proxied TCP stream data
|
||||||
|
- Added norp "persist" command-line option to allow control of how
|
||||||
|
persistently norp tries to deliver TCP data in disruptive network
|
||||||
|
environments. A -1 persistence value is infinitely persistent.
|
||||||
|
The default persistence is 120 seconds (2 minutes).
|
||||||
|
|
||||||
|
Version 0.1b1
|
||||||
|
=============
|
||||||
|
- Fixed bugs with "forward" command recently added
|
||||||
|
- Updated "norm" with bug fix in normSession.cpp
|
||||||
|
|
||||||
|
Version 0.1
|
||||||
|
=============
|
||||||
|
- Started versioning
|
||||||
|
- This version adds the "forward" command for non-SOCKS proxying
|
||||||
|
|
||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
|
@ -0,0 +1,567 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?xml-stylesheet type="text/xsl" href="transform.xsl"?>
|
||||||
|
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.1/docbookx.dtd">
|
||||||
|
<article>
|
||||||
|
<articleinfo>
|
||||||
|
<title><inlinemediaobject>
|
||||||
|
<imageobject>
|
||||||
|
<imagedata align="center" fileref="resources/ProteanLogo.png"
|
||||||
|
scale="30"/>
|
||||||
|
</imageobject>
|
||||||
|
</inlinemediaobject> <emphasis>norp</emphasis> User's Guide</title>
|
||||||
|
|
||||||
|
<titleabbrev><emphasis>norp</emphasis> User's Guide</titleabbrev>
|
||||||
|
|
||||||
|
<abstract>
|
||||||
|
<para>The NRL Nack-Oriented Proxy (<emphasis>norp</emphasis>) project
|
||||||
|
includes software for an RFC 1928 SOCKS5-compatible proxy server daemon
|
||||||
|
that is able to use the RFC 5740 Nack-Oriented Reliable Multicast (NORM)
|
||||||
|
transport protocol for efficient and robust data transfer between
|
||||||
|
<emphasis>norp</emphasis> proxy instances. The <emphasis>norp</emphasis>
|
||||||
|
proxy automatically supports conventional SOCKS TCP proxy operation when
|
||||||
|
a remote <emphasis>norp</emphasis> peer is unavailable. This software
|
||||||
|
was developed by the <ulink url="http://www.nrl.navy.mil/">Naval
|
||||||
|
Research Laboratory</ulink> (NRL) PROTocol Engineering Advanced
|
||||||
|
Networking Research Group.
|
||||||
|
The NRL reference implementation of NORM used here is available from
|
||||||
|
<ulink
|
||||||
|
url="http://www.nrl.navy.mil/itd/ncs/products/norm">http://www.nrl.navy.mil/itd/ncs/products/norm</ulink>.</para>
|
||||||
|
</abstract>
|
||||||
|
</articleinfo>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Overview</title>
|
||||||
|
|
||||||
|
<para>The <emphasis>norp</emphasis> application ....</para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="TheoryOfOperation">
|
||||||
|
<title>Theory of Operation</title>
|
||||||
|
|
||||||
|
<para>The <emphasis>norp</emphasis> program acts as a SOCKS proxy server.
|
||||||
|
It supports the SOCKS5 "CONNECT", "BIND" and "UDP-ASSOCIATE" proxy methods
|
||||||
|
for conventional SOCKS proxy operation. The current
|
||||||
|
<emphasis>norp</emphasis> implementation does not require (or support) any
|
||||||
|
client authentication. Future versions may provide authentication or other
|
||||||
|
access control mechanisms. The current <emphasis>norp</emphasis>
|
||||||
|
implementation only provides NORM transport for the SOCKS TCP "CONNECT"
|
||||||
|
requests. SOCKS "UDP-ASSOCIATE" over NORM will be supported in a future
|
||||||
|
version.</para>
|
||||||
|
|
||||||
|
<para>Unlike a conventional SOCKS server, it is expected that the
|
||||||
|
<emphasis>norp</emphasis> daemon can be installed and run as a local
|
||||||
|
"loopback" server that is co-resident on the host running applications
|
||||||
|
that wish to take advantage of NORM transport benefits. The
|
||||||
|
<emphasis>norp</emphasis> daemon implements its own signaling protocol
|
||||||
|
that will automatically determine, upon TCP (or UDP) connection
|
||||||
|
establishment, if a remote destination is also similarly
|
||||||
|
"<emphasis>norp</emphasis>-enabled" and establish a NORM transport
|
||||||
|
connection as the proxy connection. Otherwise a "business-as-usual" TCP
|
||||||
|
(or UDP) connection is established on the application's behalf and thus
|
||||||
|
compatibility with "non-<emphasis>norp</emphasis>" hosts is also
|
||||||
|
supported. <xref linkend="norpConcept"/> illustrates this high level
|
||||||
|
concept of operation.</para>
|
||||||
|
|
||||||
|
<para><figure id="norpConcept">
|
||||||
|
<title>NORP Concept of Operation</title>
|
||||||
|
|
||||||
|
<mediaobject>
|
||||||
|
<imageobject>
|
||||||
|
<imagedata fileref="resources/norpConcept.png" format="PNG"
|
||||||
|
scale="50"/>
|
||||||
|
</imageobject>
|
||||||
|
</mediaobject>
|
||||||
|
</figure></para>
|
||||||
|
|
||||||
|
<para><emphasis>TBD - provide some more details on norp signaling for peer
|
||||||
|
detection and NORM session establishment</emphasis></para>
|
||||||
|
|
||||||
|
<para>Note that as an alternative to making proxied connections directly
|
||||||
|
to connection destination addresses as illustrated above, a remote
|
||||||
|
<emphasis>norp</emphasis> peer "correspondent" can be specified as part of
|
||||||
|
the <literal>forward</literal> command or, for SOCKS connections, with the
|
||||||
|
<literal>correspondent</literal> command (see command descriptions below).
|
||||||
|
Future versions of <emphasis>norp</emphasis> will include more
|
||||||
|
sophisticated "routing" options for different destinations and traffic
|
||||||
|
types.</para>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>SOCKS Loopback and Intermediate System</title>
|
||||||
|
|
||||||
|
<para>As noted above the principal use case for
|
||||||
|
<emphasis>norp</emphasis> is to act as a local, "loopback" SOCKS server
|
||||||
|
that can be used in conjunction with a properly configured SOCKS client.
|
||||||
|
In this way, all of the configuration parameters are localized and
|
||||||
|
implicit and no precoordinated configuration with
|
||||||
|
<emphasis>norp</emphasis> peers (or non-<emphasis>norp</emphasis> hosts)
|
||||||
|
is required other than using a common UDP port number for NORP
|
||||||
|
signaling.</para>
|
||||||
|
|
||||||
|
<para>However, there may be use cases where it may be desirable to
|
||||||
|
deploy <emphasis>norp</emphasis> on intermediate systems at the
|
||||||
|
connection originating site (or domain) and/or the destination site(s)
|
||||||
|
(or domain(s)). This is easily supported by the
|
||||||
|
<emphasis>norp</emphasis> design and future norp versions will provide
|
||||||
|
configuration options for this type of deployment.</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>NORM Protocol Usage</title>
|
||||||
|
|
||||||
|
<para><emphasis>TBD - describe how the NORM streaming capability is used
|
||||||
|
in a flow-controlled, positively-acknowledged fashion to provide a
|
||||||
|
reliable TCP proxy function. Also describe the NORM congestion control
|
||||||
|
options here.</emphasis></para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="Usage">
|
||||||
|
<title>Usage</title>
|
||||||
|
|
||||||
|
<para>Typically, <emphasis>norp</emphasis> can be run in its default
|
||||||
|
configuration with no command-line options required. However, a number of
|
||||||
|
options are available via the command-line. This is a summary of
|
||||||
|
<emphasis>norp</emphasis> usage:</para>
|
||||||
|
|
||||||
|
<para><informalexample>
|
||||||
|
<programlisting><?dbfo keep-together="always"?>norp [interface <ifaceName>][address <publicAddr>][sport <socksPort>][port <norpPort>]
|
||||||
|
[norm {on|off}][id <normId>][nport <normPort>][cce | ccl | rate <bits/sec>]
|
||||||
|
[limit <bits/sec>][persist <seconds>][correspondent <remoteNorpAddr>]
|
||||||
|
[forward <tcpPort>,<destAddr>/<destPort>[,<remoteNorpAddr>]][version][debug <level>]
|
||||||
|
[trace][dlog <debugLog>][lport <localNorpPort>][rport <remoteNorpPort>]</programlisting>
|
||||||
|
|
||||||
|
<para>The <emphasis>norp</emphasis> program command-line options
|
||||||
|
include ...</para>
|
||||||
|
</informalexample></para>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<title><emphasis><emphasis>norp</emphasis></emphasis> Command-line
|
||||||
|
Options</title>
|
||||||
|
|
||||||
|
<?dbfo keep-together="always"?>
|
||||||
|
|
||||||
|
<tgroup cols="2">
|
||||||
|
<colspec colname="Command" colwidth="1*"/>
|
||||||
|
|
||||||
|
<colspec colname="Description" colwidth="2.5*"/>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry align="left"><literal>interface
|
||||||
|
<interfaceName></literal></entry>
|
||||||
|
|
||||||
|
<entry>The given <literal><interfaceName></literal>
|
||||||
|
specifies the name (or IP address) of the host network interface
|
||||||
|
<emphasis>norp</emphasis> uses as its "public" proxy address.
|
||||||
|
Currently a single interface may be designated for an instance of
|
||||||
|
<emphasis>norp</emphasis>. Future version of
|
||||||
|
<emphasis>norp</emphasis> may allow for multiple interfaces to be
|
||||||
|
designated depending upon the source and/or destination address of
|
||||||
|
SOCKS proxy connections.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>address <publicAddr></literal></entry>
|
||||||
|
|
||||||
|
<entry>This is similar to the "<literal>interface</literal>"
|
||||||
|
command, but allows a specific address to be set. For example,
|
||||||
|
hosts with multiple addresses assigned may wish to use a specific
|
||||||
|
address for proxy functions.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>sport <socksPort></literal></entry>
|
||||||
|
|
||||||
|
<entry>This command is used to specify the port number on which
|
||||||
|
the <emphasis>norp</emphasis> server listens for SOCKS client
|
||||||
|
connections. The default port is currently port number
|
||||||
|
7000.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>port <norpPort></literal></entry>
|
||||||
|
|
||||||
|
<entry>This command is used to specify the UDP port number used
|
||||||
|
for <emphasis>norp</emphasis> session setup signaling. The default
|
||||||
|
<emphasis>norp</emphasis> UDP signaling port is 7001. The
|
||||||
|
configured <emphasis>norp</emphasis> port number (and NORM port
|
||||||
|
number) MUST be unblocked by any network firewalls between
|
||||||
|
<emphasis>norp</emphasis> peers. The given port number is used by
|
||||||
|
<emphasis>norp</emphasis> to listen for remote connection request
|
||||||
|
and is used as the destination port to signal remote
|
||||||
|
<emphasis>norp</emphasis> peers.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>norm {on | off}</literal></entry>
|
||||||
|
|
||||||
|
<entry>By default, <emphasis>norp</emphasis> attempts to signal
|
||||||
|
the SOCKS connection endpoint to setup a NORM transport connection
|
||||||
|
to handle reliable data transfer for the TCP connection being
|
||||||
|
instantiated. This command with the "<literal>off</literal>"
|
||||||
|
argument will disable this function and <emphasis>norp</emphasis>
|
||||||
|
will act as a conventional SOCKS proxy server.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>id <normId></literal></entry>
|
||||||
|
|
||||||
|
<entry>By default, <emphasis>norp</emphasis> will attempt to
|
||||||
|
self-configure a NORM protocol node identifier using the IP
|
||||||
|
address of the server host. This command allows a specific NORM
|
||||||
|
node identifier value to be set. It is generally not necessary to
|
||||||
|
explicitly set this value for <emphasis>norp</emphasis> unicast
|
||||||
|
proxy connections.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><constant>nport <normPort></constant></entry>
|
||||||
|
|
||||||
|
<entry>This command can be used to specify a UDP port number that
|
||||||
|
will be used for NORM protocol transport connections. The default
|
||||||
|
NORM port number used by <emphasis>norp</emphasis> is 7002. The
|
||||||
|
configured NORM port number (and <emphasis>norp</emphasis> UDP
|
||||||
|
signaling <literal>port</literal> number) MUST be unblocked by any
|
||||||
|
network firewalls between <emphasis>norp</emphasis> peers.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>cce</literal></entry>
|
||||||
|
|
||||||
|
<entry>This option enables NORM-CCE congestion control operation
|
||||||
|
that uses Explicit Congestion Notification (ECN) information for
|
||||||
|
NORM protocol end-to-end transmission rate adaption. This is an
|
||||||
|
alternative to the TCP-friendly congestion control mechanism used
|
||||||
|
for NORM by default. Routers in the path of the
|
||||||
|
<emphasis>norp</emphasis> peers using the NORM-CCE option MUST be
|
||||||
|
configured for ECN packet marking in response to
|
||||||
|
congestion.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>ccl</literal></entry>
|
||||||
|
|
||||||
|
<entry>This option enables experimental NORM-CCL ("Loss Tolerant")
|
||||||
|
congestion control operation that uses some simple heuristics to
|
||||||
|
try to differentiate packet loss due to congestion versus duo to
|
||||||
|
channel bit errors. This is another alternative to the
|
||||||
|
TCP-friendly congestion control mechanism used for NORM by
|
||||||
|
default. No special intermediate system configuration is required,
|
||||||
|
and while more loss tolerant than the default TCP-friendly
|
||||||
|
behavior, is not as effective as the NORM-CCE mode of
|
||||||
|
operation.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>rate <bits/sec></literal></entry>
|
||||||
|
|
||||||
|
<entry>This option causes <emphasis>norp</emphasis> to use a
|
||||||
|
preset and fixed transmission rate for each proxied data flow
|
||||||
|
(e.g. TCP connection). This should only be used when the network
|
||||||
|
connectivity usage is carefully pre-planned and previsioned for
|
||||||
|
the expected (i.e. <emphasis>a priori</emphasis> known) flows. At
|
||||||
|
this time, one common transmission rate is used for all
|
||||||
|
flows.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>limit <bits/sec></literal></entry>
|
||||||
|
|
||||||
|
<entry>This option sets a limit for the
|
||||||
|
<emphasis>cumulative</emphasis> transmit rate for
|
||||||
|
<emphasis>all</emphasis> flows that <emphasis>norp</emphasis> is
|
||||||
|
proxying. For automated congestion operation, this can also work
|
||||||
|
to "jump start" the usual "slow start" transport rate control by
|
||||||
|
setting the lower bound of rate adjustment based on the limit
|
||||||
|
<literal><bits/sec> / <numFlows></literal>. For
|
||||||
|
example, a single flow will immediately "jump" to close the full
|
||||||
|
limit rate, while the second of two flows would "jump" to half of
|
||||||
|
the "limit" rate. Also, by setting a limit based on <emphasis>a
|
||||||
|
priori</emphasis> connectivity information, this can avoid rate
|
||||||
|
adjustment "overshoot" and help congestion control operate more
|
||||||
|
effectively as compared to a "blind" situation. IMPORTANT: This
|
||||||
|
options should only be applied when the connectivity path is well
|
||||||
|
known and the impact of the lower bound enforcement here will not
|
||||||
|
adversely impact other network traffic flows. A future option may
|
||||||
|
be provided to further reduce or eliminate the lower bound
|
||||||
|
enforcement that would eliminate this concern in less controlled
|
||||||
|
network deployments. A limit value of "-1.0" (default) disables
|
||||||
|
the limit enforcement.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>correspondent
|
||||||
|
<remoteNorpAddr></literal></entry>
|
||||||
|
|
||||||
|
<entry>This option causes <emphasis>norp</emphasis> to "route"
|
||||||
|
connections through a <emphasis>norp</emphasis> peer at the
|
||||||
|
specified <parameter><remoteNorpAddr></parameter>. This is
|
||||||
|
an alternative to the default behavior where
|
||||||
|
<emphasis>norp</emphasis> attempts to connect directly to the
|
||||||
|
connection destination addresses.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>persist <seconds></literal></entry>
|
||||||
|
|
||||||
|
<entry>This option controls how persistently norp attempts to
|
||||||
|
deliver data to the remote endpoint when the remote endpoint fails
|
||||||
|
to acknowledge reception. A persist value of -1 makes norp
|
||||||
|
infinitely persistent and the corresponding norp session remains
|
||||||
|
in place until all data is delivered. If not, an orphaned session
|
||||||
|
will remain in place if the remote endpoint is permanently
|
||||||
|
disconnected. The default persist value is 120 seconds (2
|
||||||
|
minutes).</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>forward
|
||||||
|
<tcpPort>,<dstAddr>/<dstPort>[,<norpAddr>]</literal></entry>
|
||||||
|
|
||||||
|
<entry>This command sets up a "preset" TCP proxy (non-SOCKS) port
|
||||||
|
forwarding session by listening on the specified TCP
|
||||||
|
<parameter><tcpPort></parameter> for connections and then
|
||||||
|
connecting to the given remote
|
||||||
|
<parameter><dstAddr>/<dstPort></parameter>.
|
||||||
|
Optionally, a separate remote
|
||||||
|
<parameter><norpAddr></parameter> may be given. Otherwise, a
|
||||||
|
<emphasis>norp</emphasis> proxy connection is attempted to the
|
||||||
|
given <parameter><dstAddr></parameter> platform on the
|
||||||
|
<emphasis>norp</emphasis> <parameter><port></parameter> (or
|
||||||
|
<parameter><rport></parameter> if specified). Note that
|
||||||
|
multiple such "preset" proxy sessions may be specified on the
|
||||||
|
command-line and each "preset" proxy session can handle multiple
|
||||||
|
connections as needed.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>debug <debugLevel></literal></entry>
|
||||||
|
|
||||||
|
<entrytbl cols="1">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>This command can be used to control the verbosity of
|
||||||
|
<emphasis>norp</emphasis> debug logging output. Generally,
|
||||||
|
the range of the value is 0-12. A higher value results in
|
||||||
|
more verbose, detailed debug output.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</entrytbl>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>trace</literal></entry>
|
||||||
|
|
||||||
|
<entry>This command enables NORM send and receive packet trace
|
||||||
|
logging.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>dlog <fileName></literal></entry>
|
||||||
|
|
||||||
|
<entrytbl cols="1">
|
||||||
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>This command can be used to direct
|
||||||
|
<emphasis>norp</emphasis> debug logging output to a given
|
||||||
|
file. The default <emphasis>norp</emphasis> debug logging is
|
||||||
|
to STDERR.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</entrytbl>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>lport <localNorpPort></literal></entry>
|
||||||
|
|
||||||
|
<entry>This command can enable single host, loopback testing by a
|
||||||
|
having <emphasis>norp</emphasis> listen on a different port number
|
||||||
|
than which it uses as the destination port for remote
|
||||||
|
<emphasis>norp</emphasis> peer signaling. E.g., two
|
||||||
|
<emphasis>norp</emphasis> instances on a single machine can be set
|
||||||
|
up with unique <literal><localNorpPort></literal> values and
|
||||||
|
then use the "<literal>rport</literal>" command to specify each
|
||||||
|
other's destination <emphasis>norp</emphasis> port
|
||||||
|
numbers.</entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry><literal>rport <remoteNorpPort></literal></entry>
|
||||||
|
|
||||||
|
<entry>This command is intended to be used in conjunction with the
|
||||||
|
"<literal>lport</literal>" command to allow separate specification
|
||||||
|
of the destination port number used for remote
|
||||||
|
<emphasis>norp</emphasis> peer signaling.</entry>
|
||||||
|
</row>
|
||||||
|
</tbody>
|
||||||
|
</tgroup>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title>SOCKS Client Configuration</title>
|
||||||
|
|
||||||
|
<para><emphasis>TBD - provide overview and examples (for specific SOCKS
|
||||||
|
clients of note such as Dante, Proxifier, etc) of SOCKS client
|
||||||
|
configuration</emphasis></para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2 id="ExampleUsage">
|
||||||
|
<title>Usage Examples</title>
|
||||||
|
|
||||||
|
<para>The SOCKS client(s) must be configured to use the
|
||||||
|
<emphasis>norp</emphasis> server unless a preset TCP port
|
||||||
|
<literal>forward</literal> is specified. For example the Dante proxy
|
||||||
|
distribution (available from <ulink
|
||||||
|
url="http://www.inet.no/dante/">http://www.inet.no/dante/</ulink>) has a
|
||||||
|
<emphasis>socksify</emphasis> command that is installed and can be used
|
||||||
|
to launch existing network applications so their socket communications
|
||||||
|
are directed through the configured server. With Dante, a SOCKS
|
||||||
|
configuration file (typically <filename>/etc/socks.conf</filename>) or
|
||||||
|
the <constant>SOCKS5_SERVER</constant> environment variable can be used
|
||||||
|
to set the server address and port number.</para>
|
||||||
|
|
||||||
|
<para>The <emphasis>norp</emphasis> "server" is a lightweight module and
|
||||||
|
can be installed on the same end systems requiring the performance
|
||||||
|
benefits of NORM transport. In this case the SOCKS client server
|
||||||
|
configuration is the loopback address and <emphasis>norp</emphasis>
|
||||||
|
SOCKS port number (i.e. <literal>127.0.0.1:7000</literal>). The locally
|
||||||
|
installed norp SOCKS server will signal remote network destinations
|
||||||
|
(e.g., upon TCP connection initiation) to determine if the destination
|
||||||
|
is <emphasis>norp</emphasis>-capable. If possible, it will establish a
|
||||||
|
NORM-connection to the remote <emphasis>norp</emphasis> correspondent
|
||||||
|
that connects to the final destination. Otherwise a direct TCP
|
||||||
|
connection (or UDP relay) will be made to the remote destination.</para>
|
||||||
|
</sect2>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1 id="Commands">
|
||||||
|
<title>The "NORP" UDP Signaling Message Format</title>
|
||||||
|
|
||||||
|
<para>The <emphasis>norp</emphasis> proxy uses UDP signaling to confirm
|
||||||
|
presence of a remote <emphasis>norp</emphasis> peer and to set up (and
|
||||||
|
tear down) NORM transport protocol sessions to support the proxied TCP
|
||||||
|
(and eventually UDP) transport connections. The norp instance originating
|
||||||
|
a SOCKS session request is referred to here as the "originator" and the
|
||||||
|
remote norp peer to which the request is directed is referred to as the
|
||||||
|
"correspondent". The <emphasis>norp</emphasis> "originator" is the server
|
||||||
|
associated with the SOCKS client making a request while the
|
||||||
|
"correspondent" establishes connections with the remote SOCKS
|
||||||
|
destination.</para>
|
||||||
|
|
||||||
|
<para>The following UDP payload format is used for NORP signaling:</para>
|
||||||
|
|
||||||
|
<para><programlisting><?dbfo keep-together="always"?>0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| msgType | reserved | sessionId |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| normNodeId |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| normSrcPort | normDstPort |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| timestamp_sec |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| timestamp_usec |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| content ...
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|
||||||
|
</programlisting></para>
|
||||||
|
|
||||||
|
<para>The NORP message types include:</para>
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term>SOCKS_REQ</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>The message content contains a SOCKS5 Request message from the
|
||||||
|
"originator" to the "correspondent" <emphasis>norp</emphasis>
|
||||||
|
server.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>ACK_REQ</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>The message is used to acknowledge receipt of a SOCKS_REQ
|
||||||
|
message. There is no "content"</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>SOCKS_REP</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>The message content contains a SOCKS5 Reply message from the
|
||||||
|
"correspondent" <emphasis>norp</emphasis> server.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>ACK_REP</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>The message is used to acknoledge receipt of a SOCKS_REP
|
||||||
|
message. There is no "content".</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>ORIG_END</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>This message indicates the "originator"
|
||||||
|
<emphasis>norp</emphasis> server is terminating the given session.
|
||||||
|
There is no "content".</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>CORR_END</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>This message indicates the "correspondent"
|
||||||
|
<emphasis>norp</emphasis> server is terminating the given session.
|
||||||
|
There is no "content".</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>ACK_END</term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>This message is used to acknowledge receipt of either an
|
||||||
|
ORIG_END or CORR_END message. There is no "content".</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
|
||||||
|
<para><emphasis>TBD - describe NORP signaling and the message format given
|
||||||
|
here.</emphasis></para>
|
||||||
|
</sect1>
|
||||||
|
|
||||||
|
<sect1>
|
||||||
|
<title>Future Plans</title>
|
||||||
|
|
||||||
|
<para>There are a number of additional features and refinements planned
|
||||||
|
for the <emphasis>norp</emphasis> implementation. Some of these
|
||||||
|
include:</para>
|
||||||
|
|
||||||
|
<orderedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>Source / destination configuration and "routing" options</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Data compression options</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Security features</para>
|
||||||
|
</listitem>
|
||||||
|
</orderedlist>
|
||||||
|
</sect1>
|
||||||
|
</article>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -0,0 +1,644 @@
|
||||||
|
#ifndef _NORP
|
||||||
|
#define _NORP
|
||||||
|
|
||||||
|
#include "protoSocket.h"
|
||||||
|
#include "protoTimer.h"
|
||||||
|
#include "protoTree.h"
|
||||||
|
#include "protoDispatcher.h"
|
||||||
|
#include "protoPktSOCKS.h"
|
||||||
|
#include "normApi.h"
|
||||||
|
|
||||||
|
class Norp;
|
||||||
|
|
||||||
|
// A "NorpSession" associates a SOCKS client session with either a remote
|
||||||
|
// NORP endpoint (if one was or can be established) or a "direct connect"
|
||||||
|
// (TCP, UDP) if the remote endpoint is not NORP-enabled
|
||||||
|
|
||||||
|
// SOCKS requests/replies relayed via NORM command transmissions
|
||||||
|
// are prepended with this to uniquely identify the command
|
||||||
|
// (SOCKS request or reply and associate it with a NorpSession
|
||||||
|
// TBD - or should the endpoint socket binding addrs/ports be used instead??
|
||||||
|
|
||||||
|
//
|
||||||
|
// ProtoPktNORP is the packet format that NORP uses to relay SOCKS
|
||||||
|
// requests and replies via the NORM application-defined command
|
||||||
|
// signaling mechanism. The format of these commands is:
|
||||||
|
//
|
||||||
|
// 0 1 2 3
|
||||||
|
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | msgType | reserved | sessionId |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | normNodeId |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | normSrcPort | normDstPort |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | timestamp_sec |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | timestamp_usec |
|
||||||
|
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
// | Content ... |
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
class PortPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PortPool(UINT16 basePort);
|
||||||
|
|
||||||
|
UINT16 GrabPort();
|
||||||
|
void ReleasePort(UINT16 thePort);
|
||||||
|
|
||||||
|
private:
|
||||||
|
UINT16 base_port;
|
||||||
|
bool port_array[50];
|
||||||
|
}; // end class PortPool
|
||||||
|
|
||||||
|
class NorpMsg : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpMsg(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~NorpMsg();
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int msgLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(msgLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
MSG_INVALID = 0,
|
||||||
|
SOCKS_REQ, // "content" is a SOCKS5 request
|
||||||
|
REQ_ACK, // request acknowledgment (no content)
|
||||||
|
SOCKS_REP, // "content" is a SOCKS5 request
|
||||||
|
REP_ACK, // reply acknowledgment (no content)
|
||||||
|
ORIG_END, // sent by originator to end session
|
||||||
|
CORR_END, // sent by correspondent to end session
|
||||||
|
ACK_END // end session acknowledgment (by either)
|
||||||
|
};
|
||||||
|
|
||||||
|
Type GetType() const
|
||||||
|
{return (Type)((UINT8*)buffer_ptr)[OFFSET_TYPE];}
|
||||||
|
|
||||||
|
UINT16 GetSessionId() const
|
||||||
|
{return (Type)ntohs(((UINT16*)buffer_ptr)[OFFSET_SESSION_ID]);}
|
||||||
|
|
||||||
|
// note "GetUINT32()" does ntohl() conversion
|
||||||
|
NormNodeId GetNodeId() const
|
||||||
|
{return (NormNodeId)GetUINT32(buffer_ptr + OFFSET_NODE_ID);}
|
||||||
|
|
||||||
|
UINT16 GetSourcePort() const
|
||||||
|
{return (Type)ntohs(((UINT16*)buffer_ptr)[OFFSET_SRC_PORT]);}
|
||||||
|
|
||||||
|
UINT16 GetDestinationPort() const
|
||||||
|
{return (Type)ntohs(((UINT16*)buffer_ptr)[OFFSET_DST_PORT]);}
|
||||||
|
|
||||||
|
void GetTimestamp(struct timeval& timestamp) const
|
||||||
|
{
|
||||||
|
timestamp.tv_sec = GetUINT32(buffer_ptr + OFFSET_SEC);
|
||||||
|
timestamp.tv_usec = GetUINT32(buffer_ptr + OFFSET_USEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetTimestamp(ProtoTime& theTime) const
|
||||||
|
{
|
||||||
|
struct timeval& timestamp = theTime.AccessTimeVal();
|
||||||
|
timestamp.tv_sec = GetUINT32(buffer_ptr + OFFSET_SEC);
|
||||||
|
timestamp.tv_usec = GetUINT32(buffer_ptr + OFFSET_USEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
const UINT32* GetContentPtr() const
|
||||||
|
{return ((const UINT32*)AccessContentPtr());}
|
||||||
|
|
||||||
|
UINT32* AccessContentPtr() const
|
||||||
|
{return (buffer_ptr + OFFSET_CONTENT);}
|
||||||
|
|
||||||
|
unsigned int GetContentLength() const
|
||||||
|
{return (GetLength() - (OFFSET_CONTENT*4));}
|
||||||
|
|
||||||
|
// Packet building methods
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
SetType(MSG_INVALID);
|
||||||
|
SetLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetType(Type msgType)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_TYPE] = (UINT8)msgType;
|
||||||
|
pkt_length = (pkt_length < 1) ? 1 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSessionId(UINT16 sessionId)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_RESERVED] = 0;
|
||||||
|
((UINT16*)buffer_ptr)[OFFSET_SESSION_ID] = htons(sessionId);
|
||||||
|
pkt_length = (pkt_length < 4) ? 4 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNodeId(NormNodeId nodeId)
|
||||||
|
{
|
||||||
|
SetUINT32(buffer_ptr + OFFSET_NODE_ID, nodeId);
|
||||||
|
pkt_length = (pkt_length<8) ? 8 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSourcePort(UINT16 srcPort)
|
||||||
|
{
|
||||||
|
((UINT16*)buffer_ptr)[OFFSET_SRC_PORT] = htons(srcPort);
|
||||||
|
pkt_length = (pkt_length < 10) ? 10 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDestinationPort(UINT16 dstPort)
|
||||||
|
{
|
||||||
|
((UINT16*)buffer_ptr)[OFFSET_DST_PORT] = htons(dstPort);
|
||||||
|
pkt_length = (pkt_length < 12) ? 12 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTimestamp(struct timeval& timestamp)
|
||||||
|
{
|
||||||
|
SetUINT32(buffer_ptr+OFFSET_SEC, timestamp.tv_sec);
|
||||||
|
SetUINT32(buffer_ptr+OFFSET_USEC, timestamp.tv_usec);
|
||||||
|
pkt_length = (pkt_length < 20) ? 20 : pkt_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SetContent(const char* data, unsigned int numBytes)
|
||||||
|
{
|
||||||
|
if ((numBytes + (4*OFFSET_CONTENT)) > GetBufferLength()) return false;
|
||||||
|
memcpy((char*)(buffer_ptr+OFFSET_CONTENT), data, numBytes);
|
||||||
|
SetContentLength(numBytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetContentLength(unsigned int numBytes)
|
||||||
|
{pkt_length = (4*OFFSET_CONTENT) + numBytes;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_TYPE = 0, // UINT8 offset
|
||||||
|
OFFSET_RESERVED = OFFSET_TYPE + 1, // UINT8 offset
|
||||||
|
OFFSET_SESSION_ID = (OFFSET_RESERVED+1)/2, // UINT16 offset
|
||||||
|
OFFSET_NODE_ID = (2*(OFFSET_SESSION_ID+1))/4, // UINT32 offset
|
||||||
|
OFFSET_SRC_PORT = (4*(OFFSET_NODE_ID+1))/2, // UINT16 offset
|
||||||
|
OFFSET_DST_PORT = OFFSET_SRC_PORT + 1, // UINT16 offset
|
||||||
|
OFFSET_SEC = (2*(OFFSET_DST_PORT+1))/4, // UINT32 offset
|
||||||
|
OFFSET_USEC = OFFSET_SEC + 1, // UINT32 offset
|
||||||
|
OFFSET_CONTENT = OFFSET_USEC + 1 // UINT32 offset
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end class NorpMsg
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// A NorpPreset is a non-SOCKS proxied session where a
|
||||||
|
// local TCP port is monitored and connections are proxied
|
||||||
|
// proxied to a preset remote destination
|
||||||
|
class NorpPreset : public ProtoTree::Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpPreset(Norp& norpController, UINT16 tcpPort, const ProtoAddress& dstAddr, const ProtoAddress& norpAddr);
|
||||||
|
~NorpPreset();
|
||||||
|
|
||||||
|
const ProtoAddress& GetDstAddr() const
|
||||||
|
{return dst_addr;}
|
||||||
|
const ProtoAddress& GetNorpAddr() const
|
||||||
|
{return (norp_addr.IsValid() ? norp_addr : dst_addr);}
|
||||||
|
|
||||||
|
bool Listen();
|
||||||
|
|
||||||
|
ProtoSocket& AccessServerSocket()
|
||||||
|
{return server_socket;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* GetKey() const
|
||||||
|
{return ((const char*)&tcp_port);}
|
||||||
|
unsigned int GetKeysize() const
|
||||||
|
{return (sizeof(UINT16) << 3);}
|
||||||
|
|
||||||
|
|
||||||
|
void OnSocketEvent(ProtoSocket& theSocket, ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
Norp& controller;
|
||||||
|
UINT16 tcp_port;
|
||||||
|
ProtoAddress dst_addr;
|
||||||
|
ProtoAddress norp_addr;
|
||||||
|
ProtoSocket server_socket;
|
||||||
|
|
||||||
|
}; // end class NorpPreset
|
||||||
|
|
||||||
|
class NorpPresetList : public ProtoTreeTemplate<NorpPreset>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpPreset* FindPreset(UINT16 tcpPort) const
|
||||||
|
{return Find((char*)&tcpPort, sizeof(UINT16) << 3);}
|
||||||
|
}; // end class NorpPresetList
|
||||||
|
|
||||||
|
class NorpSession : public ProtoTree::Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpSession(Norp& norpController, UINT16 sessionId, NormNodeId originatorId = NORM_NODE_NONE);
|
||||||
|
~NorpSession();
|
||||||
|
|
||||||
|
enum SocksState
|
||||||
|
{
|
||||||
|
SOCKS_VOID, // when session gives self back to "controller" at Close
|
||||||
|
SOCKS_IDLE, // initial, inactive state (socks_client_socket is closed)
|
||||||
|
SOCKS_GET_AUTH_REQ, // first active state, accumulating auth request bytes from client
|
||||||
|
SOCKS_PUT_AUTH_REP, // next, writing auth reply bytes to client
|
||||||
|
SOCKS_GET_REQUEST, // next, accumulate SOCKS request bytes from client
|
||||||
|
SOCKS_PUT_REQUEST, // relaying request to remote NORP peer
|
||||||
|
SOCKS_CONNECTING, // attempt to satisfy request via remote connect, etc (this may need to be refined)
|
||||||
|
SOCKS_GET_REPLY, // awaiting reply from remote NORP peer
|
||||||
|
SOCKS_PUT_REPLY, // next, writing SOCK reply bytes to client
|
||||||
|
SOCKS_CONNECTED, // finally, reading/writing data from/to client
|
||||||
|
SOCKS_SHUTDOWN // session ended, in process of shutting down
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetProxyAddress(const ProtoAddress& proxyAddr)
|
||||||
|
{proxy_addr = proxyAddr;}
|
||||||
|
|
||||||
|
void SetNormRateBounds(double rateMin, double rateMax);
|
||||||
|
|
||||||
|
NormNodeId GetNodeId() const;
|
||||||
|
|
||||||
|
UINT16 GetSessionId() const
|
||||||
|
{return session_id.identifier;}
|
||||||
|
|
||||||
|
NormNodeId GetOriginatorId() const
|
||||||
|
{return session_id.originator;}
|
||||||
|
|
||||||
|
bool IsRemoteSession() const
|
||||||
|
{return (NORM_SESSION_INVALID != norm_session);}
|
||||||
|
|
||||||
|
bool IsRemoteOriginator() const // assumes "IsRemoteSession()"
|
||||||
|
{return (NORM_NODE_NONE == GetOriginatorId());}
|
||||||
|
|
||||||
|
bool AcceptClientConnection(ProtoSocket& serverSocket, bool normEnable = true);
|
||||||
|
|
||||||
|
bool AcceptPresetClientConnection(NorpPreset& preset, bool normEnable);
|
||||||
|
|
||||||
|
SocksState GetSocksState() const
|
||||||
|
{return socks_state;}
|
||||||
|
|
||||||
|
const ProtoAddress& GetClientAddress() const
|
||||||
|
{return socks_client_socket.GetDestination();}
|
||||||
|
|
||||||
|
void Shutdown(); // hard shutdown, including signaling remote via NORP messaging
|
||||||
|
|
||||||
|
bool ShutdownComplete() const; // Tests for inband shutdown completion
|
||||||
|
|
||||||
|
void Close(); // hard local shutdown and cleanup including session deletion by controller
|
||||||
|
|
||||||
|
void OnNormEvent(NormEvent& theEvent);
|
||||||
|
|
||||||
|
bool OnClientRequest(const ProtoPktSOCKS::Request request, const ProtoAddress& srcAddr);
|
||||||
|
|
||||||
|
bool MakeDirectConnect(); // convert remote session to direct connect
|
||||||
|
|
||||||
|
// handles request relayed from remote NORP server
|
||||||
|
bool OnRemoteRequest(const NorpMsg& theMsg, const ProtoAddress& senderAddr);
|
||||||
|
|
||||||
|
bool OnRemoteRequestAcknowledgment(const NorpMsg& theMsg, const ProtoAddress& senderAddr);
|
||||||
|
|
||||||
|
bool OnRemoteReply(const NorpMsg& theMsg, const ProtoAddress& senderAddr);
|
||||||
|
|
||||||
|
bool OnRemoteReplyAcknowledgment(const NorpMsg& theMsg);
|
||||||
|
|
||||||
|
typedef struct Moniker
|
||||||
|
{
|
||||||
|
NormNodeId originator;
|
||||||
|
UINT16 identifier; // TBD - make this UINT32?
|
||||||
|
} Moniker;
|
||||||
|
|
||||||
|
static bool GetNormNodeAddress(NormNodeHandle nodeHandle, ProtoAddress& theAddr);
|
||||||
|
|
||||||
|
static const double NORP_RTT_MIN;
|
||||||
|
static const double NORP_RTT_MAX;
|
||||||
|
static const double NORP_RTT_DEFAULT;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ActivateTimer(ProtoTimer& theTimer);
|
||||||
|
|
||||||
|
const char* GetKey() const
|
||||||
|
{return ((const char*)&session_id);}
|
||||||
|
unsigned int GetKeysize() const
|
||||||
|
{return (sizeof(Moniker) << 3);}
|
||||||
|
|
||||||
|
void OnSocksClientEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
// Note our "norp_tx_socket" is "connected" so we get error message when "port unreachable"
|
||||||
|
bool SendMessage(const NorpMsg& msg)
|
||||||
|
{
|
||||||
|
unsigned int numBytes = msg.GetLength();
|
||||||
|
return norp_tx_socket.Send((const char*)msg.GetBuffer(), numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnNorpMsgTimeout(ProtoTimer& theTimer);
|
||||||
|
|
||||||
|
bool OnCloseTimeout(ProtoTimer& theTimer);
|
||||||
|
|
||||||
|
void OnUdpRelayEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
// These methods are invoked as needed upon different events and SOCKS state transitions
|
||||||
|
bool GetClientAuthRequest();
|
||||||
|
bool PutClientAuthReply();
|
||||||
|
bool GetClientRequest();
|
||||||
|
bool ConnectToRemote(const ProtoAddress& srcAddr);
|
||||||
|
bool BindRemote(UINT16 bindPort);
|
||||||
|
bool OpenUdpRelay();
|
||||||
|
bool PutClientReply();
|
||||||
|
bool GetClientData();
|
||||||
|
bool PutClientData();
|
||||||
|
|
||||||
|
bool PutRemoteRequest(const ProtoPktSOCKS::Request& request, const ProtoAddress& remoteAddr);
|
||||||
|
bool OriginatorStartNorm(const ProtoAddress& senderAddr,
|
||||||
|
NormNodeId corrNormId,
|
||||||
|
UINT16 normSrcPort,
|
||||||
|
UINT16 normDstPort);
|
||||||
|
|
||||||
|
bool PutRemoteReply();
|
||||||
|
|
||||||
|
void OnSocksRemoteEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
// These methods are invoked as needed upon different events and SOCKS state transitions
|
||||||
|
bool GetRemoteData();
|
||||||
|
bool PutRemoteData();
|
||||||
|
|
||||||
|
enum {SOCKS_BUFFER_SIZE = 16384};
|
||||||
|
enum {NORP_BUFFER_SIZE = 512};
|
||||||
|
enum {NORM_BUFFER_SIZE = (8192*1024)};
|
||||||
|
|
||||||
|
unsigned int WriteToNormStream(const char* buffer, unsigned int numBytes);
|
||||||
|
void FlushNormStream(bool eom, NormFlushMode flushMode);
|
||||||
|
unsigned int ComputeNormStreamBufferSegmentCount(unsigned int bufferBytes, UINT16 segmentSize, UINT16 blockSize);
|
||||||
|
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
Norp& controller;
|
||||||
|
bool is_preset; // special "preset" (non-SOCKS) proxy session
|
||||||
|
ProtoTimer close_timer;
|
||||||
|
Moniker session_id;
|
||||||
|
ProtoAddress proxy_addr; // address to advertise for remote connections
|
||||||
|
SocksState socks_state;
|
||||||
|
ProtoSocket socks_client_socket; // TCP connection from this server to SOCKS client
|
||||||
|
ProtoSocket socks_remote_socket; // TCP connection to remote when "direct connect" is used
|
||||||
|
ProtoSocket udp_relay_socket; // UDP relay socket (used for UDP_ASSOC requests)
|
||||||
|
ProtoAddress udp_client_addr; // address of local UDP_ASSOC client
|
||||||
|
|
||||||
|
UINT32 client_buffer[SOCKS_BUFFER_SIZE/sizeof(UINT32)]; // usually data received from client
|
||||||
|
unsigned int client_pending; // total bytes pending reception or transmission
|
||||||
|
unsigned int client_index; // current index
|
||||||
|
UINT32 remote_buffer[SOCKS_BUFFER_SIZE/sizeof(UINT32)]; // usually for data received from remote
|
||||||
|
unsigned int remote_pending; // total bytes pending reception or transmission
|
||||||
|
unsigned int remote_index; // current index
|
||||||
|
|
||||||
|
// NORM-related state
|
||||||
|
bool norm_enable;
|
||||||
|
ProtoSocket norp_tx_socket; // used to send NORP signaling messages
|
||||||
|
ProtoAddress norp_remote_addr;
|
||||||
|
ProtoTimer norp_msg_timer;
|
||||||
|
NorpMsg norp_msg; // current message being transmitted
|
||||||
|
UINT32 norp_msg_buffer[NORP_BUFFER_SIZE/sizeof(UINT32)];
|
||||||
|
double norp_rtt_estimate; // from REQUEST<->ACK or REPLY<->ACK exchange
|
||||||
|
NormSessionHandle norm_session;
|
||||||
|
NormObjectHandle norm_tx_stream;
|
||||||
|
NormObjectHandle norm_rx_stream;
|
||||||
|
bool norm_rx_pending;
|
||||||
|
double persist_interval; // in seconds, to timeout NORM delivery persistence after local TCP disconnect
|
||||||
|
ProtoTime persist_start_time; // marks start of persistence timeout
|
||||||
|
double norm_rate_min;
|
||||||
|
double norm_rate_max;
|
||||||
|
|
||||||
|
UINT16 norm_segment_size;
|
||||||
|
unsigned int norm_stream_buffer_max;
|
||||||
|
unsigned int norm_stream_buffer_count;
|
||||||
|
unsigned int norm_stream_bytes_remain;
|
||||||
|
bool norm_watermark_pending;
|
||||||
|
|
||||||
|
}; // end class NorpSession
|
||||||
|
|
||||||
|
class NorpSessionList : public ProtoTreeTemplate<NorpSession>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpSession* FindSession(UINT16 sessionId, NormNodeId originatorId = NORM_NODE_NONE) const
|
||||||
|
{
|
||||||
|
NorpSession::Moniker id;
|
||||||
|
memset(&id, 0, sizeof(NorpSession::Moniker));
|
||||||
|
id.originator = originatorId;
|
||||||
|
id.identifier = sessionId;
|
||||||
|
return Find((char*)&id, sizeof(NorpSession::Moniker) << 3);
|
||||||
|
} // end NorpSessionList::FindSession()
|
||||||
|
}; // end class NorpSessionList
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// The "Norp" class is an instance of a SOCKS server that manages
|
||||||
|
// SOCKS/NORM (or direct-connect) sessions
|
||||||
|
class Norp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Norp(ProtoDispatcher& theDispatcher);
|
||||||
|
~Norp();
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
DEFAULT_SOCKS_PORT = 7000, // SOCKS server TCP listen port used for NORP
|
||||||
|
DEFAULT_NORP_PORT = 7001, // Where NORP listens for UDP signaling, relayed commands, etc
|
||||||
|
DEFAULT_NORM_PORT = 7002 // Port used for NORM data transfer
|
||||||
|
};
|
||||||
|
|
||||||
|
static const double DEFAULT_TX_RATE;
|
||||||
|
static const double DEFAULT_PERSIST_INTERVAL;
|
||||||
|
|
||||||
|
void SetSocksPort(UINT16 thePort)
|
||||||
|
{socks_port = thePort;}
|
||||||
|
|
||||||
|
void SetProxyAddress(const ProtoAddress& proxyAddr)
|
||||||
|
{proxy_addr = proxyAddr;}
|
||||||
|
|
||||||
|
const ProtoAddress& GetProxyAddress() const
|
||||||
|
{return proxy_addr;}
|
||||||
|
|
||||||
|
bool StartServer(bool normEnable);
|
||||||
|
|
||||||
|
void StopServer();
|
||||||
|
|
||||||
|
void SetLocalNorpPort(UINT16 thePort)
|
||||||
|
{norp_local_port = thePort;}
|
||||||
|
|
||||||
|
void SetRemoteNorpPort(UINT16 thePort)
|
||||||
|
{norp_remote_port = thePort;}
|
||||||
|
|
||||||
|
UINT16 GetNorpPort() const
|
||||||
|
{return norp_remote_port;}
|
||||||
|
|
||||||
|
// In future, this will reference a "routing"
|
||||||
|
// table using the "destAddr"
|
||||||
|
bool GetRemoteNorpAddress(const ProtoAddress& destAddr,
|
||||||
|
ProtoAddress& norpAddr) const
|
||||||
|
{
|
||||||
|
norpAddr = norp_remote_addr.IsValid() ? norp_remote_addr : destAddr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// This sets a remote "norp" peer address that is used instead of
|
||||||
|
// connecting directly to destination endpoints
|
||||||
|
// TBD - add more routing options than this
|
||||||
|
void SetRemoteNorpAddress(const ProtoAddress& remoteAddr)
|
||||||
|
{norp_remote_addr = remoteAddr;}
|
||||||
|
|
||||||
|
void SetInitialRtt(double seconds)
|
||||||
|
{norp_rtt_init = seconds;}
|
||||||
|
|
||||||
|
double GetInitialRtt() const
|
||||||
|
{return norp_rtt_init;}
|
||||||
|
|
||||||
|
// NORM protocol parameters
|
||||||
|
void SetNormNodeId(NormNodeId nodeId)
|
||||||
|
{norm_node_id = nodeId;}
|
||||||
|
NormNodeId GetNormNodeId() const
|
||||||
|
{return norm_node_id;}
|
||||||
|
|
||||||
|
NormInstanceHandle GetNormInstance() const
|
||||||
|
{return norm_instance;}
|
||||||
|
|
||||||
|
void SetNormPort(UINT16 thePort)
|
||||||
|
{norm_port = thePort;}
|
||||||
|
UINT16 GetNormPort() const
|
||||||
|
{return norm_port;}
|
||||||
|
|
||||||
|
/*
|
||||||
|
UINT16 GrabPort()
|
||||||
|
{return port_pool.GrabPort();}
|
||||||
|
void ReleasePort(UINT16 thePort)
|
||||||
|
{port_pool.ReleasePort(thePort);}
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum NormCC
|
||||||
|
{
|
||||||
|
NORM_CC,
|
||||||
|
NORM_CCE,
|
||||||
|
NORM_CCL,
|
||||||
|
NORM_FIXED
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetNormCC(NormCC ccMode)
|
||||||
|
{norm_cc_mode = ccMode;}
|
||||||
|
NormCC GetNormCC() const
|
||||||
|
{return norm_cc_mode;}
|
||||||
|
|
||||||
|
// For fixed-rate operation
|
||||||
|
void SetNormTxRate(double txRate)
|
||||||
|
{norm_tx_rate = txRate;}
|
||||||
|
double GetNormTxRate() const
|
||||||
|
{return norm_tx_rate;}
|
||||||
|
|
||||||
|
// Sets upper bound on _cumulative_ NormSession
|
||||||
|
// transmit rates
|
||||||
|
void SetNormTxLimit(double txLimit)
|
||||||
|
{norm_tx_limit = txLimit;}
|
||||||
|
|
||||||
|
double GetNormTxLimit() const
|
||||||
|
{return norm_tx_limit;}
|
||||||
|
|
||||||
|
void SetNormTrace(bool enable)
|
||||||
|
{norm_trace = enable;}
|
||||||
|
bool GetNormTrace() const
|
||||||
|
{return norm_trace;}
|
||||||
|
|
||||||
|
void SetNormSegmentSize(UINT16 numBytes)
|
||||||
|
{norm_segment_size = numBytes;}
|
||||||
|
UINT16 GetNormSegmentSize() const
|
||||||
|
{return norm_segment_size;}
|
||||||
|
|
||||||
|
void SetNormBlockSize(UINT32 numSegments)
|
||||||
|
{norm_block_size = numSegments;}
|
||||||
|
UINT16 GetNormBlockSize() const
|
||||||
|
{return norm_block_size;}
|
||||||
|
|
||||||
|
void SetNormParityCount(UINT16 numSegments)
|
||||||
|
{norm_parity_count = numSegments;}
|
||||||
|
UINT16 GetNormParityCount() const
|
||||||
|
{return norm_parity_count;}
|
||||||
|
|
||||||
|
void SetNormParityAuto(UINT16 numSegments)
|
||||||
|
{norm_parity_auto = numSegments;}
|
||||||
|
UINT16 GetNormParityAuto() const
|
||||||
|
{return norm_parity_auto;}
|
||||||
|
|
||||||
|
ProtoSocket::Notifier& GetSocketNotifier() const
|
||||||
|
{return static_cast<ProtoSocket::Notifier&>(dispatcher);}
|
||||||
|
|
||||||
|
void ActivateTimer(ProtoTimer& theTimer)
|
||||||
|
{dispatcher.ActivateTimer(theTimer);}
|
||||||
|
|
||||||
|
bool SendMessage(const NorpMsg& msg, const ProtoAddress& dstAddr)
|
||||||
|
{return norp_rx_socket.SendTo((const char*)msg.GetBuffer(), msg.GetLength(), dstAddr);}
|
||||||
|
|
||||||
|
void OnNorpSocketEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
void OnSessionClose(NorpSession& theSession);
|
||||||
|
|
||||||
|
bool AddPreset(UINT16 tcpPort, const ProtoAddress& dstAddr, const ProtoAddress& norpAddr);
|
||||||
|
bool AcceptPresetClientConnection(NorpPreset& preset);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void AddSession(NorpSession& session);
|
||||||
|
void RemoveSession(NorpSession& session);
|
||||||
|
|
||||||
|
void OnSocksServerEvent(ProtoSocket& theSocket,
|
||||||
|
ProtoSocket::Event theEvent);
|
||||||
|
|
||||||
|
static void NormEventCallback(ProtoDispatcher::Descriptor descriptor,
|
||||||
|
ProtoDispatcher::Event theEvent,
|
||||||
|
const void* userData);
|
||||||
|
|
||||||
|
void OnNormEvent();
|
||||||
|
void OnRemoteRequest(const NorpMsg& theMsg, const ProtoAddress& senderAddr);
|
||||||
|
void OnRemoteReply(const NorpMsg& theMsg, const ProtoAddress& senderAddr);
|
||||||
|
|
||||||
|
// Member variables
|
||||||
|
ProtoDispatcher& dispatcher; // TBD - make Norp multi-threaded w/ a pool of dispatchers
|
||||||
|
|
||||||
|
ProtoSocket socks_server_socket; // (SOCKS clients connect to this)
|
||||||
|
UINT16 socks_port;
|
||||||
|
ProtoAddress proxy_addr;
|
||||||
|
UINT16 next_session_id; // used to dole out unique session ids
|
||||||
|
NorpSessionList session_list; // list of client and remote sessions
|
||||||
|
unsigned int session_count;
|
||||||
|
NorpPresetList preset_list; // list of preset proxies w/ listening TCP socket
|
||||||
|
|
||||||
|
ProtoSocket norp_rx_socket; // UDP socket for receiving NORP signaling
|
||||||
|
UINT16 norp_local_port; // For loopback debugging, we allow "local" server port to be different than "remote"
|
||||||
|
UINT16 norp_remote_port;
|
||||||
|
ProtoAddress norp_remote_addr; // if unspecified, we proxy directly to connection destination address
|
||||||
|
double norp_rtt_init; // used as initial roundtrip estimate for NORP signaling
|
||||||
|
|
||||||
|
bool norm_enable;
|
||||||
|
NormInstanceHandle norm_instance;
|
||||||
|
NormNodeId norm_node_id;
|
||||||
|
|
||||||
|
// NORM parameters (including some for debugging
|
||||||
|
UINT16 norm_port;
|
||||||
|
NormCC norm_cc_mode;
|
||||||
|
double norm_tx_rate; // in bits/sec, only applicable for cc_mode == NORM_FIXED
|
||||||
|
double norm_tx_limit; // in bits/sec (_cumulative_ rate limit option)
|
||||||
|
char iface_name[64]; // Network interface
|
||||||
|
UINT16 norm_segment_size; // payload bytes per NORM_DATA message
|
||||||
|
UINT16 norm_block_size; // number of user data segments per FEC coding block
|
||||||
|
UINT16 norm_parity_count; // number of _computed_ parity segments per FEC coding block
|
||||||
|
UINT16 norm_parity_auto; // number of proactive (automatically sent) parity segments per block
|
||||||
|
|
||||||
|
bool norm_trace;
|
||||||
|
|
||||||
|
//PortPool port_pool;
|
||||||
|
|
||||||
|
}; // end class Norp
|
||||||
|
|
||||||
|
#endif // _NORP
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
#ifndef _NORP_VERSION
|
||||||
|
#define NORP_VERSION "0.1b5"
|
||||||
|
#endif // NORP_VERSION
|
||||||
|
|
@ -0,0 +1,379 @@
|
||||||
|
|
||||||
|
#ifndef _PROTO_SOCKS
|
||||||
|
#define _PROTO_SOCKS
|
||||||
|
|
||||||
|
#include "protoPkt.h"
|
||||||
|
#include "protoAddress.h"
|
||||||
|
|
||||||
|
// These classes provide message parsing and building for
|
||||||
|
// the RFC 1928 SOCKS5 protocol specification.
|
||||||
|
// NOTES:
|
||||||
|
// 1) Only the methods needed for SOCKS server operation are defined here so far
|
||||||
|
// 2) Additional external helper logic is needed to incrementally read data from a
|
||||||
|
// SOCKS TCP client-server socket for a full SOCKS message. The message parsing
|
||||||
|
// here assumes the message has been read up to the point of whatever field
|
||||||
|
// is being requested.
|
||||||
|
|
||||||
|
namespace ProtoPktSOCKS
|
||||||
|
{
|
||||||
|
// SOCKS5 message definitions per RFC1928
|
||||||
|
|
||||||
|
// SOCKS5 auth request: VERSION + NMETHODS + METHOD_LIST ...
|
||||||
|
// 1 byte + 1 byte + N bytes
|
||||||
|
|
||||||
|
// SOCKS5 authentication methods
|
||||||
|
enum AuthType
|
||||||
|
{
|
||||||
|
AUTH_NONE = 0x00,
|
||||||
|
AUTH_GSSAPI = 0x01,
|
||||||
|
AUTH_USER = 0x02, // username / password
|
||||||
|
AUTH_INVALID = 0xff // no acceptable method
|
||||||
|
};
|
||||||
|
|
||||||
|
class AuthRequest : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AuthRequest(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~AuthRequest();
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int reqLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(reqLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
UINT8 GetVersion() const
|
||||||
|
{return ((pkt_length > OFFSET_VERSION) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_VERSION]) : 0);}
|
||||||
|
|
||||||
|
UINT8 GetMethodCount() const
|
||||||
|
{return ((pkt_length > OFFSET_NMETHOD) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_NMETHOD]) : 0);}
|
||||||
|
|
||||||
|
AuthType GetMethod(UINT8 index) const
|
||||||
|
{return ((pkt_length > (unsigned int)(OFFSET_METHODS + index)) ?
|
||||||
|
(AuthType)(((UINT8*)buffer_ptr)[OFFSET_METHODS + index]) : AUTH_INVALID);}
|
||||||
|
|
||||||
|
// TBD - implement auth request building (don't need this for a server)
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_VERSION = 0, // 1 byte
|
||||||
|
OFFSET_NMETHOD = OFFSET_VERSION + 1, // 1 byte
|
||||||
|
OFFSET_METHODS = OFFSET_NMETHOD + 1 // N bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end class ProtoPktSOCKS::AuthRequest
|
||||||
|
|
||||||
|
// SOCKS5 auth reply: VERSION + METHOD_SELECTED
|
||||||
|
// bytes: 1 + 1
|
||||||
|
class AuthReply : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AuthReply(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~AuthReply();
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int replyLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(replyLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
UINT8 GetVersion() const
|
||||||
|
{return ((pkt_length > OFFSET_VERSION) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_VERSION]) : 0);}
|
||||||
|
|
||||||
|
UINT8 GetMethod() const
|
||||||
|
{return ((pkt_length > OFFSET_METHOD) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_METHOD]) : AUTH_INVALID);}
|
||||||
|
|
||||||
|
void SetVersion(UINT8 version)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_VERSION] = version;
|
||||||
|
pkt_length = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMethod(AuthType method)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_METHOD] = method;
|
||||||
|
pkt_length = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_VERSION = 0, // 1 byte
|
||||||
|
OFFSET_METHOD = OFFSET_VERSION + 1 // 1 byte
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // end class ProtoPktSOCKS::AuthReply
|
||||||
|
|
||||||
|
// SOCKS5 request: VERSION + REQ + RESV + ADDR_TYP + DST.ADDR + DST.PORT
|
||||||
|
// bytes: 1 + 1 + 1 + 1 + N + 2
|
||||||
|
|
||||||
|
// SOCKS5 address types (1 byte)
|
||||||
|
enum AddrType
|
||||||
|
{
|
||||||
|
ADDR_INVALID = 0x00, // invalid addr type (for implementation)
|
||||||
|
IPv4 = 0x01, // 4-bytes, network byte order
|
||||||
|
NAME = 0x03, // 1-byte of "name" length, followed by "name"
|
||||||
|
IPv6 = 0x04 // 16-bytes, network byte order
|
||||||
|
}; // end ProtoPktSOCKS::AddrType
|
||||||
|
|
||||||
|
class Request : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Request(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~Request();
|
||||||
|
|
||||||
|
enum Command
|
||||||
|
{
|
||||||
|
CMD_INVALID = 0x00,
|
||||||
|
CONNECT = 0x01,
|
||||||
|
BIND = 0x02,
|
||||||
|
UDP_ASSOC = 0x03 // Setup UDP association
|
||||||
|
}; // end ProtoPktSOCKS::Request::Command
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int replyLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(replyLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
UINT8 GetVersion() const
|
||||||
|
{return ((pkt_length > OFFSET_VERSION) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_VERSION]) : 0);}
|
||||||
|
|
||||||
|
Command GetCommand() const
|
||||||
|
{return ((pkt_length > OFFSET_COMMAND) ?
|
||||||
|
(Command)(((UINT8*)buffer_ptr)[OFFSET_COMMAND]) : CMD_INVALID);}
|
||||||
|
|
||||||
|
AddrType GetAddressType() const
|
||||||
|
{return ((pkt_length > OFFSET_ATYPE) ?
|
||||||
|
(AddrType)(((UINT8*)buffer_ptr)[OFFSET_ATYPE]) : ADDR_INVALID);}
|
||||||
|
|
||||||
|
UINT8 GetAddressLength() const;
|
||||||
|
|
||||||
|
const char* GetAddressPtr() const
|
||||||
|
{return (const char*)AccessAddressPtr();}
|
||||||
|
|
||||||
|
UINT16 GetPort() const;
|
||||||
|
|
||||||
|
bool GetAddress(ProtoAddress& theAddr) const;
|
||||||
|
|
||||||
|
// TBD - implement request building (don't need this for a server)
|
||||||
|
|
||||||
|
void SetVersion(UINT8 version)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_VERSION] = version;
|
||||||
|
pkt_length = 1;
|
||||||
|
}
|
||||||
|
void SetCommand(Command cmd)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_COMMAND] = (UINT8)cmd;
|
||||||
|
pkt_length = 2;
|
||||||
|
}
|
||||||
|
void SetAddressType(AddrType addrType)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_RESERVED] = 0;
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)addrType;
|
||||||
|
pkt_length = 4;
|
||||||
|
}
|
||||||
|
bool SetAddress(const ProtoAddress& theAddr); // note this sets port, too
|
||||||
|
bool SetName(const char* theName);
|
||||||
|
bool SetPort(UINT16 thePort);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_VERSION = 0, // 1 byte
|
||||||
|
OFFSET_COMMAND = OFFSET_VERSION + 1, // 1 byte
|
||||||
|
OFFSET_RESERVED = OFFSET_COMMAND + 1, // 1 byte
|
||||||
|
OFFSET_ATYPE = OFFSET_RESERVED + 1, // 1 byte
|
||||||
|
OFFSET_ADDR = OFFSET_ATYPE + 1 // N bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
char* AccessAddressPtr() const
|
||||||
|
{
|
||||||
|
char* addrPtr = ((char*)buffer_ptr) + OFFSET_ADDR;
|
||||||
|
return (NAME == GetAddressType()) ? (addrPtr + 1) : addrPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end class ProtoPktSOCKS::Request
|
||||||
|
|
||||||
|
// SOCKS5 REPLY: VERSION + REP + RESV + ATYP + BIND.ADDR + BIND.PORT
|
||||||
|
// bytes: 1 + 1 + 1 + 1 + N + 2
|
||||||
|
class Reply : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Reply(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~Reply();
|
||||||
|
|
||||||
|
enum Type
|
||||||
|
{
|
||||||
|
SUCCESS = 0x00, // succeeded
|
||||||
|
FAILURE = 0x01, // general failure
|
||||||
|
DENIED = 0x02, // connection not allowed
|
||||||
|
NET_X = 0x03, // network unreachable
|
||||||
|
HOST_X = 0x04, // host unreachable
|
||||||
|
REFUSED = 0x05, // connection refused
|
||||||
|
TTL_X = 0x06, // TTL expired
|
||||||
|
CMD_X = 0x07, // command not supported
|
||||||
|
ADDR_X = 0x08, // address type not supported
|
||||||
|
TYPE_INVALID = 0xff // invalid reply type
|
||||||
|
}; // end ProtoPktSOCKS::Reply::Type
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int replyLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(replyLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
UINT8 GetVersion() const
|
||||||
|
{return ((pkt_length > OFFSET_VERSION) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_VERSION]) : 0);}
|
||||||
|
|
||||||
|
Type GetType() const
|
||||||
|
{return ((pkt_length > OFFSET_TYPE) ?
|
||||||
|
(Type)(((UINT8*)buffer_ptr)[OFFSET_TYPE]) : TYPE_INVALID);}
|
||||||
|
|
||||||
|
AddrType GetAddressType() const
|
||||||
|
{return ((pkt_length > OFFSET_ATYPE) ?
|
||||||
|
(AddrType)(((UINT8*)buffer_ptr)[OFFSET_ATYPE]) : ADDR_INVALID);}
|
||||||
|
|
||||||
|
UINT8 GetAddressLength() const;
|
||||||
|
|
||||||
|
const char* GetAddressPtr() const
|
||||||
|
{return (const char*)AccessAddressPtr();}
|
||||||
|
|
||||||
|
UINT16 GetPort() const;
|
||||||
|
|
||||||
|
bool GetAddress(ProtoAddress& theAddr) const;
|
||||||
|
|
||||||
|
// Reply building (call these in order
|
||||||
|
void SetVersion(UINT8 version)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_VERSION] = version;
|
||||||
|
pkt_length = 1;
|
||||||
|
}
|
||||||
|
void SetType(Type replyType)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_TYPE] = (UINT8)replyType;
|
||||||
|
pkt_length = 2;
|
||||||
|
}
|
||||||
|
void SetAddress(AddrType addrType, const char* addrPtr, UINT8 addrLen);
|
||||||
|
void SetPort(UINT16 thePort);
|
||||||
|
void SetAddress(const ProtoAddress& theAddr); // sets address and port from ProtoAddress
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_VERSION = 0, // 1 byte
|
||||||
|
OFFSET_TYPE = OFFSET_VERSION + 1, // 1 byte
|
||||||
|
OFFSET_RESERVED = OFFSET_TYPE + 1, // 1 byte
|
||||||
|
OFFSET_ATYPE = OFFSET_RESERVED + 1, // 1 byte
|
||||||
|
OFFSET_ADDR = OFFSET_ATYPE + 1 // N bytes
|
||||||
|
};
|
||||||
|
|
||||||
|
char* AccessAddressPtr() const
|
||||||
|
{
|
||||||
|
char* addrPtr = ((char*)buffer_ptr) + OFFSET_ADDR;
|
||||||
|
return (NAME == GetAddressType()) ? (addrPtr + 1) : addrPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end class ProtoPktSOCKS::Reply
|
||||||
|
|
||||||
|
// UDP relay header: RESV + FRAG + ATYP + DST.ADDR + DST.PORT + DATA
|
||||||
|
// bytes: 2 + 1 1 + N + 2 + K
|
||||||
|
|
||||||
|
class UdpRequest : public ProtoPkt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UdpRequest(UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool initFromBuffer = true,
|
||||||
|
bool freeOnDestruct = false);
|
||||||
|
~UdpRequest();
|
||||||
|
|
||||||
|
bool InitFromBuffer(unsigned int requestLength,
|
||||||
|
UINT32* bufferPtr = NULL,
|
||||||
|
unsigned int numBytes = 0,
|
||||||
|
bool freeOnDestruct = false)
|
||||||
|
{return ProtoPkt::InitFromBuffer(requestLength, bufferPtr, numBytes, freeOnDestruct);}
|
||||||
|
|
||||||
|
UINT8 GetFrag() const
|
||||||
|
{return ((pkt_length > OFFSET_FRAG) ?
|
||||||
|
(((UINT8*)buffer_ptr)[OFFSET_FRAG]) : 0);}
|
||||||
|
|
||||||
|
AddrType GetAddressType() const
|
||||||
|
{return ((pkt_length > OFFSET_ATYPE) ?
|
||||||
|
(AddrType)(((UINT8*)buffer_ptr)[OFFSET_ATYPE]) : ADDR_INVALID);}
|
||||||
|
|
||||||
|
UINT8 GetAddressLength() const;
|
||||||
|
|
||||||
|
const char* GetAddressPtr() const
|
||||||
|
{return (const char*)AccessAddressPtr();}
|
||||||
|
|
||||||
|
UINT16 GetPort() const;
|
||||||
|
|
||||||
|
bool GetAddress(ProtoAddress& theAddr) const;
|
||||||
|
|
||||||
|
const char* GetDataPtr() const
|
||||||
|
{return (const char*)AccessDataPtr();}
|
||||||
|
|
||||||
|
unsigned int GetDataLength() const
|
||||||
|
{return (GetLength() - (GetDataPtr() - ((const char*)buffer_ptr)));}
|
||||||
|
|
||||||
|
|
||||||
|
// Packet building (call these in order)
|
||||||
|
void SetFragment(UINT8 fragId)
|
||||||
|
{
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_RESERVED] = 0;
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_FRAG] = fragId;
|
||||||
|
pkt_length = OFFSET_FRAG + 1;
|
||||||
|
}
|
||||||
|
void SetAddress(AddrType addrType, const char* addrPtr, UINT8 addrLen);
|
||||||
|
void SetPort(UINT16 thePort);
|
||||||
|
void SetAddress(const ProtoAddress& theAddr); // sets address and port from ProtoAddress
|
||||||
|
void SetData(const char* data, unsigned int numBytes)
|
||||||
|
{
|
||||||
|
memcpy(AccessDataPtr(), data, numBytes);
|
||||||
|
SetDataLength(numBytes);
|
||||||
|
}
|
||||||
|
void SetDataLength(unsigned int numBytes)
|
||||||
|
{pkt_length = (GetDataPtr() - ((char*)buffer_ptr)) + numBytes;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OFFSET_RESERVED = 0, // 2 bytes
|
||||||
|
OFFSET_FRAG = OFFSET_RESERVED + 2, // 1 byte
|
||||||
|
OFFSET_ATYPE = OFFSET_FRAG + 1, // 1 byte
|
||||||
|
OFFSET_ADDR = OFFSET_ATYPE + 1 // N bytes
|
||||||
|
};
|
||||||
|
char* AccessAddressPtr() const
|
||||||
|
{
|
||||||
|
char* addrPtr = ((char*)buffer_ptr) + OFFSET_ADDR;
|
||||||
|
return (NAME == GetAddressType()) ? (addrPtr + 1) : addrPtr;
|
||||||
|
}
|
||||||
|
char* AccessDataPtr() const
|
||||||
|
{return (AccessAddressPtr() + GetAddressLength() + 2);}
|
||||||
|
|
||||||
|
}; // end class ProtoPktSOCKS::UdpRequest
|
||||||
|
|
||||||
|
}; // end namespace ProtoPktSOCKS
|
||||||
|
|
||||||
|
#endif // _PROTO_SOCKS
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#########################################################################
|
||||||
|
# "norp" common Makefile portion
|
||||||
|
#
|
||||||
|
|
||||||
|
SHELL=/bin/sh
|
||||||
|
|
||||||
|
.SUFFIXES: .cpp $(.SUFFIXES)
|
||||||
|
|
||||||
|
# "chant" depends upon the NRL "norm" and "protolib" libraries
|
||||||
|
NORM = ../norm
|
||||||
|
PROTOLIB = $(NORM)/protolib
|
||||||
|
LIBPROTO = $(PROTOLIB)/lib/libprotokit.a
|
||||||
|
LIBNORM = $(NORM)/lib/libnorm.a
|
||||||
|
|
||||||
|
COMMON = ../src/common
|
||||||
|
|
||||||
|
NORP_SRC = $(COMMON)/norp.cpp $(COMMON)/norpApp.cpp \
|
||||||
|
$(COMMON)/protoPktSOCKS.cpp $(SYSTEM_SRC)
|
||||||
|
|
||||||
|
NORP_OBJ = $(NORP_SRC:.cpp=.o)
|
||||||
|
|
||||||
|
INCLUDES = -I../include -I$(NORM)/include -I$(PROTOLIB)/include
|
||||||
|
|
||||||
|
CFLAGS = -g -DPROTO_DEBUG -Wall -O -fPIC $(SYSTEM_CFLAGS) $(PROTO_CFLAGS) $(INCLUDES)
|
||||||
|
|
||||||
|
LIBS = $(SYSTEM_LIBS)
|
||||||
|
|
||||||
|
TARGETS = norp
|
||||||
|
|
||||||
|
# Rule for C++ .cpp extension
|
||||||
|
.cpp.o:
|
||||||
|
$(CC) -c $(CFLAGS) -o $*.o $*.cpp
|
||||||
|
|
||||||
|
|
||||||
|
all: norp
|
||||||
|
|
||||||
|
$(PROTOLIB)/lib/libprotokit.a:
|
||||||
|
$(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) libprotokit.a
|
||||||
|
|
||||||
|
$(NORM)/lib/libnorm.a:
|
||||||
|
$(MAKE) -C $(NORM)/makefiles -f Makefile.$(SYSTEM) libnorm.a
|
||||||
|
|
||||||
|
norp: $(LIBPROTO) $(LIBNORM) $(NORP_OBJ)
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $(NORP_OBJ) $(LIBS) $(LIBNORM) $(LIBPROTO)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f norp $(COMMON)/*.o;
|
||||||
|
$(MAKE) -C $(NORM)/makefiles -f Makefile.$(SYSTEM) clean;
|
||||||
|
$(MAKE) -C $(PROTOLIB)/makefiles -f Makefile.$(SYSTEM) clean;
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
|
||||||
|
# DO NOT DELETE THIS LINE -- mkdep uses it.
|
||||||
|
# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
#
|
||||||
|
# Linux wxWindows Makefile definitions
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1) Where to find the wxWindows files
|
||||||
|
WX_FLAGS = `wx-config --cxxflags`
|
||||||
|
WX_LIBS = `wx-config --libs`
|
||||||
|
|
||||||
|
# 2) System specific additional libraries, include paths, etc
|
||||||
|
# (Where to find X11 libraries, etc)
|
||||||
|
#
|
||||||
|
SYSTEM_FLAGS =
|
||||||
|
SYSTEM_INCLUDES =
|
||||||
|
SYSTEM_LIBS = -lm -lpthread
|
||||||
|
SYSTEM_REZ = touch
|
||||||
|
|
||||||
|
|
||||||
|
PROTO_CFLAGS = -DLINUX -DUNIX -DHAVE_IPV6 -DHAVE_GETLOGIN -D_FILE_OFFSET_BITS=64 -DHAVE_LOCKF -DHAVE_OLD_SIGNALHANDLER -DHAVE_DIRFD -DHAVE_ASSERT
|
||||||
|
|
||||||
|
SYSTEM = linux
|
||||||
|
CC = g++
|
||||||
|
RANLIB = ranlib
|
||||||
|
AR = ar
|
||||||
|
|
||||||
|
SYSTEM_SRC =
|
||||||
|
|
||||||
|
include Makefile.common
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#
|
||||||
|
# MacOS-X wxWindows Makefile definitions
|
||||||
|
#
|
||||||
|
|
||||||
|
# 1) wxWidgets flags and libs
|
||||||
|
WX_CONFIG_PATH = /usr/local/bin/wx-config
|
||||||
|
WX_CFLAGS = `$(WX_CONFIG_PATH) --cxxflags`
|
||||||
|
WX_LIBS = `$(WX_CONFIG_PATH) --libs`
|
||||||
|
|
||||||
|
# 2) System-specific flags and libs
|
||||||
|
SYSTEM_CFLAGS = -arch x86_64
|
||||||
|
SYSTEM_LIBS = -arch x86_64 -lresolv
|
||||||
|
|
||||||
|
# 3) System-specific Protolib flags (_must_ correspond to Protolib SYSTEM_HAVES)
|
||||||
|
# Must choose appropriate for the following:
|
||||||
|
#
|
||||||
|
# A) -DHAVE_CUSERID (preferred) or -DHAVE_GETLOGIN for cuserid() or getlogin()
|
||||||
|
# functions to obtain user's login name (We may change this to getpwd()
|
||||||
|
# if that is better across different platforms and login environments)
|
||||||
|
#
|
||||||
|
# B) -DHAVE_LOCKF (preferred) or -D_LOCKF for lockf() or flock() file locking
|
||||||
|
# functions to attempt exclusive lock on writing to files
|
||||||
|
#
|
||||||
|
# C) Specify -DHAVE_DIRFD if you system provides the "dirfd()" function
|
||||||
|
# (Most don't have it defined ... but some do)
|
||||||
|
#
|
||||||
|
# D) Optionally specify -DHAVE_ASSERT if your system has a built-in ASSERT()
|
||||||
|
# routine.
|
||||||
|
#
|
||||||
|
# E) Some systems (SOLARIS/SUNOS) have a few gotchas which require
|
||||||
|
# some #ifdefs to avoid compiler warnings ... so you might need
|
||||||
|
# to specify -DSOLARIS or -DSUNOS depending on your OS.
|
||||||
|
# (We export these for other Makefiles as needed)
|
||||||
|
#
|
||||||
|
|
||||||
|
PROTO_CFLAGS = -DUNIX -DHAVE_IPV6 -DHAVE_ASSERT -DHAVE_GETLOGIN -DHAVE_FLOCK -DHAVE_DIRFD
|
||||||
|
|
||||||
|
# Additional system-specific source code to use
|
||||||
|
SYSTEM_SRC =
|
||||||
|
|
||||||
|
SYSTEM = macosx
|
||||||
|
CC = c++
|
||||||
|
RANLIB = ranlib
|
||||||
|
AR = ar
|
||||||
|
|
||||||
|
SYSTEM_BUNDLE = chant.app
|
||||||
|
|
||||||
|
include Makefile.common
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,378 @@
|
||||||
|
#include "protoApp.h"
|
||||||
|
#include "protoNet.h"
|
||||||
|
#include "norp.h"
|
||||||
|
#include "norpVersion.h"
|
||||||
|
|
||||||
|
#include <stdio.h> // for stderr
|
||||||
|
#include <stdlib.h> // for atoi()
|
||||||
|
|
||||||
|
class NorpApp : public ProtoApp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NorpApp();
|
||||||
|
~NorpApp();
|
||||||
|
|
||||||
|
// Required verrides from ProtoApp base
|
||||||
|
bool OnStartup(int argc, const char*const* argv);
|
||||||
|
bool ProcessCommands(int argc, const char*const* argv);
|
||||||
|
void OnShutdown();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum CmdType {CMD_INVALID, CMD_ARG, CMD_NOARG};
|
||||||
|
static CmdType GetCmdType(const char* string);
|
||||||
|
bool OnCommand(const char* cmd, const char* val);
|
||||||
|
void Usage();
|
||||||
|
|
||||||
|
static const char* const CMD_LIST[];
|
||||||
|
|
||||||
|
Norp norp;
|
||||||
|
bool norm_enable;
|
||||||
|
|
||||||
|
}; // end class NorpApp
|
||||||
|
|
||||||
|
// Our application instance
|
||||||
|
PROTO_INSTANTIATE_APP(NorpApp)
|
||||||
|
|
||||||
|
|
||||||
|
NorpApp::NorpApp()
|
||||||
|
: norp(dispatcher), norm_enable(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NorpApp::~NorpApp()
|
||||||
|
{
|
||||||
|
norp.StopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NorpApp::Usage()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: norp [interface <ifaceName>][address <publicAddr>][sport <socksPort>][port <norpPort>]\n"
|
||||||
|
" [norm {on|off}][id <normId>][nport <normPort>][cce | ccl | rate <bits/sec>][persist <seconds>][limit <bits/sec>]\n"
|
||||||
|
" [correspondent <remoteNorpAddr>][forward <tcpPort>,<destAddr>/<destPort>[,<remoteNorpAddr>]][version]\n"
|
||||||
|
" [debug <level>][trace][dlog <debugLog>][lport <localNorpPort>][rport <remoteNorpPort>]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* const NorpApp::CMD_LIST[] =
|
||||||
|
{
|
||||||
|
"+interface", // "public facing" interface (its address is used for bindings)
|
||||||
|
"+address", // explicit "public facing" address to use for bindings
|
||||||
|
"+sport", // SOCKS server port (7000 by default)
|
||||||
|
"+port", // NORP UDP signaling port number (7001 by default)
|
||||||
|
"+norm", // "on" or "off" to enable/disable NORM proxying ("on" by default)
|
||||||
|
"+id", // set local NormNodeId (auto set from IP address by default)
|
||||||
|
"+nport", // NORM port (UDP) (7002 by default)
|
||||||
|
"-cce", // Use NORM-CCE instead of NORM-CC
|
||||||
|
"-ccl", // Use NORM-CCL instead of NORM-CC
|
||||||
|
"+rate", // set fixed transmit rate (no congestion control)
|
||||||
|
"+limit", // set _cumulaltive_ NORP transmit rate limit
|
||||||
|
"+persist", // <seconds> how long to persist NORM data delivery to receiver after TCP socket closure
|
||||||
|
"+debug", // set debug level
|
||||||
|
"-trace", // enables NORM protocol packet send/recv trace in debug output
|
||||||
|
"+dlog", // specify a file for debug logging
|
||||||
|
"+lport", // "local" NORP port (for loopback debugging)
|
||||||
|
"+rport", // "remote" NORP port (for loopback debugging)
|
||||||
|
"+forward", // <port>,<dstAddr>/<dstPort>[,<remoteNorpAddr>] to set up a preset proxy TCP listener
|
||||||
|
"+correspondent", // <remoteNorpAddr> to route proxied connections through remote NORP proxy at given addr
|
||||||
|
"-version", // print version number and exit
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
NorpApp::CmdType NorpApp::GetCmdType(const char* cmd)
|
||||||
|
{
|
||||||
|
if (!cmd) return CMD_INVALID;
|
||||||
|
unsigned int len = strlen(cmd);
|
||||||
|
bool matched = false;
|
||||||
|
CmdType type = CMD_INVALID;
|
||||||
|
const char* const* nextCmd = CMD_LIST;
|
||||||
|
while (*nextCmd)
|
||||||
|
{
|
||||||
|
if (!strncmp(cmd, *nextCmd+1, len))
|
||||||
|
{
|
||||||
|
if (matched)
|
||||||
|
{
|
||||||
|
// ambiguous command (command should match only once)
|
||||||
|
return CMD_INVALID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matched = true;
|
||||||
|
if ('+' == *nextCmd[0])
|
||||||
|
type = CMD_ARG;
|
||||||
|
else
|
||||||
|
type = CMD_NOARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nextCmd++;
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
} // end NorpApp::GetCmdType()
|
||||||
|
|
||||||
|
bool NorpApp::OnStartup(int argc, const char*const* argv)
|
||||||
|
{
|
||||||
|
if (!ProcessCommands(argc, argv))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnStartup() error: bad command line\n");
|
||||||
|
Usage();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// If a proxy address wasn't set, use "default" local address for host
|
||||||
|
if (!norp.GetProxyAddress().IsValid())
|
||||||
|
{
|
||||||
|
ProtoAddress theAddr;
|
||||||
|
if (theAddr.ResolveLocalAddress())
|
||||||
|
norp.SetProxyAddress(theAddr);
|
||||||
|
else
|
||||||
|
PLOG(PL_WARN, "NorpApp::OnStartup() warning: proxy address undetermined!\n");
|
||||||
|
}
|
||||||
|
PLOG(PL_INFO, "norp: starting proxy with address %s\n", norp.GetProxyAddress().GetHostString());
|
||||||
|
|
||||||
|
if (!norp.StartServer(norm_enable))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnStartup() error: norp server startup failure!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end NorpApp::OnStartup()
|
||||||
|
|
||||||
|
void NorpApp::OnShutdown()
|
||||||
|
{
|
||||||
|
norp.StopServer();
|
||||||
|
CloseDebugLog();
|
||||||
|
} // end Norp::OnShutdown()
|
||||||
|
|
||||||
|
bool NorpApp::ProcessCommands(int argc, const char*const* argv)
|
||||||
|
{
|
||||||
|
// Dispatch command-line commands to our OnCommand() method
|
||||||
|
int i = 1;
|
||||||
|
while ( i < argc)
|
||||||
|
{
|
||||||
|
// Is it a class NorpApp command?
|
||||||
|
switch (GetCmdType(argv[i]))
|
||||||
|
{
|
||||||
|
case CMD_INVALID:
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::ProcessCommands() Invalid command:%s\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case CMD_NOARG:
|
||||||
|
if (!OnCommand(argv[i], NULL))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::ProcessCommands() ProcessCommand(%s) error\n", argv[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
case CMD_ARG:
|
||||||
|
if (!OnCommand(argv[i], argv[i+1]))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::ProcessCommands() ProcessCommand(%s, %s) error\n", argv[i], argv[i+1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end NorpApp::ProcessCommands()
|
||||||
|
|
||||||
|
bool NorpApp::OnCommand(const char* cmd, const char* val)
|
||||||
|
{
|
||||||
|
// (TBD) move command processing into Mgen class ???
|
||||||
|
CmdType type = GetCmdType(cmd);
|
||||||
|
ASSERT(CMD_INVALID != type);
|
||||||
|
unsigned int len = strlen(cmd);
|
||||||
|
if ((CMD_ARG == type) && !val)
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::ProcessCommand(%s) missing argument\n", cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!strncmp("version", cmd, len))
|
||||||
|
{
|
||||||
|
fprintf(stdout, "norp version %s\n", NORP_VERSION);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
else if (!strncmp("debug", cmd, len))
|
||||||
|
{
|
||||||
|
SetDebugLevel(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("trace", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetNormTrace(true);
|
||||||
|
}
|
||||||
|
else if (!strncmp("dlog", cmd, len))
|
||||||
|
{
|
||||||
|
OpenDebugLog(val);
|
||||||
|
}
|
||||||
|
else if (!strncmp("interface", cmd, len))
|
||||||
|
{
|
||||||
|
ProtoAddress ifaceAddr;
|
||||||
|
if (!ProtoNet::GetInterfaceAddress(val, ProtoAddress::IPv4, ifaceAddr))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(interface) error: unable to get address for interface \"%s\"\n", val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
norp.SetProxyAddress(ifaceAddr);
|
||||||
|
}
|
||||||
|
else if (!strncmp("address", cmd, len))
|
||||||
|
{
|
||||||
|
ProtoAddress theAddr;
|
||||||
|
if (!theAddr.ResolveFromString(val))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(interface) error: invalid address \"%s\"\n", val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
norp.SetProxyAddress(theAddr);
|
||||||
|
}
|
||||||
|
else if (!strncmp("sport", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetSocksPort(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("port", cmd, len))
|
||||||
|
{
|
||||||
|
UINT16 norpPort = atoi(val);
|
||||||
|
norp.SetLocalNorpPort(norpPort);
|
||||||
|
norp.SetRemoteNorpPort(norpPort);
|
||||||
|
}
|
||||||
|
else if (!strncmp("norm", cmd, len))
|
||||||
|
{
|
||||||
|
if (0 == strcmp("on", val))
|
||||||
|
norm_enable = true;
|
||||||
|
else
|
||||||
|
norm_enable = false;
|
||||||
|
}
|
||||||
|
else if (!strncmp("id", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetNormNodeId(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("nport", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetNormPort(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("cce", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetNormCC(Norp::NORM_CCE);
|
||||||
|
}
|
||||||
|
else if (!strncmp("ccl", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetNormCC(Norp::NORM_CCL);
|
||||||
|
}
|
||||||
|
else if (!strncmp("rate", cmd, len))
|
||||||
|
{
|
||||||
|
double txRate;
|
||||||
|
if (1 != sscanf(val, "%lf", &txRate))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(rate) error: invalid rate \"%s\" bps\n", val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
norp.SetNormCC(Norp::NORM_FIXED);
|
||||||
|
norp.SetNormTxRate(txRate);
|
||||||
|
}
|
||||||
|
else if (!strncmp("limit", cmd, len))
|
||||||
|
{
|
||||||
|
double txLimit;
|
||||||
|
if (1 != sscanf(val, "%lf", &txLimit))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(limit) error: invalid limit rate \"%s\" bps\n", val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
norp.SetNormTxLimit(txLimit);
|
||||||
|
}
|
||||||
|
else if (!strncmp("lport", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetLocalNorpPort(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("rport", cmd, len))
|
||||||
|
{
|
||||||
|
norp.SetRemoteNorpPort(atoi(val));
|
||||||
|
}
|
||||||
|
else if (!strncmp("forward", cmd, len))
|
||||||
|
{
|
||||||
|
// <port>,<dstAddr>/<dstPort>[,<remoteNorpAddr>]
|
||||||
|
char* text = new char[strlen(val) + 1]; // copy so we can slice and dice
|
||||||
|
if (NULL == text)
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s) new char[] error: %s\n", cmd, GetErrorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
strcpy(text, val);
|
||||||
|
char* dstAddrPtr = strchr(text, ',');
|
||||||
|
if (NULL == dstAddrPtr)
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: missing <dstAddr>!\n", cmd, val);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*dstAddrPtr++ = '\0';
|
||||||
|
char* dstPortPtr = strchr(dstAddrPtr, '/');
|
||||||
|
if (NULL == dstPortPtr)
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: missing <dstPort>!\n", cmd, val);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UINT16 tcpPort;
|
||||||
|
int result = sscanf(text, "%hu", &tcpPort);
|
||||||
|
if ((1 != result) || (0 == tcpPort))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: invalid <port> \"%s\"!\n", cmd, val, text);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*dstPortPtr++ = '\0';
|
||||||
|
char* norpAddrPtr = strchr(dstPortPtr, ',');
|
||||||
|
if (NULL != norpAddrPtr) *norpAddrPtr++ = '\0';
|
||||||
|
ProtoAddress dstAddr;
|
||||||
|
if (!dstAddr.ResolveFromString(dstAddrPtr))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: invalid <dstAddr> \"%s\"!\n", cmd, val, dstAddrPtr);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UINT16 dstPort;
|
||||||
|
result = sscanf(dstPortPtr, "%hu", &dstPort);
|
||||||
|
if ((1 != result) || (0 == dstPort))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: invalid <dstPort> \"%s\"!\n", cmd, val, text);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dstAddr.SetPort(dstPort);
|
||||||
|
ProtoAddress norpAddr;
|
||||||
|
if (NULL != norpAddrPtr)
|
||||||
|
{
|
||||||
|
if (!norpAddr.ResolveFromString(norpAddrPtr))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: invalid <norpAddr> \"%s\"!\n", cmd, val, norpAddrPtr);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!norp.AddPreset(tcpPort, dstAddr, norpAddr))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: unable to add preset!\n", cmd, val);
|
||||||
|
delete[] text;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
delete[] text;
|
||||||
|
}
|
||||||
|
else if (!strncmp("correspondent", cmd, len))
|
||||||
|
{
|
||||||
|
// <remoteNorpAddr>
|
||||||
|
ProtoAddress norpAddr;
|
||||||
|
if (!norpAddr.ResolveFromString(val))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s, %s) error: invalid <remoteNorpAddr>!\n", cmd, val);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
norp.SetRemoteNorpAddress(norpAddr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "NorpApp::OnCommand(%s) error: unimplemented command!\n", cmd);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // end NorpApp::OnCommand()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,388 @@
|
||||||
|
#include "protoPktSOCKS.h"
|
||||||
|
#include "protoDebug.h"
|
||||||
|
|
||||||
|
ProtoPktSOCKS::AuthRequest::AuthRequest(UINT32* bufferPtr, unsigned int numBytes, bool initFromBuffer, bool freeOnDestruct)
|
||||||
|
: ProtoPkt(bufferPtr, numBytes, freeOnDestruct)
|
||||||
|
{
|
||||||
|
if (initFromBuffer) InitFromBuffer(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::AuthRequest::~AuthRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::AuthReply::AuthReply(UINT32* bufferPtr, unsigned int numBytes, bool initFromBuffer, bool freeOnDestruct)
|
||||||
|
: ProtoPkt(bufferPtr, numBytes, freeOnDestruct)
|
||||||
|
{
|
||||||
|
if (initFromBuffer) InitFromBuffer(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::AuthReply::~AuthReply()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::Request::Request(UINT32* bufferPtr, unsigned int numBytes, bool initFromBuffer, bool freeOnDestruct)
|
||||||
|
: ProtoPkt(bufferPtr, numBytes, freeOnDestruct)
|
||||||
|
{
|
||||||
|
if (initFromBuffer) InitFromBuffer(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::Request::~Request()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 ProtoPktSOCKS::Request::GetAddressLength() const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
return 4;
|
||||||
|
case NAME:
|
||||||
|
// First byte of "name" is length value
|
||||||
|
return ((UINT8*)buffer_ptr)[OFFSET_ADDR];
|
||||||
|
case IPv6:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::Request::GetAddressLength()
|
||||||
|
|
||||||
|
UINT16 ProtoPktSOCKS::Request::GetPort() const
|
||||||
|
{
|
||||||
|
const char* portPtr = GetAddressPtr() + GetAddressLength();
|
||||||
|
UINT16 temp16;
|
||||||
|
memcpy(&temp16, portPtr, 2);
|
||||||
|
return ntohs(temp16);
|
||||||
|
} // end ProtoPktSOCKS::Request::GetPort()
|
||||||
|
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::Request::GetAddress(ProtoAddress& theAddr) const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv4, GetAddressPtr(), 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NAME:
|
||||||
|
{
|
||||||
|
char name[256];
|
||||||
|
UINT8 addrLen = GetAddressLength();
|
||||||
|
strncpy(name, GetAddressPtr(), addrLen);
|
||||||
|
name[addrLen] = '\0';
|
||||||
|
if (!theAddr.ResolveFromString(name))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Request::GetAddress() error: unable to resolve name \"%s\" to addr!\n", name);
|
||||||
|
return false;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
case IPv6:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv6, GetAddressPtr(), 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Request::GetAddress() error: invalid address type!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
theAddr.SetPort(GetPort());
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::Request::GetAddress()
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::Request::SetAddress(const ProtoAddress& theAddr)
|
||||||
|
{
|
||||||
|
AddrType addrType;
|
||||||
|
UINT8 addrLength;
|
||||||
|
switch (theAddr.GetType())
|
||||||
|
{
|
||||||
|
case ProtoAddress::IPv4:
|
||||||
|
addrType = IPv4;
|
||||||
|
addrLength = 4;
|
||||||
|
break;
|
||||||
|
case ProtoAddress::IPv6:
|
||||||
|
addrType = IPv6;
|
||||||
|
addrLength = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Request::SetAddress() error: invalid address type!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SetAddressType(addrType);
|
||||||
|
memcpy(AccessAddressPtr(), theAddr.GetRawHostAddress(), addrLength);
|
||||||
|
pkt_length = OFFSET_ADDR + addrLength;
|
||||||
|
|
||||||
|
SetPort(theAddr.GetPort());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::Request::SetAddress()
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::Request::SetPort(UINT16 thePort)
|
||||||
|
{
|
||||||
|
char* portPtr = AccessAddressPtr() + GetAddressLength();
|
||||||
|
UINT16 temp16 = htons(thePort);
|
||||||
|
memcpy(portPtr, (char*)&temp16, 2);
|
||||||
|
pkt_length = OFFSET_ADDR + GetAddressLength() + 2;
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::Request::SetPort()
|
||||||
|
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::Request::SetName(const char* theName)
|
||||||
|
{
|
||||||
|
SetAddressType(NAME);
|
||||||
|
unsigned int nameLength = strlen(theName);
|
||||||
|
// TBD - validate there is sufficient buffer space
|
||||||
|
memcpy(AccessAddressPtr(), theName, nameLength);
|
||||||
|
pkt_length += nameLength;
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::Request::SetAddress()
|
||||||
|
|
||||||
|
ProtoPktSOCKS::Reply::Reply(UINT32* bufferPtr, unsigned int numBytes, bool initFromBuffer, bool freeOnDestruct)
|
||||||
|
: ProtoPkt(bufferPtr, numBytes, freeOnDestruct)
|
||||||
|
{
|
||||||
|
if (initFromBuffer) InitFromBuffer(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::Reply::~Reply()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 ProtoPktSOCKS::Reply::GetAddressLength() const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
return 4;
|
||||||
|
case NAME:
|
||||||
|
// First byte of "name" is length value
|
||||||
|
return ((UINT8*)buffer_ptr)[OFFSET_ADDR];
|
||||||
|
case IPv6:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::Reply::GetAddressLength()
|
||||||
|
|
||||||
|
UINT16 ProtoPktSOCKS::Reply::GetPort() const
|
||||||
|
{
|
||||||
|
const char* portPtr = GetAddressPtr() + GetAddressLength();
|
||||||
|
UINT16 temp16;
|
||||||
|
memcpy(&temp16, portPtr, 2);
|
||||||
|
return ntohs(temp16);
|
||||||
|
} // end ProtoPktSOCKS::Reply::GetPort()
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::Reply::GetAddress(ProtoAddress& theAddr) const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv4, GetAddressPtr(), 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NAME:
|
||||||
|
{
|
||||||
|
char name[256];
|
||||||
|
UINT8 addrLen = GetAddressLength();
|
||||||
|
strncpy(name, GetAddressPtr(), addrLen);
|
||||||
|
name[addrLen] = '\0';
|
||||||
|
if (!theAddr.ResolveFromString(name))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Reply::GetAddress() error: unable to resolve name \"%s\" to addr!\n", name);
|
||||||
|
return false;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
case IPv6:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv6, GetAddressPtr(), 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Reply::GetAddress() error: invalid address type!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
theAddr.SetPort(GetPort());
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::Reply::GetAddress()
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::Reply::SetAddress(AddrType addrType, const char* addrPtr, UINT8 addrLen)
|
||||||
|
{
|
||||||
|
switch (addrType)
|
||||||
|
{
|
||||||
|
case ProtoPktSOCKS::IPv4:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::IPv4;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR, addrPtr, 4);
|
||||||
|
pkt_length = OFFSET_ADDR + 4;
|
||||||
|
break;
|
||||||
|
case ProtoPktSOCKS::NAME:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::NAME;
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ADDR] = (UINT8)addrLen;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR + 1, addrPtr, addrLen);
|
||||||
|
pkt_length = OFFSET_ADDR + 1 + addrLen;
|
||||||
|
break;
|
||||||
|
case ProtoPktSOCKS::IPv6:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::IPv6;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR, addrPtr, 16);
|
||||||
|
pkt_length = OFFSET_ADDR + 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Reply::SetAddress() invalid SOCKS address type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::Reply::SetAddress()
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::Reply::SetPort(UINT16 thePort)
|
||||||
|
{
|
||||||
|
UINT16 temp16 = htons(thePort);
|
||||||
|
char* portPtr = AccessAddressPtr() + GetAddressLength();
|
||||||
|
memcpy(portPtr, &temp16, 2);
|
||||||
|
pkt_length = (GetAddressPtr() + GetAddressLength() + 2 - (char*)buffer_ptr);
|
||||||
|
} // end ProtoPktSOCKS::Reply::SetPort()
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::Reply::SetAddress(const ProtoAddress& theAddr)
|
||||||
|
{
|
||||||
|
switch (theAddr.GetType())
|
||||||
|
{
|
||||||
|
case ProtoAddress::IPv4:
|
||||||
|
SetAddress(ProtoPktSOCKS::IPv4, theAddr.GetRawHostAddress(), 4);
|
||||||
|
SetPort(theAddr.GetPort());
|
||||||
|
break;
|
||||||
|
case ProtoAddress::IPv6:
|
||||||
|
SetAddress(ProtoPktSOCKS::IPv6, theAddr.GetRawHostAddress(), 16);
|
||||||
|
SetPort(theAddr.GetPort());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::Reply::SetAddress() invalid ProtoAddress type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::Reply::SetAddress()
|
||||||
|
|
||||||
|
ProtoPktSOCKS::UdpRequest::UdpRequest(UINT32* bufferPtr, unsigned int numBytes, bool initFromBuffer, bool freeOnDestruct)
|
||||||
|
: ProtoPkt(bufferPtr, numBytes, freeOnDestruct)
|
||||||
|
{
|
||||||
|
if (initFromBuffer) InitFromBuffer(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoPktSOCKS::UdpRequest::~UdpRequest()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 ProtoPktSOCKS::UdpRequest::GetAddressLength() const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
return 4;
|
||||||
|
case NAME:
|
||||||
|
// First byte of "name" is length value
|
||||||
|
return ((UINT8*)buffer_ptr)[OFFSET_ADDR];
|
||||||
|
case IPv6:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::GetAddressLength()
|
||||||
|
|
||||||
|
UINT16 ProtoPktSOCKS::UdpRequest::GetPort() const
|
||||||
|
{
|
||||||
|
const char* portPtr = GetAddressPtr() + GetAddressLength();
|
||||||
|
UINT16 temp16;
|
||||||
|
memcpy(&temp16, portPtr, 2);
|
||||||
|
return ntohs(temp16);
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::GetPort()
|
||||||
|
|
||||||
|
|
||||||
|
bool ProtoPktSOCKS::UdpRequest::GetAddress(ProtoAddress& theAddr) const
|
||||||
|
{
|
||||||
|
switch (GetAddressType())
|
||||||
|
{
|
||||||
|
case IPv4:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv4, GetAddressPtr(), 4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NAME:
|
||||||
|
{
|
||||||
|
char name[256];
|
||||||
|
UINT8 addrLen = GetAddressLength();
|
||||||
|
strncpy(name, GetAddressPtr(), addrLen);
|
||||||
|
name[addrLen] = '\0';
|
||||||
|
if (!theAddr.ResolveFromString(name))
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::UdpRequest::GetAddress() error: unable to resolve name \"%s\" to addr!\n", name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IPv6:
|
||||||
|
{
|
||||||
|
theAddr.SetRawHostAddress(ProtoAddress::IPv6, GetAddressPtr(), 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::UdpRequest::GetAddress() error: invalid address type!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
theAddr.SetPort(GetPort());
|
||||||
|
return true;
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::GetAddress()
|
||||||
|
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::UdpRequest::SetAddress(AddrType addrType, const char* addrPtr, UINT8 addrLen)
|
||||||
|
{
|
||||||
|
switch (addrType)
|
||||||
|
{
|
||||||
|
case ProtoPktSOCKS::IPv4:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::IPv4;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR, addrPtr, 4);
|
||||||
|
pkt_length = OFFSET_ADDR + 4;
|
||||||
|
break;
|
||||||
|
case ProtoPktSOCKS::NAME:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::NAME;
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ADDR] = (UINT8)addrLen;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR + 1, addrPtr, addrLen);
|
||||||
|
pkt_length = OFFSET_ADDR + 1 + addrLen;
|
||||||
|
break;
|
||||||
|
case ProtoPktSOCKS::IPv6:
|
||||||
|
((UINT8*)buffer_ptr)[OFFSET_ATYPE] = (UINT8)ProtoPktSOCKS::IPv6;
|
||||||
|
memcpy(((char*)buffer_ptr) + OFFSET_ADDR, addrPtr, 16);
|
||||||
|
pkt_length = OFFSET_ADDR + 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::UdpRequest::SetAddress() invalid SOCKS address type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::SetAddress()
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::UdpRequest::SetPort(UINT16 thePort)
|
||||||
|
{
|
||||||
|
UINT16 temp16 = htons(thePort);
|
||||||
|
char* portPtr = AccessAddressPtr() + GetAddressLength();
|
||||||
|
memcpy(portPtr, &temp16, 2);
|
||||||
|
pkt_length = (GetAddressPtr() + GetAddressLength() + 2 - (char*)buffer_ptr);
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::SetPort()
|
||||||
|
|
||||||
|
void ProtoPktSOCKS::UdpRequest::SetAddress(const ProtoAddress& theAddr)
|
||||||
|
{
|
||||||
|
switch (theAddr.GetType())
|
||||||
|
{
|
||||||
|
case ProtoAddress::IPv4:
|
||||||
|
SetAddress(ProtoPktSOCKS::IPv4, theAddr.GetRawHostAddress(), 4);
|
||||||
|
SetPort(theAddr.GetPort());
|
||||||
|
break;
|
||||||
|
case ProtoAddress::IPv6:
|
||||||
|
SetAddress(ProtoPktSOCKS::IPv6, theAddr.GetRawHostAddress(), 16);
|
||||||
|
SetPort(theAddr.GetPort());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
PLOG(PL_ERROR, "ProtoPktSOCKS::UdpRequest::SetAddress() invalid ProtoAddress type\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end ProtoPktSOCKS::UdpRequest::SetAddress()
|
||||||
|
|
||||||
Loading…
Reference in New Issue