You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
9.6 KiB
353 lines
9.6 KiB
2 years ago
|
#define PY_SSIZE_T_CLEAN
|
||
|
#include <Python.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <netdb.h>
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <syslog.h>
|
||
|
#include <signal.h>
|
||
|
#include <string.h>
|
||
|
#include <time.h>
|
||
|
#include <poll.h>
|
||
|
|
||
|
// #include <curses.h>
|
||
|
|
||
|
#include <sys/socket.h>
|
||
|
#include <net/if.h>
|
||
|
#include <net/ethernet.h>
|
||
|
|
||
|
#include <netax25/ax25.h>
|
||
|
#include <netax25/axconfig.h>
|
||
|
#include <netax25/axlib.h>
|
||
|
|
||
|
static PyObject * config_load_ports(PyObject* self, PyObject* args) {
|
||
|
int activePort;
|
||
|
activePort = ax25_config_load_ports();
|
||
|
return PyLong_FromLong(activePort);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_first_port(PyObject* self, PyObject* args) {
|
||
|
char *portName;
|
||
|
portName = ax25_config_get_next(NULL);
|
||
|
return Py_BuildValue("s", portName);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_next_port(PyObject* self, PyObject* args) {
|
||
|
char *portName;
|
||
|
char *nextPort;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
nextPort = ax25_config_get_next(portName);
|
||
|
return Py_BuildValue("s", nextPort);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_port_name(PyObject* self, PyObject* args) {
|
||
|
char *device;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &device);
|
||
|
portName = ax25_config_get_name(device);
|
||
|
return Py_BuildValue("s", portName);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_address(PyObject* self, PyObject* args) {
|
||
|
char *portName;
|
||
|
char *address;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
address = ax25_config_get_addr(portName);
|
||
|
return Py_BuildValue("s", address);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_device(PyObject* self, PyObject* args) {
|
||
|
char *device;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
device = ax25_config_get_dev(portName);
|
||
|
return Py_BuildValue("s", device);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_window(PyObject* self, PyObject* args) {
|
||
|
int window;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
window = ax25_config_get_window(portName);
|
||
|
return PyLong_FromLong(window);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_packet_length(PyObject* self, PyObject* args) {
|
||
|
int packetLength;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
packetLength = ax25_config_get_paclen(portName);
|
||
|
return PyLong_FromLong(packetLength);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_baudrate(PyObject* self, PyObject* args) {
|
||
|
int baudRate;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
baudRate = ax25_config_get_baud(portName);
|
||
|
return Py_BuildValue("i", baudRate);
|
||
|
}
|
||
|
|
||
|
static PyObject * config_get_description(PyObject* self, PyObject* args) {
|
||
|
char *description;
|
||
|
char *portName;
|
||
|
PyArg_ParseTuple(args, "s", &portName);
|
||
|
description = ax25_config_get_desc(portName);
|
||
|
return Py_BuildValue("s", description);
|
||
|
}
|
||
|
|
||
|
static PyObject * aton_entry(PyObject* self, PyObject* args) {
|
||
|
char *callsignNetwork = null_ax25_address.ax25_call;
|
||
|
char *callsignString;
|
||
|
int result;
|
||
|
|
||
|
PyArg_ParseTuple(args, "s", &callsignString);
|
||
|
result = ax25_aton_entry(callsignString, callsignNetwork);
|
||
|
return Py_BuildValue("iy", result, callsignNetwork);
|
||
|
}
|
||
|
|
||
|
static PyObject * ntoa(PyObject* self, PyObject* args) {
|
||
|
static PyObject * callsignPython;
|
||
|
char *callsignNetwork;
|
||
|
char *callsignString;
|
||
|
|
||
|
ax25_address *callsign = &null_ax25_address;
|
||
|
|
||
|
if (!PyArg_ParseTuple(args, "y", &callsignNetwork))
|
||
|
fprintf(stderr, "ERROR: CANNOT ASSIGN\n");
|
||
|
|
||
|
strncpy(callsign->ax25_call, callsignNetwork, 7);
|
||
|
callsignString = ax25_ntoa(callsign);
|
||
|
|
||
|
callsignPython = Py_BuildValue("s", callsignString);
|
||
|
|
||
|
return callsignPython;
|
||
|
}
|
||
|
|
||
|
static PyObject * datagram_socket(PyObject* self, PyObject* args) {
|
||
|
int fileDescriptor;
|
||
|
fileDescriptor = socket(AF_AX25, SOCK_DGRAM, 0);
|
||
|
return PyLong_FromLong(fileDescriptor);
|
||
|
}
|
||
|
|
||
|
static PyObject * datagram_bind(PyObject* self, PyObject* args) {
|
||
|
struct full_sockaddr_ax25 src;
|
||
|
char *portcall, *srccall;
|
||
|
int len, sock, result;
|
||
|
|
||
|
PyArg_ParseTuple(args, "iss", &sock, &srccall, &portcall);
|
||
|
|
||
|
char * addr = malloc(sizeof(char*) * (strlen(srccall) + strlen(portcall) + 2));
|
||
|
sprintf(addr, "%s %s", srccall, portcall);
|
||
|
|
||
|
len = ax25_aton(addr, &src);
|
||
|
|
||
|
free(addr);
|
||
|
|
||
|
// Binding the socket to source
|
||
|
if (bind(sock, (struct sockaddr *)&src, len) == -1) {
|
||
|
result = 1;
|
||
|
}
|
||
|
else {
|
||
|
result = 0;
|
||
|
}
|
||
|
|
||
|
return PyLong_FromLong(result);
|
||
|
|
||
|
}
|
||
|
|
||
|
static PyObject * datagram_tx_digi(PyObject* self, PyObject* args) {
|
||
|
struct full_sockaddr_ax25 dest;
|
||
|
char *destcall = NULL, *digicall = NULL;
|
||
|
char *message;
|
||
|
int dlen, sock, result;
|
||
|
|
||
|
PyArg_ParseTuple(args, "isss", &sock, &destcall, &digicall, &message);
|
||
|
|
||
|
char * addr = malloc(sizeof(char*) * (strlen(destcall) + strlen(digicall) + 2));
|
||
|
sprintf(addr, "%s %s", destcall, digicall);
|
||
|
|
||
|
dlen = ax25_aton(addr, &dest);
|
||
|
|
||
|
free(addr);
|
||
|
|
||
|
// Send a datagram packet to socket
|
||
|
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *)&dest, dlen) == -1) {
|
||
|
result = 1;
|
||
|
}
|
||
|
|
||
|
result = 0;
|
||
|
return PyLong_FromLong(result);
|
||
|
}
|
||
|
|
||
|
static PyObject * datagram_tx(PyObject* self, PyObject* args) {
|
||
|
struct full_sockaddr_ax25 dest;
|
||
|
char *destcall = NULL;
|
||
|
char *message;
|
||
|
int dlen, sock, result;
|
||
|
|
||
|
PyArg_ParseTuple(args, "iss", &sock, &destcall, &message);
|
||
|
|
||
|
dlen = ax25_aton(destcall, &dest);
|
||
|
|
||
|
// Send a datagram packet to socket
|
||
|
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *)&dest, dlen) == -1) {
|
||
|
result = 1;
|
||
|
}
|
||
|
|
||
|
result = 0;
|
||
|
return PyLong_FromLong(result);
|
||
|
}
|
||
|
|
||
|
// Using PF_PACKET Socket
|
||
|
|
||
|
static PyObject * packet_socket(PyObject* self, PyObject* args) {
|
||
|
int fileDescriptor;
|
||
|
fileDescriptor = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_AX25));
|
||
|
return PyLong_FromLong(fileDescriptor);
|
||
|
}
|
||
|
|
||
|
// Close a socket
|
||
|
static PyObject * close_socket(PyObject* self, PyObject* args) {
|
||
|
int fileDescriptor;
|
||
|
int result;
|
||
|
|
||
|
PyArg_ParseTuple(args, "i", &fileDescriptor);
|
||
|
result = close(fileDescriptor);
|
||
|
return PyLong_FromLong(result);
|
||
|
}
|
||
|
|
||
|
static PyObject * packet_tx(PyObject* self, PyObject* args) {
|
||
|
int fileDescriptor;
|
||
|
int result;
|
||
|
int length;
|
||
|
char *buffer;
|
||
|
char *destination;
|
||
|
struct sockaddr socketAddress;
|
||
|
int addressSize = sizeof(socketAddress);
|
||
|
unsigned char newBuffer[1000];
|
||
|
int bufferLength;
|
||
|
int i;
|
||
|
int k;
|
||
|
unsigned char charBuffer;
|
||
|
|
||
|
PyArg_ParseTuple(args, "isis", &fileDescriptor, &buffer, &length, &destination);
|
||
|
|
||
|
bufferLength = strlen(buffer);
|
||
|
|
||
|
i = 0;
|
||
|
k = 0;
|
||
|
|
||
|
while ( i < bufferLength ) {
|
||
|
charBuffer = (buffer[i++] & 0x0f) << 4;
|
||
|
charBuffer = charBuffer | (buffer[i++] & 0x0f);
|
||
|
newBuffer[k++] = charBuffer;
|
||
|
}
|
||
|
|
||
|
strcpy(socketAddress.sa_data, destination);
|
||
|
socketAddress.sa_family = AF_AX25;
|
||
|
|
||
|
result = sendto(fileDescriptor, newBuffer, k, 0, &socketAddress, addressSize);
|
||
|
|
||
|
return Py_BuildValue("i", result);
|
||
|
}
|
||
|
|
||
|
static PyObject * packet_rx(PyObject* self, PyObject* args) {
|
||
|
int fileDescriptor;
|
||
|
int result;
|
||
|
int addressSize;
|
||
|
int packetSize;
|
||
|
int timeout;
|
||
|
|
||
|
struct sockaddr socketAddress;
|
||
|
struct pollfd pollFileDescriptor;
|
||
|
|
||
|
unsigned char receiveBuffer[1024];
|
||
|
|
||
|
PyArg_ParseTuple(args, "ii", &fileDescriptor, &timeout);
|
||
|
|
||
|
// Poll the socket for an available data
|
||
|
pollFileDescriptor.fd = fileDescriptor;
|
||
|
pollFileDescriptor.events = POLLRDNORM;
|
||
|
|
||
|
result = poll(&pollFileDescriptor, 1, timeout);
|
||
|
|
||
|
// Read all packet received
|
||
|
packetSize = 0;
|
||
|
socketAddress.sa_family = AF_UNSPEC;
|
||
|
strcpy(socketAddress.sa_data, "");
|
||
|
|
||
|
if (result == 1) {
|
||
|
addressSize = sizeof(socketAddress);
|
||
|
packetSize = recvfrom(fileDescriptor, receiveBuffer, sizeof(receiveBuffer),
|
||
|
0, &socketAddress, (socklen_t*)&addressSize);
|
||
|
}
|
||
|
|
||
|
return Py_BuildValue("(is)y#", socketAddress.sa_family, socketAddress.sa_data,
|
||
|
receiveBuffer, packetSize);
|
||
|
}
|
||
|
|
||
|
static PyObject *PythonAx25Error;
|
||
|
|
||
|
//////////////////////////////////////////
|
||
|
// Define methods
|
||
|
//////////////////////////////////////////
|
||
|
|
||
|
static PyMethodDef python_ax25_functions[] = {
|
||
|
{"config_load_ports", config_load_ports, METH_VARARGS, ""},
|
||
|
{"config_get_first_port", config_get_first_port, METH_VARARGS, ""},
|
||
|
{"config_get_next_port", config_get_next_port, METH_VARARGS, ""},
|
||
|
{"config_get_port_name", config_get_port_name, METH_VARARGS, ""},
|
||
|
{"config_get_address", config_get_address, METH_VARARGS, ""},
|
||
|
{"config_get_device", config_get_device, METH_VARARGS, ""},
|
||
|
{"config_get_window", config_get_window, METH_VARARGS, ""},
|
||
|
{"config_get_packet_length", config_get_packet_length, METH_VARARGS, ""},
|
||
|
{"config_get_baudrate", config_get_baudrate, METH_VARARGS, ""},
|
||
|
{"config_get_description", config_get_description, METH_VARARGS, ""},
|
||
|
{"network_to_ascii", ntoa, METH_VARARGS, ""},
|
||
|
{"ascii_to_network", aton_entry, METH_VARARGS, ""},
|
||
|
{"datagram_socket", datagram_socket, METH_VARARGS, ""},
|
||
|
{"datagram_bind", datagram_bind, METH_VARARGS, ""},
|
||
|
{"datagram_tx_digi", datagram_tx_digi, METH_VARARGS, ""},
|
||
|
{"datagram_tx", datagram_tx, METH_VARARGS, ""},
|
||
|
{"packet_socket", packet_socket, METH_VARARGS, ""},
|
||
|
{"packet_rx", packet_rx, METH_VARARGS, ""},
|
||
|
{"packet_tx", packet_tx, METH_VARARGS, ""},
|
||
|
{"close_socket", close_socket, METH_VARARGS, ""},
|
||
|
{NULL, NULL, 0, NULL}
|
||
|
};
|
||
|
|
||
|
// Initialize module
|
||
|
static struct PyModuleDef moduledef = {
|
||
|
PyModuleDef_HEAD_INIT,
|
||
|
"pythonax25",
|
||
|
"This is a python module for ax.25",
|
||
|
-1,
|
||
|
python_ax25_functions,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
PyMODINIT_FUNC
|
||
|
|
||
|
PyInit_pythonax25(void) {
|
||
|
PyObject * m;
|
||
|
m = PyModule_Create(&moduledef);
|
||
|
|
||
|
if (m == NULL)
|
||
|
return NULL;
|
||
|
|
||
|
PythonAx25Error = PyErr_NewException("pythonax25.error", NULL, NULL);
|
||
|
Py_INCREF(PythonAx25Error);
|
||
|
PyModule_AddObject(m, "error", PythonAx25Error);
|
||
|
|
||
|
return m;
|
||
|
}
|