Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Apr 2007 16:02:35 GMT
From:      Alexey Tarasov <taleks@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 118835 for review
Message-ID:  <200704261602.l3QG2ZuP059723@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118835

Change 118835 by taleks@taleks_th on 2007/04/26 16:01:49

	Updated icmp code, added icmp echo replying.

Affected files ...

.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#2 edit
.. //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#2 edit

Differences ...

==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.c#2 (text+ko) ====


==== //depot/projects/soc2007/taleks-pxe_http/pxe_core.h#2 (text+ko) ====

@@ -4,6 +4,10 @@
 #include <stdint.h>
 #include <stddef.h>
 
+/* PXE structures and function codes
+#include "sys/boot/libi386/pxe.h"
+*/
+
 /*
   contains wrappers for UNDI functions
 */
@@ -60,6 +64,12 @@
 /* interrupt handler function, that used to get new packets */
 void pxe_core_isr();
 
+/* installs irq handler*/
+void pxe_core_install_isr();
+
+/* removes irq handler*/
+void pxe_core_remove_isr();
+
 /* stores data in packet */
 int pxe_core_recieve(pxe_packet* pack, void* data, size_t size);
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_icmp.c#2 (text+ko) ====

@@ -1,60 +1,164 @@
+#include <stand.h>
 #include "pxe_ip.h"
 #include "pxe_icmp.h"
 #include "pxe_core.h"
 #include "pxe_conv.h"
 
