Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Sep 2002 10:28:27 +0200
From:      Christian Zander <zander@minion.de>
To:        Julian Elischer <julian@elischer.org>
Cc:        Christian Zander <zander@minion.de>, Nate Lawson <nate@root.org>, freebsd-hackers@FreeBSD.ORG
Subject:   Re: interrupting the remote kernel
Message-ID:  <20020907102827.L652@chronos>
In-Reply-To: <Pine.BSF.4.21.0209070054180.44951-100000@InterJet.elischer.org>
References:  <20020907094726.K652@chronos> <Pine.BSF.4.21.0209070054180.44951-100000@InterJet.elischer.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Sat, Sep 07, 2002 at 12:56:12AM -0700, Julian Elischer wrote:
> 
> > What I found to work well is remote GDB debugging with the UDP
> > wrapper (ip-gdb), it responds to CTRL-C as expected.
> 
> huh? do we have that?
> (rushes of to see it it's in ports)
> comes back sadly..
> 
> (where do you get it from?)
> 

Yes, Tim Gilman posted about this on freebsd-hackers earlier this
year, the project has been sittling idle since, but can still be
found here: http://sourceforge.net/projects/ipgdb/. I did a little
bit of work on it to make it work in environments with routers; I
sent a patch to Tim, but have not yet heard back. I attached this
updated version as a patch that should apply cleanly against 4.5+.
It will work with eepro100 adapters in my version, but adding the
necessary support for other NICs is trivial. The complete patch
also needs to change a few lines in gdb to make it work, this is
included in the original patch, but not in the one I attached.

-- 
christian zander
zander@minion.de

--W/nzBZO5zC0uMSeA
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ipgdb.diff"

Binary files 4.5/compile/DEBUG/kernel.debug and sys/compile/DEBUG/kernel.debug differ
diff -ruN 4.5/conf/files sys/conf/files
--- 4.5/conf/files	Tue Mar 26 02:12:22 2002
+++ sys/conf/files	Sat Jun 22 17:14:38 2002
@@ -523,6 +523,10 @@
 i4b/layer4/i4b_l4mgmt.c		optional i4b
 i4b/layer4/i4b_l4timer.c	optional i4b
 #
+# UDP wrapper for serial GDB stub
+#
+ipgdb/ipgdb.c optional ip_gdb
+#
 isofs/cd9660/cd9660_bmap.c	optional cd9660
 isofs/cd9660/cd9660_lookup.c	optional cd9660
 isofs/cd9660/cd9660_node.c	optional cd9660
diff -ruN 4.5/conf/options sys/conf/options
--- 4.5/conf/options	Tue Feb 19 15:08:49 2002
+++ sys/conf/options	Sat Jun 22 17:01:49 2002
@@ -63,6 +63,10 @@
 DDB
 DDB_UNATTENDED	opt_ddb.h
 GDB_REMOTE_CHAT	opt_ddb.h
+
+IP_GDB          opt_ip_gdb.h
+IP_GDB_FXP      opt_ip_gdb_fxp.h
+
 HW_WDOG
 KTRACE
 LIBICONV
diff -ruN 4.5/dev/fxp/if_fxp.c sys/dev/fxp/if_fxp.c
--- 4.5/dev/fxp/if_fxp.c	Mon Feb 11 15:22:43 2002
+++ sys/dev/fxp/if_fxp.c	Sat Jun 22 17:08:56 2002
@@ -77,6 +77,8 @@
 #include <dev/fxp/if_fxpvar.h>
 #include <dev/fxp/rcvbundl.h>
 
+#include "opt_ip_gdb_fxp.h"
+
 MODULE_DEPEND(fxp, miibus, 1, 1, 1);
 #include "miibus_if.h"
 
@@ -169,7 +171,12 @@
 static int		fxp_suspend(device_t dev);
 static int		fxp_resume(device_t dev);
 
-static void		fxp_intr(void *xsc);
+#ifdef IP_GDB_FXP
+void            fxp_intr(void *xsc);
+#else
+static void     fxp_intr(void *xsc);
+#endif
+
 static void		fxp_intr_body(struct fxp_softc *sc,
 				u_int8_t statack, int count);
 
@@ -1179,7 +1186,11 @@
 /*
  * Process interface interrupts.
  */
+#ifdef IP_GDB_FXP
+void
+#else
 static void
+#endif
 fxp_intr(void *xsc)
 {
 	struct fxp_softc *sc = xsc;
diff -ruN 4.5/i386/i386/i386-gdbstub.c sys/i386/i386/i386-gdbstub.c
--- 4.5/i386/i386/i386-gdbstub.c	Wed Aug  2 17:54:41 2000
+++ sys/i386/i386/i386-gdbstub.c	Thu Jun 20 16:01:29 2002
@@ -102,8 +102,11 @@
 
 #include <setjmp.h>
 
+#include <ipgdb/ipgdb.h>
+
 #include "sio.h"
 #include "opt_ddb.h"
+#include "opt_ip_gdb.h"
 
 void		gdb_handle_exception (db_regs_t *, int, int);
 
@@ -489,13 +492,22 @@
 
   *ptr++ = 0;
 
+#ifdef IP_GDB
+  ipgdb_putpacket_add_wrapper (remcomOutBuffer);
+#else
   putpacket (remcomOutBuffer);
+#endif
 
   while (1)
     {
       remcomOutBuffer[0] = 0;
 
+#ifdef IP_GDB
+      ipgdb_getpacket (remcomInBuffer);
+#else
       getpacket (remcomInBuffer);
+#endif
+
       switch (remcomInBuffer[0]) 
 	{
 	case '?':
@@ -506,7 +518,12 @@
 	  break;
 
 	case 'D':		/* detach; say OK and turn off gdb */
+#ifdef IP_GDB
+	  ipgdb_putpacket_add_wrapper(remcomOutBuffer);
+	  ipgdb_connected = 0;
+#else
 	  putpacket(remcomOutBuffer);
+#endif
 	  boothowto &= ~RB_GDB;
 	  return;
 
@@ -608,11 +625,17 @@
 	  raw_regs->tf_ds = registers.ds;
 	  raw_regs->tf_es = registers.es;
 	  return;
-
+	/* default: */
+	  /* if we don't recognize a packet, reply with empty packet */
 	} /* switch */
 
       /* reply to the request */
+#ifdef IP_GDB
+      ipgdb_putpacket_add_wrapper (remcomOutBuffer);
+#else
       putpacket (remcomOutBuffer);
+#endif
     }
 }
 #endif /* NSIO > 0 */
+
diff -ruN 4.5/ipgdb/ipgdb.c sys/ipgdb/ipgdb.c
--- 4.5/ipgdb/ipgdb.c	Wed Dec 31 16:00:00 1969
+++ sys/ipgdb/ipgdb.c	Sat Jun 22 17:40:59 2002
@@ -0,0 +1,712 @@
+/*
+ * Copyright (c) 2002
+ *      Panasas, Inc.  All rights reserved.
+ *
+ * Some of this code is derived from FreeBSD sources.  See Copyright
+ * below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Panasas, Inc.
+ * 4. The name of Panasas, Inc. may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PANASAS, INC. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PANASAS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1980, 1986, 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/* ipgdb.c
+ *
+ * UDP implementation for remote debugger.
+ * Ideas lifted from NetBSD's ipkdb.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/sysctl.h>
+#include <sys/reboot.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#define _IP_VHL
+#include <netinet/ip.h>
+#undef _IP_VHL
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+
+#include <i386/include/in_cksum.h>
+
+#include <machine/bus.h>
+
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+
+#include <machine/clock.h>      /* for DELAY */
+
+#include <ipgdb/ipgdb.h>
+
+/* To get the GDB related variables */
+#include <ddb/ddb.h>
+
+#include "opt_ip_gdb_fxp.h"
+
+#define BUFMAX 400
+
+static char	ipgdb_inbuf[BUFMAX];
+static char	ipgdb_outbuf[BUFMAX];
+static char 	*ipgdb_getoff;
+static int	ipgdb_gotone = 0; /* only if we have cmd packet */
+int	ipgdb_connected = 0;
+static int	ipgdb_ack_packet = 0; /* only if recv'd + packet */
+static struct ifnet *ipgdb_ifp;
+static struct sockaddr_in	ipgdb_ip_us;
+static struct sockaddr_in	ipgdb_ip_them;
+static u_char	ipgdb_ether_us[ETHER_ADDR_LEN];
+static u_char	ipgdb_ether_them[ETHER_ADDR_LEN];
+
+/* need prototype to clobber warning */
+/* NIC_intr is the NIC's interrupt handler.  AFAIK there's no way
+ * to call this function except directly.
+ *
+ * To enable a different NIC, go make NIC_intr not static, and
+ * add code as below:
+ */
+
+#ifdef IP_GDB_FXP
+extern void fxp_intr  __P((void *));
+#endif
+#ifdef IP_GDB_SIS
+extern void sis_intr  __P((void *));
+#endif
+
+/*
+ * We need to make sure that the target machine still responds to ARP
+ * requests when trapped in the debugger. If it doesn't, routers will
+ * assume that it is no longer available and send ICMP "Destination
+ * Unreachable", "Host Unreachable" error messages to remotes sending
+ * packets to the target. Similarly to NIC_intr(), arpintr() needs to
+ * be called regularly to prevent this from happening.
+ */
+
+extern void arpintr   __P((void));
+
+#ifndef IP_GDB_FXP
+#ifndef IP_GDB_SIS
+#error You must specify an interface with IPGDB.  Eg, in your config file, add "IP_GDB_nic".
+#endif
+#endif
+
+
+static int
+ipgdb_strlen (const char *s)
+{
+    const char *s1 = s;
+ 
+    while (*s1++ != '\000');
+ 
+    return s1 - s;
+}                         
+
+
+char *
+ipgdb_strcpy (char *dst, const char *src)
+{
+    char *retval = dst;
+
+    while ((*dst++ = *src++) != '\000');
+
+    return retval;
+}
+
+
+static void
+ipgdb_copy(void *s, void *d, int n)
+{
+    char *sp = s, *dp = d;
+ 
+    while (--n >= 0)
+        *dp++ = *sp++;
+}
+
+
+void
+ipgdb_fillbuff (const char *src)
+{
+    (void)ipgdb_strcpy(ipgdb_inbuf, src);
+    ipgdb_getoff = ipgdb_inbuf;
+}
+
+
+static u_int ipgdb_getns __P((void *));
+
+__inline static u_int
+ipgdb_getns(void *vs)
+{
+    u_char *s = vs;
+
+    return (*s << 8)|s[1];
+}
+
+
+static const char hexchars[]="0123456789abcdef";
+
+static int
+hex(char ch)
+{
+    if ((ch >= 'a') && (ch <= 'f'))
+        return (ch-'a'+10);
+    if ((ch >= '0') && (ch <= '9'))
+        return (ch-'0');
+    if ((ch >= 'A') && (ch <= 'F'))
+        return (ch-'A'+10);
+    return (-1);
+}
+
+
+/* gdb-stub uses put/getpacket to talk to remote */
+void
+ipgdb_putpacket_add_wrapper(char *buffer)
+{
+    /* we're passed a buffer filled with Important Data, */
+    /* wrap it up and send it out.. */
+    unsigned char 	checksum;
+    int 	count;
+    unsigned char 	ch, *c_ptr;
+
+    /* sending an empty buffer is the appropriate response
+     * to unknown/unsupported gdb commands
+     */
+    while (ipgdb_connected == 0) {
+        DELAY(1000000);
+    }
+
+    c_ptr = ipgdb_outbuf;
+    *c_ptr++ = '$';  /* special header character */
+    checksum = 0;
+    count = 0;
+
+    while ((ch = buffer[count]) != 0)
+    {
+        checksum += ch;
+        count += 1;
+        *c_ptr++ = ch;  /* add the guts of message */
+    }
+
+    *c_ptr++ = '#';  /* special marker */
+    /* after special marker, insert checksum */
+    *c_ptr++ = hexchars[checksum >> 4];
+    *c_ptr++ = hexchars[checksum & 0xf];
+
+    *c_ptr = '\000';
+
+    ipgdb_putpacket(ipgdb_outbuf);
+}
+
+
+static u_short ipgdb_ip_id;
+
+void
+ipgdb_putpacket(char *snd_buf)
+{
+    register struct udpiphdr	*ui;
+    register struct ether_header	*eh;
+    struct ip *ip_ptr;
+    struct mbuf	*m;
+    int	s, length, sw_csum;
+    int	hlen = sizeof(struct ip);
+    short	type;
+
+    /* now send packet.  need to build packet first */
+    /* put data into mbuf form */
+    m = m_devget(snd_buf, ipgdb_strlen(snd_buf), 0, ipgdb_ifp, NULL);
+
+    length = m->m_pkthdr.len;
+
+    /* jmb, the length is actually really restricted.
+     * it should be set to the path mtu to avoid ip fragmentation
+     * assume mtu is that of ethernet, 1472 ( 1500-sizeof(ip+udp headers))
+     */
+    if (length > 1472) {
+        printf("ipgdb_putpacket: EMSGSIZE: %s\n", snd_buf);
+        m_freem(m);
+        return;
+    }
+
+    /* slap on udp & ip headers */
+    M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
+    if (m == 0) {
+        printf("ipgdb_putpacket: ENOBUFS: %s\n", snd_buf);
+        m_free(m);
+        return;
+    }
+
+    /* fill in headers */
+    ui = mtod(m, struct udpiphdr *);
+    bzero(ui->ui_x1, sizeof(ui->ui_x1));    /* XXX still needed? */
+    ui->ui_pr = IPPROTO_UDP;
+    ui->ui_src = ipgdb_ip_us.sin_addr;
+    ui->ui_dst = ipgdb_ip_them.sin_addr;
+    ui->ui_sport = ipgdb_ip_us.sin_port;
+    ui->ui_dport = ipgdb_ip_them.sin_port;
+    ui->ui_ulen = htons((u_short)length + sizeof(struct udphdr));
+
+    /* tack on udp checksum */
+    ui->ui_sum = in_pseudo(ui->ui_src.s_addr, ui->ui_dst.s_addr,
+        htons((u_short)length + sizeof(struct udphdr) + IPPROTO_UDP));
+    m->m_pkthdr.csum_flags = CSUM_UDP;
+    m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
+    /* end of UDP section */
+
+    ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + length;
+    ((struct ip *)ui)->ip_ttl = 127;    /* XXX */
+
+    /* begin IP section (ip_output:.c) */
+    ip_ptr = mtod(m, struct ip *);
+
+    ip_ptr->ip_vhl = IP_MAKE_VHL(IPVERSION, hlen >> 2);
+    ip_ptr->ip_off &= IP_DF;
+    ip_ptr->ip_id = htons(ipgdb_ip_id++);
+
+    /* IP checksum */
+    sw_csum = m->m_pkthdr.csum_flags | CSUM_IP;
+    m->m_pkthdr.csum_flags = sw_csum & ipgdb_ifp->if_hwassist;
+    sw_csum &= ~ipgdb_ifp->if_hwassist;
+    if (sw_csum & CSUM_DELAY_DATA) {
+        in_delayed_cksum(m);
+        sw_csum &= ~CSUM_DELAY_DATA;
+    }
+
+    HTONS(ip_ptr->ip_len);
+    HTONS(ip_ptr->ip_off);
+    ip_ptr->ip_sum = 0;
+
+    if (sw_csum & CSUM_DELAY_IP) {
+        if (ip_ptr->ip_vhl == IP_VHL_BORING) {
+            ip_ptr->ip_sum = in_cksum_hdr(ip_ptr);
+        } else {
+            ip_ptr->ip_sum = in_cksum(m, hlen);
+        }
+    }
+
+    /* ready to send */
+
+    /* go straight to ethernet, do not pass IP */
+    type = htons(ETHERTYPE_IP);
+
+    M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+    if (m == 0) {
+        printf("ipgdb: error building ether header\n");
+        m_freem(m);
+        return;
+    }
+    eh = mtod(m, struct ether_header *);
+    (void)memcpy(&eh->ether_type, &type, sizeof(eh->ether_type));
+    (void)memcpy(eh->ether_dhost, ipgdb_ether_them, sizeof(ipgdb_ether_them));
+    (void)memcpy(eh->ether_shost, ipgdb_ether_us, sizeof(ipgdb_ether_us));
+
+    /* time to stuff this into the driver */
+
+    s = splimp();
+    if (IF_QFULL(&ipgdb_ifp->if_snd)) {
+        IF_DROP(&ipgdb_ifp->if_snd);
+        splx(s);
+        m_freem(m);
+        printf("ipgdb: IF_QFULL, looks full\n");
+        return;
+    }
+    IF_ENQUEUE(&ipgdb_ifp->if_snd, m);
+    /* if ((ipgdb_ifp->if_flags & IFF_OACTIVE) == 0) */
+        (*ipgdb_ifp->if_start)(ipgdb_ifp);
+    splx(s);
+
+    /* this grossness is due to the fact that on connection,
+     * gdb-host sends two packets, a + and then something.
+     */
+    if (ipgdb_ack_packet == 1) {
+        ipgdb_ack_packet = 0;
+        return;
+    }
+
+    /* wait for an ack packet */
+    if (*snd_buf != '+' && *snd_buf != '-') {
+        while (ipgdb_ack_packet == 0) {
+            DELAY(10000);
+#ifdef IP_GDB_FXP
+            fxp_intr(ipgdb_ifp->if_softc);
+#endif
+#ifdef IP_GDB_SIS
+            sis_intr(ipgdb_ifp->if_softc);
+#endif
+        }
+    ipgdb_ack_packet = 0;
+    }
+}
+
+
+/* this will not return until a valid cmd is received */
+void
+ipgdb_getpacket(char *buffer)
+{
+    unsigned char	checksum, xmitcsum, ch, *c_ptr;
+    int		count;
+
+/* while interface hasn't responded, do nothing */
+tryagain:
+    while (ipgdb_gotone == 0) {
+        DELAY(10000);
+#ifdef IP_GDB_FXP
+        fxp_intr(ipgdb_ifp->if_softc);
+#endif
+#ifdef IP_GDB_SIS
+        sis_intr(ipgdb_ifp->if_softc);
+#endif
+	/* make sure ARP requests are handled */
+	arpintr();
+    }
+
+    ipgdb_gotone = 0;
+
+    if (ipgdb_inbuf[0] != '$')
+        goto tryagain;
+
+    c_ptr = ipgdb_inbuf;
+    ++c_ptr; /* skip over the $ */
+    checksum = 0;
+    xmitcsum = -1;
+    count = 0;
+
+    /* XXX 400 is gdb-stub's BUFMAX, deal with the ugliness */
+    while (count < 400)
+    {
+        ch = *c_ptr & 0x7f;
+        ++c_ptr;
+        if (ch == '#')
+            break;
+        checksum = checksum + ch;
+        buffer[count] = ch;
+        count = count + 1;
+    }
+    buffer[count] = 0;
+
+    if (ch == '#')
+    {
+        xmitcsum = hex(*c_ptr & 0x7f) << 4;
+        ++c_ptr;
+        xmitcsum += hex(*c_ptr & 0x7f);
+        ++c_ptr;
+
+        if (checksum != xmitcsum)
+        {
+            /* send a - packet, ugh, Bad */
+            ipgdb_putpacket("-");
+            /* discard the packet */
+            goto tryagain;
+        } else {
+            /* send a + packet, ugha, Good! */
+            ipgdb_putpacket("+");
+
+            /* if a sequence char is present, reply the seq ID */
+            /* tgilman - sequence stuff is deprecated */
+        } /* else */
+    } /* if */
+}
+
+/*
+ * ipgdb_forward() is called from net/if_ethersubr.c
+ * just before the schednetisr() call, if need be
+ */
+int
+ipgdb_forward(m, ifp, eh)
+    struct mbuf *m;
+    struct ifnet *ifp;
+    struct ether_header *eh;
+{
+    register struct ip *ip_ptr;
+    register struct udphdr *uh;
+    int ip_hlen, ulen, ip_plen;
+    u_int data_size;
+    u_short sum;
+
+    if (m->m_pkthdr.len < sizeof(struct ip)) {
+        return 0;
+    }
+ 
+    if (m->m_len < sizeof (struct ip) &&
+      (m = m_pullup(m, sizeof (struct ip))) == 0) {
+        return 0;
+    }
+
+    ip_ptr = mtod(m, struct ip *);
+
+    /* don't look at ip fragments */
+    if(ip_ptr->ip_off!=0) {
+        return 0;    
+    }
+
+    /* determine if this packet is for the debugger */
+    if (IP_VHL_V(ip_ptr->ip_vhl) != IPVERSION) {
+        return 0;
+    }
+
+    /* need min header before we can check protocol type */
+    ip_hlen = IP_VHL_HL(ip_ptr->ip_vhl) << 2;
+    if (ip_hlen < sizeof(struct ip)) { /* min header length */
+        return 0;
+    }
+
+    if (ip_hlen > m->m_len) { /* get the whole IP header */
+        if ((m = m_pullup(m, ip_hlen)) == 0) {
+            return 0;
+        }
+        ip_ptr = mtod(m, struct ip *);
+    }
+
+    /* 
+     * although we haven't finished processing at the IP level
+     * peek at the protocol value so we can determine early 
+     * if the packet is of interest.  the debugger only
+     * wants UDP stuff, ignore everything else
+     */
+    if (ip_ptr->ip_p != IPPROTO_UDP) {/* UDP? */
+        return 0;
+    }
+
+    /* this code is religiously stolen from, i mean *modeled after*, 
+     * code from netinet/ip_input.c:line 317, ip_input()
+     */
+    /* verify the ip header checksum */
+    if(m->m_pkthdr.csum_flags & CSUM_IP_CHECKED) {
+        sum = !(m->m_pkthdr.csum_flags & CSUM_IP_VALID);
+    } else {
+        if (ip_hlen == sizeof(struct ip)) {
+            sum = in_cksum_hdr(ip_ptr);
+        } else {
+            sum = in_cksum(m, ip_hlen);
+        }
+    }
+    if (sum) {
+        return 0;
+    }
+  
+    /* sanity check the length of the ip packet */
+    /* mbuf is too short for ip packet */
+    ip_plen = ntohs(ip_ptr->ip_len);
+  
+    if(m->m_pkthdr.len < ip_plen) {
+        return 0;
+    }
+
+    /* XXX kgdb will not work on machines that are doing IP
+     * forwarding -- need to check ip address to get this to work
+     * see "to forward or not to forward, p217, tcpip illustrated, vol. 2
+     */
+  
+    /* onto UPD level processing */
+    /* checked protocol type above before checking ip header checksum
+     * and sanity checking the lengths
+     */
+    /* now pulling from udp_usrreq.c:169 */
+
+    /* get the whole UDP header in the mbuf */
+    if (m->m_len < ip_hlen + sizeof(struct udphdr)) {
+        if ((m = m_pullup(m, ip_hlen + sizeof(struct udphdr))) == 0) {
+            return 0;
+        }
+        ip_ptr = mtod(m, struct ip *);
+    }
+    uh = (struct udphdr *)((caddr_t)ip_ptr + ip_hlen);
+    /* now that we've got the udp header, check port number */
+    if (ipgdb_getns(&uh->uh_dport) != IPGDBPORT ) {
+        return 0;
+    }
+
+    /* check the UDP length agains the mbuf length
+     * and the IP length.
+     *
+     * at this point we've determined the the IP data is
+     * ours and we can do with it what we wish,
+     * if its bad we should be able to drop it
+     *
+     * XXX could probably update UDP stats here also
+     */
+    /* strip the IP options so the we can do the checksum */
+    /* trim the packet if longer than we expect */
+    if(m->m_pkthdr.len > ip_plen) {
+        /* if m_len == m_pkthdr.len, the mbuf is simple, directly modify len */
+        if(m->m_len == m->m_pkthdr.len) {
+            m->m_len = ip_plen;
+            m->m_pkthdr.len = ip_plen;
+        } else {
+            m_adj(m, ip_plen - m->m_pkthdr.len);
+        }
+    }
+
+    if(ip_hlen > sizeof(struct ip)) {
+        ip_stripoptions(m, (struct mbuf *)0);
+        ip_hlen = sizeof(struct ip);
+    }
+    ip_ptr = mtod(m, struct ip *);
+    uh = (struct udphdr *)((caddr_t)ip_ptr + ip_hlen);
+
+    ulen = ntohs((u_short)uh->uh_ulen);
+    if((ip_plen - sizeof(struct ip)) != ulen) {
+        if(ulen > ip_plen || ulen < sizeof(struct udphdr)) {
+            /* drop the packet */
+            m_freem(m);
+            return 1;
+        }
+        m_adj(m, ulen - (ip_plen-sizeof(struct ip)));
+    }
+
+    /* 
+     * do a UDP checksum to further verify the UDP packet 
+     */
+    if (uh->uh_sum) {
+        if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+            if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
+                uh->uh_sum = m->m_pkthdr.csum_data;
+            } else {
+                uh->uh_sum = in_pseudo(ip_ptr->ip_src.s_addr,
+                    ip_ptr->ip_dst.s_addr, 
+                    htonl((u_short)ulen +
+                    m->m_pkthdr.csum_data + IPPROTO_UDP));
+            }
+            uh->uh_sum ^= 0xffff;
+        } else {
+            bzero(((struct ipovly *)ip_ptr)->ih_x1, 9);
+            ((struct ipovly *)ip_ptr)->ih_len = uh->uh_ulen;
+            uh->uh_sum = in_cksum(m, ulen + sizeof (struct ip));
+        }
+        if (uh->uh_sum) {
+            m_freem(m);
+            return 1;
+        }
+    }
+
+    ip_hlen += sizeof(struct udphdr);
+    m_adj(m, ip_hlen);
+    data_size = ulen - sizeof(struct udphdr);
+    m_copydata(m,0,data_size,(caddr_t)ipgdb_inbuf);
+    /* cap off the buffer */
+    ipgdb_inbuf[data_size] = '\000';
+
+    if (ipgdb_connected == 0) { /* first time? */
+        /* if we're not connected, this packet might not be for */
+        /* us.  check for the expected first packet. */
+        if (ipgdb_inbuf[0] != '+') { /* not ours */
+            m_freem(m);
+            return 1;
+        }
+        ipgdb_ack_packet = 1; /* just checked this */
+        /* record some information about our session */
+        ipgdb_ifp = ifp;
+        ipgdb_ip_us.sin_port = uh->uh_dport;
+        ipgdb_ip_us.sin_addr = ip_ptr->ip_dst;
+        ipgdb_ip_them.sin_port = uh->uh_sport;
+        ipgdb_ip_them.sin_addr = ip_ptr->ip_src;
+
+        /* save off the ethernet addrs */
+        ipgdb_copy(eh->ether_dhost, ipgdb_ether_us, sizeof(eh->ether_dhost));
+        ipgdb_copy(eh->ether_shost, ipgdb_ether_them, sizeof(eh->ether_shost));
+
+#if 0
+        /* prepare for callback from driver */
+        ipgdb_connected = 2;
+        m_freem(m);
+        return 1;
+#else
+        /* make note of our connectedness */
+        ipgdb_connected = 1;
+
+        /* setup code path to drop immediately into
+         * remote debugging session
+         */
+        boothowto |= RB_GDB; /* causes Debugger() to go remote */ 
+        m_freem(m);
+        Debugger("remote debugging initiated");
+        return 1;
+#endif
+    }
+
+    /* note ack/+ packets now */
+    if (ipgdb_inbuf[0] == '+') {
+        ipgdb_ack_packet = 1;
+    } else {
+        ipgdb_gotone = 1;
+    }
+
+    /* special case: user 'c'ontinued, then CNTL-C'd */
+    if (ipgdb_inbuf[0] == 0x3) {
+        ipgdb_gotone = 0;
+        m_freem(m);
+#if 0
+        ipgdb_connected = 2;	/* force driver to callback */
+#else
+        Debugger("break into remote debugger");
+#endif
+        return 1;
+    }
+
+    /* free up the mbuf */
+    m_freem(m);
+    return 1;
+}
+
diff -ruN 4.5/ipgdb/ipgdb.h sys/ipgdb/ipgdb.h
--- 4.5/ipgdb/ipgdb.h	Wed Dec 31 16:00:00 1969
+++ sys/ipgdb/ipgdb.h	Thu Feb 28 17:25:31 2002
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2002
+ *      Panasas, Inc.  All rights reserved.
+ *
+ * Some of this code is derived from FreeBSD sources.  See Copyright
+ * below.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by Panasas, Inc.
+ * 4. The name of Panasas, Inc. may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PANASAS, INC. ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL PANASAS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1980, 1986, 1991, 1993
+ *      The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the University of
+ *      California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * ipgdb.h
+ *
+ * udp-based debugger guts for use by other kernel parts
+ *
+ */
+
+#ifndef _IPGDB_H
+#define _IPGDB_H
+
+#include <sys/mbuf.h>
+#include <net/ethernet.h>
+
+#define IPGDBPORT	4	/* debugging port */
+
+/* gdb-stub uses put/getpacket */
+void ipgdb_putpacket_add_wrapper(char *buffer);
+void ipgdb_putpacket(char *snd_buf);
+void ipgdb_getpacket(char *buffer);
+
+/* some prototypes for ipgdb */
+void ipgdb_fillbuff(const char *src);
+int ipgdb_forward(struct mbuf *m, struct ifnet *ifp, struct ether_header *eh);
+
+extern int ipgdb_connected;
+
+/* help functions to prevent debugger lock via breakpoint */
+char * ipgdb_strcpy(char *dst, const char *src);
+
+#endif /* _IPGDB_H */
+
diff -ruN 4.5/kern/kern_shutdown.c sys/kern/kern_shutdown.c
--- 4.5/kern/kern_shutdown.c	Thu Feb 21 11:15:10 2002
+++ sys/kern/kern_shutdown.c	Thu Jun 20 16:03:18 2002
@@ -43,6 +43,7 @@
 #include "opt_hw_wdog.h"
 #include "opt_panic.h"
 #include "opt_show_busybufs.h"
