
#include<stdio.h>
#include<netinet/in.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#include<unistd.h>

#include<pthread.h>
#include"sitar.h"
#include"sitar_scan.h"
#include<almemsys/almemsys.h>
#include"jpreturn.h"



/* ------ SCAN PORT --------- */
int scan_port(private_data_t *pd)
{
int st;
int ret = -1;
int inA = 0;
int inB = 0;
int out = 1;
int by = 100; // ICMPのしきい値が1の場合、10msec (0.1秒)

st = 0;

if((self_memcmp(pd->sb.ch_prot, "HOST")) == 0){
   pd->sb.ch_info = scan_host(pd->sb.ch_com, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot, "SNTP")) == 0){
   pd->sb.ch_info = scan_sntp_connect(123, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot, "ICMP")) == 0){

   pd->sb.ch_info=scan_icmp(pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret, by); // 1回め
   usleep(1000000);
   pd->sb.ch_info=scan_icmp(pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret, by); // 2回め

   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"URL")) == 0){
   pd->sb.ch_info=scan_url_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret, 0);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"GET")) == 0){
   pd->sb.ch_info=scan_url_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret, 1);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"SSL")) == 0){
   //  1209600 = 2週間の秒　証明証が安全に更新出来る時間
   time_t lim;
   if(0 <= ch_int2(pd->sb.ch_com)){
      lim = (86400 * strtol(pd->sb.ch_com, (char **)NULL, 10));
      }
   else{
      lim = 1209600;
      }
   #ifdef SSL_BUG
   printf("SSL_BUG: scan_ssl_connect(x509): limit time = %ld\n", lim);
   #endif

   pd->sb.ch_info=scan_ssl_command(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, lim, &ret, pd->sb.ch_plai);

   if(0 == (int)strlen(pd->sb.ch_info)){
      if(ret > -1){
         pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d host_data=%s: %s\n", pd->sb.port, pd->sb.ch_host, HTTPS_1);
         }
      else{
         pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d host_data=%s: %s\n", pd->sb.port, pd->sb.ch_host, HTTPS_2);
         }
      }
   #ifdef SSL_BUG
   printf("SSL_BUG: scan_ssl_connect(): %d, %s, <%s>, %d, %d, %d, %s\n"
     ,pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, lim, ret, pd->sb.ch_plai);
   #endif
   }



else if((self_memcmp(pd->sb.ch_prot,"MYSQL")) == 0){

   pd->sb.ch_info = db_data_delim(pd->sb.ch_info, pd->sb.ch_host, pd, &ret);

   if(ret > -1){

      if(pd->db.port == 0){
         pd->db.port = pd->sb.port;
         }
      if(pd->db.timeout == 0){
         pd->db.timeout = pd->sb.timeout;
         }

      pd->sb.ch_info = scan_mysql_command(pd->sb.ch_info,
                         pd->sb.ch_com, pd->db.server, pd->db.username, pd->db.passwd,
                         pd->db.database, pd->db.port, pd->db.timeout, &ret, pd->sb.ch_plai);

      if(0 == (int)strlen(pd->sb.ch_info)){
         if(ret > -1){
            pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
               pd->db.port,pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, MYSQL_1);
            }
         else{
            pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
               pd->db.port, pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, MYSQL_2);
            }

         }
      #ifdef MYSQL_BUG
      printf("port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
         pd->db.port, pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, MYSQL_2);
      #endif
      }

   db_malloc_null(pd);
   }





else if((self_memcmp(pd->sb.ch_prot,"PGSQL")) == 0){

   pd->sb.ch_info = db_data_delim(pd->sb.ch_info, pd->sb.ch_host, pd, &ret);

   if(ret > -1){

      if(pd->db.port == 0){
         pd->db.port = pd->sb.port;
         }
      if(pd->db.timeout == 0){
         pd->db.timeout = pd->sb.timeout;
         }

      pd->sb.ch_info = scan_psql_command(pd->sb.ch_info,
                         pd->sb.ch_com, pd->db.server, pd->db.username, pd->db.passwd,
                         pd->db.database, pd->db.port, pd->db.timeout, &ret, pd->sb.ch_plai);

      if(0 == (int)strlen(pd->sb.ch_info)){
         if(ret > -1){
            pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
               pd->db.port,pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, PGSQL_1);
            }
         else{
            pd->sb.ch_info=safe_sprintf(pd->sb.ch_info, BUF_MAX,"port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
               pd->db.port, pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, PGSQL_2);
            }

         }
      #ifdef PGSQL_BUG
      printf("port=%d: pass=%s: user=%s: db=%s: Query=%s: %s\n",
          pd->db.port,pd->db.passwd, pd->db.username, pd->db.database, pd->sb.ch_com, PGSQL_1);
      #endif
      }

   db_malloc_null(pd);
   }




