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
[EMAIL PROTECTED]
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;