Jump to content

Модификация консольного конфигуратора


Recommended Posts

Нужно было реализовать перенос неистраченного бесплатного траффика на следующий месяц, а возможности установить freemb в КК не было...

Поэтому решил немного модифицировать КК для того чтобы можно было менять скриптами любые параметры пользователя без перезагрузки сервера.

Изменения заключаются в том, что выкинут код, формирующий запрос к серверу (его проще сформировать в скрипте) и запрос читается из файлика, кодируется и отсылается серверу.

Изменился только файл main.cpp :

#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#include "common.h"
#include "netunit.h"

#define FN_LEN          512
#define REQ_STR_LEN    300
char fileName[FN_LEN];

char * ParseServerAddress(char * a);
short int ParseServerPort(const char * p);
char * ParseAdminLogin(char * adm);
char * ParseAdminPassword(char * pass);
char * ParseUser(char * usr);
int CheckLogin(const char * login);
int Process(REQUEST * r);
int CheckParameters(REQUEST * req);
void ParseReply(const char * ans);
void Usage();
void Encode12(char * dst, const char * src, int srcLen);

struct option long_options[] = {
{"server",      1, 0, 's'},  //Server
{"port",        1, 0, 'p'},  //Port
{"admin",       1, 0, 'a'},  //Admin
{"admin_pass",  1, 0, 'w'},  //passWord
{"file",      	1, 0, 'f'},  //File
{0, 0, 0, 0}};


int main (int argc, char **argv) 
{
int c;
int digit_optind = 0;
REQUEST req;
memset(&req, 0, sizeof(req));

while (1)
   {
   int this_option_optind = optind ? optind : 1;
   int option_index = 0;

   c = getopt_long(argc, argv, "s:p:a:w:f:", long_options, &option_index);
   if (c == -1)
       break;

   switch ©
       {
       case 's': //server
           strcpy(req.server, ParseServerAddress(optarg));
           req.serverReq = 1;
           break;
       case 'p': //port
           req.port = ParseServerPort(optarg);
           req.portReq = 1;
           break;
       case 'a': //admin
           strcpy(req.admLogin, ParseAdminLogin(optarg));
           req.admLoginReq = 1;
           break;
       case 'w': //admon password
           strcpy(req.admPasswd, ParseAdminPassword(optarg));
           req.admPasswdReq = 1;
           break;
       case 'f': //file
           strcpy(fileName,optarg);
           break;
       case '?':
           //printf ("Unknown option \n");
           break;
       default:
           printf ("?? getopt returned character code 0%o ??\n", c);
       }
   }

if (optind < argc)
   {
   printf ("non-option ARGV-elements: ");
   while (optind < argc)
       printf ("%s ", argv[optind++]);
   printf ("\n");
   exit(PARAMETER_PARSING_ERR_CODE);
   }

if (CheckParameters(&req) == 0)
   {
   //printf("Parameter needed\n");
   Usage();
   exit(PARAMETER_PARSING_ERR_CODE);
   }

Process(&req);

return 0;
}
//-----------------------------------------------------------------------------
char * ParseServerAddress(char * a)
{
/*long int addr = inet_addr(a);

if(INADDR_NONE == addr)
   {
   printf("Incorrect server address %s\n", a);
   exit(NETWORK_ERR_CODE);
   }*/
if (strlen(a) >= SERVER_NAME_LEN)
   {
   printf("Server name too long %s\n", a);
   exit(PARAMETER_PARSING_ERR_CODE);
   }

return a;
}
//-----------------------------------------------------------------------------
short int ParseServerPort(const char * p)
{
int port;
if (strtoi2(p, port) != 0)
   {
   printf("Incorresct server port %s\n", p);
   exit(NETWORK_ERR_CODE);
   }
return (short)port;
}
//-----------------------------------------------------------------------------
char * ParseAdminLogin(char * adm)
{
if (CheckLogin(adm))
   {
   printf("Incorresct admin login %s\n", adm);
   exit(PARAMETER_PARSING_ERR_CODE);
   }
return adm;
}
//-----------------------------------------------------------------------------
char * ParseAdminPassword(char * pass)
{
if (strlen(pass) >= ADM_PASSWD_LEN)
   {
   printf("Password too big %s\n", pass);
   exit(PARAMETER_PARSING_ERR_CODE);
   }

return pass;
}
//-----------------------------------------------------------------------------
int CheckLogin(const char * login)
{
for (int i = 0; i < strlen(login); i++)
   {
   if (!(( login[i] >= 'a' && login[i] <= 'z')
       || (login[i] >= 'A' && login[i] <= 'Z')
       || (login[i] >= '0' && login[i] <= '9')
       ||  login[i] == '_'))
       {
       return 1;
       }
   }
return 0;
}
//-----------------------------------------------------------------------------
void FileRequest(char * r)
{
char str[1024];
FILE *f;

r[0] = 0;
f = NULL;
f = fopen(fileName, "rt");
if (!f)
{
 printf("Can't open request file\n");
 exit(PARAMETER_PARSING_ERR_CODE);
}
char ts[REQ_STR_LEN];
while (fgets(ts, REQ_STR_LEN, f))
   { strncat(r, ts, REQ_STR_LEN);}
fclose(f);
}

