./ MultiCS.r82 / telnet.c
#include "common.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#ifdef WIN32
#include <windows.h>
#include <sys/types.h>
#include <sys/_default_fcntl.h>
#include <sys/poll.h>
#include <cygwin/types.h>
#include <cygwin/socket.h>
#include <sys/errno.h>
#include <cygwin/in.h>
#include <sched.h>
#include <netdb.h>
#include <netinet/tcp.h>
#else
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <poll.h>
#include <sys/prctl.h>
#endif
#include "debug.h"
#include "convert.h"
#include "tools.h"
#include "threads.h"
#include "ecmdata.h"
#ifdef CCCAM
#include "msg-cccam.h"
#endif
#include "config.h"
#include "sockets.h"
#include "telnet.h"
#include "main.h"
#include "parser.h"
#include "httpserver.h"
int writes( int fd, char *str )
{
return write(fd, str, strlen(str) );
}
char *getcountrycodebyip(uint32_t ip);
void *telnetprocess(int *param )
{
int fd = *param;
free(param);
char buf[4096];
char str[256];
char wbuf[4096];
int len;
//
writes(fd, "Welcome to Telnet Server\r\n\r\nLogin: ");
len = recv( fd, buf, sizeof(buf), MSG_NOSIGNAL);
if (len<=0) { close(fd); return NULL; }
//printf(" Received(%d): '%s'\r\n", len, buf);
if ( (buf[len-2]!='\r')||(buf[len-1]!='\n') ) { close(fd); return NULL; }
buf[len-2] = 0;
if ( strcmp(buf, cfg.telnet.user) ) {
writes(fd, "wrong username, bye.\r\n");
close(fd);
return NULL;
}
//
writes(fd, "Password: ");
len = recv( fd, buf, sizeof(buf), MSG_NOSIGNAL);
if (len<=0) { close(fd); return NULL; }
//printf(" Received(%d): '%s'\r\n", len, buf);
if ( (buf[len-2]!='\r')||(buf[len-1]!='\n') ) { close(fd); return NULL; }
buf[len-2] = 0;
if ( strcmp(buf, cfg.telnet.pass) ) {
writes(fd, "wrong password, bye.\r\n");
close(fd);
return NULL;
}
strcpy(buf, "\r\n\r\ntype 'help' for command list\r\n");write(fd, buf, strlen(buf) );
while ( 1 ) {
writes(fd, "\r\n[command]: ");
len = recv( fd, buf, sizeof(buf), MSG_NOSIGNAL);
if (len<=0) { close(fd); return NULL; }
//printf(" Received(%d): %s", len, buf);
if ( (buf[len-2]!='\r')||(buf[len-1]!='\n') ) { close(fd); return NULL; }
buf[len-2] = 0;
iparser = buf;
parse_spaces();
if (*iparser==0) continue;
if (!parse_name(str)) continue;
uppercase(str);
if ( !strcmp(str, "EXIT") || !strcmp(str, "QUIT") ) {
writes(fd, "bye.\r\n");
break;
}
else if ( !strcmp(str, "UPTIME") ) {
unsigned int d= GetTickCount()/1000;
sprintf( wbuf,"Uptime: %02dd %02d:%02d:%02d\r\n", d/(3600*24), (d/3600)%24, (d/60)%60, d%60);
writes(fd, wbuf);
}
else if ( !strcmp(str, "STAT") ) {
sprintf( wbuf,"Total Profiles: %d\r\nTotal Servers: %d\r\nTotal Cache Servers: %d\r\nTotal CCcam Servers: %d\r\n", cfg.totalprofiles, cfg.totalservers, cfg.cache.totalservers, cfg.cccam.totalservers);
writes(fd, wbuf);
}
else if ( !strcmp(str, "DEBUG") ) {
int i=idbgline;
do {
sprintf( wbuf, "%s", dbgline[i] );
writes(fd, wbuf);
i++;
if (i>=MAX_DBGLINES) i=0;
} while (i!=idbgline);
}
else if ( !strcmp(str, "LOADAVG") ) {
FILE *fp = fopen ("/proc/loadavg", "r");
if ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "MEMINFO") ) {
FILE *fp = fopen ("/proc/meminfo", "r");
if ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
if ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "CPUINFO") ) {
FILE *fp = fopen ("/proc/cpuinfo", "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "SCHED") ) {
if (parse_name(str)) {
uppercase(str);
if ( !strcmp(str, "CCCAM") ) {
sprintf( str, "/proc/%d/sched", prg.pid_cc_msg);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "NEWCAMD") ) {
sprintf( str, "/proc/%d/sched", prg.pid_cs_msg);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "ECM") ) {
sprintf( str, "/proc/%d/sched", prg.pid_msg);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
else if ( !strcmp(str, "MGCAMD") ) {
sprintf( str, "/proc/%d/sched", prg.pid_mg_msg);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
#ifdef CACHEEX
else if ( !strcmp(str, "CACHEEX") ) {
sprintf( str, "/proc/%d/sched", prg.pid_ccex_msg);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
#endif
else if ( !strcmp(str, "CACHE") ) {
sprintf( str, "/proc/%d/sched", prg.pid_cache);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
}
else {
sprintf( str, "/proc/%d/sched", prg.pid_main);
FILE *fp = fopen ( str, "r");
while ( fgets(wbuf, sizeof(wbuf), fp) ) writes(fd, wbuf);
fclose(fp);
}
}
else if ( !strcmp(str, "HELP") ) {
writes(fd, " Commands: help - uptime - stat - cccam - mgcamd - debug - loadavg - cpuinfo - meminfo - exit/quit\r\n");
}
else if (!strcmp(str,"CCCAM")) {
if (!parse_int(str)) {
int index = 0;
struct cccam_server_data *srv = cfg.cccam.server;
while (srv) {
index++;
sprintf( wbuf, "id:%d Port:%d", srv->id, srv->port);
if (srv->handle>0) strcat( wbuf, " Status:ON "); else strcat( wbuf, " Status:OFF");
int total, connected, active;
cccam_clients( srv, &total, &connected, &active );
sprintf( str, "Clients Total:%d, Connected:%d, Active:%d", total, connected, active );
strcat( wbuf, str );
strcat( wbuf, "\r\n");
writes(fd, wbuf);
srv = srv->next;
}
sprintf(wbuf, "Total CCcam servers = %d\r\n", index);
writes(fd, wbuf);
}
else { // cccam <cientname>
struct cccam_server_data *cccam = getcccamserverbyid( atoi(str) );
if (!cccam) continue;
if (!parse_name(str)) continue;
struct cc_client_data *cli = getcccamclientbyname( cccam, str );
if (!cli) continue;
if (cli->connection.status>0) {
char *p = getcountrycodebyip(cli->ip);
if (p)
sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=online>Connected</td><td>[%s] %s</td>", cfg.http.title, cli->user, p, ip2string(cli->ip) );
else
sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=online>Connected</td><td>%s</td>", cfg.http.title, cli->user, ip2string(cli->ip) );
//Last Used Share
if ( cli->lastecm.caid ) {
char tmp[512];
if (cli->lastecm.status)
sprintf( tmp,"<td class=success>channel %s (%dms) OK</td>", getchname(cli->lastecm.caid, cli->lastecm.prov, cli->lastecm.sid) , cli->lastecm.decodetime );
else
sprintf( tmp,"<td class=failed>channel %s (%dms) NOK</td>", getchname(cli->lastecm.caid, cli->lastecm.prov, cli->lastecm.sid) , cli->lastecm.decodetime );
strcat( wbuf, tmp);
// last time
unsigned int d= (GetTickCount()-cli->ecm.recvtime)/1000;
sprintf( tmp,"<td>%02dd %02d:%02d:%02d</td></tr>\r\n", d/(3600*24), (d/3600)%24, (d/60)%60, d%60);
strcat( wbuf, tmp);
} else strcat( wbuf, "<td> </td><td> </td></tr>\r\n");
}
else {
if (cli->connection.lastseen) {
uint32_t d = (GetTickCount()-cli->connection.lastseen)/1000;
sprintf( wbuf,"<tr><td>%s</td><td>%s</td><td class=offline>Disconnected</td><td>Last Seen</td><td>%02dd %02d:%02d:%02d</td></tr>\r\n", cfg.http.title, cli->user, d/(3600*24),(d/3600)%24,(d/60)%60,d%60);
}
else sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=offline>Disconnected</td><td> </td><td> </td></tr>\r\n", cfg.http.title, cli->user );
}
writes(fd, wbuf);
}
}
else if (!strcmp(str,"MGCAMD")) {
if (!parse_int(str)) {
int index = 0;
struct mgcamdserver_data *srv = cfg.mgcamd.server;
while (srv) {
index++;
sprintf( wbuf, "id:%d Port:%d", srv->id, srv->port);
if (srv->handle>0) strcat( wbuf, " Status:ON "); else strcat( wbuf, " Status:OFF");
int total, connected, active;
mgcamd_clients( srv, &total, &connected, &active );
sprintf( str, "Clients Total:%d, Connected:%d, Active:%d", total, connected, active );
strcat( wbuf, str );
strcat( wbuf, "\r\n");
writes(fd, wbuf);
srv = srv->next;
}
sprintf(wbuf, "Total Mgcamd servers = %d\r\n", index);
writes(fd, wbuf);
}
else { // mgcamd <cientname>
struct mgcamdserver_data *srv = getmgcamdserverbyid( atoi(str) );
if (!srv) continue;
if (!parse_name(str)) continue;
struct mg_client_data *cli = getmgcamdclientbyname( srv, str );
if (!cli) continue;
if (cli->handle>0) {
char *p = getcountrycodebyip(cli->ip);
if (p)
sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=online>Connected</td><td>[%s] %s</td>", cfg.http.title, cli->user, p, ip2string(cli->ip) );
else
sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=online>Connected</td><td>%s</td>", cfg.http.title, cli->user, ip2string(cli->ip) );
//Last Used Share
if ( cli->lastecm.caid ) {
char tmp[512];
if (cli->lastecm.status)
sprintf( tmp,"<td class=success>channel %s (%dms) OK</td>", getchname(cli->lastecm.caid, cli->lastecm.prov, cli->lastecm.sid) , cli->lastecm.decodetime );
else
sprintf( tmp,"<td class=failed>channel %s (%dms) NOK</td>", getchname(cli->lastecm.caid, cli->lastecm.prov, cli->lastecm.sid) , cli->lastecm.decodetime );
strcat( wbuf, tmp);
// last time
unsigned int d= (GetTickCount()-cli->ecm.recvtime)/1000;
sprintf( tmp,"<td>%02dd %02d:%02d:%02d</td></tr>\r\n", d/(3600*24), (d/3600)%24, (d/60)%60, d%60);
strcat( wbuf, tmp);
} else strcat( wbuf, "<td> </td><td> </td></tr>\r\n");
}
else sprintf(wbuf, "<tr><td>%s</td><td>%s</td><td class=offline>Disconnected</td><td> </td><td> </td></tr>\r\n", cfg.http.title, cli->user );
writes(fd, wbuf);
}
}
else if (!strcmp(str,"UPDATE")) {
if (parse_name(str)) {
uppercase(str);
if ( !strcmp(str, "CCCAM") ) {
if (parse_int(str)) {
struct cccam_server_data *cccam = getcccamserverbyid( atoi(str) );
if (!cccam) continue;
// user
if (!parse_str(str)) continue;
struct cc_client_data *cli = getcccamclientbyname( cccam, str );
if (!cli) continue;
// pass
if (!parse_str(str)) continue;
if ( strcmp(str, "*") ) {
if ( strcmp(cli->pass, str) ) {
strcpy(cli->pass, str);
// disconnect
if (cli->connection.status>0) cc_disconnect_cli(cli);
}
}
// date
if (!parse_str(str)) continue;
if ( strcmp(str, "*") ) {
if ( (str[4]=='-')&&(str[7]=='-') ) strptime( str, "%Y-%m-%d %H", &cli->enddate);
else if ( (str[2]=='-')&&(str[5]=='-') ) strptime( str, "%d-%m-%Y %H", &cli->enddate);
}
//
if (parse_int(str)) {
if (str[0]=='1') cli->flags &= ~FLAG_DISABLE;
else {
cli->flags |= FLAG_DISABLE;
if (cli->connection.status>0) cc_disconnect_cli(cli);
}
}
sprintf(wbuf, "CCcam Client '%s' Updated\r\n", cli->user);
writes(fd, wbuf);
} else writes(fd, "update cccam <server id> <client name> <password> <expire-date> <1:enable/0:disable>\r\n");
}
else
if ( !strcmp(str, "MGCAMD") ) {
if (parse_int(str)) {
struct mgcamdserver_data *mgcamd = getmgcamdserverbyid( atoi(str) );
if (!mgcamd) continue;
// user
if (!parse_str(str)) continue;
struct mg_client_data *cli = getmgcamdclientbyname( mgcamd, str );
if (!cli) continue;
// pass
if (!parse_str(str)) continue;
if ( strcmp(str, "*") ) {
if ( strcmp(cli->pass, str) ) {
strcpy(cli->pass, str);
// disconnect
if (cli->connection.status>0) mg_disconnect_cli(cli);
}
}
// date
if (!parse_name(str)) continue;
if ( strcmp(str, "*") ) {
if ( (str[4]=='-')&&(str[7]=='-') ) strptime( str, "%Y-%m-%d %H", &cli->enddate);
else if ( (str[2]=='-')&&(str[5]=='-') ) strptime( str, "%d-%m-%Y %H", &cli->enddate);
}
//
if (parse_int(str)) {
if (str[0]=='1') cli->flags &= ~FLAG_DISABLE;
else {
cli->flags |= FLAG_DISABLE;
if (cli->connection.status>0) mg_disconnect_cli(cli);
}
}
sprintf(wbuf, "mgcamd Client '%s' Updated\r\n", cli->user);
writes(fd, wbuf);
} else writes(fd, "update mgcamd <server id> <client name> <password> <expire-date> <1:enable/0:disable>\r\n");
}
}
}
else {
writes(fd, "unknown command.\r\n");
}
}
close(fd);
return NULL;
}
void *telnet_thread(void *param)
{
int clientsock;
struct sockaddr_in client_addr;
socklen_t socklen = sizeof(client_addr);
prctl(PR_SET_NAME,"Telnet",0,0,0);
while(1) {
if (cfg.telnet.handle>0) {
struct pollfd pfd;
pfd.fd = cfg.telnet.handle;
pfd.events = POLLIN | POLLPRI;
int retval = poll(&pfd, 1, 3002);
if ( retval>0 ) {
if ( pfd.revents & (POLLIN|POLLPRI) ) {
clientsock = accept(cfg.telnet.handle, (struct sockaddr*)&client_addr, /*(socklen_t*)*/&socklen);
if ( clientsock<0 ) {
debugf(getdbgflag(DBG_HTTP,0,0)," telnet Server: Accept Error\n");
break;
}
else {
//SetSocketNoDelay(clientsock);
pthread_t cli_tid;
int *param = malloc( sizeof(int) );
*param = clientsock;
if ( !create_thread(&cli_tid, (threadfn)telnetprocess,param) ) {
free( param );
close( clientsock );
}
}
}
}
else if (retval<0) {
debugf(getdbgflag(DBG_HTTP,0,0)," THREAD telnet: poll error %d(errno=%d)\n", retval, errno);
usleep(50000);
}
} else usleep(100000);
}// While
debugf(getdbgflag(DBG_HTTP,0,0),"Exiting telnet Thread\n");
return NULL;
}
pthread_t telnet_tid;
int start_thread_telnet()
{
create_thread(&telnet_tid, telnet_thread, NULL); // Priority
return 0;
}