+#include "opt_ip_gdb.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -590,6 +591,9 @@
 
 #if defined(DDB)
 	if (debugger_on_panic)
+#if defined IP_GDB
+		boothowto |= RB_GDB;
+#endif
 		Debugger ("panic");
 #endif
 	boot(bootopt);
diff -ruN 4.5/modules/fxp/Makefile sys/modules/fxp/Makefile
--- 4.5/modules/fxp/Makefile	Tue Dec  4 12:01:53 2001
+++ sys/modules/fxp/Makefile	Sat Jun 22 17:46:55 2002
@@ -3,6 +3,7 @@
 .PATH:	${.CURDIR}/../../dev/fxp
 KMOD	= if_fxp
 SRCS	= if_fxp.c opt_bdg.h device_if.h bus_if.h pci_if.h miibus_if.h
+SRCS	+= opt_ip_gdb_fxp.h
 KMODDEPS = miibus
 
 .include <bsd.kmod.mk>
diff -ruN 4.5/net/if_ethersubr.c sys/net/if_ethersubr.c
--- 4.5/net/if_ethersubr.c	Wed Apr  3 21:51:55 2002
+++ sys/net/if_ethersubr.c	Sat Jun 22 16:19:52 2002
@@ -40,6 +40,7 @@
 #include "opt_ipx.h"
 #include "opt_bdg.h"
 #include "opt_netgraph.h"
