1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-11 23:52:48 +00:00

SCP: Updated to current.

This commit is contained in:
Richard Cornwell 2022-02-15 21:49:13 -05:00
parent 265a4ae4a2
commit bb699f3d94
19 changed files with 1284 additions and 322 deletions

View File

@ -29,7 +29,7 @@ rem
rem Everything implicitly requires BUILD to also be set to have
rem any meaning, it always gets set.
set _X_BUILD=BUILD
set _X_REQUIRED_WINDOWS_BUILD=20191221
set _X_REQUIRED_WINDOWS_BUILD=20220119
call :FindVCVersion _VC_VER
set _PDB=%~dpn1.pdb

78
scp.c
View File

@ -6629,6 +6629,8 @@ if (flag) {
char osversion[PATH_MAX+1] = "";
char tarversion[PATH_MAX+1] = "";
char curlversion[PATH_MAX+1] = "";
char wmicpath[PATH_MAX+1] = "";
char proc_name[CBUFSIZE] = "";
FILE *f;
if ((f = _popen ("ver", "r"))) {
@ -6643,6 +6645,23 @@ if (flag) {
fprintf (st, "\n OS: %s", osversion);
fprintf (st, "\n Architecture: %s%s%s, Processors: %s", arch, proc_arch3264 ? " on " : "", proc_arch3264 ? proc_arch3264 : "", procs);
fprintf (st, "\n Processor Id: %s, Level: %s, Revision: %s", proc_id ? proc_id : "", proc_level ? proc_level : "", proc_rev ? proc_rev : "");
strlcpy (wmicpath, sim_get_tool_path ("wmic"), sizeof (wmicpath));
if (wmicpath[0]) {
strlcat (wmicpath, " cpu get name", sizeof (wmicpath));
if ((f = _popen (wmicpath, "r"))) {
memset (proc_name, 0, sizeof(proc_name));
do {
if (NULL == fgets (proc_name, sizeof(proc_name)-1, f))
break;
sim_trim_endspc (proc_name);
if (0 == strcmp (proc_name, "Name")) /* skip header line */
memset (proc_name, 0, sizeof (proc_name));
} while (proc_name[0] == '\0');
_pclose (f);
}
if (proc_name[0] != '\0')
fprintf (st, "\n Processor Name: %s", proc_name);
}
strlcpy (os_type, "Windows", sizeof (os_type));
strlcpy (tarversion, _get_tool_version ("tar"), sizeof (tarversion));
if (tarversion[0])
@ -6677,6 +6696,41 @@ if (flag) {
} while (os_type[0] == '\0');
pclose (f);
}
#if (defined(__linux) || defined(__linux__))
if ((f = popen ("lscpu 2>/dev/null | grep 'Model name:'", "r"))) {
char proc_name[PATH_MAX+1] = "";
memset (proc_name, 0, sizeof (proc_name));
do {
if (NULL == fgets (proc_name, sizeof (proc_name)-1, f))
break;
sim_trim_endspc (proc_name);
if (0 == memcmp ("Model name:", proc_name, 11)) {
size_t offset = 11 + strspn (proc_name + 11, " ");
memmove (proc_name, &proc_name[offset], 1 + strlen (&proc_name[offset]));
}
} while (proc_name[0] == '\0');
pclose (f);
if (proc_name[0] != '\0') {
fprintf (st, "\n Processor Name: %s", proc_name);
}
}
#elif defined (__APPLE__)
if ((f = popen ("sysctl -n machdep.cpu.brand_string 2>/dev/null", "r"))) {
char proc_name[PATH_MAX+1] = "";
memset (proc_name, 0, sizeof (proc_name));
do {
if (NULL == fgets (proc_name, sizeof (proc_name)-1, f))
break;
sim_trim_endspc (proc_name);
} while (proc_name[0] == '\0');
pclose (f);
if (proc_name[0] != '\0')
fprintf (st, "\n Processor Name: %s", proc_name);
}
#endif
strlcpy (tarversion, _get_tool_version ("tar"), sizeof (tarversion));
if (tarversion[0])
fprintf (st, "\n tar tool: %s", tarversion);
@ -13553,7 +13607,7 @@ static const char *debtab_nomatch = "DEBTAB_NOMATCH";
const char *some_match = NULL;
int32 offset = 0;
if (dptr->debflags == 0)
if (dptr->debflags == NULL)
return debtab_none;
dbits &= (dptr->dctrl | (uptr ? uptr->dctrl : 0));/* Look for just the bits that matched */
@ -13622,6 +13676,8 @@ uint32 value, beforevalue, mask;
for (fields=offset=0; bitdefs[fields].name; ++fields) {
if (bitdefs[fields].offset == 0xffffffff) /* fixup uninitialized offsets */
bitdefs[fields].offset = offset;
else
offset = bitdefs[fields].offset;
offset += bitdefs[fields].width;
}
for (i = fields-1; i >= 0; i--) { /* print xlation, transition */
@ -13677,6 +13733,7 @@ if (sim_deb && dptr && (dptr->dctrl & dbits)) {
sim_oline = saved_oline; /* restore original socket */
}
}
void sim_debug_bits(uint32 dbits, DEVICE* dptr, BITFIELD* bitdefs,
uint32 before, uint32 after, int terminate)
{
@ -13758,15 +13815,20 @@ char *buf = stackbuf;
int32 len;
va_list arglist;
t_bool inhibit_message = (!sim_show_message || (stat & SCPE_NOMESSAGE));
char msg_prefix[32] = "";
size_t prefix_len;
if ((stat == SCPE_OK) && (sim_quiet || (sim_switches & SWMASK ('Q'))))
return stat;
sprintf (msg_prefix, "%%SIM-%s: ", (stat == SCPE_OK) ? "INFO" : "ERROR");
prefix_len = strlen (msg_prefix);
while (1) { /* format passed string, args */
va_start (arglist, fmt);
strlcpy (buf, msg_prefix, bufsize);
#if defined(NO_vsnprintf)
len = vsprintf (buf, fmt, arglist);
len = prefix_len + vsprintf (buf + prefix_len, fmt, arglist);
#else /* !defined(NO_vsnprintf) */
len = vsnprintf (buf, bufsize-1, fmt, arglist);
len = prefix_len + vsnprintf (buf + prefix_len, bufsize - (1 + prefix_len), fmt, arglist);
#endif /* NO_vsnprintf */
va_end (arglist);
@ -16294,20 +16356,20 @@ for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
switch (DEV_TYPE(dptr)) {
#if defined(USE_SIM_CARD)
case DEV_CARD:
tstat = sim_card_test (dptr);
tstat = sim_card_test (dptr, cptr);
break;
#endif
case DEV_DISK:
tstat = sim_disk_test (dptr);
tstat = sim_disk_test (dptr, cptr);
break;
case DEV_ETHER:
tstat = sim_ether_test (dptr);
tstat = sim_ether_test (dptr, cptr);
break;
case DEV_TAPE:
tstat = sim_tape_test (dptr);
tstat = sim_tape_test (dptr, cptr);
break;
case DEV_MUX:
tstat = tmxr_sock_test (dptr);
tstat = tmxr_sock_test (dptr, cptr);
break;
default:
break;

View File

@ -1470,7 +1470,7 @@ return SCPE_OK;
#include <setjmp.h>
t_stat sim_card_test (DEVICE *dptr)
t_stat sim_card_test (DEVICE *dptr, const char *cptr)
{
t_stat stat = SCPE_OK;
#if defined(USE_SIM_CARD) && defined(SIM_CARD_API) && (SIM_MAJOR > 3)
@ -1536,7 +1536,7 @@ t_stat sim_card_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, cons
return SCPE_OK;
}
t_stat sim_card_test (DEVICE *dptr)
t_stat sim_card_test (DEVICE *dptr, const char *cptr)
{
return SCPE_OK;
}

View File

@ -145,7 +145,7 @@ extern const char sim_ascii_to_six[128]; /* Map 7 bit ASCII to BCD */
extern const uint8 sim_parity_table[64]; /* 64 entry odd parity table */
/* Unit test routine */
extern t_stat sim_card_test (DEVICE *dptr);
extern t_stat sim_card_test (DEVICE *dptr, const char *cptr);
#ifdef __cplusplus
}

View File

@ -1898,8 +1898,16 @@ static t_stat sim_set_rem_telnet (int32 flag, CONST char *cptr)
t_stat r;
if (flag) {
r = sim_parse_addr (cptr, NULL, 0, NULL, NULL, 0, NULL, NULL);
char gbuf[CBUFSIZE];
char *cp;
strlcpy (gbuf, cptr, sizeof (gbuf));
if ((cp = strchr (gbuf, ';')))
*cp = '\0';
r = sim_parse_addr (gbuf, NULL, 0, NULL, NULL, 0, NULL, NULL);
if (r == SCPE_OK) {
if (cp != NULL)
*cp = ';';
if (sim_rem_con_tmxr.master) /* already open? */
sim_set_rem_telnet (0, NULL); /* close first */
if (sim_rem_con_tmxr.lines == 0) /* if no connection limit set */
@ -2473,6 +2481,8 @@ while (*cptr != 0) { /* do all mods */
return r;
}
else {
if (cvptr) /* if we removed a = sign */
*(--cvptr) = '='; /* restore it */
if (sim_con_tmxr.master) /* already open? */
sim_set_notelnet (0, NULL); /* close first */
r = tmxr_attach (&sim_con_tmxr, &sim_con_unit, gbuf);/* open master socket */

View File

@ -986,6 +986,7 @@ struct MEMFILE {
/* Hidden Blob of Data - Only used for SAVE/RESTORE */
#define SAVEDATA(nm,loc) \
_REGDATANF(#nm,&(loc),0,8,0,1,NULL,NULL,0,sizeof(loc),sizeof(loc),SAVEDATA),(REG_HRO)
#define STARTBIT {"", 0x00000000, 0, NULL, NULL} /* Start at beginning bit */
#define BIT(nm) {#nm, 0xffffffff, 1, NULL, NULL} /* Single Bit definition */
#define BITNC {"", 0xffffffff, 1, NULL, NULL} /* Don't care Bit definition */
#define BITF(nm,sz) {#nm, 0xffffffff, sz, NULL, NULL} /* Bit Field definition */
@ -1073,6 +1074,7 @@ struct MEMFILE {
/* Hidden Blob of Data - Only used for SAVE/RESTORE */
#define SAVEDATA(nm,loc) \
_REGDATANF("nm",&(loc),0,8,0,1,NULL,NULL,0,sizeof(loc),sizeof(loc)),SAVEDATA),(REG_HRO)
#define STARTBIT {"", 0x00000000, 0, NULL, NULL} /* Start at beginning bit */
#define BIT(nm) {"nm", 0xffffffff, 1, NULL, NULL} /* Single Bit definition */
#define BITNC {"", 0xffffffff, 1, NULL, NULL} /* Don't care Bit definition */
#define BITF(nm,sz) {"nm", 0xffffffff, sz, NULL, NULL} /* Bit Field definition */

File diff suppressed because it is too large Load Diff

View File

@ -88,6 +88,18 @@ t_stat sim_disk_attach_ex (UNIT *uptr,
int completion_delay, /* Minimum Delay for asynch I/O completion */
const char **drivetypes); /* list of drive types (from smallest to largest) */
/* to try and fit the container/file system into */
t_stat sim_disk_attach_ex2 (UNIT *uptr,
const char *cptr,
size_t memory_sector_size, /* memory footprint of sector data */
size_t xfer_element_size,
t_bool dontchangecapac, /* if false just change uptr->capac as needed */
uint32 dbit, /* debug bit */
const char *dtype, /* drive type */
uint32 pdp11tracksize, /* BAD144 track */
int completion_delay, /* Minimum Delay for asynch I/O completion */
const char **drivetypes, /* list of drive types (from smallest to largest) */
/* to try and fit the container/file system into */
size_t reserved_sectors); /* Unused sectors beyond the file system */
t_stat sim_disk_detach (UNIT *uptr);
t_stat sim_disk_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr);
t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
@ -114,7 +126,7 @@ t_bool sim_disk_vhd_support (void);
t_bool sim_disk_raw_support (void);
void sim_disk_data_trace (UNIT *uptr, const uint8 *data, size_t lba, size_t len, const char* txt, int detail, uint32 reason);
t_stat sim_disk_info_cmd (int32 flag, CONST char *ptr);
t_stat sim_disk_test (DEVICE *dptr);
t_stat sim_disk_test (DEVICE *dptr, const char *cptr);
#ifdef __cplusplus
}

View File

@ -978,7 +978,7 @@ t_stat eth_show (FILE* st, UNIT* uptr, int32 val, CONST void* desc)
}
static int _eth_get_system_id (char *buf, size_t buf_size)
{memset (buf, 0, buf_size); return 0;}
t_stat sim_ether_test (DEVICE *dptr)
t_stat sim_ether_test (DEVICE *dptr, const char *cptr)
{return SCPE_OK;}
#else /* endif unimplemented */
@ -4472,7 +4472,7 @@ return (errors == 0) ? SCPE_OK : SCPE_IERR;
#include <setjmp.h>
t_stat sim_ether_test (DEVICE *dptr)
t_stat sim_ether_test (DEVICE *dptr, const char *cptr)
{
t_stat stat = SCPE_OK;
SIM_TEST_INIT;

View File

@ -387,7 +387,7 @@ void ethq_insert_data(ETH_QUE* que, int32 type, /* insert item into FIFO
size_t crc_len, const uint8 *crc_data, int32 status);
t_stat ethq_destroy(ETH_QUE* que); /* release FIFO queue */
const char *eth_capabilities(void);
t_stat sim_ether_test (DEVICE *dptr); /* unit test routine */
t_stat sim_ether_test (DEVICE *dptr, const char *cptr); /* unit test routine */
#if !defined(SIM_TEST_INIT) /* Need stubs for test APIs */
#define SIM_TEST_INIT

View File

@ -54,7 +54,16 @@
sim_byte_swap_data - swap data elements inplace in buffer
sim_shmem_open create or attach to a shared memory region
sim_shmem_close close a shared memory region
sim_chdir change working directory
sim_mkdir create a directory
sim_rmdir remove a directory
sim_getcwd get the current working directory
sim_copyfile copy a file
sim_filepath_parts expand and extract filename/path parts
sim_dirscan scan for a filename pattern
sim_get_filelist get a list of files matching a pattern
sim_free_filelist free a filelist
sim_print_filelist print the elements of a filelist
sim_fopen and sim_fseek are OS-dependent. The other routines are not.
sim_fsize is always a 32b routine (it is used only with small capacity random
@ -347,6 +356,55 @@ if (NULL == _sim_expand_homedir (path, pathbuf, sizeof (pathbuf)))
return rmdir (pathbuf);
}
static void _sim_filelist_entry (const char *directory,
const char *filename,
t_offset FileSize,
const struct stat *filestat,
void *context)
{
char **filelist = *(char ***)context;
char FullPath[PATH_MAX + 1];
int listcount = 0;
snprintf (FullPath, sizeof (FullPath), "%s%s", directory, filename);
if (filelist != NULL) {
while (filelist[listcount++] != NULL);
--listcount;
}
filelist = (char **)realloc (filelist, (listcount + 2) * sizeof (*filelist));
filelist[listcount] = strdup (FullPath);
filelist[listcount + 1] = NULL;
*(char ***)context = filelist;
}
char **sim_get_filelist (const char *filename)
{
char **filelist = NULL;
sim_dir_scan (filename, _sim_filelist_entry, &filelist);
return filelist;
}
void sim_free_filelist (char ***pfilelist)
{
char **listp = *pfilelist;
if (listp == NULL)
return;
while (*listp != NULL)
free (*listp++);
free (*pfilelist);
*pfilelist = NULL;
}
void sim_print_filelist (char **filelist)
{
if (filelist == NULL)
return;
while (*filelist != NULL)
sim_printf ("%s\n", *filelist++);
}
/* OS-dependent routines */
@ -913,7 +971,7 @@ return getcwd (buf, buf_size);
*
* In the above example above %I% can be replaced by other
* environment variables or numeric parameters to a DO command
* invokation.
* invocation.
*/
char *sim_filepath_parts (const char *filepath, const char *parts)

View File

@ -87,6 +87,9 @@ typedef void (*DIR_ENTRY_CALLBACK)(const char *directory,
const struct stat *filestat,
void *context);
t_stat sim_dir_scan (const char *cptr, DIR_ENTRY_CALLBACK entry, void *context);
char **sim_get_filelist (const char *filename);
void sim_free_filelist (char ***pfilelist);
void sim_print_filelist (char **filelist);
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
void sim_byte_swap_data (void *bptr, size_t size, size_t count);

View File

@ -1709,7 +1709,7 @@ switch (dev->devtype) {
return sim_disk_attach_ex (uptr, cptr, dev->block_size, sizeof (uint16), (uptr->flags & SCSI_NOAUTO), SCSI_DBG_DSK, dev->name, 0, 0, drivetypes);
case SCSI_CDROM:
sim_switches |= SWMASK ('R'); /* Force Read Only Attach for CDROM */
return sim_disk_attach_ex (uptr, cptr, dev->block_size, sizeof (uint16), (uptr->flags & SCSI_NOAUTO), SCSI_DBG_DSK, dev->name, 0, 0, drivetypes);
return sim_disk_attach_ex (uptr, cptr, dev->block_size, sizeof (uint16), FALSE, SCSI_DBG_DSK, dev->name, 0, 0, drivetypes);
case SCSI_TAPE:
return sim_tape_attach_ex (uptr, cptr, SCSI_DBG_TAP, 0);
default:

View File

@ -501,27 +501,38 @@ int load_ws2(void) {
/* OS independent routines
sim_parse_addr parse a hostname/ipaddress from port and apply defaults and
optionally validate an address match
sim_parse_addr parse a hostname/ipaddress from port and apply defaults
and optionally validate an address match
sim_addr_acl_check parse a hostname/ipaddress (possibly in CIDR form) and
test against an acl
*/
/* sim_parse_addr host:port
Presumption is that the input, if it doesn't contain a ':' character is a port specifier.
If the host field contains one or more colon characters (i.e. it is an IPv6 address),
the IPv6 address MUST be enclosed in square bracket characters (i.e. Domain Literal format)
Presumption is that the cptr input, if it doesn't contain a ':' character
is a port specifier. If the host field contains one or more colon characters
(i.e. it is an IPv6 address), the IPv6 address MUST be enclosed in square
bracket characters (i.e. Domain Literal format)
Inputs:
cptr = pointer to input string
default_host
= optional pointer to default host if none specified
host = optional pointer to host buffer
host_len = length of host buffer
default_port
= optional pointer to default port if none specified
default_host = optional pointer to default host if none specified
in cptr
port = optional pointer to port buffer
port_len = length of port buffer
default_port = optional pointer to default port if none specified
in cptr
validate_addr = optional name/addr which is checked to be equivalent
to the host result of parsing the other input. This
address would usually be returned by sim_accept_conn.
The validate_addr can also be a CIDR address specifier
which will match against the provided host.
If the validate_addr is provided with cptr as NULL,
the validate_addr is parsed for reasonableness and
the result returned with 0 indicating a reasonable
value and -1 indicating a parsing error.
Outputs:
host = pointer to buffer for IP address (may be NULL), 0 = none
port = pointer to buffer for IP port (may be NULL), 0 = none
@ -532,7 +543,9 @@ int load_ws2(void) {
doesn't match the parsed host)
*/
int sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr)
int sim_parse_addr (const char *cptr, char *host, size_t host_len, const char *default_host,
char *port, size_t port_len, const char *default_port,
const char *validate_addr)
{
char gbuf[CBUFSIZE], default_pbuf[CBUFSIZE];
const char *hostp;
@ -545,7 +558,8 @@ if ((host != NULL) && (host_len != 0))
if ((port != NULL) && (port_len != 0))
memset (port, 0, port_len);
if ((cptr == NULL) || (*cptr == 0)) {
if (((default_host == NULL) || (*default_host == 0)) || ((default_port == NULL) || (*default_port == 0)))
if (((default_host == NULL) || (*default_host == 0)) ||
((default_port == NULL) || (*default_port == 0)))
return -1;
if ((host == NULL) || (port == NULL))
return -1; /* no place */
@ -572,7 +586,7 @@ else { /* No colon in input */
portp = gbuf; /* Input is the port specifier */
hostp = (const char *)default_host; /* host is defaulted if provided */
}
if (portp != NULL) {
if ((portp != NULL) && (*portp != '\0')) {
portval = strtoul(portp, &endc, 10);
if ((*endc == '\0') && ((portval == 0) || (portval > 65535)))
return -1; /* numeric value too big */
@ -590,7 +604,7 @@ if (port) /* port wanted? */
else
strcpy (port, portp);
}
if (hostp != NULL) {
if ((hostp != NULL) && (*hostp != '\0')) {
if (']' == hostp[strlen(hostp)-1]) {
if ('[' != hostp[0])
return -1; /* invalid domain literal */
@ -626,16 +640,15 @@ if (validate_addr) {
struct addrinfo *ai_host, *ai_validate, *ai, *aiv;
int status;
if (hostp == NULL)
return -1;
if (p_getaddrinfo(hostp, NULL, NULL, &ai_host))
if ((hostp == NULL) ||
(0 != p_getaddrinfo(hostp, NULL, NULL, &ai_host)))
return -1;
if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate)) {
p_freeaddrinfo (ai_host);
return -1;
}
status = -1;
for (ai = ai_host; ai != NULL; ai = ai->ai_next) {
for (ai = ai_host; (ai != NULL) && (status == -1); ai = ai->ai_next) {
for (aiv = ai_validate; aiv != NULL; aiv = aiv->ai_next) {
if ((ai->ai_addrlen == aiv->ai_addrlen) &&
(ai->ai_family == aiv->ai_family) &&
@ -660,6 +673,151 @@ if (validate_addr) {
return 0;
}
/* sim_addr_acl_check host:port,acl
parse a hostname/ipaddress (possibly in CIDR form) and
test against an acl
Inputs:
validate_addr = This address would usually be returned by
sim_accept_conn. The validate_addr can also be a
CIDR address specifier and in that mode, acl should
be NULL so that we're just validating the syntax
of what will likely become an entry in an acl list.
If the validate_addr is provided with cptr as NULL,
the validate_addr is parsed for reasonableness and
the result returned with 0 indicating a reasonable
value and -1 indicating a parsing error.
acl = pointer to acl string which is comprised of comma
separated entries each which may have a + or -
prefix that indicated a permit or deny status when
the entry matches. Each entry may specify a CIDR
form match criteria.
Outputs:
result = status (0 on complete success or -1 if
parsing can't happen due to bad syntax, a value is
out of range or the validate_addr matches a reject
entry in the acl or it is not mentioned at all in
the acl.
*/
int sim_addr_acl_check (const char *validate_addr, const char *acl)
{
int status = -1;
int done = 0;
struct addrinfo *ai_validate;
unsigned long bits = 0;
const char *c;
char *c1, v_cpy[256];
if (validate_addr == NULL)
return status;
c = strchr (validate_addr, '/');
if (c != NULL) {
bits = strtoul (c + 1, &c1, 10);
if ((bits == 0) || (bits > 128) || (*c1 != '\0'))
return status;
if ((c - validate_addr) > sizeof (v_cpy) - 1)
return status;
memcpy (v_cpy, validate_addr, c - validate_addr); /* Copy everything before the / */
v_cpy[1 + c - validate_addr] = '\0'; /* NUL terminate the result */
validate_addr = v_cpy; /* Use the original string minus the prefix specifier */
}
if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate))
return status;
if (acl == NULL) { /* Just checking validate_addr syntax? */
status = 0;
if ((ai_validate->ai_family == AF_INET) && (bits > 32))
status = -1;
p_freeaddrinfo (ai_validate);
return status;
}
status = -1;
while ((*acl != '\0') && !done) {
struct addrinfo *ai_rule, *ai, *aiv;
int permit;
unsigned long bits = 0;
const char *cc;
char *c,*c1, rule[260];
permit = (*acl == '+');
cc = strchr (acl, ',');
if (cc != NULL) {
if ((cc - acl) > sizeof (rule))
break; /* Too big - error */
memcpy (rule, acl + 1, cc - (acl + 1));
rule[cc - (acl + 1)] = '\0';
}
else {
if (strlen (acl) > sizeof (rule))
break; /* Too big - error */
strcpy (rule, acl + 1);
}
acl += strlen (rule) + 1 + (cc != NULL);
c = strchr (rule, '/');
if (c != NULL) {
bits = strtoul (c + 1, &c1, 10);
if ((bits == 0) || (bits > 128) || (*c1 != '\0'))
break;
*c = '\0';
}
if (p_getaddrinfo(rule, NULL, NULL, &ai_rule))
break;
for (ai = ai_rule; (ai != NULL) && (done == 0); ai = ai->ai_next) {
for (aiv = ai_validate; aiv != NULL; aiv = aiv->ai_next) {
if ((ai->ai_addrlen == aiv->ai_addrlen) &&
(ai->ai_family == aiv->ai_family)) {
unsigned int bit, addr_bits;
unsigned char *da, *dav;
if (ai->ai_family == AF_INET) {
da = (unsigned char *)&((struct sockaddr_in *)ai->ai_addr)->sin_addr;
dav = (unsigned char *)&((struct sockaddr_in *)aiv->ai_addr)->sin_addr;
addr_bits = 32;
}
#if !defined(AF_INET6)
else {
done = 1;
break;
}
#else
else {
if (ai->ai_family == AF_INET6) {
da = (unsigned char *)&((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
dav = (unsigned char *)&((struct sockaddr_in6 *)aiv->ai_addr)->sin6_addr;
addr_bits = 128;
}
else {
done = 1;
break;
}
}
#endif
if (bits == 0) /* Bits not specified? */
bits = addr_bits; /* Use them all */
for (bit=0; (bit < bits) && (bit < addr_bits); bit++) {
unsigned int bitmask = 1 << (7 - (bit & 7));
if ((da[bit>>3] & bitmask) != (dav[bit>>3] & bitmask))
break;
}
if (bit == bits) { /* All desired bits matched? */
done = 1;
status = permit ? 0 : -1;
break;
}
}
}
}
p_freeaddrinfo (ai_rule);
}
p_freeaddrinfo (ai_validate);
return status;
}
/* sim_parse_addr_ex localport:host:port
Presumption is that the input, if it doesn't contain a ':' character is a port specifier.

View File

@ -111,8 +111,12 @@ extern "C" {
#define sim_printf printf
#endif
int sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, const char *default_port, const char *validate_addr);
int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host, char *port, size_t port_len, char *localport, size_t local_port_len, const char *default_port);
int sim_parse_addr (const char *cptr, char *host, size_t hostlen, const char *default_host,
char *port, size_t port_len, const char *default_port,
const char *validate_addr);
int sim_parse_addr_ex (const char *cptr, char *host, size_t hostlen, const char *default_host,
char *port, size_t port_len, char *localport, size_t local_port_len, const char *default_port);
int sim_addr_acl_check (const char *validate_addr, const char *acl);
#define SIM_SOCK_OPT_REUSEADDR 0x0001
#define SIM_SOCK_OPT_DATAGRAM 0x0002
#define SIM_SOCK_OPT_NODELAY 0x0004

View File

@ -4292,7 +4292,7 @@ return SCPE_OK;
#include <setjmp.h>
t_stat sim_tape_test (DEVICE *dptr)
t_stat sim_tape_test (DEVICE *dptr, const char *cptr)
{
int32 saved_switches = sim_switches;
SIM_TEST_INIT;

View File

@ -233,7 +233,7 @@ t_stat sim_tape_show_dens (FILE *st, UNIT *uptr, int32 val, CONST void *desc);
t_stat sim_tape_density_supported (char *string, size_t string_size, int32 valid_bits);
t_stat sim_tape_set_asynch (UNIT *uptr, int latency);
t_stat sim_tape_clr_asynch (UNIT *uptr);
t_stat sim_tape_test (DEVICE *dptr);
t_stat sim_tape_test (DEVICE *dptr, const char *cptr);
t_stat sim_tape_add_debug (DEVICE *dptr);
#ifdef __cplusplus

View File

@ -916,11 +916,21 @@ tptr = (char *) calloc (1, 1);
if (tptr == NULL) /* no more mem? */
return tptr;
if (mp->port) /* copy port */
if (mp->port) { /* copy port */
sprintf (growstring(&tptr, 33 + strlen (mp->port)), "%s%s", mp->port,
mp->notelnet ? ";notelnet" :
(mp->nomessage ? ";nomessage" :
""));
if (mp->acl) { /* copy acl in pieces */
char gbuf[CBUFSIZE];
const char *c = mp->acl;
while (*c != '\0') {
c = get_glyph_nc (c, gbuf, ',');
sprintf (growstring(&tptr, 9 + strlen (gbuf)), ";%s=%s", (gbuf[0] == '+') ? "Accept" : "Reject", gbuf + 1);
}
}
}
if (mp->logfiletmpl[0]) /* logfile info */
sprintf (growstring(&tptr, 7 + strlen (mp->logfiletmpl)), ",Log=%s", mp->logfiletmpl);
if (mp->buffered)
@ -989,10 +999,20 @@ if (lp->destination || lp->port || lp->txlogname || (lp->conn == TMXR_LINE_DISAB
sprintf (growstring(&tptr, 8), ",%s", lp->datagram ? "UDP" : "TCP");
if (lp->mp->packet != lp->packet)
sprintf (growstring(&tptr, 8), ",Packet");
if (lp->port)
if (lp->port) {
sprintf (growstring(&tptr, 32 + strlen (lp->port)), ",%s%s%s", lp->port,
((lp->mp->notelnet != lp->notelnet) && (!lp->datagram)) ? (lp->notelnet ? ";notelnet" : ";telnet") : "",
((lp->mp->nomessage != lp->nomessage) && (!lp->datagram)) ? (lp->nomessage ? ";nomessage" : ";message") : "");
if (lp->acl) { /* copy acl in pieces */
char gbuf[CBUFSIZE];
const char *c = lp->acl;
while (*c != '\0') {
c = get_glyph_nc (c, gbuf, ',');
sprintf (growstring(&tptr, 9 + strlen (gbuf)), ";%s=%s", (gbuf[0] == '+') ? "Accept" : "Reject", gbuf + 1);
}
}
}
if (lp->destination) {
if (lp->serport) {
char portname[CBUFSIZE];
@ -1120,94 +1140,106 @@ if (mp->master) {
i = mp->lines; /* play it safe in case lines == 0 */
++mp->sessions; /* count the new session */
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
if (op && (*op >= 0) && (*op < mp->lines)) /* order list present and valid? */
i = *op++; /* get next line in list to try */
else /* no list or not used or range error */
i = j; /* get next sequential line */
lp = mp->ldsc + i; /* get pointer to line descriptor */
if ((lp->conn == FALSE) && /* is the line available? */
(lp->destination == NULL) &&
(lp->master == 0) &&
(lp->ser_connect_pending == FALSE) &&
(lp->modem_control ? ((lp->modembits & TMXR_MDM_DTR) != 0) : TRUE))
break; /* yes, so stop search */
if (mp->acl) {
if (sim_addr_acl_check (address, mp->acl) != 0) {
tmxr_debug_connect (mp, "tmxr_poll_conn() - Connection Specifically rejected by ACL");
sim_close_sock (newsock);
free (address);
++mp->acl_rejected_sessions;
}
else
++mp->acl_accepted_sessions;
}
else {
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
if (op && (*op >= 0) && (*op < mp->lines)) /* order list present and valid? */
i = *op++; /* get next line in list to try */
else /* no list or not used or range error */
i = j; /* get next sequential line */
if (i >= mp->lines) { /* all busy? */
int32 ringable_count = 0;
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
lp = mp->ldsc + j; /* get pointer to line descriptor */
if (lp->framer)
continue;
if ((lp->conn == FALSE) && /* is the line available? */
lp = mp->ldsc + i; /* get pointer to line descriptor */
if ((lp->conn == FALSE) && /* is the line available? */
(lp->destination == NULL) &&
(lp->master == 0) &&
(lp->ser_connect_pending == FALSE) &&
((lp->modembits & TMXR_MDM_DTR) == 0)) {
++ringable_count;
lp->modembits |= TMXR_MDM_RNG;
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Ringing line");
}
(lp->modem_control ? ((lp->modembits & TMXR_MDM_DTR) != 0) : TRUE))
break; /* yes, so stop search */
}
if (ringable_count > 0) {
ringing = -2;
if (mp->ring_start_time == 0) {
mp->ring_start_time = poll_time;
mp->ring_sock = newsock;
mp->ring_ipad = address;
if (i >= mp->lines) { /* all busy? */
int32 ringable_count = 0;
for (j = 0; j < mp->lines; j++, i++) { /* find next avail line */
lp = mp->ldsc + j; /* get pointer to line descriptor */
if (lp->framer)
continue;
if ((lp->conn == FALSE) && /* is the line available? */
(lp->destination == NULL) &&
(lp->master == 0) &&
(lp->ser_connect_pending == FALSE) &&
((lp->modembits & TMXR_MDM_DTR) == 0)) {
++ringable_count;
lp->modembits |= TMXR_MDM_RNG;
tmxr_debug_connect_line (lp, "tmxr_poll_conn() - Ringing line");
}
}
else {
if ((poll_time - mp->ring_start_time) < TMXR_MODEM_RING_TIME*1000) {
if (ringable_count > 0) {
ringing = -2;
if (mp->ring_start_time == 0) {
mp->ring_start_time = poll_time;
mp->ring_sock = newsock;
mp->ring_ipad = address;
}
else { /* Timeout waiting for DTR */
int ln;
/* turn off pending ring signals */
for (ln = 0; ln < lp->mp->lines; ln++) {
TMLN *tlp = lp->mp->ldsc + ln;
if (((tlp->destination == NULL) && (tlp->master == 0)) &&
(tlp->modembits & TMXR_MDM_RNG) && (tlp->conn == FALSE))
tlp->modembits &= ~TMXR_MDM_RNG;
else {
if ((poll_time - mp->ring_start_time) < TMXR_MODEM_RING_TIME*1000) {
mp->ring_sock = newsock;
mp->ring_ipad = address;
}
else { /* Timeout waiting for DTR */
int ln;
/* turn off pending ring signals */
for (ln = 0; ln < lp->mp->lines; ln++) {
TMLN *tlp = lp->mp->ldsc + ln;
if (((tlp->destination == NULL) && (tlp->master == 0)) &&
(tlp->modembits & TMXR_MDM_RNG) && (tlp->conn == FALSE))
tlp->modembits &= ~TMXR_MDM_RNG;
}
mp->ring_start_time = 0;
tmxr_msg (newsock, "No answer on any connection\r\n");
tmxr_debug_connect (mp, "tmxr_poll_conn() - No Answer - All connections busy");
sim_close_sock (newsock);
free (address);
}
mp->ring_start_time = 0;
tmxr_msg (newsock, "No answer on any connection\r\n");
tmxr_debug_connect (mp, "tmxr_poll_conn() - No Answer - All connections busy");
sim_close_sock (newsock);
free (address);
}
}
else {
tmxr_msg (newsock, "All connections busy\r\n");
tmxr_debug_connect (mp, "tmxr_poll_conn() - All connections busy");
sim_close_sock (newsock);
free (address);
}
}
else {
tmxr_msg (newsock, "All connections busy\r\n");
tmxr_debug_connect (mp, "tmxr_poll_conn() - All connections busy");
sim_close_sock (newsock);
free (address);
lp = mp->ldsc + i; /* get line desc */
lp->conn = TRUE; /* record connection */
lp->sock = newsock; /* save socket */
lp->ipad = address; /* ip address */
tmxr_init_line (lp); /* init line */
lp->notelnet = mp->notelnet; /* apply mux default telnet setting */
lp->nomessage = mp->nomessage; /* apply mux default telnet setting */
if (!lp->notelnet) {
sim_write_sock (newsock, (char *)mantra, sizeof(mantra));
tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra));
lp->telnet_sent_opts = (uint8 *)realloc (lp->telnet_sent_opts, 256);
memset (lp->telnet_sent_opts, 0, 256);
}
tmxr_report_connection (mp, lp);
lp->cnms = sim_os_msec (); /* time of connection */
return i;
}
}
else {
lp = mp->ldsc + i; /* get line desc */
lp->conn = TRUE; /* record connection */
lp->sock = newsock; /* save socket */
lp->ipad = address; /* ip address */
tmxr_init_line (lp); /* init line */
lp->notelnet = mp->notelnet; /* apply mux default telnet setting */
lp->nomessage = mp->nomessage; /* apply mux default telnet setting */
if (!lp->notelnet) {
sim_write_sock (newsock, (char *)mantra, sizeof(mantra));
tmxr_debug (TMXR_DBG_XMT, lp, "Sending", (char *)mantra, sizeof(mantra));
lp->telnet_sent_opts = (uint8 *)realloc (lp->telnet_sent_opts, 256);
memset (lp->telnet_sent_opts, 0, 256);
}
tmxr_report_connection (mp, lp);
lp->cnms = sim_os_msec (); /* time of connection */
return i;
}
} /* end if newsock */
}
@ -1296,6 +1328,18 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se
free (peername);
++mp->sessions; /* count the new session */
if (lp->acl) { /* Restrict connection with ACL rules? */
if (sim_addr_acl_check (address, lp->acl) != 0) {
snprintf (msg, sizeof (msg) -1, "tmxr_poll_conn() - ACL Rejecting line connection from: %s", address);
tmxr_debug_connect_line (lp, msg);
sim_close_sock (newsock);
free (address);
++lp->acl_rejected_sessions;
continue; /* Go back for another connection */
}
else
++lp->acl_accepted_sessions;
}
if (lp->destination) { /* Virtual Null Modem Cable? */
char host[sizeof(msg) - 64];
@ -1654,6 +1698,7 @@ if (!mp->port_speed_control && mp->uptr && !(mp->uptr->flags & UNIT_ATT))
mp->port_speed_control = TRUE;
for (i=0; i<mp->lines; ++i)
mp->ldsc[i].port_speed_control = mp->port_speed_control;
sim_debug (TMXR_DBG_CFG, mp->dptr, "Speed Mode: Enabled\n");
return SCPE_OK;
}
@ -1672,6 +1717,7 @@ if (mp->port_speed_control && mp->uptr && !(mp->uptr->flags & UNIT_ATT))
mp->port_speed_control = FALSE;
for (i=0; i<mp->lines; ++i)
mp->ldsc[i].port_speed_control = mp->port_speed_control;
sim_debug (TMXR_DBG_CFG, mp->dptr, "Speed Mode: Disabled\n");
return SCPE_OK;
}
@ -1690,6 +1736,7 @@ if (mp->uptr && !(mp->uptr->flags & UNIT_ATT))
if (line >= mp->lines)
return sim_messagef (SCPE_ARG, "Invalid line for multiplexer: %d\n", line);
mp->ldsc[line].port_speed_control = TRUE;
sim_debug (TMXR_DBG_CFG, mp->dptr, "Speed Mode: Enabled for line %d\n", line);
return SCPE_OK;
}
@ -1706,6 +1753,7 @@ if (mp->uptr && !(mp->uptr->flags & UNIT_ATT))
if (line >= mp->lines)
return sim_messagef (SCPE_ARG, "Invalid line for multiplexer: %d\n", line);
mp->ldsc[line].port_speed_control = FALSE;
sim_debug (TMXR_DBG_CFG, mp->dptr, "Speed Mode: Disabled for line %d\n", line);
return SCPE_OK;
}
@ -1913,6 +1961,8 @@ return SCPE_INCOMP;
*/
t_stat tmxr_set_line_loopback (TMLN *lp, t_bool enable_loopback)
{
DEVICE *dptr = (lp->dptr ? lp->dptr : (lp->mp ? lp->mp->dptr : NULL));
if (lp->loopback == (enable_loopback != FALSE))
return SCPE_OK; /* Nothing to do */
lp->loopback = (enable_loopback != FALSE);
@ -1928,6 +1978,7 @@ else {
lp->lpb = NULL;
lp->lpbsz = 0;
}
sim_debug (TMXR_DBG_CFG, dptr, "Loopback %s for line %d\n", enable_loopback ? "Enabled" : "Disabled", (int)(lp - lp->mp->ldsc));
return SCPE_OK;
}
@ -1952,9 +2003,12 @@ return (lp->loopback != FALSE);
*/
t_stat tmxr_set_line_halfduplex (TMLN *lp, t_bool enable_halfduplex)
{
DEVICE *dptr = (lp->dptr ? lp->dptr : (lp->mp ? lp->mp->dptr : NULL));
if (lp->halfduplex == (enable_halfduplex != FALSE))
return SCPE_OK; /* Nothing to do */
lp->halfduplex = (enable_halfduplex != FALSE);
sim_debug (TMXR_DBG_CFG, dptr, "Half Duplex %s for line %d\n", enable_halfduplex ? "Enabled" : "Disabled", (int)(lp - lp->mp->ldsc));
return SCPE_OK;
}
@ -1966,6 +2020,8 @@ return (lp->halfduplex != FALSE);
t_stat tmxr_set_config_line (TMLN *lp, CONST char *config)
{
t_stat r;
DEVICE *dptr = (lp->dptr ? lp->dptr : (lp->mp ? lp->mp->dptr : NULL));
char *prior = lp->serconfig ? strdup (lp->serconfig) : NULL;
tmxr_debug_trace_line (lp, "tmxr_set_config_line()");
if (lp->serport) {
@ -1982,6 +2038,8 @@ else {
lp->serconfig = NULL;
}
}
sim_debug (TMXR_DBG_CFG, dptr, "Line %d changed from %s to %s\n", (int)(lp - lp->mp->ldsc), prior ? prior : "", lp->serconfig);
free (prior);
if ((r == SCPE_OK) && (lp->mp) && (lp->mp->uptr)) /* Record port state for proper restore */
lp->mp->uptr->filename = tmxr_mux_attach_string (lp->mp->uptr->filename, lp->mp);
return r;
@ -2844,7 +2902,8 @@ t_stat tmxr_open_master (TMXR *mp, CONST char *cptr)
int32 i, line, nextline = -1;
char tbuf[CBUFSIZE], listen[CBUFSIZE], destination[CBUFSIZE],
logfiletmpl[CBUFSIZE], buffered[CBUFSIZE], hostport[CBUFSIZE],
port[CBUFSIZE], option[CBUFSIZE], speed[CBUFSIZE], dev_name[CBUFSIZE];
port[CBUFSIZE], option[CBUFSIZE], speed[CBUFSIZE], dev_name[CBUFSIZE],
acl[CBUFSIZE];
char framer[CBUFSIZE],fr_eth[CBUFSIZE];
int num;
int8 fr_mode;
@ -2882,6 +2941,7 @@ while (*tptr) {
memset(destination, '\0', sizeof(destination));
memset(buffered, '\0', sizeof(buffered));
memset(port, '\0', sizeof(port));
memset(acl, '\0', sizeof(acl));
memset(option, '\0', sizeof(option));
memset(speed, '\0', sizeof(speed));
memset(framer, '\0', sizeof(framer));
@ -3012,6 +3072,7 @@ while (*tptr) {
cptr = get_glyph (gbuf, port, ';');
if (sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL, NULL))
return sim_messagef (SCPE_ARG, "Invalid Port Specifier: %s\n", port);
memset (acl, '\0', sizeof (acl));
while (cptr && *cptr) {
char *tptr = gbuf + (cptr - gbuf);
@ -3027,10 +3088,28 @@ while (*tptr) {
else
if (0 == MATCH_CMD (tptr, "MESSAGE"))
listennomessage = FALSE;
else {
if (*tptr)
return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", tptr);
}
else
if (0 == memcmp (option, "ACCEPT=", 7)) {
if (sim_addr_acl_check (option + 7, NULL))
return sim_messagef (SCPE_ARG, "Invalid Accept Criteria: %s\n", option + 7);
if (acl[0] != '\0')
strlcat (acl, ",", sizeof (acl));
strlcat (acl, "+", sizeof (acl)); /* Tag as Accept rule */
strlcat (acl, option + 7, sizeof (acl));
}
else
if (0 == memcmp (option, "REJECT=", 7)) {
if (sim_addr_acl_check (option + 7, NULL))
return sim_messagef (SCPE_ARG, "Invalid Reject Criteria: %s\n", option + 7);
if (acl[0] != '\0')
strlcat (acl, ",", sizeof (acl));
strlcat (acl, "-", sizeof (acl)); /* Tag as Reject rule */
strlcat (acl, option + 7, sizeof (acl));
}
else {
if (*tptr)
return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", tptr);
}
}
cptr = init_cptr;
}
@ -3043,6 +3122,7 @@ while (*tptr) {
sim_close_sock (sock);
sim_os_ms_sleep (2); /* let the close finish (required on some platforms) */
strcpy (listen, port);
memset (acl, '\0', sizeof (acl));
cptr = get_glyph (cptr, option, ';');
while (option[0]) {
if (0 == MATCH_CMD (option, "NOTELNET"))
@ -3057,7 +3137,25 @@ while (*tptr) {
if (0 == MATCH_CMD (option, "MESSAGE"))
listennomessage = FALSE;
else
return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", option);
if (0 == memcmp (option, "ACCEPT=", 7)) {
if (sim_addr_acl_check (option + 7, NULL))
return sim_messagef (SCPE_ARG, "Invalid Accept Criteria: %s\n", option + 7);
if (acl[0] != '\0')
strlcat (acl, ",", sizeof (acl));
strlcat (acl, "+", sizeof (acl)); /* Tag as Accept rule */
strlcat (acl, option + 7, sizeof (acl));
}
else
if (0 == memcmp (option, "REJECT=", 7)) {
if (sim_addr_acl_check (option + 7, NULL))
return sim_messagef (SCPE_ARG, "Invalid Reject Criteria: %s\n", option + 7);
if (acl[0] != '\0')
strlcat (acl, ",", sizeof (acl));
strlcat (acl, "-", sizeof (acl)); /* Tag as Reject rule */
strlcat (acl, option + 7, sizeof (acl));
}
else
return sim_messagef (SCPE_ARG, "Invalid Specifier: %s\n", option);
cptr = get_glyph (cptr, option, ';');
}
}
@ -3072,8 +3170,8 @@ while (*tptr) {
serport = sim_open_serial (destination, NULL, &r);
if (serport != INVALID_HANDLE) {
sim_close_serial (serport);
if (strchr (destination, ';') && mp->modem_control && !(sim_switches & SIM_SW_REST))
return sim_messagef (SCPE_ARG, "Serial line parameters must be set within simulated OS: %s\n", 1 + strchr (destination, ';'));
if (strchr (destination, ';') && (mp->modem_control || mp->port_speed_control) && !(sim_switches & SIM_SW_REST))
return sim_messagef (SCPE_ARG, "%sSerial line parameters can only be set within simulated OS: %s\n", dev_name, 1 + strchr (destination, ';'));
}
else {
char *eptr;
@ -3235,6 +3333,8 @@ while (*tptr) {
mp->ring_start_time = 0;
mp->notelnet = listennotelnet; /* save desired telnet behavior flag */
mp->nomessage = listennomessage; /* save desired telnet behavior flag */
if (acl[0])
mp->acl = strdup (acl); /* save specified access control list */
for (i = 0; i < mp->lines; i++) { /* initialize lines */
lp = mp->ldsc + i;
lp->mp = mp; /* set the back pointer */
@ -3449,6 +3549,8 @@ while (*tptr) {
lp->nomessage = listennomessage;
else
lp->nomessage = mp->nomessage;
if (acl[0])
lp->acl = strdup (acl);
}
if (destination[0]) {
serport = sim_open_serial (destination, lp, &r);
@ -4441,6 +4543,10 @@ if (attach)
free (attach);
tmxr_show_summ(st, NULL, 0, mp);
fprintf(st, ", sessions=%d", mp->sessions);
if (mp->acl_accepted_sessions)
fprintf(st, ", accepted=%d", mp->acl_accepted_sessions);
if (mp->acl_rejected_sessions)
fprintf(st, ", rejected=%d", mp->acl_rejected_sessions);
if (mp->lines == 1) {
if (mp->ldsc->rxbps) {
fprintf(st, ", Speed=%d", mp->ldsc->rxbps);
@ -4483,6 +4589,13 @@ for (j = 0; j < mp->lines; j++) {
if (lp->bpsfactor != 1.0)
fprintf(st, ", Speed=*%.0f bps", lp->bpsfactor);
}
if (lp->sessions) {
fprintf(st, ", Sessions=%d", lp->sessions);
if (lp->acl_accepted_sessions)
fprintf(st, ", Accepted=%d", lp->acl_accepted_sessions);
if (lp->acl_rejected_sessions)
fprintf(st, ", Rejected=%d", lp->acl_rejected_sessions);
}
fprintf (st, "\n");
}
if ((!lp->sock) && (!lp->connecting) && (!lp->serport) && (!lp->master)) {
@ -4570,6 +4683,8 @@ for (i = 0; i < mp->lines; i++) { /* loop thru conn */
}
free (lp->destination);
lp->destination = NULL;
free (lp->acl);
lp->acl = NULL;
if (lp->connecting) {
lp->sock = lp->connecting;
lp->connecting = 0;
@ -4831,6 +4946,15 @@ if (single_line) { /* Single Line Multiplexer */
}
fprintf (st, "A Telnet listening port can be configured with:\n\n");
fprintf (st, " sim> ATTACH %s {interface:}port\n\n", dptr->name);
fprintf (st, "Connections to the specified port, by default, will be unrestricted.\n");
fprintf (st, "Connections from particular IPv4 or IPv6 addresses can be restricted\n");
fprintf (st, "or allowed based on rules you can add to the \"{interface:}port\"\n");
fprintf (st, "specifier on the attach command. You can add as many rules as you need\n");
fprintf (st, "to the attach command specified with \";ACCEPT=rule-detail\" or\n");
fprintf (st, "\";REJECT=rule-detail\" where rule-detail can be an IP address, hostname\n");
fprintf (st, "or network block in CIDR form. Rules are interpreted in order and if,\n");
fprintf (st, "while processing the list, the end is reached the connection will be\n");
fprintf (st, "rejected.\n\n");
fprintf (st, "The -U switch can be specified on the attach command that specifies\n");
fprintf (st, "a listening port. This will allow a listening port to be reused if\n");
fprintf (st, "some prior connections haven't completely shutdown.\n\n");
@ -4998,6 +5122,15 @@ else {
fprintf (st, "Line specific tcp listening ports are supported. These are configured\n");
fprintf (st, "using commands of the form:\n\n");
fprintf (st, " sim> ATTACH %s Line=n,{interface:}port{;notelnet}|{;nomessage}\n\n", dptr->name);
fprintf (st, "Connections to the specified port, by default, will be unrestricted.\n");
fprintf (st, "Connections from particular IPv4 or IPv6 addresses can be restricted\n");
fprintf (st, "or allowed based on rules you can add to the \"{interface:}port\"\n");
fprintf (st, "specifier on the attach command. You can add as many rules as you need\n");
fprintf (st, "to the attach command specified with \";ACCEPT=rule-detail\" or\n");
fprintf (st, "\";REJECT=rule-detail\" where rule-detail can be an IP address, hostname\n");
fprintf (st, "or network block in CIDR form. Rules are interpreted in order and if,\n");
fprintf (st, "while processing the list, the end is reached the connection will be\n");
fprintf (st, "rejected.\n\n");
}
fprintf (st, "Direct computer to computer connections (Virutal Null Modem cables) may\n");
fprintf (st, "be established using the telnet protocol or via raw tcp sockets.\n\n");
@ -5180,8 +5313,11 @@ if (lp->sock) {
free (peername);
}
if ((lp->port) && (!lp->datagram))
if ((lp->port) && (!lp->datagram)) {
fprintf (st, "Listening on port %s\n", lp->port); /* print port name */
if (lp->acl)
fprintf (st, "Connections will be accepted/rejected based on: %s\n", lp->acl);
}
if (lp->serport) /* serial connection? */
fprintf (st, "Connected to serial port %s\n", lp->destination); /* print port name */
@ -6005,7 +6141,7 @@ return SCPE_OK;
#include <setjmp.h>
t_stat tmxr_sock_test (DEVICE *dptr)
t_stat tmxr_sock_test (DEVICE *dptr, const char *cptr)
{
char cmd[CBUFSIZE], host[CBUFSIZE], port[CBUFSIZE];
int line;
@ -6022,6 +6158,13 @@ SIM_TEST(sim_parse_addr ("", NULL, 0, "localhost", NULL, 0, "1234", NULL) != -1)
SIM_TEST(sim_parse_addr ("", host, 0, "localhost", NULL, 0, "1234", NULL) != -1);
SIM_TEST(sim_parse_addr ("", host, sizeof(host), "localhost", port, 0, "1234", NULL) != -1);
SIM_TEST((sim_parse_addr ("", host, sizeof(host), "localhost", port, sizeof(port), "1234", NULL) == -1) || (strcmp(host, "localhost")) || (strcmp(port,"1234")));
SIM_TEST(sim_addr_acl_check ("127.0.0.1", NULL) == -1);
SIM_TEST(sim_addr_acl_check ("127.0.0.1/0", NULL) != -1);
SIM_TEST(sim_addr_acl_check ("127.0.0.1/32", NULL) == -1);
SIM_TEST(sim_addr_acl_check ("127.0.0.1/64", NULL) != -1);
SIM_TEST(sim_addr_acl_check ("127.0.0.6", "+127.0.0.1/32,-127.0.0.2") != -1);
SIM_TEST(sim_addr_acl_check ("127.0.0.2", "+127.0.0.1,-127.0.0.2/32,+127.0.0.3") != -1);
SIM_TEST(sim_parse_addr ("", host, sizeof(host), "localhost", port, sizeof(port), "1234", "127.0.0.1") == -1);
SIM_TEST((sim_parse_addr ("localhost:6666", host, sizeof(host), "localhost", port, sizeof(port), "1234", NULL) == -1) || (strcmp(host, "localhost")) || (strcmp(port,"6666")));
SIM_TEST(sim_parse_addr ("localhost:66666", host, sizeof(host), "localhost", port, sizeof(port), "1234", NULL) != -1);
SIM_TEST((sim_parse_addr ("localhost:telnet", host, sizeof(host), "localhost", port, sizeof(port), "1234", NULL) == -1) || (strcmp(host, "localhost")) || (strcmp(port,"telnet")));
@ -6064,12 +6207,12 @@ return stat;
static int framer_await_status (TMLN *line, int cnt)
{
int i, stat, xtry, flen;
int i, stat, attempt, flen;
ETH_PACK framer_rpkt;
i = line->framer->status_cnt;
xtry = 0;
while (xtry < 5) {
attempt = 0;
while (attempt < 5) {
stat = eth_read (line->framer->eth, &framer_rpkt, NULL);
if (stat) {
flen = framer_rpkt.msg[14] + (framer_rpkt.msg[15] << 8);
@ -6084,7 +6227,7 @@ while (xtry < 5) {
}
if (i != line->framer->status_cnt)
return 1;
xtry++;
attempt++;
sim_os_ms_sleep (50);
}
tmxr_debug_trace_line (line, "no status received\n");

View File

@ -66,10 +66,11 @@ typedef struct SERPORT *SERHANDLE;
#define TMXR_MODEM_RING_TIME 3 /* seconds to wait for DTR for incoming connections */
#define TMXR_DEFAULT_CONNECT_POLL_INTERVAL 1 /* seconds between connection polls */
#define TMXR_DBG_XMT 0x00200000 /* Debug Transmit Data */
#define TMXR_DBG_RCV 0x00400000 /* Debug Received Data */
#define TMXR_DBG_RET 0x00800000 /* Debug Returned Received Data */
#define TMXR_DBG_MDM 0x01000000 /* Debug Modem Signals */
#define TMXR_DBG_XMT 0x00100000 /* Debug Transmit Data */
#define TMXR_DBG_RCV 0x00200000 /* Debug Received Data */
#define TMXR_DBG_RET 0x00400000 /* Debug Returned Received Data */
#define TMXR_DBG_MDM 0x00800000 /* Debug Modem Signals */
#define TMXR_DBG_CFG 0x01000000 /* Debug Line Configuration Activities */
#define TMXR_DBG_CON 0x02000000 /* Debug Connection Activities */
#define TMXR_DBG_ASY 0x04000000 /* Debug Asynchronous Activities */
#define TMXR_DBG_TRC 0x08000000 /* Debug trace routine calls */
@ -140,6 +141,9 @@ struct tmln {
char *ipad; /* IP address */
SOCKET master; /* line specific master socket */
char *port; /* line specific listening port */
char *acl; /* Access control list (CIDR) to accept or reject connects from */
int32 acl_accepted_sessions; /* count of ACL accepted tcp connections */
int32 acl_rejected_sessions; /* count of ACL rejected tcp connections */
int32 sessions; /* count of tcp connections received */
uint32 cnms; /* conn time */
int32 tsta; /* Telnet state */
@ -217,6 +221,9 @@ struct tmxr {
TMLN *ldsc; /* line descriptors */
int32 *lnorder; /* line connection order */
DEVICE *dptr; /* multiplexer device */
char *acl; /* Access control list (CIDR) to accept or reject connects from */
int32 acl_accepted_sessions; /* count of ACL accepted tcp connections */
int32 acl_rejected_sessions; /* count of ACL rejected tcp connections */
UNIT *uptr; /* polling unit (connection) */
char logfiletmpl[FILENAME_MAX]; /* template logfile name */
int32 txcount; /* count of transmit bytes */
@ -318,7 +325,7 @@ const char *tmxr_send_line_name (const SEND *snd);
const char *tmxr_expect_line_name (const EXPECT *exp);
t_stat tmxr_startup (void);
t_stat tmxr_shutdown (void);
t_stat tmxr_sock_test (DEVICE *dptr);
t_stat tmxr_sock_test (DEVICE *dptr, const char *cptr);
t_stat tmxr_start_poll (void);
t_stat tmxr_stop_poll (void);
/* Framer support. These are a NOP if called on a non-framer line. */