| |
| #include "headers.h" |
| #include "runner.h" |
| #include "util.h" |
| #include "zpingp.h" |
| #include "settings.h" |
| #include <net/if.h> |
| #include <netinet/ip_icmp.h> |
| #include "softap_api.h" |
| |
| |
| #define LOG_EMERG 0 /* system is unusable */ |
| #define LOG_ALERT 1 /* action must be taken immediately */ |
| #define LOG_CRIT 2 /* critical conditions */ |
| #define LOG_ERR 3 /* error conditions */ |
| #define LOG_WARNING 4 /* warning conditions */ |
| #define LOG_NOTICE 5 /* normal but significant condition */ |
| #define LOG_INFO 6 /* informational */ |
| #define LOG_DEBUG 7 |
| |
| #define DEFAULT_IP_ICMP_SIZE 1500 |
| #define DEFAULT_ICMP_SIZE 1480 |
| #define DEFAULT_ICMP_DATA_SIZE 1472 |
| |
| #define IPHDR_MINLEN 20 |
| |
| #define DEV_NAME_LEN 32 |
| #define MAX_MARK_NUM 45 |
| |
| u_int16_t id = 0; |
| u_int16_t last_seq_send = 0; |
| u_int16_t last_seq_recv = 0; |
| |
| u_int16_t send_num = 0; |
| u_int16_t recv_num = 0; |
| |
| int pingcount = 100; |
| |
| int16_t myid = 0; // 0x7777 |
| |
| int delayoutput = 0; |
| int lostoutput = 0; |
| |
| int maxwaitnum = 0; |
| |
| u_int32_t labels[MAX_MARK_NUM]; |
| int lost_count[MAX_MARK_NUM]; |
| |
| enum { |
| DEFDATALEN = 56, |
| MAXIPLEN = 60, |
| MAXICMPLEN = 76, |
| MAXPACKET = 65468, |
| MAX_DUP_CHK = (8 * 128), |
| MAXWAIT = 10, |
| PINGINTERVAL = 1, /* 1 second */ |
| }; |
| |
| zping_print_t label_string[] = { |
| {CLINET_RECV, "CLINET_RECV"}, |
| {CLINET_SEND, "CLIENT_SEND"}, |
| {SERVER_RECV, "SERVER_RECV"}, |
| {SERVER_SEND, "SERVER_SEND"}, |
| |
| {AP_USB_IN, "AP_USB_IN"}, |
| {AP_USB_OUT, "AP_USB_OUT"}, |
| {AP_PS_IN, "AP_PS_IN"}, |
| {AP_PS_OUT, "AP_PS_OUT"}, |
| {AP_WIFI_WAN_IN, "AP_WIFI_WAN_IN"}, |
| {AP_WIFI_WAN_OUT, "AP_WIFI_WAN_OUT"}, |
| {AP_WIFI_LAN_IN, "AP_WIFI_LAN_IN"}, |
| {AP_WIFI_LAN_OUT, "AP_WIFI_LAN_OUT"}, |
| {AP_ETH_WAN_IN, "AP_ETH_WAN_IN"}, |
| {AP_ETH_WAN_OUT, "AP_ETH_WAN_OUT"}, |
| {AP_ETH_LAN_IN, "AP_ETH_LAN_IN"}, |
| {AP_ETH_LAN_OUT, "AP_ETH_LAN_OUT"}, |
| {AP_PS_EXT1_IN, "AP_PS_EXT1_IN"}, |
| {AP_PS_EXT1_OUT, "AP_PS_EXT1_OUT"}, |
| {AP_PS_EXT2_IN, "AP_PS_EXT2_IN"}, |
| {AP_PS_EXT2_OUT, "AP_PS_EXT2_OUT"}, |
| {AP_PS_EXT3_IN, "AP_PS_EXT3_IN"}, |
| {AP_PS_EXT3_OUT, "AP_PS_EXT3_OUT"}, |
| {AP_PS_EXT4_IN, "AP_PS_EXT4_IN"}, |
| {AP_PS_EXT4_OUT, "AP_PS_EXT4_OUT"}, |
| |
| {CP_ETH1_IN, "CP_ETH1_IN"}, |
| {CP_ETH1_OUT, "CP_ETH1_OUT"}, |
| {CP_ETH2_IN, "CP_ETH2_IN"}, |
| {CP_ETH2_OUT, "CP_ETH2_OUT"}, |
| {CP_ETH3_IN, "CP_ETH3_IN"}, |
| {CP_ETH3_OUT, "CP_ETH3_OUT"}, |
| {CP_ETH4_IN, "CP_ETH4_IN"}, |
| {CP_ETH4_OUT, "CP_ETH4_OUT"}, |
| {CP_PS1_IN, "CP_PS1_IN"}, |
| {CP_PS1_OUT, "CP_PS1_OUT"}, |
| {CP_PS2_IN, "CP_PS2_IN"}, |
| {CP_PS2_OUT, "CP_PS2_OUT"}, |
| {CP_PS3_IN, "CP_PS3_IN"}, |
| {CP_PS3_OUT, "CP_PS3_OUT"}, |
| {CP_PS4_IN, "CP_PS4_IN"}, |
| {CP_PS4_OUT, "CP_PS4_OUT"}, |
| {CP_CTRM1_IN, "CP_CTRM1_IN"}, |
| {CP_CTRM1_OUT, "CP_CTRM1_OUT"}, |
| {CP_CTRM2_IN, "CP_CTRM2_IN"}, |
| {CP_CTRM2_OUT, "CP_CTRM2_OUT"}, |
| {CP_CTRM3_IN, "CP_CTRM3_IN"}, |
| {CP_CTRM3_OUT, "CP_CTRM3_OUT"}, |
| {CP_CTRM4_IN, "CP_CTRM4_IN"}, |
| {CP_CTRM4_OUT, "CP_CTRM4_OUT"}, |
| |
| {LABEL_NULL, 0} |
| }; |
| |
| static void init_and_reset(zping_settings_t *zping_settings) |
| { |
| id = 0; |
| last_seq_send = 0; |
| last_seq_recv = 0; |
| |
| send_num = 0; |
| recv_num = 0; |
| |
| pingcount = zping_settings->pingcount; |
| |
| myid = zping_settings->set_id; // 0x7777 |
| } |
| |
| static int in_cksum(unsigned short *buf, int sz) |
| { |
| int nleft = sz; |
| int sum = 0; |
| unsigned short *w = buf; |
| unsigned short ans = 0; |
| |
| while (nleft > 1) { |
| sum += *w++; |
| nleft -= 2; |
| } |
| |
| if (nleft == 1) { |
| *(unsigned char *)(&ans) = *(unsigned char *) w; |
| sum += ans; |
| } |
| |
| sum = (sum >> 16) + (sum & 0xFFFF); |
| sum += (sum >> 16); |
| ans = ~sum; |
| return ans; |
| } |
| |
| static const char *icmp_type_name(int id) |
| { |
| switch (id) { |
| case ICMP_ECHOREPLY: |
| return "Echo Reply"; |
| case ICMP_DEST_UNREACH: |
| return "Destination Unreachable"; |
| case ICMP_SOURCE_QUENCH: |
| return "Source Quench"; |
| case ICMP_REDIRECT: |
| return "Redirect (change route)"; |
| case ICMP_ECHO: |
| return "Echo Request"; |
| case ICMP_TIME_EXCEEDED: |
| return "Time Exceeded"; |
| case ICMP_PARAMETERPROB: |
| return "Parameter Problem"; |
| case ICMP_TIMESTAMP: |
| return "Timestamp Request"; |
| case ICMP_TIMESTAMPREPLY: |
| return "Timestamp Reply"; |
| case ICMP_INFO_REQUEST: |
| return "Information Request"; |
| case ICMP_INFO_REPLY: |
| return "Information Reply"; |
| case ICMP_ADDRESS: |
| return "Address Mask Request"; |
| case ICMP_ADDRESSREPLY: |
| return "Address Mask Reply"; |
| default: |
| return "unknown ICMP type"; |
| } |
| } |
| |
| char *translate_label(u_int32_t label, char *label_str, int len) |
| { |
| if (label_str == NULL) |
| return NULL; |
| |
| if (len < DEV_NAME_LEN) |
| return NULL; |
| |
| memset(label_str, 0, len); |
| |
| int i = 0; |
| |
| while (1) { |
| if (label_string[i].label == LABEL_NULL) |
| break; |
| if (label == label_string[i].label) { |
| strcpy(label_str, label_string[i].name); |
| break; |
| } |
| i++; |
| } |
| return label_str; |
| } |
| |
| static int analyse_each_zping_reply(char *buf, u_int16_t recv_seq, const u_int16_t id) |
| { |
| zping_hdr_t *zping_hdr; |
| zping_item_t *zping_item, *zping_item_first, *zping_items; |
| zping_pktlost_item_t *zping_pktlost_item, *zping_pktlost_item_first, *zping_pktlost_items; |
| int i, j, lost_count_all = 0; |
| char name[32] = {0}; |
| //int i, left, right; |
| //char label_str[DEV_NAME_LEN]; |
| //char label_str_temp[DEV_NAME_LEN]; |
| //zping_item_t *zping_items; |
| int32_t interval_secs, interval_usecs, prev_interval_secs, prev_interval_usecs, temp_secs, temp_usecs; |
| u_int32_t prev_secs, prev_usecs, first_secs, first_usecs; |
| u_int16_t prev_label = 0xffff; |
| prev_secs = prev_usecs = first_secs = first_usecs = -1; |
| int string_for_label = 0; |
| //u_int32_t prev_label = 0; |
| |
| interval_secs = interval_usecs = prev_interval_secs = prev_interval_usecs = temp_secs = temp_usecs = -1; |
| |
| if (buf == NULL) |
| return 0; |
| |
| zping_hdr = (zping_hdr_t *)buf; |
| |
| //zping_print(LOG_ALERT, "\n"); |
| //zping_print(LOG_ALERT, "item_count:%d, item_index:%d, seq:%d\n", |
| //zping_hdr->item_count, zping_hdr->item_index, recv_seq); |
| |
| if (id == 0) { |
| zping_pktlost_items = (zping_pktlost_item_t *)malloc(zping_hdr->item_index * sizeof(zping_pktlost_item_t)); |
| } else { |
| zping_items = (zping_item_t *)malloc(zping_hdr->item_index * sizeof(zping_item_t)); |
| } |
| |
| if (delayoutput) { |
| if (id == 0) { |
| for (i = 0; i < zping_hdr->item_index; i++) { |
| zping_pktlost_item = (zping_pktlost_item_t *)(buf + sizeof(zping_hdr_t) + sizeof(zping_pktlost_item_t) * i); |
| |
| zping_print(LOG_ALERT, " last_seq:%d, label:%d \t", zping_pktlost_item->last_seq, zping_pktlost_item->label);//translate_label(zping_item->label, label_str, 16), |
| |
| zping_pktlost_items[i].label = zping_pktlost_item->label; |
| zping_pktlost_items[i].last_seq = zping_pktlost_item->last_seq; |
| } |
| zping_print(LOG_ALERT, "\n"); |
| } else { |
| for (i = 0; i < zping_hdr->item_index; i++) { |
| zping_item = (zping_item_t *)(buf + sizeof(zping_hdr_t) + sizeof(zping_item_t) * i); |
| |
| for (string_for_label = 0; label_string[string_for_label].label != LABEL_NULL; string_for_label++) { |
| if (label_string[string_for_label].label == zping_item->label) |
| { |
| strcpy(name,label_string[string_for_label].name); |
| break; |
| } |
| } |
| |
| zping_print(LOG_ALERT, "node:%d, %s label: %d, last_seq:%ld \n secs:%ld, usecs:%ld \n", |
| i, name, zping_item->label,zping_item->last_seq, zping_item->secs, zping_item->usecs); |
| |
| zping_items[i].label = zping_item->label; |
| zping_items[i].last_seq = zping_item->last_seq; |
| zping_items[i].secs = zping_item->secs; |
| zping_items[i].usecs = zping_item->usecs; |
| |
| if (prev_label != 0xffff) |
| { |
| zping_print(LOG_ALERT, " delay: secs %d usecs %d \n", |
| zping_item->secs - prev_secs, zping_item->usecs - prev_usecs); |
| } |
| |
| |
| prev_secs = zping_item->secs; |
| prev_usecs = zping_item->usecs; |
| prev_label = zping_item->label; |
| if (first_secs == -1) |
| { |
| first_secs = zping_item->secs; |
| first_usecs = zping_item->usecs; |
| } |
| } |
| if (zping_hdr->item_index > 1) { |
| zping_print(LOG_ALERT, "whole time interval:%d secs %d usecs \n \n", |
| zping_item->secs - first_secs, zping_item->usecs - first_usecs); |
| } |
| } |
| } |
| |
| if (lostoutput) { |
| if (id == 0) { |
| zping_pktlost_item_first = (zping_pktlost_item_t *)(buf + sizeof(zping_hdr_t)); |
| if (send_num - zping_pktlost_item_first->last_seq > 1) { |
| return -1; |
| } |
| prev_label = zping_pktlost_item_first->label; |
| labels[0] = zping_pktlost_item_first->label; |
| for (i = 1; i < zping_hdr->item_index; i++) { |
| zping_pktlost_item = (zping_pktlost_item_t *)(buf + sizeof(zping_hdr_t) + sizeof(zping_pktlost_item_t) * i); |
| |
| labels[i] = zping_pktlost_item->label; |
| |
| //zping_print(LOG_ALERT, "label:%d, send_num:%d, zping_item->last_seq:%d\n", zping_item->label, send_num, zping_item->last_seq); |
| if (send_num - zping_pktlost_item->last_seq > 1) { |
| zping_print(LOG_ALERT, "node :%d, between label %d and label %d \n", |
| i, prev_label, zping_pktlost_item->label); |
| |
| lost_count[i]++; |
| if (i > 0) { |
| for (j = 1; j < zping_hdr->item_index; j++) { |
| lost_count_all += lost_count[j]; |
| } |
| zping_print(LOG_ALERT, "statistics: "); |
| for (j = 1; j < zping_hdr->item_index; j++) { |
| if (lost_count[j] > 0) { |
| zping_print(LOG_ALERT, "between label %d and label %d, lost count:%d, ", labels[j - 1], labels[j], lost_count[j]); |
| zping_print(LOG_ALERT, " label %d : %s label %d : %s\n",labels[j - 1],label_string[labels[j - 1]].name,labels[j],label_string[labels[j]].name); |
| } |
| } |
| zping_print(LOG_ALERT, "lost count all:%d\n", lost_count_all); |
| } |
| |
| break; |
| } |
| prev_label = zping_pktlost_item->label; |
| } |
| } else { |
| zping_item_first = (zping_item_t *)(buf + sizeof(zping_hdr_t)); |
| if (send_num - zping_item_first->last_seq > 1) { |
| return -1; |
| } |
| prev_label = zping_item_first->label; |
| labels[0] = zping_item_first->label; |
| for (i = 1; i < zping_hdr->item_index; i++) { |
| zping_item = (zping_item_t *)(buf + sizeof(zping_hdr_t) + sizeof(zping_item_t) * i); |
| |
| labels[i] = zping_item->label; |
| |
| //zping_print(LOG_ALERT, "label:%d, send_num:%d, zping_item->last_seq:%d\n", zping_item->label, send_num, zping_item->last_seq); |
| if (send_num - zping_item->last_seq > 1) { |
| zping_print(LOG_ALERT, "node:%d, between label %d and label %d, seq lost between %d and %d\n", i, prev_label, zping_item->label, zping_item->last_seq, send_num); |
| |
| lost_count[i]++; |
| if (i > 0) { |
| for (j = 1; j < zping_hdr->item_index; j++) { |
| lost_count_all += lost_count[j]; |
| } |
| zping_print(LOG_ALERT, "statistics: "); |
| for (j = 1; j < zping_hdr->item_index; j++) { |
| if (lost_count[j] > 0) { |
| zping_print(LOG_ALERT, "between label %d and label %d, lost count:%d, ", labels[j - 1], labels[j], lost_count[j]); |
| } |
| } |
| zping_print(LOG_ALERT, "lost count all:%d\n", lost_count_all); |
| } |
| |
| break; |
| } |
| prev_label = zping_item->label; |
| } |
| } |
| } |
| |
| if (id == 0) { |
| free(zping_pktlost_items); |
| } else { |
| free(zping_items); |
| } |
| return 1; |
| } |
| |
| int zping_hdr_init(char *buffer, int len, u_int16_t itemcount, u_int16_t id) |
| { |
| zping_hdr_t *zping_hdr; |
| int item_size = 0; |
| if (len < sizeof(zping_hdr_t)) |
| return 0; |
| zping_hdr = (zping_hdr_t*)buffer; |
| |
| zping_hdr->id = id; |
| zping_hdr->item_count = itemcount; |
| zping_hdr->item_index = 0; |
| zping_hdr->item_index_padding = 0xFFFF; |
| zping_hdr->flags = 0; |
| zping_hdr->flags_padding = 0xFFFF; |
| |
| item_size = id == 0 ? sizeof(zping_pktlost_item_t) : sizeof(zping_item_t); |
| if (len - sizeof(zping_hdr_t) < zping_hdr->item_count * item_size) |
| return 0; |
| |
| return 1; |
| } |
| |
| void init_all_items(char *buffer, u_int16_t itemcount, const u_int16_t id) |
| { |
| int i; |
| zping_item_t *zping_item; |
| zping_pktlost_item_t *zping_pktlost_item; |
| |
| if (id == 0) { |
| for (i = 0; i < itemcount; i++) { |
| zping_pktlost_item = (zping_pktlost_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_pktlost_item_t) * i); |
| zping_pktlost_item->label = 0x0; |
| zping_pktlost_item->label_padding = 0xFFFF; |
| zping_pktlost_item->last_seq = 0x0; |
| zping_pktlost_item->last_seq_padding = 0xFFFF; |
| } |
| return; |
| } |
| |
| for (i = 0; i < itemcount; i++) { |
| zping_item = (zping_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_item_t) * i); |
| zping_item->label = 0x0; |
| zping_item->label_padding = 0xFFFF; |
| zping_item->secs = 0x0; |
| zping_item->secs_padding = 0xFFFFFFFF; |
| zping_item->usecs = 0x0; |
| zping_item->usecs_padding = 0xFFFFFFFF; |
| zping_item->last_seq = 0x0; |
| zping_item->last_seq_padding = 0xFFFF; |
| } |
| } |
| |
| int get_current_item_index(char *buffer) |
| { |
| zping_hdr_t *zping_hdr = (zping_hdr_t*)buffer; |
| return zping_hdr->item_index; |
| } |
| void get_uniform_time(unsigned long * sec ,unsigned long * usec ) |
| { |
| unsigned long long time_usec = get_time_us(); |
| *usec = (unsigned long)time_usec; |
| *sec = (unsigned long)((unsigned long)time_usec/1000000); |
| } |
| |
| int set_send_zping_item(char *buffer, int index, const u_int16_t id) |
| { |
| struct timeval tv; |
| zping_hdr_t *zping_hdr = (zping_hdr_t*)buffer; |
| zping_pktlost_item_t *zping_pktlost_item; |
| zping_item_t *zping_item; |
| |
| if (id == 0) { |
| zping_pktlost_item = (zping_pktlost_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_pktlost_item_t) * (index - 1)); |
| zping_pktlost_item->label = CLINET_SEND; |
| zping_pktlost_item->label_padding = 0xFFFF; |
| zping_pktlost_item->last_seq = last_seq_send; |
| } else { |
| zping_item = (zping_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_item_t) * (index - 1)); |
| zping_item->label = CLINET_SEND; |
| zping_item->label_padding = 0xFFFF; |
| zping_item->secs_padding = 0xFFFFFFFF; |
| zping_item->usecs_padding = 0xFFFFFFFF; |
| //gettimeofday(&tv, NULL); |
| //zping_item->secs = tv.tv_sec; |
| //zping_item->usecs = tv.tv_usec; |
| get_uniform_time(&zping_item->secs,&zping_item->usecs); |
| zping_item->last_seq = last_seq_send; |
| } |
| |
| zping_hdr->item_index++; |
| return 1; |
| } |
| |
| int set_recv_zping_item(char *buffer, int index, const u_int16_t id) |
| { |
| struct timeval tv; |
| zping_hdr_t *zping_hdr = (zping_hdr_t*)buffer; |
| zping_pktlost_item_t *zping_pktlost_item; |
| zping_item_t *zping_item; |
| if (id == 0) { |
| zping_pktlost_item = (zping_pktlost_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_pktlost_item_t) * (index - 1)); |
| zping_pktlost_item->label_padding = 0xFFFF; |
| zping_pktlost_item->last_seq = last_seq_recv; |
| } else { |
| zping_item = (zping_item_t *)(buffer + sizeof(zping_hdr_t) + sizeof(zping_item_t) * (index - 1)); |
| zping_item->label = CLINET_RECV; |
| zping_item->label_padding = 0xFFFF; |
| zping_item->secs_padding = 0xFFFFFFFF; |
| zping_item->usecs_padding = 0xFFFFFFFF; |
| |
| //gettimeofday(&tv, NULL); |
| //zping_item->secs = tv.tv_sec; |
| //zping_item->usecs = tv.tv_usec; |
| get_uniform_time(&zping_item->secs,&zping_item->usecs); |
| zping_item->last_seq = last_seq_recv; |
| } |
| zping_hdr->item_index++; |
| return 1; |
| } |
| |
| static int unpack4(char *buf, int sz, struct sockaddr_in *from, const u_int16_t id) |
| { |
| //zping_print(LOG_ALERT, "unpack4 enter\n"); |
| struct icmp *icmppkt; |
| struct iphdr *iphdr; |
| u_int16_t recv_seq; |
| |
| iphdr = (struct iphdr *) buf; |
| icmppkt = (struct icmp *)(buf + (iphdr->ihl << 2)); |
| |
| set_recv_zping_item(icmppkt->icmp_data, get_current_item_index(icmppkt->icmp_data) + 1, id); |
| recv_seq = ntohs(icmppkt->icmp_seq); |
| |
| recv_num++; |
| |
| return analyse_each_zping_reply(icmppkt->icmp_data, recv_seq, id); |
| /* |
| if (sz >= ICMP_MINLEN + sizeof(uint32_t)) // todo |
| tp = (uint32_t *) icmppkt->icmp_data; |
| unpack_tail(sz, tp, |
| inet_ntoa(*(struct in_addr *) &from->sin_addr.s_addr), |
| recv_seq, iphdr->ttl); |
| */ |
| //return 1; |
| } |
| |
| static int zping_validate(char *buf, int sz, int send_icmp_data_size) |
| { |
| struct icmp *icmppkt; |
| struct iphdr *iphdr; |
| int hlen; |
| |
| /* discard if too short */ |
| if (sz < (IPHDR_MINLEN + ICMP_MINLEN + send_icmp_data_size)) |
| return 0; |
| |
| /* check IP header */ |
| iphdr = (struct iphdr *) buf; |
| hlen = iphdr->ihl << 2; |
| sz -= hlen; |
| icmppkt = (struct icmp *)(buf + hlen); |
| if (ntohs(icmppkt->icmp_id) != myid) |
| return 0; /* not our ping */ |
| |
| if (icmppkt->icmp_type == ICMP_ECHOREPLY) { |
| |
| } else if (icmppkt->icmp_type != ICMP_ECHO) { |
| zping_print(LOG_ALERT, "warning: got ICMP %d (%s)", |
| icmppkt->icmp_type, |
| icmp_type_name(icmppkt->icmp_type)); |
| return 0; |
| } |
| return 1; |
| } |
| |
| void sendping4(zping_settings_t *zping_settings) |
| { |
| |
| } |
| |
| void ping4(zping_settings_t *zping_settings) |
| { |
| struct sockaddr_in pingaddr; |
| int ret; |
| int data_size, icmp_size; |
| int pingsock; |
| int sockopt; |
| struct timeval tv, start_tv, end_tv; |
| |
| struct icmp *icmp_pkt; |
| char packet[DEFAULT_IP_ICMP_SIZE]; |
| char *icmp_data_zping; |
| |
| struct sockaddr_in from; |
| socklen_t fromlen = sizeof(from); |
| int c; |
| int n = 1; |
| int mark = 0; |
| int recv_wait_num = 0; |
| |
| memset(lost_count, 0, MAX_MARK_NUM * sizeof(int)); |
| memset(labels, 0, MAX_MARK_NUM * sizeof(int)); |
| |
| data_size = zping_settings->size; |
| |
| pingsock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); /* 1 == ICMP */ |
| FAIL_errno(pingsock < 0, "sock creat failed"); |
| |
| /* set recv buf (needed if we can get lots of responses: flood ping, |
| * broadcast ping etc) */ |
| sockopt = (DEFDATALEN * 2) + 7 * 1024; /* giving it a bit of extra room */ |
| setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); |
| |
| tv.tv_sec = zping_settings->timeout == 0 ? 4 : zping_settings->timeout; |
| tv.tv_usec = 0; |
| setsockopt(pingsock, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval)); |
| |
| another_round: |
| init_and_reset(zping_settings); |
| // zping_print(LOG_ALERT, "\nround %d starts\n", n++); |
| while (1) { |
| if (pingcount != 0 && send_num >= pingcount) { |
| goto out; |
| } |
| |
| icmp_size = data_size + ICMP_MINLEN; |
| |
| icmp_pkt = (struct icmp *) packet; |
| memset(icmp_pkt, 0, icmp_size); |
| icmp_pkt->icmp_type = ICMP_ECHO; |
| icmp_pkt->icmp_seq = htons(send_num); /* don't ++ here, it can be a macro */ |
| icmp_pkt->icmp_id = htons(myid); // no need to do htons if it's 0x7777 |
| //icmp_pkt->icmp_cksum = in_cksum((unsigned short *)icmp_pkt, icmp_size); |
| |
| icmp_data_zping = (char *)(icmp_pkt->icmp_data); |
| |
| zping_hdr_init(icmp_data_zping, data_size, zping_settings->itemcount, zping_settings->set_id); |
| |
| init_all_items(icmp_data_zping, zping_settings->itemcount, zping_settings->set_id); |
| |
| //gettimeofday(&tv, NULL); |
| |
| set_send_zping_item(icmp_data_zping, 1, zping_settings->set_id); |
| |
| icmp_pkt->icmp_cksum = in_cksum((unsigned short *)icmp_pkt, icmp_size); |
| |
| gettimeofday(&start_tv, NULL); |
| |
| ret = sendto(pingsock, icmp_pkt, icmp_size, 0, |
| (struct sockaddr *)&zping_settings->zping_sockaddr, sizeof(zping_settings->zping_sockaddr)); |
| |
| if (mark == 0) { |
| system("cat /proc/uptime 1>/dev/console 2>&1"); |
| mark = 1; |
| } |
| FAIL_errno(ret < 0, "sock sendto failed"); |
| //zping_print(LOG_ALERT, "ping4 sendto\n"); |
| |
| |
| recv_reply: |
| /* listen for replies */ |
| while (1) { |
| |
| memset(icmp_pkt, 0, icmp_size); |
| c = recvfrom(pingsock, packet, DEFAULT_IP_ICMP_SIZE, 0, (struct sockaddr *)&from, &fromlen); |
| //zping_print(LOG_ALERT, "try recvfrom\n"); |
| if (c < 0) { |
| //zping_print(LOG_ALERT, "recvfrom error\n"); |
| if (errno == EINTR) |
| continue; |
| else { |
| //FAIL_errno(1, "sock recvfrom failed"); |
| zping_print(LOG_ALERT, "recvfrom error errno=%d \n",errno); |
| WARN_errno(1, "sock recvfrom failed"); |
| recv_wait_num++; |
| if (recv_wait_num >= maxwaitnum) |
| break; |
| //goto out; |
| } |
| } else { |
| //zping_print(LOG_ALERT, "recvfrom received something len:%d\n", c); |
| |
| if (zping_validate(packet, c, data_size) == 0) { |
| zping_print(LOG_ALERT, "recvfrom received something we don't need\n"); |
| continue; |
| } else { |
| if (mark == 1) { |
| system("cat /proc/uptime 1>/dev/console 2>&1"); |
| mark = 2; |
| } |
| ret = unpack4(packet, c, &from, zping_settings->set_id); |
| if (ret == -1) { |
| continue; |
| } else { |
| last_seq_recv = send_num; |
| break; |
| } |
| } |
| /* |
| if(c < icmp_size) |
| { |
| zping_print(LOG_ALERT, "recvfrom len < icmp_size"); |
| goto out; // think more |
| } |
| |
| if(unpack4(packet, c, &from, data_size)) |
| { |
| break; |
| } |
| */ |
| } |
| |
| } |
| |
| last_seq_send = send_num; |
| send_num++; |
| |
| if (pingcount != 0 && send_num > pingcount) { |
| break; |
| } else { |
| gettimeofday(&end_tv, NULL); |
| if (end_tv.tv_sec - start_tv.tv_sec < zping_settings->interval) { |
| sleep(zping_settings->interval - end_tv.tv_sec + start_tv.tv_sec); |
| } |
| } |
| } |
| |
| out: |
| |
| if (zping_settings->unstopped) { |
| goto another_round; |
| } |
| |
| |
| close(pingsock); |
| pingsock = -1; |
| } |
| |
| static void ping(zping_settings_t *zping_settings) |
| { |
| zping_print(LOG_ALERT, "PING %s", zping_settings->address_str); |
| zping_print(LOG_ALERT, ": %d data bytes\n", zping_settings->size); |
| |
| ping4(zping_settings); // ping6 is to be on the way if needed |
| } |
| |
| void start_run(zping_settings_t *zping_settings) |
| { |
| delayoutput = zping_settings->delayoutput; |
| lostoutput = zping_settings->lostoutput; |
| maxwaitnum = zping_settings->maxwaitnum; |
| ping(zping_settings); |
| } |