⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ping.c

📁 这是ICMP源程序包含PING的接收和发送
💻 C
字号:
/* * Created with help from Mike Muuss' PING.C * (part of netkit-base-0.17) *   AND * Help from Beej's guide to network programming * http://www.ecst.csuchico.edu/~beej/guide/net/ */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <netinet/ip.h>#include <sys/timeb.h>#include "Ping.h"#define INPACK_LENGTH 65535#define OUTPACK_LENGTH 65535struct icmp_echo {    u_int8_t type;    u_int8_t code;    u_int16_t checksum;    u_int16_t identifier;    u_int16_t sequence_number;};char *icmp_data;pid_t ident = 0;u_int16_t seq = 0;int sockfd_global;int invalid_checksum = 0;/* * Borrowed the checksum code from: * http://www.fenix.ne.jp/~thomas/memo/ip/checksum.html */unsigned short checksum(unsigned short *buf, int size) {    unsigned long sum = 0;    while (size > 1) {	sum += *buf++;	size -= 2;    }    if (size) {	sum += *(u_int8_t *)buf;    }    sum = (sum & 0xffff) + (sum >> 16);    sum = (sum & 0xffff) + (sum >> 16);    return ~sum;}int send_echo_request(int sockfd, struct sockaddr_in *their_addr, char *data) {    void *outpack = malloc(OUTPACK_LENGTH);    size_t space = 0;    struct icmp_echo *echo_packet;    int numbytes = 0;    echo_packet = malloc(sizeof(struct icmp_echo));    if (echo_packet == NULL)	return -3;        echo_packet->type = 8;    echo_packet->code = 0;    echo_packet->checksum = 0;    echo_packet->identifier = (u_int16_t) getpid();    echo_packet->sequence_number = seq;        memcpy(outpack, echo_packet, sizeof(struct icmp_echo));    space += sizeof(struct icmp_echo);    memcpy(outpack+(sizeof(struct icmp_echo)), data, strlen(data));    space += strlen(data);    invalid_checksum = 0;        echo_packet->checksum = checksum((unsigned short *)		    outpack, space);    memcpy(outpack, echo_packet, sizeof(struct icmp_echo));        numbytes = sendto(sockfd, (void *) outpack, space, 0,		    (struct sockaddr *)their_addr, sizeof(struct sockaddr));    if (numbytes == -1) {	return -4;    }    free(outpack);        return 0;}/* * int icmp_echo_send(char *host, int sequence, char *data); * * Parameters: *    host     - host to send icmp echo packet to *    sequence - packet sequence number *    data     - data to include in packet * * Return Values: *    0        - icmp echo send success *    -1       - failure looking up hostname *    -2       - failure creating network socket *    -3       - error malloc'ing memory *    -4       - error sending packet */int icmp_echo_send(char *host, int sequence, char *data) {    int sockfd;    int packlen = 0;    struct hostent *he;    struct sockaddr_in dest;    if ((he = gethostbyname(host)) == NULL)	return -1;        sockfd = socket(PF_INET, SOCK_RAW, 1);    sockfd_global = sockfd;    if (sockfd == -1)	return -2;    dest.sin_family = PF_INET;    dest.sin_port = htons(0);    dest.sin_addr = *((struct in_addr *)he->h_addr);    memset(&(dest.sin_zero), '\0', 8);    ident = getpid();    seq = sequence;        return send_echo_request(sockfd, &dest, data);}/* * JNI Wrapper code to icmp_echo_send() */JNIEXPORT jint JNICALL Java_Ping_icmp_1send (JNIEnv *env, jobject obj,		jstring host, jint s, jstring data) {    jint retval;        char *h = (*env)->GetStringUTFChars(env, host, 0);    char *d = (*env)->GetStringUTFChars(env, data, 0);    retval = (jint) icmp_echo_send(h, s, d);    (*env)->ReleaseStringUTFChars(env, host, h);    (*env)->ReleaseStringUTFChars(env, data, d);    return retval;}/*  * JNI Wrapper code to icmp_echo_reply() * (returns NULL if a error occours receiving the packet, * or packet timeout expires) */JNIEXPORT jstring JNICALL Java_Ping_icmp_1recv (JNIEnv *env, jobject obj,		jint t) {    int retval = icmp_echo_reply(t);    jstring tmp;    if (retval < 0) {	return NULL;    }    tmp = (*env)->NewStringUTF(env, icmp_data);    free(icmp_data);        return tmp;}#ifndef LIB/* * Small implementation of ping code for testing purposes */int main(int argc, char *argv[]) {    int retval = 0;     struct timeb start;    struct timeb end;    struct timeb res;    struct hostent *h;    if (argc != 5) {	fprintf(stderr, "Error! Usage:\n");	fprintf(stderr, "  %s <dst host> <seq num> <data> <timeout>\n",			argv[0]);	exit(1);    }    if ((h = gethostbyname(argv[1])) == NULL) {	herror("gethostbyname");	exit(1);    }    printf("icmp echo (request) to %s [%s]\n", h->h_name,		    inet_ntoa(*((struct in_addr *)h->h_addr)));        ftime(&start);    retval = icmp_echo_send(argv[1], atoi(argv[2]), argv[3]);    if (retval < 0) {	fprintf(stderr, "Error (%d) sending packet\n", retval);	return;    }        retval = icmp_echo_reply(atoi(argv[4]));    ftime(&end);    if (retval < 0) {	printf("[TIMEOUT]\n");	return 1;    }       if (start.millitm > end.millitm) {	end.time -= 1;	end.millitm += 1000;    }    printf("time delta: %ds%dms", end.time - start.time,		    end.millitm - start.millitm);    if (invalid_checksum) {	printf("   [INCORRECT CHECKSUM]");    }    printf("\n");    return 0;}#endifint icmp_reply(void *inpack, int packlen) {    struct ip *ip_pkt = malloc(sizeof(struct ip));    struct icmp_echo *icmp_pkt = malloc(sizeof(struct icmp_echo));    size_t ipoptlen;    size_t hlen;    void *data = malloc(INPACK_LENGTH);    void *tmp_ck = malloc(OUTPACK_LENGTH);    u_int16_t cksum, cksum_tmp;    size_t space = 0;    ip_pkt = (struct ip *)inpack;    hlen = ip_pkt->ip_hl << 2;    ipoptlen = hlen - sizeof(struct ip);    packlen -= hlen;        icmp_pkt = (struct icmp_echo *) (inpack+hlen);    if ((u_int16_t) getpid() != icmp_pkt->identifier) {	return -1;    }        memcpy(data, inpack+hlen+8, packlen-8);    cksum = icmp_pkt->checksum;    icmp_pkt->checksum = 0;        memcpy(tmp_ck, icmp_pkt, sizeof(struct icmp_echo));    space += sizeof(struct icmp_echo);    memcpy(tmp_ck+(sizeof(struct icmp_echo)), data, strlen(data));    space += strlen(data);    cksum_tmp = checksum((unsigned short *) tmp_ck, space);    if (cksum_tmp != cksum) {	invalid_checksum = 1;    }    icmp_pkt->checksum = cksum;    icmp_data = malloc(INPACK_LENGTH);    sprintf(icmp_data, "%d %s\0", icmp_pkt->sequence_number, data);#ifdef DEBUG    printf("received: ");    printf("type: %x\n", icmp_pkt->type);    printf("code: %x\n", icmp_pkt->code);    printf("checksum: %x\n", icmp_pkt->checksum);    printf("sequence: %d\n", icmp_pkt->sequence_number);    printf("identifier: %d\n", icmp_pkt->identifier);    printf("%s\n", (char *)data);#endif        return 0;}int icmp_echo_reply(int timeout) {    int packlen = 0, retval = 0;    void *inpack = malloc(INPACK_LENGTH);    fd_set readfds;    struct timeval tv;    struct sockaddr_in from;    socklen_t fromlen = sizeof(from);    int sockfd = sockfd_global;    FD_ZERO(&readfds);    FD_SET(sockfd, &readfds);    tv.tv_sec = timeout;    tv.tv_usec = 0;    while (tv.tv_sec > 0) {	retval = select(sockfd + 1, &readfds, NULL, NULL, &tv);	if (retval > 0) {	    packlen = recvfrom(sockfd, inpack, INPACK_LENGTH, 0,			    (struct sockaddr *)&from, &fromlen);	    if ((icmp_reply(inpack, packlen)) == -1) {#ifdef DEBUG		printf("Not our packet!\n");#endif		continue;	    } else {		return 0;	    }	} else {	    return -1;	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -