From owner-freebsd-hackers Sat Sep 7 1:31:54 2002 Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8C32D37B400 for ; Sat, 7 Sep 2002 01:31:12 -0700 (PDT) Received: from moutng.kundenserver.de (moutng.kundenserver.de [212.227.126.177]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3DF4143E3B for ; Sat, 7 Sep 2002 01:31:11 -0700 (PDT) (envelope-from phoenix@minion.de) Received: from [212.227.126.161] (helo=mrelayng2.kundenserver.de) by moutng3.kundenserver.de with esmtp (Exim 3.35 #2) id 17nayT-0002Uc-00; Sat, 07 Sep 2002 10:29:49 +0200 Received: from [80.144.20.168] (helo=chronos) by mrelayng2.kundenserver.de with asmtp (Exim 3.35 #1) id 17nayR-0002sz-00; Sat, 07 Sep 2002 10:29:47 +0200 Received: from phoenix by chronos with local (Exim 3.35 #1 (Debian)) id 17nax9-0000lg-00; Sat, 07 Sep 2002 10:28:27 +0200 Date: Sat, 7 Sep 2002 10:28:27 +0200 From: Christian Zander To: Julian Elischer Cc: Christian Zander , Nate Lawson , freebsd-hackers@FreeBSD.ORG Subject: Re: interrupting the remote kernel Message-ID: <20020907102827.L652@chronos> Reply-To: Christian Zander References: <20020907094726.K652@chronos> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="W/nzBZO5zC0uMSeA" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.3.22.1i X-Operating-System: GNU/Linux [2.4.19][i686] Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG --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 #include +#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 +#include + #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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#define _IP_VHL +#include +#undef _IP_VHL +#include +#include +#include + +#include + +#include + +#include +#include + +#include /* for DELAY */ + +#include + +/* To get the GDB related variables */ +#include + +#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 +#include + +#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 #include @@ -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 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 #include @@ -60,6 +61,10 @@ #include #include +#ifdef IP_GDB +#include +#endif + #if defined(INET) || defined(INET6) #include #include @@ -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 #include +#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