else if((self_memcmp(pd->sb.ch_prot,"SMTP")) == 0){
   pd->sb.ch_info = scan_smtp_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info,pd->sb.timeout,&ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"FTP")) == 0){
   pd->sb.ch_info = scan_stat_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, "220", 3, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"POP")) == 0){
   pd->sb.ch_info = scan_stat_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, "+OK", 3, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"SSH")) == 0){
   pd->sb.ch_info = scan_stat_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, "SSH", 3, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot,"DHW")) == 0){
   pd->sb.ch_info = scan_dhw_connect(pd->sb.ch_com, pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout,&ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot, "TCP")) == 0){
   pd->sb.ch_info=scan_tcp_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &ret);
   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else if((self_memcmp(pd->sb.ch_prot, "UDP")) == 0){

// info_swap = scan_icmp(pd->sb.ch_host, info_swap, pd->sb.timeout, &inA, by); // 1回め
   pd->sb.ch_info = scan_icmp(pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &inA, by); // 1回め
   usleep(1000000);
// info_swap = scan_icmp(pd->sb.ch_host, info_swap, pd->sb.timeout, &inA, by); // 2回め
   pd->sb.ch_info = scan_icmp(pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &inA, by); // 2回め

   pd->sb.ch_info = scan_udp_connect(pd->sb.port, pd->sb.ch_host, pd->sb.ch_info, pd->sb.timeout, &inB);

   if(inA == 0 && inB == 0){
      ret = 0;
      }

   else if(inA != 0 && inB == 0){
      ret = -3;
      #ifdef SCAN_PORT_DEBUG
      fprintf(stderr,"SCAN_PORT: scan_port(): %s non icmp support or not server\n", pd->sb.ch_host);
      #endif
//    pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX, "%s %s. ", pd->sb.ch_host, info_swap);
      pd->sb.ch_info = safe_sprintf(pd->sb.ch_info, BUF_MAX, "%s %s. ", pd->sb.ch_host, "non icmp suppot or not server.");
      }

   else if(inA != 0 && inB != 0){
      ret = -2;
      #ifdef SCAN_PORT_DEBUG
      fprintf(stderr,"SCAN_PORT: scan_port(): %s is not server\n", pd->sb.ch_host);
      #endif
      }

   else if(inA == 0 && inB != 0){
      ret = -1;
      #ifdef SCAN_PORT_DEBUG
      fprintf(stderr,"SCAN_PORT: scan_port(): %s is icmp support ok. bat <port=%d> is not open\n",
      pd->sb.ch_host, pd->sb.port);
      #endif
      }

   else{
      ret = -1;
      #ifdef SCAN_PORT_DEBUG
      fprintf(stderr,"SCAN_PORT: scan_port(): %s <port=%d> not support ???\n",
      pd->sb.ch_host, pd->sb.port);
      #endif
      }

   if(0 == (int)strlen(pd->sb.ch_info)){
      pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"Information is a no bur error.\n",BUF_MAX);
      }
   }

else{
   ret = -1;
   pd->sb.ch_info=safe_memcpy(pd->sb.ch_info,"not support protocoll.\n",BUF_MAX);
   }



// テストとログモードの処理
if(0 == self_memcmp(pd->sb.ch_plai, "4")){
   out = 4;
   #ifdef SCAN_PORT_DEBUG
   printf("SCAN_PORT: scan_port(): port chack out = %d\n", out);
   #endif
   if(2 > strlen(pd->sb.ch_info)){
      pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, COM_3, BUF_MAX );
      }
   ret = -1;
   }
else if(0 == self_memcmp(pd->sb.ch_plai, "11")){
   if(2 > strlen(pd->sb.ch_info)){
      pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, COM_4, BUF_MAX );
      }
   #ifdef SCAN_PORT_DEBUG
   printf("SCAN_PORT: scan_port(): plai = %s ret = %d\n", pd->sb.ch_plai, ret);
   #endif
   if(ret == -1){
      pd->sb.ch_plai = safe_memcpy(pd->sb.ch_plai, "1", BUF_MAX);
      }
   ret = -1;
   }
else if(0 == self_memcmp(pd->sb.ch_plai, "12")){
   if(2 > strlen(pd->sb.ch_info)){
      pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, COM_4, BUF_MAX );
      }
   #ifdef SCAN_PORT_DEBUG
   printf("SCAN_PORT: scan_port(): plai = %s ret = %d\n", pd->sb.ch_plai, ret);
   #endif
   if(ret == -1){
      pd->sb.ch_plai = safe_memcpy(pd->sb.ch_plai, "2", BUF_MAX);
      }
   ret = -1;
   }
else if(0 == self_memcmp(pd->sb.ch_plai, "13")){
   if(2 > strlen(pd->sb.ch_info)){
      pd->sb.ch_info = safe_memcpy(pd->sb.ch_info, COM_4, BUF_MAX );
      }
   #ifdef SCAN_PORT_DEBUG
   printf("SCAN_PORT: scan_port(): plai = %s ret = %d\n", pd->sb.ch_plai, ret);
   #endif
   if(ret == -1){
      pd->sb.ch_plai = safe_memcpy(pd->sb.ch_plai, "3", BUF_MAX);
      }
   ret = -1;
   }

// check_statの設定 正か逆かで反転する。
// 監視の正逆の判断 check_stat == 1 はエラー 0は正常
if(ret < 0){

   if(pd->sb.ch_stat[0] == '0'){
      pd->sb.check_stat = 1;
      }
   else if(pd->sb.ch_stat[0] == '1'){
      pd->sb.check_stat = 0;
      }
   }

if(ret >= 0){

   if(pd->sb.ch_stat[0] == '1'){
      pd->sb.check_stat = 1;
      }
   else if(pd->sb.ch_stat[0] == '0'){
      pd->sb.check_stat = 0;
      }
   }

return 0;
}