+#include "opt_ip_gdb.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -60,6 +61,10 @@
 #include <net/ethernet.h>
 #include <net/bridge.h>
 
+#ifdef IP_GDB
+#include <ipgdb/ipgdb.h>
+#endif
+
 #if defined(INET) || defined(INET6)
 #include <netinet/in.h>
 #include <netinet/in_var.h>
@@ -552,6 +557,10 @@
 	switch (ether_type) {
 #ifdef INET
 	case ETHERTYPE_IP:
+#ifdef IP_GDB
+		if (ipgdb_forward(m, ifp, eh))
+			return;
+#endif /* IP_GDB */
 		if (ipflow_fastforward(m))
 			return;
 		schednetisr(NETISR_IP);
diff -ruN 4.5/netinet/if_ether.c sys/netinet/if_ether.c
--- 4.5/netinet/if_ether.c	Wed Mar 27 08:40:59 2002
+++ sys/netinet/if_ether.c	Sat Jun 22 17:11:45 2002
@@ -71,6 +71,8 @@
 #include <net/if_arc.h>
 #include <net/iso88025.h>
 
+#include "opt_ip_gdb.h"
+
 #define SIN(s) ((struct sockaddr_in *)s)
 #define SDL(s) ((struct sockaddr_dl *)s)
 
@@ -118,7 +120,11 @@
 static void	arp_rtrequest __P((int, struct rtentry *, struct rt_addrinfo *));
 static void	arprequest __P((struct ifnet *,
 			struct in_addr *, struct in_addr *, u_char *));
-static void	arpintr __P((void));
+#ifdef IP_GDB
+       void	arpintr __P((void));
+#else
+static void arpintr __P((void));
+#endif
 static void	arptfree __P((struct llinfo_arp *));
 static void	arptimer __P((void *));
 static struct llinfo_arp
@@ -492,7 +498,11 @@
  * Common length and type checks are done here,
  * then the protocol-specific routine is called.
  */
+#ifdef IP_GDB
+void
+#else
 static void
+#endif
 arpintr()
 {
 	register struct mbuf *m;

--W/nzBZO5zC0uMSeA--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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