mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
222 lines
5.2 KiB
C
222 lines
5.2 KiB
C
|
#include "syshdrs.h"
|
||
|
|
||
|
#ifndef INADDR_ANY
|
||
|
# define INADDR_ANY ((unsigned long int) 0x00000000)
|
||
|
#endif
|
||
|
|
||
|
#ifndef INADDR_NONE
|
||
|
# define INADDR_NONE ((unsigned long int) 0xffffffff)
|
||
|
#endif
|
||
|
|
||
|
/* Linux libc 5.3.x has a bug that causes isalnum() to not work! */
|
||
|
#define ISALNUM(c) ( (((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z')) || (((c) >= '0') && ((c) <= '9')) )
|
||
|
|
||
|
static unsigned int
|
||
|
ServiceNameToPortNumber(const char *const s)
|
||
|
{
|
||
|
char str[64];
|
||
|
char *cp;
|
||
|
struct servent *sp;
|
||
|
|
||
|
strncpy(str, s, sizeof(str) - 1);
|
||
|
str[sizeof(str) - 1] = '\0';
|
||
|
cp = str;
|
||
|
if (isdigit(*cp)) {
|
||
|
while (isdigit(*cp))
|
||
|
cp++;
|
||
|
*cp = '\0';
|
||
|
return (atoi(str));
|
||
|
}
|
||
|
for (;; cp++) {
|
||
|
if ((*cp == '\0')
|
||
|
|| ((!ISALNUM(*cp)) && (*cp != '-') && (*cp != '_')))
|
||
|
break;
|
||
|
}
|
||
|
*cp = '\0';
|
||
|
|
||
|
sp = getservbyname(str, "tcp");
|
||
|
if (sp != NULL) {
|
||
|
/* endservent(); */
|
||
|
return ((unsigned int) ntohs((unsigned short) sp->s_port));
|
||
|
}
|
||
|
sp = getservbyname(str, "udp");
|
||
|
if (sp != NULL) {
|
||
|
/* endservent(); */
|
||
|
return ((unsigned int) ntohs((unsigned short) sp->s_port));
|
||
|
}
|
||
|
return (0); /* error */
|
||
|
} /* ServiceNameToPortNumber */
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
int
|
||
|
AddrStrToAddr(const char * const s, struct sockaddr_in * const sa, const int defaultport)
|
||
|
{
|
||
|
char portstr[128];
|
||
|
unsigned long ipnum;
|
||
|
unsigned int port;
|
||
|
struct hostent *hp;
|
||
|
char *hostcp, *atsign, *colon, *cp, *p2;
|
||
|
|
||
|
memset(sa, 0, sizeof(struct sockaddr_in));
|
||
|
strncpy(portstr, s, sizeof(portstr));
|
||
|
portstr[sizeof(portstr) - 1] = '\0';
|
||
|
|
||
|
if ((colon = strchr(portstr, ':')) != NULL) {
|
||
|
/* Does it look like a URL? http://host ? */
|
||
|
if ((colon[1] == '/') && (colon[2] == '/')) {
|
||
|
*colon = '\0';
|
||
|
port = 0;
|
||
|
hostcp = colon + 3;
|
||
|
for (cp = hostcp; *cp != '\0'; cp++) {
|
||
|
if ((!ISALNUM(*cp)) && (*cp != '.')) {
|
||
|
/* http://host:port */
|
||
|
if ((*cp == ':') && (isdigit(cp[1]))) {
|
||
|
*cp++ = '\0';
|
||
|
p2 = cp;
|
||
|
while (isdigit(*cp))
|
||
|
cp++;
|
||
|
*cp = '\0';
|
||
|
port = atoi(p2);
|
||
|
}
|
||
|
*cp = '\0';
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (port == 0)
|
||
|
port = ServiceNameToPortNumber(portstr);
|
||
|
} else {
|
||
|
/* Look for host.name.domain:port */
|
||
|
*colon = '\0';
|
||
|
hostcp = portstr;
|
||
|
port = (unsigned int) atoi(colon + 1);
|
||
|
}
|
||
|
} else if ((atsign = strchr(portstr, '@')) != NULL) {
|
||
|
/* Look for port@host.name.domain */
|
||
|
*atsign = '\0';
|
||
|
hostcp = atsign + 1;
|
||
|
port = (unsigned int) atoi(portstr);
|
||
|
} else if (defaultport > 0) {
|
||
|
/* Have just host.name.domain, use that w/ default port. */
|
||
|
port = (unsigned int) defaultport;
|
||
|
hostcp = portstr;
|
||
|
} else {
|
||
|
/* If defaultport <= 0, they must supply a port number
|
||
|
* in the host/port string.
|
||
|
*/
|
||
|
errno = EADDRNOTAVAIL;
|
||
|
return (kAddrStrToAddrMiscErr);
|
||
|
}
|
||
|
|
||
|
sa->sin_port = htons((short) port);
|
||
|
|
||
|
ipnum = inet_addr(hostcp);
|
||
|
if (ipnum != INADDR_NONE) {
|
||
|
sa->sin_family = AF_INET;
|
||
|
sa->sin_addr.s_addr = ipnum;
|
||
|
} else {
|
||
|
errno = 0;
|
||
|
hp = gethostbyname(hostcp);
|
||
|
if (hp == NULL) {
|
||
|
if (errno == 0)
|
||
|
errno = ENOENT;
|
||
|
return (kAddrStrToAddrBadHost);
|
||
|
}
|
||
|
sa->sin_family = hp->h_addrtype;
|
||
|
memcpy(&sa->sin_addr.s_addr, hp->h_addr_list[0],
|
||
|
(size_t) hp->h_length);
|
||
|
}
|
||
|
return (0);
|
||
|
} /* AddrStrToAddr */
|
||
|
|
||
|
|
||
|
|
||
|
char *
|
||
|
AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr_in * const saddrp, int dns, const char *fmt)
|
||
|
{
|
||
|
const char *addrNamePtr;
|
||
|
struct hostent *hp;
|
||
|
char str[128];
|
||
|
char *dlim, *dp;
|
||
|
const char *cp;
|
||
|
struct servent *pp;
|
||
|
|
||
|
if (dns == 0) {
|
||
|
addrNamePtr = inet_ntoa(saddrp->sin_addr);
|
||
|
} else {
|
||
|
hp = gethostbyaddr((char *) &saddrp->sin_addr, (int) sizeof(struct in_addr), AF_INET);
|
||
|
if ((hp != NULL) && (hp->h_name != NULL) && (hp->h_name[0] != '\0')) {
|
||
|
addrNamePtr = hp->h_name;
|
||
|
} else {
|
||
|
addrNamePtr = inet_ntoa(saddrp->sin_addr);
|
||
|
}
|
||
|
}
|
||
|
if (fmt == NULL)
|
||
|
fmt = "%h:%p";
|
||
|
for (dp = dst, dlim = dp + dsize - 1; ; fmt++) {
|
||
|
if (*fmt == '\0') {
|
||
|
break; /* done */
|
||
|
} else if (*fmt == '%') {
|
||
|
fmt++;
|
||
|
if (*fmt == '%') {
|
||
|
if (dp < dlim)
|
||
|
*dp++ = '%';
|
||
|
} else if (*fmt == 'p') {
|
||
|
sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
|
||
|
for (cp = str; *cp != '\0'; cp++)
|
||
|
if (dp < dlim)
|
||
|
*dp++ = *cp;
|
||
|
*dp = '\0';
|
||
|
} else if (*fmt == 'h') {
|
||
|
if (addrNamePtr != NULL) {
|
||
|
cp = addrNamePtr;
|
||
|
} else {
|
||
|
cp = "unknown";
|
||
|
}
|
||
|
for ( ; *cp != '\0'; cp++)
|
||
|
if (dp < dlim)
|
||
|
*dp++ = *cp;
|
||
|
*dp = '\0';
|
||
|
} else if (*fmt == 's') {
|
||
|
pp = getservbyport((int) (saddrp->sin_port), "tcp");
|
||
|
if (pp == NULL)
|
||
|
pp = getservbyport((int) (saddrp->sin_port), "udp");
|
||
|
if (pp == NULL) {
|
||
|
sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
|
||
|
cp = str;
|
||
|
} else {
|
||
|
cp = pp->s_name;
|
||
|
}
|
||
|
for ( ; *cp != '\0'; cp++)
|
||
|
if (dp < dlim)
|
||
|
*dp++ = *cp;
|
||
|
/* endservent(); */
|
||
|
*dp = '\0';
|
||
|
} else if ((*fmt == 't') || (*fmt == 'u')) {
|
||
|
pp = getservbyport((int) (saddrp->sin_port), (*fmt == 'u') ? "udp" : "tcp");
|
||
|
if (pp == NULL) {
|
||
|
sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
|
||
|
cp = str;
|
||
|
} else {
|
||
|
cp = pp->s_name;
|
||
|
}
|
||
|
for ( ; *cp != '\0'; cp++)
|
||
|
if (dp < dlim)
|
||
|
*dp++ = *cp;
|
||
|
/* endservent(); */
|
||
|
*dp = '\0';
|
||
|
} else if (*fmt == '\0') {
|
||
|
break;
|
||
|
} else {
|
||
|
if (dp < dlim)
|
||
|
*dp++ = *fmt;
|
||
|
}
|
||
|
} else if (dp < dlim) {
|
||
|
*dp++ = *fmt;
|
||
|
}
|
||
|
}
|
||
|
*dp = '\0';
|
||
|
return (dst);
|
||
|
} /* AddrToAddrStr */
|