1 /******************************************************************************
2 (c) 2001-2005 Christine Caulfield christine.caulfield@googlemail.com
3 (c) 2003 Dmitri Popov
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 ******************************************************************************/
15 #include <sys/param.h> /* for PATH_MAX and types */
16 #include <sys/uio.h>
17 #include <sys/un.h>
18 #include <sys/ioctl.h>
19 #include <sys/wait.h>
20 #include <sys/stat.h>
21 #include <sys/time.h>
22 #include <sys/socket.h>
23 #include <sys/utsname.h>
24 #ifdef HAVE_NET_ETHERNET_H
25 #include <net/ethernet.h>
26 #endif
27 #include <stdio.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <signal.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <dirent.h>
34 #include <syslog.h>
35 #include <ctype.h>
36 #include <regex.h>
37 #include <stdlib.h>
38 // #include <utmp.h>
39 #include <grp.h>
40 #include <signal.h>
41 #include <assert.h>
42 #include <netinet/in.h>
43
44 #include <list>
45 #include <queue>
46 #include <map>
47 #include <string>
48 #include <algorithm>
49 #include <iterator>
50 #include <sstream>
51 #include <iomanip>
52
53 #include "lat.h"
54 #include "utils.h"
55 #include "session.h"
56 #include "localport.h"
57 #include "connection.h"
58 #include "circuit.h"
59 #include "latcpcircuit.h"
60 #include "llogincircuit.h"
61 #include "server.h"
62 #include "services.h"
63 #include "lat_messages.h"
64 #include "dn_endian.h"
65
66 #if defined (__APPLE__) && !defined(_SOCKLEN_T)
67 typedef int socklen_t;
68 #endif
69
70 // Remove any dangling symlinks in the /dev/lat directory
tidy_dev_directory()71 void LATServer::tidy_dev_directory()
72 {
73 DIR *dir;
74 struct dirent *de;
75 char current_dir[PATH_MAX];
76
77 getcwd(current_dir, sizeof(current_dir));
78 chdir(LAT_DIRECTORY);
79
80 dir = opendir(LAT_DIRECTORY);
81 if (!dir) return; // Doesn't exist - this is OK
82
83 while ( (de = readdir(dir)) )
84 {
85 if (de->d_name[0] != '.')
86 unlink(de->d_name);
87 }
88 closedir(dir);
89 chdir(current_dir);
90 }
91
get_local_node(void)92 unsigned char *LATServer::get_local_node(void)
93 {
94 unsigned int i;
95
96 if (local_name[0] == '\0')
97 {
98 struct utsname uts;
99 char *trailer;
100
101 uname(&uts);
102 if (strchr(uts.nodename, '.'))
103 *strchr(uts.nodename, '.') = '\0';
104
105 // This gets rid of the name-Computer bit on Darwin
106 trailer = strstr(uts.nodename, "-Computer");
107 if (trailer)
108 *trailer = '\0';
109
110 // LAT node names must be <= 16 characters long
111 if (strlen(uts.nodename) > 16)
112 uts.nodename[16] = '\0';
113
114 strcpy((char *)local_name, uts.nodename);
115
116 // Make it all upper case
117 for (i=0; i<strlen((char *)local_name); i++)
118 {
119 if (islower(local_name[i])) local_name[i] = toupper(local_name[i]);
120 }
121 }
122 return local_name;
123 }
124
alarm_signal(int sig)125 void LATServer::alarm_signal(int sig)
126 {
127 if (Instance()->alarm_mode == 0)
128 {
129 Instance()->send_service_announcement(sig);
130 }
131 Instance()->send_solicit_messages(sig);
132
133 }
134
135
136 // Send ENQUIRY for a node - mainly needed for DS90L servers that
137 // don't advertise.
send_enq(const char * node)138 void LATServer::send_enq(const char *node)
139 {
140 unsigned char packet[1600];
141 static unsigned char id = 1;
142 LAT_Enquiry *enqmsg = (LAT_Enquiry *)packet;
143 int ptr = sizeof(LAT_Enquiry);
144
145 enqmsg->cmd = LAT_CCMD_ENQUIRE;
146 enqmsg->dummy = 0;
147 enqmsg->hiver = LAT_VERSION;
148 enqmsg->lover = LAT_VERSION;
149 enqmsg->latver = LAT_VERSION;
150 enqmsg->latver_eco = LAT_VERSION_ECO;
151 enqmsg->mtu = dn_htons(1500);
152 enqmsg->id = id++;
153 enqmsg->retrans_timer = 75; // * 10ms - give it more time to respond
154
155 add_string(packet, &ptr, (const unsigned char *)node);
156 packet[ptr++] = 1; /* Length of group data */
157 packet[ptr++] = 1; /* Group mask */
158
159 add_string(packet, &ptr, local_name);
160 packet[ptr++] = 0x00;
161 packet[ptr++] = 0x00;
162 packet[ptr++] = 0x00;
163 packet[ptr++] = 0x00;
164
165 /* This is the LAT multicast address */
166 static unsigned char addr[6] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x0f };
167
168 debuglog(("send_enq : node: %s, local_name: %s\n", node, local_name));
169
170 for (int i=0; i<num_interfaces;i++)
171 {
172 if (iface->send_packet(interface_num[i], addr, packet, ptr) < 0)
173 {
174 debuglog(("Error send packet\n"));
175 interface_error(interface_num[i], errno);
176 }
177 else
178 {
179 interface_errs[interface_num[i]] = 0; // Clear errors
180 }
181 }
182
183 LATServices::Instance()->touch_dummy_node_respond_counter(node);
184 }
185
add_slave_node(const char * node_name)186 void LATServer::add_slave_node(const char *node_name)
187 {
188 sig_blk_t _block(SIGALRM);
189 for (std::list<std::string>::iterator iter = slave_nodes.begin();
190 iter != slave_nodes.end();
191 iter++)
192 {
193 if (*iter == node_name) {
194 // do not duplicate nodes
195 return;
196 }
197 }
198 slave_nodes.push_front(node_name);
199 }
200
201 /* Called on the multicast timer - advertise our service on the LAN */
send_service_announcement(int sig)202 void LATServer::send_service_announcement(int sig)
203 {
204 unsigned char packet[1600];
205 int ptr;
206 struct utsname uinfo;
207 char *myname;
208
209 // Only send it if we have some services
210 if (servicelist.size())
211 {
212 LAT_ServiceAnnounce *announce = (LAT_ServiceAnnounce *)packet;
213 ptr = sizeof(LAT_ServiceAnnounce);
214
215 announce->cmd = LAT_CCMD_SERVICE;
216 announce->circuit_timer = circuit_timer;
217 announce->hiver = LAT_VERSION;
218 announce->lover = LAT_VERSION;
219 announce->latver = LAT_VERSION;
220 announce->latver_eco = LAT_VERSION_ECO;
221 announce->incarnation = --multicast_incarnation;
222 announce->flags = 0x1f;
223 announce->mtu = dn_htons(1500);
224 announce->multicast_timer = multicast_timer;
225 if (do_shutdown)
226 {
227 announce->node_status = 3; // Not accepting connections
228 }
229 else
230 {
231 announce->node_status = 2; // Accepting connections
232 }
233
234 // Send group codes
235 if (groups_set)
236 {
237 announce->group_length = 32;
238 memcpy(&packet[ptr], groups, 32);
239 ptr += 32;
240 announce->flags |= 1;
241 }
242 else
243 {
244 announce->group_length = 1;
245 packet[ptr++] = 01;
246 }
247
248 /* Get host info */
249 uname(&uinfo);
250
251 // Node name
252 myname = (char*)get_local_node();
253 packet[ptr++] = strlen(myname);
254 strcpy((char*)packet+ptr, myname);
255 ptr += strlen(myname);
256
257 // Greeting
258 packet[ptr++] = strlen((char*)greeting);
259 strcpy((char*)packet+ptr, (char*)greeting);
260 ptr += strlen((char*)greeting);
261
262 // Number of services
263 packet[ptr++] = servicelist.size();
264 std::list<serviceinfo>::iterator i(servicelist.begin());
265 for (; i != servicelist.end(); i++)
266 {
267 // Service rating
268 unsigned char real_rating;
269 if (i->get_static())
270 {
271 real_rating = i->get_rating();
272 }
273 else
274 {
275 /* Calculate dynamic rating */
276 real_rating = (unsigned char)(i->get_rating() / (get_loadavg()+1.0));
277 debuglog(("Dynamic service rating is %d\n", real_rating));
278 }
279 packet[ptr++] = real_rating;
280
281 // Service name
282 const std::string name = i->get_name();
283 packet[ptr++] = name.length();
284 strcpy((char *)packet+ptr, i->get_name().c_str());
285 ptr += name.length();
286
287 // Service Identification
288 std::string id = i->get_id();
289 if (id.length() == 0)
290 {
291 // Default service identification string
292 char stringbuf[1024];
293 sprintf(stringbuf, "%s %s", uinfo.sysname, uinfo.release);
294 id = std::string(stringbuf);
295 }
296
297 packet[ptr++] = id.length();
298 strcpy((char *)packet+ptr, id.c_str());
299 ptr += id.length();
300
301 // Make sure the service table knows about all our services
302 unsigned char dummy_macaddr[6];
303 memset(dummy_macaddr, 0, sizeof(dummy_macaddr));
304 if (!do_shutdown)
305 LATServices::Instance()->add_service(std::string((char*)get_local_node()),
306 name,
307 id, real_rating, 0, dummy_macaddr);
308 }
309
310 // Not sure what node service classes are
311 // probably somthing to do with port services and stuff.
312 packet[ptr++] = 0x01; // Node service classes length
313 packet[ptr++] = 0x01; // Node service classes
314 packet[ptr++] = 0x00;
315 packet[ptr++] = 0x00;
316
317 unsigned char addr[6];
318 /* This is the LAT multicast address */
319 addr[0] = 0x09;
320 addr[1] = 0x00;
321 addr[2] = 0x2b;
322 addr[3] = 0x00;
323 addr[4] = 0x00;
324 addr[5] = 0x0f;
325
326 for (int i=0; i<num_interfaces;i++)
327 {
328 if (iface->send_packet(interface_num[i], addr, packet, ptr) < 0)
329 {
330 debuglog(("sending service announcement, send error: %d\n", errno));
331 interface_error(interface_num[i], errno);
332 }
333 else
334 interface_errs[interface_num[i]] = 0; // Clear errors
335 }
336 }
337 /* Send it every minute */
338 signal(SIGALRM, &alarm_signal);
339 alarm(multicast_timer);
340 }
341
342 // Send solicit messages to slave nodes
send_solicit_messages(int sig)343 void LATServer::send_solicit_messages(int sig)
344 {
345 static unsigned int counter = 0;
346 static unsigned int last_list_size = 0;
347
348 if (alarm_mode == 0)
349 {
350 counter = 0;
351 alarm_mode = 1;
352 debuglog(("set alarm_mode to 1\n"));
353
354 if (!known_slave_nodes.empty())
355 {
356 std::string known_node = known_slave_nodes.front();
357 known_slave_nodes.pop_front();
358 slave_nodes.push_back(known_node);
359 debuglog(("known(%d) => slave(%d) : %s\n", known_slave_nodes.size(),
360 slave_nodes.size(), known_node.c_str()));
361 if (slave_nodes.size() == 1)
362 {
363 alarm_mode = 0;
364 debuglog(("set alarm_mode to 0 - one slave\n"));
365 send_enq(slave_nodes.front().c_str());
366 // alarm() is already charged by send_service_announcement()
367 return;
368 }
369 }
370 }
371 else
372 {
373 if (slave_nodes.size() < last_list_size)
374 {
375 counter -= last_list_size - slave_nodes.size();
376 }
377 }
378
379 if (slave_nodes.size() > counter && !slave_nodes.empty())
380 {
381 std::string node_name = slave_nodes.front();
382 slave_nodes.pop_front();
383 slave_nodes.push_back(node_name);
384
385 send_enq(node_name.c_str());
386
387 alarm(1);
388 counter++;
389 last_list_size = slave_nodes.size();
390 }
391 else
392 {
393 alarm_mode = 0;
394
395 //well, it's not quite correct, I know...
396 alarm(counter >= multicast_timer ? 1 : multicast_timer - counter);
397 debuglog(("set alarm_mode to 0, timer %d\n", counter >= multicast_timer ? 1 : multicast_timer - counter));
398 }
399 }
400
401 // Log an error against an interface. If we get three of these
402 // then we remove it.
403 // If that means we have no interfaces, then closedown.
interface_error(int ifnum,int err)404 void LATServer::interface_error(int ifnum, int err)
405 {
406 syslog(LOG_ERR, "Error on interface %s: %s\n", iface->ifname(ifnum).c_str(), strerror(err));
407
408 // Too many errors, remove it
409 if (++interface_errs[ifnum] > 3)
410 {
411 int i,j;
412
413 syslog(LOG_ERR, "Interface will be removed from LATD\n");
414
415 // Look for it
416 for (i=0; i<num_interfaces; i++)
417 {
418 if (interface_num[i] == ifnum) goto remove_if;
419 }
420
421 // Ugh, didn't find it. that can't be right!
422 if (i>=num_interfaces)
423 {
424 syslog(LOG_ERR, "Don't seem to have a reference to this interface....\n");
425 return;
426 }
427
428 remove_if:
429 // Shuffle the list down
430 for (j=i; j<num_interfaces-1; j++)
431 {
432 interface_num[j] = interface_num[j+1];
433 }
434
435 if (--num_interfaces == 0)
436 {
437 syslog(LOG_ERR, "No valid interfaces left. LATD closing down\n");
438
439 // No point in going down cleanly as that just sends network messages
440 // and we have nowhere to send then through.
441 exit(9);
442 }
443 }
444 }
445
446 /* Main loop */
run()447 void LATServer::run()
448 {
449 int status;
450
451 // Bind interfaces
452 for (int i=0; i<num_interfaces;i++)
453 {
454 iface->set_lat_multicast(interface_num[i]);
455 }
456
457 // Add it/them to the sockets list
458 if (iface->one_fd_per_interface())
459 {
460 for (int i=0; i<num_interfaces;i++)
461 {
462 fdlist.push_back(fdinfo(iface->get_fd(interface_num[i]), 0, LAT_SOCKET));
463 }
464 }
465 else
466 {
467 fdlist.push_back(fdinfo(iface->get_fd(0), 0, LAT_SOCKET));
468 }
469
470 // Open LATCP socket
471 unlink(LATCP_SOCKNAME);
472 latcp_socket = socket(PF_UNIX, SOCK_STREAM, 0);
473 if (latcp_socket < 0)
474 {
475 syslog(LOG_ERR, "Can't create latcp socket: %m");
476 exit(1);
477 }
478
479 struct sockaddr_un sockaddr;
480 strcpy(sockaddr.sun_path, LATCP_SOCKNAME);
481 sockaddr.sun_family = AF_UNIX;
482 if (bind(latcp_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr)))
483 {
484 syslog(LOG_ERR, "can't bind latcp socket: %m");
485 exit(1);
486 }
487 if (listen(latcp_socket, 1) != 0)
488 {
489 syslog(LOG_ERR, "listen latcp: %m");
490 }
491 // Make sure only root can talk to us via the latcp socket
492 chmod(LATCP_SOCKNAME, 0600);
493 fdlist.push_back(fdinfo(latcp_socket, 0, LATCP_RENDEZVOUS));
494
495 // Open llogin socket
496 unlink(LLOGIN_SOCKNAME);
497 llogin_socket = socket(PF_UNIX, SOCK_STREAM, 0);
498 if (llogin_socket < 0)
499 {
500 syslog(LOG_ERR, "Can't create llogin socket: %m");
501 exit(1);
502 }
503
504 strcpy(sockaddr.sun_path, LLOGIN_SOCKNAME);
505 sockaddr.sun_family = AF_UNIX;
506 if (bind(llogin_socket, (struct sockaddr *)&sockaddr, sizeof(sockaddr)))
507 {
508 syslog(LOG_ERR, "can't bind llogin socket: %m");
509 exit(1);
510 }
511 if (listen(llogin_socket, 1) != 0)
512 {
513 syslog(LOG_ERR, "listen llogin: %m");
514 }
515 // Make sure everyone can use it
516 chmod(LLOGIN_SOCKNAME, 0666);
517 fdlist.push_back(fdinfo(llogin_socket, 0, LLOGIN_RENDEZVOUS));
518
519 // Don't start sending service announcements
520 // until we get an UNLOCK message from latcp.
521
522 // We rely on POSIX's select() behaviour in that we use the
523 // time left in the timeval parameter to make sure the circuit timer
524 // goes off at a reasonably predictable interval.
525
526 #ifndef __linux__
527 struct timeval next_circuit_time;
528 next_circuit_time.tv_sec = 0;
529 next_circuit_time.tv_usec = 0;
530 #endif
531
532 struct timeval tv = {0, circuit_timer*10000};
533 time_t last_node_expiry = time(NULL);
534 do_shutdown = false;
535 do
536 {
537 fd_set fds;
538 FD_ZERO(&fds);
539
540 std::list<fdinfo>::iterator i(fdlist.begin());
541 for (; i != fdlist.end(); i++)
542 {
543 if (i->active())
544 FD_SET(i->get_fd(), &fds);
545 }
546
547 // Only Linux seems to have this select behaviour...
548 // for BSDs we need to work our for ourselves the delay
549 // until the next circuit timer tick.
550 #ifndef __linux__
551 struct timeval now;
552
553 gettimeofday(&now, NULL);
554 if (next_circuit_time.tv_sec == 0)
555 {
556 next_circuit_time = now;
557 next_circuit_time.tv_usec += circuit_timer*10000;
558 next_circuit_time.tv_sec += (next_circuit_time.tv_usec / 1000000);
559 next_circuit_time.tv_usec = (next_circuit_time.tv_usec % 1000000);
560 }
561
562 tv = next_circuit_time;
563 if (tv.tv_sec < now.tv_sec
564 || (tv.tv_sec == now.tv_sec
565 && tv.tv_usec <= now.tv_usec))
566 {
567 tv.tv_sec = tv.tv_usec = 0;
568 }
569 else
570 {
571 tv.tv_sec -= now.tv_sec;
572 if ((tv.tv_usec -= now.tv_usec) < 0)
573 {
574 tv.tv_sec--;
575 tv.tv_usec += 1000000;
576 }
577 }
578 #endif
579
580 status = select(FD_SETSIZE, &fds, NULL, NULL, &tv);
581 if (status < 0)
582 {
583 if (errno != EINTR)
584 {
585 syslog(LOG_WARNING, "Error in select: %m");
586 debuglog(("Error in select: %s\n", strerror(errno)));
587 do_shutdown = true;
588 }
589 }
590 else
591 {
592 if (status == 0) // Circuit timer
593 {
594 for (int i=1; i<MAX_CONNECTIONS; i++)
595 if (connections[i])
596 connections[i]->circuit_timer();
597 tv.tv_usec = circuit_timer*10000;
598
599 // Is it time we expired some more nodes ?
600 if (time(NULL) - last_node_expiry > 15)
601 LATServices::Instance()->expire_nodes();
602 #ifndef __linux__
603 next_circuit_time.tv_sec = 0;
604 #endif
605 }
606 else
607 {
608 // Unix will never scale while this is necessary
609 std::list<fdinfo>::iterator fdl(fdlist.begin());
610 for (; fdl != fdlist.end(); fdl++)
611 {
612 if (fdl->active() &&
613 FD_ISSET(fdl->get_fd(), &fds))
614 {
615 process_data(*fdl);
616 }
617 }
618 }
619 }
620
621 // Tidy deleted sessions
622 if (!dead_session_list.empty())
623 {
624 std::list<deleted_session>::iterator dsl(dead_session_list.begin());
625 for (; dsl != dead_session_list.end(); dsl++)
626 {
627 delete_entry(*dsl);
628 }
629 dead_session_list.clear();
630 }
631
632 // Tidy deleted connections
633 if (!dead_connection_list.empty())
634 {
635 std::list<int>::iterator dcl(dead_connection_list.begin());
636 for (; dcl != dead_connection_list.end(); dcl++)
637 {
638 if (connections[*dcl])
639 {
640 delete connections[*dcl];
641 connections[*dcl] = NULL;
642 }
643 }
644 dead_connection_list.clear();
645 }
646
647 } while (!do_shutdown);
648
649 send_service_announcement(-1); // Say we are unavailable
650
651 close(latcp_socket);
652 unlink(LATCP_SOCKNAME);
653 unlink(LLOGIN_SOCKNAME);
654
655 tidy_dev_directory();
656 }
657
658 /* LAT socket has something for us */
read_lat(int sock)659 void LATServer::read_lat(int sock)
660 {
661 unsigned char buf[1600];
662 unsigned char macaddr[6];
663 int len;
664 int i;
665 int ifn;
666 bool more = true;
667 LAT_Header *header = (LAT_Header *)buf;
668
669 while (more)
670 {
671 len = iface->recv_packet(sock, ifn, macaddr, buf, sizeof(buf), more);
672 if (len == 0)
673 continue; // Probably a rogue packet
674
675 if (len < 0)
676 {
677 if (errno != EINTR && errno != EAGAIN)
678 {
679 syslog(LOG_ERR, "recvmsg: %m");
680 return;
681 }
682 }
683
684 // Not listening yet, but we must read the message otherwise we
685 // we will spin until latcp unlocks us.
686 if (locked)
687 continue;
688
689 // Parse & dispatch it.
690 switch(header->cmd)
691 {
692 case LAT_CCMD_SREPLY:
693 case LAT_CCMD_SDATA:
694 case LAT_CCMD_SESSION:
695 {
696 debuglog(("session cmd for connid %d\n", header->remote_connid));
697 LATConnection *conn = NULL;
698 if(header->remote_connid < MAX_CONNECTIONS)
699 {
700 conn = connections[header->remote_connid];
701 }
702
703 if (conn)
704 {
705 conn->process_session_cmd(buf, len, macaddr);
706 }
707 else
708 {
709 // Message format error
710 send_connect_error(2, header, ifn, macaddr);
711 }
712 }
713 break;
714
715 case LAT_CCMD_CONNECT:
716 {
717 // Make a new connection
718
719 // Check that the connection is really for one of our services
720 unsigned char name[256];
721 int ptr = sizeof(LAT_Start);
722 get_string(buf, &ptr, name);
723
724 debuglog(("got connect for node %s\n", name));
725
726 if (strcmp((char *)name, (char *)get_local_node()))
727 {
728 // How the &?* did that happen?
729 send_connect_error(2, header, ifn, macaddr);
730 continue;
731 }
732
733 // Make a new connection.
734 if ( ((i=make_new_connection(buf, len, ifn, header, macaddr) )) > 0)
735 {
736 debuglog(("Made new connection: %d\n", i));
737 connections[i]->send_connect_ack();
738 }
739 }
740 break;
741
742 case LAT_CCMD_CONACK:
743 {
744 LATConnection *conn = NULL;
745 debuglog(("Got connect ACK for %d\n", header->remote_connid));
746 if (header->remote_connid < MAX_CONNECTIONS)
747 {
748 conn = connections[header->remote_connid];
749 }
750
751 if (conn)
752 {
753 conn->got_connect_ack(buf);
754 }
755 else
756 {
757 // Insufficient resources
758 send_connect_error(7, header, ifn, macaddr);
759 }
760 }
761 break;
762
763 case LAT_CCMD_CONREF:
764 case LAT_CCMD_DISCON:
765 {
766 debuglog(("Disconnecting connection %d: status %x(%s)\n",
767 header->remote_connid,
768 buf[sizeof(LAT_Header)],
769 lat_messages::connection_disconnect_msg(buf[sizeof(LAT_Header)]) ));
770 if (header->remote_connid < MAX_CONNECTIONS)
771 {
772 LATConnection *conn = connections[header->remote_connid];
773 if (conn)
774 {
775 // We don't delete clients, we just quiesce them.
776 if (conn->isClient())
777 {
778 conn->disconnect_client();
779 if (conn->num_clients() == 0)
780 {
781 delete conn;
782 connections[header->remote_connid] = NULL;
783 }
784 }
785 else
786 {
787 delete conn;
788 connections[header->remote_connid] = NULL;
789 }
790 }
791 }
792 else
793 {
794 // Message format error
795 send_connect_error(2, header, ifn, macaddr);
796 }
797 }
798 break;
799
800 case LAT_CCMD_SERVICE:
801 // Keep a list of known services
802 add_services(buf, len, ifn, macaddr);
803 break;
804
805 case LAT_CCMD_ENQUIRE:
806 reply_to_enq(buf, len, ifn, macaddr);
807 break;
808
809 case LAT_CCMD_ENQREPLY:
810 got_enqreply(buf, len, ifn, macaddr);
811 break;
812
813 case LAT_CCMD_STATUS:
814 forward_status_messages(buf, len);
815 break;
816
817 // Request for a reverse-LAT connection.
818 case LAT_CCMD_COMMAND:
819 process_command_msg(buf, len, ifn, macaddr);
820 break;
821 }
822 }
823 }
824
825 // Add an FD to the list of FDs to listen to
add_fd(int fd,fd_type type)826 void LATServer::add_fd(int fd, fd_type type)
827 {
828 std::list<fdinfo>::iterator fdi;
829
830 debuglog(("Add_fd: %d\n", fd));
831
832 fdi = find(fdlist.begin(), fdlist.end(), fd);
833 if (fdi != fdlist.end()) return; // Already exists
834
835
836 fdlist.push_back(fdinfo(fdinfo(fd, NULL, type)));
837 }
838
839 // Remove FD from the FD list
remove_fd(int fd)840 void LATServer::remove_fd(int fd)
841 {
842 std::list<fdinfo>::iterator fdi;
843 debuglog(("remove_fd: %d\n", fd));
844
845 fdi = find(fdlist.begin(), fdlist.end(), fd);
846 if (fdi == fdlist.end()) return; // Does not exist
847
848 fdlist.remove(*fdi);
849 }
850
851 // Change the DISABLED state of a PTY fd
set_fd_state(int fd,bool disabled)852 void LATServer::set_fd_state(int fd, bool disabled)
853 {
854 std::list<fdinfo>::iterator fdi;
855 debuglog(("set_fd_state: %d, %d\n", fd, disabled));
856
857 fdi = find(fdlist.begin(), fdlist.end(), fd);
858 if (fdi == fdlist.end()) return; // Does not exist
859
860 fdi->set_disabled(disabled);
861 }
862
863
864
865 /* Send a LAT message to a specified MAC address */
send_message(unsigned char * buf,int len,int interface,unsigned char * macaddr)866 int LATServer::send_message(unsigned char *buf, int len, int interface, unsigned char *macaddr)
867 {
868 if (len < 46) len = 46; // Minimum packet length
869 if (len%2) len++; // Must be an even number
870
871 #ifdef PACKET_LOSS
872 static int c=0;
873 if ((++c % PACKET_LOSS) == 0) {
874 debuglog(("NOT SENDING THIS MESSAGE!\n"));
875 return 0;
876 }
877 #endif
878
879 if (interface == 0) // Send to all
880 {
881 for (int i=0; i<num_interfaces;i++)
882 {
883 if (iface->send_packet(interface_num[i], macaddr, buf, len) < 0)
884 {
885 interface_error(interface_num[i], errno);
886 }
887 else
888 interface_errs[interface_num[i]] = 0; // Clear errors
889
890 }
891 }
892 else
893 {
894 if (iface->send_packet(interface, macaddr, buf, len) < 0)
895 {
896 interface_error(interface, errno);
897 return -1;
898 }
899 interface_errs[interface] = 0; // Clear errors
900 }
901
902 return 0;
903
904 }
905
906 /* Get the system load average */
get_loadavg(void)907 double LATServer::get_loadavg(void)
908 {
909 double avg[3];
910
911 if (getloadavg(avg, 3) > 0)
912 {
913 return avg[0];
914 }
915 else
916 {
917 return 0;
918 }
919 }
920
921 // Forward status messages to their recipient connection objects.
forward_status_messages(unsigned char * inbuf,int len)922 void LATServer::forward_status_messages(unsigned char *inbuf, int len)
923 {
924 int ptr = sizeof(LAT_Status);
925 unsigned char node[256];
926
927 get_string(inbuf, &ptr, node);
928
929 // Forward all the StatusEntry messages
930 while (ptr <= len)
931 {
932 if (ptr%2) ptr++; // Word aligned
933
934 LAT_StatusEntry *entry = (LAT_StatusEntry *)&inbuf[ptr];
935 if (entry->length == 0) break;
936
937 ptr += sizeof(LAT_StatusEntry);
938 get_string(inbuf, &ptr, node); // Service name
939 ptr += inbuf[ptr]+1; // Past port name
940 ptr += inbuf[ptr]+1; // Past service description
941
942 if (entry->request_id < MAX_CONNECTIONS &&
943 connections[entry->request_id])
944 connections[entry->request_id]->got_status(node, entry);
945
946 }
947 }
948
949 /* Reply to an ENQUIRE message with our MAC address & service name */
reply_to_enq(unsigned char * inbuf,int len,int interface,unsigned char * remote_mac)950 void LATServer::reply_to_enq(unsigned char *inbuf, int len, int interface,
951 unsigned char *remote_mac)
952 {
953 int inptr, outptr, i;
954 unsigned char outbuf[1600];
955 unsigned char req_service[1600];
956 LAT_Header *outhead = (LAT_Header *)outbuf;
957 LAT_Header *inhead = (LAT_Header *)inbuf;
958
959 inptr = sizeof(LAT_Header)+4;
960
961 /* This is the service being enquired about */
962 get_string(inbuf, &inptr, req_service);
963
964 debuglog(("got ENQ for %s\n", req_service));
965
966 // Ignore empty requests:: TODO: is this right?? - maybe we issue
967 // a response with all our services in it.
968 if (strlen((char*)req_service) == 0) return;
969
970 unsigned char reply_macaddr[6];
971 unsigned char *reply_node;
972
973 // See if it is for us if we're not doing responder work.
974 if (!responder)
975 {
976 std::list<serviceinfo>::iterator sii;
977 sii = find(servicelist.begin(), servicelist.end(), (char *)req_service);
978 if (sii == servicelist.end()) return; // Not ours
979 }
980
981 std::string node;
982 if (LATServices::Instance()->get_highest(std::string((char *)req_service),
983 node, reply_macaddr, &interface))
984 {
985 reply_node = (unsigned char *)node.c_str();
986 }
987 else
988 {
989 return; // nevver 'eard of 'im.
990 }
991
992 debuglog(("Sending ENQ reply for %s\n", req_service));
993
994 inptr += 2;
995
996 outptr = sizeof(LAT_Header);
997 outbuf[outptr++] = 0x93;
998 outbuf[outptr++] = 0x07;
999 outbuf[outptr++] = 0x00;
1000 outbuf[outptr++] = 0x00;
1001
1002 /* The service's MAC address */
1003 outbuf[outptr++] = 0x06;
1004 outbuf[outptr++] = 0x00;
1005 for (i=0; i<5; i++)
1006 outbuf[outptr++] = reply_macaddr[i];
1007
1008 /* Don't know what this is */
1009 outbuf[outptr++] = 0x14;
1010 outbuf[outptr++] = 0x00;
1011
1012 add_string(outbuf, &outptr, reply_node);
1013 outbuf[outptr++] = 0x01;
1014 outbuf[outptr++] = 0x01;
1015 add_string(outbuf, &outptr, req_service);
1016
1017 outhead->cmd = LAT_CCMD_ENQREPLY;
1018 outhead->num_slots = 0;
1019 outhead->remote_connid = inhead->remote_connid;
1020 outhead->local_connid = inhead->local_connid;
1021 outhead->sequence_number = inhead->sequence_number;
1022 outhead->ack_number = inhead->ack_number;
1023
1024 send_message(outbuf, outptr, interface, remote_mac);
1025 }
1026
shutdown()1027 void LATServer::shutdown()
1028 {
1029 do_shutdown = true;
1030 }
1031
init(bool _static_rating,int _rating,char * _service,char * _greeting,char ** _interfaces,int _verbosity,int _timer)1032 void LATServer::init(bool _static_rating, int _rating,
1033 char *_service, char *_greeting, char **_interfaces,
1034 int _verbosity, int _timer)
1035 {
1036 // Server is locked until latcp has finished
1037 locked = true;
1038
1039 /* Initialise the platform-specific interface code */
1040 iface = LATinterfaces::Create();
1041 if (iface->Start(LATinterfaces::ProtoLAT) == -1)
1042 {
1043 syslog(LOG_ERR, "Can't create LAT protocol socket: %m\n");
1044 exit(1);
1045
1046 }
1047
1048 #ifdef ENABLE_DEFAULT_SERVICE
1049 // Add the default session
1050 servicelist.push_back(serviceinfo(_service,
1051 _rating,
1052 _static_rating));
1053 #endif
1054
1055 strcpy((char *)greeting, _greeting);
1056 verbosity = _verbosity;
1057
1058 // Convert all the interface names to numbers and check they are usable
1059 if (_interfaces[0])
1060 {
1061 int i=0;
1062 while (_interfaces[i])
1063 {
1064 interface_num[num_interfaces] = iface->find_interface(_interfaces[i]);
1065 if (interface_num[num_interfaces] == -1)
1066 {
1067 syslog(LOG_ERR, "Can't use interface %s: ignored\n", _interfaces[i]);
1068 }
1069 else
1070 {
1071 interface_errs[num_interfaces] = 0; // Clear errors
1072 num_interfaces++;
1073 }
1074 i++;
1075 }
1076 if (num_interfaces == 0)
1077 {
1078 syslog(LOG_ERR, "No usable interfaces, latd exiting.\n");
1079 exit(9);
1080 }
1081 }
1082 else
1083 {
1084 iface->get_all_interfaces(interface_num, num_interfaces);
1085 }
1086
1087 // Remove any old /dev/lat symlinks
1088 tidy_dev_directory();
1089
1090 // Save these two for any newly added services
1091 rating = _rating;
1092 static_rating = _static_rating;
1093
1094 next_connection = 1;
1095 multicast_incarnation = 0;
1096 circuit_timer = _timer/10;
1097 local_name[0] = '\0'; // Use default node name
1098
1099 memset(connections, 0, sizeof(connections));
1100
1101 // Enable user group 0
1102 memset(user_groups, 0, 32);
1103 user_groups[0] = 1;
1104
1105 // Look in /etc/group for a group called "lat"
1106 struct group *gr = getgrnam("lat");
1107 if (gr)
1108 lat_group = gr->gr_gid;
1109 else
1110 lat_group = 0;
1111
1112 }
1113
1114 // Create a new connection object for this remote node.
make_new_connection(unsigned char * buf,int len,int interface,LAT_Header * header,unsigned char * macaddr)1115 int LATServer::make_new_connection(unsigned char *buf, int len,
1116 int interface,
1117 LAT_Header *header,
1118 unsigned char *macaddr)
1119 {
1120 int i;
1121 i = get_next_connection_number();
1122
1123 if (i >= 0)
1124 {
1125 next_connection = i+1;
1126 connections[i] = new LATConnection(i, buf, len, interface,
1127 header->sequence_number,
1128 header->ack_number,
1129 macaddr);
1130 }
1131 else
1132 {
1133 // Number of virtual circuits exceeded
1134 send_connect_error(9, header, interface, macaddr);
1135 return -1;
1136 }
1137 return i;
1138 }
1139
delete_session(int conn,unsigned char id,int fd)1140 void LATServer::delete_session(int conn, unsigned char id, int fd)
1141 {
1142 // Add this to the list and delete them later
1143 deleted_session s(LOCAL_PTY, conn, id, fd);
1144 dead_session_list.push_back(s);
1145 }
1146
delete_connection(int conn)1147 void LATServer::delete_connection(int conn)
1148 {
1149 // Add this to the list and delete them later
1150 debuglog(("connection %d pending deletion\n", conn));
1151
1152 dead_connection_list.push_back(conn);
1153 }
1154
1155 // Got a reply from a DS90L - add it to the services list in a dummy service
got_enqreply(unsigned char * buf,int len,int interface,unsigned char * macaddr)1156 void LATServer::got_enqreply(unsigned char *buf, int len, int interface, unsigned char *macaddr)
1157 {
1158 int off = 14;
1159 unsigned char node_addr[6];
1160 char node_description[256];
1161 char node_name[256];
1162
1163 memset(node_addr, 0x00, sizeof(node_addr));
1164 if (0 == memcmp(node_addr, buf + off, sizeof(node_addr)))
1165 {
1166 return;
1167 }
1168
1169 memset(node_addr, 0xFF, sizeof(node_addr));
1170 if (0 == memcmp(node_addr, buf + off, sizeof(node_addr)))
1171 {
1172 return;
1173 }
1174
1175 // Node MAC address
1176 memcpy(node_addr, buf + off, sizeof(node_addr));
1177
1178 // Skip destination node name
1179 off = 22;
1180 off += buf[off] + 1;
1181
1182 // Skip node groups
1183 off += buf[off] + 1;
1184
1185 get_string(buf, &off, (unsigned char*)node_name);
1186 get_string(buf, &off, (unsigned char*)node_description);
1187
1188 #if defined(debuglog)
1189 if (memcmp(node_addr, macaddr, sizeof(node_addr))) {
1190 debuglog(("got_enqreply : macaddr is different : %02hhX-%02hhX-%02hhX-%02hhX-%02hhX-%02hhX\n",
1191 macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]));
1192 }
1193 #endif
1194
1195 // Add it to the dummy service.
1196 debuglog(("got_enqreply : node: '%s' : %02hhX-%02hhX-%02hhX-%02hhX-%02hhX-%02hhX\n",
1197 node_name,
1198 node_addr[0], node_addr[1], node_addr[2], node_addr[3], node_addr[4], node_addr[5]));
1199 LATServices::Instance()->add_service(std::string(node_name),
1200 std::string(""), // Dummy service name
1201 std::string(node_description),
1202 0,
1203 interface, node_addr);
1204
1205 {
1206 sig_blk_t _block(SIGALRM);
1207 std::list<std::string>::iterator sl_iter;
1208 sl_iter = find(slave_nodes.begin(), slave_nodes.end(), node_name);
1209 if (sl_iter != slave_nodes.end()) {
1210 debuglog(("got_enqreply : to remove from slave(%d), node: '%s'\n",
1211 slave_nodes.size(), sl_iter->c_str()));
1212 slave_nodes.erase(sl_iter);
1213 }
1214
1215 sl_iter = find(known_slave_nodes.begin(), known_slave_nodes.end(), node_name);
1216 if (sl_iter == known_slave_nodes.end()) {
1217 known_slave_nodes.push_back(node_name);
1218 debuglog(("got_enqreply : added to known(%d), node: '%s'\n",
1219 known_slave_nodes.size(),
1220 node_name));
1221 }
1222 }
1223 }
1224
1225
1226 // Got a COMMAND message from a remote node. it probably wants
1227 // to set up a reverse-LAT session to us.
process_command_msg(unsigned char * buf,int len,int interface,unsigned char * macaddr)1228 void LATServer::process_command_msg(unsigned char *buf, int len, int interface, unsigned char *macaddr)
1229 {
1230 LAT_Command *msg = (LAT_Command *)buf;
1231 int ptr = sizeof(LAT_Command);
1232 unsigned char remnode[256];
1233 unsigned char remport[256];
1234 unsigned char service[256];
1235 unsigned char portname[256];
1236
1237 // TODO: Check the params in the LAT_Command message...
1238 debuglog(("REVLAT cmd: %d, opcode:%d request_id: %d\n", msg->cmd, msg->opcode, msg->request_id));
1239
1240 ptr += buf[ptr]+1; // Skip past groups for now.
1241 ptr += buf[ptr]+1; // Skip past groups for now.
1242
1243 // Get the remote node name.
1244 get_string(buf, &ptr, remnode);
1245 get_string(buf, &ptr, remport);
1246 ptr += buf[ptr]+1; // Skip past greeting...
1247 get_string(buf, &ptr, service);
1248 get_string(buf, &ptr, portname);
1249
1250 debuglog(("Got request for reverse-LAT connection to %s/%s from %s/%s\n",
1251 service, portname, remnode, remport));
1252
1253 // Make a new connection
1254 // We can reuse connections here...
1255 int connid = find_connection_by_node((char *)remnode);
1256 if (connid == -1)
1257 {
1258 connid = get_next_connection_number();
1259 connections[connid] = new LATConnection(connid,
1260 (char *)service,
1261 (char *)remport,
1262 (char *)portname,
1263 (char *)remnode,
1264 false,
1265 true);
1266 }
1267
1268 // Make a reverse-session and connect it.
1269 LAT_SessionStartCmd startcmd;
1270 memset(&startcmd, 0, sizeof(startcmd));
1271 startcmd.dataslotsize = 255;
1272 if (connections[connid]->create_reverse_session((const char *)service,
1273 (const char *)&startcmd,
1274 dn_ntohs(msg->request_id),
1275 interface, macaddr) == -1)
1276 {
1277 // If we created this connection just for the new session
1278 // then get rid of it.
1279 if (connections[connid]->num_clients() == 0)
1280 delete_connection(connid);
1281 }
1282 }
1283
1284 // Add services received from a service announcement multicast
add_services(unsigned char * buf,int len,int interface,unsigned char * macaddr)1285 void LATServer::add_services(unsigned char *buf, int len, int interface, unsigned char *macaddr)
1286 {
1287 LAT_ServiceAnnounce *announce = (LAT_ServiceAnnounce *)buf;
1288 int ptr = sizeof(LAT_ServiceAnnounce);
1289 unsigned char service_groups[32];
1290 unsigned char nodename[256];
1291 unsigned char greeting[255];
1292 unsigned char service[255];
1293 unsigned char ident[255];
1294
1295 // Set the groups to all zeros initially
1296 memset(service_groups, 0, sizeof(service_groups));
1297
1298 // Make sure someone isn't pulling our leg.
1299 if (announce->group_length > 32)
1300 announce->group_length = 32;
1301
1302 // Get group numbers
1303 memcpy(service_groups, buf+ptr, announce->group_length);
1304
1305 // Compare with our user groups mask (which is always either completely
1306 // empty or the full 32 bytes)
1307 int i;
1308 bool gotone = false;
1309 for (i=0; i<announce->group_length; i++)
1310 {
1311 if (user_groups[i] & service_groups[i])
1312 {
1313 gotone = true;
1314 break;
1315 }
1316 }
1317
1318 if (!gotone)
1319 {
1320 debuglog(("remote node not in our user groups list\n"));
1321 return;
1322 }
1323
1324 ptr += announce->group_length;
1325 get_string(buf, &ptr, nodename);
1326 get_string(buf, &ptr, greeting);
1327
1328 int num_services = buf[ptr++];
1329
1330 debuglog(("service announcement: status = %d\n", announce->node_status));
1331
1332 // Get all the services & register them
1333 for (int i=1; i<=num_services; i++)
1334 {
1335 int rating = buf[ptr++];
1336
1337 get_string(buf, &ptr, service);
1338 get_string(buf, &ptr, ident);
1339
1340 if ( (announce->node_status & 1) == 0)
1341 {
1342 LATServices::Instance()->add_service(std::string((char*)nodename),
1343 std::string((char*)service),
1344 std::string((char*)ident),
1345 rating,
1346 interface, macaddr);
1347 }
1348 else
1349 {
1350 LATServices::Instance()->remove_node(std::string((char*)nodename));
1351 }
1352 }
1353 }
1354
1355 // Wait for data available on a client PTY
add_pty(LocalPort * port,int fd)1356 void LATServer::add_pty(LocalPort *port, int fd)
1357 {
1358 fdlist.push_back(fdinfo(fd, port, LOCAL_PTY));
1359 }
1360
1361
1362 // Got a new connection from latcp
accept_latcp(int fd)1363 void LATServer::accept_latcp(int fd)
1364 {
1365 struct sockaddr_un socka;
1366 socklen_t sl = sizeof(socka);
1367
1368 int latcp_client_fd = accept(fd, (struct sockaddr *)&socka, &sl);
1369 if (latcp_client_fd >= 0)
1370 {
1371 debuglog(("Got LATCP connection\n"));
1372 latcp_circuits[latcp_client_fd] = new LATCPCircuit(latcp_client_fd);
1373
1374 fdlist.push_back(fdinfo(latcp_client_fd, 0, LATCP_SOCKET));
1375 }
1376 else
1377 syslog(LOG_WARNING, "accept on latcp failed: %m");
1378 }
1379
1380 // Got a new connection from llogin
accept_llogin(int fd)1381 void LATServer::accept_llogin(int fd)
1382 {
1383 struct sockaddr_un socka;
1384 socklen_t sl = sizeof(socka);
1385
1386 int llogin_client_fd = accept(fd, (struct sockaddr *)&socka, &sl);
1387 if (llogin_client_fd >= 0)
1388 {
1389 debuglog(("Got llogin connection\n"));
1390 latcp_circuits[llogin_client_fd] = new LLOGINCircuit(llogin_client_fd);
1391
1392 fdlist.push_back(fdinfo(llogin_client_fd, 0, LLOGIN_SOCKET));
1393 }
1394 else
1395 syslog(LOG_WARNING, "accept on llogin failed: %m");
1396 }
1397
1398 // Read a request from LATCP
read_latcp(int fd)1399 void LATServer::read_latcp(int fd)
1400 {
1401 debuglog(("Got command on latcp socket: %d\n", fd));
1402
1403 if (!latcp_circuits[fd]->do_command())
1404 {
1405 // Mark the FD for removal
1406 deleted_session s(LATCP_SOCKET, 0, 0, fd);
1407 dead_session_list.push_back(s);
1408 }
1409 }
1410
1411 // Read a request from LLOGIN
read_llogin(int fd)1412 void LATServer::read_llogin(int fd)
1413 {
1414 debuglog(("Got command on llogin socket: %d\n", fd));
1415
1416 if (!latcp_circuits[fd]->do_command())
1417 {
1418 // Mark the FD for removal
1419 deleted_session s(LLOGIN_SOCKET, 0, 0, fd);
1420 dead_session_list.push_back(s);
1421 }
1422 }
1423
delete_entry(deleted_session & dsl)1424 void LATServer::delete_entry(deleted_session &dsl)
1425 {
1426 switch (dsl.get_type())
1427 {
1428 case INACTIVE:
1429 break; // do nothing;
1430
1431 case LAT_SOCKET:
1432 case LATCP_RENDEZVOUS:
1433 case LLOGIN_RENDEZVOUS:
1434 // These never get deleted
1435 break;
1436
1437 case LATCP_SOCKET:
1438 case LLOGIN_SOCKET:
1439 remove_fd(dsl.get_fd());
1440 close(dsl.get_fd());
1441 delete latcp_circuits[dsl.get_fd()];
1442 latcp_circuits.erase(dsl.get_fd());
1443 break;
1444
1445 case LOCAL_PTY:
1446 case DISABLED_PTY:
1447 remove_fd(dsl.get_fd());
1448 if (connections[dsl.get_conn()])
1449 connections[dsl.get_conn()]->remove_session(dsl.get_id());
1450 break;
1451
1452 default:
1453 debuglog(("Unknown socket type: %d\n", dsl.get_type()));
1454 break;
1455 }
1456 }
1457
process_data(fdinfo & fdi)1458 void LATServer::process_data(fdinfo &fdi)
1459 {
1460 switch (fdi.get_type())
1461 {
1462 case INACTIVE:
1463 case DISABLED_PTY:
1464 break; // do nothing;
1465
1466 case LOCAL_PTY:
1467 fdi.get_localport()->do_read();
1468 break;
1469
1470 case LAT_SOCKET:
1471 read_lat(fdi.get_fd());
1472 break;
1473
1474 case LATCP_RENDEZVOUS:
1475 accept_latcp(fdi.get_fd());
1476 break;
1477
1478 case LLOGIN_RENDEZVOUS:
1479 accept_llogin(fdi.get_fd());
1480 break;
1481
1482 case LATCP_SOCKET:
1483 read_latcp(fdi.get_fd());
1484 break;
1485
1486 case LLOGIN_SOCKET:
1487 read_llogin(fdi.get_fd());
1488 break;
1489 }
1490 }
1491
1492 // Send a circuit disconnect with error code
send_connect_error(int reason,LAT_Header * msg,int interface,unsigned char * macaddr)1493 void LATServer::send_connect_error(int reason, LAT_Header *msg, int interface,
1494 unsigned char *macaddr)
1495 {
1496 unsigned char buf[1600];
1497 LAT_Header *header = (LAT_Header *)buf;
1498 int ptr=sizeof(LAT_Header);
1499
1500 memset(buf, 0, sizeof(buf));
1501
1502 header->cmd = LAT_CCMD_DISCON;
1503 header->num_slots = 0;
1504 header->local_connid = 0; // Servers expect this to be clear
1505 header->remote_connid = msg->local_connid;
1506 header->sequence_number = msg->sequence_number;
1507 header->ack_number = msg->ack_number;
1508 buf[ptr++] = reason;
1509 send_message(buf, ptr, interface, macaddr);
1510 }
1511
1512 // Shutdown by latcp
Shutdown()1513 void LATServer::Shutdown()
1514 {
1515 // Shutdown all the connections first
1516 for (int i=1; i<MAX_CONNECTIONS; i++)
1517 {
1518 if (connections[i])
1519 dead_connection_list.push_back(i);
1520 }
1521
1522 // Exit the main loop.
1523 do_shutdown = true;
1524 }
1525
1526 // Return true if 'name' is a local service
is_local_service(char * name)1527 bool LATServer::is_local_service(char *name)
1528 {
1529 // Look for it.
1530 std::list<serviceinfo>::iterator sii;
1531 sii = find(servicelist.begin(), servicelist.end(), name);
1532 if (sii != servicelist.end()) return true;
1533
1534 return false;
1535 }
1536
1537 // Return the command info for a service
get_service_info(char * name,std::string & cmd,int & maxcon,int & curcon,uid_t & uid,gid_t & gid)1538 int LATServer::get_service_info(char *name, std::string &cmd, int &maxcon, int &curcon, uid_t &uid, gid_t &gid)
1539 {
1540 // Look for it.
1541 std::list<serviceinfo>::iterator sii;
1542 sii = find(servicelist.begin(), servicelist.end(), name);
1543 if (sii != servicelist.end())
1544 {
1545 cmd = sii->get_command();
1546 maxcon = sii->get_max_connections();
1547 curcon = sii->get_cur_connections();
1548 uid = sii->get_uid();
1549 gid = sii->get_gid();
1550
1551 return 0;
1552 }
1553
1554 return -1;
1555 }
1556
1557 // Add a new service from latcp
add_service(char * name,char * ident,char * command,int max_conn,uid_t uid,gid_t gid,int _rating,bool _static_rating)1558 bool LATServer::add_service(char *name, char *ident, char *command, int max_conn,
1559 uid_t uid, gid_t gid, int _rating, bool _static_rating)
1560 {
1561 // Look for it.
1562 std::list<serviceinfo>::iterator sii;
1563 sii = find(servicelist.begin(), servicelist.end(), name);
1564 if (sii != servicelist.end()) return false; // Already exists
1565
1566 // if rating is 0 then use the node default.
1567 if (!_rating) _rating = rating;
1568
1569 servicelist.push_back(serviceinfo(name,
1570 _rating,
1571 _static_rating,
1572 ident,
1573 max_conn,
1574 command,
1575 uid, gid));
1576
1577 // Resend the announcement message.
1578 send_service_announcement(-1);
1579
1580 return true;
1581 }
1582
1583
1584 // Change the rating of a service
set_rating(char * name,int _rating,bool _static_rating)1585 bool LATServer::set_rating(char *name, int _rating, bool _static_rating)
1586 {
1587 // Look for it.
1588 std::list<serviceinfo>::iterator sii;
1589 sii = find(servicelist.begin(), servicelist.end(), name);
1590 if (sii == servicelist.end()) return false; // Not found it
1591
1592 sii->set_rating(_rating, _static_rating);
1593
1594 // Resend the announcement message.
1595 send_service_announcement(-1);
1596 return true;
1597 }
1598
1599 // Change the ident of a service
set_ident(char * name,char * ident)1600 bool LATServer::set_ident(char *name, char *ident)
1601 {
1602 // Look for it.
1603 std::list<serviceinfo>::iterator sii;
1604 sii = find(servicelist.begin(), servicelist.end(), name);
1605 if (sii == servicelist.end()) return false; // Not found it
1606
1607 debuglog(("Setting ident for %s to '%s'\n", name, ident));
1608
1609 sii->set_ident(ident);
1610
1611 // Resend the announcement message.
1612 send_service_announcement(-1);
1613 return true;
1614 }
1615
1616
1617 // Remove reverse-LAT port via latcp
remove_port(char * name)1618 bool LATServer::remove_port(char *name)
1619 {
1620 debuglog(("remove port %s\n", name));
1621
1622 // Search for it.
1623 std::list<LocalPort>::iterator p(portlist.begin());
1624 for (; p != portlist.end(); p++)
1625 {
1626 if (strcmp(p->get_devname().c_str(), name) == 0)
1627 {
1628 p->close_and_delete();
1629 portlist.erase(p);
1630 return true;
1631 }
1632
1633 }
1634 return false;
1635 }
1636
1637
1638
1639 // Remove service via latcp
remove_service(char * name)1640 bool LATServer::remove_service(char *name)
1641 {
1642 // Only add the service if it does not already exist.
1643 std::list<serviceinfo>::iterator sii;
1644 sii = find(servicelist.begin(), servicelist.end(), name);
1645 if (sii == servicelist.end()) return false; // Does not exist
1646
1647 servicelist.erase(sii);
1648
1649 // This is overkill but it gets rid of the service in the known
1650 // services table.
1651 LATServices::Instance()->remove_node(std::string((char*)get_local_node()));
1652
1653 // Resend the announcement message -- this will re-add our node
1654 // services back into the known services list.
1655 send_service_announcement(-1);
1656
1657 return true;
1658 }
1659
1660 // Change the multicast timer
set_multicast(int newtime)1661 void LATServer::set_multicast(int newtime)
1662 {
1663 if (newtime)
1664 {
1665 multicast_timer = newtime;
1666 alarm(newtime);
1667 }
1668 }
1669
1670 // Change the node name
set_nodename(unsigned char * name)1671 void LATServer::set_nodename(unsigned char *name)
1672 {
1673 debuglog(("New node name is %s\n", name));
1674
1675 // Remove all existing node services
1676 LATServices::Instance()->remove_node(std::string((char*)get_local_node()));
1677
1678 // Set the new name
1679 strcpy((char *)local_name, (char *)name);
1680
1681 // Resend the announcement message -- this will re-add our node
1682 // services back into the known services list.
1683 send_service_announcement(-1);
1684
1685 }
1686
1687 // Start sending service announcements
unlock()1688 void LATServer::unlock()
1689 {
1690 sig_blk_t _block(SIGALRM);
1691 locked = false;
1692 alarm_signal(SIGALRM);
1693 }
1694
1695 // Generic make_connection code for llogin & port sessions.
make_connection(int fd,const char * service,const char * rnode,const char * port,const char * localport,const char * password,bool queued)1696 int LATServer::make_connection(int fd, const char *service, const char *rnode, const char *port,
1697 const char *localport, const char *password, bool queued)
1698 {
1699 unsigned char macaddr[6];
1700 std::string servicenode;
1701 int this_int;
1702 char node[255];
1703
1704 // Take a local copy of the node so we can overwrite it.
1705 strcpy(node, rnode);
1706
1707 // If no node was specified then use the highest rated one
1708 if (node[0] == '\0')
1709 {
1710 debuglog(("make_connection : no node, use highest\n"));
1711 if (!LATServices::Instance()->get_highest(std::string((char*)service),
1712 servicenode, macaddr,
1713 &this_int))
1714 {
1715 debuglog(("Can't find service %s\n", service));
1716 return -2; // Never eard of it!
1717 }
1718 strcpy((char *)node, servicenode.c_str());
1719 }
1720 else
1721 {
1722 debuglog(("make_connection : node : %s\n", node));
1723 // Try to find the node
1724 if (!LATServices::Instance()->get_node(std::string((char*)service),
1725 std::string((char*)node), macaddr,
1726 &this_int))
1727 {
1728 debuglog(("Can't find node %s in service\n", node, service));
1729
1730 return -2;
1731 }
1732 }
1733
1734 // Look for a connection that's already in use for this node, unless we
1735 // are queued in which case we need to allocate a new connection for
1736 // initiating the connection and receiving status requests on.
1737 int connid = -1;
1738 if (!queued) connid = find_connection_by_node(node);
1739 if (connid == -1)
1740 {
1741 // None: create a new one
1742 connid = get_next_connection_number();
1743 connections[connid] = new LATConnection(connid,
1744 (char *)service,
1745 (char *)port,
1746 (char *)localport,
1747 (char *)node,
1748 queued,
1749 false);
1750 }
1751
1752 return connid;
1753 }
1754
1755
make_llogin_connection(int fd,const char * service,const char * rnode,const char * port,const char * localport,const char * password,bool queued)1756 int LATServer::make_llogin_connection(int fd, const char *service, const char *rnode, const char *port,
1757 const char *localport, const char *password, bool queued)
1758 {
1759 int ret;
1760 int connid;
1761
1762 connid = make_connection(fd, service, rnode, port, localport, password, queued);
1763 if (connid < 0)
1764 return connid;
1765
1766 debuglog(("lloginSession for %s has connid %d\n", service, connid));
1767
1768 ret = connections[connid]->create_llogin_session(fd, service, port, localport, password);
1769
1770 // Remove LLOGIN socket from the list as it's now been
1771 // added as a PTY (honest!)
1772 deleted_session s(LLOGIN_SOCKET, 0, 0, fd);
1773 dead_session_list.push_back(s);
1774
1775 return ret;
1776 }
1777
1778
1779 // Called when activity is detected on a LocalPort - we connect it
1780 // to the service.
make_port_connection(int fd,LocalPort * lport,const char * service,const char * rnode,const char * port,const char * localport,const char * password,bool queued)1781 int LATServer::make_port_connection(int fd, LocalPort *lport,
1782 const char *service, const char *rnode,
1783 const char *port,
1784 const char *localport,
1785 const char *password,
1786 bool queued)
1787 {
1788 int ret;
1789 int connid;
1790 debuglog(("LATServer::make_port_connection : fd %d, lport '0x%X', service '%s', rnode '%s', port '%s', localport '%s', pwd '%s'\n",
1791 fd, lport, service, rnode, port, localport, password));
1792
1793 connid = make_connection(fd, service, rnode, port, localport, password, queued);
1794 if (connid < 0)
1795 return connid;
1796
1797 debuglog(("localport for %s has connid %d\n", service, connid));
1798
1799 ret = connections[connid]->create_localport_session(fd, lport, service,
1800 port, localport, password);
1801
1802 return ret;
1803 }
1804
1805
1806 // Called from latcp to create a /dev/lat/ port
1807 // Here we simply add it to a lookaside list and wait
1808 // for it to be activated by a user.
create_local_port(unsigned char * service,unsigned char * portname,unsigned char * devname,unsigned char * remnode,bool queued,bool clean,unsigned char * password)1809 int LATServer::create_local_port(unsigned char *service,
1810 unsigned char *portname,
1811 unsigned char *devname,
1812 unsigned char *remnode,
1813 bool queued,
1814 bool clean,
1815 unsigned char *password)
1816 {
1817 debuglog(("Server::create_local_port: %s\n", devname));
1818
1819 // Don't create it if it already exists.
1820 std::list<LocalPort>::iterator i(portlist.begin());
1821 for (; i != portlist.end(); i++)
1822 {
1823 if (strcmp(i->get_devname().c_str(), (char *)devname) == 0)
1824 {
1825 return 1; // already in use
1826 }
1827 }
1828
1829 portlist.push_back(LocalPort(service, portname, devname, remnode, queued, clean, password));
1830
1831 // Find the actual port in the list and start it up, this is because
1832 // the STL containers hold actual objects rather then pointers
1833 std::list<LocalPort>::iterator p(portlist.begin());
1834 for (; p != portlist.end(); p++)
1835 {
1836 if (strcmp(p->get_devname().c_str(), (char *)devname) == 0)
1837 {
1838 p->init_port();
1839 break;
1840 }
1841 }
1842
1843 return 0;
1844 }
1845
1846
1847 // Make this as much like VMS LATCP SHOW NODE as possible.
show_characteristics(bool verbose,std::ostringstream & output)1848 bool LATServer::show_characteristics(bool verbose, std::ostringstream &output)
1849 {
1850 output <<std::endl;
1851 output.setf(std::ios::left, std::ios::adjustfield);
1852
1853 output << "Node Name: ";
1854 output.width(15);
1855 output << get_local_node() << " " << " LAT Protocol Version: " << LAT_VERSION << "." << LAT_VERSION_ECO << std::endl;
1856 output.setf(std::ios::right, std::ios::adjustfield);
1857 output << "Node State: On " << " LATD Version: " << VERSION << std::endl;
1858 output << "Node Ident: " << greeting << std::endl;
1859 output << std::endl;
1860
1861 output << "Service Responder : " << (responder?"Enabled":"Disabled") << std::endl;
1862 output << "Interfaces : ";
1863 for (int i=0; i<num_interfaces; i++)
1864 {
1865 output << iface->ifname(interface_num[i]) << " ";
1866 }
1867 output << std::endl << std::endl;
1868
1869 output << "Circuit Timer (msec): " << std::setw(6) << circuit_timer*10 << " Keepalive Timer (sec): " << std::setw(6) << keepalive_timer << std::endl;
1870 output << "Retransmit Limit: " << std::setw(6) << retransmit_limit << std::endl;
1871 output << "Multicast Timer (sec):" << std::setw(6) << multicast_timer << std::endl;
1872 output << std::endl;
1873
1874 // Show groups
1875 output << "User Groups: ";
1876 print_bitmap(output, true, user_groups);
1877 output << "Service Groups: ";
1878 print_bitmap(output, groups_set, groups);
1879 output << std::endl;
1880
1881 // Show services we are accepting for.
1882 output << "Service Name Status Rating Identification" << std::endl;
1883 std::list<serviceinfo>::iterator i(servicelist.begin());
1884 for (; i != servicelist.end(); i++)
1885 {
1886 output.width(15);
1887 output.setf(std::ios::left, std::ios::adjustfield);
1888 output << i->get_name().c_str();
1889 output.setf(std::ios::right, std::ios::adjustfield);
1890 output << "Enabled" << std::setw(6) << i->get_rating() <<
1891 (i->get_static()?" ":" D ") << i->get_id() << std::endl;
1892 }
1893
1894 output << std::endl << "Port Service Node Remote Port Queued" << std::endl;
1895
1896 // Show allocated ports
1897 std::list<LocalPort>::iterator p(portlist.begin());
1898 for (; p != portlist.end(); p++)
1899 {
1900 p->show_info(verbose, output);
1901 }
1902
1903 // NUL-terminate it.
1904 output << std::endl << std::ends;
1905
1906 return true;
1907 }
1908
show_nodes(bool verbose,std::ostringstream & output)1909 bool LATServer::show_nodes(bool verbose, std::ostringstream &output)
1910 {
1911 return LATServices::Instance()->list_dummy_nodes(verbose, output);
1912 }
1913
1914 // Return a number for a new connection
get_next_connection_number()1915 int LATServer::get_next_connection_number()
1916 {
1917 int i;
1918 for (i=next_connection; i < MAX_CONNECTIONS; i++)
1919 {
1920 if (!connections[i])
1921 {
1922 next_connection = i+1;
1923 return i;
1924 }
1925 }
1926
1927 // Didn't find a slot here - try from the start
1928 for (i=1; i < next_connection; i++)
1929 {
1930 if (!connections[i])
1931 {
1932 next_connection = i+1;
1933 return i;
1934 }
1935 }
1936 return -1;
1937 }
1938
set_servergroups(unsigned char * bitmap)1939 int LATServer::set_servergroups(unsigned char *bitmap)
1940 {
1941 // Assume all unset if this is the first mention of groups
1942 if (!groups_set)
1943 {
1944 memset(groups, 0, 32);
1945 user_groups[0] = 1; // But enable group 0
1946 }
1947 groups_set = true;
1948
1949 for (int i=0; i<32; i++)
1950 {
1951 groups[i] |= bitmap[i];
1952 }
1953 return true;
1954 }
1955
unset_servergroups(unsigned char * bitmap)1956 int LATServer::unset_servergroups(unsigned char *bitmap)
1957 {
1958 // Assume all set if this is the first mention of groups
1959 if (!groups_set)
1960 {
1961 memset(groups, 0xFF, 32);
1962 }
1963 groups_set = true;
1964
1965 for (int i=0; i<32; i++)
1966 {
1967 groups[i] &= ~bitmap[i];
1968 }
1969 return true;
1970 }
1971
set_usergroups(unsigned char * bitmap)1972 int LATServer::set_usergroups(unsigned char *bitmap)
1973 {
1974 for (int i=0; i<32; i++)
1975 {
1976 user_groups[i] |= bitmap[i];
1977 }
1978 return true;
1979 }
1980
unset_usergroups(unsigned char * bitmap)1981 int LATServer::unset_usergroups(unsigned char *bitmap)
1982 {
1983 for (int i=0; i<32; i++)
1984 {
1985 user_groups[i] &= ~bitmap[i];
1986 }
1987 return true;
1988 }
1989
1990 // Look for a connection for this node name, if not found then
1991 // return -1
find_connection_by_node(const char * node)1992 int LATServer::find_connection_by_node(const char *node)
1993 {
1994 debuglog(("Looking for connection to node %s\n", node));
1995 for (int i=1; i<MAX_CONNECTIONS; i++)
1996 {
1997 if (connections[i] &&
1998 connections[i]->node_is(node) &&
1999 connections[i]->num_clients() < LATConnection::MAX_SESSIONS-1)
2000 {
2001 debuglog(("Reusing connection for node %s\n", node));
2002 return i;
2003 }
2004 }
2005 return -1;
2006 }
2007
2008 // Print a groups bitmap
2009 // TODO: print x-y format like we accept in latcp.
print_bitmap(std::ostringstream & output,bool isset,unsigned char * bitmap)2010 void LATServer::print_bitmap(std::ostringstream &output, bool isset, unsigned char *bitmap)
2011 {
2012 if (!isset)
2013 {
2014 output << "0" << std::endl;
2015 return;
2016 }
2017
2018 bool printed = false;
2019
2020 for (int i=0; i<32; i++) // Show bytes
2021 {
2022 unsigned char thebyte = bitmap[i];
2023
2024 for (int j=0; j<8; j++) // Bits in the byte
2025 {
2026 if (thebyte&1)
2027 {
2028 if (printed) output << ",";
2029 printed = true;
2030 output << i*8+j;
2031 }
2032 thebyte = thebyte>>1;
2033 }
2034 }
2035 output << std::endl;
2036 }
2037
2038 LATServer *LATServer::instance = NULL;
2039 unsigned char LATServer::greeting[255] = {'\0'};
2040