GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/npppd/npppd/../common/net_utils.c Lines: 0 90 0.0 %
Date: 2017-11-13 Branches: 0 65 0.0 %

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