1 
2 /***************************************************************************
3  * EchoServer.cc --                                                        *
4  *                                                                         *
5  ***********************IMPORTANT NMAP LICENSE TERMS************************
6  *                                                                         *
7  * The Nmap Security Scanner is (C) 1996-2020 Insecure.Com LLC ("The Nmap  *
8  * Project"). Nmap is also a registered trademark of the Nmap Project.     *
9  *                                                                         *
10  * This program is distributed under the terms of the Nmap Public Source   *
11  * License (NPSL). The exact license text applying to a particular Nmap    *
12  * release or source code control revision is contained in the LICENSE     *
13  * file distributed with that version of Nmap or source code control       *
14  * revision. More Nmap copyright/legal information is available from       *
15  * https://nmap.org/book/man-legal.html, and further information on the    *
16  * NPSL license itself can be found at https://nmap.org/npsl. This header  *
17  * summarizes some key points from the Nmap license, but is no substitute  *
18  * for the actual license text.                                            *
19  *                                                                         *
20  * Nmap is generally free for end users to download and use themselves,    *
21  * including commercial use. It is available from https://nmap.org.        *
22  *                                                                         *
23  * The Nmap license generally prohibits companies from using and           *
24  * redistributing Nmap in commercial products, but we sell a special Nmap  *
25  * OEM Edition with a more permissive license and special features for     *
26  * this purpose. See https://nmap.org/oem                                  *
27  *                                                                         *
28  * If you have received a written Nmap license agreement or contract       *
29  * stating terms other than these (such as an Nmap OEM license), you may   *
30  * choose to use and redistribute Nmap under those terms instead.          *
31  *                                                                         *
32  * The official Nmap Windows builds include the Npcap software             *
33  * (https://npcap.org) for packet capture and transmission. It is under    *
34  * separate license terms which forbid redistribution without special      *
35  * permission. So the official Nmap Windows builds may not be              *
36  * redistributed without special permission (such as an Nmap OEM           *
37  * license).                                                               *
38  *                                                                         *
39  * Source is provided to this software because we believe users have a     *
40  * right to know exactly what a program is going to do before they run it. *
41  * This also allows you to audit the software for security holes.          *
42  *                                                                         *
43  * Source code also allows you to port Nmap to new platforms, fix bugs,    *
44  * and add new features.  You are highly encouraged to submit your         *
45  * changes as a Github PR or by email to the dev@nmap.org mailing list     *
46  * for possible incorporation into the main distribution. Unless you       *
47  * specify otherwise, it is understood that you are offering us very       *
48  * broad rights to use your submissions as described in the Nmap Public    *
49  * Source License Contributor Agreement. This is important because we      *
50  * fund the project by selling licenses with various terms, and also       *
51  * because the inability to relicense code has caused devastating          *
52  * problems for other Free Software projects (such as KDE and NASM).       *
53  *                                                                         *
54  * The free version of Nmap is distributed in the hope that it will be     *
55  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of  *
56  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Warranties,        *
57  * indemnification and commercial support are all available through the    *
58  * Npcap OEM program--see https://nmap.org/oem.                            *
59  *                                                                         *
60  ***************************************************************************/
61 
62 #include "nping.h"
63 #include "EchoServer.h"
64 #include "EchoHeader.h"
65 #include "NEPContext.h"
66 #include <vector>
67 #include "nsock.h"
68 #include "output.h"
69 #include "NpingOps.h"
70 #include "ProbeMode.h"
71 #include <signal.h>
72 
73 extern NpingOps o;
74 extern EchoServer es;
75 
EchoServer()76 EchoServer::EchoServer() {
77   this->reset();
78 } /* End of EchoServer constructor */
79 
80 
~EchoServer()81 EchoServer::~EchoServer() {
82 } /* End of EchoServer destructor */
83 
84 
85 /** Sets every attribute to its default value- */
reset()86 void EchoServer::reset() {
87   this->client_ctx.clear();
88   this->client_id_count=-1;
89 } /* End of reset() */
90 
91 
92 /** Adds a new client context object to the server context list */
addClientContext(NEPContext ctx)93 int EchoServer::addClientContext(NEPContext ctx){
94   nping_print(DBG_4, "%s(ctx->id=%d)", __func__, ctx.getIdentifier());
95   this->client_ctx.push_back(ctx);
96   return OP_SUCCESS;
97 } /* End of addClientContext() */
98 
99 
100 /** Looks up the context of a given client, based on the supplied client ID.
101   * On success, it returns a pointer to the client's context object. NULL is
102   * returned when no context could be found.  */
getClientContext(clientid_t clnt)103 NEPContext *EchoServer::getClientContext(clientid_t clnt){
104   nping_print(DBG_4, "%s(%d) %lu", __func__, clnt, (unsigned long)this->client_ctx.size());
105   for(unsigned int i=0; i<this->client_ctx.size(); i++){
106     if(this->client_ctx[i].getIdentifier() == clnt ){
107         nping_print(DBG_3, "Found client with ID #%d at p%d. Total clients %lu", clnt, i, (unsigned long)this->client_ctx.size());
108         return &(this->client_ctx[i]);
109     }
110   }
111   nping_print(DBG_3, "No client with ID #%d was found. Total clients %lu", clnt, (unsigned long)this->client_ctx.size());
112   return NULL;
113 } /* End of getClientContext() */
114 
115 
116 /** Looks up the context of a given client, based on the supplied nsock IOD.
117   * On success, it returns a pointer to the client's context object. NULL is
118   * returned when no context could be found.  */
getClientContext(nsock_iod iod)119 NEPContext *EchoServer::getClientContext(nsock_iod iod){
120   nping_print(DBG_4, "%s()", __func__);
121   clientid_t *id=NULL;
122   if( (id=(clientid_t *)nsock_iod_get_udata(iod))==NULL )
123     return NULL;
124   else
125     return this->getClientContext(*id);
126 } /* End of getClientContext() */
127 
128 
129 /** Deletes context information associated with a given client. Returns
130   * OP_SUCCESS if the context object was successfully deleted or OP_FAILURE if
131   * the context could not be found.  */
destroyClientContext(clientid_t clnt)132 int EchoServer::destroyClientContext(clientid_t clnt){
133   bool deleted=false;
134   std::vector<NEPContext>::iterator it;
135   /* Iterate through the context array and delete the one that belongs to clnt */
136   for ( it=this->client_ctx.begin(); it<this->client_ctx.end(); it++){
137       if(it->getIdentifier()==clnt){
138         this->client_ctx.erase(it);
139         deleted=true;
140         break;
141       }
142   }
143   return (deleted) ? OP_SUCCESS : OP_FAILURE;
144 } /* End of destroyClientContext() */
145 
146 
147 /** Returns the Nsock IOD associated with a given client ID. */
getClientNsockIOD(clientid_t clnt)148 nsock_iod EchoServer::getClientNsockIOD(clientid_t clnt){
149   nping_print(DBG_4, "%s(%d)", __func__, clnt);
150   NEPContext *ctx;
151   if((ctx=this->getClientContext(clnt))==NULL )
152     return NULL;
153   else
154     return ctx->getNsockIOD();
155 } /* End of getClientNsockIOD() */
156 
157 
158 /** Generates a new client identifier. This is used internally by the echo
159   * server, but this value is never sent over the wire (it has nothing to do
160   * with the NEP protocol). Each call to getNewClientID() generates a new
161   * identifier, so it should only be called once per client session.
162   * Warning: This code checks for an overflow and wraps the client id count back
163   * to zero if necessary. A given execution of a server should be able to handle
164   * 4,294,967,296 client sessions. Practically there is no way to achieve that
165   * number (it would be something like receiving one client session per second
166   * for 136 years, so relax!) However, it should be noted that this
167   * implementation makes no effort to handle re-used client identifiers, so
168   * there is a tiny chance that after the 4,294,967,296th client, the assigned
169   * number conflicts with an active session ;-) */
getNewClientID()170 clientid_t EchoServer::getNewClientID(){
171   nping_print(DBG_4, "%s()", __func__);
172   if(this->client_id_count==0xFFFF)  /* Wrap back to zero. */
173       this->client_id_count=0;
174   else
175     this->client_id_count++;
176   return this->client_id_count;
177 } /* End of getNewClientID() */
178 
179 
180 /** Returns a socket suitable to be passed to accept() */
nep_listen_socket()181 int EchoServer::nep_listen_socket(){
182   nping_print(DBG_4, "%s()", __func__);
183   int one=1;                 /**< Dummy var for setsockopt() call      */
184   int master_sd=-1;          /**< Master socket. Server listens on it  */
185   struct sockaddr_in server_addr4;  /**< For our own IPv4 address      */
186   struct sockaddr_in6 server_addr6; /**< For our own IPv6 address      */
187   int port = o.getEchoPort();
188 
189   /* Ignore SIGPIPE signal, received when a client disconnects suddenly and
190    *data is sent to it before noticing. */
191   #ifndef WIN32
192     signal(SIGPIPE, SIG_IGN);
193   #endif
194 
195   /* AF_INET6 */
196   if( o.ipv6() ){
197 
198     /* Obtain a regular TCP socket for IPv6 */
199     if( (master_sd=socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP))<0 )
200         nping_fatal(QT_3, "Could not obtain AF_INET/SOCK_STREAM/IPPROTO_TCP socket");
201 
202     /* Set SO_REUSEADDR on socket so the bind does not fail if we had used
203      * this port in a previous execution, not long ago. */
204     if( setsockopt(master_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int))!=0 )
205         nping_warning(QT_3, "Failed to set SO_REUSEADDR on master socket.");
206 
207     memset(&server_addr6, 0, sizeof(struct sockaddr_in6));
208     server_addr6.sin6_addr = (o.spoofSource()) ? o.getIPv6SourceAddress() : in6addr_any;
209     server_addr6.sin6_family = AF_INET6;
210     server_addr6.sin6_port = htons(port);
211     server_addr6.sin6_flowinfo = 0;
212     #ifdef HAVE_SOCKADDR_IN6_SIN6_LEN
213         server_addr6.sin6_len = sizeof(struct sockaddr_in6);
214     #endif
215     /* Bind to local address and the specified port */
216     if( ::bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){
217         nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr6.sin6_addr), port);
218         /* If the bind failed for the supplied address, just try again with in6addr_any */
219         if( o.spoofSource() ){
220             server_addr6.sin6_addr = in6addr_any;
221             if( ::bind(master_sd, (struct sockaddr *)&server_addr6, sizeof(server_addr6)) != 0 ){
222                 nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno));
223             }else{
224                 nping_print(VB_1, "Server bound to port %d", port);
225             }
226         }
227     }else{
228         nping_print(VB_1, "Server bound to %s:%d", IPtoa(server_addr6.sin6_addr), port);
229     }
230 
231 
232   /* AF_INET */
233   }else{
234 
235     /* Obtain a regular TCP socket for IPv4 */
236     if( (master_sd=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))<0 )
237         nping_fatal(QT_3, "Could not obtain AF_INET/SOCK_STREAM/IPPROTO_TCP socket");
238 
239     /* Set SO_REUSEADDR on socket so the bind does not fail if we had used
240      * this port in a previous execution, not long ago. */
241     if( setsockopt(master_sd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(int))!=0 )
242         nping_warning(QT_3, "Failed to set SO_REUSEADDR on master socket.");
243 
244 
245     memset(&server_addr4, 0, sizeof(struct sockaddr_in));
246     server_addr4.sin_family = AF_INET;
247     server_addr4.sin_port = htons(port);
248     server_addr4.sin_addr.s_addr = (o.spoofSource()) ? o.getIPv4SourceAddress().s_addr : INADDR_ANY;
249 #ifdef HAVE_SOCKADDR_IN_SIN_LEN
250     server_addr4.sin_len = sizeof(struct sockaddr_in);
251 #endif
252 
253     /* Bind to local address and the specified port */
254     if( ::bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){
255         nping_warning(QT_3, "Failed to bind to source address %s. Trying to bind to port %d...", IPtoa(server_addr4.sin_addr), port);
256         /* If the bind failed for the supplied address, just try again with in6addr_any */
257         if( o.spoofSource() ){
258             server_addr4.sin_addr.s_addr=INADDR_ANY;
259             if( ::bind(master_sd, (struct sockaddr *)&server_addr4, sizeof(server_addr4)) != 0 ){
260                 nping_fatal(QT_3, "Could not bind to port %d (%s).", port, strerror(errno));
261             }else{
262                 nping_print(VB_1, "Server bound to port %d", port);
263             }
264         }
265     }else{
266         nping_print(VB_1, "Server bound to %s:%d", IPtoa(server_addr4.sin_addr), port);
267     }
268 
269   }
270 
271    /* Listen for incoming TCP connections... */
272    if( listen(master_sd, LISTEN_QUEUE_SIZE) != 0 ){
273        nping_fatal(QT_3, "[E] Failed to listen() on port %d (%s)", port, strerror(errno));
274    }
275   return master_sd;
276 } /* End of nep_listen() */
277 
278 
279 
280 /* Weighting factors */
281 #define FACTOR_IPv4_TOS       1.0
282 #define FACTOR_IPv4_PROTO     0.9
283 #define FACTOR_IPv4_ID        2.5
284 #define FACTOR_IPv4_FRAGOFF   1.0
285 #define FACTOR_IPv6_TCLASS    1.0
286 #define FACTOR_IPv6_FLOW      2.5
287 #define FACTOR_IPv6_NHDR      0.9
288 #define FACTOR_TCP_SPORT      1.5
289 #define FACTOR_TCP_DPORT      1.0
290 #define FACTOR_TCP_SEQ        2.0
291 #define FACTOR_TCP_ACK        1.0
292 #define FACTOR_TCP_FLAGS      1.0
293 #define FACTOR_TCP_WIN        1.0
294 #define FACTOR_TCP_URP        1.0
295 #define FACTOR_ICMP_TYPE      1.0
296 #define FACTOR_ICMP_CODE      1.0
297 #define FACTOR_UDP_SPORT      1.0
298 #define FACTOR_UDP_DPORT      1.0
299 #define FACTOR_UDP_LEN        1.0
300 #define FACTOR_PAYLOAD_MAGIC  1.0
301 
302 #define ZERO_PENALTY    0.3
303 
304 #define MIN_ACCEPTABLE_SCORE_TCP  10.0
305 #define MIN_ACCEPTABLE_SCORE_UDP  8.0
306 #define MIN_ACCEPTABLE_SCORE_ICMP 6.0
307 
nep_match_headers(IPv4Header * ip4,IPv6Header * ip6,TCPHeader * tcp,UDPHeader * udp,ICMPv4Header * icmp4,RawData * payload)308 clientid_t EchoServer::nep_match_headers(IPv4Header *ip4, IPv6Header *ip6, TCPHeader *tcp, UDPHeader *udp, ICMPv4Header *icmp4, RawData *payload){
309   nping_print(DBG_4, "%s(%p,%p,%p,%p,%p,%p)", __func__, ip4, ip6, tcp, udp, icmp4, payload);
310     unsigned int i=0, k=0;
311     u8 *buff=NULL;
312     int bufflen=-1;
313     NEPContext *ctx;
314     fspec_t *fspec;
315     float current_score=0;
316     float candidate_score=-1;
317     float minimum_score=0;
318     clientid_t candidate=-1;
319 
320     /* Iterate through the list of connected clients */
321     for(i=0; i<this->client_ctx.size(); i++ ){
322         current_score=0;
323         ctx=&(this->client_ctx[i]);
324         nping_print(DBG_2, "%s() Trying to match packet against client #%d", __func__, ctx->getIdentifier());
325         if( ctx->ready() ){
326             /* Iterate through client's list of packet field specifiers */
327             for(k=0; (fspec=ctx->getClientFieldSpec(k))!=NULL; k++){
328                 switch(fspec->field){
329                     case PSPEC_IPv4_TOS:
330                         if(ip4==NULL)break;
331                         nping_print(DBG_3, "%s() Trying to match IP TOS", __func__);
332                         if( ip4->getTOS()==fspec->value[0] ){
333                             nping_print(DBG_3, "[Match] IP TOS=%02x", ip4->getTOS());
334                             current_score += 1 * FACTOR_IPv4_TOS * ((ip4->getTOS()==0) ? ZERO_PENALTY : 1);
335                         }
336                     break;
337                     case PSPEC_IPv4_PROTO:
338                         if(ip4==NULL)break;
339                         nping_print(DBG_3, "%s() Trying to match IP Next Protocol", __func__);
340                         if( ip4->getNextProto()==fspec->value[0] ){
341                             nping_print(DBG_3, "[Match] IP Proto=%02x", ip4->getNextProto());
342                             current_score += 1 * FACTOR_IPv4_PROTO;
343                         }
344                     break;
345                     case PSPEC_IPv4_ID:
346                         if(ip4==NULL)break;
347                         nping_print(DBG_3, "%s() Trying to match IP Identification", __func__);
348                         if( ip4->getIdentification()==ntohs( *((u16 *)fspec->value) ) ){
349                             nping_print(DBG_3, "[Match] IP Id=%u", ip4->getIdentification());
350                             current_score += 2 * FACTOR_IPv4_ID;
351                         }
352                     break;
353                     case PSPEC_IPv4_FRAGOFF:
354                         if(ip4==NULL)break;
355                         nping_print(DBG_3, "%s() Trying to match IP Fragment offset", __func__);
356                         if( ip4->getFragOffset()==ntohs( *((u16 *)fspec->value)) ){
357                             nping_print(DBG_3, "[Match] IP FragOff=%u", ip4->getFragOffset() );
358                             current_score += 2 * FACTOR_IPv4_FRAGOFF * ((ip4->getFragOffset()==0) ? ZERO_PENALTY : 1);
359                         }
360                     break;
361 
362                     case PSPEC_IPv6_TCLASS:
363                         if(ip6==NULL)break;
364                         nping_print(DBG_3, "%s() Trying to match IPv6 Traffic Class", __func__);
365                         if( ip6->getTrafficClass()==fspec->value[0] ){
366                             nping_print(DBG_3, "[Match] IPv6 TClass=%u", ip6->getTrafficClass() );
367                             current_score += 1 * FACTOR_IPv6_TCLASS  * ((ip6->getTrafficClass()==0) ? ZERO_PENALTY : 1);
368                         }
369                     break;
370                     case PSPEC_IPv6_FLOW:
371                         if(ip6==NULL)break;
372                         nping_print(DBG_3, "%s() Trying to match IPv6 Flow Label", __func__);
373                         if( ip6->getFlowLabel()==ntohl( *((u32 *)fspec->value)) ){
374                             nping_print(DBG_3, "[Match] IPv6 Flow=%lu", (long unsigned)ip6->getFlowLabel() );
375                             current_score += 3 * FACTOR_IPv6_FLOW  * ((ip6->getFlowLabel()==0) ? ZERO_PENALTY : 1);
376                         }
377                     break;
378                     case PSPEC_IPv6_NHDR:
379                         if(ip6==NULL)break;
380                         nping_print(DBG_3, "%s() Trying to match IPv6 Next Header", __func__);
381                         if( ip6->getNextHeader()==fspec->value[0] ){
382                             nping_print(DBG_3, "[Match] IPv6 NextHdr=%02x", ip6->getNextHeader());
383                             current_score += 1 * FACTOR_IPv6_NHDR;
384                         }
385                     break;
386                     case PSPEC_TCP_SPORT:
387                         if(tcp==NULL)break;
388                         nping_print(DBG_3, "%s() Trying to match TCP Source Port", __func__);
389                         if( tcp->getSourcePort()==ntohs( *((u16 *)fspec->value) ) ){
390                             nping_print(DBG_3, "[Match] TCP Src=%u", tcp->getSourcePort());
391                             current_score += 2 * FACTOR_TCP_SPORT;
392                         }
393                     break;
394                     case PSPEC_TCP_DPORT:
395                         if(tcp==NULL)break;
396                         nping_print(DBG_3, "%s() Trying to match TCP Destination Port", __func__);
397                         if( tcp->getDestinationPort()==ntohs( *((u16 *)fspec->value) ) ){
398                             nping_print(DBG_3, "[Match] TCP Dst=%u", tcp->getDestinationPort());
399                             current_score += 2 * FACTOR_TCP_DPORT;
400                         }
401                     break;
402                     case PSPEC_TCP_SEQ:
403                         if(tcp==NULL)break;
404                         nping_print(DBG_3, "%s() Trying to match TCP Sequence Number", __func__);
405                         if( tcp->getSeq()==ntohl( *((u32 *)fspec->value) ) ){
406                             nping_print(DBG_3, "[Match] TCP Seq=%u", tcp->getSeq());
407                             current_score += 4 * FACTOR_TCP_SEQ  * ((tcp->getSeq()==0) ? ZERO_PENALTY : 1);
408                         }
409                     break;
410                     case PSPEC_TCP_ACK:
411                         if(tcp==NULL)break;
412                         nping_print(DBG_3, "%s() Trying to match TCP Acknowledgment", __func__);
413                         if( tcp->getAck()==ntohl( *((u32 *)fspec->value) ) ){
414                             nping_print(DBG_3, "[Match] TCP Ack=%u", tcp->getAck());
415                             current_score += 4 * FACTOR_TCP_ACK  * ((tcp->getAck()==0) ? ZERO_PENALTY : 1);
416                         }
417                     break;
418                     case PSPEC_TCP_FLAGS:
419                         if(tcp==NULL)break;
420                         if( tcp->getFlags()==fspec->value[0] ){
421                             nping_print(DBG_3, "%s() Trying to match TCP Flags", __func__);
422                             nping_print(DBG_3, "[Match] TCP Flags=%02x", tcp->getFlags());
423                             current_score += 1 * FACTOR_TCP_FLAGS;
424                         }
425                     break;
426                     case PSPEC_TCP_WIN:
427                         if(tcp==NULL)break;
428                         nping_print(DBG_3, "%s() Trying to match TCP Window", __func__);
429                         if( tcp->getWindow()==ntohs( *((u16 *)fspec->value) ) ){
430                             nping_print(DBG_3, "[Match] TCP Win=%u", tcp->getWindow());
431                             current_score += 2 * FACTOR_TCP_WIN  * ((tcp->getWindow()==0) ? ZERO_PENALTY : 1);
432                         }
433                     break;
434                     case PSPEC_TCP_URP:
435                         if(tcp==NULL)break;
436                         nping_print(DBG_3, "%s() Trying to match TCP Urgent Pointer", __func__);
437                         if( tcp->getUrgPointer()==ntohs( *((u16 *)fspec->value) ) ){
438                             nping_print(DBG_3, "[Match] TCP Win=%u", tcp->getUrgPointer());
439                             current_score += 2 * FACTOR_TCP_URP  * ((tcp->getUrgPointer()==0) ? ZERO_PENALTY : 1);
440                         }
441                     break;
442                     case PSPEC_ICMP_TYPE:
443                         if(icmp4==NULL)break;
444                         nping_print(DBG_3, "%s() Trying to match ICMPv4 Type", __func__);
445                         if( icmp4->getType()==fspec->value[0] ){
446                             nping_print(DBG_3, "[Match] ICMPv4 Type=%02x", icmp4->getType());
447                             current_score += 1 * FACTOR_ICMP_TYPE;
448                         }
449                     break;
450                     case PSPEC_ICMP_CODE:
451                         if(icmp4==NULL)break;
452                         nping_print(DBG_3, "%s() Trying to match ICMPv4 Code", __func__);
453                         if( icmp4->getCode()==fspec->value[0] ){
454                             nping_print(DBG_3, "[Match] ICMPv4 Code=%02x", icmp4->getCode());
455                             current_score += 1 * FACTOR_ICMP_CODE  * ((icmp4->getCode()==0) ? ZERO_PENALTY : 1);
456                         }
457                     break;
458                     case PSPEC_UDP_SPORT:
459                         if(udp==NULL)break;
460                         nping_print(DBG_3, "%s() Trying to match UDP Source Port", __func__);
461                         if( udp->getSourcePort()==ntohs( *((u16 *)fspec->value) ) ){
462                             nping_print(DBG_3, "[Match] UDP Src=%u", udp->getSourcePort());
463                             current_score += 2 * FACTOR_UDP_SPORT;
464                         }
465                     break;
466                     case PSPEC_UDP_DPORT:
467                         if(udp==NULL)break;
468                         nping_print(DBG_3, "%s() Trying to match UDP Destination Port", __func__);
469                         if( udp->getDestinationPort()==ntohs( *((u16 *)fspec->value) ) ){
470                             nping_print(DBG_3, "[Match] UDP Dst=%u", udp->getDestinationPort());
471                             current_score += 2 * FACTOR_UDP_DPORT;
472                         }
473                     break;
474                     case PSPEC_UDP_LEN:
475                         if(udp==NULL)break;
476                         nping_print(DBG_3, "%s() Trying to match UDP Length", __func__);
477                         if( udp->getTotalLength()==ntohs( *((u16 *)fspec->value) ) ){
478                             nping_print(DBG_3, "[Match] UDP Len=%u", udp->getTotalLength());
479                             current_score += 2 * FACTOR_UDP_LEN * ((udp->getTotalLength()==8) ? ZERO_PENALTY : 1);
480                         }
481                     break;
482                     case PSPEC_PAYLOAD_MAGIC:
483                         if(payload==NULL)break;
484                         nping_print(DBG_3, "%s() Trying to match Payload Magic value", __func__);
485                         buff=payload->getBinaryBuffer(&bufflen);
486                         if(buff==NULL || bufflen<=0 || fspec->len>bufflen)
487                             break;
488                         if( memcmp(buff, fspec->value, fspec->len)==0 ){
489                             nping_print(DBG_3|NO_NEWLINE, "[Match] Payload magic=0x");
490                             for(unsigned int i=0; i<fspec->len; i++)
491                                 nping_print(DBG_3|NO_NEWLINE,"%02x", fspec->value[i]);
492                             nping_print(DBG_3, ";");
493                             /* The payload magic may affect the score only between
494                              * zero and 4 bytes. This is done to prevent long
495                              * common strings like "GET / HTTP/1.1\r\n"
496                              * increasing the score a lot and cause problems for
497                              * the matching logic. */
498                             current_score+= MIN(4, fspec->len)*FACTOR_PAYLOAD_MAGIC;
499                         }
500                     break;
501 
502                     default:
503                         nping_warning(QT_2, "Bogus field specifier found in client #%d context. Please report a bug", ctx->getIdentifier());
504                     break;
505                 }
506             } /* End of field specifiers loop */
507 
508             nping_print(DBG_3, "%s() current_score=%.02f candidate_score=%.02f", __func__, current_score, candidate_score);
509             if( (current_score>0) && (current_score>=candidate_score)){
510                 candidate_score=current_score;
511                 candidate=ctx->getIdentifier();
512                 nping_print(DBG_3, "%s() Found better candidate (client #%d; score=%.02f)", __func__, candidate, candidate_score);
513             }
514         }
515     } /* End of connected clients loop */
516 
517     if( tcp!=NULL )
518         minimum_score=MIN_ACCEPTABLE_SCORE_TCP;
519     else if (udp!=NULL)
520         minimum_score=MIN_ACCEPTABLE_SCORE_UDP;
521     else if(icmp4!=NULL)
522         minimum_score=MIN_ACCEPTABLE_SCORE_ICMP;
523     else
524         minimum_score=10000;
525 
526     /* Check if we managed to match packet and client */
527     if (candidate>=0 && candidate_score>=minimum_score){
528         nping_print(DBG_2, "%s() Packet matched successfully with client #%d", __func__, candidate);
529         return candidate;
530     }else{
531         if(candidate<0)
532             nping_print(DBG_2, "%s() Couldn't match packet with any client.", __func__);
533         else
534             nping_print(DBG_2, "%s() Found matching client but score is too low. Discarded.", __func__);
535         return CLIENT_NOT_FOUND;
536     }
537     return CLIENT_NOT_FOUND;
538 } /* End of nep_match_ipv4() */
539 
540 
nep_match_packet(const u8 * pkt,size_t pktlen)541 clientid_t EchoServer::nep_match_packet(const u8 *pkt, size_t pktlen){
542   nping_print(DBG_4, "%s(%p, %lu)", __func__, pkt, (long unsigned)pktlen);
543   int iplen=0, ip6len=0, tcplen=0, udplen=0;
544   bool payload_included=false;
545   IPv4Header ip4;
546   IPv6Header ip6;
547   TCPHeader tcp;
548   UDPHeader udp;
549   ICMPv4Header icmp4;
550   RawData payload;
551 
552   if(this->client_id_count<0){
553     nping_print(DBG_1, "Error trying to match the packet. No clients connected.");
554     return CLIENT_NOT_FOUND;
555   }else if(pktlen<IP_HEADER_LEN){
556     nping_print(DBG_1, "Error trying to match the packet. Bogus packet received (too short)");
557     return CLIENT_NOT_FOUND;
558   }
559 
560   /* Determine IP version */
561   if (ip4.storeRecvData(pkt, pktlen)==OP_FAILURE)
562     return CLIENT_NOT_FOUND;
563 
564   if(ip4.getVersion()==0x04){
565 
566     nping_print(DBG_2, "Recv packet is IPv4. Trying to find a matching client.");
567     if( (iplen=ip4.validate())==OP_FAILURE){
568         return CLIENT_NOT_FOUND;
569     }else{
570         switch( ip4.getNextProto() ){
571             case 1: // ICMP
572                 if( icmp4.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE )
573                     return CLIENT_NOT_FOUND;
574                 else
575                     return this->nep_match_headers(&ip4, NULL, NULL, NULL, &icmp4, NULL);
576             break;
577 
578             case 6: // TCP
579                 if( tcp.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
580                     return CLIENT_NOT_FOUND;
581                 }else{
582                     if( (tcplen=tcp.validate())==OP_FAILURE){
583                         return CLIENT_NOT_FOUND;
584                     }else{
585                         if( (int)pktlen > (iplen+tcplen) ){
586                            if( payload.storeRecvData(pkt+iplen+tcplen, pktlen-iplen-tcplen)!=OP_FAILURE)
587                                payload_included=true;
588                         }
589                         if(payload_included)
590                             return this->nep_match_headers(&ip4, NULL, &tcp, NULL, NULL, &payload);
591                         else
592                             return this->nep_match_headers(&ip4, NULL, &tcp, NULL, NULL, NULL);
593                     }
594                 }
595             break;
596 
597             case 17: // UDP
598                 if( udp.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
599                     return CLIENT_NOT_FOUND;
600                 }else{
601                     if( (udplen=udp.validate())==OP_FAILURE){
602                         return CLIENT_NOT_FOUND;
603                     }else{
604                         if( (int)pktlen > (iplen+udplen) ){
605                            if( payload.storeRecvData(pkt+iplen+udplen, pktlen-iplen-udplen)!=OP_FAILURE)
606                                payload_included=true;
607                         }
608                         if(payload_included)
609                             return this->nep_match_headers(&ip4, NULL, NULL, &udp, NULL, &payload);
610                         else
611                             return this->nep_match_headers(&ip4, NULL, NULL, &udp, NULL, NULL);
612                     }
613                 }
614             break;
615 
616             case 41: /* IPv6 encapsulated in the IPv4 datagram! */
617                 if( ip6.storeRecvData(pkt+iplen, pktlen-iplen)==OP_FAILURE ){
618                     return CLIENT_NOT_FOUND;
619                 }else{
620                     if( (ip6len=ip6.validate())==OP_FAILURE){
621                         return CLIENT_NOT_FOUND;
622                     }else{
623                         switch( ip6.getNextHeader() ){
624                             case 58: // ICMPv6
625                                 nping_print(DBG_4, "Encapsulated IPv4{ IPv6{ ICMPv6 } } received. Not supported.");
626                                 return CLIENT_NOT_FOUND;
627                             break;
628 
629                             case 6: // TCP
630                                 if( tcp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
631                                     return CLIENT_NOT_FOUND;
632                                 }else{
633                                     if( (tcplen=tcp.validate())==OP_FAILURE){
634                                         return CLIENT_NOT_FOUND;
635                                     }else{
636                                         if( (int)pktlen > (ip6len+iplen+tcplen) ){
637                                            if( payload.storeRecvData(pkt+ip6len+iplen+tcplen, pktlen-ip6len-iplen-tcplen)!=OP_FAILURE)
638                                                payload_included=true;
639                                         }
640                                         if(payload_included)
641                                             return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, &payload);
642                                         else
643                                             return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, NULL);
644                                     }
645                                 }
646                             break;
647 
648                             case 17: // UDP
649                                 if( udp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
650                                     return CLIENT_NOT_FOUND;
651                                 }else{
652                                     if( (udplen=udp.validate())==OP_FAILURE){
653                                         return CLIENT_NOT_FOUND;
654                                     }else{
655                                         if( (int)pktlen > (ip6len+iplen+udplen) ){
656                                            if( payload.storeRecvData(pkt+ip6len+iplen+udplen, pktlen-ip6len-iplen-udplen)!=OP_FAILURE)
657                                                payload_included=true;
658                                         }
659                                         if(payload_included)
660                                             return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, &payload);
661                                         else
662                                             return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, NULL);
663                                     }
664                                 }
665                             break;
666 
667                             default:
668                                 return CLIENT_NOT_FOUND;
669                             break;
670                         }
671                     }
672                 }
673             break;
674 
675             default:
676                 return CLIENT_NOT_FOUND;
677             break;
678         }
679     }
680   }else if(ip4.getVersion()==0x06){
681 
682     nping_print(DBG_2, "Recv packet is IPv6. Trying to find a matching client.");
683     if (ip6.storeRecvData(pkt, pktlen)==OP_FAILURE)
684         return CLIENT_NOT_FOUND;
685 
686     if( (ip6len=ip6.validate())==OP_FAILURE )
687         return CLIENT_NOT_FOUND;
688 
689     switch( ip6.getNextHeader() ){
690         case 58: // ICMPv6
691             nping_print(DBG_4, "Received ICMPv6 packet. Not yet supported.");
692             return CLIENT_NOT_FOUND;
693         break;
694 
695         case 6: // TCP
696             if( tcp.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
697                 return CLIENT_NOT_FOUND;
698             }else{
699                 if( (tcplen=tcp.validate())==OP_FAILURE){
700                     return CLIENT_NOT_FOUND;
701                 }else{
702                     if( (int)pktlen > (ip6len+tcplen) ){
703                        if( payload.storeRecvData(pkt+ip6len+tcplen, pktlen-ip6len-tcplen)!=OP_FAILURE)
704                            payload_included=true;
705                     }
706                     if(payload_included)
707                         return this->nep_match_headers(NULL, &ip6, &tcp, NULL, NULL, &payload);
708                     else
709                         return this->nep_match_headers(NULL, &ip6, &tcp, NULL, NULL, NULL);
710                 }
711             }
712         break;
713 
714         case 17: // UDP
715             if( udp.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
716                 return CLIENT_NOT_FOUND;
717             }else{
718                 if( (udplen=udp.validate())==OP_FAILURE){
719                     return CLIENT_NOT_FOUND;
720                 }else{
721                     if( (int)pktlen > (ip6len+udplen) ){
722                        if( payload.storeRecvData(pkt+ip6len+udplen, pktlen-ip6len-udplen)!=OP_FAILURE)
723                            payload_included=true;
724                     }
725                     if(payload_included)
726                         return this->nep_match_headers(NULL, &ip6, NULL, &udp, NULL, &payload);
727                     else
728                         return this->nep_match_headers(NULL, &ip6, NULL, &udp, NULL, NULL);
729                 }
730             }
731         break;
732 
733         case 4: /* IPv4 encapsulated in the IPv6 datagram */
734             if( ip4.storeRecvData(pkt+ip6len, pktlen-ip6len)==OP_FAILURE ){
735                 return CLIENT_NOT_FOUND;
736             }else{
737                 if( (iplen=ip4.validate())==OP_FAILURE){
738                     return CLIENT_NOT_FOUND;
739                 }else{
740                     switch( ip4.getNextProto() ){
741                         case 1: // ICMP
742                             if( icmp4.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE )
743                                 return CLIENT_NOT_FOUND;
744                             else
745                                 return this->nep_match_headers(&ip4, &ip6, NULL, NULL, &icmp4, NULL);
746                         break;
747 
748                         case 6: // TCP
749                             if( tcp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
750                                 return CLIENT_NOT_FOUND;
751                             }else{
752                                 if( (tcplen=tcp.validate())==OP_FAILURE){
753                                     return CLIENT_NOT_FOUND;
754                                 }else{
755                                     if( (int)pktlen > (ip6len+iplen+tcplen) ){
756                                        if( payload.storeRecvData(pkt+ip6len+iplen+tcplen, pktlen-ip6len-iplen-tcplen)!=OP_FAILURE)
757                                            payload_included=true;
758                                     }
759                                     if(payload_included)
760                                         return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, &payload);
761                                     else
762                                         return this->nep_match_headers(&ip4, &ip6, &tcp, NULL, NULL, NULL);
763                                 }
764                             }
765                         break;
766 
767                         case 17: // UDP
768                             if( udp.storeRecvData(pkt+ip6len+iplen, pktlen-ip6len-iplen)==OP_FAILURE ){
769                                 return CLIENT_NOT_FOUND;
770                             }else{
771                                 if( (udplen=udp.validate())==OP_FAILURE){
772                                     return CLIENT_NOT_FOUND;
773                                 }else{
774                                     if( (int)pktlen > (ip6len+iplen+udplen) ){
775                                        if( payload.storeRecvData(pkt+ip6len+iplen+udplen, pktlen-ip6len-iplen-udplen)!=OP_FAILURE)
776                                            payload_included=true;
777                                     }
778                                     if(payload_included)
779                                         return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, &payload);
780                                     else
781                                         return this->nep_match_headers(&ip4, &ip6, NULL, &udp, NULL, NULL);
782                                 }
783                             }
784                         break;
785 
786                         default:
787                             return CLIENT_NOT_FOUND;
788                         break;
789                     }
790                 }
791             }
792         break;
793 
794         default:
795             return CLIENT_NOT_FOUND;
796         break;
797     }
798   }else{
799     nping_print(DBG_2, "Received packet is not IP: Discarded.");
800     return CLIENT_NOT_FOUND;
801   }
802   return CLIENT_NOT_FOUND;
803 } /* End of nep_match_packet() */
804 
805 
nep_capture_handler(nsock_pool nsp,nsock_event nse,void * param)806 int EchoServer::nep_capture_handler(nsock_pool nsp, nsock_event nse, void *param){
807   nping_print(DBG_4, "%s()", __func__);
808   clientid_t clnt=CLIENT_NOT_FOUND;
809   const unsigned char *packet=NULL;
810   const unsigned char *link=NULL;
811   nsock_iod nsi = nse_iod(nse);
812   struct timeval pcaptime;
813   nsock_iod clnt_iod=NULL;
814   NEPContext *ctx=NULL;
815   EchoHeader pkt_out;
816   size_t linklen=0;
817   size_t packetlen=0;
818   handler_arg_t arg;
819   arg.me=this;
820   arg.param=NULL;
821 
822   /* If there are connected clients, schedule another packet capture event */
823   if(this->client_ctx.size()>0){
824     nsock_pcap_read_packet(nsp, nsi, capture_handler, NSOCK_INFINITE, &arg);
825     nping_print(DBG_3, "Scheduled next capture event");
826   }
827 
828   /* Get the actual captured packet */
829   nse_readpcap(nse, &link, &linklen, &packet, &packetlen, NULL, &pcaptime);
830   nping_print(DBG_3, "Captured %lu bytes", (unsigned long)packetlen);
831 
832   /* Update Rx stats */
833   o.stats.addRecvPacket(packetlen);
834 
835   /* Try to match received packet with a connected client. */
836   if( (clnt=this->nep_match_packet(packet, packetlen)) == CLIENT_NOT_FOUND ){
837     nping_print(DBG_3, "Couldn't match captured packet with a client");
838     return OP_FAILURE;
839   }else{
840     nping_print(DBG_4, "Captured packet belongs to client #%d", clnt);
841   }
842 
843   /* Fetch client context */
844   if( (ctx=this->getClientContext(clnt)) == NULL ){
845     nping_print(DBG_2, "Error: no context found for client #%d", clnt);
846     return OP_FAILURE;
847   }
848 
849   /* Lookup client's IOD */
850   if( (clnt_iod=ctx->getNsockIOD()) == NULL ){
851     nping_print(DBG_2, "Error: no IOD found for client #%d", clnt);
852     return OP_FAILURE;
853   }
854 
855   if( ctx->ready() ){
856       this->generate_echo(&pkt_out, packet, packetlen, ctx);
857       nsock_write(nsp, clnt_iod, echo_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
858       o.stats.addEchoedPacket(packetlen);
859   }
860   return OP_SUCCESS;
861 } /* End of nep_capture_handler() */
862 
863 
nep_echo_handler(nsock_pool nsp,nsock_event nse,void * param)864 int EchoServer::nep_echo_handler(nsock_pool nsp, nsock_event nse, void *param){
865   nping_print(DBG_4, "%s()", __func__);
866   enum nse_status status=nse_status(nse);
867   if (status!=NSE_STATUS_SUCCESS){
868       nping_print(DBG_1, "Couldn't send NEP_ECHO. Terminating client session\n");
869       this->nep_session_ended_handler(nsp, nse, param);
870   }else{
871     nping_print(DBG_1, "SENT: NEP_ECHO");
872   }
873   return OP_SUCCESS;
874 } /* End of nep_echo_handler() */
875 
876 
nep_hs_server_handler(nsock_pool nsp,nsock_event nse,void * param)877 int EchoServer::nep_hs_server_handler(nsock_pool nsp, nsock_event nse, void *param){
878   nping_print(DBG_4, "%s()", __func__);
879   nsock_iod nsi = nse_iod(nse);
880   NEPContext *ctx=NULL;
881   enum nse_status status=nse_status(nse);
882   if (status!=NSE_STATUS_SUCCESS){
883       nping_print(DBG_1, "Couldn't send NEP_HANDSHAKE_SERVER. Terminating client session\n");
884       this->nep_session_ended_handler(nsp, nse, param);
885       return OP_FAILURE;
886   }
887   /* Lookup client context and schedule a read operation to receive a
888    * NEP_HANDSHAKE_CLIENT message */
889   if( (ctx=this->getClientContext(nsi))!=NULL ){
890       ctx->setState(STATE_HS_SERVER_SENT);
891       nping_print(DBG_1, "SENT: NEP_HANDSHAKE_SERVER to %s", IPtoa(ctx->getAddress()));
892       nsock_readbytes(nsp, nsi, hs_client_handler, NSOCK_INFINITE, NULL, NEP_HANDSHAKE_CLIENT_LEN);
893   }
894   return OP_SUCCESS;
895 } /* End of nep_hs_server_handler() */
896 
897 
nep_hs_client_handler(nsock_pool nsp,nsock_event nse,void * param)898 int EchoServer::nep_hs_client_handler(nsock_pool nsp, nsock_event nse, void *param){
899   nping_print(DBG_4, "%s()", __func__);
900   nsock_iod nsi = nse_iod(nse);
901   NEPContext *ctx=NULL;
902   EchoHeader pkt_out;
903   u8 *inbuff=NULL;
904   int inlen=0;
905   enum nse_status status=nse_status(nse);
906   if (status!=NSE_STATUS_SUCCESS){
907     nping_print(DBG_1, "Failed to receive NEP_HANDSHAKE_CLIENT. Terminating client session");
908     this->nep_session_ended_handler(nsp, nse, param);
909     return OP_FAILURE;
910   }else{
911     nping_print(DBG_1, "RCVD: NEP_HANDSHAKE_CLIENT");
912   }
913 
914   /* Lookup client context */
915   if( (ctx=this->getClientContext(nsi))==NULL ){
916     this->nep_session_ended_handler(nsp, nse, param);
917     return OP_FAILURE;
918   }
919 
920   /* Ask nsock to provide received data */
921   if( (inbuff=(u8 *)nse_readbuf(nse, &inlen))==NULL ){
922     this->nep_session_ended_handler(nsp, nse, param);
923     return OP_FAILURE;
924   }
925 
926   /* Validate received NEP_HANDSHAKE_CLIENT */
927   if( this->parse_hs_client(inbuff, inlen, ctx)!=OP_SUCCESS ){
928       this->nep_session_ended_handler(nsp, nse, param);
929       return OP_FAILURE;
930   }
931   ctx->setState(STATE_HS_FINAL_SENT);
932 
933   /* Craft a NEP_HANDSHAKE_FINAL message and send it to the client */
934   if( this->generate_hs_final(&pkt_out, ctx)!=OP_SUCCESS ){
935       this->nep_session_ended_handler(nsp, nse, param);
936       return OP_FAILURE;
937   }
938   nsock_write(nsp, nsi, hs_final_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
939   return OP_SUCCESS;
940 } /* End of nep_hs_client_handler() */
941 
942 
nep_hs_final_handler(nsock_pool nsp,nsock_event nse,void * param)943 int EchoServer::nep_hs_final_handler(nsock_pool nsp, nsock_event nse, void *param){
944   nping_print(DBG_4, "%s()", __func__);
945   nsock_iod nsi = nse_iod(nse);
946   nping_print(DBG_1, "SENT: NEP_HANDSHAKE_FINAL");
947   /* Receive NEP_PACKETSPEC */
948   nsock_readbytes(nsp, nsi, packetspec_handler, NSOCK_INFINITE, NULL, NEP_PACKETSPEC_LEN);
949   return OP_SUCCESS;
950 } /* End of nep_hs_final_handler() */
951 
952 
nep_packetspec_handler(nsock_pool nsp,nsock_event nse,void * param)953 int EchoServer::nep_packetspec_handler(nsock_pool nsp, nsock_event nse, void *param){
954   nping_print(DBG_4, "%s()", __func__);
955   nsock_iod nsi = nse_iod(nse);
956   EchoHeader pkt_in;
957   EchoHeader pkt_out;
958   NEPContext *ctx=NULL;
959   u8 *recvbuff=NULL;
960   int recvbytes=0;
961   enum nse_status status=nse_status(nse);
962   if (status!=NSE_STATUS_SUCCESS){
963     nping_print(DBG_1, "Failed to receive NEP_PACKET_SPEC message. Terminating client session\n");
964     this->nep_session_ended_handler(nsp, nse, param);
965     return OP_FAILURE;
966   }else{
967     nping_print(DBG_1, "RCVD: NEP_PACKETSPEC");
968   }
969 
970   /* Lookup client context */
971   if( (ctx=this->getClientContext(nsi))==NULL ){
972     this->nep_session_ended_handler(nsp, nse, param);
973     return OP_FAILURE;
974   }
975 
976   /* Ask nsock to provide received data */
977   if( (recvbuff=(u8 *)nse_readbuf(nse, &recvbytes))==NULL ){
978     this->nep_session_ended_handler(nsp, nse, param);
979     return OP_FAILURE;
980   }
981 
982   /* Validate received NEP_PACKET_SPEC message */
983   if( this->parse_packet_spec(recvbuff, recvbytes, ctx)!=OP_SUCCESS ){
984       this->nep_session_ended_handler(nsp, nse, param);
985       nping_print(VB_1, "[%lu] Couldn't establish NEP session with client #%d (%s:%d).", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
986       return OP_FAILURE;
987   }
988   ctx->setState(STATE_READY_SENT);
989   nping_print(VB_1, "[%lu] NEP handshake with client #%d (%s:%d) was performed successfully", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
990 
991   /* Craft response and send it */
992   this->generate_ready(&pkt_out, ctx);
993   nsock_write(nsp, nsi, ready_handler, NSOCK_INFINITE, NULL, (const char *)pkt_out.getBinaryBuffer(), pkt_out.getLen());
994 
995   /* From this point, the client is not supposed to send anything to the server
996    * through the side channel. However, we now schedule a read operation so
997    * we detect when the client disconnects (because Nsock will tell us). */
998   nsock_readbytes(nsp, nsi, session_ended_handler, NSOCK_INFINITE, NULL, 65535);
999 
1000   /* At this point, we consider the NEP session fully established and therefore
1001    * we update the count of served clients */
1002   o.stats.addEchoClientServed();
1003 
1004   return OP_SUCCESS;
1005 } /* End of nep_packetspec_handler() */
1006 
1007 
nep_ready_handler(nsock_pool nsp,nsock_event nse,void * param)1008 int EchoServer::nep_ready_handler(nsock_pool nsp, nsock_event nse, void *param){
1009   nping_print(DBG_4, "%s()", __func__);
1010   nping_print(DBG_1, "SENT: NEP_READY");
1011   return OP_SUCCESS;
1012 } /* End of nep_ready_handler() */
1013 
1014 
nep_session_ended_handler(nsock_pool nsp,nsock_event nse,void * param)1015 int EchoServer::nep_session_ended_handler(nsock_pool nsp, nsock_event nse, void *param){
1016   nping_print(DBG_4, "%s()", __func__);
1017   nsock_iod nsi = nse_iod(nse);
1018   clientid_t clnt;
1019   NEPContext *ctx=NULL;
1020 
1021   /* Lookup client context */
1022   if( (ctx=this->getClientContext(nsi))!=NULL ){
1023     nping_print(VB_0, "[%lu] Client #%d (%s:%d) disconnected", (unsigned long)time(NULL), ctx->getIdentifier(), IPtoa(ctx->getAddress()), sockaddr2port(ctx->getAddress()));
1024     clnt=ctx->getIdentifier();
1025     if(this->destroyClientContext(clnt)!=OP_SUCCESS)
1026         nping_print(DBG_2, "Client #%d disconnected but no context found. This may be a bug.", clnt);
1027     else
1028         nping_print(DBG_2, "Deleted client #%d context.", clnt);
1029   }
1030   nsock_iod_delete(nsi, NSOCK_PENDING_SILENT);
1031 
1032   /* Exit the server if --once has been set */
1033   if(o.once()){
1034     o.displayStatistics();
1035     o.displayNpingDoneMsg();
1036     o.cleanup();
1037     exit(EXIT_SUCCESS);
1038   }
1039   return OP_SUCCESS;
1040 } /* End of nep_session_ended_handler() */
1041 
1042 
1043 
1044 /** Processes and validates a received NEP_HANDSHAKE_CLIENT message. On success
1045   * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
1046   * is not valid. */
parse_hs_client(u8 * pkt,size_t pktlen,NEPContext * ctx)1047 int EchoServer::parse_hs_client(u8 *pkt, size_t pktlen, NEPContext *ctx){
1048   nping_print(DBG_4, "%s()", __func__);
1049   u8 *next_iv=NULL;
1050   EchoHeader h;
1051   if(pkt==NULL || ctx==NULL){
1052     nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
1053     return OP_FAILURE;
1054   }
1055   if(pktlen!=NEP_HANDSHAKE_CLIENT_LEN){
1056     nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
1057     return OP_FAILURE;
1058   }
1059   h.storeRecvData(pkt, pktlen);
1060 
1061   /* Validate version number */
1062   if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
1063     nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
1064     return OP_FAILURE;
1065   }
1066 
1067   /* Ensure the expected message type was received */
1068   if(h.getMessageType()!=TYPE_NEP_HANDSHAKE_CLIENT){
1069     nping_print(DBG_1, "Expected NEP_HANDSHAKE_CLIENT but received %02X", h.getMessageType() );
1070     return OP_FAILURE;
1071   }
1072 
1073   /* Ensure the received timestamp falls into the allowed time window */
1074   //if( h.verifyTimestamp()!=OP_SUCCESS ){
1075   //    nping_print(DBG_1, "NEP_HANDSHAKE_CLIENT timestamp is too old", h.getMessageType() );
1076   //    return OP_FAILURE;
1077   //}
1078 
1079   /* Ensure message length is correct */
1080   if( h.getTotalLength()!=(NEP_HANDSHAKE_CLIENT_LEN/4)){
1081     nping_print(DBG_1, "Received NEP_HANDSHAKE_CLIENT specifies an incorrect length (%u)", h.getTotalLength()*4 );
1082     return OP_FAILURE;
1083   }
1084 
1085   /* Ensure the client echoed the nonce we sent in our NEP_HANDSHAKE_SERVER */
1086   if( memcmp(h.getServerNonce(), ctx->getServerNonce(), NONCE_LEN)!=0 ){
1087     nping_print(DBG_1, "Echoed nonce in NEP_HANDSHAKE_CLIENT message does not match client generate nonce");
1088     return OP_FAILURE;
1089   }
1090   /* Store the received nonce */
1091   ctx->setClientNonce(h.getClientNonce());
1092 
1093   /* Store client's sequence number */
1094   ctx->setLastClientSequence( h.getSequenceNumber() );
1095 
1096   /* Generate all session keys */
1097   ctx->generateCipherKeyC2S();
1098   ctx->generateCipherKeyS2C();
1099   ctx->generateMacKeyC2S();
1100   ctx->generateMacKeyS2C();
1101 
1102   nping_print(DBG_3,"Session Key MAC_C2S:"); print_hexdump(DBG_3,ctx->getMacKeyC2S(), MAC_KEY_LEN);
1103   nping_print(DBG_3,"Session Key MAC_S2C:"); print_hexdump(DBG_3,ctx->getMacKeyS2C(), MAC_KEY_LEN);
1104   nping_print(DBG_3,"Session Key CIPHER_C2S:"); print_hexdump(DBG_3,ctx->getCipherKeyC2S(), MAC_KEY_LEN);
1105   nping_print(DBG_3,"Session Key CIPHER_S2C:"); print_hexdump(DBG_3,ctx->getCipherKeyS2C(), MAC_KEY_LEN);
1106 
1107 
1108   /* Decrypt the encrypted part of the message before validating the MAC */
1109   if((next_iv=h.decrypt(ctx->getCipherKeyC2S(), CIPHER_KEY_LEN, ctx->getClientNonce(), TYPE_NEP_HANDSHAKE_CLIENT))==NULL){
1110       nping_print(DBG_1, "Failed to decrypt NEP_HANDSHAKE_CLIENT data." );
1111       return OP_FAILURE;
1112   }
1113   ctx->setNextDecryptionIV(next_iv);
1114 
1115   /* Check the authenticity of the received message */
1116   if( h.verifyMessageAuthenticationCode( ctx->getMacKeyC2S(), MAC_KEY_LEN)!=OP_SUCCESS ){
1117       nping_print(DBG_1, "NEP_HANDSHAKE_CLIENT authentication failed" );
1118       return OP_FAILURE;
1119   }
1120 
1121   return OP_SUCCESS;
1122 } /* End of parse_hs_client() */
1123 
1124 
1125 /** Processes and validates a received NEP_PACKET_SPEC message. On success
1126   * it returns OP_SUCCESS. OP_FAILURE is returned in case the received packet
1127   * is not valid. */
parse_packet_spec(u8 * pkt,size_t pktlen,NEPContext * ctx)1128 int EchoServer::parse_packet_spec(u8 *pkt, size_t pktlen, NEPContext *ctx){
1129   nping_print(DBG_4, "%s()", __func__);
1130   EchoHeader h;
1131   int recvspecs=0;
1132   bool id_received=false;
1133   u8 field=0;
1134   size_t len=0;
1135   u8 *next_iv=NULL;
1136   u8 specbuff[PACKETSPEC_FIELD_LEN];
1137   if(pkt==NULL){
1138     nping_print(DBG_1,"%s(): NULL parameter supplied.", __func__ );
1139     return OP_FAILURE;
1140   }
1141   if(pktlen!=NEP_PACKETSPEC_LEN){
1142     nping_print(DBG_1,"%s(): Unexpected length supplied.", __func__ );
1143     return OP_FAILURE;
1144   }
1145   h.storeRecvData(pkt, pktlen);
1146 
1147   /* Decrypt message */
1148   if((next_iv=h.decrypt(ctx->getCipherKeyC2S(), CIPHER_KEY_LEN, ctx->getNextDecryptionIV(), TYPE_NEP_PACKET_SPEC))==NULL){
1149       nping_print(DBG_1, "Failed to decrypt NEP_PACKET_SPEC data." );
1150       return OP_FAILURE;
1151   }
1152   ctx->setNextDecryptionIV(next_iv);
1153 
1154   /* Validate version number */
1155   if( h.getVersion() != ECHO_CURRENT_PROTO_VER ){
1156     nping_print(DBG_1, "Expected NEP version %02x but message used %02x", ECHO_CURRENT_PROTO_VER, h.getVersion() );
1157     return OP_FAILURE;
1158   }
1159 
1160   /* Ensure the expected message type was received */
1161   if(h.getMessageType()!=TYPE_NEP_PACKET_SPEC){
1162     nping_print(DBG_1, "Expected NEP_PACKET_SPEC but received %02X", h.getMessageType() );
1163     return OP_FAILURE;
1164   }
1165 
1166   /* Ensure the received timestamp falls into the allowed time window */
1167   //if( h.verifyTimestamp()!=OP_SUCCESS ){
1168   //    nping_print(DBG_1, "NEP_PACKET_SPEC timestamp is too old", h.getMessageType() );
1169   //    return OP_FAILURE;
1170   //}
1171 
1172   /* Ensure message length is correct */
1173   if( h.getTotalLength()!=(NEP_PACKETSPEC_LEN/4)){
1174     nping_print(DBG_1, "Received NEP_PACKET_SPEC specifies an incorrect length (%u)", h.getTotalLength()*4 );
1175     return OP_FAILURE;
1176   }
1177 
1178   /* Ensure the received sequence number is the previous+1 */
1179   if( h.getSequenceNumber()!=(ctx->getLastClientSequence()+1)){
1180     nping_print(DBG_1, "Expected sequence number %d but received %d", ctx->getLastClientSequence()+1, h.getSequenceNumber() );
1181     return OP_FAILURE;
1182   }else{
1183     /* Increment next expected sequence number*/
1184     ctx->getNextClientSequence();
1185   }
1186 
1187   /* Check the authenticity of the received message */
1188   if( h.verifyMessageAuthenticationCode( ctx->getMacKeyC2S(), MAC_KEY_LEN)!=OP_SUCCESS ){
1189       nping_print(DBG_1, "NEP_PACKET_SPEC authentication failed" );
1190       return OP_FAILURE;
1191   }
1192 
1193   /* Now that we have verified the authenticity of the message, let's process
1194    * the field specifiers */
1195   while(1){
1196     if( h.getNextFieldSpec(&field, specbuff, &len)==OP_FAILURE ){
1197           break;
1198     }else{
1199 
1200         /* Ensure the field spec is unique. Malicious users could try to supply
1201          * the same spec more than once in order to get higher packet scores. */
1202         if( ctx->isDuplicateFieldSpec(field) ){
1203           nping_print(DBG_1, "Detected duplicate field specs in NEP_PACKET_SPEC message" );
1204           return OP_FAILURE;
1205         }else{
1206             ctx->addClientFieldSpec(field, len, specbuff);
1207             recvspecs++;
1208         }
1209         /* Set a flag to indicate that mandatory IPv4 ID or IPv6 Flow has been
1210          * supplied by the client */
1211         if(h.getIPVersion()==0x04 && field==PSPEC_IPv4_ID)
1212           id_received=true;
1213         else if(h.getIPVersion()==0x06 && field==PSPEC_IPv6_FLOW)
1214           id_received=true;
1215         nping_print(DBG_3|NO_NEWLINE,"RCVD FieldSpec: Type=%02X Len=%02x Data=0x", field, (u8)len);
1216         for(unsigned int i=0; i<len; i++)
1217             nping_print(DBG_3|NO_NEWLINE,"%02x", specbuff[i]);
1218         nping_print(DBG_3, ";");
1219     }
1220   }
1221   /* Check client provided mandatory IP ID (or Flow) spec and at least one other spec */
1222   if(id_received && recvspecs>=4){
1223     nping_print(VB_2, "[%lu] Good packet specification received from client #%d (Specs=%d,IP=%d,Proto=%d,Cnt=%d)",
1224       (unsigned long)time(NULL), ctx->getIdentifier(), recvspecs, h.getIPVersion(), h.getProtocol(), h.getPacketCount()
1225             );
1226     return OP_SUCCESS;
1227   }else{
1228     return OP_FAILURE;
1229   }
1230 } /* End of parse_packet_spec() */
1231 
1232 
1233 /** Generates a NEP_HANDSHAKE_SERVER message. On success it returns OP_SUCCESS.
1234   * OP_FAILURE is returned in case of error.
1235   * @warning the caller must ensure that the supplied context object
1236   * already contains an initial sequence number and a server nonce. */
generate_hs_server(EchoHeader * h,NEPContext * ctx)1237 int EchoServer::generate_hs_server(EchoHeader *h, NEPContext *ctx){
1238   nping_print(DBG_4, "%s()", __func__);
1239   if(h==NULL || ctx==NULL)
1240     return OP_FAILURE;
1241 
1242   /* Craft NEP_HANDSHAKE_SERVER message */
1243   h->setMessageType(TYPE_NEP_HANDSHAKE_SERVER);
1244   h->setSequenceNumber( ctx->getLastServerSequence() );
1245   h->setTimestamp();
1246   h->setServerNonce( ctx->getServerNonce() );
1247   h->setTotalLength();
1248   h->setMessageAuthenticationCode( ctx->getMacKeyS2C(), MAC_KEY_LEN);
1249   return OP_SUCCESS;
1250 } /* End of generate_hs_server() */
1251 
1252 
1253 /** Generates a NEP_HANDSHAKE_FINAL message. On success it returns OP_SUCCESS.
1254   * OP_FAILURE is returned in case of error. */
generate_hs_final(EchoHeader * h,NEPContext * ctx)1255 int EchoServer::generate_hs_final(EchoHeader *h, NEPContext *ctx){
1256   nping_print(DBG_4, "%s()", __func__);
1257   struct sockaddr_storage ss;
1258   u8 *next_iv=NULL;
1259   if(h==NULL || ctx==NULL)
1260     return OP_FAILURE;
1261 
1262   /* Craft NEP_HANDSHAKE_CLIENT message */
1263   h->setMessageType(TYPE_NEP_HANDSHAKE_FINAL);
1264   h->setSequenceNumber(ctx->getNextServerSequence() );
1265   h->setTimestamp();
1266   h->setClientNonce( ctx->getClientNonce() );
1267   ss=ctx->getAddress();
1268   if(ss.ss_family==AF_INET6){
1269       struct sockaddr_in6 *s6=(struct sockaddr_in6 *)&ss;
1270       h->setPartnerAddress(s6->sin6_addr);
1271   }else{
1272       struct sockaddr_in *s4=(struct sockaddr_in *)&ss;
1273       h->setPartnerAddress(s4->sin_addr);
1274   }
1275   h->setTotalLength();
1276   h->setMessageAuthenticationCode( ctx->getMacKeyS2C(), MAC_KEY_LEN);
1277 
1278   /* Encrypt message */
1279   if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getServerNonce()))==NULL )
1280       return OP_FAILURE;
1281   ctx->setNextEncryptionIV(next_iv);
1282 
1283 
1284   return OP_SUCCESS;
1285 } /* End of generate_hs_final() */
1286 
1287 
1288 /** Generates a NEP_READY message. On success it returns OP_SUCCESS.
1289   * OP_FAILURE is returned in case of error. */
generate_ready(EchoHeader * h,NEPContext * ctx)1290 int EchoServer::generate_ready(EchoHeader *h, NEPContext *ctx){
1291   nping_print(DBG_4, "%s()", __func__);
1292   u8 *next_iv=NULL;
1293   if(h==NULL || ctx==NULL)
1294     return OP_FAILURE;
1295 
1296   /* Craft NEP_READY message */
1297   h->setMessageType(TYPE_NEP_READY);
1298   h->setSequenceNumber( ctx->getNextServerSequence() );
1299   h->setTimestamp();
1300   h->setTotalLength();
1301   h->setMessageAuthenticationCode(ctx->getMacKeyS2C(), MAC_KEY_LEN);
1302 
1303   /* Encrypt message */
1304   if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getNextEncryptionIV()))==NULL )
1305       return OP_FAILURE;
1306   ctx->setNextEncryptionIV(next_iv);
1307 
1308   return OP_SUCCESS;
1309 } /* End of generate_ready() */
1310 
1311 
1312 /** Generates a NEP_ECHO message. On success it returns OP_SUCCESS.
1313   * OP_FAILURE is returned in case of error. */
generate_echo(EchoHeader * h,const u8 * pkt,size_t pktlen,NEPContext * ctx)1314 int EchoServer::generate_echo(EchoHeader *h, const u8 *pkt, size_t pktlen, NEPContext *ctx){
1315   nping_print(DBG_4, "%s()", __func__);
1316   u8 *next_iv=NULL;
1317   if(h==NULL || ctx==NULL || pkt==NULL || pktlen==0)
1318     return OP_FAILURE;
1319 
1320   /* Craft NEP_ECHO message */
1321   h->setMessageType(TYPE_NEP_ECHO);
1322   h->setSequenceNumber( ctx->getNextServerSequence() );
1323   h->setTimestamp();
1324   h->setDLT(DLT_NODATALINKHEADERINCLUDED);
1325 
1326   /* If allowed, echo the whole packet, including any application layer data */
1327   if( o.echoPayload() ){
1328       h->setEchoedPacket(pkt, pktlen);
1329   /* Otherwise, find if the packet contains application layer data and erase it */
1330   }else{
1331     /* Determine where the application data starts */
1332     int offset=PacketParser::payload_offset(pkt, pktlen, false);
1333 
1334     /* If the packet does not have application data, don't touch it */
1335     if(offset==0){
1336         nping_print(DBG_3, "No payload found. Echoing the whole packet\n");
1337         h->setEchoedPacket(pkt, pktlen);
1338     /* If we found application data, zero it */
1339     }else{
1340         nping_print(DBG_3, "Erasing %d payload bytes\n", (int)pktlen-offset);
1341         /* Allocate a new buffer, big enough to hold the packet */
1342         u8 *new_pkt=(u8 *)safe_zalloc(pktlen);
1343         /* Copy the initial header, and leave the rest as 0x00 bytes */
1344         if(offset>0 && offset<(int)pktlen){
1345             memcpy(new_pkt, pkt, offset);
1346         /* If there was some error trying to find application data, include a
1347          * default amount of data */
1348         }else{
1349             memcpy(new_pkt, pkt, MIN(pktlen, PAYLOAD_ECHO_BYTES_IN_DOUBT));
1350         }
1351         h->setEchoedPacket(new_pkt, pktlen);
1352         free(new_pkt);
1353     }
1354   }
1355 
1356   h->setTotalLength();
1357   h->setMessageAuthenticationCode(ctx->getMacKeyS2C(), MAC_KEY_LEN);
1358 
1359   if( (next_iv=h->encrypt(ctx->getCipherKeyS2C(), CIPHER_KEY_LEN, ctx->getNextEncryptionIV()))==NULL )
1360       return OP_FAILURE;
1361   ctx->setNextEncryptionIV(next_iv);
1362 
1363   return OP_SUCCESS;
1364 } /* End of generate_echo() */
1365 
1366 
1367 /** This is the server's main method. It sets up nsock and pcap, waits for
1368   * client connections and handles all the events of the client sessions. */
start()1369 int EchoServer::start() {
1370   nping_print(DBG_4, "%s()", __func__);
1371   nsock_pool nsp;                  /**< Nsock pool                           */
1372   enum nsock_loopstatus loopret;   /**< Stores nsock_loop returned status    */
1373   nsock_iod client_nsi;            /**< Stores connected client IOD          */
1374   nsock_iod pcap_nsi;              /**< Stores Pcap IOD                      */
1375   char pcapdev[128];               /**< Device name passed to pcap_open_live */
1376   struct timeval now;              /**< For timestamps                       */
1377   struct sockaddr_storage ss;      /**< New client socket address            */
1378   socklen_t sslen=sizeof(ss);      /**< New client socket address len        */
1379   int listen_sd=-1;                /**< Socket descriptor for listening      */
1380   int client_sd=-1;                /**< Socket descriptor for new clients    */
1381   clientid_t *idpnt=NULL;          /**< For new client assigned identifiers  */
1382   NEPContext ctx;                  /**< Context for the new client           */
1383   EchoHeader h;
1384   int rc;
1385 
1386   /* Create a new nsock pool */
1387   if ((nsp = nsock_pool_new(NULL)) == NULL)
1388     nping_fatal(QT_3, "Failed to create new pool.  QUITTING.\n");
1389 
1390   /* Set nsock trace level */
1391   gettimeofday(&now, NULL);
1392   if( o.getDebugging() == DBG_5 )
1393     nsock_set_loglevel(NSOCK_LOG_INFO);
1394   else if( o.getDebugging() > DBG_5 )
1395     nsock_set_loglevel(NSOCK_LOG_DBG_ALL);
1396 
1397   /* Create new IOD for pcap */
1398   if ((pcap_nsi = nsock_iod_new(nsp, NULL)) == NULL)
1399     nping_fatal(QT_3, "Failed to create new nsock_iod.  QUITTING.\n");
1400 
1401   /* Open pcap */
1402   nping_print(DBG_2,"Opening pcap device %s", o.getDevice());
1403   Strncpy(pcapdev, o.getDevice(), sizeof(pcapdev));
1404   rc = nsock_pcap_open(nsp, pcap_nsi, pcapdev, MAX_ECHOED_PACKET_LEN, 1,
1405                        ProbeMode::getBPFFilterString());
1406   if (rc)
1407     nping_fatal(QT_3, "Error opening capture device %s\n", o.getDevice());
1408   else
1409     nping_print(VB_0,"Packet capture will be performed using network interface %s.", o.getDevice());
1410   nping_print(VB_0,"Waiting for connections...");
1411 
1412   /* Get a socket suitable for an accept() call */
1413   listen_sd=this->nep_listen_socket();
1414 
1415   while(1){
1416     /* If --once is enabled, just allow the first client */
1417     if(o.once()==false || this->client_id_count==-1){
1418         /* Check if we have received a connection*/
1419         unblock_socket(listen_sd);
1420         if ((client_sd=accept(listen_sd, (struct sockaddr *)&ss, &sslen)) >= 0){
1421             nping_print(VB_0, "[%lu] Connection received from %s:%d", (unsigned long)time(NULL), IPtoa(&ss), sockaddr2port(&ss));
1422             /* Assign a new client identifier. The ID is bound to the IOD */
1423             if( (idpnt=(clientid_t *)calloc(1, sizeof(clientid_t)))==NULL ){
1424                 nping_warning(QT_2, "Not enough memory for new clients.");
1425                 return OP_FAILURE;
1426             }
1427             *idpnt=this->getNewClientID();
1428             if( (client_nsi=nsock_iod_new2(nsp, client_sd, idpnt))==NULL ){
1429                 nping_warning(QT_2, "Not enough memory for new clients.");
1430                 return OP_FAILURE;
1431             }else{
1432                 close(client_sd); /* nsock_iod_new2() dups the socket */
1433             }
1434 
1435             /* Stop listening if --once is enabled */
1436             if(o.once()==true)
1437                 close(listen_sd);
1438 
1439             /* Create a new client context object */
1440             ctx.setIdentifier(*idpnt);
1441             ctx.setAddress(ss);
1442             ctx.setNsockIOD(client_nsi);
1443             ctx.generateServerNonce();
1444             ctx.generateInitialServerSequence();
1445             ctx.generateMacKeyS2CInitial();
1446             nping_print(DBG_3,"Session Key MAC_S2C_INITIAL:"); print_hexdump(DBG_3,ctx.getMacKeyS2C(), MAC_KEY_LEN);
1447 
1448             /* Craft NEP_HANDSHAKE_SERVER message */
1449             if( this->generate_hs_server(&h, &ctx)!=OP_SUCCESS)
1450                 return OP_FAILURE;
1451             else
1452                 this->addClientContext(ctx);
1453 
1454             /* Schedule send operation */
1455             nsock_write(nsp, client_nsi, hs_server_handler, NSOCK_INFINITE, NULL, (const char *)h.getBufferPointer(), h.getLen() );
1456 
1457             /* For every client we schedule a packet capture event. */
1458             nsock_pcap_read_packet(nsp, pcap_nsi, capture_handler, NSOCK_INFINITE, NULL);
1459 
1460         }
1461         block_socket(listen_sd);
1462     }
1463     /* Sleep for a second until we check again for incoming connection requests */
1464     nsock_timer_create(nsp, empty_handler, 1000, NULL);
1465     loopret=nsock_loop(nsp, 1000);
1466     //If something went wrong in nsock_loop, let's just bail out.
1467     if (loopret == NSOCK_LOOP_ERROR) {
1468         nping_warning(QT_3, "Unexpected nsock_loop error.\n");
1469         return OP_FAILURE;
1470     }
1471   }
1472   return OP_SUCCESS;
1473 } /* End of start() */
1474 
1475 
1476 /** Performs cleanup functions */
cleanup()1477 int EchoServer::cleanup(){
1478   // For the moment there is nothing to cleanup
1479   return OP_SUCCESS;
1480 } /* End of cleanup() */
1481 
1482 /******************************************************************************/
1483 /**** HANDLER WRAPPERS ********************************************************/
1484 /******************************************************************************/
1485 
1486 /* This handler is a wrapper for the EchoServer::nep_read_handler() method. We
1487  * need this because C++ does not allow to use class methods as callback
1488  * functions for things like signal() or the Nsock lib. */
capture_handler(nsock_pool nsp,nsock_event nse,void * arg)1489 void capture_handler(nsock_pool nsp, nsock_event nse, void *arg){
1490   nping_print(DBG_4, "%s()", __func__);
1491   es.nep_capture_handler(nsp, nse, arg);
1492   return;
1493 } /* End of capture_handler() */
1494 
1495 
1496 /* This handler is a wrapper for the EchoServer::nep_echo_handler() method. We
1497  * need this because C++ does not allow to use class methods as callback
1498  * functions for things like signal() or the Nsock lib. */
echo_handler(nsock_pool nsp,nsock_event nse,void * arg)1499 void echo_handler(nsock_pool nsp, nsock_event nse, void *arg){
1500   nping_print(DBG_4, "%s()", __func__);
1501   es.nep_echo_handler(nsp, nse, arg);
1502   return;
1503 } /* End of echo_handler() */
1504 
1505 
1506 /* This handler is a wrapper for the EchoServer::nep_hs_server_handler() method. We
1507  * need this because C++ does not allow to use class methods as callback
1508  * functions for things like signal() or the Nsock lib. */
hs_server_handler(nsock_pool nsp,nsock_event nse,void * arg)1509 void hs_server_handler(nsock_pool nsp, nsock_event nse, void *arg){
1510   nping_print(DBG_4, "%s()", __func__);
1511   es.nep_hs_server_handler(nsp, nse, arg);
1512   return;
1513 } /* End of hs_server_handler() */
1514 
1515 
1516 /* This handler is a wrapper for the EchoServer::nep_hs_client_handler() method. We
1517  * need this because C++ does not allow to use class methods as callback
1518  * functions for things like signal() or the Nsock lib. */
hs_client_handler(nsock_pool nsp,nsock_event nse,void * arg)1519 void hs_client_handler(nsock_pool nsp, nsock_event nse, void *arg){
1520   nping_print(DBG_4, "%s()", __func__);
1521   es.nep_hs_client_handler(nsp, nse, arg);
1522   return;
1523 } /* End of hs_client_handler() */
1524 
1525 
1526 /* This handler is a wrapper for the EchoServer::nep_hs_final_handler() method. We
1527  * need this because C++ does not allow to use class methods as callback
1528  * functions for things like signal() or the Nsock lib. */
hs_final_handler(nsock_pool nsp,nsock_event nse,void * arg)1529 void hs_final_handler(nsock_pool nsp, nsock_event nse, void *arg){
1530   nping_print(DBG_4, "%s()", __func__);
1531   es.nep_hs_final_handler(nsp, nse, arg);
1532   return;
1533 } /* End of hs_final_handler() */
1534 
1535 
1536 /* This handler is a wrapper for the EchoServer::nep_packetspec_handler() method. We
1537  * need this because C++ does not allow to use class methods as callback
1538  * functions for things like signal() or the Nsock lib. */
packetspec_handler(nsock_pool nsp,nsock_event nse,void * arg)1539 void packetspec_handler(nsock_pool nsp, nsock_event nse, void *arg){
1540   nping_print(DBG_4, "%s()", __func__);
1541   es.nep_packetspec_handler(nsp, nse, arg);
1542   return;
1543 } /* End of packetspec_handler() */
1544 
1545 
1546 /* This handler is a wrapper for the EchoServer::nep_ready_handler() method. We
1547  * need this because C++ does not allow to use class methods as callback
1548  * functions for things like signal() or the Nsock lib. */
ready_handler(nsock_pool nsp,nsock_event nse,void * arg)1549 void ready_handler(nsock_pool nsp, nsock_event nse, void *arg){
1550   nping_print(DBG_4, "%s()", __func__);
1551   es.nep_ready_handler(nsp, nse, arg);
1552   return;
1553 } /* End of ready_handler() */
1554 
1555 
1556 /* This handler is a wrapper for the EchoServer::nep_ready_handler() method. We
1557  * need this because C++ does not allow to use class methods as callback
1558  * functions for things like signal() or the Nsock lib. */
session_ended_handler(nsock_pool nsp,nsock_event nse,void * arg)1559 void session_ended_handler(nsock_pool nsp, nsock_event nse, void *arg){
1560   nping_print(DBG_4, "%s()", __func__);
1561   es.nep_session_ended_handler(nsp, nse, arg);
1562   return;
1563 } /* End of ready_handler() */
1564 
1565 
1566 /* Void handler that does nothing */
empty_handler(nsock_pool nsp,nsock_event nse,void * arg)1567 void empty_handler(nsock_pool nsp, nsock_event nse, void *arg){
1568   return;
1569 } /* End of capture_handler() */
1570