1 /*************************************************************/
2 /* FGD.C by Oliver Delise */
4 /* e-mail: delise@mail.isis.de */
5 /* www: http://www.isis.de/members/~odelise/progs/mmx-emu/ */
6 /* ftp: http://www.isis.de/members/~odelise/progs/flightgear */
8 /* Version 0.1-alpha */
9 /* The author of this program offers no waranty at all */
10 /* about the correct execution of this software material. */
11 /* Furthermore, the author can NOT be held responsible for */
12 /* any physical or moral damage caused by the use of this */
15 /* This is a standalone Tool to communicate with any */
16 /* FlightGear System and FGFS-Deamon. */
17 /* This is Open Source Software with some parts */
18 /* shamelessly stolen from others... */
20 /* -> This program will use a TCP port listening on a */
21 /* remote or local host inside the range you give to it. */
22 /* I offer no warranty over the accuracy though :) */
23 /* There are 3 verbose modes: No info, service info, and */
24 /* full info. No info is good of you only want the list */
25 /* of the ports, no more info. The best mode is Full */
26 /* info, as you get error information,etc. The main */
27 /* output is STDOUT, and ALL the errors go to STDERR. */
29 /* History: v0.1pre-alpha: May 25 1999 -> First release */
30 /* v0.1-alpha : Nov 08 1999 */
31 /*************************************************************/
35 #include <sys/socket.h>
36 #include <sys/types.h>
37 #include <netinet/in.h>
42 #include <sys/utsname.h>
48 int maxfd, nready, retval;
50 struct utsname myname;
51 char *fgd_host, *src_host;
54 int verbose, fgd_len_msg;
56 /* List-stuff (doubly-Linked-list) */
60 int i, j, fgd_cnt, fgd_curpos;
65 float sgFGD_COORD[4][4];
68 unsigned char ipadr[16], callsign[16];
69 unsigned char lat[8], lon[8], alt[8], speed[8], roll[8], pitch[8], yaw[8];
70 float latf, lonf, altf, speedf, rollf, pitchf, yawf;
71 float sgFGD_COORD[4][4];
72 struct list_ele *next, *prev;
75 struct list_ele *head, *tail, *act, *test, *incoming; /* fgd_msg; */
77 struct fgd_sock_list {
82 struct fgd_sock_list fgd_cli_list[255];
83 int fgd_known_cli = -1; /* False */
86 /*...Create head and tail of list */
87 void list_init( void) {
88 incoming = (struct list_ele*) malloc(sizeof(struct list_ele));
89 head = (struct list_ele*) malloc(sizeof(struct list_ele));
90 tail = (struct list_ele*) malloc(sizeof(struct list_ele));
91 if (head == NULL || tail == NULL) { printf("Out of memory\n"); exit(1); }
92 /* fixme :Where is the "with foobar do command "
93 head->ipadr = "127.0.0.0";
94 strcpy(head->callsign, "None");
102 /* yaw!. Who the f$%& invented this ;-) */
104 tail->ipadr[0] = 255;
106 head->prev = tail->prev = head;
107 head->next = tail->next = tail;
108 act = head; /* put listpointer to beginning of list */
111 void list_output( void) {
114 void list_search( char name[16]) {
116 if (strcmp(name, head->next->ipadr) <= 0) act = head;
117 else if (strcmp(name, tail->prev->ipadr) > 0) act = tail->prev;
119 int vergleich = strcmp(name, act->ipadr);
121 while (strcmp(name, act->next->ipadr) > 0) {
124 else if (vergleich < 0)
125 while (strcmp(name, act->ipadr) < 0) {
129 while (strcmp(name, act->ipadr) == 0) {
135 void list_insert( char newip[16]) {
136 struct list_ele *new_ele;
138 new_ele = (struct list_ele*) malloc(sizeof(struct list_ele));
139 if (new_ele == NULL) { printf("Out of memory\n"); exit(1); }
140 strcpy(new_ele->ipadr, newip);
141 /* setting default */
142 strcpy(new_ele->callsign, "not assigned");
145 new_ele->next = act->next;
146 act->next->prev = act->next = new_ele;
149 void list_setval( char newip[16]) {
152 strcpy( act->next->callsign, incoming->callsign);
153 act->next->latf = incoming->latf;
154 act->next->lonf = incoming->lonf;
155 act->next->altf = incoming->altf;
156 act->next->speedf = incoming->speedf;
157 act->next->rollf = incoming->rollf;
158 act->next->pitchf = incoming->pitchf;
159 act->next->yawf = incoming->yawf;
160 printf("Callsign %s ", act->next->callsign);
161 printf(" lat: %7.3f lon: %7.3f alt: %7.3f speed: %7.3f roll: %7.3f pitch: %7.3f yaw: %7.3f",
162 act->next->latf, act->next->lonf, act->next->altf, act->next->speedf,
163 act->next->rollf, act->next->pitchf, act->next->yawf);
166 void list_setval_Mat4( char newip[16]) {
169 strcpy( act->next->callsign, incoming->callsign);
172 act->next->sgFGD_COORD[i][j] = incoming->sgFGD_COORD[i][j];
173 printf("Callsign %s ", act->next->callsign);
177 void list_clear( char clrip[16]) {
178 struct list_ele *clr_ele;
181 if ( strcmp( clrip, act->next->ipadr))
182 printf("....Name %s nicht vorhanden", clrip);
185 act->next = act->next->next;
186 act->next->prev = act;
192 int list_not_in( char name[16]) {
196 while ((test != tail) && (i==True)) {
197 i = (strcmp(test->ipadr, name) ? True : False);
199 if (verbose != 0) printf("list_not_in : %d\n",i);
214 struct { char *adr, *lon, *lat, *alt;} fgd_client;
217 struct sockaddr_in address;
218 struct sockaddr_in my_address;
220 extern char *sys_errlist[];
222 int current_port = 0;
223 u_short base_port = 0;
224 u_short end_port = 1024;
225 struct hostent *host_info;
226 struct servent *service_info;
230 int main(int argc, char **argv)
233 fprintf(stderr,"Usage: fgd [start port] [end port] [name] <-v or -vv>\n");
238 case 5: if (!strcmp(argv[4],"-v"))
240 else if (!strcmp(argv[4],"-vv"))
242 else { fprintf(stderr,"Usage: fgd [start port] [end port] [name] <-v or -vv>\n");
245 case 4: base_port = (u_short)atoi(argv[1]);
246 end_port = (u_short)atoi(argv[2]);
249 default: fprintf(stderr,"Usage: fgd [start port] [end port] [name] <-v or -vv>\n");
254 bzero((char *)&address, sizeof(address));
255 address.sin_family = AF_INET;
256 if (uname(&myname) == 0) fgd_host = myname.nodename;
257 printf(" I am running as %s on HOST %s\n", fgd_name, fgd_host);
259 if (verbose == 2) printf(" Resolving: %s ->",fgd_host);
260 if (host_info = gethostbyname(fgd_host)) {
261 bcopy(host_info->h_addr, (char *)&address.sin_addr,host_info->h_length);
262 printf(" fgd : ip = %s\n", inet_ntoa( address.sin_addr));
264 if (verbose == 2) printf(" resolved\n");
265 } else if ((address.sin_addr.s_addr = inet_addr(fgd_host)) == INADDR_NONE) {
266 fprintf(stderr,"Could not get %s host entry !\n",argv[1]);
267 printf(" NOT resolved !!!\n");
269 } else if (verbose == 2) printf(" address valid\n");
271 if ((base_port > end_port) || ((short)base_port < 0)) {
272 fprintf(stderr,"Bad port range : start=%d end=%d !\n");
274 } else if (verbose == 2) {
275 printf(" Port range: %d to %d\n",base_port,end_port);
277 printf(" verbose: %d\n",verbose);
278 /* some init stuff */
279 fgd_txt = (char *) malloc(1024);
285 void fgd_init(void) {
287 struct { char *ip, *lon, *lat, *alt;} fg_id;
290 current_port = base_port;
291 while (current_port <= end_port) {
292 sock = socket(PF_INET, SOCK_STREAM, 0);
295 fprintf(stderr, "Error assigning master socket: %s\n",sys_errlist[errno]);
299 address.sin_port = htons(current_port);
300 if (verbose == 2) printf(" address.sin_port : %d\n",htons(address.sin_port));
302 if ( bind(sock, (struct sockaddr *)&address, sizeof(address)) == -1) {
303 printf(" Aiiiieeehh...ADRESS ALSO IN USE...\7hmmm...please check another port\n");
311 FD_SET( sock, &allset);
316 nready = select( sock + 1, &rset, NULL, NULL, &tv);
317 if (FD_ISSET( sock, &rset)) {
318 my_sock = accept( sock, (struct sockaddr *)&address, (int*) sizeof(address));
320 /* reading length of senders' ip */
322 read( my_sock, buff, 1);
323 fgd_ele_len = buff[0];
324 if (verbose == 2) printf("ele_len %d\n", fgd_ele_len);
325 /* reading senders' ip */
326 read( my_sock, &buff, fgd_ele_len);
328 // printf("%d %d %d %d %x %x %x\n", buff[0], buff[1], buff[2], buff[3], &ip, ip, *ip);
329 fgd_client.adr = (char*) inet_ntoa( *ip);
330 src_host = fgd_client.adr;
331 /* reading commando */
332 read( my_sock, &buff, 1);
333 /* closing previous file descriptor of same client, at least we know now
334 that the previous command is finished since it's the same client who
335 again requests something. Maybe I'm to quick and diiirty ;-) */
336 printf("FGD : Using socket #%d\n", my_sock);
337 fgd_known_cli = False;
338 for ( fgd_cnt = 1; fgd_cnt < fgd_cli+1; fgd_cnt++) {
339 printf("FGD : fgd_cnt:%d fgd_cli:%d fgd_client.adr: %s prev.sock:%d fgd_cli_list[fgd_cnt].adr: %s\n",
340 fgd_cnt, fgd_cli, fgd_client.adr,
341 fgd_cli_list[fgd_cnt].prev_sock, fgd_cli_list[fgd_cnt].adr);
342 if ( strcmp( fgd_cli_list[fgd_cnt].adr, fgd_client.adr) == 0) {
343 printf("FGD : In Vergleichsloop. Closing socket: %d\n",
344 fgd_cli_list[fgd_cnt].prev_sock);
345 close( fgd_cli_list[fgd_cnt].prev_sock);
346 fgd_cli_list[fgd_cnt].prev_sock = my_sock;
347 fgd_known_cli = True;
350 if ( fgd_known_cli == False) {
352 fgd_cli_list[fgd_cli].prev_sock = my_sock;
353 strcpy(fgd_cli_list[fgd_cli].adr, fgd_client.adr);
355 printf(" Commando received : %s from Host : %s\n", &buff, src_host);
356 fgd_com = ( (char) buff[0]) - 0x30;
357 printf("%d \n", fgd_com);
359 case 0: printf(" fgd : Identify\n");
360 sprintf( (char*) buff, "FGDLH%s", fgd_name);
361 buff[3] = strlen(fgd_name) + 1; /* Lo, incl.zero */
362 buff[4] = 0; /* Hi, names < 0xff ! */
363 buff[buff[3] + 4] = 0; /* Term.zero */
364 printf(" I am : %s\n", fgd_name);
365 write( my_sock, &buff, buff[3]+5); /* fgd housekeeping ;-) */
368 case 1: printf(" fgd : Register\n");
369 /* reading length of FGFS_host ip */
371 read( my_sock, &buff, 1);
372 fgd_ele_len = (int) &buff;
373 /* reading FGFS_host ip */
374 read( my_sock, &buff, fgd_ele_len);
376 fgd_client.adr = (char*) inet_ntoa( *ip);
377 if (list_not_in(fgd_client.adr) == True) {
378 list_insert(fgd_client.adr);
379 list_search(fgd_client.adr);
380 // strcpy(act->callsign, "None");
381 printf(" Setting default values\n");
382 printf(" IP : %s\n", act->next->ipadr);
383 printf(" PILOT : %s\n", act->next->callsign);
385 /* writing answer back to client */
386 sprintf( (char*) buff, "FGDLH%s", fgd_client.adr);
387 buff[3] = strlen(fgd_client.adr) + 1; /* Lo, incl.zero */
388 buff[4] = 0; /* Hi, names < 0xff ! */
389 buff[buff[3] + 4] = 0; /* Term.zero */
390 write( my_sock, &buff, buff[3]+5); /* fgd housekeeping ;-) */
393 case 2: printf(" fgd : Show Registered\n");
394 sprintf( (char*) buff, "FGD");
395 // buff[3] = buff[4] = 0;
399 while (test != tail) {
400 printf(" IP : %s\n", test->ipadr);
402 fgd_ele_len = strlen(test->ipadr) + 1;
403 // printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
404 buff[fgd_curpos] = fgd_ele_len;
406 bcopy(test->ipadr, &buff[fgd_curpos], fgd_ele_len);
407 fgd_curpos += fgd_ele_len;
408 //buff[fgd_curpos] = 0;
411 if (fgd_cnt == 0) fgd_curpos--;
412 buff[3] = fgd_curpos & 0xff;
413 buff[4] = fgd_curpos >> 8;
415 write( my_sock, &buff, fgd_curpos);
418 case 3: printf(" fgd : Send MSG\n");
421 case 4: printf(" fgd : Send MSG to all\n");
424 case 5: printf(" fgd : Get DATA from client\n");
425 read( my_sock, &buff, 1);
426 fgd_ele_len = buff[0];
427 read( my_sock, &buff, fgd_ele_len);
429 fgd_client.adr = (char*) inet_ntoa( *ip);
430 printf(" IP : %s\n", fgd_client.adr);
431 if (verbose != 0) printf("not_in (CASE) : %d\n", list_not_in(fgd_client.adr));
432 if (list_not_in(fgd_client.adr) == False) {
433 printf(" Checkpoint\n");
434 read( my_sock, &buff, 1);
435 printf(" Checkpoint 1\n");
436 fgd_ele_len = buff[0];
437 read( my_sock, &buff, fgd_ele_len);
438 incoming->callsign[fgd_ele_len] = 0;
439 bcopy( &buff, incoming->callsign, fgd_ele_len);
441 read( my_sock, &buff, 56);
442 sscanf( buff," %7f %7f %7f %7f %7f %7f %7f", &incoming->latf, &incoming->lonf,
443 &incoming->altf, &incoming->speedf, &incoming->rollf,
444 &incoming->pitchf, &incoming->yawf);
445 printf(" lat :%7.3f\n lon :%7.3f\n alt :%7.3f\n speed :%7.3f\n roll :%7.3f\n pitch :%7.3f\n yaw :%7.3f\n",
446 incoming->latf, incoming->lonf, incoming->altf, incoming->speedf,
447 incoming->rollf, incoming->pitchf, incoming->yawf);
448 list_setval(fgd_client.adr);
450 else strcpy( fgd_client.adr, "UNKNOWN");
451 /* writing answer back to client */
452 sprintf( (char*) buff, "%s %s", "FGD", fgd_client.adr);
453 buff[3] = strlen(fgd_client.adr);
454 printf(" IP : %s\n", fgd_client.adr);
455 write( my_sock, &buff, buff[3]+4);
458 case 17: printf(" fgd : Get Mat4 DATA from client\n");
459 read( my_sock, &buff, 1);
460 fgd_ele_len = buff[0];
461 read( my_sock, &buff, fgd_ele_len);
463 fgd_client.adr = (char*) inet_ntoa( *ip);
464 printf(" IP : %s\n", fgd_client.adr);
465 if (verbose != 0) printf("not_in (CASE) : %d\n", list_not_in(fgd_client.adr));
466 if (list_not_in(fgd_client.adr) == False) {
467 printf(" Checkpoint\n");
468 read( my_sock, &buff, 1);
469 printf(" Checkpoint 1\n");
470 fgd_ele_len = buff[0];
471 read( my_sock, &buff, fgd_ele_len);
472 incoming->callsign[fgd_ele_len] = 0;
473 bcopy( &buff, incoming->callsign, fgd_ele_len);
475 read( my_sock, &buff, 158);
476 i = sscanf( buff," %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
477 &incoming->sgFGD_COORD[0][0], &incoming->sgFGD_COORD[0][1], &incoming->sgFGD_COORD[0][2], &incoming->sgFGD_COORD[0][3],
478 &incoming->sgFGD_COORD[1][0], &incoming->sgFGD_COORD[1][1], &incoming->sgFGD_COORD[1][2], &incoming->sgFGD_COORD[1][3],
479 &incoming->sgFGD_COORD[2][0], &incoming->sgFGD_COORD[2][1], &incoming->sgFGD_COORD[2][2], &incoming->sgFGD_COORD[2][3],
480 &incoming->sgFGD_COORD[3][0], &incoming->sgFGD_COORD[3][1], &incoming->sgFGD_COORD[3][2], &incoming->sgFGD_COORD[3][3]);
482 // printf(" sscanf input: %d\n",i);
483 printf(" sgMat4: \n%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
484 incoming->sgFGD_COORD[0][0], incoming->sgFGD_COORD[0][1], incoming->sgFGD_COORD[0][2], incoming->sgFGD_COORD[0][3],
485 incoming->sgFGD_COORD[1][0], incoming->sgFGD_COORD[1][1], incoming->sgFGD_COORD[1][2], incoming->sgFGD_COORD[1][3],
486 incoming->sgFGD_COORD[2][0], incoming->sgFGD_COORD[2][1], incoming->sgFGD_COORD[2][2], incoming->sgFGD_COORD[2][3],
487 incoming->sgFGD_COORD[3][0], incoming->sgFGD_COORD[3][1], incoming->sgFGD_COORD[3][2], incoming->sgFGD_COORD[3][3]);
488 list_setval_Mat4(fgd_client.adr);
490 else strcpy( fgd_client.adr, "UNKNOWN");
491 /* writing answer back to client */
492 sprintf( (char*) buff, "FGDLH%s", fgd_client.adr);
493 buff[3] = strlen(fgd_client.adr) + 1;
494 buff[4] = buff[buff[3]+5] = 0;
495 printf(" IP : %s\n", fgd_client.adr);
496 write( my_sock, &buff, buff[3]+5);
499 case 6: printf(" fgd : Send all DATA to client\n");
500 sprintf( (char*) buff, "%s %s", "FGD", fgd_client.adr);
505 while (test != tail) {
506 printf(" IP : %-16s Callsign : %-16s\n", test->ipadr, test->callsign);
509 fgd_ele_len = strlen(test->ipadr);
510 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
511 buff[fgd_curpos] = fgd_ele_len;
513 bcopy(test->ipadr, &buff[fgd_curpos], fgd_ele_len);
514 fgd_curpos = fgd_curpos + fgd_ele_len;
516 fgd_ele_len = strlen(test->callsign);
517 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
518 buff[fgd_curpos] = fgd_ele_len;
520 bcopy(test->callsign, &buff[fgd_curpos], fgd_ele_len);
521 fgd_curpos = fgd_curpos + fgd_ele_len;
522 /* Lat, Lon, Alt, Speed, Roll, Pitch, Yaw
523 hope this sprintf call is not too expensive */
524 sprintf( fgd_txt, " %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f",
525 test->latf, test->lonf, test->altf, test->speedf,
526 test->rollf, test->pitchf, test->yawf);
527 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
528 printf(" Data : %s\n", fgd_txt);
529 bcopy((char *) fgd_txt, &buff[fgd_curpos], 56);
533 if (fgd_cnt == 0) fgd_curpos --;
534 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
535 buff[3] = fgd_curpos;
537 write( my_sock, &buff, fgd_curpos);
540 case 18: printf(" fgd : Send all Mat4 DATA to client\n");
541 sprintf( (char*) buff, "FGDLH");
542 buff[3] = buff[4] = 0;
546 while (test != tail) {
547 printf(" IP : %-16s Callsign : %-16s\n", test->ipadr, test->callsign);
550 fgd_ele_len = strlen(test->ipadr);
551 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
552 buff[fgd_curpos] = fgd_ele_len;
554 bcopy(test->ipadr, &buff[fgd_curpos], fgd_ele_len);
555 fgd_curpos = fgd_curpos + fgd_ele_len;
557 fgd_ele_len = strlen(test->callsign);
558 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
559 buff[fgd_curpos] = fgd_ele_len;
561 bcopy(test->callsign, &buff[fgd_curpos], fgd_ele_len);
562 fgd_curpos = fgd_curpos + fgd_ele_len;
563 /* Lat, Lon, Alt, Speed, Roll, Pitch, Yaw
564 hope this sprintf call is not too expensive */
565 fgd_len_msg = sprintf( fgd_txt, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f",
566 test->sgFGD_COORD[0][0], test->sgFGD_COORD[0][1], test->sgFGD_COORD[0][2], test->sgFGD_COORD[0][3],
567 test->sgFGD_COORD[1][0], test->sgFGD_COORD[1][1], test->sgFGD_COORD[1][2], test->sgFGD_COORD[1][3],
568 test->sgFGD_COORD[2][0], test->sgFGD_COORD[2][1], test->sgFGD_COORD[2][2], test->sgFGD_COORD[2][3],
569 test->sgFGD_COORD[3][0], test->sgFGD_COORD[3][1], test->sgFGD_COORD[3][2], test->sgFGD_COORD[3][3]);
570 fgd_txt[fgd_len_msg] = 0;
571 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
572 printf(" Data : %s\n", fgd_txt);
573 bcopy((char *) fgd_txt, &buff[fgd_curpos], fgd_len_msg+1);
574 fgd_curpos += fgd_len_msg+1;
577 if (fgd_cnt == 0) fgd_curpos -= 1;
578 printf(" ele_len %d curpos %d\n", fgd_ele_len, fgd_curpos);
579 buff[3] = fgd_curpos & 0xff;
580 buff[4] = fgd_curpos / 256;
582 printf("ANZ: %d CURPOS: %d\n", (unsigned char) buff[3] + (unsigned char) buff[4] * 256, fgd_curpos);
583 write( my_sock, &buff, fgd_curpos);
586 case 8: printf(" fgd : Unregister\n");
587 read( my_sock, &buff, 1);
588 fgd_ele_len = (int) &buff;
589 read( my_sock, &buff, fgd_ele_len);
591 fgd_client.adr = (char*) inet_ntoa( *ip);
592 printf(" IP : %s\n", fgd_client.adr);
593 if (verbose != 0) printf("not_in (CASE) : %d\n", list_not_in(fgd_client.adr));
594 if (list_not_in(fgd_client.adr) == -1) {
595 list_clear(fgd_client.adr);
597 else strcpy( fgd_client.adr, "UNKNOWN");
598 /* writing answer back to client */
599 sprintf( (char*) buff, "%s %s", "FGD", fgd_client.adr);
600 buff[3] = strlen(fgd_client.adr);
601 printf(" IP : %s\n", fgd_client.adr);
602 write( my_sock, &buff, buff[3]+4);
605 case 9: printf(" fgd : Shutdown\n");
609 default: printf(" fgd : Huh?...Unknown Command\n");
616 case 0: printf("%d\n",base_port+current_port);
618 case 1: service_info = getservbyport(htons(base_port+current_port),"tcp");
620 printf("%d -> service name unknown\n",base_port+current_port);
622 printf("%d -> %s\n",base_port+current_port,service_info->s_name);
625 case 2: service_info = getservbyport(htons(base_port+current_port),"tcp");
627 printf("Port %d found. Service name unknown\n",base_port+current_port);
629 printf("Port %d found. Service name: %s\n",base_port+current_port,service_info->s_name);
634 } else if (errno == 113) {
635 fprintf(stderr,"No route to host !\n");
638 /* current_port++; */
641 if (verbose == 2) printf("Port scan finished !\n");