3 * - address-family specific code
6 * This file is part of adns, which is
7 * Copyright (C) 1997-2000,2003,2006 Ian Jackson
8 * Copyright (C) 1999-2000,2003,2006 Tony Finch
9 * Copyright (C) 1991 Massachusetts Institute of Technology
10 * (See the file INSTALL for full details.)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
44 #define SIN(sa) ((struct sockaddr_in *)(sa))
45 #define CSIN(sa) ((const struct sockaddr_in *)(sa))
47 static const void *inet_sockaddr_to_inaddr(const struct sockaddr
*sa
)
48 { return &CSIN(sa
)->sin_addr
; }
50 static int inet_sockaddr_equalp(const struct sockaddr
*sa
,
51 const struct sockaddr
*sb
)
53 const struct sockaddr_in
*sina
= CSIN(sa
), *sinb
= CSIN(sb
);
54 return (sina
->sin_addr
.s_addr
== sinb
->sin_addr
.s_addr
&&
55 sina
->sin_port
== sinb
->sin_port
);
58 static void inet_prefix_mask(int len
, union gen_addr
*mask
)
59 { mask
->v4
.s_addr
= htonl(!len ?
0 : 0xffffffff << (32 - len
)); }
61 static int inet_guess_len(const union gen_addr
*addr
)
63 unsigned a
= (ntohl(addr
->v4
.s_addr
) >> 24) & 0xff;
65 if (a
< 128) return 8;
66 else if (a
< 192) return 16;
67 else if (a
< 224) return 24;
71 static int inet_matchp(const union gen_addr
*addr
,
72 const union gen_addr
*base
,
73 const union gen_addr
*mask
)
74 { return (addr
->v4
.s_addr
& mask
->v4
.s_addr
) == base
->v4
.s_addr
; }
76 static int inet_rev_parsecomp(const char *p
, size_t n
)
82 if ('0' <= *p
&& *p
<= '9') i
= 10*i
+ *p
++ - '0';
88 static void inet_rev_mkaddr(union gen_addr
*addr
, const byte
*ipv
)
90 addr
->v4
.s_addr
= htonl((ipv
[3]<<24) | (ipv
[2]<<16) |
91 (ipv
[1]<<8) | (ipv
[0]));
94 static char *inet_rev_mkname(const struct sockaddr
*sa
, char *buf
)
96 unsigned long a
= ntohl(CSIN(sa
)->sin_addr
.s_addr
);
99 for (i
= 0; i
< 4; i
++) {
101 buf
+= sprintf(buf
, "%d", (int)(a
& 0xff));
107 const afinfo adns__inet_afinfo
= {
108 AF_INET
, 32, '.', 4, 3, adns_r_a
,
109 inet_sockaddr_to_inaddr
, inet_sockaddr_equalp
,
110 inet_prefix_mask
, inet_guess_len
, inet_matchp
,
111 inet_rev_parsecomp
, inet_rev_mkaddr
, inet_rev_mkname
118 #define SIN6(sa) ((struct sockaddr_in6 *)(sa))
119 #define CSIN6(sa) ((const struct sockaddr_in6 *)(sa))
121 static const void *inet6_sockaddr_to_inaddr(const struct sockaddr
*sa
)
122 { return &CSIN6(sa
)->sin6_addr
; }
124 static int inet6_sockaddr_equalp(const struct sockaddr
*sa
,
125 const struct sockaddr
*sb
)
127 const struct sockaddr_in6
*sin6a
= CSIN6(sa
), *sin6b
= CSIN6(sb
);
128 return (memcmp(sin6a
->sin6_addr
.s6_addr
,
129 sin6b
->sin6_addr
.s6_addr
,
130 sizeof(sin6a
->sin6_addr
.s6_addr
)) == 0 &&
131 sin6a
->sin6_port
== sin6b
->sin6_port
&&
132 sin6a
->sin6_scope_id
== sin6b
->sin6_scope_id
);
135 static void inet6_prefix_mask(int len
, union gen_addr
*mask
)
137 int i
= len
/8, j
= len
%8;
138 unsigned char *m
= mask
->v6
.s6_addr
;
142 if (j
) m
[i
++] = (0xff << (8-j
)) & 0xff;
143 memset(m
+ i
, 0, 16-i
);
146 static int inet6_guess_len(const union gen_addr
*addr
)
149 static int inet6_matchp(const union gen_addr
*addr
,
150 const union gen_addr
*base
,
151 const union gen_addr
*mask
)
154 const char *a
= addr
->v6
.s6_addr
;
155 const char *b
= base
->v6
.s6_addr
;
156 const char *m
= mask
->v6
.s6_addr
;
158 for (i
= 0; i
< 16; i
++)
159 if ((a
[i
] & m
[i
]) != b
[i
]) return 0;
163 static int inet6_rev_parsecomp(const char *p
, size_t n
)
165 if (n
!= 1) return -1;
166 else if ('0' <= *p
&& *p
<= '9') return *p
- '0';
167 else if ('a' <= *p
&& *p
<= 'f') return *p
- 'a' + 10;
168 else if ('A' <= *p
&& *p
<= 'F') return *p
- 'a' + 10;
172 static void inet6_rev_mkaddr(union gen_addr
*addr
, const byte
*ipv
)
174 unsigned char *a
= addr
->v6
.s6_addr
;
177 for (i
= 0; i
< 16; i
++)
178 a
[i
] = (ipv
[31-2*i
] << 4) | (ipv
[30-2*i
] << 0);
181 static char *inet6_rev_mkname(const struct sockaddr
*sa
, char *buf
)
183 const unsigned char *a
= CSIN6(sa
)->sin6_addr
.s6_addr
+ 16;
187 for (i
= 0; i
< 16; i
++) {
189 for (j
= 0; j
< 2; j
++) {
190 if (i
|| j
) *buf
++ = '.';
192 if (y
< 10) *buf
++ = y
+ '0';
193 else *buf
++ = y
- 10 + 'a';
200 const afinfo adns__inet6_afinfo
= {
201 AF_INET6
, 128, ':', 32, 1, adns_r_aaaa
,
202 inet6_sockaddr_to_inaddr
, inet6_sockaddr_equalp
,
203 inet6_prefix_mask
, inet6_guess_len
, inet6_matchp
,
204 inet6_rev_parsecomp
, inet6_rev_mkaddr
, inet6_rev_mkname