diff options
-rw-r--r-- | sockclnt.c | 352 | ||||
-rw-r--r-- | sockserv.c | 420 |
2 files changed, 772 insertions, 0 deletions
diff --git a/sockclnt.c b/sockclnt.c new file mode 100644 index 0000000..3e1f9bb --- /dev/null +++ b/sockclnt.c @@ -0,0 +1,352 @@ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <iconv.h> +#include <signal.h> + +#include <sys/wait.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/utsname.h> +#include <arpa/inet.h> + +#define BUFFER_SIZE (1024*1024) + +typedef struct { + int inpbufsz; + int outbufsz; + short port; + char* addr; + int debug; +} parms_t; + +char inpbuf[BUFFER_SIZE]; +char outbuf[BUFFER_SIZE]; +char cnvbuf[BUFFER_SIZE]; /* For iconv */ +void pid_printf(const char* msg, ...); +void pid_perror(char* msg); +#ifdef __MVS__ +size_t convert(iconv_t cd, char* inpbuf, size_t inplen, char* outbuf, size_t outlen); +#endif + +void init_parms(parms_t *parms, int argc, char* argv[]) +{ + int opt; +#ifdef __MVS__ + char* optarg = NULL; +#endif + + parms->inpbufsz = 0; + parms->outbufsz = 0; + parms->debug = 0; + parms->addr = NULL; + parms->port = 15000; + + while ((opt = getopt(argc, argv, ":i:o:p:a:d:")) != -1) { + /* printf("%c %s\n", opt, *__opargf()); */ +#ifdef __MVS__ + optarg = *__opargf(); +#endif + switch (opt) { + case 'i': /* Input buffer size */ + parms->inpbufsz = atoi(optarg); + break; + case 'o': /* Output buffer size */ + parms->outbufsz = atoi(optarg); + break; + case 'p': /* Port number */ + parms->port = (short) atoi(optarg); + break; + case 'a': /* Listen address */ + parms->addr = optarg; + break; + case 'd': /* Enable debug info */ + printf(optarg); + parms->debug = atoi(optarg); + break; + case ':': + printf("Invalid parm value\n!"); + default: + printf("%c\n", opt); + } + } +} + +in_addr_t convipv4(char* addrstr) { + + char *octet; + char* buffer = malloc(strlen(addrstr) + 1); + + if (buffer == NULL) { + /* if moc error - give safe response */ + return htonl(INADDR_ANY); + } + + in_addr_t addr = (in_addr_t) 0; + strcpy(buffer, addrstr); + + octet = strtok(buffer, "."); + while (octet != NULL) { + addr = (addr << 8) | (unsigned char) atoi(octet); + octet = strtok(NULL, "."); + } + free(buffer); + return htonl(addr); +} + +void handler(int signal) { + pid_t pid; + int stat; + while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { + pid_printf("Child process %d finished\n", pid); + } + + return; +} + +int main(int argc, char* argv[]) { + + parms_t parms; + + init_parms(&parms, argc, argv); + + int sock = -1; + int count = -1; + pid_t pid = 0; + pid_t fpid = 0; + +#ifdef __MVS__ + size_t cnvlen; + iconv_t cnvinp = iconv_open("IBM-1047", "ISO8859-1"); + iconv_t cnvout = iconv_open("ISO8859-1" , "IBM-1047"); +#endif + + pid = getpid(); + + /* set signal action */ + + struct sigaction signew; + struct sigaction sigold; + + sigemptyset(&signew.sa_mask); + + signew.sa_flags = SA_NOCLDWAIT; /*SA_NOCLDSTOP;*/ + signew.sa_flags = 0; + signew.sa_handler = handler; + + if (sigaction(SIGCHLD, &signew, &sigold) < 0) { + pid_perror("SIGACTION"); + } + + struct sockaddr_in servaddr, connaddr; + + servaddr.sin_family = AF_INET; + + /* read address from command line */ + if (parms.addr != NULL) { + servaddr.sin_addr.s_addr = convipv4(parms.addr); + pid_printf("IP address for connect: %s <0x%8.8X>\n", + parms.addr, + servaddr.sin_addr.s_addr); + } + else { + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + pid_printf("IP address for listen: 0.0.0.0 <0x%8.8X>\n", + servaddr.sin_addr.s_addr); + } + servaddr.sin_port = htons(parms.port); + + sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock < 0) { + pid_perror("SOCKET: "); + exit(1); + } + + /* Set size of receive buffer */ + if (parms.inpbufsz > 0) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &parms.inpbufsz, sizeof(parms.inpbufsz)) == -1) { + pid_perror("Error in setting socket option:"); + } + else { + pid_printf("InpBufSz: %d\n", parms.inpbufsz); + } + } + + /* Set size of send buffer */ + if (parms.outbufsz > 0) { + if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &parms.outbufsz, sizeof(parms.outbufsz)) == -1) { + pid_perror("Error in setting socket option:"); + } + else { + pid_printf("OutBufSz: %d\n", parms.outbufsz); + } + } + + /* Set reuse addr */ + int reuse = 1; + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { + pid_perror("Error in setting socket option SO_REUSEADDR"); + } + + if (connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) { + pid_perror("CONNECT"); + exit(1); + } + + char* message = "ala ma kota"; + count = snprintf(cnvbuf, sizeof(cnvbuf), "%s\n", message); +#ifdef __MVS__ + cnvlen = convert(cnvout, (char *) cnvbuf, count, (char *) outbuf, sizeof(outbuf)); + count = write(sock, outbuf, cnvlen); +#else + count = write(sock, cnvbuf, count); +#endif + + close(sock); + +#ifdef __MVS__ + iconv_close(cnvinp); + iconv_close(cnvout); +#endif + + pid_printf("Main process finished\n"); + return 0; + + +} + +#ifdef __MVS__ +size_t convert(iconv_t cd, char* inpbuf, size_t inplen, char* outbuf, size_t outlen) { + + /* iconv variables */ + int rc; + char* inpptr; + char* outptr; + size_t inpcnt; + size_t outcnt; + + inpptr = inpbuf; + outptr = outbuf; + inpcnt = inplen; + outcnt = outlen; +#ifdef DEBUG + pid_printf("Buffer: "); + for (int i = 0; i < inplen; ++i) { + printf("%2.2X", inpbuf + i); + } + printf("\n"); + +#endif + + rc = iconv(cd, &inpptr, &inpcnt, &outptr, &outcnt); + + outlen = outlen - outcnt; + +#ifdef DEBUG + pid_printf("Iconv: rc=%d errno=%d inpcnt=%d outcnt=%d\n", rc, errno, inpcnt, outcnt); + + pid_printf("Output: "); + for (int i = 0; i < outlen; ++i) { + printf("%2.2X", outbuf + i); + } +#endif + printf("\n"); + + if (rc == ((size_t) -1)) { + return (size_t) 0; + } + + return (size_t) outlen; +} + +#endif + +void example_gethostbyname(char* addr) { + + struct hostent *hostinfo; + + printf("%s\n", addr); + hostinfo = gethostbyname(addr); + if (hostinfo != NULL) { + char* name = NULL; + char** p; + p = hostinfo->h_aliases; + name = *p++; + while(name != NULL) { + printf("%s\n", name); + name = *p++; + } + + /* Address list print */ + char* addr = NULL; + p = hostinfo->h_addr_list; + addr = *p++; + while(addr != NULL) { + for (int i = 0; i < 4; ++i) { + printf("%2.2X\n", addr[i]); + } + addr = *p++; + } + } + else { +#ifdef __MVS__ + printf("Error(threads): %d\n", *__h_errno()); +#endif + printf("Error: %d\n", h_errno); + } + exit(0); +} + +void pid_printf(const char* format, ...) { + pid_t pid = getpid(); + char* fmtptr = NULL; + int fmtlen = 0; + char* bufptr = NULL; + int buflen = 0; + char* fmtpfx = "%8.8X "; + + /* + fmtlen = strlen(fmtpfx) + strlen(format) + 1; + fmtptr = malloc(fmtlen); + + if (fmtptr) { + strncpy(fmtptr, fmtpfx, fmtlen); + strncat(fmtptr, format, fmtlen); + printf(fmtptr, pid, va_list + free(fmtptr); + } + */ + printf("%8.8X ", pid); + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + + fflush(stdout); + return; +} + +void pid_perror(char* msg) { + pid_t pid = getpid(); + char* bufptr = NULL; + int buflen = 0; + + buflen = 8 + 1 + strlen(msg) + 1; + bufptr = malloc(buflen); + + if (bufptr) { + snprintf(bufptr, buflen, "%8.8X %s", pid, msg); + perror(bufptr); + fflush(stderr); + free(bufptr); + } + + + return; +} \ No newline at end of file diff --git a/sockserv.c b/sockserv.c new file mode 100644 index 0000000..6c675ee --- /dev/null +++ b/sockserv.c @@ -0,0 +1,420 @@ +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <iconv.h> +#include <signal.h> + +#include <sys/wait.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/utsname.h> +#include <arpa/inet.h> + +#define BUFFER_SIZE (1024*1024) + +typedef struct { + int inpbufsz; + int outbufsz; + short port; + char* addr; + int debug; +} parms_t; + +char inpbuf[BUFFER_SIZE]; +char outbuf[BUFFER_SIZE]; +char cnvbuf[BUFFER_SIZE]; /* For iconv */ +void pid_printf(const char* msg, ...); +void pid_perror(char* msg); +#ifdef __MVS__ +size_t convert(iconv_t cd, char* inpbuf, size_t inplen, char* outbuf, size_t outlen); +#endif + +void init_parms(parms_t *parms, int argc, char* argv[]) +{ + int opt; +#ifdef __MVS__ + char* optarg = NULL; +#endif + + parms->inpbufsz = 0; + parms->outbufsz = 0; + parms->debug = 0; + parms->addr = NULL; + parms->port = 15000; + + while ((opt = getopt(argc, argv, ":i:o:p:a:d:")) != -1) { + /* printf("%c %s\n", opt, *__opargf()); */ +#ifdef __MVS__ + optarg = *__opargf(); +#endif + switch (opt) { + case 'i': /* Input buffer size */ + parms->inpbufsz = atoi(optarg); + break; + case 'o': /* Output buffer size */ + parms->outbufsz = atoi(optarg); + break; + case 'p': /* Port number */ + parms->port = (short) atoi(optarg); + break; + case 'a': /* Listen address */ + parms->addr = optarg; + break; + case 'd': /* Enable debug info */ + printf(optarg); + parms->debug = atoi(optarg); + break; + case ':': + printf("Invalid parm value\n!"); + default: + printf("%c\n", opt); + } + } +} + +in_addr_t convipv4(char* addrstr) { + + char *octet; + char* buffer = malloc(strlen(addrstr) + 1); + + if (buffer == NULL) { + /* if moc error - give safe response */ + return htonl(INADDR_ANY); + } + + in_addr_t addr = (in_addr_t) 0; + strcpy(buffer, addrstr); + + octet = strtok(buffer, "."); + while (octet != NULL) { + addr = (addr << 8) | (unsigned char) atoi(octet); + octet = strtok(NULL, "."); + } + free(buffer); + return htonl(addr); +} + +void handler(int signal) { + pid_t pid; + int stat; + while ((pid = waitpid(-1, &stat, WNOHANG)) > 0) { + pid_printf("Child process %d finished\n", pid); + } + + return; +} + +int main(int argc, char* argv[]) { + + parms_t parms; + + init_parms(&parms, argc, argv); + + int sock = -1; + int conn = -1; + int count = -1; + pid_t pid = 0; + pid_t fpid = 0; + iconv_t cnvinp; + iconv_t cnvout; + + pid = getpid(); + + /* set signal action */ + + struct sigaction signew; + struct sigaction sigold; + + sigemptyset(&signew.sa_mask); + + signew.sa_flags = SA_NOCLDWAIT; /*SA_NOCLDSTOP;*/ + signew.sa_flags = 0; + signew.sa_handler = handler; + + if (sigaction(SIGCHLD, &signew, &sigold) < 0) { + pid_perror("SIGACTION"); + } + + struct sockaddr_in servaddr, connaddr; + + servaddr.sin_family = AF_INET; + + /* read address from command line */ + if (parms.addr != NULL) { + servaddr.sin_addr.s_addr = convipv4(parms.addr); + pid_printf("IP address for listen: %s <0x%8.8X>\n", + parms.addr, + servaddr.sin_addr.s_addr); + } + else { + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + pid_printf("IP address for listen: 0.0.0.0 <0x%8.8X>\n", + servaddr.sin_addr.s_addr); + } + servaddr.sin_port = htons(parms.port); + + sock = socket(AF_INET, SOCK_STREAM, 0); + + if (sock < 0) { + pid_perror("SOCKET: "); + exit(1); + } + + /* Set size of receive buffer */ + if (parms.inpbufsz > 0) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &parms.inpbufsz, sizeof(parms.inpbufsz)) == -1) { + pid_perror("Error in setting socket option:"); + } + else { + pid_printf("InpBufSz: %d\n", parms.inpbufsz); + } + } + + /* Set size of send buffer */ + if (parms.outbufsz > 0) { + if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &parms.outbufsz, sizeof(parms.outbufsz)) == -1) { + pid_perror("Error in setting socket option:"); + } + else { + pid_printf("OutBufSz: %d\n", parms.outbufsz); + } + } + + /* Set reuse addr */ + int reuse = 1; + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) { + pid_perror("Error in setting socket option SO_REUSEADDR"); + } + + if (bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) { + pid_perror("BIND"); + exit(1); + } + + if (listen(sock, 10) == -1) { + pid_perror("LISTEN"); + exit(1); + } + + + struct utsname info; + char nodename[5] = "----"; + if (uname(&info) == -1) { + pid_perror("Uname error:"); + } else { + strncpy(nodename, info.nodename, sizeof(nodename)); + } + + cnvinp = iconv_open("IBM-1047", "ISO8859-1"); + cnvout = iconv_open("ISO8859-1" , "IBM-1047"); + for ( ; ; ) { + size_t cnvlen; + socklen_t connsize = sizeof(connaddr); + + conn = accept(sock, (struct sockaddr *) &connaddr, &connsize); + if (conn < 0) { + if (errno == EINTR) { + continue; /* interrupted syscall */ + } else { + pid_perror("ACCEPT:"); + exit(1); + } + } + fpid = fork(); + if (fpid == 0) { + /* Here inside child process */ + pid_printf("Forked process initialized\n"); + close(sock); + + + pid_printf("IP address for serv: <0x%8.8X>\n", servaddr.sin_addr.s_addr); + pid_printf("IP port for serv: <%5d>\n", servaddr.sin_port); + pid_printf("IP address for peer: <0x%8.8X>\n", connaddr.sin_addr.s_addr); + pid_printf("IP port for peer: <%5d>\n", connaddr.sin_port); + + char locip[256]; + char rmtip[265]; + strcpy(locip, inet_ntoa(servaddr.sin_addr)); + strcpy(rmtip, inet_ntoa(connaddr.sin_addr)); + count = snprintf(cnvbuf, sizeof(cnvbuf), "%s PID:%8.8X LOC-IP:%s:%05.5d RMT-IP:%s:%05.5d \n", + nodename, getpid(), locip, servaddr.sin_port, rmtip, connaddr.sin_port); +#ifdef __MVS__ + cnvlen = convert(cnvout, (char *) cnvbuf, count, (char *) outbuf, sizeof(outbuf)); + count = write(conn, outbuf, cnvlen); +#else + count = write(conn, cnvbuf, count); +#endif + + + count = read(conn, inpbuf, sizeof(inpbuf)); + while (count > 0) { + pid_printf("Packet received, size: %d\n", count); + + if (parms.debug != 0) { +#ifdef __MVS__ + cnvlen = convert(cnvinp, (char *) inpbuf, count, (char *) cnvbuf, sizeof(cnvbuf)); + pid_printf("Packet bytes below: \n%.*s\n", cnvlen, cnvbuf); +#else + pid_printf("Packet bytes below: \n%.*s\n", count, inpbuf); +#endif + } + + count = read(conn, inpbuf, sizeof(inpbuf)); + } + if (count == 0) { + pid_printf("Forked process will be finished\n"); + } + else if (count < 0 ) { + pid_printf("ERRNO: %d\n", fpid, errno); + pid_printf("Interrupt\n"); + } + + exit(0); + } + close(conn); + } + + iconv_close(cnvinp); + iconv_close(cnvout); + close(sock); + + pid_printf("Main process finished\n"); + return 0; + + +} + +#ifdef __MVS__ +size_t convert(iconv_t cd, char* inpbuf, size_t inplen, char* outbuf, size_t outlen) { + + /* iconv variables */ + int rc; + char* inpptr; + char* outptr; + size_t inpcnt; + size_t outcnt; + + inpptr = inpbuf; + outptr = outbuf; + inpcnt = inplen; + outcnt = outlen; +#ifdef DEBUG + pid_printf("Buffer: "); + for (int i = 0; i < inplen; ++i) { + printf("%2.2X", inpbuf + i); + } + printf("\n"); + +#endif + + rc = iconv(cd, &inpptr, &inpcnt, &outptr, &outcnt); + + outlen = outlen - outcnt; + +#ifdef DEBUG + pid_printf("Iconv: rc=%d errno=%d inpcnt=%d outcnt=%d\n", rc, errno, inpcnt, outcnt); + + pid_printf("Output: "); + for (int i = 0; i < outlen; ++i) { + printf("%2.2X", outbuf + i); + } +#endif + printf("\n"); + + if (rc == ((size_t) -1)) { + return (size_t) 0; + } + + return (size_t) outlen; +} + +#endif + +void example_gethostbyname(char* addr) { + + struct hostent *hostinfo; + + printf("%s\n", addr); + hostinfo = gethostbyname(addr); + if (hostinfo != NULL) { + char* name = NULL; + char** p; + p = hostinfo->h_aliases; + name = *p++; + while(name != NULL) { + printf("%s\n", name); + name = *p++; + } + + /* Address list print */ + char* addr = NULL; + p = hostinfo->h_addr_list; + addr = *p++; + while(addr != NULL) { + for (int i = 0; i < 4; ++i) { + printf("%2.2X\n", addr[i]); + } + addr = *p++; + } + } + else { +#ifdef __MVS__ + printf("Error(threads): %d\n", *__h_errno()); +#endif + printf("Error: %d\n", h_errno); + } + exit(0); +} + +void pid_printf(const char* format, ...) { + pid_t pid = getpid(); + char* fmtptr = NULL; + int fmtlen = 0; + char* bufptr = NULL; + int buflen = 0; + char* fmtpfx = "%8.8X "; + + /* + fmtlen = strlen(fmtpfx) + strlen(format) + 1; + fmtptr = malloc(fmtlen); + + if (fmtptr) { + strncpy(fmtptr, fmtpfx, fmtlen); + strncat(fmtptr, format, fmtlen); + printf(fmtptr, pid, va_list + free(fmtptr); + } + */ + printf("%8.8X ", pid); + va_list args; + va_start(args, format); + vprintf(format, args); + va_end(args); + + fflush(stdout); + return; +} + +void pid_perror(char* msg) { + pid_t pid = getpid(); + char* bufptr = NULL; + int buflen = 0; + + buflen = 8 + 1 + strlen(msg) + 1; + bufptr = malloc(buflen); + + if (bufptr) { + snprintf(bufptr, buflen, "%8.8X %s", pid, msg); + perror(bufptr); + fflush(stderr); + free(bufptr); + } + + + return; +} \ No newline at end of file |