xref: /openbsd/usr.sbin/radiusd/util.c (revision 515e489c)
1*515e489cSderaadt /*	$OpenBSD: util.c,v 1.3 2019/07/03 03:24:03 deraadt Exp $	*/
2a7ca44b8Syasuoka 
3a7ca44b8Syasuoka /*
4a7ca44b8Syasuoka  * Copyright (c) 2013 Internet Initiative Japan Inc.
5a7ca44b8Syasuoka  *
6a7ca44b8Syasuoka  * Permission to use, copy, modify, and distribute this software for any
7a7ca44b8Syasuoka  * purpose with or without fee is hereby granted, provided that the above
8a7ca44b8Syasuoka  * copyright notice and this permission notice appear in all copies.
9a7ca44b8Syasuoka  *
10a7ca44b8Syasuoka  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a7ca44b8Syasuoka  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a7ca44b8Syasuoka  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a7ca44b8Syasuoka  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a7ca44b8Syasuoka  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a7ca44b8Syasuoka  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a7ca44b8Syasuoka  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a7ca44b8Syasuoka  */
18a7ca44b8Syasuoka #include <sys/types.h>
19a7ca44b8Syasuoka #include <sys/socket.h>
20a7ca44b8Syasuoka #include <netinet/in.h>
21a7ca44b8Syasuoka 
22a7ca44b8Syasuoka #include <netdb.h>
23a7ca44b8Syasuoka #include <string.h>
24798f02aeSyasuoka #include <stdio.h>
25a7ca44b8Syasuoka 
26a7ca44b8Syasuoka #include "util.h"
27a7ca44b8Syasuoka 
28a7ca44b8Syasuoka /*
29a7ca44b8Syasuoka  * Convert argument like "192.168.160.1:1723/tcp" or "[::1]:1723/tcp" to
30a7ca44b8Syasuoka  * match getaddrinfo(3)'s specification and pass them to getaddrinfo(3).
31a7ca44b8Syasuoka  */
32a7ca44b8Syasuoka int
addrport_parse(const char * addrport,int proto,struct addrinfo ** p_ai)33a7ca44b8Syasuoka addrport_parse(const char *addrport, int proto, struct addrinfo **p_ai)
34a7ca44b8Syasuoka {
35a7ca44b8Syasuoka 	char		*servp, *nodep, *slash, buf[256];
36a7ca44b8Syasuoka 	struct addrinfo	 hints;
37a7ca44b8Syasuoka 
38a7ca44b8Syasuoka 	strlcpy(buf, addrport, sizeof(buf));
39a7ca44b8Syasuoka 	if (buf[0] == '[' && (servp = strchr(buf, ']')) != NULL) {
40a7ca44b8Syasuoka 		nodep = buf + 1;
41a7ca44b8Syasuoka 		*servp++ = '\0';
42a7ca44b8Syasuoka 		if (*servp != ':')
43a7ca44b8Syasuoka 			servp = NULL;
44a7ca44b8Syasuoka 	} else {
45a7ca44b8Syasuoka 		nodep = buf;
46a7ca44b8Syasuoka 		servp = strrchr(nodep, ':');
47a7ca44b8Syasuoka 	}
48a7ca44b8Syasuoka 	if (servp != NULL) {
49a7ca44b8Syasuoka 		*servp = '\0';
50a7ca44b8Syasuoka 		servp++;
51a7ca44b8Syasuoka 		slash = strrchr(servp, '/');
52a7ca44b8Syasuoka 		if (slash != NULL) {
53a7ca44b8Syasuoka 			/*
54a7ca44b8Syasuoka 			 * Ignore like "/tcp"
55a7ca44b8Syasuoka 			 */
56a7ca44b8Syasuoka 			*slash = '\0';
57a7ca44b8Syasuoka 			slash++;
58a7ca44b8Syasuoka 		}
59a7ca44b8Syasuoka 	} else
60a7ca44b8Syasuoka 		servp = NULL;
61a7ca44b8Syasuoka 	memset(&hints, 0, sizeof(hints));
62a7ca44b8Syasuoka 	hints.ai_flags = AI_NUMERICHOST;
63a7ca44b8Syasuoka 	hints.ai_family = AF_UNSPEC;
64a7ca44b8Syasuoka 	switch (proto) {
65a7ca44b8Syasuoka 	case IPPROTO_TCP:
66a7ca44b8Syasuoka 		hints.ai_socktype = SOCK_STREAM;
67a7ca44b8Syasuoka 		break;
68a7ca44b8Syasuoka 	case IPPROTO_UDP:
69a7ca44b8Syasuoka 		hints.ai_socktype = SOCK_DGRAM;
70a7ca44b8Syasuoka 		break;
71a7ca44b8Syasuoka 	}
72a7ca44b8Syasuoka 	hints.ai_protocol = proto;
73a7ca44b8Syasuoka 
74a7ca44b8Syasuoka 	return (getaddrinfo(nodep, servp, &hints, p_ai));
75a7ca44b8Syasuoka }
76a7ca44b8Syasuoka 
77a7ca44b8Syasuoka /*
78a7ca44b8Syasuoka  * Make a string like "192.168.160.1:1723" or "[::1]:1723" from a struct
79a7ca44b8Syasuoka  * sockaddr
80a7ca44b8Syasuoka  */
81a7ca44b8Syasuoka const char *
addrport_tostring(struct sockaddr * sa,socklen_t salen,char * buf,size_t lbuf)82798f02aeSyasuoka addrport_tostring(struct sockaddr *sa, socklen_t salen, char *buf, size_t lbuf)
83a7ca44b8Syasuoka {
84a7ca44b8Syasuoka 	char	 hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
85798f02aeSyasuoka 	int	 ret;
86a7ca44b8Syasuoka 
87a7ca44b8Syasuoka 	if (getnameinfo(sa, salen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
88a7ca44b8Syasuoka 	    NI_NUMERICHOST | NI_NUMERICSERV) != 0)
89a7ca44b8Syasuoka 		return (NULL);
90a7ca44b8Syasuoka 
91a7ca44b8Syasuoka 	switch (sa->sa_family) {
92a7ca44b8Syasuoka 	case AF_INET6:
93798f02aeSyasuoka 		ret = snprintf(buf, lbuf, "[%s]:%s", hbuf, sbuf);
94a7ca44b8Syasuoka 		break;
95a7ca44b8Syasuoka 
96a7ca44b8Syasuoka 	case AF_INET:
97798f02aeSyasuoka 		ret = snprintf(buf, lbuf, "%s:%s", hbuf, sbuf);
98a7ca44b8Syasuoka 		break;
99a7ca44b8Syasuoka 
100a7ca44b8Syasuoka 	default:
101798f02aeSyasuoka 		return "error";
102a7ca44b8Syasuoka 	}
103a7ca44b8Syasuoka 
104*515e489cSderaadt 	if (ret < 0 || ret >= (int)lbuf)
105798f02aeSyasuoka 		return "(error)";
106a7ca44b8Syasuoka 	return (buf);
107a7ca44b8Syasuoka }
108