port_handle_s *p_port_handle =
__port_manager_get_current_port_handle(manager);
+ g_free(manager->p_hdr_buf);
+ manager->p_hdr_buf = NULL;
+ manager->packet_len = 0;
+
if (!p_port_handle)
return;
p_port_handle->sock = -1;
p_port_handle->sock_io_channel = NULL;
p_port_handle->sock_source_id = 0;
+ g_free(manager->p_hdr_buf);
+ manager->p_hdr_buf = NULL;
+ manager->packet_len = 0;
}
static void __port_manager_deinitialize(port_manager_s *manager)
return 0;
}
+
+static gint __create_raw_sock()
+{
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0,};
+ int on = 1;
+ gint sock = -1;
+
+ sock = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
+ if (sock < 0) {
+ INM_LOGW("socket Failed");
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ INM_LOGE("Could not send with %s", error_buf);
+ close(sock);
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ if (setsockopt(sock, SOL_IP, IP_RECVERR, (char*)&on, sizeof(on)) < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ INM_LOGE("setsock ERCVERR errno[%d]: %s", errno, error_buf);
+ close(sock);
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ return sock;
+}
+
+static int __create_raw_port_handle(port_manager_s *p_port_manager)
+{
+ port_handle_s *p_port_handle = NULL;
+ gint sock = -1;
+ int ret;
+
+ __INM_FUNC_ENTER__;
+
+ p_port_handle = __port_manager_get_current_port_handle(p_port_manager);
+ if (!p_port_handle) {
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ sock = __create_raw_sock();
+ if (sock < 0) {
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ ret = inm_util_create_gio_channel(sock, &p_port_handle->sock_io_channel);
+ if (ret != 0) {
+ INM_LOGI("Failed to create gio channel");
+ close(sock);
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ p_port_handle->sock = sock;
+
+ __INM_FUNC_EXIT__;
+ return 0;
+}
+
+int __raw_sock_port_scan_start(port_manager_s *p_port_manager)
+{
+ if (!p_port_manager)
+ return -1;
+
+ __port_manager_initialize_current_sock(p_port_manager);
+
+ if (__create_raw_port_handle(p_port_manager) < 0)
+ return -1;
+
+ return 0;
+}
+
static inline int __get_target_port(target_manager_s *p_target_manager, port_manager_s *p_port_manager)
{
if (!p_target_manager || !p_port_manager)
return 0;
}
+static unsigned short __checksum(unsigned short *buf, int len)
+{
+ int sum = 0;
+ int left = len;
+ u_short *word = buf;
+ u_short rest = 0;
+ while (left > 1) {
+ sum += *word++;
+ left -= 2;
+ }
+ if (left) {
+ *(u_char *)(&rest) = *(u_char *)word;
+ sum += rest;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+
+ return (unsigned short)(~sum);
+}
+
+static void __set_default_hdr(unsigned char flags,
+ target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager,
+ unsigned char *buf)
+{
+ struct ip *p_ip_hdr;
+ struct tcphdr *p_tcp_hdr;
+ pseudo_hdr_s *p_pseudo_hdr;
+ char dst_ip_addr_str[INET_ADDRSTRLEN] = {0,};
+ struct sockaddr_in *sin;
+
+ __INM_FUNC_ENTER__;
+ if (!buf) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ sin = (struct sockaddr_in *)p_target_manager->p_addr_info_current->ai_addr;
+ inet_ntop(p_target_manager->p_addr_info_current->ai_family,
+ &sin->sin_addr,
+ dst_ip_addr_str,
+ sizeof(dst_ip_addr_str));
+
+ p_ip_hdr = (struct ip*)buf;
+ p_tcp_hdr = (struct tcphdr *)(buf + sizeof(struct ip));
+ p_pseudo_hdr = (pseudo_hdr_s *)((char *)p_tcp_hdr - sizeof(pseudo_hdr_s));
+ p_pseudo_hdr->saddr = inet_addr(p_target_manager->src_addr);
+ p_pseudo_hdr->daddr = inet_addr(dst_ip_addr_str);
+ p_pseudo_hdr->protocol = IPPROTO_TCP;
+ p_pseudo_hdr->tcplength = htons(sizeof(struct tcphdr));
+ memset((char *)p_tcp_hdr, 0, sizeof(struct tcphdr));
+ p_tcp_hdr->th_sport = htons(DEFAULT_SRC_PORT);
+ p_tcp_hdr->th_dport = htons(__get_target_port(p_target_manager, p_port_manager));
+ p_tcp_hdr->th_seq = htons(DEFAULT_SEQ);
+ p_tcp_hdr->th_ack = htons(DEFAULT_ACK_SEQ);
+ p_tcp_hdr->th_off = 5;
+ p_tcp_hdr->th_flags = flags;
+ p_tcp_hdr->window = htons(512);
+ p_tcp_hdr->check = __checksum((unsigned short *)p_pseudo_hdr,
+ sizeof(pseudo_hdr_s) + sizeof(struct tcphdr));
+ memset((char *)p_ip_hdr, 0, sizeof(struct ip));
+ p_ip_hdr->ip_v = 4;
+ p_ip_hdr->ip_hl = 5;
+ p_ip_hdr->ip_p = IPPROTO_TCP;
+ p_ip_hdr->ip_len = 40;
+ p_ip_hdr->ip_id = htons(777);
+ p_ip_hdr->ip_ttl = 60;
+ inet_aton(p_target_manager->src_addr, &(p_ip_hdr->ip_src));
+ inet_aton(dst_ip_addr_str, &(p_ip_hdr->ip_dst));
+ p_ip_hdr->ip_sum = __checksum((unsigned short *)p_ip_hdr, sizeof(struct ip));
+ __INM_FUNC_EXIT__;
+ return;
+}
+
+static int __create_raw_tcp_pkt(unsigned char flags,
+ target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ unsigned char *buf = NULL;
+ int packet_len;
+
+ __INM_FUNC_ENTER__;
+ if (!p_target_manager || !p_port_manager) {
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ packet_len = sizeof(struct ip) + sizeof(struct tcphdr);
+ buf = g_try_malloc0(packet_len);
+ if (!buf) {
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ __set_default_hdr(flags, p_target_manager, p_port_manager, buf);
+
+ g_free(p_port_manager->p_hdr_buf);
+ p_port_manager->p_hdr_buf = buf;
+ p_port_manager->packet_len = packet_len;
+
+ __INM_FUNC_EXIT__;
+ return 0;
+}
+
+static int __send_raw_tcp_pkt(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ port_handle_s *p_port_handle = NULL;
+ struct sockaddr_in address;
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0,};
+ char dst_ip_addr_str[INET_ADDRSTRLEN] = {0,};
+ struct sockaddr_in *sin;
+ ssize_t nsend;
+
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ p_port_handle = __port_manager_get_current_port_handle(p_port_manager);
+ if (!p_port_handle)
+ return -1;
+
+ sin = (struct sockaddr_in *)p_target_manager->p_addr_info_current->ai_addr;
+ inet_ntop(p_target_manager->p_addr_info_current->ai_family,
+ &sin->sin_addr,
+ dst_ip_addr_str,
+ sizeof(dst_ip_addr_str));
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(__get_target_port(p_target_manager, p_port_manager));
+ address.sin_addr.s_addr = inet_addr(dst_ip_addr_str);
+
+ nsend = sendto(p_port_handle->sock,
+ p_port_manager->p_hdr_buf,
+ p_port_manager->packet_len,
+ 0x0,
+ (struct sockaddr *)&address,
+ sizeof(address));
+ if (nsend < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ INM_LOGE("Could not send with %s", error_buf);
+ } else
+ INM_LOGI("%zd sent", nsend);
+
+ return 0;
+}
+
+static int __handle_raw_tcp_packet(unsigned char flags,
+ target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ int ret = 0;
+
+ if (!p_port_manager->p_hdr_buf)
+ ret = __create_raw_tcp_pkt(flags, p_target_manager, p_port_manager);
+ if (ret != 0)
+ return -1;
+
+ if (__send_raw_tcp_pkt(p_target_manager, p_port_manager) < 0)
+ return -1;
+
+ return 0;
+}
+
+int __syn_port_scan_send(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ if (__handle_raw_tcp_packet(TH_SYN, p_target_manager, p_port_manager) < 0) {
+ __port_manager_shutdown_current_sock(p_port_manager);
+ return -1;
+ }
+
+ return 0;
+}
+
+int __ack_port_scan_send(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ if (__handle_raw_tcp_packet(TH_ACK, p_target_manager, p_port_manager) < 0) {
+ __port_manager_shutdown_current_sock(p_port_manager);
+ return -1;
+ }
+
+ return 0;
+}
+
+int __fin_port_scan_send(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ if (__handle_raw_tcp_packet(TH_FIN, p_target_manager, p_port_manager) < 0) {
+ __port_manager_shutdown_current_sock(p_port_manager);
+ return -1;
+ }
+
+ return 0;
+}
+
+int __xmas_port_scan_send(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ if (__handle_raw_tcp_packet(TH_FIN | TH_PUSH | TH_URG,
+ p_target_manager,
+ p_port_manager) < 0) {
+ __port_manager_shutdown_current_sock(p_port_manager);
+ return -1;
+ }
+
+ return 0;
+}
+
+int __null_port_scan_send(target_manager_s *p_target_manager,
+ port_manager_s *p_port_manager)
+{
+ if (!p_target_manager || !p_port_manager)
+ return -1;
+
+ if (__handle_raw_tcp_packet(0, p_target_manager, p_port_manager) < 0) {
+ __port_manager_shutdown_current_sock(p_port_manager);
+ return -1;
+ }
+
+ return 0;
+}
+
static void __handle_sock_nval_hup(port_manager_s *p_port_manager, result_manager_s *p_result_manager)
{
if (!p_port_manager || !p_result_manager)
return;
}
+static void __handle_pkt(port_scan_received_result *result,
+ port_manager_s *p_port_manager,
+ result_manager_s *p_result_manager)
+{
+ if (!p_port_manager || !p_result_manager)
+ return;
+
+ if ((result->tcp_flag & TH_SYN) && (result->tcp_flag & TH_ACK))
+ __result_manager_set_result(p_port_manager->current_port_handle_index,
+ INM_PORT_SCAN_STATE_OPEN,
+ p_result_manager);
+ else if (result->tcp_flag & TH_RST)
+ __result_manager_set_result(p_port_manager->current_port_handle_index,
+ INM_PORT_SCAN_STATE_CLOSE,
+ p_result_manager);
+
+ return;
+}
+
+static void __handle_local_err(port_manager_s *p_port_manager, result_manager_s *p_result_manager)
+{
+ if (!p_port_manager || !p_result_manager)
+ return;
+
+ __result_manager_set_result(p_port_manager->current_port_handle_index,
+ INM_PORT_SCAN_STATE_NO_RESPONSE,
+ p_result_manager);
+
+ return;
+}
+
+static void __handle_icmp_err(port_manager_s *p_port_manager, result_manager_s *p_result_manager)
+{
+ if (!p_port_manager || !p_result_manager)
+ return;
+
+ __result_manager_set_result(p_port_manager->current_port_handle_index,
+ INM_PORT_SCAN_STATE_NO_RESPONSE,
+ p_result_manager);
+
+ return;
+}
+
+static void __handle_max_retries(port_manager_s *p_port_manager, result_manager_s *p_result_manager)
+{
+ if (!p_port_manager || !p_result_manager)
+ return;
+
+ __result_manager_set_result(p_port_manager->current_port_handle_index,
+ INM_PORT_SCAN_STATE_NO_RESPONSE,
+ p_result_manager);
+
+ return;
+}
+
+static void __port_scan_raw_sock_recv(port_scan_received_result *result,
+ port_manager_s *p_port_manager,
+ result_manager_s *p_result_manager)
+{
+ __INM_FUNC_ENTER__;
+
+ if (!result || !p_port_manager || !p_result_manager) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ if (result->type == PORT_SCAN_RECEIVE_TYPE_PKT)
+ __handle_pkt(result, p_port_manager, p_result_manager);
+ else if (result->type == PORT_SCAN_RECEIVE_TYPE_LOCAL_ERROR)
+ __handle_local_err(p_port_manager, p_result_manager);
+ else if (result->type == PORT_SCAN_RECEIVE_TYPE_ICMP_ERROR)
+ __handle_icmp_err(p_port_manager, p_result_manager);
+ else if (result->type == PORT_SCAN_RECEIVE_TYPE_SOCK_HUP_NVAL)
+ __handle_sock_nval_hup(p_port_manager, p_result_manager);
+ else if (result->type == PORT_SCAN_RECEIVE_TYPE_MAX_RETRIES)
+ __handle_max_retries(p_port_manager, p_result_manager);
+
+ __INM_FUNC_EXIT__;
+ return;
+}
+
static int __port_scan_stop(port_manager_s *p_port_manager)
{
if (!p_port_manager)
static port_scan_start scan_start_funcs[] = {
[INM_PORT_SCAN_TYPE_CONN]
= __conn_port_scan_start,
+ [INM_PORT_SCAN_TYPE_SYN]
+ = __raw_sock_port_scan_start,
+ [INM_PORT_SCAN_TYPE_ACK]
+ = __raw_sock_port_scan_start,
+ [INM_PORT_SCAN_TYPE_FIN]
+ = __raw_sock_port_scan_start,
+ [INM_PORT_SCAN_TYPE_XMAS]
+ = __raw_sock_port_scan_start,
+ [INM_PORT_SCAN_TYPE_NULL]
+ = __raw_sock_port_scan_start,
};
static port_scan_send scan_send_funcs[] = {
[INM_PORT_SCAN_TYPE_CONN]
= __conn_port_scan_send,
+ [INM_PORT_SCAN_TYPE_SYN]
+ = __syn_port_scan_send,
+ [INM_PORT_SCAN_TYPE_ACK]
+ = __ack_port_scan_send,
+ [INM_PORT_SCAN_TYPE_FIN]
+ = __fin_port_scan_send,
+ [INM_PORT_SCAN_TYPE_XMAS]
+ = __xmas_port_scan_send,
+ [INM_PORT_SCAN_TYPE_NULL]
+ = __null_port_scan_send,
};
static port_scan_recv scan_recv_funcs[] = {
[INM_PORT_SCAN_TYPE_CONN]
= __conn_port_scan_recv,
+ [INM_PORT_SCAN_TYPE_SYN]
+ = __port_scan_raw_sock_recv,
+ [INM_PORT_SCAN_TYPE_ACK]
+ = __port_scan_raw_sock_recv,
+ [INM_PORT_SCAN_TYPE_FIN]
+ = __port_scan_raw_sock_recv,
+ [INM_PORT_SCAN_TYPE_XMAS]
+ = __port_scan_raw_sock_recv,
+ [INM_PORT_SCAN_TYPE_NULL]
+ = __port_scan_raw_sock_recv,
};
static port_scan_stop scan_stop_funcs[] = {
[INM_PORT_SCAN_TYPE_CONN]
= __port_scan_stop,
+ [INM_PORT_SCAN_TYPE_SYN]
+ = __port_scan_stop,
+ [INM_PORT_SCAN_TYPE_ACK]
+ = __port_scan_stop,
+ [INM_PORT_SCAN_TYPE_FIN]
+ = __port_scan_stop,
+ [INM_PORT_SCAN_TYPE_XMAS]
+ = __port_scan_stop,
+ [INM_PORT_SCAN_TYPE_NULL]
+ = __port_scan_stop,
};
static char *__print_port_state(inm_port_scan_state_e state)
return FALSE;
}
+static void __debug_received_tcp_packet(struct tcphdr *p_tcp_header)
+{
+ INM_LOGI("Window Size : %d", p_tcp_header->window);
+ INM_LOGI("Flags : ");
+ if (p_tcp_header->th_flags & TH_FIN)
+ INM_LOGI("[FIN]");
+ if (p_tcp_header->th_flags & TH_SYN)
+ INM_LOGI("[SYN]");
+ if (p_tcp_header->th_flags & TH_RST)
+ INM_LOGI("[RST]");
+ if (p_tcp_header->th_flags & TH_PUSH)
+ INM_LOGI("[PSH]");
+ if (p_tcp_header->th_flags & TH_ACK)
+ INM_LOGI("[ACK]");
+ if (p_tcp_header->th_flags & TH_URG)
+ INM_LOGI("[URG]");
+}
+
+static int __read_channel(GIOChannel *source, unsigned char *tcp_flags)
+{
+ gchar buf[4096] = {0, };
+ gsize bytes_read = 0;
+ GError *error = NULL;
+
+ INM_LOGI("Read channel");
+ if (g_io_channel_read_chars(source, buf, sizeof(buf),
+ &bytes_read, &error) != G_IO_STATUS_NORMAL) {
+ INM_LOGE("Failure received tcp packet[%d]:[%s]",
+ error->code, error->message);
+ g_error_free(error);
+ return -1;
+ }
+
+ /* handle received packet for proper type */
+ INM_LOGI("%" G_GSIZE_FORMAT " bytes read", bytes_read);
+ struct ip *p_ip_hdr = (struct ip *)buf;
+ if (p_ip_hdr->ip_p != IPPROTO_TCP) {
+ INM_LOGI("Protocol type is not TCP %d", p_ip_hdr->ip_p);
+ return -1;
+ }
+ INM_LOGI("IP Version : %d", p_ip_hdr->ip_v);
+ INM_LOGI("Time To Live : %d", p_ip_hdr->ip_ttl);
+
+ struct tcphdr *p_tcp_header = (struct tcphdr *)(buf + sizeof(struct ip));
+ __debug_received_tcp_packet(p_tcp_header);
+ *tcp_flags = p_tcp_header->th_flags;
+
+ return 0;
+}
+
+static void __scanner_raw_sock_io_in(GIOChannel *source, port_scan_data_s *p_port_scan)
+{
+ port_scan_received_result result = {0, };
+ unsigned char tcp_flags = 0;
+ __INM_FUNC_ENTER__;
+
+ if (!p_port_scan) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ if (__read_channel(source, &tcp_flags) != 0) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ result.type = PORT_SCAN_RECEIVE_TYPE_PKT;
+ result.tcp_flag = tcp_flags;
+ scan_recv_funcs[p_port_scan->type](&result,
+ &(p_port_scan->port_manager),
+ &(p_port_scan->result_manager));
+
+ return;
+}
+
+static void __handle_icmp_cmsg(struct sock_extended_err *sock_err,
+ port_scan_received_result *result)
+{
+ if (!sock_err || !result)
+ return;
+
+ INM_LOGI("We got ICMP message %d", sock_err->ee_errno);
+ INM_LOGI("We got ICMP type %d", sock_err->ee_type);
+ INM_LOGI("We got ICMP code %d", sock_err->ee_code);
+ result->type = PORT_SCAN_RECEIVE_TYPE_ICMP_ERROR;
+ result->icmp_type = sock_err->ee_type;
+ result->icmp_code = sock_err->ee_code;
+}
+
+static inline void __handle_local_cmsg(struct sock_extended_err *sock_err,
+ port_scan_received_result *result)
+{
+ if (!sock_err || !result)
+ return;
+
+ INM_LOGI("We got local message %d", sock_err->ee_errno);
+ /* Handle MTU error only */
+ if (sock_err->ee_errno == EMSGSIZE)
+ INM_LOGI("mtu %d", sock_err->ee_info);
+
+ result->type = PORT_SCAN_RECEIVE_TYPE_LOCAL_ERROR;
+ result->local_error = sock_err->ee_errno;
+}
+
+static int __handle_ip_recv_err(struct cmsghdr *cmsg,
+ struct sockaddr_in *p_remote_addr,
+ port_scan_received_result *result)
+{
+ struct sock_extended_err *sock_err;
+ struct sockaddr_in *addr_in;
+ struct sockaddr *addr;
+
+ if (!cmsg || !p_remote_addr || !result)
+ return -1;
+
+ INM_LOGI("We got IP_RECVERR message");
+
+ sock_err = (struct sock_extended_err*)CMSG_DATA(cmsg);
+ if (!sock_err)
+ return -1;
+
+ addr = SO_EE_OFFENDER(sock_err);
+ addr_in = (struct sockaddr_in *)addr;
+ if (addr->sa_family == AF_INET)
+ INM_LOGI("received from %s %d", inet_ntoa(addr_in->sin_addr), p_remote_addr->sin_port);
+ if (sock_err->ee_origin == SO_EE_ORIGIN_ICMP)
+ __handle_icmp_cmsg(sock_err, result);
+ else if (sock_err->ee_origin == SO_EE_ORIGIN_LOCAL)
+ __handle_local_cmsg(sock_err, result);
+
+ return 0;
+}
+
+static int __handle_cmsg(struct msghdr *msg,
+ struct sockaddr_in *p_remote_addr,
+ port_scan_received_result *result)
+{
+ struct cmsghdr *cmsg;
+
+ if (!msg)
+ return -1;
+
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ /* Received IP layer error */
+ if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVERR)
+ return __handle_ip_recv_err(cmsg, p_remote_addr, result);
+ }
+
+ return -1;
+}
+
+static int __recv_sock_msg_err_queue(int sock, port_scan_received_result *result)
+{
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0,};
+ char buffer[1500];
+ struct icmphdr icmph;
+ struct sockaddr_in remote;
+ struct iovec iov;
+ struct msghdr msg;
+ int res = 0;
+
+ if (sock <= 0 || !result)
+ return -1;
+
+ iov.iov_base = &icmph;
+ iov.iov_len = sizeof(icmph);
+ msg.msg_name = (void *)&remote;
+ msg.msg_namelen = sizeof(remote);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_flags = 0;
+ msg.msg_control = buffer;
+ msg.msg_controllen = sizeof(buffer);
+
+ res = recvmsg(sock, &msg, MSG_ERRQUEUE);
+ INM_LOGI("%d recvmsg received", res);
+ if (res < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ INM_LOGE("recvmsg errno[%d]: %s", errno, error_buf);
+ __INM_FUNC_EXIT__;
+ return -1;
+ }
+
+ return __handle_cmsg(&msg, &remote, result);
+}
+
+static void __scanner_raw_sock_io_err(port_scan_data_s *p_port_scan)
+{
+ port_handle_s *p_port_handle = NULL;
+ port_scan_received_result result = {0, };
+
+ __INM_FUNC_ENTER__;
+ if (!p_port_scan) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ p_port_handle = __port_manager_get_current_port_handle(&(p_port_scan->port_manager));
+ if (!p_port_handle) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ if (__recv_sock_msg_err_queue(p_port_handle->sock, &result) != 0) {
+ __INM_FUNC_EXIT__;
+ return;
+ }
+
+ scan_recv_funcs[p_port_scan->type](&result,
+ &(p_port_scan->port_manager),
+ &(p_port_scan->result_manager));
+
+ __INM_FUNC_EXIT__;
+ return;
+}
+static inline void __scanner_raw_sock_hup_nval(port_scan_data_s *p_port_scan)
+{
+ port_scan_received_result result = {0, };
+ if (!p_port_scan)
+ return;
+
+ INM_LOGE("sock HUP or NVAL");
+ result.type = PORT_SCAN_RECEIVE_TYPE_SOCK_HUP_NVAL;
+ scan_recv_funcs[g_port_scan->type](&result,
+ &(p_port_scan->port_manager),
+ &(p_port_scan->result_manager));
+}
+
+gboolean __scanner_receive_event_from_raw_sock(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ port_scan_data_s *p_port_scan_data = NULL;
+ __INM_FUNC_ENTER__;
+
+ p_port_scan_data = data;
+ if (!p_port_scan_data) {
+ INM_LOGI("Invalid data");
+ return FALSE;
+ }
+
+ if (condition == G_IO_IN)
+ __scanner_raw_sock_io_in(source, p_port_scan_data);
+ else if (condition & G_IO_ERR)
+ __scanner_raw_sock_io_err(p_port_scan_data);
+ else if (condition & (G_IO_HUP | G_IO_NVAL))
+ __scanner_raw_sock_hup_nval(p_port_scan_data);
+ else
+ INM_LOGE("unrecognized condition %d", condition);
+
+ __scanner_next_port(p_port_scan_data);
+ __INM_FUNC_EXIT__;
+ return FALSE;
+}
+
static void __scanner_attach_source(port_scan_data_s *p_port_scan)
{
port_manager_s *p_port_manager = NULL;
if (!p_port_handle)
return;
- p_port_handle->sock_source_id =
- g_io_add_watch(p_port_handle->sock_io_channel,
- G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
- __scanner_receive_event_from_tcp_sock,
- p_port_scan);
+
+ if (p_port_scan->type == INM_PORT_SCAN_TYPE_CONN)
+ p_port_handle->sock_source_id =
+ g_io_add_watch(p_port_handle->sock_io_channel,
+ G_IO_OUT | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ __scanner_receive_event_from_tcp_sock,
+ p_port_scan);
+ else
+ p_port_handle->sock_source_id =
+ g_io_add_watch(p_port_handle->sock_io_channel,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ __scanner_receive_event_from_raw_sock,
+ p_port_scan);
INM_LOGI("socket %d source_id %d", p_port_handle->sock, p_port_handle->sock_source_id);
+}
+
+static void __reach_max_retries(port_scan_data_s *p_port_scan)
+{
+ port_scan_received_result result = {0, };
+ if (!p_port_scan)
+ return;
+
+ INM_LOGI("Max retries");
+ result.type = PORT_SCAN_RECEIVE_TYPE_MAX_RETRIES;
+ scan_recv_funcs[p_port_scan->type](&result,
+ &(p_port_scan->port_manager),
+ &(p_port_scan->result_manager));
+ return;
+}
+
+static void __retry_port_scan(port_scan_data_s *p_port_scan)
+{
+ if (!p_port_scan)
+ return;
+
+ scan_send_funcs[p_port_scan->type](
+ &(p_port_scan->target_manager),
+ &(p_port_scan->port_manager));
+ return;
+}
+
+static gboolean __scanner_retry_port_scan(gpointer user_data)
+{
+ port_scan_data_s *p_port_scan;
+ port_handle_s *p_port_handle = NULL;
+
+ p_port_scan = (port_scan_data_s *)user_data;
+ if (!p_port_scan)
+ return FALSE;
+
+ p_port_handle = __port_manager_get_current_port_handle(&(p_port_scan->port_manager));
+ if (!p_port_handle)
+ return FALSE;
+
+ p_port_handle->retries++;
+ if (p_port_handle->retries >= DEFAULT_MAX_RETRIES) {
+ __reach_max_retries(p_port_scan);
+ __scanner_next_port(p_port_scan);
+ return FALSE;
+ } else {
+ __retry_port_scan(p_port_scan);
+ }
+
+ return TRUE;
}
static int __scanner_scan_start(port_scan_data_s *p_port_scan)
{
port_manager_s *p_port_manager = NULL;
+ port_handle_s *p_port_handle = NULL;
if (!p_port_scan)
return -1;
return -1;
}
+ if (p_port_scan->type != INM_PORT_SCAN_TYPE_CONN) {
+ p_port_handle = __port_manager_get_current_port_handle(p_port_manager);
+ p_port_handle->retry_timer_source_id =
+ g_timeout_add(DEFAULT_RETRY_TIMEOUT_MS,
+ __scanner_retry_port_scan,
+ p_port_scan);
+ }
+
return 0;
}