Browse Source

more commenting and cleaning

Joseph Henry 10 years ago
parent
commit
bbdb8eb0de
4 changed files with 163 additions and 75 deletions
  1. 91 65
      netcon/NetconEthernetTap.cpp
  2. 17 10
      netcon/NetconService.hpp
  3. 28 0
      netcon/NetconUtilities.cpp
  4. 27 0
      netcon/NetconUtilities.hpp

+ 91 - 65
netcon/NetconEthernetTap.cpp

@@ -254,12 +254,10 @@ NetconConnection *NetconEthernetTap::getConnectionByPCB(struct tcp_pcb *pcb)
 
 
 NetconConnection *NetconEthernetTap::getConnectionByThisFD(int fd)
 NetconConnection *NetconEthernetTap::getConnectionByThisFD(int fd)
 {
 {
-	//fprintf(stderr, "  getConnectionByThisFD\n");
 	for(size_t i=0; i<clients.size(); i++) {
 	for(size_t i=0; i<clients.size(); i++) {
 		for(size_t j=0; j<clients[i]->connections.size(); j++) {
 		for(size_t j=0; j<clients[i]->connections.size(); j++) {
-			if(_phy.getDescriptor(clients[i]->connections[j]->sock) == fd) {
+			if(_phy.getDescriptor(clients[i]->connections[j]->sock) == fd)
 				return clients[i]->connections[j];
 				return clients[i]->connections[j];
-			}
 		}
 		}
 	}
 	}
 	return NULL;
 	return NULL;
@@ -268,9 +266,8 @@ NetconConnection *NetconEthernetTap::getConnectionByThisFD(int fd)
 NetconClient *NetconEthernetTap::getClientByPCB(struct tcp_pcb *pcb)
 NetconClient *NetconEthernetTap::getClientByPCB(struct tcp_pcb *pcb)
 {
 {
 	for(size_t i=0; i<clients.size(); i++) {
 	for(size_t i=0; i<clients.size(); i++) {
-		if(clients[i]->containsPCB(pcb)) {
+		if(clients[i]->containsPCB(pcb))
 			return clients[i];
 			return clients[i];
-		}
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
@@ -282,16 +279,30 @@ void NetconEthernetTap::closeAllClients()
 	}
 	}
 }
 }
 
 
+/*
+ * Closes a NetconConnection and associated LWIP PCB strcuture.
+ */
 void NetconEthernetTap::closeConnection(NetconConnection *conn)
 void NetconEthernetTap::closeConnection(NetconConnection *conn)
 {
 {
 	NetconClient *client = conn->owner;
 	NetconClient *client = conn->owner;
+  lwipstack->tcp_arg(conn->pcb, NULL);
+  lwipstack->tcp_sent(conn->pcb, NULL);
+  lwipstack->tcp_recv(conn->pcb, NULL);
+  lwipstack->tcp_err(conn->pcb, NULL);
+  lwipstack->tcp_poll(conn->pcb, NULL, 0);
+  lwipstack->tcp_close(conn->pcb);
 	_phy.close(conn->sock);
 	_phy.close(conn->sock);
 	lwipstack->tcp_close(conn->pcb);
 	lwipstack->tcp_close(conn->pcb);
 	client->removeConnection(conn->sock);
 	client->removeConnection(conn->sock);
 }
 }
 
 
+/*
+ * Closes a NetconClient and all associated NetconConnections (rpc, data, and unmapped)
+ */
 void NetconEthernetTap::closeClient(NetconClient *client)
 void NetconEthernetTap::closeClient(NetconClient *client)
 {
 {
+	closeConnection(client->rpc);
+	closeConnection(client->unmapped_conn);
 	for(size_t i=0; i<client->connections.size(); i++)
 	for(size_t i=0; i<client->connections.size(); i++)
 	{
 	{
 		close(_phy.getDescriptor(client->connections[i]->sock));
 		close(_phy.getDescriptor(client->connections[i]->sock));
@@ -301,10 +312,6 @@ void NetconEthernetTap::closeClient(NetconClient *client)
 	}
 	}
 }
 }
 
 
-/*------------------------------------------------------------------------------
------------------------- low-level Interface functions -------------------------
-------------------------------------------------------------------------------*/
-
 #define ZT_LWIP_TCP_TIMER_INTERVAL 10
 #define ZT_LWIP_TCP_TIMER_INTERVAL 10
 
 
 void NetconEthernetTap::threadMain()
 void NetconEthernetTap::threadMain()
@@ -425,7 +432,6 @@ void NetconEthernetTap::phyOnUnixClose(PhySocket *sock,void **uptr)
  */
  */
 void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
 void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,unsigned long len)
 {
 {
-	fprintf(stderr, "phyOnUnixData(): rpc = %d\n", _phy.getDescriptor(sock));
 	unsigned char *buf = (unsigned char*)data;
 	unsigned char *buf = (unsigned char*)data;
 	NetconClient *client = (NetconClient*)*uptr;
 	NetconClient *client = (NetconClient*)*uptr;
 
 
@@ -475,7 +481,9 @@ void NetconEthernetTap::phyOnUnixData(PhySocket *sock,void **uptr,void *data,uns
 void NetconEthernetTap::phyOnUnixWritable(PhySocket *sock,void **uptr)
 void NetconEthernetTap::phyOnUnixWritable(PhySocket *sock,void **uptr)
 {
 {
 }
 }
-
+/*
+ * Send a return value to the client for an RPC
+ */
 int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
 int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
 {
 {
   char retmsg[4];
   char retmsg[4];
@@ -483,7 +491,6 @@ int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
   retmsg[0]=RPC_RETVAL;
   retmsg[0]=RPC_RETVAL;
   memcpy(&retmsg[1], &retval, sizeof(retval));
   memcpy(&retmsg[1], &retval, sizeof(retval));
   int n = write(_phy.getDescriptor(client->rpc->sock), &retmsg, sizeof(retmsg));
   int n = write(_phy.getDescriptor(client->rpc->sock), &retmsg, sizeof(retmsg));
-
   if(n > 0) {
   if(n > 0) {
 		// signal that we've satisfied this requirement
 		// signal that we've satisfied this requirement
     client->waiting_for_retval = false;
     client->waiting_for_retval = false;
@@ -501,6 +508,11 @@ int NetconEthernetTap::send_return_value(NetconClient *client, int retval)
 
 
 /*
 /*
  * Callback from LWIP to do whatever work we might need to do.
  * Callback from LWIP to do whatever work we might need to do.
+ *
+ * @param associated service state object
+ * @param PCB we're polling on
+ * @return ERR_OK if everything is ok, -1 otherwise
+ *
  */
  */
 err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *tpcb)
 err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *tpcb)
 {
 {
@@ -523,6 +535,12 @@ err_t NetconEthernetTap::nc_poll(void* arg, struct tcp_pcb *tpcb)
  * is then required to tell the service what new file descriptor it has allocated
  * is then required to tell the service what new file descriptor it has allocated
  * for this connection. After the mapping is complete, the accepted socket can be
  * for this connection. After the mapping is complete, the accepted socket can be
  * used.
  * used.
+ *
+ * @param associated service state object
+ * @param newly allocated PCB
+ * @param error code
+ * @return ERR_OK if everything is ok, -1 otherwise
+ *
  */
  */
 err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
 err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
 {
 {
@@ -575,6 +593,13 @@ err_t NetconEthernetTap::nc_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
  *
  *
  * Data is in the form of a linked list of struct pbufs, it is then recombined and
  * Data is in the form of a linked list of struct pbufs, it is then recombined and
  * send to the client over the associated unix socket.
  * send to the client over the associated unix socket.
+ *
+ * @param associated service state object
+ * @param allocated PCB
+ * @param chain of pbufs
+ * @param error code
+ * @return ERR_OK if everything is ok, -1 otherwise
+ *
  */
  */
 err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
 err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
 {
 {
@@ -591,8 +616,8 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf
   }
   }
   if(p == NULL) {
   if(p == NULL) {
     if(c) {
     if(c) {
-			//fprintf(stderr, "nc_recved(): closing connection (p==NULL)\n");
-      nc_close(tpcb);
+			fprintf(stderr, "nc_recved(): closing connection\n");
+      //tap->_phy.lwipstack->tcp_close(tpcb);
 			tap->_phy.close(c->sock);
 			tap->_phy.close(c->sock);
 			tap->closeConnection(c);
 			tap->closeConnection(c);
     }
     }
@@ -627,6 +652,10 @@ err_t NetconEthernetTap::nc_recved(void *arg, struct tcp_pcb *tpcb, struct pbuf
  *
  *
  * Since the PCB related to this error might no longer exist, only its perviously
  * Since the PCB related to this error might no longer exist, only its perviously
  * associated (arg) is provided to us.
  * associated (arg) is provided to us.
+ *
+ * @param associated service state object
+ * @param error code
+ *
  */
  */
 void NetconEthernetTap::nc_err(void *arg, err_t err)
 void NetconEthernetTap::nc_err(void *arg, err_t err)
 {
 {
@@ -642,44 +671,32 @@ void NetconEthernetTap::nc_err(void *arg, err_t err)
   }
   }
 }
 }
 
 
-/*
- * Callback from LWIP when this PCB has been closed
- */
-void NetconEthernetTap::nc_close(struct tcp_pcb* tpcb)
-{
-	fprintf(stderr, "nc_close\n");
-	//closeConnection(getConnectionByPCB(tpcb));
-	/*
-  lwipstack->tcp_arg(tpcb, NULL);
-  lwipstack->tcp_sent(tpcb, NULL);
-  lwipstack->tcp_recv(tpcb, NULL);
-  lwipstack->tcp_err(tpcb, NULL);
-  lwipstack->tcp_poll(tpcb, NULL, 0);
-  lwipstack->tcp_close(tpcb);
-	*/
-}
-
-/*
- * Callback from LWIP
- */
-err_t NetconEthernetTap::nc_send(struct tcp_pcb *tpcb)
-{
-	fprintf(stderr, "nc_send\n");
-	return ERR_OK;
-}
-
 /*
 /*
  * Callback from LWIP
  * Callback from LWIP
+ *
+ * This could be used to track the amount of data sent by a connection.
+ *
+ * @param associated service state object
+ * @param relevant PCB
+ * @param length of data sent
+ * @return ERR_OK if everything is ok, -1 otherwise
+ *
  */
  */
 err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *tpcb, u16_t len)
 err_t NetconEthernetTap::nc_sent(void* arg, struct tcp_pcb *tpcb, u16_t len)
 {
 {
-	fprintf(stderr, "nc_sent\n");
+	//fprintf(stderr, "nc_sent\n");
 	return len;
 	return len;
 }
 }
 
 
 /*
 /*
  * Callback from LWIP which sends a return value to the client to signal that
  * Callback from LWIP which sends a return value to the client to signal that
  * a connection was established for this PCB
  * a connection was established for this PCB
+ *
+ * @param associated service state object
+ * @param relevant PCB
+ * @param error code
+ * @return ERR_OK if everything is ok, -1 otherwise
+ *
  */
  */
 err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
 err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
 {
 {
@@ -702,49 +719,44 @@ err_t NetconEthernetTap::nc_connected(void *arg, struct tcp_pcb *tpcb, err_t err
 
 
 /*
 /*
  * Handles an RPC to bind an LWIP PCB to a given address and port
  * Handles an RPC to bind an LWIP PCB to a given address and port
+ *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
+ *
  */
  */
 void NetconEthernetTap::handle_bind(NetconClient *client, struct bind_st *bind_rpc)
 void NetconEthernetTap::handle_bind(NetconClient *client, struct bind_st *bind_rpc)
 {
 {
-	// FIXME: Is this hack still needed?
   struct sockaddr_in *connaddr;
   struct sockaddr_in *connaddr;
   connaddr = (struct sockaddr_in *) &bind_rpc->addr;
   connaddr = (struct sockaddr_in *) &bind_rpc->addr;
   int conn_port = lwipstack->ntohs(connaddr->sin_port);
   int conn_port = lwipstack->ntohs(connaddr->sin_port);
   ip_addr_t conn_addr;
   ip_addr_t conn_addr;
 	conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
 	conn_addr.addr = *((u32_t *)_ips[0].rawIpData());
-
-  /*
-  int ip = connaddr->sin_addr.s_addr;
-  unsigned char bytes[4];
-  bytes[0] = ip & 0xFF;
-  bytes[1] = (ip >> 8) & 0xFF;
-  bytes[2] = (ip >> 16) & 0xFF;
-  bytes[3] = (ip >> 24) & 0xFF;
-  fprintf(stderr, "binding to: %d.%d.%d.%d\n", bytes[0], bytes[1], bytes[2], bytes[3]);
-	fprintf(stderr, "PORT = %d\n", conn_port);
-  */
-
 	NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd);
 	NetconConnection *c = client->getConnectionByTheirFD(bind_rpc->sockfd);
   if(c) {
   if(c) {
     if(c->pcb->state == CLOSED){
     if(c->pcb->state == CLOSED){
       int err = lwipstack->tcp_bind(c->pcb, &conn_addr, conn_port);
       int err = lwipstack->tcp_bind(c->pcb, &conn_addr, conn_port);
       if(err != ERR_OK) {
       if(err != ERR_OK) {
-        fprintf(stderr, "error while binding to addr/port\n");
+				int ip = connaddr->sin_addr.s_addr;
+				unsigned char d[4];
+				d[0] = ip & 0xFF;
+				d[1] = (ip >> 8) & 0xFF;
+				d[2] = (ip >> 16) & 0xFF;
+				d[3] = (ip >> 24) & 0xFF;
+				fprintf(stderr, "handle_bind(): error binding to %d.%d.%d.%d : %d\n", d[0],d[1],d[2],d[3], conn_port);
       }
       }
-      else {
-        fprintf(stderr, "bind successful\n");
-      }
-    }
-    else {
-      fprintf(stderr, "PCB not in CLOSED state. Ignoring BIND request.\n");
+      //else fprintf(stderr, "bind successful\n");
     }
     }
+    else fprintf(stderr, "handle_bind(): PCB not in CLOSED state. Ignoring BIND request.\n");
   }
   }
-  else {
-    fprintf(stderr, "can't locate connection for PCB\n");
-  }
+  else fprintf(stderr, "handle_bind(): can't locate connection for PCB\n");
 }
 }
 
 
 /*
 /*
  * Handles an RPC to put an LWIP PCB into LISTEN mode
  * Handles an RPC to put an LWIP PCB into LISTEN mode
+ *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
+ *
  */
  */
 void NetconEthernetTap::handle_listen(NetconClient *client, struct listen_st *listen_rpc)
 void NetconEthernetTap::handle_listen(NetconClient *client, struct listen_st *listen_rpc)
 {
 {
@@ -775,6 +787,10 @@ void NetconEthernetTap::handle_listen(NetconClient *client, struct listen_st *li
 /**
 /**
  * Handles a return value (client's perceived fd) and completes a mapping
  * Handles a return value (client's perceived fd) and completes a mapping
  * so that we know what connection an RPC call should be associated with.
  * so that we know what connection an RPC call should be associated with.
+ *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
+ *
  */
  */
 void NetconEthernetTap::handle_retval(NetconClient *client, unsigned char* buf)
 void NetconEthernetTap::handle_retval(NetconClient *client, unsigned char* buf)
 {
 {
@@ -792,6 +808,10 @@ void NetconEthernetTap::handle_retval(NetconClient *client, unsigned char* buf)
  * for use in the main ZT I/O loop, and one end is sent to the client. The client
  * for use in the main ZT I/O loop, and one end is sent to the client. The client
  * is then required to tell the service what new file descriptor it has allocated
  * is then required to tell the service what new file descriptor it has allocated
  * for this connection. After the mapping is complete, the socket can be used.
  * for this connection. After the mapping is complete, the socket can be used.
+ *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
+ *
  */
  */
 void NetconEthernetTap::handle_socket(NetconClient *client, struct socket_st* socket_rpc)
 void NetconEthernetTap::handle_socket(NetconClient *client, struct socket_st* socket_rpc)
 {
 {
@@ -815,6 +835,10 @@ void NetconEthernetTap::handle_socket(NetconClient *client, struct socket_st* so
 
 
 /*
 /*
  * Handles an RPC to connect to a given address and port
  * Handles an RPC to connect to a given address and port
+ *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
+ *
  */
  */
 void NetconEthernetTap::handle_connect(NetconClient *client, struct connect_st* connect_rpc)
 void NetconEthernetTap::handle_connect(NetconClient *client, struct connect_st* connect_rpc)
 {
 {
@@ -855,9 +879,11 @@ void NetconEthernetTap::handle_connect(NetconClient *client, struct connect_st*
 /*
 /*
  * Writes data pulled from the client's socket buffer to LWIP. This merely sends the
  * Writes data pulled from the client's socket buffer to LWIP. This merely sends the
  * data to LWIP to be enqueued and eventually sent to the network.
  * data to LWIP to be enqueued and eventually sent to the network.
+ * *
+ * @param Client that is making the RPC
+ * @param structure containing the data and parameters for this client's RPC
  *
  *
  * TODO: Optimize write logic (should we stop using poll?)
  * TODO: Optimize write logic (should we stop using poll?)
- *
  */
  */
 void NetconEthernetTap::handle_write(NetconConnection *c)
 void NetconEthernetTap::handle_write(NetconConnection *c)
 {
 {

+ 17 - 10
netcon/NetconService.hpp

@@ -41,9 +41,13 @@ using namespace std;
 
 
 namespace ZeroTier {
 namespace ZeroTier {
 
 
+  enum NetconConnectionType { RPC, BUFFER };
+
   class NetconEthernetTap;
   class NetconEthernetTap;
 
 
-  // Helper class for passing reference to Phy to LWIP callbacks
+  /*
+   * A helper class for passing a reference to _phy to LWIP callbacks as a "state"
+   */
   class Larg
   class Larg
   {
   {
   public:
   public:
@@ -52,13 +56,13 @@ namespace ZeroTier {
     Larg(NetconEthernetTap *_tap, PhySocket *_sock) : tap(_tap), sock(_sock) {}
     Larg(NetconEthernetTap *_tap, PhySocket *_sock) : tap(_tap), sock(_sock) {}
   };
   };
 
 
-  enum NetconConnectionType { RPC, BUFFER };
-
   // prototypes
   // prototypes
   class NetconClient;
   class NetconClient;
   class NetconConnection;
   class NetconConnection;
 
 
-  //
+  /*
+   * A data connection, any number of these may be associated with a NetconClient
+   */
   class NetconConnection
   class NetconConnection
   {
   {
   public:
   public:
@@ -73,7 +77,9 @@ namespace ZeroTier {
     NetconConnection(NetconConnectionType type, PhySocket *sock) : type(type), sock(sock) {}
     NetconConnection(NetconConnectionType type, PhySocket *sock) : type(type), sock(sock) {}
   };
   };
 
 
-  //
+  /*
+   * A "harnessed" client with associated rpc and data connections.
+   */
   class NetconClient
   class NetconClient
   {
   {
   public:
   public:
@@ -98,7 +104,7 @@ namespace ZeroTier {
         return rpc;
         return rpc;
       }
       }
       for(size_t i=0; i<connections.size(); i++) {
       for(size_t i=0; i<connections.size(); i++) {
-        if(sock == connections[i]->sock) { return connections[i];}
+        if(sock == connections[i]->sock)  return connections[i];
       }
       }
       return NULL;
       return NULL;
     }
     }
@@ -107,7 +113,7 @@ namespace ZeroTier {
     NetconConnection *getConnectionByTheirFD(int fd)
     NetconConnection *getConnectionByTheirFD(int fd)
     {
     {
       for(size_t i=0; i<connections.size(); i++) {
       for(size_t i=0; i<connections.size(); i++) {
-        if(connections[i]->their_fd == fd) { return connections[i]; }
+        if(connections[i]->their_fd == fd) return connections[i];
       }
       }
       return NULL;
       return NULL;
     }
     }
@@ -116,7 +122,7 @@ namespace ZeroTier {
     NetconConnection *getConnectionByPCB(struct tcp_pcb *pcb)
     NetconConnection *getConnectionByPCB(struct tcp_pcb *pcb)
     {
     {
       for(size_t i=0; i<connections.size(); i++) {
       for(size_t i=0; i<connections.size(); i++) {
-        if(connections[i]->pcb == pcb) { return connections[i]; }
+        if(connections[i]->pcb == pcb) return connections[i];
       }
       }
       return NULL;
       return NULL;
     }
     }
@@ -124,7 +130,7 @@ namespace ZeroTier {
     NetconConnection *containsPCB(struct tcp_pcb *pcb)
     NetconConnection *containsPCB(struct tcp_pcb *pcb)
     {
     {
       for(size_t i=0; i<connections.size(); i++) {
       for(size_t i=0; i<connections.size(); i++) {
-        if(connections[i]->pcb == pcb) { return connections[i]; }
+        if(connections[i]->pcb == pcb) return connections[i];
       }
       }
       return NULL;
       return NULL;
     }
     }
@@ -132,7 +138,8 @@ namespace ZeroTier {
     void removeConnection(PhySocket *sock)
     void removeConnection(PhySocket *sock)
     {
     {
       for(size_t i=0; i<connections.size(); i++) {
       for(size_t i=0; i<connections.size(); i++) {
-        if(connections[i]->sock == sock) { connections.erase(connections.begin() + i); }
+        if(connections[i]->sock == sock)
+          connections.erase(connections.begin() + i);
       }
       }
     }
     }
   };
   };

+ 28 - 0
netcon/NetconUtilities.cpp

@@ -1,4 +1,32 @@
 
 
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2015  ZeroTier, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
+
 #include <stdlib.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdio.h>

+ 27 - 0
netcon/NetconUtilities.hpp

@@ -1,4 +1,31 @@
 
 
+/*
+ * ZeroTier One - Network Virtualization Everywhere
+ * Copyright (C) 2011-2015  ZeroTier, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * --
+ *
+ * ZeroTier may be used and distributed under the terms of the GPLv3, which
+ * are available at: http://www.gnu.org/licenses/gpl-3.0.html
+ *
+ * If you would like to embed ZeroTier into a commercial application or
+ * redistribute it in a modified binary form, please contact ZeroTier Networks
+ * LLC. Start here: http://www.zerotier.com/
+ */
+
 #ifndef _NETCON_UTILITIES_H
 #ifndef _NETCON_UTILITIES_H
 #define _NETCON_UTILITIES_H
 #define _NETCON_UTILITIES_H