2 * copyright (c) 2011 Emil Mikulic.
4 * addr.c: compound IPv4/IPv6 address
6 * You may use, modify and redistribute this file under the terms of the
7 * GNU General Public License version 2. (see COPYING.GPL)
12 #include <arpa/inet.h> /* for inet_ntop */
14 #include <string.h> /* for memcmp */
15 #include <netdb.h> /* for getaddrinfo */
17 int addr_equal(const struct addr
* const a
, const struct addr
* const b
)
19 if (a
->family
!= b
->family
)
21 if (a
->family
== IPv4
)
22 return (a
->ip
.v4
== b
->ip
.v4
);
24 assert(a
->family
== IPv6
);
25 return (memcmp(&(a
->ip
.v6
), &(b
->ip
.v6
), sizeof(a
->ip
.v6
)) == 0);
29 static char _addrstrbuf
[INET6_ADDRSTRLEN
];
30 const char *addr_to_str(const struct addr
* const a
)
32 if (a
->family
== IPv4
) {
35 return (inet_ntoa(in
));
37 assert(a
->family
== IPv6
);
38 inet_ntop(AF_INET6
, &(a
->ip
.v6
), _addrstrbuf
, sizeof(_addrstrbuf
));
43 int str_to_addr(const char *s
, struct addr
*a
)
45 struct addrinfo hints
, *ai
;
48 memset(&hints
, 0, sizeof(hints
));
49 hints
.ai_family
= AF_UNSPEC
;
50 hints
.ai_flags
= AI_NUMERICHOST
;
52 if ((ret
= getaddrinfo(s
, NULL
, &hints
, &ai
)) != 0)
55 if (ai
->ai_family
== AF_INET
) {
57 a
->ip
.v4
= ((const struct sockaddr_in
*)ai
->ai_addr
)->sin_addr
.s_addr
;
58 } else if (ai
->ai_family
== AF_INET6
) {
61 ((struct sockaddr_in6
*)ai
->ai_addr
)->sin6_addr
.s6_addr
,
71 void addr_mask(struct addr
*a
, const struct addr
* const mask
)
73 assert(a
->family
== mask
->family
);
74 if (a
->family
== IPv4
)
75 a
->ip
.v4
&= mask
->ip
.v4
;
79 assert(a
->family
== IPv6
);
80 for (i
=0; i
<sizeof(a
->ip
.v6
.s6_addr
); i
++)
81 a
->ip
.v6
.s6_addr
[i
] &= mask
->ip
.v6
.s6_addr
[i
];
85 int addr_inside(const struct addr
* const a
,
86 const struct addr
* const net
, const struct addr
* const mask
)
90 assert(a
->family
== net
->family
);
91 assert(a
->family
== mask
->family
);
94 addr_mask(&masked
, mask
);
95 return (addr_equal(&masked
, net
));
98 /* vim:set ts=3 sw=3 tw=78 et: */