1 /******************************************************************************
2     (c) 2000-2009 Christine Caulfield                 christine.caulfield@googlemail.com
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 ******************************************************************************/
14 
15 #include <stdio.h>
16 #include <sys/time.h>
17 #include <netinet/in.h>
18 #include <string.h>
19 #include <list>
20 #include <map>
21 #include <queue>
22 #include <string>
23 #include <sstream>
24 #include <iterator>
25 
26 
27 #include "lat.h"
28 #include "utils.h"
29 #include "session.h"
30 #include "serversession.h"
31 #include "reversesession.h"
32 #include "clientsession.h"
33 #include "lloginsession.h"
34 #include "localportsession.h"
35 #include "queuedsession.h"
36 #include "localport.h"
37 #include "connection.h"
38 #include "circuit.h"
39 #include "latcpcircuit.h"
40 #include "server.h"
41 #include "services.h"
42 #include "lat_messages.h"
43 #include "dn_endian.h"
44 
45 
46 // Create a server connection
LATConnection(int _num,unsigned char * buf,int len,int _interface,unsigned char _seq,unsigned char _ack,unsigned char * _macaddr)47 LATConnection::LATConnection(int _num, unsigned char *buf, int len,
48 			     int _interface,
49 			     unsigned char _seq,
50 			     unsigned char _ack,
51 			     unsigned char *_macaddr):
52     num(_num),
53     interface(_interface),
54     keepalive_timer(0),
55     last_sent_seq(0xff),
56     last_sent_ack(0),
57     last_recv_seq(_seq),
58     last_recv_ack(_ack),
59     last_time(0L),
60     need_ack(false),
61     queued(false),
62     eightbitclean(false),
63     connected(false),
64     delete_pending(false),
65     request_id(0),
66     last_msg_type(0),
67     last_msg_retries(0),
68     role(SERVER),
69     send_ack(false)
70 {
71     memcpy(macaddr, (char *)_macaddr, 6);
72     int  ptr = sizeof(LAT_Start);
73     LAT_Start *msg = (LAT_Start *)buf;
74 
75     debuglog(("New connection: (s: %x, a: %x)\n",
76              last_recv_seq, last_recv_ack));
77 
78     get_string(buf, &ptr, servicename); // This is actually local nodename
79     get_string(buf, &ptr, remnode);
80 
81     debuglog(("Connect from %s (LAT %d.%d) for %s, window size: %d\n",
82 	     remnode, msg->latver, msg->latver_eco, servicename, msg->exqueued));
83 
84     remote_connid = msg->header.local_connid;
85     next_session = 1;
86     highest_session = 1;
87     max_window_size = msg->exqueued+1;
88     max_window_size = 1; // All we can manage
89     window_size = 0;
90     lat_eco = msg->latver_eco;
91     max_slots_per_packet = 4;
92 
93     memset(sessions, 0, sizeof(sessions));
94 }
95 
96 // Create a client connection
LATConnection(int _num,const char * _service,const char * _portname,const char * _lta,const char * _remnode,bool queued,bool clean)97 LATConnection::LATConnection(int _num, const char *_service,
98 			     const char *_portname, const char *_lta,
99 			     const char *_remnode, bool queued, bool clean):
100     num(_num),
101     keepalive_timer(0),
102     last_sent_seq(0xff),
103     last_sent_ack(0),
104     last_recv_seq(0),
105     last_recv_ack(0xff),
106     last_time(0L),
107     need_ack(false),
108     queued(queued),
109     eightbitclean(clean),
110     connected(false),
111     connecting(false),
112     delete_pending(false),
113     request_id(0),
114     last_msg_type(0),
115     last_msg_retries(0),
116     role(CLIENT),
117     send_ack(false)
118 {
119     debuglog(("New client connection for %s created\n", _remnode));
120     memset(sessions, 0, sizeof(sessions));
121     strcpy((char *)servicename, _service);
122     strcpy((char *)portname, _portname);
123     strcpy((char *)remnode, _remnode);
124     strcpy(lta_name, _lta);
125 
126     max_slots_per_packet = 4;
127     max_window_size = 1;      // Gets overridden later on.
128     window_size = 0;
129     next_session = 1;
130     highest_session = 1;
131 }
132 
133 
process_session_cmd(unsigned char * buf,int len,unsigned char * macaddr)134 bool LATConnection::process_session_cmd(unsigned char *buf, int len,
135 					unsigned char *macaddr)
136 {
137     int  msglen;
138     unsigned int command;
139     int  i;
140     int  newsessionnum;
141     int  ptr = sizeof(LAT_Header);
142     LATSession *newsession;
143     LAT_SessionCmd *msg = (LAT_SessionCmd *)buf;
144     int num_replies = 0;
145     LAT_SlotCmd *reply[MAX_REPLIES];
146     char replybuf[MAX_REPLIES][256];
147     bool replyhere = false;
148 
149     debuglog(("process_session_cmd: %d slots, %d bytes\n",
150              msg->header.num_slots, len));
151 
152     /* Clear out the reply slots and initialise pointers */
153     memset(replybuf, 0, sizeof(replybuf));
154     for (unsigned int ri=0; ri<MAX_REPLIES; ri++)
155 	reply[ri] = (LAT_SlotCmd *)replybuf[ri];
156 
157 #ifdef REALLY_VERBOSE_DEBUGLOG
158     debuglog(("MSG:      seq: %d,        ack: %d (last sent seq = %d)\n",
159 	      msg->header.sequence_number, msg->header.ack_number, last_sent_seq));
160 
161     debuglog(("PREV:last seq: %d,   last ack: %d\n",
162 	      last_recv_seq, last_recv_ack));
163 #endif
164 
165     // Is this a duplicate?
166     // Check the previous ack number too as we could be one packet out
167     if (msg->header.sequence_number == last_recv_seq ||
168 	msg->header.sequence_number == last_recv_seq-1)
169     {
170 	if (msg->header.ack_number == last_recv_ack)
171 	{
172 	    debuglog(("Duplicate packet received...resending ACK\n"));
173 
174 	    // But still send an ACK as it could be the ACK that went missing
175 	    last_ack_message.send(interface, last_recv_seq, macaddr);
176 
177 	    // If the last DATA message wasn't seen either then resend that too
178 	    if (last_message.get_seq() > msg->header.ack_number ||
179 		(last_message.get_seq() == 0 && msg->header.ack_number == 0xff))
180 
181 	    {
182 		debuglog(("Also sending last DATA message (%d)\n", last_message.get_seq()));
183 		last_message.send(interface,  last_recv_seq, macaddr);
184 	    }
185 	}
186 	return false;
187     }
188 
189     // If we got an old message then process that.
190     if (msg->header.ack_number != last_sent_seq)
191     {
192 	debuglog(("Got ack for old message, resending ACK\n"));
193 	last_ack_message.send(interface,  last_recv_seq, macaddr);
194 
195 	// If the last DATA message wasn't seen either then resend that too
196 	if (last_message.get_seq() > msg->header.ack_number ||
197 	    (last_message.get_seq() == 0 && msg->header.ack_number == 0xff))
198 	{
199 	    debuglog(("Also sending last DATA message (%d)\n", last_message.get_seq()));
200 	    last_message.send(interface,  last_recv_seq, macaddr);
201 	}
202     }
203 
204     window_size--;
205     if (window_size < 0) window_size = 0;
206 
207     need_ack = false;
208     last_recv_ack = msg->header.ack_number;
209     last_recv_seq = msg->header.sequence_number;
210 
211     // No blocks? just ACK it (if we're a server)
212     if (msg->header.num_slots == 0)
213     {
214 	if (role == SERVER)
215 	{
216 	    reply[0]->remote_session = msg->slot.local_session;
217 	    reply[0]->local_session = msg->slot.remote_session;
218 	    reply[0]->length = 0;
219 	    reply[0]->cmd = 0;
220 	    replyhere = true;
221 	}
222 
223 	LAT_SlotCmd *slotcmd = (LAT_SlotCmd *)(buf+ptr);
224 	unsigned char credits = slotcmd->cmd & 0x0F;
225 
226 	debuglog(("No data: cmd: %d, credit: %d\n", msg->header.cmd, credits));
227 
228 	LATSession *session = sessions[slotcmd->local_session];
229 	if (credits)
230 	{
231 	    if (session) session->add_credit(credits);
232 	}
233 	if (replyhere && session && session->get_remote_credit() <= 2)
234 	{
235 	    reply[0]->cmd |= 15; // Add credit
236 	    session->inc_remote_credit(15);
237 	}
238     }
239     else
240     {
241 	replyhere = true;
242         for (i=0; i<msg->header.num_slots && ptr<len; i++)
243 	{
244 	    LAT_SlotCmd *slotcmd = (LAT_SlotCmd *)(buf+ptr);
245 	    msglen  = slotcmd->length;
246 	    command = slotcmd->cmd & 0xF0;
247 	    unsigned char credits = slotcmd->cmd & 0x0F;
248 
249 	    debuglog(("process_slot_cmd(%d:%x). command: %x, credit: %d, len: %d\n",
250 		     i, ptr, command, credits, msglen));
251 
252 	    ptr += sizeof(LAT_SlotCmd);
253 
254 	    // Process the data.
255 	    LATSession *session = sessions[slotcmd->local_session];
256 	    if (session && credits) session->add_credit(credits);
257 
258 	    switch (command)
259 	    {
260 	    case 0x00:
261             {
262                 if (session)
263                 {
264                     if (session->send_data_to_process(buf+ptr, msglen))
265                     {
266                         // No echo.
267                         if (role == SERVER)
268 			{
269 			    replyhere = true;
270 			}
271                     }
272                     // We are expecting an echo - don't send anything now
273 		    // but still increment the remote credit if the other end
274 		    // has run out.
275 		    debuglog(("Remote credit is %d\n", session->get_remote_credit()));
276 		    if (session->get_remote_credit() <= 2)
277 		    {
278 			reply[num_replies]->remote_session = slotcmd->local_session;
279 			reply[num_replies]->local_session = slotcmd->remote_session;
280 			reply[num_replies]->length = 0;
281 			reply[num_replies]->cmd = 15; // Just credit
282 			num_replies++;
283 			session->inc_remote_credit(15);
284 		    }
285                 }
286                 else
287                 {
288                     // An error - send a disconnect.
289 		    reply[num_replies]->remote_session = slotcmd->local_session;
290 		    reply[num_replies]->local_session = slotcmd->remote_session;
291 		    reply[num_replies]->length = 0;
292 		    reply[num_replies]->cmd = 0xD3; // Invalid slot recvd
293 		    num_replies++;
294                 }
295             }
296             break;
297 
298 	    case 0x90:
299 		if (role == SERVER)
300 		{
301 		    int queued_connection;
302 		    if (is_queued_reconnect(buf, len, &queued_connection))
303 		    {
304 			LATConnection **master_conn = LATServer::Instance()->get_connection(queued_connection);
305 			if (!(*master_conn))
306 			{
307 			    debuglog(("Got queued reconnect for non-existant request ID\n"));
308 
309 			    // Not us mate...
310 			    reply[num_replies]->remote_session = slotcmd->local_session;
311 			    reply[num_replies]->local_session = slotcmd->remote_session;
312 			    reply[num_replies]->length = 0;
313 			    reply[num_replies]->cmd = 0xD7; // No such service
314 			    num_replies++;
315 			}
316 			else
317 			{
318 			    last_msg_type = 0;
319 			    (*master_conn)->last_msg_type = 0;
320 
321 			    last_msg_retries= 0;
322 			    (*master_conn)->last_msg_retries = 0;
323 
324 			    // Connect a new port session to it
325 			    ClientSession *cs = (ClientSession *)(*master_conn)->sessions[1];
326 
327 			    newsessionnum = next_session_number();
328 			    newsession = new QueuedSession(*this,
329 							   (LAT_SessionStartCmd *)buf,
330 							   cs,
331 							   slotcmd->remote_session,
332 							   newsessionnum,
333 							   (*master_conn)->eightbitclean);
334 			    if (newsession->new_session(remnode, (char*)"", (char*)"",
335 							credits) == -1)
336 			    {
337 				newsession->send_disabled_message();
338 				delete newsession;
339 			    }
340 			    else
341 			    {
342 				sessions[newsessionnum] = newsession;
343 				newsession->set_master_conn(master_conn);
344 
345 				// If we were pending a delete, we aren't now
346 				delete_pending = false;
347 			    }
348 			}
349 		    }
350 		    else
351 		    {
352 			//  Check service name is one we recognise.
353 			ptr = sizeof(LAT_SessionStartCmd);
354 			unsigned char name[256];
355 			get_string(buf, &ptr, name);
356 
357                         // Do parameters -- look for a 5 (remote port name)
358 			while (ptr < len)
359 			{
360 			    int param_type = buf[ptr++];
361 			    if (param_type == 5)
362 			    {
363 				get_string(buf, &ptr, portname);
364 			    }
365 			    else
366 			    {
367 				ptr += buf[ptr]+1; // Skip over it
368 			    }
369 			}
370 
371 			if (!LATServer::Instance()->is_local_service((char *)name))
372 			{
373 			    reply[num_replies]->remote_session = slotcmd->local_session;
374 			    reply[num_replies]->local_session = slotcmd->remote_session;
375 			    reply[num_replies]->length = 0;
376 			    reply[num_replies]->cmd = 0xD7; // No such service
377 			    num_replies++;
378 			}
379 			else
380 			{
381 			    std::string cmd;
382 			    int maxcon;
383 			    uid_t uid;
384 			    gid_t gid;
385 			    int curcon;
386 			    LATServer::Instance()->get_service_info((char *)name, cmd, maxcon, curcon, uid, gid);
387 			    strcpy((char *)servicename, (char *)name);
388 
389 			    newsessionnum = next_session_number();
390 			    newsession = new ServerSession(*this,
391 							   (LAT_SessionStartCmd *)buf,
392 							   cmd, uid, gid,
393 							   slotcmd->remote_session,
394 							   newsessionnum, false);
395 			    if (newsession->new_session(remnode, (char*)"", (char *)portname,
396 							credits) == -1)
397 			    {
398 				newsession->send_disabled_message();
399 				delete newsession;
400 			    }
401 			    else
402 			    {
403 				sessions[newsessionnum] = newsession;
404 				// If we were pending a delete, we aren't now
405 				delete_pending = false;
406 			    }
407 			}
408 		    }
409 		}
410 		else // CLIENT
411 		{
412 		    if (session)
413 			((LATSession *)session)->got_connection(slotcmd->remote_session);
414 		}
415 		break;
416 
417 	    case 0xa0:
418 		// Data_b message - port information
419 		if (session)
420 		    session->set_port((unsigned char *)slotcmd);
421 		break;
422 
423 	    case 0xb0:
424                 // Attention. Force XON, Abort etc.
425 	        break;
426 
427 
428 	    case 0xc0:  // Reject - we will get disconnected
429 		debuglog(("Reject code %d: %s\n", credits,
430 			  lat_messages::session_disconnect_msg(credits)));
431 		// Deliberate fall-through.
432 
433 	    case 0xd0:  // Disconnect
434 		if (session) session->disconnect_session(credits);
435 
436 		// If we have no sessions left then disconnect
437 		if (num_clients() == 0)
438 		{
439 		    reply[num_replies]->remote_session = slotcmd->local_session;
440 		    reply[num_replies]->local_session = slotcmd->remote_session;
441 		    reply[num_replies]->length = 0;
442 		    reply[num_replies]->cmd = 0xD1;/* No more slots on circuit */
443 		    num_replies++;
444 		}
445 		break;
446 
447 	    default:
448 		debuglog(("Unknown slot command %x found. length: %d\n",
449                          command, msglen));
450 		replyhere=true;
451 		break;
452 	    }
453 	    ptr += msglen;
454 	    if (ptr%2) ptr++; // Word-aligned
455         }
456     }
457 
458     // If "Response Requested" set, then make sure we send one.
459     if (msg->header.cmd & 1 && !replyhere)
460     {
461 	debuglog(("Sending response because we were told to (%x)\n", msg->header.cmd));
462 	replyhere = true;
463     }
464 
465     // If the reply is just an ack then just set a flag
466     // Then in circuit_timer, we send an ACK only if there is no DATA to send.
467     if (replyhere && num_replies == 0)
468 	send_ack = true;
469 
470     // Send any replies
471     if (replyhere && num_replies)
472     {
473 	debuglog(("Sending %d slots in reply\n", num_replies));
474 	unsigned char replybuf[1600];
475 
476 	memset(replybuf, 0, sizeof(replybuf));
477 	LAT_Header *header  = (LAT_Header *)replybuf;
478 	ptr = sizeof(LAT_Header);
479 
480 	header->cmd       = LAT_CCMD_SREPLY;
481 	header->num_slots = num_replies;
482 	if (role == CLIENT) header->cmd |= 2; // To Host
483 
484 	for (int i=0; i < num_replies; i++)
485 	{
486 	    memcpy(replybuf + ptr, reply[i], sizeof(LAT_SlotCmd));
487 	    ptr += sizeof(LAT_SlotCmd); // Already word-aligned
488 	}
489 
490 	header->local_connid    = num;
491 	header->remote_connid   = remote_connid;
492 
493 	pending_data.push(pending_msg(replybuf, ptr, false));
494 
495 	return true;
496     }
497 
498     return false;
499 }
500 
501 
send_connect_ack()502 void LATConnection::send_connect_ack()
503 {
504     unsigned char reply[1600];
505     int ptr;
506     LAT_StartResponse *response = (LAT_StartResponse *)reply;
507     LATServer *server = LATServer::Instance();
508 
509     // Send response...
510     response->header.cmd       = LAT_CCMD_CONACK;
511     response->header.num_slots = 0;
512     response->maxsize          = dn_htons(1500);
513     response->latver           = LAT_VERSION;
514     response->latver_eco       = LAT_VERSION_ECO;
515     response->maxsessions      = 254;
516     response->exqueued         = 0;
517     response->circtimer        = LATServer::Instance()->get_circuit_timer();
518     response->keepalive        = LATServer::Instance()->get_keepalive_timer();
519     response->facility         = dn_htons(0);
520     response->prodtype         = 3;   // Wot do we use here???
521     response->prodver          = 3;   // and here ???
522 
523     ptr = sizeof(LAT_StartResponse);
524     add_string(reply, &ptr, server->get_local_node());
525     add_string(reply, &ptr, remnode);
526     add_string(reply, &ptr, (unsigned char*)LATServer::greeting);
527     reply[ptr++] = '\0';
528 
529     queue_message(reply, ptr);
530 }
531 
532 // Send a message on this connection NOW
send_message(unsigned char * buf,int len,send_type type)533 int LATConnection::send_message(unsigned char *buf, int len, send_type type)
534 {
535     LAT_Header *response = (LAT_Header *)buf;
536 
537     response->local_connid    = num;
538     response->remote_connid   = remote_connid;
539     response->sequence_number = ++last_sent_seq;
540     response->ack_number      = last_recv_seq;
541 
542     retransmit_count = 0;
543     last_sent_ack = last_recv_seq;
544 
545     debuglog(("Sending message for connid %d (seq: %d, ack: %d) window=%d\n",
546 	      num, last_sent_seq, last_sent_ack, window_size ));
547 
548     keepalive_timer = 0;
549 
550     if (type == DATA)
551     {
552 	need_ack = true;
553 	last_message = pending_msg(buf, len, true);
554 	window_size++;
555     }
556     else
557     {
558 	need_ack = false;
559 	last_ack_message = pending_msg(buf, len, false);
560     }
561 
562     return LATServer::Instance()->send_message(buf, len, interface, macaddr);
563 }
564 
565 // Queue up a reply message
queue_message(unsigned char * buf,int len)566 int LATConnection::queue_message(unsigned char *buf, int len)
567 {
568     LAT_Header *response = (LAT_Header *)buf;
569 
570     response->local_connid    = num;
571     response->remote_connid   = remote_connid;
572     // SEQ and ACK filled in when we send it
573 
574     debuglog(("Queued data messsge for connid %d\n", num));
575 
576     pending_data.push(pending_msg(buf, len, true));
577     return 0;
578 }
579 
580 
581 // Enque a slot message on this connection
send_slot_message(unsigned char * buf,int len)582 void LATConnection::send_slot_message(unsigned char *buf, int len)
583 {
584     slots_pending.push(slot_cmd(buf,len));
585 }
586 
~LATConnection()587 LATConnection::~LATConnection()
588 {
589     debuglog(("LATConnection dtor: %d\n", num));
590 
591     // Delete server sessions
592     for (unsigned int i=1; i<=highest_session; i++)
593     {
594 	if (sessions[i])
595 	{
596 	    LATConnection *master = sessions[i]->get_master_conn();
597 	    if (master)
598 	    {
599 		ClientSession *cs = (ClientSession *)master->sessions[1];
600 		if (cs) cs->restart_pty();
601 	    }
602 	    delete sessions[i];
603 	    sessions[i] = NULL;
604 	}
605     }
606 // Send a "shutting down" message to the other end
607 
608 }
609 
610 // Generate the next session ID
next_session_number()611 int LATConnection::next_session_number()
612 {
613     unsigned int i;
614     for (i=next_session; i < MAX_SESSIONS; i++)
615     {
616 	if (!sessions[i])
617 	{
618 	    next_session = i+1;
619 	    highest_session = i;
620 	    return i;
621 	}
622     }
623 
624 // Didn't find a slot here - try from the start
625     for (i=1; i < next_session; i++)
626     {
627 	if (!sessions[i])
628 	{
629 	    next_session = i+1;
630 	    return i;
631 	}
632     }
633     return -1;
634 }
635 
636 
637 //
638 //  Send queued packets
639 //
circuit_timer(void)640 void LATConnection::circuit_timer(void)
641 {
642     // Did we get an ACK for our last message?
643     if (need_ack && last_sent_seq != last_recv_ack)
644     {
645 	if (++retransmit_count > LATServer::Instance()->get_retransmit_limit())
646 	{
647 	    debuglog(("hit retransmit limit on connection %d\n", num));
648 
649 	    unsigned char buf[1600];
650 	    LAT_Header *header = (LAT_Header *)buf;
651 	    int ptr = sizeof(LAT_Header);
652 
653 	    header->cmd             = LAT_CCMD_CONREF;
654 	    if (role == CLIENT)
655 		header->cmd |= 2;
656 	    header->num_slots       = 0;
657 	    header->local_connid    = num;
658 	    header->remote_connid   = remote_connid;
659 	    header->sequence_number = ++last_sent_seq;
660 	    header->ack_number      = last_recv_seq;
661 	    buf[ptr++] = 0x06; // Retransmission limit reached.
662 	    LATServer::Instance()->send_message(buf, ptr, interface, macaddr);
663 
664 	    // Set this connection pending deletion
665 	    LATServer::Instance()->delete_connection(num);
666 
667 	    // Mark this node as unavailable in the service list
668 	    LATServices::Instance()->remove_node(std::string((char *)remnode));
669 	    return;
670 	}
671 	debuglog(("Last message not ACKed: RESEND\n"));
672 	last_message.send(interface, last_recv_seq, macaddr);
673 	return;
674     }
675 
676     // If we're waiting for a non-flow-control message then
677     // check for timeout.
678     if (last_msg_type)
679     {
680 	time_t tt;
681 	tt = time(NULL);
682 
683 	if (tt - last_msg_time > 5)
684 	{
685 	    last_msg_time = tt;
686 
687 	    // Too many retries ??
688 	    if (++last_msg_retries >= 3)
689 	    {
690 		LATServer::Instance()->delete_connection(num);
691 		last_msg_type = 0;
692 		return;
693 	    }
694 	    switch (last_msg_type)
695 	    {
696 		// Connect
697 	    case LAT_CCMD_CONNECT:
698 	        {
699 		    // Send another connect command
700 		    int ptr;
701 		    unsigned char buf[1600];
702 		    LAT_Start *msg = (LAT_Start *)buf;
703 		    ptr = sizeof(LAT_Start);
704 
705 		    debuglog(("Resending connect to service on interface %d\n", interface));
706 
707 		    msg->header.cmd          = LAT_CCMD_CONNECT;
708 		    msg->header.num_slots    = 0;
709 		    msg->header.local_connid = num;
710 
711 		    msg->maxsize     = dn_htons(1500);
712 		    msg->latver      = LAT_VERSION;
713 		    msg->latver_eco  = LAT_VERSION_ECO;
714 		    msg->maxsessions = 254;
715 		    msg->exqueued    = 0;
716 		    msg->circtimer   = LATServer::Instance()->get_circuit_timer();
717 		    msg->keepalive   = LATServer::Instance()->get_keepalive_timer();
718 		    msg->facility    = dn_htons(0); // Eh?
719 		    msg->prodtype    = 3;   // Wot do we use here???
720 		    msg->prodver     = 3;   // and here ???
721 
722 		    add_string(buf, &ptr, remnode);
723 		    add_string(buf, &ptr, LATServer::Instance()->get_local_node());
724 		    add_string(buf, &ptr, (unsigned char *)LATServer::greeting);
725 		    send_message(buf, ptr, DATA);
726 		    return;
727 		}
728 		break;
729 
730 		// Request for queued connect
731 	    case LAT_CCMD_COMMAND:
732                 {
733 		    int ptr;
734 		    unsigned char buf[1600];
735 		    LAT_Command *msg = (LAT_Command *)buf;
736 		    ptr = sizeof(LAT_Command);
737 
738 		    debuglog(("Resending queued connect to service on interface %d\n", interface));
739 
740 		    msg->cmd         = LAT_CCMD_COMMAND;
741 		    msg->format      = 0;
742 		    msg->hiver       = LAT_VERSION;
743 		    msg->lover       = LAT_VERSION;
744 		    msg->latver      = LAT_VERSION;
745 		    msg->latver_eco  = LAT_VERSION_ECO;
746 		    msg->maxsize     = dn_htons(1500);
747 		    msg->request_id  = num;
748 		    msg->entry_id    = 0;
749 		    msg->opcode      = 2; // Request Queued connection
750 		    msg->modifier    = 1; // Send status periodically
751 
752 		    add_string(buf, &ptr, remnode);
753 
754 		    buf[ptr++] = 32; // Groups length
755 		    memcpy(buf + ptr, LATServer::Instance()->get_user_groups(), 32);
756 		    ptr += 32;
757 
758 		    add_string(buf, &ptr, LATServer::Instance()->get_local_node());
759 		    buf[ptr++] = 0; // ASCIC source port
760 		    buf[ptr++] = 0; // add_string(buf, &ptr, (unsigned char *)LATServer::greeting);
761 		    add_string(buf, &ptr, servicename);
762 		    add_string(buf, &ptr, portname);
763 
764 		    // Send it raw.
765 		    LATServer::Instance()->send_message(buf, ptr, interface, macaddr);
766 		    return;
767 		}
768 		break;
769 
770 	    default:
771 		break;
772 	    }
773 	}
774 	return;
775     }
776 
777     retransmit_count = 0;
778 
779 
780     // Poll our sessions
781     for (unsigned int i=0; i<=highest_session; i++)
782     {
783 	if (sessions[i] && sessions[i]->isConnected())
784 	    sessions[i]->read_pty();
785     }
786 
787     // Coalesce pending messages and queue them
788     while (!slots_pending.empty())
789     {
790 	debuglog(("circuit Timer:: slots pending = %d\n", slots_pending.size()));
791         unsigned char buf[1600];
792         LAT_Header *header = (LAT_Header *)buf;
793         int len = sizeof(LAT_Header);
794 
795 	if (role == SERVER)
796 	    header->cmd         = LAT_CCMD_SDATA;
797 	else
798 	    header->cmd         = LAT_CCMD_SESSION;
799         header->num_slots       = 0;
800 
801 	// Send as many slot data messages as we can
802 	while ( (header->num_slots < max_slots_per_packet && !slots_pending.empty()))
803         {
804             slot_cmd &cmd(slots_pending.front());
805 
806 	    // make sure it fits
807 	    // do we really need max_slots_per_packet ?
808 	    if ((len + cmd.get_len()) > 1500)
809 		break;
810 	    header->num_slots++;
811 
812             memcpy(buf+len, cmd.get_buf(), cmd.get_len());
813             len += cmd.get_len();
814             if (len%2) len++;    // Keep it on even boundary
815 
816             slots_pending.pop();
817         }
818 
819 	if (header->num_slots)
820 	{
821 	    debuglog(("Collected %d slots on circuit timer\n", header->num_slots));
822 	    header->local_connid    = num;
823 	    header->remote_connid   = remote_connid;
824 	    pending_data.push(pending_msg(buf, len, true));
825 	}
826     }
827 
828     // Send a reply if there are no data messages and the remote
829     // end needs an ACK.
830     if (send_ack &&
831 	(pending_data.empty() || window_size >= max_window_size))
832     {
833 	debuglog(("Sending ACK reply\n"));
834 	unsigned char replybuf[1600];
835 
836 	memset(replybuf, 0, sizeof(replybuf));
837 	LAT_Header *header  = (LAT_Header *)replybuf;
838 	int len = sizeof(LAT_Header);
839 
840 	header->cmd       = LAT_CCMD_SREPLY;
841 	header->num_slots = 0;
842 	if (role == CLIENT) header->cmd |= 2; // To Host
843 
844 	header->local_connid    = num;
845 	header->remote_connid   = remote_connid;
846 
847         header->sequence_number = last_sent_seq;
848         header->ack_number      = last_recv_seq;
849 
850 	send_message(replybuf, len, REPLY);
851     }
852     send_ack = false;
853 
854     //  Send a pending data message (if we can)
855     if (!pending_data.empty() && window_size <= max_window_size)
856     {
857         // Send the top message
858         pending_msg &msg(pending_data.front());
859 
860 	retransmit_count = 0;
861 	need_ack = msg.needs_ack();
862 	window_size++;
863 
864         LAT_Header *header      = msg.get_header();
865 
866 	header->local_connid    = num;
867 	header->remote_connid   = remote_connid;
868         header->sequence_number = ++last_sent_seq;
869         header->ack_number      = last_recv_seq;
870 
871         debuglog(("Sending data message on circuit timer: seq: %d, ack: %d\n",
872 		  last_sent_seq, last_recv_seq));
873 
874         msg.send(interface, macaddr);
875 	last_message = msg; // Save it in case it gets lost on the wire;
876         pending_data.pop();
877 	keepalive_timer = 0;
878     }
879 
880     // Increment keepalive timer and trigger it if we are getting too close.
881     // Keepalive timer is held in milli-seconds.
882 
883     // Of course, we needn't send keepalive messages when we are a
884     // disconnected client.
885     if (role == SERVER ||
886 	(role == CLIENT && connected))
887     {
888 	struct timeval tv;
889 	long time_in_msec;
890 
891 	// Initialise last_time for the first time
892 	if (last_time == 0)
893 	{
894 	    gettimeofday(&tv, NULL);
895 	    last_time = tv.tv_sec*1000 + tv.tv_usec/1000;
896 	}
897 
898 	gettimeofday(&tv, NULL);
899 	time_in_msec = tv.tv_sec*1000 + tv.tv_usec/1000;
900 
901 	keepalive_timer += time_in_msec - last_time;
902 	last_time = time_in_msec;
903 
904 	if (keepalive_timer > (LATServer::Instance()->get_keepalive_timer()-3)*1000 )
905 	{
906 	    // Send an empty message that needs an ACK.
907 	    // If we don't get a response to this then we abort the circuit.
908 	    debuglog(("keepalive timer expired: %d: limit: %d\n", keepalive_timer,
909 		      LATServer::Instance()->get_keepalive_timer()*1000));
910 
911 	    // If we get into this block then there is no chance that there is
912 	    // an outstanding ack (or if there is then it's all gone horribly wrong anyway)
913 	    // so it's safe to just send a NULL message out.
914 	    // If we do exqueued properly this may need revisiting.
915 	    send_ack = true;
916 	    return;
917 	}
918     }
919     // Delete us if delete_pending is set and no more data to send
920     if (delete_pending && pending_data.empty() &&
921 	slots_pending.empty())
922     {
923 	LAT_Header msg;
924 
925 	debuglog(("Deleting pending connection\n"));
926 	msg.local_connid = remote_connid;
927 	msg.remote_connid = num;
928 	msg.sequence_number = ++last_sent_seq;
929 	msg.ack_number = last_recv_ack;
930 	LATServer::Instance()->send_connect_error(1, &msg, interface, macaddr);
931 	LATServer::Instance()->delete_connection(num);
932     }
933 
934 }
935 
936 // Add as many data slots as we can to a reply.
add_data_slots(int start_slot,LAT_SlotCmd * slots[4])937 int LATConnection::add_data_slots(int start_slot, LAT_SlotCmd *slots[4])
938 {
939     int slot_num = start_slot;
940 
941     // Poll our sessions
942     for (unsigned int i=0; i<=highest_session; i++)
943     {
944 	if (sessions[i] && sessions[i]->isConnected())
945 	    sessions[i]->read_pty();
946     }
947 
948 // Overwrite any empty slot at the start
949     LAT_SlotCmd *slot_header = (LAT_SlotCmd *)slots[0];
950     if (start_slot == 1 &&
951 	slot_header->length == 0 &&
952 	!slots_pending.empty())
953     {
954 	slot_num--;
955     }
956 
957     while (slot_num < max_slots_per_packet && !slots_pending.empty())
958     {
959 	slot_cmd &cmd(slots_pending.front());
960 
961 	memcpy((char*)slots[slot_num], cmd.get_buf(), cmd.get_len());
962 
963 	slots_pending.pop();
964 	slot_num++;
965     }
966     return slot_num;
967 }
968 
remove_session(unsigned char id)969 void LATConnection::remove_session(unsigned char id)
970 {
971     debuglog(("Deleting session %d\n", id));
972     if (sessions[id])
973     {
974         delete sessions[id];
975 	sessions[id] = NULL;
976     }
977 
978 // Disconnect & remove connection if no sessions active...
979 // and no messages pending on circuit timer....
980     if (num_clients() == 0)
981     {
982 
983 	if (pending_data.empty() && slots_pending.empty())
984 	{
985 	    LAT_Header msg;
986 
987 	    msg.local_connid = remote_connid;
988 	    msg.remote_connid = num;
989 	    msg.sequence_number = ++last_sent_seq;
990 	    msg.ack_number = last_recv_ack;
991 	    LATServer::Instance()->send_connect_error(1, &msg, interface, macaddr);
992 	    LATServer::Instance()->delete_connection(num);
993 	}
994 	else
995 	{
996 	    // Otherwise just delete us when it's all calmed down.
997 	    delete_pending = true;
998 	}
999     }
1000 }
1001 
1002 // Initiate a client connection
connect(LATSession * session)1003 int LATConnection::connect(LATSession *session)
1004 {
1005    // Look up the service name.
1006     std::string node;
1007     int  this_int=0;
1008 
1009     // Are we in the middle of actually connecting ?
1010     if (connecting) return 0;
1011 
1012     // Only connect if we are the first session,
1013     // else just initiate slot connect.
1014     if (!connected)
1015     {
1016 	// If no node was specified then just use the highest rated one
1017 	if (remnode[0] == '\0')
1018 	{
1019 	    if (!LATServices::Instance()->get_highest(std::string((char*)servicename),
1020 						      node, macaddr, &this_int))
1021 	    {
1022 		debuglog(("Can't find service %s\n", servicename));
1023 		// Tell the user
1024 		session->disconnect_session(7);
1025 		return -2; // Never eard of it!
1026 	    }
1027 	    strcpy((char *)remnode, node.c_str());
1028 	}
1029 	else
1030 	{
1031 	    // Try to find the node
1032 	    if (!LATServices::Instance()->get_node(std::string((char*)servicename),
1033 						   std::string((char*)remnode), macaddr, &this_int))
1034 	    {
1035 		debuglog(("Can't find node %s in service\n", remnode, servicename));
1036 
1037 		// Tell the user
1038 		session->disconnect_session(7);
1039 		return -2; // Never eard of it!
1040 	    }
1041 	}
1042 
1043 	// Reset the sequence & ack numbers
1044 	last_recv_seq = 0xff;
1045 	last_recv_ack = 0;
1046 	last_sent_seq = 0xff;
1047 	last_sent_ack = 0;
1048 	remote_connid = 0;
1049 	interface = this_int;
1050 	connecting = true;
1051 
1052 	// Queued connection or normal?
1053 	if (queued)
1054 	{
1055 	    debuglog(("Requesting connect to queued service\n"));
1056 
1057 	    int ptr;
1058 	    unsigned char buf[1600];
1059 	    LAT_Command *msg = (LAT_Command *)buf;
1060 	    ptr = sizeof(LAT_Command);
1061 
1062 	    msg->cmd         = LAT_CCMD_COMMAND;
1063 	    msg->format      = 0;
1064 	    msg->hiver       = LAT_VERSION;
1065 	    msg->lover       = LAT_VERSION;
1066 	    msg->latver      = LAT_VERSION;
1067 	    msg->latver_eco  = LAT_VERSION_ECO;
1068 	    msg->maxsize     = dn_htons(1500);
1069 	    msg->request_id  = num;
1070 	    msg->entry_id    = 0;
1071 	    msg->opcode      = 2; // Request Queued connection
1072 	    msg->modifier    = 1; // Send status periodically
1073 
1074 	    add_string(buf, &ptr, remnode);
1075 
1076 	    buf[ptr++] = 32; // Groups length
1077 	    memcpy(buf + ptr, LATServer::Instance()->get_user_groups(), 32);
1078 	    ptr += 32;
1079 
1080 	    add_string(buf, &ptr, LATServer::Instance()->get_local_node());
1081 	    buf[ptr++] = 0; // ASCIC source port
1082 	    buf[ptr++] = 0; // add_string(buf, &ptr, (unsigned char *)LATServer::greeting);
1083 	    add_string(buf, &ptr, servicename);
1084 	    add_string(buf, &ptr, portname);
1085 
1086 	    // Save the time we sent the connect so we
1087             // know if we got a response.
1088 	    last_msg_time = time(NULL);
1089 	    last_msg_type = msg->cmd;
1090 	    last_msg_retries = 0;
1091 
1092 	    // Send it raw.
1093 	    return LATServer::Instance()->send_message(buf, ptr, interface, macaddr);
1094 	}
1095 	else
1096 	{
1097 	    int ptr;
1098 	    unsigned char buf[1600];
1099 	    LAT_Start *msg = (LAT_Start *)buf;
1100 	    ptr = sizeof(LAT_Start);
1101 
1102 	    debuglog(("Requesting connect to service on interface %d\n", interface));
1103 
1104 	    msg->header.cmd          = LAT_CCMD_CONNECT;
1105 	    msg->header.num_slots    = 0;
1106 	    msg->header.local_connid = num;
1107 
1108 	    msg->maxsize     = dn_htons(1500);
1109 	    msg->latver      = LAT_VERSION;
1110 	    msg->latver_eco  = LAT_VERSION_ECO;
1111 	    msg->maxsessions = 254;
1112 	    msg->exqueued    = 0;
1113 	    msg->circtimer   = LATServer::Instance()->get_circuit_timer();
1114 	    msg->keepalive   = LATServer::Instance()->get_keepalive_timer();
1115 	    msg->facility    = dn_htons(0); // Eh?
1116 	    msg->prodtype    = 3;   // Wot do we use here???
1117 	    msg->prodver     = 3;   // and here ???
1118 
1119 	    add_string(buf, &ptr, remnode);
1120 	    add_string(buf, &ptr, LATServer::Instance()->get_local_node());
1121 	    add_string(buf, &ptr, (unsigned char *)LATServer::greeting);
1122 
1123 	    // Save the time we sent the connect so we
1124             // know if we got a response.
1125 	    last_msg_time = time(NULL);
1126 	    last_msg_type = msg->header.cmd;
1127 	    last_msg_retries = 0;
1128 
1129 	    return send_message(buf, ptr, DATA);
1130 	}
1131     }
1132     else
1133     {
1134 	// Just do a session connect.
1135 	session->connect();
1136     }
1137     return 0;
1138 }
1139 
1140 // Initiate a reverse-LAT connection
rev_connect()1141 int LATConnection::rev_connect()
1142 {
1143     // Reset the sequence & ack numbers
1144     last_recv_seq = 0xff;
1145     last_recv_ack = 0;
1146     last_sent_seq = 0xff;
1147     last_sent_ack = 0;
1148     remote_connid = 0;
1149     connecting = true;
1150 
1151     int ptr;
1152     unsigned char buf[1600];
1153     LAT_Start *msg = (LAT_Start *)buf;
1154     ptr = sizeof(LAT_Start);
1155 
1156     debuglog(("REVLAT: Requesting connect to service on interface %d, request id = %d\n", interface, request_id));
1157 
1158     msg->header.cmd          = LAT_CCMD_CONNECT;
1159     msg->header.num_slots    = 0;
1160     msg->header.local_connid = num;
1161 
1162     msg->maxsize     = dn_htons(1500);
1163     msg->latver      = LAT_VERSION;
1164     msg->latver_eco  = LAT_VERSION_ECO;
1165     msg->maxsessions = 254;
1166     msg->exqueued    = 0;
1167     msg->circtimer   = LATServer::Instance()->get_circuit_timer();
1168     msg->keepalive   = LATServer::Instance()->get_keepalive_timer();
1169     msg->facility    = dn_htons(0); // Eh?
1170     msg->prodtype    = 3;   // Wot do we use here???
1171     msg->prodver     = 3;   // and here ???
1172 
1173     add_string(buf, &ptr, remnode);
1174     add_string(buf, &ptr, LATServer::Instance()->get_local_node());
1175 
1176     // Save the time we sent the connect so we
1177     // know if we got a response.
1178     last_msg_time = time(NULL);
1179     last_msg_type = msg->header.cmd;
1180     last_msg_retries = 0;
1181 
1182     return send_message(buf, ptr, DATA);
1183 }
1184 
got_status(unsigned char * node,LAT_StatusEntry * entry)1185 void LATConnection::got_status(unsigned char *node, LAT_StatusEntry *entry)
1186 {
1187     debuglog(("Got status %d from node %s, queue pos = %d,%d. session: %d\n",
1188 	      entry->status, node, entry->max_que_pos, entry->min_que_pos,
1189 	      entry->session_id));
1190 
1191 // Check this is OK - status session ID seems to be rubbish
1192     if (role == CLIENT && sessions[1])
1193     {
1194 	last_msg_type = 0;
1195 	last_msg_retries = 0;
1196 	ClientSession *s = (ClientSession *)sessions[1];
1197 	s->show_status(node, entry);
1198     }
1199 
1200 // TODO: mark this session (connection?) as waiting for connect so
1201 // that, if the user quits, we can tell the server. (TODODO: what message ??)
1202 }
1203 
create_llogin_session(int fd,const char * service,const char * port,const char * localport,const char * password)1204 int LATConnection::create_llogin_session(int fd, const char *service, const char *port, const char *localport,
1205 					 const char *password)
1206 {
1207 // Create an lloginSession
1208     int newsessionnum = next_session_number();
1209     if (newsessionnum == -1)
1210 	return -1;
1211 
1212     lloginSession *newsession = new lloginSession(*this, 0, newsessionnum,
1213 						  (char *)localport, fd);
1214     if (newsession->new_session((unsigned char *)remnode, (char *)service, (char *)port, (char *)password, 0) == -1)
1215     {
1216 	delete newsession;
1217 	return -1;
1218     }
1219     sessions[newsessionnum] = newsession;
1220     return 0;
1221 }
1222 
create_localport_session(int fd,LocalPort * lport,const char * service,const char * port,const char * localport,const char * password)1223 int LATConnection::create_localport_session(int fd, LocalPort *lport,
1224 					    const char *service, const char *port,
1225 					    const char *localport, const char *password)
1226 {
1227 // Create a localportSession for a /dev/lat port
1228     int newsessionnum = next_session_number();
1229 
1230     localportSession *newsession = new localportSession(*this, lport, 0, newsessionnum,
1231 						  (char *)localport, fd);
1232     if (newsession->new_session((unsigned char *)remnode, (char *)service, (char *)port, (char *)password, 0) == -1)
1233     {
1234 	delete newsession;
1235 	return -1;
1236     }
1237     sessions[newsessionnum] = newsession;
1238     return 0;
1239 }
1240 
1241 // Create a server session for an incoming reverse-LAT connection
create_reverse_session(const char * service,const char * cmdbuf,int reqid,int ifn,unsigned char * mac)1242 int LATConnection::create_reverse_session(const char *service,
1243 					  const char *cmdbuf,
1244 					  int reqid,
1245 					  int ifn,
1246 					  unsigned char *mac)
1247 {
1248     std::string cmd;
1249     int maxcon;
1250     uid_t uid;
1251     gid_t gid;
1252     int curcon;
1253 
1254     debuglog(("Create reverse session for %s\n", service));
1255 
1256     if (LATServer::Instance()->get_service_info((char *)service, cmd, maxcon, curcon, uid, gid) == -1)
1257     {
1258 	debuglog(("Service not known\n"));
1259 	return -1;
1260     }
1261 
1262     int newsessionnum = next_session_number();
1263 
1264     request_id = reqid;
1265     interface = ifn;
1266     memcpy(macaddr, mac, 6);
1267 
1268     debuglog(("service %s, cmd = %s\n", service, cmd.c_str()));
1269 
1270     ReverseSession *newsession = new ReverseSession(*this,
1271 						    (LAT_SessionStartCmd *)cmdbuf,
1272 						    cmd,
1273 						    uid,gid,
1274 						    0,newsessionnum,
1275 						    true);
1276 
1277     if (newsession->new_session((unsigned char *)remnode, (char *)remnode, (char *)"", 0) == -1)
1278     {
1279 	delete newsession;
1280 	return -1;
1281     }
1282     sessions[newsessionnum] = newsession;
1283     newsession->set_request_id(reqid);
1284 
1285     // Start it connecting.
1286     if (!connected && !connecting)
1287 	rev_connect();
1288 
1289     if (connected)
1290 	newsession->connect();
1291     return 0;
1292 }
1293 
got_connect_ack(unsigned char * buf)1294 int LATConnection::got_connect_ack(unsigned char *buf)
1295 {
1296     LAT_StartResponse *reply = (LAT_StartResponse *)buf;
1297     remote_connid = reply->header.local_connid;
1298 
1299     last_recv_ack = reply->header.ack_number;
1300     last_recv_seq = reply->header.sequence_number;
1301 
1302     connected = true;
1303     connecting = false;
1304 
1305     max_window_size = reply->exqueued+1;
1306     max_window_size = 1; // All we can manage
1307     window_size = 0;
1308 //    need_ack = false;
1309 
1310     last_msg_type = 0;  // Not waiting anymore
1311     last_msg_retries = 0;
1312 
1313     debuglog(("got connect ack. seq: %d, ack: %d\n",
1314 	      last_recv_seq, last_recv_ack));
1315 
1316 // Start clientsessions
1317     for (unsigned int i=1; i<=highest_session; i++)
1318     {
1319 	ClientSession *cs = (ClientSession *)sessions[i];
1320 	if (cs && cs->waiting_start())
1321 	{
1322 	    cs->connect();
1323 	}
1324     }
1325     return 0;
1326 }
1327 
1328 // Called when the client needs disconnecting
disconnect_client()1329 int LATConnection::disconnect_client()
1330 {
1331 // Reset all clients - remote end has disconnected the connection
1332     for (unsigned int i=0; i<=highest_session; i++)
1333     {
1334 	ClientSession *cs = (ClientSession *)sessions[i];
1335 	if (cs)
1336 	{
1337 	    cs->restart_pty();
1338 	}
1339     }
1340     return 0;
1341 }
1342 
1343 
1344 // Extract "parameter 2" from the packet. If there is one then
1345 // it means this is a connection from the terminal server for
1346 // a queued *client* port so we...
1347 // do "something clever..."
is_queued_reconnect(unsigned char * buf,int len,int * conn)1348 bool LATConnection::is_queued_reconnect(unsigned char *buf, int len, int *conn)
1349 {
1350     int ptr = sizeof(LAT_SessionCmd)+3;
1351 
1352     ptr += buf[ptr]+1; // Skip over destination service
1353     if (ptr >= len) return false;
1354 
1355     ptr += buf[ptr]+1; // Skip over source service
1356     if (ptr >= len) return false;
1357 
1358 // Do parameters -- look for a 2
1359     while (ptr < len)
1360     {
1361 	int param_type = buf[ptr++];
1362 	if (param_type == 2)
1363 	{
1364 	    ptr++; //Skip over parameter length (it's 2)
1365 	    unsigned short param = dn_ntohs(*(unsigned short *)(buf+ptr));
1366 
1367 	    debuglog(("found Parameter 2: request ID is %d\n", param));
1368 	    *conn = param;
1369 	    ptr +=2;
1370 	    return true;
1371 	}
1372 	else
1373 	{
1374 	    ptr += buf[ptr]+1; // Skip over it
1375 	}
1376     }
1377     return false;
1378 }
1379 
send(int interface,unsigned char * macaddr)1380 int LATConnection::pending_msg::send(int interface, unsigned char *macaddr)
1381 {
1382     return LATServer::Instance()->send_message(buf, len, interface, macaddr);
1383 }
1384 
num_clients()1385 unsigned int LATConnection::num_clients()
1386 {
1387     unsigned int i;
1388     unsigned int num = 0;
1389 
1390     for (i=1; i<=highest_session; i++)
1391 	if (sessions[i])
1392 		num++;
1393 
1394     return num;
1395 }
1396