From: Don Slutz <dslutz@xxxxxxxxxxx> Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx> --- defs.h | 1 + remote.c | 241 +++++++++++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 173 insertions(+), 69 deletions(-) diff --git a/defs.h b/defs.h index a5299cc..108ffc1 100755 --- a/defs.h +++ b/defs.h @@ -504,6 +504,7 @@ struct program_context { #define GET_LOG (0x200ULL) #define VMCOREINFO (0x400ULL) #define ALLOW_FP (0x800ULL) +#define REMOTE_NIL (0x1000ULL) char *cleanup; char *namelist_orig; char *namelist_debug_orig; diff --git a/remote.c b/remote.c index fca08a1..e64f2bd 100755 --- a/remote.c +++ b/remote.c @@ -1808,6 +1808,10 @@ static int remote_file_type(char *); static int remote_lkcd_dump_init(void); static int remote_s390_dump_init(void); static int remote_netdump_init(void); +static int remote_tcp_read(int, const char *, size_t); +static int remote_tcp_read_string(int, const char *, size_t, int); +static int remote_tcp_write(int, const void *, size_t); +static int remote_tcp_write_string(int, const char *); /* * Parse, verify and establish a connection with the network daemon @@ -1921,6 +1925,16 @@ is_remote_daemon(char *dp) remote_socket_options(pc->sockfd); + /* + * Try and use NIL mode. + */ + BZERO(sendbuf, BUFSIZE); + BZERO(recvbuf, BUFSIZE); + sprintf(sendbuf, "NIL"); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, 0); + if (!strstr(recvbuf, "<FAIL>")) + pc->flags2 |= REMOTE_NIL; /* * Get the remote machine type and verify a match. The daemon pid * is also used as a live system initial context. @@ -1928,8 +1942,8 @@ is_remote_daemon(char *dp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "MACHINE_PID"); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); p1 = strtok(recvbuf, " "); /* MACHINE */ p1 = strtok(NULL, " "); /* machine type */ if (CRASHDEBUG(1)) @@ -2032,8 +2046,8 @@ remote_file_type(char *file) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "TYPE %s", file); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) error(FATAL, "invalid remote file name: %s\n", file); @@ -2112,6 +2126,84 @@ remote_socket_options(int sockfd) } /* + * Wrapper around recv to read full length packet. + */ +static int +remote_tcp_read(int sock, const char *pv_buffer, size_t cb_buffer) +{ + size_t cb_total = 0; + + do + { + ssize_t cb_read = recv(sock, (void*)pv_buffer, cb_buffer, MSG_NOSIGNAL); + + if (cb_read <= 0) + return cb_read; + cb_total += cb_read; + cb_buffer -= cb_read; + pv_buffer = (char *)pv_buffer + cb_read; + } while (cb_buffer); + + return cb_total; +} + +/* + * Wrapper around recv to read full string packet. + */ +static int +remote_tcp_read_string(int sock, const char *pv_buffer, size_t cb_buffer, int nil_mode) +{ + size_t cb_total = 0; + + do + { + ssize_t cb_read = recv(sock, (void*)pv_buffer, cb_buffer, MSG_NOSIGNAL); + + if (cb_read <= 0) + return cb_read; + cb_total += cb_read; + if (!nil_mode && cb_total >= 4) + return cb_total; + if (!pv_buffer[cb_read - 1]) + return cb_total; + cb_buffer -= cb_read; + pv_buffer = (char *)pv_buffer + cb_read; + } while (cb_buffer); + + return cb_total; +} + +/* + * Wrapper around send to send full packet. + */ +static int +remote_tcp_write(int sock, const void *pv_buffer, size_t cb_buffer) +{ + do + { + size_t cb_now = cb_buffer; + ssize_t cb_written = send(sock, (const char *)pv_buffer, cb_now, MSG_NOSIGNAL); + + if (cb_written < 0) + return 1; + cb_buffer -= cb_written; + pv_buffer = (char *)pv_buffer + cb_written; + } while (cb_buffer); + + return 0; +} + +/* + * Wrapper around tcp_write to send a string + */ +static int +remote_tcp_write_string(int sock, const char *pv_buffer) +{ + return remote_tcp_write(sock, pv_buffer, strlen(pv_buffer) + 1); +} + + +/* * Request that the daemon open a file. */ static int @@ -2124,8 +2216,8 @@ remote_file_open(struct remote_file *rfp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "OPEN %s", rfp->filename); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (CRASHDEBUG(1)) fprintf(fp, "remote_file_open: [%s]\n", recvbuf); @@ -2159,8 +2251,8 @@ remote_file_close(struct remote_file *rfp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "CLOSE %d", rfp->fd); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); return (strstr(recvbuf, "OK") ? TRUE : FALSE); } @@ -2177,8 +2269,8 @@ remote_proc_version(char *buf) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "PROC_VERSION"); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (STREQ(recvbuf, "<FAIL>")) return FALSE; strcpy(buf, recvbuf); @@ -2359,8 +2451,8 @@ copy_to_local_namelist(struct remote_file *rfp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "DEBUGGING_SYMBOLS %s", rfp->filename); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "NO_DEBUG")) { sprintf(readbuf, "%s@%s", rfp->filename, pc->server); pc->namelist = readbuf; @@ -2472,8 +2564,8 @@ identical_namelist(char *file, struct remote_file *rfp) BZERO(readbuf, BUFSIZE); sprintf(sendbuf, "LINUX_VERSION %s", rfp->filename); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2515,8 +2607,8 @@ remote_file_checksum(struct remote_file *rfp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "SUM %s", rfp->filename); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) { error(INFO, "%s: does not exist on server %s\n", rfp->filename, pc->server); @@ -2785,8 +2877,8 @@ remote_find_booted_kernel(struct remote_file *rfp) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "FIND_BOOTED_KERNEL"); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); strtok(recvbuf, " "); /* FIND_BOOTED_KERNEL */ p1 = strtok(NULL, " "); /* filename */ if (STREQ(p1, "<FAIL>")) @@ -2806,8 +2898,8 @@ remote_lkcd_dump_init(void) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "LKCD_DUMP_INIT %d %s", pc->rmfd, pc->server_memsrc); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2844,8 +2936,8 @@ remote_s390_dump_init(void) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "S390_DUMP_INIT %d %s", pc->rmfd, pc->server_memsrc); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2880,8 +2972,8 @@ remote_netdump_init(void) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "NETDUMP_INIT %d %s", pc->rmfd, pc->server_memsrc); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2925,8 +3017,8 @@ remote_page_size(void) error(FATAL, "cannot determine remote page size (unknown memory source)\n"); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "FAIL")) error(FATAL, "cannot determine remote page size\n"); strtok(recvbuf, " "); /* PAGESIZE */ @@ -2968,7 +3060,7 @@ copy_remote_file(struct remote_file *rfp, int fd, char *file, char *ttystr) BZERO(sendbuf, BUFSIZE); sprintf(sendbuf, "READ %d %lx %ld", rfp->fd, offset, size); - bytes = write(pc->sockfd, sendbuf, strlen(sendbuf)); + bytes = write(pc->sockfd, sendbuf, strlen(sendbuf) + 1); bzero(readbuf, READBUFSIZE); @@ -3059,7 +3151,7 @@ copy_remote_gzip_file(struct remote_file *rfp, char *file, char *ttystr) BZERO(sendbuf, BUFSIZE); sprintf(sendbuf, "READ_GZIP %ld %s", pc->rcvbufsize, rfp->filename); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); + remote_tcp_write_string(pc->sockfd, sendbuf); bzero(readbuf, READBUFSIZE); @@ -3170,8 +3262,8 @@ find_remote_module_objfile(struct load_module *lm, char *module, char *retbuf) BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "FIND_MODULE %s %s", kt->utsname.release, module); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); if (strstr(recvbuf, "<FAIL>")) { fprintf(fp, "find_remote_module_objfile: [%s]\n", recvbuf); @@ -3231,8 +3323,8 @@ remote_free_memory(void) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "MEMORY FREE %s", type); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); p1 = strtok(recvbuf, " "); /* MEMORY */ p1 = strtok(NULL, " "); /* FREE */ p1 = strtok(NULL, " "); /* MCLXCD, LKCD etc. */ @@ -3267,8 +3359,8 @@ remote_memory_used(void) BZERO(sendbuf, BUFSIZE); BZERO(recvbuf, BUFSIZE); sprintf(sendbuf, "MEMORY USED %s", type); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - recv(pc->sockfd, recvbuf, BUFSIZE-1, 0); + remote_tcp_write_string(pc->sockfd, sendbuf); + remote_tcp_read_string(pc->sockfd, recvbuf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); p1 = strtok(recvbuf, " "); /* MEMORY */ p1 = strtok(NULL, " "); /* FREE */ p1 = strtok(NULL, " "); /* MCLXCD, LKCD, etc. */ @@ -3308,7 +3400,7 @@ remote_memory_dump(int verbose) BZERO(sendbuf, BUFSIZE); sprintf(sendbuf, "MEMORY_DUMP %ld %s%s", pc->rcvbufsize, type, verbose ? "_VERBOSE" : ""); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); + remote_tcp_write_string(pc->sockfd, sendbuf); bzero(readbuf, READBUFSIZE); done = total = 0; @@ -3371,10 +3463,9 @@ int remote_memory_read(int rfd, char *buffer, int cnt, physaddr_t address) { char sendbuf[BUFSIZE]; - char readbuf[READBUFSIZE]; char datahdr[DATA_HDRSIZE]; - char *bufptr, *p1; - int ret, req, tot; + char *p1; + int ret, tot; ulong addr; addr = (ulong)address; /* may be virtual */ @@ -3391,48 +3482,49 @@ remote_memory_read(int rfd, char *buffer, int cnt, physaddr_t address) else sprintf(sendbuf, "READ_LIVE %d %lx %d", rfd, addr, cnt); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); - - bzero(readbuf, READBUFSIZE); + if (remote_tcp_write_string(pc->sockfd, sendbuf)) + return -1; /* * Read request will come back with a singular header * followed by the data. */ - req = cnt+DATA_HDRSIZE; - tot = 0; - errno = 0; - bufptr = readbuf; - - while (req) { - if ((ret = recv(pc->sockfd, bufptr, req, 0)) == -1) - return -1; - req -= ret; - bufptr += ret; - tot += ret; - if ((tot >= DATA_HDRSIZE) && STRNEQ(readbuf, FAILMSG)) { - p1 = strtok(readbuf, " "); /* FAIL */ - p1 = strtok(NULL, " "); /* errno */ - errno = atoi(p1); - return -1; - } + BZERO(datahdr, DATA_HDRSIZE); + ret = remote_tcp_read_string(pc->sockfd, datahdr, DATA_HDRSIZE, 1); + if (ret <= 0) + return -1; + if (CRASHDEBUG(3)) + fprintf(fp, "remote_memory_read: [%s]\n", datahdr); + if (STRNEQ(datahdr, FAILMSG)) { + p1 = strtok(datahdr, " "); /* FAIL */ + p1 = strtok(NULL, " "); /* errno */ + errno = atoi(p1); + return -1; } - - if (!STRNEQ(readbuf, DONEMSG) && !STRNEQ(readbuf, DATAMSG)) { + if (!STRNEQ(datahdr, DONEMSG) && !STRNEQ(datahdr, DATAMSG)) { error(INFO, "out of sync with remote memory source\n"); return -1; } - strncpy(datahdr, readbuf, DATA_HDRSIZE); - if (CRASHDEBUG(3)) - fprintf(fp, "remote_memory_read: [%s]\n", datahdr); - p1 = strtok(datahdr, " "); /* DONE */ - p1 = strtok(NULL, " "); /* count */ + p1 = strtok(datahdr, " "); /* DONE */ + p1 = strtok(NULL, " "); /* count */ tot = atol(p1); - BCOPY(readbuf+DATA_HDRSIZE, buffer, tot); + if (cnt != tot) { + error(FATAL, + "requested %d bytes remote memory return %d bytes\n", + cnt, tot); + return -1; + } + ret = remote_tcp_read(pc->sockfd, buffer, tot); + if (ret != tot) { + error(FATAL, + "requested %d bytes remote memory return %d bytes\n", + ret, tot); + return -1; + } return tot; } @@ -3492,7 +3584,7 @@ remote_execute(void) BZERO(sendbuf, BUFSIZE); sprintf(sendbuf, "EXECUTE %ld %s", pc->rcvbufsize, command); - send(pc->sockfd, sendbuf, strlen(sendbuf), 0); + remote_tcp_write_string(pc->sockfd, sendbuf); bzero(readbuf, READBUFSIZE); done = total = 0; @@ -3561,12 +3653,23 @@ remote_exit(void) BZERO(buf, BUFSIZE); sprintf(buf, "EXIT"); - send(pc->sockfd, buf, strlen(buf), 0); + remote_tcp_write_string(pc->sockfd, buf); /* * Read but ignore the return status -- we don't really care... */ - recv(pc->sockfd, buf, BUFSIZE-1, 0); + remote_tcp_read_string(pc->sockfd, buf, BUFSIZE-1, pc->flags2 & REMOTE_NIL); } #endif /* !DAEMON */ +/* + * Specify Emacs local variables so the formating + * of the code stays the same. + * + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 8 + * indent-tabs-mode: t + * End: + */ -- 1.8.4 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility