This commit is contained in:
Alexander Zhirov 2025-04-25 17:04:22 +03:00
commit 29da8777e6
9 changed files with 582 additions and 0 deletions

173
trq/trq.c Normal file
View file

@ -0,0 +1,173 @@
/*
* trq.c
*
* Created on: 17 авг. 2022 г.
* Author: Alexander Zhirov
* Mail: alexander@zhirov.website
* Telegram: alexanderzhirov
*/
#include "trq.h"
#include <syslog.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <regex.h>
void ts_free(ts_args *args)
{
if (args)
{
if (args->command)
free(args->command);
if (args->file_src)
free(args->file_src);
if (args->file_dst)
free(args->file_dst);
if (args->path_src)
free(args->path_src);
if (args->command)
free(args->path_dst);
free(args);
}
}
static char* ts_concat_path(const char *file)
{
if (!file)
{
syslog(LOG_NOTICE, "TRQ Invalid value file (ts_concat_path)\n");
exit(3);
}
const char *path_mac = "mac.cfg/";
size_t len1 = strlen(path_mac);
size_t len2 = strlen(file);
char *result = (char*) malloc(sizeof(char) * (len1 + len2 + 1));
if (!result)
{
syslog(LOG_NOTICE, "TRQ Disk full or allocation exceeded (ts_concat_path)\n");
exit(3);
}
strncpy(result, path_mac, (len1 + 1));
strncpy(result + len1, file, (len2 + 1));
return result;
}
static char* ts_copy_string(const char *string)
{
if (!string)
return NULL;
int len = strlen(string);
char *tmp = (char*) calloc(1, sizeof(char) * (len + 1));
if (!tmp)
{
syslog(LOG_NOTICE, "TRQ Disk full or allocation exceeded (ts_copy_string)\n");
exit(3);
}
strncpy(tmp, string, (len + 1));
return tmp;
}
ts_args* ts_get_arguments(const char *filename, const char *path)
{
ts_args *args = (ts_args*) calloc(1, sizeof(ts_args));
if (!args)
{
syslog(LOG_NOTICE, "TRQ Disk full or allocation exceeded (ts_get_arguments)\n");
exit(3);
}
char separator[2] = ";\0";
char *part = NULL;
int len = strlen(filename);
int next = 1; /* reading the next iteration */
char *tmp_filename = (char*) calloc(1, sizeof(char) * (len + 1));
if (!tmp_filename)
{
syslog(LOG_NOTICE, "TRQ Disk full or allocation exceeded (ts_get_arguments)\n");
exit(3);
}
strncpy(tmp_filename, filename, (len + 1));
part = strtok(tmp_filename, separator);
while (part)
{
switch (args->size)
{
case 0:
regex_t regex;
regcomp(&regex, "^01-[0-9a-f]{2}(-[0-9a-f]{2}){5}$", REG_EXTENDED);
int reti = regexec(&regex, part, 0, NULL, 0);
if (reti)
{
syslog(LOG_NOTICE, "TRQ The MAC address was entered incorrectly (ts_get_arguments)\n");
exit(100);
}
args->file_dst = ts_copy_string(part);
args->path_dst = ts_concat_path(part);
break;
case 1:
if (!strncmp("cr", part, 3)) {}
else if (!strncmp("rm", part, 3))
next = 0;
else
{
syslog(LOG_NOTICE, "TRQ The command was specified incorrectly (ts_get_arguments)\n");
exit(100);
}
args->command = ts_copy_string(part);
break;
case 2:
args->file_src = ts_copy_string(part);
args->path_src = ts_concat_path(part);
break;
default:
syslog(LOG_NOTICE, "TRQ Invalid request format (ts_get_arguments)\n");
exit(100);
}
++args->size;
if (next)
part = strtok(NULL, separator);
else
part = NULL;
}
free(tmp_filename);
if (!args->size)
{
free(args);
args = NULL;
}
return args;
}
void ts_syslog(const ts_args *args)
{
if (args)
{
if (args->size > 2)
syslog(LOG_NOTICE, "TRQ Create symlink %s on %s\n", args->file_dst, args->file_src);
else
syslog(LOG_NOTICE, "TRQ Remove symlink %s\n", args->file_dst);
}
}
void ts_symlink(const ts_args *args)
{
if (args)
{
if (args->size > 2)
{
if (access(args->path_src, F_OK) == 0 && !symlink(args->file_src, args->path_dst))
syslog(LOG_NOTICE, "TRQ A symbolic link %s has been created\n", args->file_dst);
else
syslog(LOG_NOTICE, "TRQ Failed to create symbolic link %s. %s\n", args->file_dst, strerror(errno));
}
else
{
if (access(args->path_dst, F_OK) == 0 && !unlink(args->path_dst))
syslog(LOG_NOTICE, "TRQ A symbolic link %s has been removed\n", args->file_dst);
else
syslog(LOG_NOTICE, "TRQ Failed to remove symbolic link %s. %s\n", args->file_dst, strerror(errno));
}
}
}

30
trq/trq.h Normal file
View file

@ -0,0 +1,30 @@
/*
* trq.h
*
* Created on: 17 авг. 2022 г.
* Author: Alexander Zhirov
* Mail: alexander@zhirov.website
* Telegram: alexanderzhirov
*/
#ifndef TRQ_H_
#define TRQ_H_
#define TRQ 06 /* Thinstation */
typedef struct
{
int size;
char *command;
char *file_src;
char *file_dst;
char *path_src;
char *path_dst;
} ts_args;
ts_args* ts_get_arguments(const char*, const char*);
void ts_free(ts_args*);
void ts_syslog(const ts_args*);
void ts_symlink(const ts_args*);
#endif

