gateways are now in the database

pull/14/head
Tom Early 6 years ago
parent ef5bf1750e
commit 98f8072a9c

1
.gitignore vendored

@ -1,5 +1,6 @@
*.o
*.d
*~
*.gch
.vscode
qn.cfg

@ -1,6 +1,6 @@
/*
* Copyright (C) 2010-2015 by Jonathan Naylor G4KLX
* Copyright (C) 2018-2019 by Thomas A. Early N7TAE
* Copyright (C) 2018-2020 by Thomas A. Early N7TAE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -43,7 +43,7 @@ CDPlusAuthenticator::~CDPlusAuthenticator()
{
}
bool CDPlusAuthenticator::Process(std::map<std::string, std::string> &gwy_map, const bool reflectors, const bool repeaters)
bool CDPlusAuthenticator::Process(CQnetDB &db, const bool reflectors, const bool repeaters)
// return true if everything went okay
{
int result = client.Open(m_address, AF_UNSPEC, "20001");
@ -51,10 +51,10 @@ bool CDPlusAuthenticator::Process(std::map<std::string, std::string> &gwy_map, c
fprintf(stderr, "DPlus Authorization failed: %s\n", gai_strerror(result));
return true;
}
return authenticate(gwy_map, reflectors, repeaters);
return authenticate(db, reflectors, repeaters);
}
bool CDPlusAuthenticator::authenticate(std::map<std::string, std::string> &gwy_map, const bool reflectors, const bool repeaters)
bool CDPlusAuthenticator::authenticate(CQnetDB &db, const bool reflectors, const bool repeaters)
{
unsigned char* buffer = new unsigned char[4096U];
::memset(buffer, ' ', 56U);
@ -77,7 +77,6 @@ bool CDPlusAuthenticator::authenticate(std::map<std::string, std::string> &gwy_m
}
int ret = client.ReadExact(buffer, 2U);
size_t sofar = gwy_map.size();
unsigned int returned = 0;
while (ret == 2) {
@ -100,7 +99,7 @@ bool CDPlusAuthenticator::authenticate(std::map<std::string, std::string> &gwy_m
Trim(address);
Trim(name);
name.resize(8, ' ');
name.resize(6, ' ');
// Get the active flag
bool active = (buffer[i + 25U] & 0x80U) == 0x80U;
@ -109,9 +108,9 @@ bool CDPlusAuthenticator::authenticate(std::map<std::string, std::string> &gwy_m
if (address.size()>0U && name.size()>0U && active) {
returned++;
if (reflectors && 0==name.compare(0, 3, "REF"))
gwy_map[name] = address.append(" 20001");
db.UpdateGW(name.c_str(), address.c_str(), 20001);
else if (repeaters && name.compare(0, 3, "REF"))
gwy_map[name] = address.append(" 20001");
db.UpdateGW(name.c_str(), address.c_str(), 20001);
}
}
@ -120,7 +119,6 @@ bool CDPlusAuthenticator::authenticate(std::map<std::string, std::string> &gwy_m
printf("Probably authorized DPlus on %s using callsign %s\n", m_address.c_str(), m_loginCallsign.c_str());
printf("%s returned %u systems\n", m_address.c_str(), returned);
printf("The gateway map increased by %u additional DPlus gateways\n", (unsigned int)(gwy_map.size() - sofar));
client.Close();
delete[] buffer;

@ -1,7 +1,7 @@
#pragma once
/*
* Copyright (C) 2010-2013 by Jonathan Naylor G4KLX
* Copyright (C) 2018-2019 by Thomas A. Early N7TAE
* Copyright (C) 2018-2020 by Thomas A. Early N7TAE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,14 +21,16 @@
#include <netinet/in.h>
#include <map>
#include <string>
#include "TCPReaderWriterClient.h"
#include "QnetDB.h"
class CDPlusAuthenticator {
public:
CDPlusAuthenticator(const std::string &loginCallsign, const std::string &address);
~CDPlusAuthenticator();
bool Process(std::map<std::string, std::string> &gwy_map, const bool reflectors, const bool repeaters);
bool Process(CQnetDB &qn, const bool reflectors, const bool repeaters);
private:
std::string m_loginCallsign;
@ -36,5 +38,5 @@ private:
CTCPReaderWriterClient client;
void Trim(std::string &s);
bool authenticate(std::map<std::string, std::string> &gwy_map, const bool reflectors, const bool repeaters);
bool authenticate(CQnetDB &db, const bool reflectors, const bool repeaters);
};

@ -129,7 +129,7 @@ bool CQnetConfigure::GetDefaultString(const std::string &path, const std::string
search_again = mod; // we're looking from a module value. We may have to look for non-generic module parameters
if (0==path.compare(0, 7, "module_") && ('a'==path.at(7) || 'b'==path.at(7) || 'c'==path.at(7)) && '_'==path.at(8)) {
// path begins with module_{a|b|c}_
if (0==mod.compare("dvrptr") || 0==mod.compare("dvap") || 0==mod.compare("mmdvmhost") || 0==mod.compare("mmdvmmodem") || 0==mod.compare("itap")) {
if (0==mod.compare("dvrptr") || 0==mod.compare("dvap") || 0==mod.compare("mmdvmhost") || 0==mod.compare("mmdvmmodem") || 0==mod.compare("itap") || 0==mod.compare("thumbdv")) {
// and the module is recognized
search = path;
search.replace(7, 1, 1, 'x');

@ -75,6 +75,26 @@ bool CQnetDB::Init()
return true;
}
sql.assign("DROP TABLE IF EXISTS GATEWAYS;");
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
fprintf(stderr, "CQnetDB::Open drop table LINKSTATUS error: %s\n", eMsg);
sqlite3_free(eMsg);
return true;
}
sql.assign("CREATE TABLE GATEWAYS("
"name TEXT PRIMARY KEY, "
"address TEXT NOT NULL, "
"port INT NOT NULL"
") WITHOUT ROWID;");
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
fprintf(stderr, "CQnetDB::Open create table GATEWAYS error: %s\n", eMsg);
sqlite3_free(eMsg);
return true;
}
return false;
}
@ -129,6 +149,30 @@ bool CQnetDB::UpdateLS(const char *address, const char from_mod, const char *to_
return false;
}
bool CQnetDB::UpdateGW(const char *name, const char *address, unsigned short port)
{
if (NULL == db)
return false;
std::string n(name);
n.resize(6, ' ');
std::string sql = "REPLACE INTO GATEWAYS (name,address,port) VALUES ('";
sql.append(n);
sql.append("','");
sql.append(address);
sql.append("',");
sql.append(std::to_string(port));
sql.append(");");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
fprintf(stderr, "CQnetDB::UpdateGW error: %s\n", eMsg);
sqlite3_free(eMsg);
return true;
}
return false;
}
bool CQnetDB::DeleteLS(const char *address)
{
if (NULL == db)
@ -175,3 +219,43 @@ bool CQnetDB::FindLS(const char mod, std::list<CLink> &linklist)
sqlite3_finalize(stmt);
return false;
}
bool CQnetDB::FindGW(const char *name, std::string &address, unsigned short &port)
{
if (NULL == db)
return false;
std::string n(name);
n.resize(6, ' ');
std::string sql("SELECT address,port FROM GATEWAYS WHERE name=='");
sql.append(n);
sql.append("';");
sqlite3_stmt *stmt;
int rval = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0);
if (SQLITE_OK != rval) {
fprintf(stderr, "CQnetDB::FindLS error: %d\n", rval);
return true;
}
if (SQLITE_ROW == sqlite3_step(stmt)) {
address.assign((const char *)sqlite3_column_text(stmt, 0));
port = (unsigned short)(sqlite3_column_int(stmt, 1));
sqlite3_finalize(stmt);
return false;
} else {
sqlite3_finalize(stmt);
return true;
}
}
void CQnetDB::ClearGW()
{
std::string sql("DELETE FROM GATEWAYS;");
char *eMsg;
if (SQLITE_OK != sqlite3_exec(db, sql.c_str(), NULL, 0, &eMsg)) {
fprintf(stderr, "CQnetDB::Open drop table LINKSTATUS error: %s\n", eMsg);
sqlite3_free(eMsg);
}
}

@ -55,8 +55,11 @@ public:
bool Init();
bool UpdateLH(const char *callsign, const char *sfx, const char module, const char *reflector);
bool UpdateLS(const char *address, const char from_mod, const char *to_callsign, const char to_mod, time_t connect_time);
bool UpdateGW(const char *name, const char *address, unsigned short port);
bool DeleteLS(const char *address);
bool FindLS(const char mod, std::list<CLink> &linklist);
bool FindGW(const char *name, std::string &address, unsigned short &port);
void ClearGW();
private:
sqlite3 *db;

@ -230,6 +230,7 @@ bool CQnetGateway::ReadConfig(char *cfgFile)
else if (0 == type.compare("mmdvmhost")) { Rptr.mod[m].package_version.assign(GW_VERSION+".Relay"); }
else if (0 == type.compare("mmdvmmodem")) { Rptr.mod[m].package_version.assign(GW_VERSION+".Modem"); }
else if (0 == type.compare("itap")) { Rptr.mod[m].package_version.assign(GW_VERSION+".ITAP"); }
else if (0 == type.compare("thumbdv")) { Rptr.mod[m].package_version.assign(GW_VERSION+".ThumbDV"); }
else {
printf("module type '%s' is invalid\n", type.c_str());
return true;

@ -40,6 +40,7 @@
#include <netdb.h>
#include <iostream>
#include <sstream>
#include <fstream>
#include <future>
#include <exception>
@ -51,6 +52,7 @@
#include "DPlusAuthenticator.h"
#include "QnetConfigure.h"
#include "QnetLink.h"
#include "Utilities.h"
#define LINK_VERSION "QnetLink-409"
#ifndef BIN_DIR
@ -293,111 +295,37 @@ bool CQnetLink::load_gwys(const std::string &filename)
// DPlus Authenticate
if (dplus_authorize && !dplus_priority) {
CDPlusAuthenticator auth(login_call, std::string("auth.dstargateway.org"));
if (auth.Process(gwy_list, dplus_reflectors, dplus_repeaters))
if (auth.Process(qnDB, dplus_reflectors, dplus_repeaters))
fprintf(stdout, "DPlus Authorization failed.\n");
else
fprintf(stderr, "DPlus Authorization complete!\n");
}
char inbuf[1024];
const char *delim = " ";
char call[CALL_SIZE + 1];
char host[MAXHOSTNAMELEN + 1];
char port[5 + 1];
/* host + space + port + NULL */
char payload[MAXHOSTNAMELEN + 1 + 5 + 1];
unsigned short j;
printf("Trying to open file %s\n", filename.c_str());
FILE *fp = fopen(filename.c_str(), "r");
if (fp == NULL) {
printf("Failed to open file %s\n", filename.c_str());
return false;
}
printf("Opened file %s OK\n", filename.c_str());
while (fgets(inbuf, 1020, fp) != NULL) {
char *p = strchr(inbuf, '\r');
if (p)
*p = '\0';
p = strchr(inbuf, '\n');
if (p)
*p = '\0';
p = strchr(inbuf, '#');
if (p) {
printf("Comment line:[%s]\n", inbuf);
continue;
}
/* get the call */
char *tok = strtok(inbuf, delim);
if (!tok)
continue;
if ((strlen(tok) > CALL_SIZE) || (strlen(tok) < 3)) {
printf("Invalid call [%s]\n", tok);
continue;
}
memset(call, ' ', CALL_SIZE);
call[CALL_SIZE] = '\0';
memcpy(call, tok, strlen(tok));
for (j = 0; j < strlen(call); j++)
call[j] = toupper(call[j]);
if (strcmp(call, owner.c_str()) == 0) {
printf("Call [%s] will not be loaded\n", call);
continue;
}
/* get the host */
tok = strtok(NULL, delim);
if (!tok) {
printf("Call [%s] has no host\n", call);
continue;
}
strncpy(host,tok,MAXHOSTNAMELEN);
host[MAXHOSTNAMELEN] = '\0';
if (strcmp(host, "0.0.0.0") == 0) {
printf("call %s has invalid host %s\n", call, host);
continue;
}
/* get the port */
tok = strtok(NULL, delim);
if (!tok) {
printf("Call [%s] has no port\n", call);
continue;
}
if (strlen(tok) > 5) {
printf("call %s has invalid port [%s]\n", call, tok);
continue;
std::ifstream hostfile(filename);
if (hostfile.is_open()) {
std::string line;
while (std::getline(hostfile, line)) {
trim(line);
if (! line.empty() && ('#' != line.at(0))) {
std::istringstream iss(line);
std::string host, address;
unsigned short port;
iss >> host >> address >> port;
qnDB.UpdateGW(host.c_str(), address.c_str(), port);
}
}
strcpy(port, tok);
/* at this point, we have: call host port */
/* copy the payload(host port) */
sprintf(payload, "%s %s", host, port);
auto gwy_pos = gwy_list.find(call);
if (gwy_pos != gwy_list.end())
printf("%s %s has been redefined!\n", call, payload);
gwy_list[call] = payload;
hostfile.close();
}
fclose(fp);
// DPlus Authenticate
if (dplus_authorize && dplus_priority) {
CDPlusAuthenticator auth(login_call, std::string("auth.dstargateway.org"));
if (auth.Process(gwy_list, dplus_reflectors, dplus_repeaters))
if (auth.Process(qnDB, dplus_reflectors, dplus_repeaters))
fprintf(stdout, "DPlus Authorization failed.\n");
else
fprintf(stderr, "DPlus Authorization completed!\n");
}
//for (auto it=gwy_list.begin(); it!=gwy_list.end(); it++)
// printf("%s %s\n", it->first.c_str(), it->second.c_str());
printf("Added %d gateways from gwys.txt\n", (int)gwy_list.size());
return true;
}
@ -714,15 +642,6 @@ void CQnetLink::srv_close()
void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
{
char linked_remote_system[CALL_SIZE + 1];
char *space_p = 0;
char host[MAXHOSTNAMELEN + 1];
char port_s[5 + 1];
unsigned short port_i;
/* host + space + port + NULL */
char payload[MAXHOSTNAMELEN + 1 + 5 + 1];
char *p = NULL;
char link_request[519];
@ -730,10 +649,6 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
memset(link_request, 0, sizeof(link_request));
host[0] = '\0';
port_s[0] = '\0';
payload[0] = '\0';
int i;
if (from_mod == 'A')
i = 0;
@ -775,31 +690,18 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
}
}
auto gwy_pos = gwy_list.find(call);
if (gwy_pos == gwy_list.end()) {
std::string address;
unsigned short port;
if (qnDB.FindGW(call, address, port)) {
sprintf(notify_msg[i], "%c_gatewaynotfound.dat_GATEWAY_NOT_FOUND", from_mod);
printf("%s not found in gwy list\n", call);
return;
}
strcpy(payload, gwy_pos->second.c_str());
/* extract host and port */
p = strchr(payload, ' ');
if (!p) {
printf("Invalid payload [%s] for call [%s]\n", payload, call);
return;
}
*p = '\0';
strcpy(host, payload);
strcpy(port_s, p + 1);
port_i = (unsigned short)atoi(port_s);
if (host[0] != '\0') {
ok = resolve_rmt(host, port_i, to_remote_g2[i].addr);
if (address.size()) {
ok = resolve_rmt(address.c_str(), port, to_remote_g2[i].addr);
if (!ok) {
printf("Call %s is host %s but could not resolve to IP\n", call, host);
printf("Call %s is host %s but could not resolve to IP\n", call, address.c_str());
to_remote_g2[i].addr.Clear();
to_remote_g2[i].countdown = 0;
to_remote_g2[i].from_mod = '\0';
@ -819,17 +721,17 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
to_remote_g2[i].in_streamid= 0x0;
/* is it XRF? */
if (port_i == rmt_xrf_port) {
if (port == rmt_xrf_port) {
strcpy(link_request, owner.c_str());
link_request[8] = from_mod;
link_request[9] = to_mod;
link_request[10] = '\0';
printf("sending link request from mod %c to link with: [%s] mod %c [%s]\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, payload);
printf("sending link request from mod %c to link with: [%s] mod %c [%s]:%u\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, address.c_str(), port);
for (int j=0; j<5; j++)
sendto(xrf_g2_sock, link_request, CALL_SIZE + 3, 0, to_remote_g2[i].addr.GetCPointer(), to_remote_g2[i].addr.GetSize());
} else if (port_i == rmt_dcs_port) {
} else if (port == rmt_dcs_port) {
strcpy(link_request, owner.c_str());
link_request[8] = from_mod;
link_request[9] = to_mod;
@ -837,9 +739,9 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
memcpy(link_request + 11, to_remote_g2[i].cs, 8);
strcpy(link_request + 19, "<table border=\"0\" width=\"95%\"><tr><td width=\"4%\"><img border=\"0\" src=g2ircddb.jpg></td><td width=\"96%\"><font size=\"2\"><b>REPEATER</b> QnetGateway v1.0+</font></td></tr></table>");
printf("sending link request from mod %c to link with: [%s] mod %c [%s]\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, payload);
printf("sending link request from mod %c to link with: [%s] mod %c [%s]:%u\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, address.c_str(), port);
sendto(dcs_g2_sock, link_request, 519, 0, to_remote_g2[i].addr.GetCPointer(), to_remote_g2[i].addr.GetSize());
} else if (port_i == rmt_ref_port) {
} else if (port == rmt_ref_port) {
int counter;
for (counter = 0; counter < 3; counter++) {
if (counter != i) {
@ -848,7 +750,7 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
}
}
if (counter > 2) {
printf("sending link command from mod %c to: [%s] mod %c [%s]\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, payload);
printf("sending link command from mod %c to: [%s] mod %c [%s]:%u\n", to_remote_g2[i].from_mod, to_remote_g2[i].cs, to_remote_g2[i].to_mod, address.c_str(), port);
queryCommand[0] = 5;
queryCommand[1] = 0;
@ -866,7 +768,7 @@ void CQnetLink::g2link(const char from_mod, const char *call, const char to_mod)
// announce it here
strcpy(linked_remote_system, to_remote_g2[i].cs);
space_p = strchr(linked_remote_system, ' ');
auto space_p = strchr(linked_remote_system, ' ');
if (space_p)
*space_p = '\0';
sprintf(notify_msg[i], "%c_linked.dat_LINKED_%s_%c", to_remote_g2[i].from_mod, linked_remote_system, to_remote_g2[i].to_mod);
@ -1283,8 +1185,9 @@ void CQnetLink::Process()
i = 2;
/* Is this repeater listed in gwys.txt? */
auto gwy_pos = gwy_list.find(call);
if (gwy_pos == gwy_list.end()) {
std::string Address;
unsigned short Port;
if (qnDB.FindGW(call, Address, Port)) {
/* We did NOT find this repeater in gwys.txt, reject the incoming link request */
printf("Incoming link from %s,%s but not found in gwys.txt\n", call, ip.c_str());
i = -1;
@ -2839,7 +2742,7 @@ void CQnetLink::Process()
}
}
else if (0==memcmp(dsvt.hdr.urcall, " F", CALL_SIZE) && admin.find(call)!=admin.end()) { // only ADMIN can reload gwys.txt
gwy_list.clear();
qnDB.ClearGW();
load_gwys(gwys);
}
}

@ -160,10 +160,6 @@ private:
// Used to validate incoming donglers
regex_t preg;
// the map of remotes
// key is the callsign, data is the host
std::map<std::string, std::string> gwy_list;
unsigned char queryCommand[QUERY_SIZE];
// START: TEXT crap

Loading…
Cancel
Save

Powered by TurnKey Linux.