sockaddr.c 3.63 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * Copyright (C) 1999  Internet Software Consortium.
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include <config.h>

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <isc/types.h>
#include <isc/assertions.h>
#include <isc/error.h>
#include <isc/sockaddr.h>

isc_boolean_t
isc_sockaddr_equal(isc_sockaddr_t *a, isc_sockaddr_t *b)
{
Bob Halley's avatar
Bob Halley committed
33
	REQUIRE(a != NULL && b != NULL);
Michael Graff's avatar
Michael Graff committed
34

Bob Halley's avatar
Bob Halley committed
35
	if (a->length != b->length)
Michael Graff's avatar
Michael Graff committed
36
37
		return (ISC_FALSE);

38
39
40
41
42
43
	/*
	 * We don't just memcmp because the sin_zero field isn't always
	 * zero.
	 */

	if (a->type.sa.sa_family != b->type.sa.sa_family)
Michael Graff's avatar
Michael Graff committed
44
		return (ISC_FALSE);
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
	switch (a->type.sa.sa_family) {
	case AF_INET:
		if (memcmp(&a->type.sin.sin_addr, &b->type.sin.sin_addr,
			   sizeof a->type.sin.sin_addr) != 0)
			return (ISC_FALSE);
		if (a->type.sin.sin_port != b->type.sin.sin_port)
			return (ISC_FALSE);
		break;
	case AF_INET6:
		if (memcmp(&a->type.sin6.sin6_addr, &b->type.sin6.sin6_addr,
			   sizeof a->type.sin6.sin6_addr) != 0)
			return (ISC_FALSE);
		if (a->type.sin6.sin6_port != b->type.sin6.sin6_port)
			return (ISC_FALSE);
		break;
	default:
		if (memcmp(&a->type, &b->type, a->length) != 0)
			return (ISC_FALSE);
	}
Michael Graff's avatar
Michael Graff committed
64

Bob Halley's avatar
Bob Halley committed
65
66
	return (ISC_TRUE);
}
Michael Graff's avatar
Michael Graff committed
67

Bob Halley's avatar
Bob Halley committed
68
69
70
71
72
73
74
75
76
77
unsigned int
isc_sockaddr_hash(isc_sockaddr_t *sockaddr, isc_boolean_t address_only) {
	unsigned int length;
	const unsigned char *s;
	unsigned int h = 0;
	unsigned int g;
	
	/*
	 * Provide a hash value for 'sockaddr'.
	 */
Michael Graff's avatar
Michael Graff committed
78

Bob Halley's avatar
Bob Halley committed
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
	REQUIRE(sockaddr != NULL);

	if (address_only) {
		switch (sockaddr->type.sa.sa_family) {
		case AF_INET:
			return (ntohl(sockaddr->type.sin.sin_addr.s_addr));
		case AF_INET6:
			s = (unsigned char *)&sockaddr->type.sin6.sin6_addr;
			length = sizeof sockaddr->type.sin6.sin6_addr;
			break;
		default:
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "unknown address family: %d\n",
					 (int)sockaddr->type.sa.sa_family);
			s = (unsigned char *)&sockaddr->type;
			length = sockaddr->length;
		}
	} else {
		s = (unsigned char *)&sockaddr->type;
		length = sockaddr->length;
Michael Graff's avatar
Michael Graff committed
99
	}
Bob Halley's avatar
Bob Halley committed
100
101
102
103
104
105
106
107
108

	while (length > 0) {
		h = ( h << 4 ) + *s;
		if ((g = ( h & 0xf0000000 )) != 0) {
			h = h ^ (g >> 24);
			h = h ^ g;
		}
		s++;
		length--;
Michael Graff's avatar
Michael Graff committed
109
110
	}

Bob Halley's avatar
Bob Halley committed
111
	return (h);
Michael Graff's avatar
Michael Graff committed
112
}
Bob Halley's avatar
Bob Halley committed
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

void
isc_sockaddr_fromin(isc_sockaddr_t *sockaddr, struct in_addr *ina,
		    unsigned int port)
{
	sockaddr->type.sin.sin_family = AF_INET;
#ifdef ISC_NET_HAVESALEN
	sockaddr->type.sin.sin_len = sizeof sockaddr->type.sin;
#endif
	sockaddr->type.sin.sin_addr = *ina;
	sockaddr->type.sin.sin_port = htons(port);
	sockaddr->length = sizeof sockaddr->type.sin;
	ISC_LINK_INIT(sockaddr, link);
}

void
isc_sockaddr_fromin6(isc_sockaddr_t *sockaddr, struct in6_addr *ina6,
		     unsigned int port)
{
	sockaddr->type.sin6.sin6_family = AF_INET6;
#ifdef ISC_NET_HAVESALEN
	sockaddr->type.sin6.sin6_len = sizeof sockaddr->type.sin6;
#endif
	sockaddr->type.sin6.sin6_addr = *ina6;
	sockaddr->type.sin6.sin6_port = htons(port);
	sockaddr->length = sizeof sockaddr->type.sin6;
	ISC_LINK_INIT(sockaddr, link);
}