From: Don Slutz <dslutz@xxxxxxxxxxx> The new macro NIL_MODE() reflexs this state. This is the code to correctly handle that fact that TCP/IP is a stream protocol and not a "line" protocol. NIL mode is the new term interduced here to describe the zero byte termination that was added to do this. It is fully backwards compattable because the commands were terminated with a zero byte on both ends already and a extra zero byte does not affect a C array of chars. Signed-off-by: Don Slutz <dslutz@xxxxxxxxxxx> --- remote.c | 241 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 171 insertions(+), 70 deletions(-) diff --git a/remote.c b/remote.c index fca08a1..95ce03d 100755 --- a/remote.c +++ b/remote.c @@ -1808,6 +1808,20 @@ 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 *); + +struct _remote_context { + uint flags; +} remote_context; + +#define NIL_FLAG (0x01U) + +#define NIL_MODE() (rc->flags & NIL_FLAG) + +struct _remote_context *rc = &remote_context; /* * Parse, verify and establish a connection with the network daemon @@ -1921,6 +1935,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>")) + rc->flags |= NIL_FLAG; /* * Get the remote machine type and verify a match. The daemon pid * is also used as a live system initial context. @@ -1928,8 +1952,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, NIL_MODE()); p1 = strtok(recvbuf, " "); /* MACHINE */ p1 = strtok(NULL, " "); /* machine type */ if (CRASHDEBUG(1)) @@ -2032,8 +2056,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) error(FATAL, "invalid remote file name: %s\n", file); @@ -2112,6 +2136,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 +2226,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, NIL_MODE()); if (CRASHDEBUG(1)) fprintf(fp, "remote_file_open: [%s]\n", recvbuf); @@ -2159,8 +2261,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, NIL_MODE()); return (strstr(recvbuf, "OK") ? TRUE : FALSE); } @@ -2177,8 +2279,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, NIL_MODE()); if (STREQ(recvbuf, "<FAIL>")) return FALSE; strcpy(buf, recvbuf); @@ -2359,8 +2461,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, NIL_MODE()); if (strstr(recvbuf, "NO_DEBUG")) { sprintf(readbuf, "%s@%s", rfp->filename, pc->server); pc->namelist = readbuf; @@ -2472,8 +2574,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2515,8 +2617,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) { error(INFO, "%s: does not exist on server %s\n", rfp->filename, pc->server); @@ -2785,8 +2887,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, NIL_MODE()); strtok(recvbuf, " "); /* FIND_BOOTED_KERNEL */ p1 = strtok(NULL, " "); /* filename */ if (STREQ(p1, "<FAIL>")) @@ -2806,8 +2908,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2844,8 +2946,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2880,8 +2982,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) return FALSE; @@ -2925,8 +3027,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, NIL_MODE()); if (strstr(recvbuf, "FAIL")) error(FATAL, "cannot determine remote page size\n"); strtok(recvbuf, " "); /* PAGESIZE */ @@ -2968,7 +3070,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 +3161,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 +3272,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, NIL_MODE()); if (strstr(recvbuf, "<FAIL>")) { fprintf(fp, "find_remote_module_objfile: [%s]\n", recvbuf); @@ -3231,8 +3333,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, NIL_MODE()); p1 = strtok(recvbuf, " "); /* MEMORY */ p1 = strtok(NULL, " "); /* FREE */ p1 = strtok(NULL, " "); /* MCLXCD, LKCD etc. */ @@ -3267,8 +3369,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, NIL_MODE()); p1 = strtok(recvbuf, " "); /* MEMORY */ p1 = strtok(NULL, " "); /* FREE */ p1 = strtok(NULL, " "); /* MCLXCD, LKCD, etc. */ @@ -3308,7 +3410,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 +3473,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 +3492,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 +3594,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 +3663,11 @@ 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, NIL_MODE()); } #endif /* !DAEMON */ - -- 1.8.4 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility