Add IPKDB support to GDB.
This commit is contained in:
parent
7c8b72d592
commit
0bb2093748
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.35 1999/11/26 14:39:47 msaitoh Exp $
|
||||
# $NetBSD: Makefile,v 1.36 2000/03/23 20:44:40 ws Exp $
|
||||
|
||||
# for OBJECT_FMT
|
||||
.include <bsd.own.mk>
|
||||
|
@ -44,7 +44,7 @@ COMMON_SRCS= version.c blockframe.c breakpoint.c findvar.c stack.c thread.c \
|
|||
c-valprint.c cp-valprint.c ch-valprint.c f-valprint.c m2-valprint.c \
|
||||
nlmread.c serial.c mdebugread.c os9kread.c top.c utils.c
|
||||
YYSRCS= c-exp.y f-exp.y jv-exp.y m2-exp.y
|
||||
REMOTE_SRCS= remote.c dcache.c remote-utils.c tracepoint.c
|
||||
REMOTE_SRCS= remote.c dcache.c remote-utils.c tracepoint.c remote-ipkdb.c
|
||||
DEPFILES= ${TDEPFILES.${MACHINE_ARCH}} ${XDEPFILES} ${SER_HARDWIRE} \
|
||||
${NATDEPFILES} ${REMOTE_SRCS} ${SIM_SRCS}
|
||||
|
||||
|
|
|
@ -0,0 +1,753 @@
|
|||
/* Remote target communications for NetBSD targets via UDP (aka IPKDB).
|
||||
Copyright (C) 1988-1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foudation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that is will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Remote communication protocol.
|
||||
|
||||
Data is sent in binary.
|
||||
The first byte is the command code.
|
||||
|
||||
Packets have a sequence number and the data length prepended
|
||||
and a signature appended. The signature is computed according
|
||||
to the HMAC algorithm (see draft-ietf-ipsec-hmac-md5-00.txt).
|
||||
The answer has the same sequence number. On a timeout, packets
|
||||
are rerequested by resending the request.
|
||||
|
||||
Request Packet
|
||||
|
||||
read registers R
|
||||
reply pXX...X Register data is sent in target format.
|
||||
emessage for an error.
|
||||
|
||||
write regs WXX...X Same as above.
|
||||
reply ok for success.
|
||||
emessage for an error.
|
||||
|
||||
read mem MAA...ALL...L AA...A is address, LL...L is length
|
||||
(both as CORE_ADDR).
|
||||
reply pXX...X XX...X is mem contents.
|
||||
emessage for an error.
|
||||
|
||||
write mem NAA...ALL...LXX...X
|
||||
AA...A is address, LL...L is length,
|
||||
XX...X is data.
|
||||
reply ok for success.
|
||||
emessage for an error.
|
||||
|
||||
cont C
|
||||
|
||||
step S
|
||||
|
||||
open debug OII...IWW...W II...I is an arbitrary id of the session,
|
||||
WW...W is the user and machine running gdb.
|
||||
|
||||
There is no immediate reply to step, cont or open.
|
||||
The reply comes when the machines stops (again).
|
||||
It is s
|
||||
|
||||
detach X
|
||||
reply ok
|
||||
*/
|
||||
|
||||
#include "defs.h"
|
||||
#include "command.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "inferior.h"
|
||||
#include "target.h"
|
||||
#include "valprint.h"
|
||||
#include "wait.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <md5.h>
|
||||
|
||||
static struct target_ops ipkdb_ops;
|
||||
|
||||
static int ipkdb_desc = -1;
|
||||
static char host[512];
|
||||
|
||||
#define DBGPORT 1138
|
||||
|
||||
#define PBUFSIZ 400
|
||||
|
||||
static void remote_send();
|
||||
static void putpkt();
|
||||
static void getpkt();
|
||||
static int startprot();
|
||||
static void netread();
|
||||
static void netwrite();
|
||||
static void trykey();
|
||||
|
||||
/* Clean up connection to remote debugger. */
|
||||
static void
|
||||
ipkdb_close(quitting)
|
||||
int quitting;
|
||||
{
|
||||
if (ipkdb_desc >= 0)
|
||||
close(ipkdb_desc);
|
||||
ipkdb_desc = -1;
|
||||
}
|
||||
|
||||
/* Open a connection to a remote debugger.
|
||||
The argument NAME, being the hostname of the target,
|
||||
may optionally have the HMAC key for this appended. */
|
||||
static void
|
||||
ipkdb_open(name, from_tty)
|
||||
char *name;
|
||||
int from_tty;
|
||||
{
|
||||
struct hostent *he;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
if (name == 0)
|
||||
error(
|
||||
"To open a remote debug connection, you need to specify\n\
|
||||
the name of the target machine.");
|
||||
|
||||
trykey(name, from_tty);
|
||||
strcpy(host, name);
|
||||
|
||||
ipkdb_close(0);
|
||||
|
||||
if (!(he = gethostbyname(host))
|
||||
|| he->h_addrtype != AF_INET)
|
||||
error("host '%s' unknown\n", host);
|
||||
|
||||
target_preopen(from_tty);
|
||||
push_target(&ipkdb_ops);
|
||||
|
||||
if ((ipkdb_desc = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
||||
perror_with_name(host);
|
||||
|
||||
sin.sin_len = sizeof sin;
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = htons(DBGPORT);
|
||||
sin.sin_addr = *(struct in_addr *)he->h_addr;
|
||||
|
||||
if (connect(ipkdb_desc, (struct sockaddr *)&sin, sizeof sin) < 0)
|
||||
perror_with_name(host);
|
||||
|
||||
if (!catch_errors(startprot, NULL,
|
||||
"Couldn't establish connection to remote target\n",
|
||||
RETURN_MASK_ALL))
|
||||
pop_target();
|
||||
else if (from_tty)
|
||||
printf_filtered("Remote debugging on %s\n", name);
|
||||
}
|
||||
|
||||
/* Close the open connection to the remote debugger.
|
||||
Use this when you want to detach and do something else
|
||||
with your gdb. */
|
||||
static void
|
||||
ipkdb_detach(args, from_tty)
|
||||
char *args;
|
||||
int from_tty;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
int l;
|
||||
|
||||
*buf = 'X';
|
||||
l = 1;
|
||||
remote_send(buf, &l);
|
||||
pop_target();
|
||||
if (from_tty)
|
||||
puts_filtered("Ending remote debugging IPKDB.\n");
|
||||
}
|
||||
|
||||
/* Tell the remote machine to resume. */
|
||||
static void
|
||||
ipkdb_resume(pid, step, ssignal)
|
||||
int pid, step;
|
||||
enum target_signal ssignal;
|
||||
{
|
||||
if (ssignal != TARGET_SIGNAL_0)
|
||||
error("Can't send signals to a remote IPKDB system.");
|
||||
|
||||
putpkt(step ? "S" : "C", 1);
|
||||
}
|
||||
|
||||
/* Wait until the remote machine stops, then return. */
|
||||
static int
|
||||
ipkdb_wait(pid, status)
|
||||
int pid;
|
||||
struct target_waitstatus *status;
|
||||
{
|
||||
unsigned char buf[PBUFSIZ];
|
||||
int l;
|
||||
|
||||
getpkt(buf, &l);
|
||||
if (l > 0 && buf[0] == 'e') {
|
||||
buf[l] = 0;
|
||||
error("Remote failure reply: '%s'", buf + 1);
|
||||
}
|
||||
if (buf[0] != 's')
|
||||
error("Invalid remote reply: '%s'", buf);
|
||||
status->kind = TARGET_WAITKIND_STOPPED;
|
||||
status->value.sig = TARGET_SIGNAL_TRAP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the remote registers. */
|
||||
static void
|
||||
ipkdb_fetch_register(regno)
|
||||
int regno;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
int l;
|
||||
|
||||
*buf = 'R';
|
||||
l = 1;
|
||||
remote_send(buf, &l);
|
||||
|
||||
/* Reply describes registers byte by byte.
|
||||
Suck them all up, and supply them to the
|
||||
register cacheing/storage mechanism. */
|
||||
for (l = 0; l < NUM_REGS; l++)
|
||||
supply_register(l, &buf[1 + REGISTER_BYTE(l)]);
|
||||
}
|
||||
|
||||
/* Prepare to store registers. Since we send them all, we have to
|
||||
read out the ones we don't want to change first. */
|
||||
static void
|
||||
ipkdb_prepare_to_store()
|
||||
{
|
||||
ipkdb_fetch_register(-1);
|
||||
}
|
||||
|
||||
/* Store the remote registers. */
|
||||
static void
|
||||
ipkdb_store_register(regno)
|
||||
int regno;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
int l;
|
||||
|
||||
buf[0] = 'W';
|
||||
|
||||
memcpy(buf + 1, registers, REGISTER_BYTES);
|
||||
l = 1 + REGISTER_BYTES;
|
||||
|
||||
remote_send(buf, &l);
|
||||
}
|
||||
|
||||
/* Put addr into buf */
|
||||
static void
|
||||
addrput(addr, buf)
|
||||
CORE_ADDR addr;
|
||||
char *buf;
|
||||
{
|
||||
int i;
|
||||
|
||||
buf += sizeof addr;
|
||||
for (i = sizeof addr; --i >= 0; addr >>= 8)
|
||||
*--buf = addr;
|
||||
}
|
||||
|
||||
/* Write memory data directly to the remote machine. */
|
||||
static void
|
||||
ipkdb_write_bytes(memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
|
||||
*buf = 'N';
|
||||
addrput(memaddr, buf + 1);
|
||||
addrput((CORE_ADDR)len, buf + 1 + sizeof(CORE_ADDR));
|
||||
|
||||
memcpy(buf + 1 + 2 * sizeof(CORE_ADDR), myaddr, len);
|
||||
|
||||
len += 1 + 2 * sizeof(CORE_ADDR);
|
||||
remote_send(buf, &len);
|
||||
}
|
||||
|
||||
/* Read memory data directly from the remote machine. */
|
||||
static void
|
||||
ipkdb_read_bytes(memaddr, myaddr, len)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
int l;
|
||||
char *p;
|
||||
|
||||
*buf = 'M';
|
||||
addrput(memaddr, buf + 1);
|
||||
addrput((CORE_ADDR)len, buf + 1 + sizeof(CORE_ADDR));
|
||||
|
||||
l = 1 + 2 * sizeof(CORE_ADDR);
|
||||
remote_send(buf, &l);
|
||||
|
||||
if (l != len + 1)
|
||||
error("ipkdb_read_bytes got wrong size of answer");
|
||||
|
||||
memcpy(myaddr, buf + 1, len);
|
||||
}
|
||||
|
||||
/* Read or write LEN bytes from inferior memory at MEMADDR */
|
||||
static int
|
||||
ipkdb_xfer_memory(memaddr, myaddr, len, should_write, target)
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
int should_write;
|
||||
struct target_ops *target;
|
||||
{
|
||||
int origlen = len;
|
||||
int xfersize;
|
||||
|
||||
while (len > 0) {
|
||||
xfersize = min(len, PBUFSIZ - 3 * sizeof(CORE_ADDR));
|
||||
|
||||
if (should_write)
|
||||
ipkdb_write_bytes(memaddr, myaddr, xfersize);
|
||||
else
|
||||
ipkdb_read_bytes(memaddr, myaddr, xfersize);
|
||||
memaddr += xfersize;
|
||||
myaddr += xfersize;
|
||||
len -= xfersize;
|
||||
}
|
||||
return origlen;
|
||||
}
|
||||
|
||||
static void
|
||||
ipkdb_files_info()
|
||||
{
|
||||
printf_unfiltered("\tAttached to IPKDB at %s.\n", host);
|
||||
}
|
||||
|
||||
static char bpt[] = BREAKPOINT;
|
||||
|
||||
static int
|
||||
ipkdb_insert_breakpoint(addr, save)
|
||||
CORE_ADDR addr;
|
||||
char *save;
|
||||
{
|
||||
ipkdb_read_bytes(addr, save, sizeof bpt);
|
||||
ipkdb_write_bytes(addr, bpt, sizeof bpt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ipkdb_remove_breakpoint(addr, save)
|
||||
CORE_ADDR addr;
|
||||
char *save;
|
||||
{
|
||||
ipkdb_write_bytes(addr, save, sizeof bpt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ipkdb_kill()
|
||||
{
|
||||
}
|
||||
|
||||
/* Send the command in BUF to the remote machine,
|
||||
and read the reply into BUF. */
|
||||
static void
|
||||
remote_send(buf, lp)
|
||||
char *buf;
|
||||
int *lp;
|
||||
{
|
||||
putpkt(buf, *lp);
|
||||
getpkt(buf, lp);
|
||||
|
||||
if (buf[0] == 'e') {
|
||||
buf[*lp] = 0;
|
||||
error("Remote failure reply: '%s'", buf + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* HMAC Checksumming routines */
|
||||
|
||||
/*
|
||||
* The following code is more or less stolen from the hmac_md5
|
||||
* function in the Appendix of the HMAC IETF draft, but is
|
||||
* optimized as suggested in this same paper.
|
||||
*/
|
||||
static char *key;
|
||||
static MD5_CTX icontext, ocontext;
|
||||
|
||||
static void
|
||||
hmac_init()
|
||||
{
|
||||
char pad[64];
|
||||
char tk[16];
|
||||
int key_len;
|
||||
int i;
|
||||
|
||||
/* Require key to be at least 16 bytes long */
|
||||
if (!key || (key_len = strlen(key)) < 16) {
|
||||
if (key)
|
||||
/* This doesn't make too much sense, but... */
|
||||
memset(key, 0, key_len);
|
||||
|
||||
error("ipkdbkey must be at least 16 bytes long.");
|
||||
}
|
||||
/* if key is longer than 64 bytes reset it to key=MD5(key) */
|
||||
if (key_len > 64) {
|
||||
MD5Init(&icontext);
|
||||
MD5Update(&icontext, key, key_len);
|
||||
MD5Final(tk, &icontext);
|
||||
|
||||
/* This doesn't make too much sense, but... */
|
||||
memset(key, 0, key_len);
|
||||
|
||||
key = tk;
|
||||
key_len = 16;
|
||||
}
|
||||
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is and n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected
|
||||
*/
|
||||
/*
|
||||
* We do the initial part of MD5(K XOR ipad)
|
||||
* and MD5(K XOR opad) here, in order to
|
||||
* speed up the computation later on.
|
||||
*/
|
||||
memset(pad, 0, sizeof pad);
|
||||
memcpy(pad, key, key_len);
|
||||
for (i = 0; i < 64; i++)
|
||||
pad[i] ^= 0x36;
|
||||
MD5Init(&icontext);
|
||||
MD5Update(&icontext, pad, 64);
|
||||
|
||||
memset(pad, 0, sizeof pad);
|
||||
memcpy(pad, key, key_len);
|
||||
for (i = 0; i < 64; i++)
|
||||
pad[i] ^= 0x5c;
|
||||
MD5Init(&ocontext);
|
||||
MD5Update(&ocontext, pad, 64);
|
||||
|
||||
/*
|
||||
* Zero out the key.
|
||||
* This doesn't make too much sense, but...
|
||||
*/
|
||||
memset(key, 0, key_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is more or less hmac_md5 from the HMAC IETF draft, Appendix.
|
||||
*/
|
||||
static void *
|
||||
chksum(buf, len)
|
||||
void *buf;
|
||||
int len;
|
||||
{
|
||||
static u_char digest[16];
|
||||
struct MD5Context context;
|
||||
|
||||
/*
|
||||
* the HMAC_MD5 transform looks like:
|
||||
*
|
||||
* MD5(K XOR opad, MD5(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected
|
||||
*/
|
||||
/*
|
||||
* Since we've already done the precomputation,
|
||||
* we can now stuff the data into the relevant
|
||||
* preinitialized contexts to get the result.
|
||||
*/
|
||||
/*
|
||||
* perform inner MD5
|
||||
*/
|
||||
memcpy(&context, &icontext, sizeof context);
|
||||
MD5Update(&context, buf, len);
|
||||
MD5Final(digest, &context);
|
||||
/*
|
||||
* perform outer MD5
|
||||
*/
|
||||
memcpy(&context, &ocontext, sizeof context);
|
||||
MD5Update(&context, digest, 16);
|
||||
MD5Final(digest, &context);
|
||||
|
||||
return digest;
|
||||
}
|
||||
|
||||
static struct cmd_list_element *setkeycmd;
|
||||
|
||||
static void
|
||||
trykey(name, from_tty)
|
||||
char *name;
|
||||
int from_tty;
|
||||
{
|
||||
char *k;
|
||||
|
||||
for (k = name; *k && !isspace(*k); k++);
|
||||
if (*k)
|
||||
*k++ = 0;
|
||||
for (; *k && isspace(*k); k++);
|
||||
if (*k)
|
||||
do_setshow_command(k, from_tty, setkeycmd);
|
||||
else if (!key)
|
||||
error("No valid ipkdbkey yet");
|
||||
}
|
||||
|
||||
/* net I/O routines */
|
||||
static long netseq;
|
||||
|
||||
static long
|
||||
getnl(p)
|
||||
void *p;
|
||||
{
|
||||
u_char *s = p;
|
||||
|
||||
return (s[0] << 24)|(s[1] << 16)|(s[2] << 8)|s[3];
|
||||
}
|
||||
|
||||
static int
|
||||
getns(p)
|
||||
void *p;
|
||||
{
|
||||
u_char *s = p;
|
||||
|
||||
return (s[0] << 8)|s[1];
|
||||
}
|
||||
|
||||
static void
|
||||
setnl(p, l)
|
||||
void *p;
|
||||
long l;
|
||||
{
|
||||
u_char *s = p;
|
||||
|
||||
*s++ = l >> 24;
|
||||
*s++ = l >> 16;
|
||||
*s++ = l >> 8;
|
||||
*s = l;
|
||||
}
|
||||
|
||||
static void
|
||||
setns(p, l)
|
||||
void *p;
|
||||
int l;
|
||||
{
|
||||
u_char *s = p;
|
||||
|
||||
*s++ = l >> 8;
|
||||
*s = l;
|
||||
}
|
||||
|
||||
static int
|
||||
startprot(dummy)
|
||||
char *dummy;
|
||||
{
|
||||
char buf[PBUFSIZ];
|
||||
char myname[128];
|
||||
|
||||
netseq = 0;
|
||||
|
||||
gethostname(myname, sizeof myname);
|
||||
buf[0] = 'O';
|
||||
setnl(buf + 1, time(NULL));
|
||||
sprintf(buf + 5, "%s@%s", getlogin(), myname);
|
||||
putpkt(buf, 5 + strlen(buf + 5));
|
||||
|
||||
/* Don't print character strings by default. This might break the target. */
|
||||
print_max = 0;
|
||||
|
||||
start_remote();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char ibuf[512], obuf[512];
|
||||
static int olen;
|
||||
|
||||
static void
|
||||
putpkt(buf, len)
|
||||
char *buf;
|
||||
int len;
|
||||
{
|
||||
if (len > sizeof obuf - 10)
|
||||
error("putpkt: packet too large");
|
||||
|
||||
setnl(obuf, netseq);
|
||||
setns(obuf + 4, len);
|
||||
memcpy(obuf + 6, buf, len + 1);
|
||||
memcpy(obuf + len + 6, chksum(obuf, len + 6), 16);
|
||||
olen = len + 6 + 16;
|
||||
|
||||
if (write(ipkdb_desc, obuf, olen) < 0
|
||||
&& (errno != EINTR
|
||||
#ifdef ECONNREFUSED
|
||||
&& errno != ECONNREFUSED
|
||||
#endif
|
||||
#ifdef EHOSTDOWN
|
||||
&& errno != EHOSTDOWN
|
||||
#endif
|
||||
))
|
||||
fatal("putpkt: write");
|
||||
}
|
||||
|
||||
static void
|
||||
getpkt(buf, lp)
|
||||
char *buf;
|
||||
int *lp;
|
||||
{
|
||||
int len;
|
||||
struct timeval tv, deadline;
|
||||
fd_set rd;
|
||||
|
||||
gettimeofday(&deadline, NULL);
|
||||
deadline.tv_sec++;
|
||||
|
||||
while (1) {
|
||||
notice_quit();
|
||||
if (quit_flag)
|
||||
quit();
|
||||
|
||||
FD_ZERO(&rd);
|
||||
FD_SET(ipkdb_desc, &rd);
|
||||
gettimeofday(&tv, NULL);
|
||||
tv.tv_sec = deadline.tv_sec - tv.tv_sec;
|
||||
tv.tv_usec = deadline.tv_usec - tv.tv_usec;
|
||||
if (tv.tv_usec < 0) {
|
||||
tv.tv_usec += 1000000;
|
||||
tv.tv_sec--;
|
||||
}
|
||||
if (tv.tv_sec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
switch (select(ipkdb_desc + 1, &rd, NULL, NULL, &tv)) {
|
||||
case -1:
|
||||
if (errno == EINTR
|
||||
#ifdef ECONNREFUSED
|
||||
|| errno == ECONNREFUSED /* Solaris lossage??? */
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
fatal("getpkt: select");
|
||||
default:
|
||||
if (read(ipkdb_desc, ibuf, sizeof ibuf) < 0) {
|
||||
if (errno == EINTR
|
||||
#ifdef ECONNREFUSED
|
||||
|| errno == ECONNREFUSED /* Solaris lossage??? */
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
fatal("getpkt: recvfrom");
|
||||
}
|
||||
if (getnl(ibuf) != netseq)
|
||||
break;
|
||||
len = getns(ibuf + 4);
|
||||
if (!memcmp(chksum(ibuf, len + 6), ibuf + 6 + len, 16)) {
|
||||
netseq++;
|
||||
memcpy(buf, ibuf + 6, len);
|
||||
*lp = len;
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Packet had correct sequence number, but
|
||||
* wrong checksum, do an immediate retry, so...
|
||||
*/
|
||||
/* FALLTHROUGH */
|
||||
case 0:
|
||||
if (write(ipkdb_desc, obuf, olen) < 0) {
|
||||
if (errno == EINTR
|
||||
#ifdef ECONNREFUSED
|
||||
|| errno == ECONNREFUSED /* Solaris lossage??? */
|
||||
#endif
|
||||
)
|
||||
continue;
|
||||
fatal("getpkt: write");
|
||||
}
|
||||
gettimeofday(&deadline, NULL);
|
||||
deadline.tv_sec++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Defint the target subroutine names */
|
||||
static struct target_ops ipkdb_ops = {
|
||||
"ipkdb",
|
||||
"Remote IPKDB target via UDP/IP",
|
||||
"Debug a remote computer via UDP/IP.\n\"
|
||||
Specify the name of the target machine",
|
||||
ipkdb_open,
|
||||
ipkdb_close,
|
||||
0, /* attach */
|
||||
ipkdb_detach,
|
||||
ipkdb_resume,
|
||||
ipkdb_wait,
|
||||
ipkdb_fetch_register,
|
||||
ipkdb_store_register,
|
||||
ipkdb_prepare_to_store,
|
||||
ipkdb_xfer_memory,
|
||||
ipkdb_files_info,
|
||||
ipkdb_insert_breakpoint,
|
||||
ipkdb_remove_breakpoint,
|
||||
0, /* terminal_init */
|
||||
0, /* terminal_inferior */
|
||||
0, /* terminal_ours_for_output */
|
||||
0, /* terminal_ours */
|
||||
0, /* terminal_info */
|
||||
ipkdb_kill,
|
||||
0, /* load */
|
||||
0, /* lookup_symbol */
|
||||
0, /* create_inferior */
|
||||
0, /* mourn_inferior */
|
||||
0, /* can_run */
|
||||
0, /* notice_signals */
|
||||
0, /* thread_alive */
|
||||
0, /* stop */
|
||||
process_stratum, /* stratum */
|
||||
0, /* next (unused) */
|
||||
1, /* has_all_memory */
|
||||
1, /* has_memory */
|
||||
1, /* has_stack */
|
||||
1, /* has_registers */
|
||||
1, /* has_execution */
|
||||
0, /* sections */
|
||||
0, /* sections_end */
|
||||
OPS_MAGIC /* Always the last thing */
|
||||
};
|
||||
|
||||
void
|
||||
_initialize_ipkdb()
|
||||
{
|
||||
add_target(&ipkdb_ops);
|
||||
|
||||
setkeycmd = add_set_cmd("ipkdbkey", class_support, var_string,
|
||||
(char *)&key,
|
||||
"Set the key to be used for authentication of IPKDB debugging.\n\
|
||||
The key given must be at least 16 bytes in length.",
|
||||
&setlist);
|
||||
setkeycmd->function.sfunc = hmac_init;
|
||||
}
|
Loading…
Reference in New Issue