|  | 
 | #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); | 
 | } |