xref: /openbsd-src/usr.sbin/npppd/common/net_utils.c (revision 0fbf3537195de5c8bc34ec4e301ea41ad183a5e0)
1 /*-
2  * Copyright (c) 2009 Internet Initiative Japan Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 /* $Id: net_utils.c,v 1.1 2010/01/11 04:20:57 yasuoka Exp $ */
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <net/if.h>
31 #include <ifaddrs.h>
32 #include <netdb.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "net_utils.h"
37 
38 #ifdef NPPPD_USE_RTEV
39 #include "rtev.h"
40 #endif
41 
42 /** struct sockaddr ���顢�����ե�����̾��������ޤ� */
43 const char *
44 get_ifname_by_sockaddr(struct sockaddr *sa, char *ifname)
45 {
46 	struct ifaddrs *addr, *addr0;
47 	struct in_addr *in4a, *in4b;
48 	const char *ifname0 = NULL;
49 #ifdef INET6
50 	struct in6_addr *in6a, *in6b;
51 #endif
52 
53 	ifname0 = NULL;
54 	/* ��˥������������ʤ��ʤ��... */
55 	getifaddrs(&addr0);
56 	for (addr = addr0; ifname0 == NULL&& addr != NULL;
57 	    addr = addr->ifa_next) {
58 		if (addr->ifa_addr->sa_family != sa->sa_family ||
59 		    addr->ifa_addr->sa_len != sa->sa_len)
60 			continue;
61 		switch (addr->ifa_addr->sa_family) {
62 		default:
63 			continue;
64 		case AF_INET:
65 			in4a = &((struct sockaddr_in *)addr->ifa_addr)
66 			    ->sin_addr;
67 			in4b = &((struct sockaddr_in *)sa)->sin_addr;
68 			if (in4a->s_addr == in4b->s_addr) {
69 				strlcpy(ifname, addr->ifa_name, IF_NAMESIZE);
70 				ifname0 = ifname;
71 			}
72 			break;
73 #ifdef INET6
74 		case AF_INET6:
75 			in6a = &((struct sockaddr_in6 *)addr->ifa_addr)
76 			    ->sin6_addr;
77 			in6b = &((struct sockaddr_in6 *)sa)->sin6_addr;
78 			if (IN6_ARE_ADDR_EQUAL(in6a, in6b)) {
79 				strlcpy(ifname, addr->ifa_name, IF_NAMESIZE);
80 				ifname0 = ifname;
81 			}
82 			break;
83 #endif
84 		}
85 	}
86 	freeifaddrs(addr0);
87 
88 	return ifname0;
89 }
90 /**
91  * "192.168.160.1:1723/tcp" �� "[::1]:1723/tcp" �Ȥ���ʸ�����getaddrinfo(3)
92  * �ΰ����λ��ͤ�ʻ���Ƽ¹Ԥ��롣���ߤϡ�"/tcp" ����ʬ��̵�뤷�ޤ���
93  */
94 int
95 addrport_parse(const char *addrport, int proto, struct addrinfo **p_ai)
96 {
97 	char buf[256];
98 	char *servp, *nodep, *slash;
99 	struct addrinfo hints;
100 
101 	strlcpy(buf, addrport, sizeof(buf));
102 	if (buf[0] == '[' && (servp = strchr(buf, ']')) != NULL) {
103 		nodep = buf + 1;
104 		*servp++ = '\0';
105 		if (*servp != ':')
106 			servp = NULL;
107 	} else {
108 		nodep = buf;
109 		servp = strrchr(nodep, ':');
110 	}
111 	if (servp != NULL) {
112 		*servp = '\0';
113 		servp++;
114 		slash = strrchr(servp, '/');
115 		if (slash != NULL) {
116 			/*
117 			 * "/tcp" �ʤɤ�̵�뤹�롣
118 			 */
119 			*slash = '\0';
120 			slash++;
121 		}
122 	} else
123 		servp = NULL;
124 	memset(&hints, 0, sizeof(hints));
125 	hints.ai_flags = AI_NUMERICHOST;
126 	hints.ai_family = AF_UNSPEC;
127 	switch (proto) {
128 	case IPPROTO_TCP:
129 		hints.ai_socktype = SOCK_STREAM;
130 		break;
131 	case IPPROTO_UDP:
132 		hints.ai_socktype = SOCK_DGRAM;
133 		break;
134 	}
135 	hints.ai_protocol = proto;
136 
137 	return getaddrinfo(nodep, servp, &hints, p_ai);
138 }
139 
140 /**
141  * struct sockaddr ���顢 "192.168.160.1:1723" �� "[::1]:1723" �Ȥ���ʸ����
142  * ��������ޤ���
143  * @param	buf	ʸ������Ǽ����Хåե�
144  * @param	lbuf	ʸ������Ǽ����Хåե���Ĺ��
145  */
146 const char *
147 addrport_tostring(struct sockaddr *sa, socklen_t salen, char *buf, int lbuf)
148 {
149 	char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
150 
151 	if (getnameinfo(sa, salen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf),
152 	    NI_NUMERICHOST | NI_NUMERICSERV) != 0)
153 		return NULL;
154 
155 	switch (sa->sa_family) {
156 	case AF_INET6:
157 		strlcpy(buf, "[", lbuf);
158 		strlcat(buf, hbuf, lbuf);
159 		strlcat(buf, "]:", lbuf);
160 		strlcat(buf, sbuf, lbuf);
161 		break;
162 	case AF_INET:
163 		strlcpy(buf, hbuf, lbuf);
164 		strlcat(buf, ":", lbuf);
165 		strlcat(buf, sbuf, lbuf);
166 		break;
167 	default:
168 		return NULL;
169 	}
170 
171 	return buf;
172 }
173 
174 /** IPv4 �ͥåȥޥ�����ץ�ե��å���Ĺ���Ѵ����ޤ����ۥ��ȥХ��ȥ��������� */
175 int
176 netmask2prefixlen(uint32_t mask)
177 {
178     switch(mask) {
179     case 0x00000000:  return  0;
180     case 0x80000000:  return  1;
181     case 0xC0000000:  return  2;
182     case 0xE0000000:  return  3;
183     case 0xF0000000:  return  4;
184     case 0xF8000000:  return  5;
185     case 0xFC000000:  return  6;
186     case 0xFE000000:  return  7;
187     case 0xFF000000:  return  8;
188     case 0xFF800000:  return  9;
189     case 0xFFC00000:  return 10;
190     case 0xFFE00000:  return 11;
191     case 0xFFF00000:  return 12;
192     case 0xFFF80000:  return 13;
193     case 0xFFFC0000:  return 14;
194     case 0xFFFE0000:  return 15;
195     case 0xFFFF0000:  return 16;
196     case 0xFFFF8000:  return 17;
197     case 0xFFFFC000:  return 18;
198     case 0xFFFFE000:  return 19;
199     case 0xFFFFF000:  return 20;
200     case 0xFFFFF800:  return 21;
201     case 0xFFFFFC00:  return 22;
202     case 0xFFFFFE00:  return 23;
203     case 0xFFFFFF00:  return 24;
204     case 0xFFFFFF80:  return 25;
205     case 0xFFFFFFC0:  return 26;
206     case 0xFFFFFFE0:  return 27;
207     case 0xFFFFFFF0:  return 28;
208     case 0xFFFFFFF8:  return 29;
209     case 0xFFFFFFFC:  return 30;
210     case 0xFFFFFFFE:  return 31;
211     case 0xFFFFFFFF:  return 32;
212     }
213     return -1;
214 }
215