diff --git a/AltairZ80/altairz80_net.c b/AltairZ80/altairz80_net.c index 1a815486..f6d71ffe 100644 --- a/AltairZ80/altairz80_net.c +++ b/AltairZ80/altairz80_net.c @@ -154,7 +154,7 @@ static t_stat net_attach(UNIT *uptr, char *cptr) { char host[CBUFSIZE], port[CBUFSIZE]; t_stat r; - r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), "3000"); + r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), "3000", NULL); if (r != SCPE_OK) return SCPE_ARG; net_reset(&net_dev); diff --git a/HP2100/hp2100_ipl.c b/HP2100/hp2100_ipl.c index 6622e258..5a5c8cad 100644 --- a/HP2100/hp2100_ipl.c +++ b/HP2100/hp2100_ipl.c @@ -581,7 +581,7 @@ if (oldf & UNIT_ATT) ipl_detach (uptr); if ((sim_switches & SWMASK ('C')) || ((sim_switches & SIM_SW_REST) && (oldf & UNIT_ACTV))) { - r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), NULL); + r = sim_parse_addr (cptr, host, sizeof(host), "localhost", port, sizeof(port), NULL, NULL); if ((r != SCPE_OK) || (port[0] == '\0')) return SCPE_ARG; sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port); @@ -597,7 +597,7 @@ if ((sim_switches & SWMASK ('C')) || uptr->DSOCKET = newsock; } else { - r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL); + r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL); if (r != SCPE_OK) return SCPE_ARG; sprintf(hostport, "%s%s%s%s%s", strchr(host, ':') ? "[" : "", host, strchr(host, ':') ? "]" : "", host[0] ? ":" : "", port); diff --git a/Ibm1130/ibm1130_sca.c b/Ibm1130/ibm1130_sca.c index 60e850a6..8310ac40 100644 --- a/Ibm1130/ibm1130_sca.c +++ b/Ibm1130/ibm1130_sca.c @@ -462,7 +462,7 @@ static t_stat sca_attach (UNIT *uptr, char *cptr) detach_unit(&sca_unit); if (do_listen) { /* if listen mode, string specifies port number (only; otherwise it's a dummy argument) */ - r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT); + r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT, NULL); if (r != SCPE_OK) return r; if ((0 == strcmp(port, cptr)) && (0 == strcmp(port, "dummy"))) @@ -493,7 +493,7 @@ static t_stat sca_attach (UNIT *uptr, char *cptr) if (! *cptr) return SCPE_2FARG; - r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT); + r = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), SCA_DEFAULT_PORT, NULL); if (r != SCPE_OK) return r; if ((0 == strcmp(cptr, port)) && (0 == strcmp(host, ""))) { diff --git a/PDP11/pdp11_dmc.c b/PDP11/pdp11_dmc.c index 27edbf6b..8e809147 100644 --- a/PDP11/pdp11_dmc.c +++ b/PDP11/pdp11_dmc.c @@ -565,7 +565,7 @@ t_stat dmc_setpeer (UNIT* uptr, int32 val, char* cptr, void* desc) if (!cptr) return SCPE_IERR; if (uptr->flags & UNIT_ATT) return SCPE_ALATT; - status = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL); + status = sim_parse_addr (cptr, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL); if (status != SCPE_OK) return status; if (host[0] == '\0') @@ -1588,8 +1588,7 @@ int dmc_get_receive_socket(CTLR *controller, int forRead) { char host[sizeof(controller->line->transmit_host)]; - sim_parse_addr (controller->line->transmit_host, host, sizeof(host), NULL, NULL, 0, NULL); - if (strcmp(ipaddr, host)) + if (sim_parse_addr (controller->line->transmit_host, host, sizeof(host), NULL, NULL, 0, NULL, ipaddr)) { sim_debug(DBG_WRN, controller->device, "Received connection from unexpected source IP %s. Closing the connection.\n", ipaddr); dmc_close_receive(controller, "Unathorized connection", ipaddr); diff --git a/sim_console.c b/sim_console.c index 18173aa6..649d4e2e 100644 --- a/sim_console.c +++ b/sim_console.c @@ -498,7 +498,7 @@ while (*cptr != 0) { /* do all mods */ return r; } else { - r = sim_parse_addr (gbuf, NULL, 0, NULL, NULL, 0, NULL); + r = sim_parse_addr (gbuf, NULL, 0, NULL, NULL, 0, NULL, NULL); if (r == SCPE_OK) { if (sim_con_tmxr.master) /* already open? */ sim_set_notelnet (0, NULL); /* close first */ diff --git a/sim_sock.c b/sim_sock.c index fab7f64d..9c5e11bc 100644 --- a/sim_sock.c +++ b/sim_sock.c @@ -75,95 +75,6 @@ extern FILE *sim_log; sim_msg_sock send message to socket */ -/* OS independent routines - - sim_parse_addr parse a hostname/ipaddress from port and apply defaults -*/ - -/* 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) - - Inputs: - cptr = pointer to input string - default_host - = optional pointer to default host if none specified - host_len = length of host buffer - default_port - = optional pointer to default host if none specified - port_len = length of port buffer - 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 - result = status -*/ - -t_stat 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) -{ -char gbuf[CBUFSIZE]; -char *hostp, *portp; -char *endc; -unsigned long portval; - -if ((cptr == NULL) || (*cptr == 0)) - return SCPE_ARG; -if ((host != NULL) && (host_len != 0)) - memset (host, 0, host_len); -if ((port != NULL) && (port_len != 0)) - memset (port, 0, port_len); -strncpy (gbuf, cptr, CBUFSIZE); -hostp = gbuf; /* default addr */ -portp = NULL; -if ((portp = strrchr (gbuf, ':')) && /* x:y? split */ - (NULL == strchr (portp, ']'))) { - *portp++ = 0; - if (*portp == '\0') - portp = (char *)default_port; - } -else - if (default_port) - portp = (char *)default_port; - else { - portp = gbuf; - hostp = NULL; - } -if (portp != NULL) { - portval = strtoul(portp, &endc, 10); - if ((*endc == '\0') && ((portval == 0) || (portval > 65535))) - return SCPE_ARG; /* value too big */ - if (*endc != '\0') { - struct servent *se = getservbyname(portp, "tcp"); - - if (se == NULL) - return SCPE_ARG; /* invalid service name */ - } - } -if (port) /* port wanted? */ - if (portp != NULL) { - if (strlen(portp) >= port_len) - return SCPE_ARG; /* no room */ - else - strcpy (port, portp); - } -if (hostp != NULL) { - if (']' == hostp[strlen(hostp)-1]) { - if ('[' != hostp[0]) - return SCPE_ARG; /* invalid domain literal */ - strcpy(hostp, hostp+1); /* remove brackets from domain literal host */ - hostp[strlen(hostp)-1] = '\0'; - } - } -if (host) /* host wanted? */ - if (hostp != NULL) - if (strlen(hostp) >= host_len) - return SCPE_ARG; /* no room */ - else - strcpy (host, hostp); -return SCPE_OK; -} - /* First, all the non-implemented versions */ #if defined (__OS2__) && !defined (__EMX__) @@ -525,6 +436,128 @@ int load_ws2(void) { } #endif +/* OS independent routines + + sim_parse_addr parse a hostname/ipaddress from port and apply defaults and + optionally validate an address match +*/ + +/* 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) + + Inputs: + cptr = pointer to input string + default_host + = optional pointer to default host if none specified + host_len = length of host buffer + default_port + = optional pointer to default host if none specified + port_len = length of port buffer + 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. + 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 + result = status (SCPE_OK on complete success or SCPE_ARG if + parsing can't happen due to bad syntax, a value is + out of range, a result can't fit into a result buffer, + a service name doesn't exist, or a validation name + doesn't match the parsed host) +*/ + +t_stat 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]; +char *hostp, *portp; +char *endc; +unsigned long portval; + +if ((cptr == NULL) || (*cptr == 0)) + return SCPE_ARG; +if ((host != NULL) && (host_len != 0)) + memset (host, 0, host_len); +if ((port != NULL) && (port_len != 0)) + memset (port, 0, port_len); +strncpy (gbuf, cptr, CBUFSIZE); +hostp = gbuf; /* default addr */ +portp = NULL; +if ((portp = strrchr (gbuf, ':')) && /* x:y? split */ + (NULL == strchr (portp, ']'))) { + *portp++ = 0; + if (*portp == '\0') + portp = (char *)default_port; + } +else + if (default_port) + portp = (char *)default_port; + else { + portp = gbuf; + hostp = NULL; + } +if (portp != NULL) { + portval = strtoul(portp, &endc, 10); + if ((*endc == '\0') && ((portval == 0) || (portval > 65535))) + return SCPE_ARG; /* numeric value too big */ + if (*endc != '\0') { + struct servent *se = getservbyname(portp, "tcp"); + + if (se == NULL) + return SCPE_ARG; /* invalid service name */ + } + } +if (port) /* port wanted? */ + if (portp != NULL) { + if (strlen(portp) >= port_len) + return SCPE_ARG; /* no room */ + else + strcpy (port, portp); + } +if (hostp != NULL) { + if (']' == hostp[strlen(hostp)-1]) { + if ('[' != hostp[0]) + return SCPE_ARG; /* invalid domain literal */ + strcpy(hostp, hostp+1); /* remove brackets from domain literal host */ + hostp[strlen(hostp)-1] = '\0'; + } + } +if (host) /* host wanted? */ + if (hostp != NULL) + if (strlen(hostp) >= host_len) + return SCPE_ARG; /* no room */ + else + strcpy (host, hostp); +if (validate_addr) { + struct addrinfo *ai_host, *ai_validate, *ai; + t_stat status; + + if (hostp == NULL) + return SCPE_ARG; + if (p_getaddrinfo(hostp, NULL, NULL, &ai_host)) + return SCPE_ARG; + if (p_getaddrinfo(validate_addr, NULL, NULL, &ai_validate)) { + p_freeaddrinfo (ai_host); + return SCPE_ARG; + } + status = SCPE_ARG; + for (ai = ai_host; ai != NULL; ai = ai->ai_next) { + if ((ai->ai_addrlen == ai_validate->ai_addrlen) && + (ai->ai_family == ai_validate->ai_family) && + (0 == memcmp (ai->ai_addr, ai_validate->ai_addr, ai->ai_addrlen))) { + status = SCPE_OK; + break; + } + } + p_freeaddrinfo (ai_host); + p_freeaddrinfo (ai_validate); + return status; + } +return SCPE_OK; +} + void sim_init_sock (void) { #if defined (_WIN32) @@ -624,7 +657,7 @@ t_stat r; struct addrinfo hints; struct addrinfo *result = NULL; -r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL); +r = sim_parse_addr (hostport, host, sizeof(host), NULL, port, sizeof(port), NULL, NULL); if (parse_status) *parse_status = r; if (r != SCPE_OK) @@ -671,7 +704,7 @@ t_stat r; struct addrinfo hints; struct addrinfo *result = NULL; -r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port); +r = sim_parse_addr (hostport, host, sizeof(host), default_host, port, sizeof(port), default_port, NULL); if (r != SCPE_OK) return newsock; diff --git a/sim_sock.h b/sim_sock.h index c4b8e25e..039ed019 100644 --- a/sim_sock.h +++ b/sim_sock.h @@ -83,7 +83,7 @@ #endif #endif -t_stat 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); +t_stat 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); SOCKET sim_master_sock (const char *hostport, t_stat *parse_status); SOCKET sim_connect_sock (const char *hostport, const char *default_host, const char *default_port); SOCKET sim_accept_conn (SOCKET master, char **connectaddr); diff --git a/sim_tmxr.c b/sim_tmxr.c index 97298f95..6909dc31 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -791,8 +791,7 @@ for (i = 0; i < mp->lines; i++) { /* check each line in se if (lp->destination) { /* Virtual Null Modem Cable? */ char host[CBUFSIZE]; - sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL); - if (strcmp(address, host)) { + if (sim_parse_addr (lp->destination, host, sizeof(host), NULL, NULL, 0, NULL, address)) { tmxr_msg (newsock, "Rejecting connection from unexpected source\r\n"); sprintf (msg, "tmxr_poll_conn() - Rejecting line connection from: %s, Expected: %s", address, host); tmxr_debug_trace_line (lp, msg); @@ -1459,7 +1458,7 @@ while (*tptr) { continue; } cptr = get_glyph (gbuf, port, ';'); - if (SCPE_OK != sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL)) + if (SCPE_OK != sim_parse_addr (port, NULL, 0, NULL, NULL, 0, NULL, NULL)) return SCPE_ARG; if (cptr) get_glyph (cptr, cptr, 0); /* upcase this string */