/****************************************************************** * FUNCTION configure_logging * * Configure debug logging. This function evaluates command line * arguments to configure debug logging. * ******************************************************************/ static void configure_logging( int argc, char** argv ) { char* err_filename; int arg_idx = 1; char defname[21]; strncpy(defname, "/tmp/subsys-err.log", 20); err_filename = defname; while ( arg_idx < argc-1 ) { if ( !strcmp( argv[arg_idx], "-filename" ) || !strcmp( argv[arg_idx], "-f" ) ) { err_filename = argv[++arg_idx]; if ( !traceLevel ) { traceLevel = 1; } } else if ( !strcmp( argv[arg_idx], "-trace" ) || !strcmp( argv[arg_idx], "-t" ) ) { traceLevel = atoi( argv[++arg_idx] ); } ++arg_idx; } if ( traceLevel ) { errfile = fopen( err_filename, "a" ); SUBSYS_TRACE1( "\n*** New netconf Session Started ***\n" ); } }
/******************************************************************** * FUNCTION do_read * * Read from a FD * * INPUTS: * * RETURNS: * return byte count *********************************************************************/ static ssize_t do_read (int readfd, char *readbuff, size_t readcnt, status_t *retres) { boolean readdone; ssize_t retcnt; readdone = FALSE; retcnt = 0; *retres = NO_ERR; while (!readdone && *retres == NO_ERR) { retcnt = read(readfd, readbuff, readcnt); if (retcnt < 0) { if (errno != EAGAIN) { SUBSYS_TRACE1( "ERROR: do_read(): read of FD(%d): " "failed with error: %s\n", readfd, strerror( errno ) ); *retres = ERR_NCX_READ_FAILED; continue; } } else if (retcnt == 0) { SUBSYS_TRACE1( "INFO: do_read(): closed connection\n"); *retres = ERR_NCX_EOF; readdone = TRUE; continue; } else { /* retcnt is the number of bytes read */ readdone = TRUE; } } /*end readdone loop */ return retcnt; } /* do_read */
/******************************************************************** * FUNCTION main * * STDIN is input from the SSH client (sent to ncxserver) * STDOUT is output to the SSH client (rcvd from ncxserver) * * RETURNS: * 0 if NO_ERR * 1 if error connecting or logging into ncxserver *********************************************************************/ int main (int argc, char **argv) { status_t res; const char *msg; char logfile[40] = "/tmp/netconf-subsystem.log"; errfile = fopen( logfile, "a" ); configure_logging( argc, argv ); res = init_subsys(); if (res != NO_ERR) { msg = "init failed"; } if (res == NO_ERR) { res = send_ncxconnect(); if (res != NO_ERR) { msg = "connect failed"; } } if (res == NO_ERR) { res = io_loop(); if (res != NO_ERR) { msg = "IO error"; } } if (res != NO_ERR) { SUBSYS_TRACE1( "ERROR: io_loop(): exited with error %s \n", msg ); } fprintf(errfile,"%s\n", msg); fflush(errfile); fprintf(errfile,"SESSION TERMINATED with %s:%s\n",client_addr, port); fflush(errfile); cleanup_subsys(); if (res != NO_ERR) { return 1; } else { return 0; } } /* main */
/******************************************************************** * FUNCTION main * * STDIN is input from the SSH client (sent to ncxserver) * STDOUT is output to the SSH client (rcvd from ncxserver) * * RETURNS: * 0 if NO_ERR * 1 if error connecting or logging into ncxserver *********************************************************************/ int main (int argc, char **argv) { status_t res; const char *msg; configure_logging( argc, argv ); res = init_subsys(argc, argv); if (res != NO_ERR) { msg = "init failed"; } if (res == NO_ERR) { res = send_ncxconnect(); if (res != NO_ERR) { msg = "connect failed"; } } if (res == NO_ERR) { res = io_loop(); if (res != NO_ERR) { msg = "IO error"; } } if (res != NO_ERR) { SUBSYS_TRACE1( "ERROR: io_loop(): exited with error %s \n", msg ); } cleanup_subsys(); if (res != NO_ERR) { return 1; } else { return 0; } } /* main */
/******************************************************************** * FUNCTION io_loop * * Handle the IO for the program * * INPUTS: * * RETURNS: * status *********************************************************************/ static status_t io_loop (void) { status_t res; boolean done; fd_set fds; int ret; ssize_t retcnt; res = NO_ERR; done = FALSE; FD_ZERO(&fds); while (!done) { FD_SET(STDIN_FILENO, &fds); FD_SET(ncxsock, &fds); ret = select(FD_SETSIZE, &fds, NULL, NULL, NULL); if (ret < 0) { if ( errno != EINTR ) { SUBSYS_TRACE1( "ERROR: io_loop(): select() " "failed with error: %s\n", strerror( errno ) ); res = ERR_NCX_OPERATION_FAILED; done = TRUE; } else { SUBSYS_TRACE2( "INFO: io_loop(): select() " "failed with error: %s\n", strerror( errno ) ); } continue; } else if (ret == 0) { SUBSYS_TRACE1( "ERROR: io_loop(): select() " "returned 0, exiting...\n" ); res = NO_ERR; done = TRUE; continue; } /* else some IO to process */ /* check any input from client */ if (FD_ISSET(STDIN_FILENO, &fds)) { /* get buff from openssh */ retcnt = do_read(STDIN_FILENO, msgbuff, (size_t)BUFFLEN, &res); if (res == ERR_NCX_EOF) { res = NO_ERR; done = TRUE; continue; } else if (res == ERR_NCX_SKIPPED) { res = NO_ERR; } else if (res == NO_ERR && retcnt > 0) { /* send this buffer to the ncxserver */ res = send_buff(ncxsock, msgbuff, (size_t)retcnt); if (res != NO_ERR) { SUBSYS_TRACE1( "ERROR: io_loop(): send_buff() to ncxserver " "failed with %s\n", strerror( errno ) ); done = TRUE; continue; } } } /* if STDIN set */ /* check any input from the ncxserver */ if (FD_ISSET(ncxsock, &fds)) { res = NO_ERR; retcnt = do_read(ncxsock, msgbuff, (size_t)BUFFLEN, &res); if (res == ERR_NCX_EOF) { res = NO_ERR; done = TRUE; continue; } else if (res == ERR_NCX_SKIPPED) { res = NO_ERR; } else if (res == NO_ERR && retcnt > 0) { /* send this buffer to STDOUT */ res = send_buff(STDOUT_FILENO, msgbuff, (size_t)retcnt); if (res != NO_ERR) { SUBSYS_TRACE1( "ERROR: io_loop(): send_buff() to client " "failed with %s\n", strerror( errno ) ); done = TRUE; continue; } } } } return res; } /* io_loop */
/******************************************************************** * FUNCTION init_subsys * * Initialize the subsystem, and get it ready to send and receive * the first message of any kind * * RETURNS: * status *********************************************************************/ static status_t init_subsys (void) { char *cp, *con; int ret; client_addr = NULL; port = NULL; user = NULL; ncxsock = -1; ncxconnect = FALSE; /* get the client address */ con = getenv("SSH_CONNECTION"); if (!con) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Get SSH_CONNECTION variable failed\n" ); return ERR_INTERNAL_VAL; } /* get the client addr */ client_addr = strdup(con); if (!client_addr) { SUBSYS_TRACE1( "ERROR: init_subsys(): strdup(client_addr) failed\n" ); return ERR_INTERNAL_MEM; } cp = strchr(client_addr, ' '); if (!cp) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Malformed SSH_CONNECTION variable\n" ); return ERR_INTERNAL_VAL; } else { *cp = 0; } /* get the server connect port */ cp = strrchr(con, ' '); if (cp && cp[1]) { port = strdup(++cp); } if (!port) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Malformed SSH_CONNECTION variable\n" ); return ERR_INTERNAL_VAL; } /* get the username */ cp = getenv("USER"); if (!cp) { SUBSYS_TRACE1( "ERROR: init_subsys(): Get USER variable failed\n"); return ERR_INTERNAL_VAL; } user = strdup(cp); if (!user) { SUBSYS_TRACE1( "ERROR: init_subsys(): strdup(user) failed\n" ); return ERR_INTERNAL_MEM; } /* make a socket to connect to the NCX server */ ncxsock = socket(PF_LOCAL, SOCK_STREAM, 0); if (ncxsock < 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Creation failed\n" ); return ERR_NCX_CONNECT_FAILED; } ncxname.sun_family = AF_LOCAL; /* --------- LEVI --------- */ char begin[16] = "/tmp/ncxserver_"; char end[6] = ".sock"; sprintf(NCX_SOCKETFILE,"%s%s%s",begin,port,end); fprintf(errfile, "\n\n====================\n" "Incoming session\n" "--------------------\n" "Client address: %s\n" "User: %s\n" "NETCONF Port: %s\n" "Socket file: %s\n" "====================\n", client_addr, user, port, NCX_SOCKETFILE); fflush(errfile); strncpy(ncxname.sun_path, NCX_SOCKETFILE, sizeof(ncxname.sun_path)); // strncpy(ncxname.sun_path, // NCXSERVER_SOCKNAME, // sizeof(ncxname.sun_path)); /* -------- END LEVI --------- */ /* try to connect to the NCX server */ ret = connect(ncxsock, (const struct sockaddr *)&ncxname, SUN_LEN(&ncxname)); if (ret != 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Connect failed\n" ); return ERR_NCX_OPERATION_FAILED; } else { SUBSYS_TRACE2( "INFO: init_subsys(): " "NCX Socket Connected on FD: %d \n", ncxsock ); ncxconnect = TRUE; } #ifdef USE_NONBLOCKING_IO /* set non-blocking IO */ if (fcntl(ncxsock, F_SETFD, O_NONBLOCK)) { SUBSYS_TRACE1( "ERROR: init_subsys(): fnctl() failed\n" ); } #endif /* connected to the ncxserver and setup the ENV vars ok */ return NO_ERR; } /* init_subsys */
/******************************************************************** * FUNCTION init_subsys * * Initialize the subsystem, and get it ready to send and receive * the first message of any kind * * RETURNS: * status *********************************************************************/ static status_t init_subsys (int argc, char** argv) { char *cp, *con; int ret; int name_size; int i; client_addr = NULL; port = NULL; user = NULL; ncxsock = -1; ncxconnect = FALSE; ncxport_inet = -1; for(i=1; i<argc; i++) { if(strlen(argv[i])>strlen("--tcp-direct-port=") && 0==memcmp(argv[i],"--tcp-direct-port=",strlen("--tcp-direct-port="))) { ncxport_inet = atoi(argv[i]+strlen("--tcp-direct-port=")); } } /* get the client address */ con = getenv("SSH_CONNECTION"); if (!con) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Get SSH_CONNECTION variable failed\n" ); return ERR_INTERNAL_VAL; } /* get the client addr */ client_addr = strdup(con); if (!client_addr) { SUBSYS_TRACE1( "ERROR: init_subsys(): strdup(client_addr) failed\n" ); return ERR_INTERNAL_MEM; } cp = strchr(client_addr, ' '); if (!cp) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Malformed SSH_CONNECTION variable\n" ); return ERR_INTERNAL_VAL; } else { *cp = 0; } /* get the server connect port */ cp = strrchr(con, ' '); if (cp && cp[1]) { port = strdup(++cp); } if (!port) { SUBSYS_TRACE1( "ERROR: init_subsys(): " "Malformed SSH_CONNECTION variable\n" ); return ERR_INTERNAL_VAL; } /* get the username */ cp = getenv("USER"); if (!cp) { SUBSYS_TRACE1( "ERROR: init_subsys(): Get USER variable failed\n"); return ERR_INTERNAL_VAL; } user = strdup(cp); if (!user) { SUBSYS_TRACE1( "ERROR: init_subsys(): strdup(user) failed\n" ); return ERR_INTERNAL_MEM; } if(ncxport_inet != -1) { struct hostent* hp; int tcp_nodelay_option=1; /* make a socket to connect to the NCX server */ ncxsock = socket(AF_INET, SOCK_STREAM, 0); if (ncxsock < 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Creation failed\n" ); return ERR_NCX_CONNECT_FAILED; } if (setsockopt(ncxsock, IPPROTO_TCP, TCP_NODELAY, (char*) &tcp_nodelay_option, sizeof(tcp_nodelay_option)) < 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Creation failed\n" ); return ERR_NCX_CONNECT_FAILED; } hp = gethostbyname("localhost"); if (hp == NULL) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Creation failed\n" ); return ERR_NCX_CONNECT_FAILED; } memset((char *) &ncxname_inet, 0, sizeof(ncxname_inet)); ncxname_inet.sin_family = AF_INET; ncxname_inet.sin_port = htons((unsigned short)ncxport_inet); memcpy((char *) &ncxname_inet.sin_addr, hp->h_addr, hp->h_length); name_size = sizeof(ncxname_inet); ncxname = (struct sockaddr *) &ncxname_inet; } else { /* make a socket to connect to the NCX server */ ncxsock = socket(PF_LOCAL, SOCK_STREAM, 0); if (ncxsock < 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Creation failed\n" ); return ERR_NCX_CONNECT_FAILED; } ncxname_unix.sun_family = AF_LOCAL; strncpy(ncxname_unix.sun_path, ncxserver_sockname(argc, argv, port), sizeof(ncxname_unix.sun_path)); name_size = SUN_LEN(&ncxname_unix); ncxname = (struct sockaddr *)&ncxname_unix; } /* try to connect to the NCX server */ ret = connect(ncxsock, ncxname, name_size); if (ret != 0) { SUBSYS_TRACE1( "ERROR: init_subsys(): NCX Socket Connect failed\n" ); return ERR_NCX_OPERATION_FAILED; } else { SUBSYS_TRACE2( "INFO: init_subsys(): " "NCX Socket Connected on FD: %d \n", ncxsock ); ncxconnect = TRUE; } #ifdef USE_NONBLOCKING_IO /* set non-blocking IO */ if (fcntl(ncxsock, F_SETFD, O_NONBLOCK)) { SUBSYS_TRACE1( "ERROR: init_subsys(): fnctl() failed\n" ); } #endif /* connected to the ncxserver and setup the ENV vars ok */ return NO_ERR; } /* init_subsys */