1 #include "syshdrs.h"
2 
3 #ifndef INADDR_ANY
4 #	define INADDR_ANY              ((unsigned long int) 0x00000000)
5 #endif
6 
7 #ifndef INADDR_NONE
8 #	define INADDR_NONE             ((unsigned long int) 0xffffffff)
9 #endif
10 
11 /* Linux libc 5.3.x has a bug that causes isalnum() to not work! */
12 #define ISALNUM(c) ( (((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z')) || (((c) >= '0') && ((c) <= '9')) )
13 
14 static unsigned int
ServiceNameToPortNumber(const char * const s)15 ServiceNameToPortNumber(const char *const s)
16 {
17 	char str[64];
18 	char *cp;
19 	struct servent *sp;
20 
21 	strncpy(str, s, sizeof(str) - 1);
22 	str[sizeof(str) - 1] = '\0';
23 	cp = str;
24 	if (isdigit(*cp)) {
25 		while (isdigit(*cp))
26 			cp++;
27 		*cp = '\0';
28 		return (atoi(str));
29 	}
30 	for (;; cp++) {
31 		if ((*cp == '\0')
32 			|| ((!ISALNUM(*cp)) && (*cp != '-') && (*cp != '_')))
33 				break;
34 	}
35 	*cp = '\0';
36 
37 	sp = getservbyname(str, "tcp");
38 	if (sp != NULL) {
39 		/* endservent(); */
40 		return ((unsigned int) ntohs((unsigned short) sp->s_port));
41 	}
42 	sp = getservbyname(str, "udp");
43 	if (sp != NULL) {
44 		/* endservent(); */
45 		return ((unsigned int) ntohs((unsigned short) sp->s_port));
46 	}
47 	return (0);	/* error */
48 }	/* ServiceNameToPortNumber */
49 
50 
51 
52 
53 int
AddrStrToAddr(const char * const s,struct sockaddr_in * const sa,const int defaultport)54 AddrStrToAddr(const char * const s, struct sockaddr_in * const sa, const int defaultport)
55 {
56 	char portstr[128];
57 	unsigned long ipnum;
58 	unsigned int port;
59 	struct hostent *hp;
60 	char *hostcp, *atsign, *colon, *cp, *p2;
61 
62 	memset(sa, 0, sizeof(struct sockaddr_in));
63 	strncpy(portstr, s, sizeof(portstr));
64 	portstr[sizeof(portstr) - 1] = '\0';
65 
66 	if ((colon = strchr(portstr, ':')) != NULL) {
67 		/* Does it look like a URL?  http://host ? */
68 		if ((colon[1] == '/') && (colon[2] == '/')) {
69 			*colon = '\0';
70 			port = 0;
71 			hostcp = colon + 3;
72 			for (cp = hostcp; *cp != '\0'; cp++) {
73 				if ((!ISALNUM(*cp)) && (*cp != '.')) {
74 					/* http://host:port */
75 					if ((*cp == ':') && (isdigit(cp[1]))) {
76 						*cp++ = '\0';
77 						p2 = cp;
78 						while (isdigit(*cp))
79 							cp++;
80 						*cp = '\0';
81 						port = atoi(p2);
82 					}
83 					*cp = '\0';
84 					break;
85 				}
86 			}
87 			if (port == 0)
88 				port = ServiceNameToPortNumber(portstr);
89 		} else {
90 			/* Look for host.name.domain:port */
91 			*colon = '\0';
92 			hostcp = portstr;
93 			port = (unsigned int) atoi(colon + 1);
94 		}
95 	} else if ((atsign = strchr(portstr, '@')) != NULL) {
96 		/* Look for port@host.name.domain */
97 		*atsign = '\0';
98 		hostcp = atsign + 1;
99 		port = (unsigned int) atoi(portstr);
100 	} else if (defaultport > 0) {
101 		/* Have just host.name.domain, use that w/ default port. */
102 		port = (unsigned int) defaultport;
103 		hostcp = portstr;
104 	} else {
105 		/* If defaultport <= 0, they must supply a port number
106 		 * in the host/port string.
107 		 */
108 		errno = EADDRNOTAVAIL;
109 		return (kAddrStrToAddrMiscErr);
110 	}
111 
112 	sa->sin_port = htons((short) port);
113 
114 	ipnum = inet_addr(hostcp);
115 	if (ipnum != INADDR_NONE) {
116 		sa->sin_family = AF_INET;
117 		sa->sin_addr.s_addr = ipnum;
118 	} else {
119 		errno = 0;
120 		hp = gethostbyname(hostcp);
121 		if (hp == NULL) {
122 			if (errno == 0)
123 				errno = ENOENT;
124 			return (kAddrStrToAddrBadHost);
125 		}
126 		sa->sin_family = hp->h_addrtype;
127 		memcpy(&sa->sin_addr.s_addr, hp->h_addr_list[0],
128 			(size_t) hp->h_length);
129 	}
130 	return (0);
131 }	/* AddrStrToAddr */
132 
133 
134 
135 char *
AddrToAddrStr(char * const dst,size_t dsize,struct sockaddr_in * const saddrp,int dns,const char * fmt)136 AddrToAddrStr(char *const dst, size_t dsize, struct sockaddr_in * const saddrp, int dns, const char *fmt)
137 {
138 	const char *addrNamePtr;
139 	struct hostent *hp;
140 	char str[128];
141 	char *dlim, *dp;
142 	const char *cp;
143 	struct servent *pp;
144 
145 	if (dns == 0) {
146 		addrNamePtr = inet_ntoa(saddrp->sin_addr);
147 	} else {
148 		hp = gethostbyaddr((char *) &saddrp->sin_addr, (int) sizeof(struct in_addr), AF_INET);
149 		if ((hp != NULL) && (hp->h_name != NULL) && (hp->h_name[0] != '\0')) {
150 			addrNamePtr = hp->h_name;
151 		} else {
152 			addrNamePtr = inet_ntoa(saddrp->sin_addr);
153 		}
154 	}
155 	if (fmt == NULL)
156 		fmt = "%h:%p";
157 	for (dp = dst, dlim = dp + dsize - 1; ; fmt++) {
158 		if (*fmt == '\0') {
159 			break;	/* done */
160 		} else if (*fmt == '%') {
161 			fmt++;
162 			if (*fmt == '%') {
163 				if (dp < dlim)
164 					*dp++ = '%';
165 			} else if (*fmt == 'p') {
166 				sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
167 				for (cp = str; *cp != '\0'; cp++)
168 					if (dp < dlim)
169 						*dp++ = *cp;
170 				*dp = '\0';
171 			} else if (*fmt == 'h') {
172 				if (addrNamePtr != NULL) {
173 					cp = addrNamePtr;
174 				} else {
175 					cp = "unknown";
176 				}
177 				for ( ; *cp != '\0'; cp++)
178 					if (dp < dlim)
179 						*dp++ = *cp;
180 				*dp = '\0';
181 			} else if (*fmt == 's') {
182 				pp = getservbyport((int) (saddrp->sin_port), "tcp");
183 				if (pp == NULL)
184 					pp = getservbyport((int) (saddrp->sin_port), "udp");
185 				if (pp == NULL) {
186 					sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
187 					cp = str;
188 				} else {
189 					cp = pp->s_name;
190 				}
191 				for ( ; *cp != '\0'; cp++)
192 					if (dp < dlim)
193 						*dp++ = *cp;
194 				/* endservent(); */
195 				*dp = '\0';
196 			} else if ((*fmt == 't') || (*fmt == 'u')) {
197 				pp = getservbyport((int) (saddrp->sin_port), (*fmt == 'u') ? "udp" : "tcp");
198 				if (pp == NULL) {
199 					sprintf(str, "%u", (unsigned int) ntohs(saddrp->sin_port));
200 					cp = str;
201 				} else {
202 					cp = pp->s_name;
203 				}
204 				for ( ; *cp != '\0'; cp++)
205 					if (dp < dlim)
206 						*dp++ = *cp;
207 				/* endservent(); */
208 				*dp = '\0';
209 			} else if (*fmt == '\0') {
210 				break;
211 			} else {
212 				if (dp < dlim)
213 					*dp++ = *fmt;
214 			}
215 		} else if (dp < dlim) {
216 			*dp++ = *fmt;
217 		}
218 	}
219 	*dp = '\0';
220 	return (dst);
221 }	/* AddrToAddrStr */
222