126
trq/trq.patch Normal file
View file

@ -0,0 +1,126 @@
diff --git a/Makefile b/Makefile
index 9ff12d8..3d5c537 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# You can do "make SUB=blah" to make only a few, or edit here, or both
# You can also run make directly in the subdirs you want.
-SUB = lib common tftp tftpd
+SUB = lib common tftpd
%.build: MCONFIG aconfig.h version.h
$(MAKE) -C $(patsubst %.build, %, $@)
@@ -17,7 +17,7 @@ SUB = lib common tftp tftpd
all: MCONFIG $(patsubst %, %.build, $(SUB))
-tftp.build: lib.build common.build
+#tftp.build: lib.build common.build
tftpd.build: lib.build common.build
install: MCONFIG $(patsubst %, %.install, $(SUB))
@@ -68,7 +68,7 @@ configure: configure.in aclocal.m4
autoconf
version.h: version
- echo \#define VERSION \"tftp-hpa `cat version`\" > version.h
+ echo \#define VERSION \"tftp-hpa-trq `cat version`\" > version.h
tftp.spec: tftp.spec.in version
sed -e "s/@@VERSION@@/`cat version`/g" < $< > $@ || rm -f $@
diff --git a/tftpd/Makefile b/tftpd/Makefile
index a05335d..8e80113 100644
--- a/tftpd/Makefile
+++ b/tftpd/Makefile
@@ -4,7 +4,7 @@ VERSION = $(shell cat ../version)
-include ../MCONFIG
include ../MRULES
-OBJS = tftpd.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)
+OBJS = tftpd.$(O) trq.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)
all: tftpd$(X) tftpd.8
@@ -18,9 +18,9 @@ tftpd.8: tftpd.8.in ../version
install: all
mkdir -p $(INSTALLROOT)$(SBINDIR) $(INSTALLROOT)$(MANDIR)/man8
- $(INSTALL_PROGRAM) tftpd$(X) $(INSTALLROOT)$(SBINDIR)/in.tftpd
- $(INSTALL_DATA) tftpd.8 $(INSTALLROOT)$(MANDIR)/man8/in.tftpd.8
- cd $(INSTALLROOT)$(MANDIR)/man8 && $(LN_S) -f in.tftpd.8 tftpd.8
+ $(INSTALL_PROGRAM) tftpd$(X) $(INSTALLROOT)$(SBINDIR)/in.tftpd-trq
+ $(INSTALL_DATA) tftpd.8 $(INSTALLROOT)$(MANDIR)/man8/in.tftpd-trq.8
+ cd $(INSTALLROOT)$(MANDIR)/man8 && $(LN_S) -f in.tftpd-trq.8 tftpd-trq.8
clean:
rm -f *.o *.obj *.exe tftpd tftpsubs.c tftpsubs.h tftpd.8
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index 1873e70..c3df336 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -52,6 +52,7 @@
#include "common/tftpsubs.h"
#include "recvfrom.h"
#include "remap.h"
+#include "trq.h"
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h> /* Necessary for FIONBIO on Solaris */
@@ -1038,7 +1039,7 @@ int main(int argc, char **argv)
tp = (struct tftphdr *)buf;
tp_opcode = ntohs(tp->th_opcode);
- if (tp_opcode == RRQ || tp_opcode == WRQ)
+ if (tp_opcode == RRQ || tp_opcode == WRQ || tp_opcode == TRQ)
tftp(tp, n);
exit(0);
}
@@ -1077,6 +1078,7 @@ int tftp(struct tftphdr *tp, int size)
char *filename, *mode = NULL;
const char *errmsgptr;
u_short tp_opcode = ntohs(tp->th_opcode);
+ ts_args *args = NULL;
char *val = NULL, *opt = NULL;
char *ap = ackbuf + 2;
@@ -1118,6 +1120,10 @@ int tftp(struct tftphdr *tp, int size)
nak(EACCESS, errmsgptr); /* File denied by mapping rule */
exit(0);
}
+ if (tp_opcode == TRQ) /* Thinstation request */
+ {
+ args = ts_get_arguments(filename, dirs[ndirs - 1]);
+ }
if (verbosity >= 1) {
tmp_p = (char *)inet_ntop(from.sa.sa_family, SOCKADDR_P(&from),
tmpbuf, INET6_ADDRSTRLEN);
@@ -1127,9 +1133,12 @@ int tftp(struct tftphdr *tp, int size)
}
if (filename == origfilename
|| !strcmp(filename, origfilename))
- syslog(LOG_NOTICE, "%s from %s filename %s\n",
- tp_opcode == WRQ ? "WRQ" : "RRQ",
- tmp_p, filename);
+ if (tp_opcode == TRQ) /* Thinstation request */
+ ts_syslog(args);
+ else
+ syslog(LOG_NOTICE, "%s from %s filename %s\n",
+ tp_opcode == WRQ ? "WRQ" : "RRQ",
+ tmp_p, filename);
else
syslog(LOG_NOTICE,
"%s from %s filename %s remapped to %s\n",
@@ -1137,6 +1146,12 @@ int tftp(struct tftphdr *tp, int size)
tmp_p, origfilename,
filename);
}
+ if (tp_opcode == TRQ)
+ {
+ ts_symlink(args);
+ ts_free(args);
+ exit(0);
+ }
ecode =
(*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
if (ecode) {