+/* used in echo replying */
+static pinging=0;
+
 int pxe_icmp_callback(pxe_packet* pack, uint8_t function, void* data) {
 
-    return 1;
+
+    if (function==PXE_CORE_CHECK) {
+        /* we don't store icmp packets, so they cannot steal memory
+          in pxe core packet table */
+        return 0;
+    }
+
+    /* PXE_CORE_HANDLE - to handle packet
+       PXE_CORE_FRAG   - to handle fragment of packet, may be useful for fast
+                        dropping of invalid packet.
+    */
+
+
+    /* icmp header*/
+    pxe_ip*     iphdr=pack->data;
+    size_t      iphdr_len=(iphdr->ver_ihl & 0x0f)*4;
+    size_t      data_size=iphdr->length-iphdr_len-sizeof(pxe_ip);
+    pxe_icmp*   icmphdr=pack->data+sizeof(pxe_ip)+iphdr_len;
+
+    /* TODO: verify checksum */
+
+    /* reply */
+    pxe_packet* pack_out=NULL;
+    pxe_ip*     reply_iphdr=NULL;
+    pxe_icmp*   reply_icmphdr=NULL;
+    size_t      reply_size=sizeof(pxe_ip)+sizeof(pxe_icmp)+data_size;
+
+    /* we are interested only in echo related packets*/
+    switch(icmphdr->code) {
+        case PXE_ICMP_ECHO_REQUEST:
+        case PXE_ICMP_ECHO_REPLY:
+ /*       case PXE_ICMP_DEST_UNREACHABLE:
+          case PXE_ICMP_REDIRECT_MESSAGE:
+ */
+            break;
+
+        default:
+            return 0;   /* instruct pxe core to drop packet*/
+    };
+
+    if (icmphdr->code==PXE_ICMP_ECHO_REPLY) {
+
+        if (pinging==be2le32(iphdr->src_ip))
+            printf("\necho reply from %x, seq=%ld.", iphdr->src_ip, icmphdr->seq_num);
+        else /* we are not interested in this reply*/
+            printf("\nlame echo reply from %x, seq=%ld.", iphdr->src_ip, icmphdr->seq_num);
+        return 0;
+    }
+    /* all we need now is echo reply */
+    pxe_packet* pack_out=pxe_core_alloc_packet(reply_size);
+
+    if (!pack) {        /* TO THINK: failed to allocate packet,
+                        may be it's better to use
+                        statically allocated packet. */
+
+        return 0;
+    }
+
+    reply_iphdr=(pxe_ip*)pack_out->data;
+    reply_icmphdr=(pxe_icmp*)(reply_iphdr+1);
+
+    reply_icmphdr->type=PXE_ICMP_ECHO_REPLY;
+
+    /* copying same values */
+
+    reply_icmphdr->code=icmphdr->code;
+    reply_icmphdr->seq_num=icmphdr->seq_num;
+    reply_icmphdr->packet_id=icmphdr->reply_icmphdr;
+    reply_icmphdr->checksum=0;
+    reply_icmphdr->checksum=~(le2be16(pxe_ip_checksum(reply_icmphdr, sizeof(pxe_icmp))));
+
+    pxe_ip_hdr(pack_out->data, iphdr->src_ip, 0x01, reply_size, 0);
+
+    /*copying all data from request packet to reply packet, starting after headers */
+    pxe_memcpy(reply_icmphdr+1, pack->data+iphdr_len+sizeof(pxe_icmp), data_size);
+
+    pxe_core_transmit(pack_out);
+/*    pxe_core_commit(pack);
+      return 1; /* instruct core we are interested in it, so save data */
+
+    return 0;   /* drop it, we don't need this packet more */
+                /* this is a little bit ugly, may be */
+                /* using of more return codes will be more flexible */
 }
 
 int pxe_icmp_init() {
 
-    pxe_core_register(1, pxe_icmp_callback);
+    /* register protocol in pxe protocols table. */
+    /* 0x01 - ICMP protocol */
+    pxe_core_register(0x01, pxe_icmp_callback);
 
     return 1;
 }
 
 int pxe_ping(pxe_ipaddr* ip, int count) {
 
-    uint32_t scount=0;
+    int     scount=0;
 
     /* creating packet */
-
-    pxe_packet* pack=pxe_core_alloc_packet(sizeof(pxe_ip)+sizeof(pxe_icmp));
+    size_t      pack_size=sizeof(pxe_ip)+sizeof(pxe_icmp)+32;
+    pxe_packet* pack=pxe_core_alloc_packet(pack_size);
+    pxe_ip*     iphdr=NULL;
+    pxe_icmp*   icmphdr=NULL;
 
     if (!pack) {    /* failed to alloc packet */
 
         return 0;
     }
 
-    pxe_ip*     iphdr=pack->data;
-    pxe_icmp*   icmphdr=pack->data+sizeof(pxe_ip);
+    printf("\nping: %x, bytes=32", ip->ip);
+    pinging=ip->ip;
+
+    iphdr=(pxe_ip*)pack->data;
+    icmphdr=(pxe_icmp*)(pack->data+sizeof(pxe_ip));
+
+    /* base icmp header side*/
 
     icmphdr->type=PXE_ICMP_ECHO_REQUEST;
-    icmphdr->code=0;
-    icmphdr->seq_num=0;
-    icmphdr->packet_id=0;
-    icmphdr->checksum=0;
+    icmphdr->code=1;
+
+/*  icmphdr->seq_num=scount;
+    icmphdr->packet_id=scount*scount;
+*/
+
+/*  icmphdr->checksum=0;
+    reply_icmphdr->checksum=~(le2be16(pxe_ip_checksum(icmphdr, sizeof(pxe_icmp))));
+*/
+
+    /* ip header side */
+    pxe_ip_hdr(pack->data, ip->ip, 0x01, pack_size, 0);
+
+
+    while (scount<count) {
+
+        icmphdr->seq_num=scount;
+        icmphdr->packet_id=scount*scount; /* is this good idea? */
 
-/*    iphdr->checksum=0;
-    iphdr->length=le2be16(sizeof(pxe_ip)+sizeof(pxe_icmp));
-    iphdr->protocol=1;
-    iphdr->checksum=0;
-    iphdr->data_off=le2be16(sizeof(pxe_ip));
-    iphdr->dst_ip=le2be32(ip->ip);
-    iphdr->id=0;
-    iphdr->tos=0;
-    iphdr->src_ip=le2be32(pxe_get_myip32());
-    iphdr->ttl=30;
+        /* recalc for every packet */
 
-    iphdr->ver_ihl=0x45;
+        icmphdr->checksum=0;
+        reply_icmphdr->checksum=~(le2be16(pxe_ip_checksum(icmphdr, sizeof(pxe_icmp))));
 
-*/
+        pxe_core_transmit(pack);
 
-    pxe_ip_hdr(pack->data, ip->ip, 1, sizeof(pxe_ip)+sizeof(pxe_icmp), 0);
+        /* TODO: timeout checking */
 
+        ++scount;
+    }
 
+    pinging=0;
     return scount;
 }
 

==== //depot/projects/soc2007/taleks-pxe_http/pxe_ip.c#2 (text+ko) ====

@@ -24,6 +24,9 @@
 	return (uint16_t)sum;
 }
 
+/* NOTE: opts_size is unused, cause we are creating header without options.
+   it may be useful later, but now it's just unused.
+*/
 void pxe_ip_hdr(void* data, uint32_t dst_ip, uint8_t protocol, uint16_t size, uint16_t opts_size) {
 
     pxe_ip* iphdr=(pxe_ip*)data;
@@ -32,13 +35,16 @@
     iphdr->length=size;
     iphdr->protocol=protocol;
     iphdr->checksum=0;
-    iphdr->data_off=0; /* le2be16(sizeof(pxe_ip)); */
+    /* data_off - offset of fragment, need to think about renaming. */
+    iphdr->data_off=0; /* le2be16(); */
     iphdr->dst_ip=le2be32(dst_ip);
     iphdr->id=0;
     iphdr->tos=0;
     iphdr->src_ip=le2be32(pxe_get_myip32());
     iphdr->ttl=30;
 
+    /* 0x45 [ver_ihl] = 0x4 << 4 [ip version] |
+                        0x5 [header length = 20 bytes, no opts] */
     iphdr->ver_ihl=0x45;
     iphdr->ver_ihl+=(opts_size>>2)
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704261602.l3QG2ZuP059723>