1 /*
2     Mosh: the mobile shell
3     Copyright 2012 Keith Winstein
4 
5     This program is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18     In addition, as a special exception, the copyright holders give
19     permission to link the code of portions of this program with the
20     OpenSSL library under certain conditions as described in each
21     individual source file, and distribute linked combinations including
22     the two.
23 
24     You must obey the GNU General Public License in all respects for all
25     of the code used other than OpenSSL. If you modify file(s) with this
26     exception, you may extend this exception to your version of the
27     file(s), but you are not obligated to do so. If you do not wish to do
28     so, delete this exception statement from your version. If you delete
29     this exception statement from all source files in the program, then
30     also delete it here.
31 */
32 
33 #ifndef NETWORK_HPP
34 #define NETWORK_HPP
35 
36 #include <stdint.h>
37 #include <deque>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <string>
41 #include <math.h>
42 #include <vector>
43 #include <assert.h>
44 #include <exception>
45 #include <string.h>
46 
47 #include "crypto.h"
48 
49 using namespace Crypto;
50 
51 namespace Network {
52   static const unsigned int MOSH_PROTOCOL_VERSION = 2; /* bumped for echo-ack */
53 
54   uint64_t timestamp( void );
55   uint16_t timestamp16( void );
56   uint16_t timestamp_diff( uint16_t tsnew, uint16_t tsold );
57 
58   class NetworkException : public std::exception {
59   public:
60     string function;
61     int the_errno;
62   private:
63     string my_what;
64   public:
65     NetworkException( string s_function="<none>", int s_errno=0)
function(s_function)66       : function( s_function ), the_errno( s_errno ),
67         my_what(function + ": " + strerror(the_errno)) {}
what()68     const char *what() const throw () { return my_what.c_str(); }
throw()69     ~NetworkException() throw () {}
70   };
71 
72   enum Direction {
73     TO_SERVER = 0,
74     TO_CLIENT = 1
75   };
76 
77   class Packet {
78   public:
79     const uint64_t seq;
80     Direction direction;
81     uint16_t timestamp, timestamp_reply;
82     string payload;
83 
Packet(Direction s_direction,uint16_t s_timestamp,uint16_t s_timestamp_reply,const string & s_payload)84     Packet( Direction s_direction,
85 	    uint16_t s_timestamp, uint16_t s_timestamp_reply, const string & s_payload )
86       : seq( Crypto::unique() ), direction( s_direction ),
87 	timestamp( s_timestamp ), timestamp_reply( s_timestamp_reply ), payload( s_payload )
88     {}
89 
90     Packet( const Message & message );
91 
92     Message toMessage( void );
93   };
94 
95   union Addr {
96     struct sockaddr sa;
97     struct sockaddr_in sin;
98     struct sockaddr_in6 sin6;
99     struct sockaddr_storage ss;
100   };
101 
102   class Connection {
103   private:
104     /*
105      * For IPv4, guess the typical (minimum) header length;
106      * fragmentation is not dangerous, just inefficient.
107      */
108     static const int IPV4_HEADER_LEN = 20 /* base IP header */
109       + 8 /* UDP */;
110     /*
111      * For IPv6, we don't want to ever have MTU issues, so make a
112      * conservative guess about header size.
113      */
114     static const int IPV6_HEADER_LEN = 40 /* base IPv6 header */
115       + 16 /* 2 minimum-sized extension headers */
116       + 8 /* UDP */;
117     /* Application datagram MTU. For constructors and fallback. */
118     static const int DEFAULT_SEND_MTU = 500;
119     /*
120      * IPv4 MTU. Don't use full Ethernet-derived MTU,
121      * mobile networks have high tunneling overhead.
122      *
123      * As of July 2016, VPN traffic over Amtrak Acela wifi seems to be
124      * dropped if tunnelled packets are 1320 bytes or larger.  Use a
125      * 1280-byte IPv4 MTU for now.
126      *
127      * We may have to implement ICMP-less PMTUD (RFC 4821) eventually.
128      */
129     static const int DEFAULT_IPV4_MTU = 1280;
130     /* IPv6 MTU. Use the guaranteed minimum to avoid fragmentation. */
131     static const int DEFAULT_IPV6_MTU = 1280;
132 
133     static const uint64_t MIN_RTO = 50; /* ms */
134     static const uint64_t MAX_RTO = 1000; /* ms */
135 
136     static const int PORT_RANGE_LOW  = 60001;
137     static const int PORT_RANGE_HIGH = 60999;
138 
139     static const unsigned int SERVER_ASSOCIATION_TIMEOUT = 40000;
140     static const unsigned int PORT_HOP_INTERVAL          = 10000;
141 
142     static const unsigned int MAX_PORTS_OPEN             = 10;
143     static const unsigned int MAX_OLD_SOCKET_AGE         = 60000;
144 
145     static const int CONGESTION_TIMESTAMP_PENALTY = 500; /* ms */
146 
147     bool try_bind( const char *addr, int port_low, int port_high );
148 
149     class Socket
150     {
151     private:
152       int _fd;
153 
154     public:
fd(void)155       int fd( void ) const { return _fd; }
156       Socket( int family );
157       ~Socket();
158 
159       Socket( const Socket & other );
160       Socket & operator=( const Socket & other );
161     };
162 
163     std::deque< Socket > socks;
164     bool has_remote_addr;
165     Addr remote_addr;
166     socklen_t remote_addr_len;
167 
168     bool server;
169 
170     int MTU; /* application datagram MTU */
171 
172     Base64Key key;
173     Session session;
174 
175     void setup( void );
176 
177     Direction direction;
178     uint16_t saved_timestamp;
179     uint64_t saved_timestamp_received_at;
180     uint64_t expected_receiver_seq;
181 
182     uint64_t last_heard;
183     uint64_t last_port_choice;
184     uint64_t last_roundtrip_success; /* transport layer needs to tell us this */
185 
186     bool RTT_hit;
187     double SRTT;
188     double RTTVAR;
189 
190     /* Error from send()/sendto(). */
191     string send_error;
192 
193     Packet new_packet( const string &s_payload );
194 
195     void hop_port( void );
196 
sock(void)197     int sock( void ) const { assert( !socks.empty() ); return socks.back().fd(); }
198 
199     void prune_sockets( void );
200 
201     string recv_one( int sock_to_recv, bool nonblocking );
202 
203     void set_MTU( int family );
204 
205   public:
206     /* Network transport overhead. */
207     static const int ADDED_BYTES = 8 /* seqno/nonce */ + 4 /* timestamps */;
208 
209     Connection( const char *desired_ip, const char *desired_port ); /* server */
210     Connection( const char *key_str, const char *ip, const char *port ); /* client */
211 
212     void send( const string & s );
213     string recv( void );
214     const std::vector< int > fds( void ) const;
get_MTU(void)215     int get_MTU( void ) const { return MTU; }
216 
217     std::string port( void ) const;
get_key(void)218     string get_key( void ) const { return key.printable_key(); }
get_has_remote_addr(void)219     bool get_has_remote_addr( void ) const { return has_remote_addr; }
220 
221     uint64_t timeout( void ) const;
get_SRTT(void)222     double get_SRTT( void ) const { return SRTT; }
223 
get_remote_addr(void)224     const Addr &get_remote_addr( void ) const { return remote_addr; }
get_remote_addr_len(void)225     socklen_t get_remote_addr_len( void ) const { return remote_addr_len; }
226 
get_send_error(void)227     string &get_send_error( void )
228     {
229       return send_error;
230     }
231 
set_last_roundtrip_success(uint64_t s_success)232     void set_last_roundtrip_success( uint64_t s_success ) { last_roundtrip_success = s_success; }
233 
234     static bool parse_portrange( const char * desired_port_range, int & desired_port_low, int & desired_port_high );
235   };
236 }
237 
238 #endif
239