int Process(REQUEST * r)
{
char str[2048];
NETTRANSACT nt;
nt.SetServer(r->server);
nt.SetServerPort(r->port);
nt.SetLogin(r->admLogin);
nt.SetPassword(r->admPasswd);
nt.SetRxCallback(ParseReply);

FileRequest(str);

if (nt.Connect())
   {
   printf("Connect failed.\n");
   exit(NETWORK_ERR_CODE);
   }

if (nt.Transact(str))
   {
   printf("Login or password failed.\n");
   exit(LOGIN_OR_PASS_ERR_CODE);
   }

nt.Disconnect();

printf("Ok\n");
return 0;
}
//-----------------------------------------------------------------------------
int CheckParameters(REQUEST * req)
{
int a = req->admLoginReq 
   && req->admPasswdReq
   && req->serverReq
   && req->portReq;
return a;
}
//-----------------------------------------------------------------------------
void Usage()
{
printf("Use:\n");
printf("sgconf -s <server> -p <port> -a <admin> -w <admin_pass> -f <request_file>\n");
}

 

Теперь для того чтобы, например установить счет пользователя, достаточно создать файл

<SetUser>
<login value="test"/>
<cash set="10.0"/>
</SetUser>

и передать его в качесте параметра конфигуратору

Link to post
Share on other sites

Про заморозку, немного непонятно как ее перевели...

Вероятно:

<SetUser>
<login value="test"/>
<passive value="1"/>
</SetUser>

 

А вообще хорошо бы на практике проверить все параметры, отрабатывают ли. Смотрю я их в файле parser.cpp в исходниках сервера.

Link to post
Share on other sites

login

NewLogin

ip

password

address

aonline

cash

CashExpire

CreditExpire

credit

freemb

down

email

userdata0

userdata1

group

iface

note

passive

phone

Name

traff

tariff

Это то что доступно, однако работать со строковымы параметрами у меня не вышло

<SetUser>

<login value="test"/>

<address value="test"/>

<iface value="eth0"/>

</SetUser>

в поле адреса вместо тест появляеться SB

деньги интерфейс установка пасива и замарозки работает на ура

и еще я как понял если вместо параметра логин отправлять параметр NewLorin по идеи должен регистрировать нового пользователя

Link to post
Share on other sites

А со строковыми параметрами не так все просто. Для их кодирования применяется функция

void Encode12(char * dst, const char * src, int srcLen)
{
char c1, c2;
int i;
for (i = 0; i <= srcLen; i++)
   {
   c1 = src[i] & 0x0f;
   c2 = (src[i] & 0xf0) >> 4;

   c1 += 'a';
   c2 += 'a';

   dst[i*2] = c1;
   dst[i*2 + 1] = c2;
   }
dst[i*2] = 0;

Вот ёё то и придется повторить в скрипте, чтобы иметь возможность отсылать серверу строковые параметры. А суть ее заключается в том что каждый байт кодируется в 2 буквы от 'a' до 'p'

 

А для создания юзера, похоже, надо просто указать все параметры и заключить их в теги <AddUser> </AddUser>

Link to post
Share on other sites
  • 1 month later...

<AddUser>
<login value="login_name"/>
<ip value=""/>
<password value="123456"/>
<phone value=""/>
<email value=""/>
<tariff value="ehbgchjggggg"/>
<address value=""/>
<note value=""/>
<name value=""/>
<userdata0 value=""/>
<userdata1 value=""/>
<cash value="0.0"/>
<credit value="0.0"/>
<iface value="eth0"/>
<group value=""/>
<passive value="0"/>
<down value="0"/>
<aonline value="0"/>
</AddUser>

Вот так работает добавление пользователя. В данном примере тариф=encode12("tariff")

если послать <GetUser> <login value="login_name"/></GetUser> должно вернуть параметры пользователя

Link to post
Share on other sites

Для получения данных желательно подправить функцию в файле netunit.cpp:

int NETTRANSACT::RxDataAnswer()
{
int n = 0;
int ret;
char bufferS[ENC_MSG_LEN];
char buffer[ENC_MSG_LEN];

BLOWFISH_CTX ctx;
EnDecryptInit(password, PASSWD_LEN, &ctx);
FILE *f=fopen("output.xml","w");
while (1)
   {
   ret = recv(outerSocket, &bufferS[n++], 1, 0);
   if (ret <= 0)
       {
       fclose(f);
       close(outerSocket);
       strcpy(errorMsg, RECV_DATA_ANSWER_ERROR);
       return 0;
       }


   if (n == 8)
       {
       n = 0;
       Decrypt(buffer, bufferS, &ctx);

       for (int j = 0; j < 8; j++)
           {
           if (buffer[j] == 0)
               {
                   fwrite(buffer,j,1,f);
                   if (RxCallBack)  RxCallBack(answer);
                   return st_ok;
               }
           }
           fwrite(buffer,8,1,f);
       }

   }
}

Полученные данные будут записаны в файл output.xml.

<GetUser login="test"/>

Вернет данные пользователя.

Другие варианты запросов:

GetServerInfo

GetUsers

GetTariffs

GetTariff

и тд

Link to post
Share on other sites
  • 11 months later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...