patch-2.0.21-2.1.0 linux/arch/m68k/boot/atari/bootp.c
Next file: linux/arch/m68k/boot/atari/bootp.h
Previous file: linux/arch/m68k/boot/atari/Makefile
Back to the patch index
Back to the overall index
- Lines: 794
- Date:
Wed Sep 25 10:47:39 1996
- Orig file:
lx2.0/v2.0.21/linux/arch/m68k/boot/atari/bootp.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file lx2.0/v2.0.21/linux/arch/m68k/boot/atari/bootp.c linux/arch/m68k/boot/atari/bootp.c
@@ -0,0 +1,793 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "bootp.h"
+
+
+/* --------------------------------------------------------------------- */
+/* Protocol Header Structures */
+
+struct etherhdr {
+ HWADDR dst_addr;
+ HWADDR src_addr;
+ unsigned short type;
+};
+
+struct arphdr {
+ unsigned short hrd; /* format of hardware address */
+ unsigned short pro; /* format of protocol address */
+ unsigned char hln; /* length of hardware address */
+ unsigned char pln; /* length of protocol address */
+ unsigned short op; /* ARP opcode (command) */
+ unsigned char addr[0]; /* addresses (var len) */
+};
+
+struct iphdr {
+ unsigned char version : 4;
+ unsigned char ihl : 4;
+ unsigned char tos;
+ unsigned short tot_len;
+ unsigned short id;
+ unsigned short frag_off;
+ unsigned char ttl;
+ unsigned char protocol;
+ unsigned short chksum;
+ IPADDR src_addr;
+ IPADDR dst_addr;
+};
+
+struct udphdr {
+ unsigned short src_port;
+ unsigned short dst_port;
+ unsigned short len;
+ unsigned short chksum;
+};
+
+struct bootp {
+ unsigned char op; /* packet opcode type */
+ unsigned char htype; /* hardware addr type */
+ unsigned char hlen; /* hardware addr length */
+ unsigned char hops; /* gateway hops */
+ unsigned long xid; /* transaction ID */
+ unsigned short secs; /* seconds since boot began */
+ unsigned short unused;
+ IPADDR ciaddr; /* client IP address */
+ IPADDR yiaddr; /* 'your' IP address */
+ IPADDR siaddr; /* server IP address */
+ IPADDR giaddr; /* gateway IP address */
+ unsigned char chaddr[16]; /* client hardware address */
+ unsigned char sname[64]; /* server host name */
+ unsigned char file[128]; /* boot file name */
+ unsigned char vend[64]; /* vendor-specific area */
+};
+
+struct tftp_req {
+ unsigned short opcode;
+ char name[512];
+};
+
+struct tftp_data {
+ unsigned short opcode;
+ unsigned short nr;
+ unsigned char data[512];
+};
+
+struct tftp_ack {
+ unsigned short opcode;
+ unsigned short nr;
+};
+
+struct tftp_error {
+ unsigned short opcode;
+ unsigned short errcode;
+ char str[512];
+};
+
+
+typedef struct {
+ struct etherhdr ether;
+ struct arphdr arp;
+} ARP;
+
+typedef struct {
+ struct etherhdr ether;
+ struct iphdr ip;
+ struct udphdr udp;
+} UDP;
+
+#define UDP_BOOTPS 67
+#define UDP_BOOTPC 68
+#define UDP_TFTP 69
+
+typedef struct {
+ struct etherhdr ether;
+ struct iphdr ip;
+ struct udphdr udp;
+ struct bootp bootp;
+} BOOTP;
+
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+#define BOOTP_RETRYS 5
+
+typedef struct {
+ struct etherhdr ether;
+ struct iphdr ip;
+ struct udphdr udp;
+ union tftp {
+ unsigned short opcode;
+ struct tftp_req req;
+ struct tftp_data data;
+ struct tftp_ack ack;
+ struct tftp_error error;
+ } tftp;
+} TFTP;
+
+#define TFTP_RRQ 1
+#define TFTP_WRQ 2
+#define TFTP_DATA 3
+#define TFTP_ACK 4
+#define TFTP_ERROR 5
+
+
+/* --------------------------------------------------------------------- */
+/* Addresses */
+
+static HWADDR MyHwaddr;
+static HWADDR ServerHwaddr;
+static IPADDR MyIPaddr;
+static IPADDR ServerIPaddr;
+
+static IPADDR IP_Unknown_Addr = 0x00000000;
+static IPADDR IP_Broadcast_Addr = 0xffffffff;
+static HWADDR Eth_Broadcast_Addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+
+#define HZ 200
+#define _hz_200 (*(volatile unsigned long *)0x4ba)
+
+
+/* --------------------------------------------------------------------- */
+/* Error Strings */
+
+static char *ErrStr[] = {
+ "timeout",
+ "general Ethernet transmit error",
+ "general Ethernet receive error",
+ "Ethernet framing error",
+ "Ethernet overflow error",
+ "Ethernet CRC error"
+};
+
+
+/* --------------------------------------------------------------------- */
+/* Kfile Emulation Definitions */
+
+#define KFILE_CHUNK_BITS 16 /* chunk is 64 KB */
+#define KFILE_CHUNK_SIZE (1 << KFILE_CHUNK_BITS)
+#define KFILE_CHUNK_MASK (KFILE_CHUNK_SIZE-1)
+#define KFILE_N_CHUNKS (2*1024*1024/KFILE_CHUNK_SIZE)
+
+char *KFile[KFILE_N_CHUNKS];
+int KFileSize = 0;
+int KFpos = 0;
+
+
+
+
+/***************************** Prototypes *****************************/
+
+static void free_kfile( void );
+static int bootp( char *image_name );
+static int tftp( char *image_name );
+static int udp_send( UDP *pkt, int len, int fromport, int toport );
+static unsigned short ip_checksum( struct iphdr *buf );
+static int udp_rcv( UDP *pkt, int *len, int fromport, int atport );
+static void print_ip( IPADDR addr );
+static void print_hw( HWADDR addr );
+static int check_ethif( void );
+static int eth_send( Packet *pkt, int len );
+static int eth_rcv( Packet *pkt, int *len );
+
+/************************* End of Prototypes **************************/
+
+
+
+
+/* --------------------------------------------------------------------- */
+/* Interface to bootstrap.c */
+
+/* get_remote_kernel():
+ * Perform all necessary steps to get the kernel image
+ * from the boot server. If successfull (retval == 0), subsequent calls to
+ * kread() can access the data.
+ */
+
+int get_remote_kernel( const char *kname /* optional */ )
+
+{ char image_name[256];
+
+ /* Check if a Ethernet interface is present and determine the Ethernet
+ * address */
+ if (check_ethif() < 0) {
+ printf( "No Ethernet interface found -- no remote boot possible.\n" );
+ return( -1 );
+ }
+
+ /* Do a BOOTP request to find out our IP address and the kernel image's
+ * name; we also learn the IP and Ethernet address of our server */
+ if (kname)
+ strcpy( image_name, kname );
+ else
+ *image_name = 0;
+ if (bootp( image_name ) < 0)
+ return( -1 );
+
+ /* Now start a TFTP connection to receive the kernel image */
+ if (tftp( image_name ) < 0)
+ return( -1 );
+
+ return( 0 );
+}
+
+
+/* kread(), klseek(), kclose():
+ * Functions for accessing the received kernel image like with read(),
+ * lseek(), close().
+ */
+
+int kread( int fd, void *buf, unsigned cnt )
+
+{ unsigned done = 0;
+
+ if (!KFileSize)
+ return( read( fd, buf, cnt ) );
+
+ if (KFpos + cnt > KFileSize)
+ cnt = KFileSize - KFpos;
+
+ while( cnt > 0 ) {
+ unsigned chunk = KFpos >> KFILE_CHUNK_BITS;
+ unsigned endchunk = (chunk+1) << KFILE_CHUNK_BITS;
+ unsigned n = cnt;
+
+ if (KFpos + n > endchunk)
+ n = endchunk - KFpos;
+ memcpy( buf, KFile[chunk] + (KFpos & KFILE_CHUNK_MASK), n );
+ cnt -= n;
+ buf += n;
+ done += n;
+ KFpos += n;
+ }
+
+ return( done );
+}
+
+
+int klseek( int fd, int where, int whence )
+
+{
+ if (!KFileSize)
+ return( lseek( fd, where, whence ) );
+
+ switch( whence ) {
+ case SEEK_SET:
+ KFpos = where;
+ break;
+ case SEEK_CUR:
+ KFpos += where;
+ break;
+ case SEEK_END:
+ KFpos = KFileSize + where;
+ break;
+ default:
+ return( -1 );
+ }
+ if (KFpos < 0) {
+ KFpos = 0;
+ return( -1 );
+ }
+ else if (KFpos > KFileSize) {
+ KFpos = KFileSize;
+ return( -1 );
+ }
+
+ return( KFpos );
+}
+
+
+int kclose( int fd )
+
+{
+ if (!KFileSize)
+ return( close( fd ) );
+
+ free_kfile();
+ return( 0 );
+}
+
+
+static void free_kfile( void )
+
+{ int i;
+
+ for( i = 0; i < KFILE_N_CHUNKS; ++i )
+ if (KFile[i]) free( KFile[i] );
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* BOOTP Procedure */
+
+
+static int bootp( char *image_name )
+
+{ BOOTP req;
+ Packet _reply;
+ BOOTP *reply = (BOOTP *)_reply;
+ static unsigned char mincookie[] = { 99, 130, 83, 99, 255 };
+ unsigned long starttime, rancopy;
+ int err, len, retry;
+
+ memset( (char *)&req, 0, sizeof(req) );
+ /* Now fill in the packet... */
+ req.bootp.op = BOOTREQUEST;
+ req.bootp.htype = 1; /* 10Mb/s Ethernet */
+ req.bootp.hlen = 6;
+ memcpy( req.bootp.chaddr, &MyHwaddr, ETHADDRLEN );
+
+ /* Put in the minimal RFC1497 Magic cookie */
+ memcpy( req.bootp.vend, mincookie, sizeof(mincookie) );
+ /* Put the user precified bootfile name in place */
+ memcpy( req.bootp.file, image_name, strlen(image_name)+1);
+
+ starttime = _hz_200;
+ for( retry = 0; retry < BOOTP_RETRYS; ++retry ) {
+
+ /* Initialize server addresses and own IP to defaults */
+ ServerIPaddr = IP_Broadcast_Addr; /* 255.255.255.255 */
+ MyIPaddr = IP_Unknown_Addr; /* 0.0.0.0 */
+ memcpy( ServerHwaddr, Eth_Broadcast_Addr, ETHADDRLEN );
+
+ if (retry)
+ sleep( 3 );
+
+ req.bootp.xid = rancopy = _hz_200;
+ req.bootp.secs = (_hz_200 - starttime) / HZ;
+
+ if ((err = udp_send( (UDP *)&req, sizeof(req.bootp),
+ UDP_BOOTPC, UDP_BOOTPS )) < 0) {
+ printf( "bootp send: %s\n", ErrStr[-err-1] );
+ continue;
+ }
+
+ if ((err = udp_rcv( (UDP *)reply, &len,
+ UDP_BOOTPS, UDP_BOOTPC )) < 0) {
+ printf( "bootp rcv: %s\n", ErrStr[-err-1] );
+ continue;
+ }
+ if (len < sizeof(struct bootp)) {
+ printf( "received short BOOTP packet (%d bytes)\n", len );
+ continue;
+ }
+
+ if (reply->bootp.xid == rancopy)
+ /* Ok, got the answer */
+ break;
+ printf( "bootp: xid mismatch\n" );
+ }
+ if (retry >= BOOTP_RETRYS) {
+ printf( "No response from a bootp server\n" );
+ return( -1 );
+ }
+
+ ServerIPaddr = reply->bootp.siaddr;
+ memcpy( ServerHwaddr, reply->ether.src_addr, ETHADDRLEN );
+ printf( "\nBoot server is " );
+ if (strlen(reply->bootp.sname) > 0)
+ printf( "%s, IP ", reply->bootp.sname );
+ print_ip( ServerIPaddr );
+ printf( ", HW address " );
+ print_hw( ServerHwaddr );
+ printf( "\n" );
+
+ MyIPaddr = reply->bootp.yiaddr;
+ printf( "My IP address is " );
+ print_ip( MyIPaddr );
+ printf( "\n" );
+
+ strcpy( image_name, reply->bootp.file );
+ return( 0 );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* TFTP Procedure */
+
+
+static int tftp( char *image_name )
+
+{ TFTP spkt;
+ Packet _rpkt;
+ TFTP *rpkt = (TFTP *)&_rpkt;
+ unsigned short mytid, rtid = 0;
+ int blk, retries, i, wpos, err, len, datalen;
+ static char rotchar[4] = { '|', '/', '-', '\\' };
+
+ retries = 5;
+ /* Construct and send a read request */
+ repeat_req:
+ spkt.tftp.req.opcode = TFTP_RRQ;
+ strcpy( spkt.tftp.req.name, image_name );
+ strcpy( spkt.tftp.req.name + strlen(spkt.tftp.req.name) + 1, "octet" );
+ mytid = _hz_200 & 0xffff;
+
+ if ((err = udp_send( (UDP *)&spkt, sizeof(spkt.tftp.req.opcode) +
+ strlen(image_name) + 1 +
+ strlen( "octect" ) +1,
+ mytid, UDP_TFTP )) < 0) {
+ printf( "TFTP RREQ: %s\n", ErrStr[-err-1] );
+ if (--retries > 0)
+ goto repeat_req;
+ return( -1 );
+ }
+
+ retries = 5;
+ for( i = 0; i < KFILE_N_CHUNKS; ++i )
+ KFile[i] = NULL;
+ wpos = 0;
+ printf( "Receiving kernel image %s:\n", image_name );
+
+ for( blk = 1; ; ++blk ) {
+
+ repeat_data:
+ if ((err = udp_rcv( (UDP *)rpkt, &len, rtid, mytid )) < 0) {
+ printf( "TFTP rcv: %s\n", ErrStr[-err-1] );
+ if (--retries > 0)
+ goto repeat_data;
+ goto err;
+ }
+ if (rtid == 0)
+ /* Store the remote port at the first packet received */
+ rtid = rpkt->udp.src_port;
+
+ if (rpkt->tftp.opcode == TFTP_ERROR) {
+ if (strlen(rpkt->tftp.error.str) > 0)
+ printf( "TFTP error: %s\n", rpkt->tftp.error.str );
+ else
+ printf( "TFTP error #%d (no description)\n",
+ rpkt->tftp.error.errcode );
+ goto err;
+ }
+ else if (rpkt->tftp.opcode != TFTP_DATA) {
+ printf( "Bad TFTP packet type: %d\n", rpkt->tftp.opcode );
+ if (--retries > 0)
+ goto repeat_data;
+ goto err;
+ }
+
+ if (rpkt->tftp.data.nr != blk) {
+ /* doubled data packet; ignore it */
+ goto repeat_data;
+ }
+ datalen = len - sizeof(rpkt->tftp.data.opcode) -
+ sizeof(rpkt->tftp.data.nr);
+
+ /* store data */
+ if (datalen > 0) {
+ int chunk = wpos >> KFILE_CHUNK_BITS;
+ if (chunk >= KFILE_N_CHUNKS) {
+ printf( "TFTP: file too large! Aborting.\n" );
+ out_of_mem:
+ spkt.tftp.error.opcode = TFTP_ERROR;
+ spkt.tftp.error.errcode = 3;
+ strcpy( spkt.tftp.error.str, "Out of memory" );
+ udp_send( (UDP *)&spkt, sizeof(spkt.tftp.ack), mytid, rtid );
+ goto err;
+ }
+ if (!KFile[chunk]) {
+ if (!(KFile[chunk] = malloc( KFILE_CHUNK_SIZE ))) {
+ printf( "TFTP: Out of memory for kernel image\n" );
+ goto out_of_mem;
+ }
+ }
+ memcpy( KFile[chunk] + (wpos & KFILE_CHUNK_MASK),
+ rpkt->tftp.data.data, datalen );
+ wpos += datalen;
+
+#define DISPLAY_BITS 13
+ if ((wpos & ((1 << DISPLAY_BITS)-1)) == 0) {
+ printf( "\r %c %7d Bytes ",
+ rotchar[(wpos>>DISPLAY_BITS)&3], wpos );
+ fflush( stdout );
+ }
+ }
+
+ /* Send ACK packet */
+ repeat_ack:
+ spkt.tftp.ack.opcode = TFTP_ACK;
+ spkt.tftp.ack.nr = blk;
+ if ((err = udp_send( (UDP *)&spkt, sizeof(spkt.tftp.ack),
+ mytid, rtid )) < 0) {
+ printf( "TFTP ACK: %s\n", ErrStr[-err-1] );
+ if (--retries > 0)
+ goto repeat_ack;
+ goto err;
+ }
+
+ if (datalen < 512) {
+ /* This was the last packet */
+ printf( "\r %7d Bytes done\n\n", wpos );
+ break;
+ }
+
+ retries = 5;
+ }
+
+ KFileSize = wpos;
+ return( 0 );
+
+ err:
+ free_kfile();
+ return( -1 );
+}
+
+
+
+/* --------------------------------------------------------------------- */
+/* UDP/IP Protocol Quick Hack Implementation */
+
+
+static int udp_send( UDP *pkt, int len, int fromport, int toport )
+
+{
+ /* UDP layer */
+ pkt->udp.src_port = fromport;
+ pkt->udp.dst_port = toport;
+ pkt->udp.len = (len += sizeof(struct udphdr));
+ pkt->udp.chksum = 0; /* Too lazy to calculate :-) */
+
+ /* IP layer */
+ pkt->ip.version = 4;
+ pkt->ip.ihl = 5;
+ pkt->ip.tos = 0;
+ pkt->ip.tot_len = (len += sizeof(struct iphdr));
+ pkt->ip.id = 0;
+ pkt->ip.frag_off = 0;
+ pkt->ip.ttl = 255;
+ pkt->ip.protocol = 17; /* UDP */
+ pkt->ip.src_addr = MyIPaddr;
+ pkt->ip.dst_addr = ServerIPaddr;
+ pkt->ip.chksum = 0;
+ pkt->ip.chksum = ip_checksum( &pkt->ip );
+
+ /* Ethernet layer */
+ memcpy( &pkt->ether.dst_addr, ServerHwaddr, ETHADDRLEN );
+ memcpy( &pkt->ether.src_addr, MyHwaddr, ETHADDRLEN );
+ pkt->ether.type = 0x0800;
+ len += sizeof(struct etherhdr);
+
+ return( eth_send( (Packet *)pkt, len ) );
+}
+
+
+static unsigned short ip_checksum( struct iphdr *buf )
+
+{ unsigned long sum = 0, wlen = 5;
+
+ __asm__ ("subqw #1,%2\n"
+ "1:\t"
+ "movel %1@+,%/d0\n\t"
+ "addxl %/d0,%0\n\t"
+ "dbra %2,1b\n\t"
+ "movel %0,%/d0\n\t"
+ "swap %/d0\n\t"
+ "addxw %/d0,%0\n\t"
+ "clrw %/d0\n\t"
+ "addxw %/d0,%0"
+ : "=d" (sum), "=a" (buf), "=d" (wlen)
+ : "0" (sum), "1" (buf), "2" (wlen)
+ : "d0");
+ return( (~sum) & 0xffff );
+}
+
+
+static int udp_rcv( UDP *pkt, int *len, int fromport, int atport )
+
+{ int err;
+
+ repeat:
+ if ((err = eth_rcv( (Packet *)pkt, len )))
+ return( err );
+
+ /* Ethernet layer */
+ if (pkt->ether.type == 0x0806) {
+ /* ARP */
+ ARP *pk = (ARP *)pkt;
+ unsigned char *shw, *sip, *thw, *tip;
+
+ if (pk->arp.hrd != 1 || pk->arp.pro != 0x0800 ||
+ pk->arp.op != 1 || MyIPaddr == IP_Unknown_Addr)
+ /* Wrong hardware type or protocol; or reply -> ignore */
+ goto repeat;
+ shw = pk->arp.addr;
+ sip = shw + pk->arp.hln;
+ thw = sip + pk->arp.pln;
+ tip = thw + pk->arp.hln;
+
+ if (memcmp( tip, &MyIPaddr, pk->arp.pln ) == 0) {
+ memcpy( thw, shw, pk->arp.hln );
+ memcpy( tip, sip, pk->arp.pln );
+ memcpy( shw, &MyHwaddr, pk->arp.hln );
+ memcpy( sip, &MyIPaddr, pk->arp.pln );
+
+ memcpy( &pk->ether.dst_addr, thw, ETHADDRLEN );
+ memcpy( &pk->ether.src_addr, &MyHwaddr, ETHADDRLEN );
+ eth_send( (Packet *)pk, *len );
+ }
+ goto repeat;
+ }
+ else if (pkt->ether.type != 0x0800) {
+ printf( "Unknown Ethernet packet type %04x received\n",
+ pkt->ether.type );
+ goto repeat;
+ }
+
+ /* IP layer */
+ if (MyIPaddr != IP_Unknown_Addr && pkt->ip.dst_addr != MyIPaddr) {
+ printf( "Received packet for wrong IP address\n" );
+ goto repeat;
+ }
+ if (ServerIPaddr != IP_Unknown_Addr &&
+ ServerIPaddr != IP_Broadcast_Addr &&
+ pkt->ip.src_addr != ServerIPaddr) {
+ printf( "Received packet from wrong server\n" );
+ goto repeat;
+ }
+ /* If IP header is longer than 5 longs, delete the options */
+ if (pkt->ip.ihl > 5) {
+ char *udpstart = (char *)((long *)&pkt->ip + pkt->ip.ihl);
+ memmove( &pkt->udp, udpstart, *len - (udpstart-(char *)pkt) );
+ }
+
+ /* UDP layer */
+ if (fromport != 0 && pkt->udp.src_port != fromport) {
+ printf( "Received packet from wrong port %d\n", pkt->udp.src_port );
+ goto repeat;
+ }
+ if (pkt->udp.dst_port != atport) {
+ printf( "Received packet at wrong port %d\n", pkt->udp.dst_port );
+ goto repeat;
+ }
+
+ *len = pkt->udp.len - sizeof(struct udphdr);
+ return( 0 );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Address Printing */
+
+
+static void print_ip( IPADDR addr )
+
+{
+ printf( "%ld.%ld.%ld.%ld",
+ (addr >> 24) & 0xff,
+ (addr >> 16) & 0xff,
+ (addr >> 8) & 0xff,
+ addr & 0xff );
+}
+
+
+static void print_hw( HWADDR addr )
+
+{
+ printf( "%02x:%02x:%02x:%02x:%02x:%02x",
+ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] );
+}
+
+
+/* --------------------------------------------------------------------- */
+/* Ethernet Interface Abstraction Layer */
+
+
+#ifdef ETHLL_LANCE
+#include "ethlance.h"
+#endif
+
+static ETHIF_SWITCH *PossibleInterfaces[] = {
+#ifdef ETHLL_LANCE
+ &LanceSwitch,
+#endif
+};
+
+#define N_PossibleInterfaces (sizeof(PossibleInterfaces)/sizeof(*PossibleInterfaces))
+
+/* Detected interface */
+static ETHIF_SWITCH *Ethif = NULL;
+
+
+static int check_ethif( void )
+
+{ int i;
+
+ /* Check for configured interfaces */
+ Ethif = NULL;
+ for( i = 0; i < N_PossibleInterfaces; ++i ) {
+ if (PossibleInterfaces[i]->probe() >= 0) {
+ Ethif = PossibleInterfaces[i];
+ break;
+ }
+ }
+ if (!Ethif)
+ return( -1 );
+
+ if (Ethif->init() < 0) {
+ printf( "Ethernet interface initialization failed\n" );
+ return( -1 );
+ }
+ Ethif->get_hwaddr( &MyHwaddr );
+ return( 0 );
+}
+
+
+static int eth_send( Packet *pkt, int len )
+
+{
+ return( Ethif->snd( pkt, len ));
+}
+
+
+static int eth_rcv( Packet *pkt, int *len )
+
+{
+ return( Ethif->rcv( pkt, len ));
+}
+
+
+#if 0
+static void dump_packet( UDP *pkt )
+
+{ int i, l;
+ unsigned char *p;
+
+ printf( "Packet dump:\n" );
+
+ printf( "Ethernet header:\n" );
+ printf( " dst addr: " ); print_hw( pkt->ether.dst_addr ); printf( "\n" );
+ printf( " src addr: " ); print_hw( pkt->ether.src_addr ); printf( "\n" );
+ printf( " type: %04x\n", pkt->ether.type );
+
+ printf( "IP header:\n" );
+ printf( " version: %d\n", pkt->ip.version );
+ printf( " hdr len: %d\n", pkt->ip.ihl );
+ printf( " tos: %d\n", pkt->ip.tos );
+ printf( " tot_len: %d\n", pkt->ip.tot_len );
+ printf( " id: %d\n", pkt->ip.id );
+ printf( " frag_off: %d\n", pkt->ip.frag_off );
+ printf( " ttl: %d\n", pkt->ip.ttl );
+ printf( " prot: %d\n", pkt->ip.protocol );
+ printf( " src addr: " ); print_ip( pkt->ip.src_addr ); printf( "\n" );
+ printf( " dst addr: " ); print_ip( pkt->ip.dst_addr ); printf( "\n" );
+
+ printf( "UDP header:\n" );
+ printf( " src port: %d\n", pkt->udp.src_port );
+ printf( " dst port: %d\n", pkt->udp.dst_port );
+ printf( " len: %d\n", pkt->udp.len );
+
+ printf( "Data:" );
+ l = pkt->udp.len - sizeof(pkt->udp);
+ p = (unsigned char *)&pkt->udp + sizeof(pkt->udp);
+ for( i = 0; i < l; ++i ) {
+ if ((i % 32) == 0)
+ printf( "\n %04x ", i );
+ printf( "%02x ", *p );
+ }
+ printf( "\n" );
+}
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov