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))
46 static void *inet_sockaddr_to_inaddr(struct sockaddr
*sa
)
47 { return &SIN(sa
)->sin_addr
; }
49 static void inet_prefix_mask(int len
, union gen_addr
*mask
)
50 { mask
->v4
.s_addr
= htonl(!len ?
0 : 0xffffffff << (32 - len
)); }
52 static int inet_guess_len(const union gen_addr
*addr
)
54 unsigned a
= (ntohl(addr
->v4
.s_addr
) >> 24) & 0xff;
56 if (a
< 128) return 8;
57 else if (a
< 192) return 16;
58 else if (a
< 224) return 24;
62 static int inet_matchp(const union gen_addr
*addr
,
63 const union gen_addr
*base
,
64 const union gen_addr
*mask
)
65 { return (addr
->v4
.s_addr
& mask
->v4
.s_addr
) == base
->v4
.s_addr
; }
67 static int inet_rev_parsecomp(const char *p
, size_t n
)
73 if ('0' <= *p
&& *p
<= '9') i
= 10*i
+ *p
++ - '0';
79 static void inet_rev_mkaddr(union gen_addr
*addr
, const byte
*ipv
)
81 addr
->v4
.s_addr
= htonl((ipv
[3]<<24) | (ipv
[2]<<16) |
82 (ipv
[1]<<8) | (ipv
[0]));
85 static char *inet_rev_mkname(struct sockaddr
*sa
, char *buf
)
87 unsigned long a
= ntohl(SIN(sa
)->sin_addr
.s_addr
);
90 for (i
= 0; i
< 4; i
++) {
92 buf
+= sprintf(buf
, "%d", (int)(a
& 0xff));
98 const afinfo adns__inet_afinfo
= {
99 AF_INET
, 32, '.', 4, 3, adns_r_a
,
100 inet_sockaddr_to_inaddr
, inet_prefix_mask
, inet_guess_len
, inet_matchp
,
101 inet_rev_parsecomp
, inet_rev_mkaddr
, inet_rev_mkname
108 #define SIN6(sa) ((struct sockaddr_in6 *)(sa))
110 static void *inet6_sockaddr_to_inaddr(struct sockaddr
*sa
)
111 { return &SIN6(sa
)->sin6_addr
; }
113 static void inet6_prefix_mask(int len
, union gen_addr
*mask
)
115 int i
= len
/8, j
= len
%8;
116 unsigned char *m
= mask
->v6
.s6_addr
;
120 if (j
) m
[i
++] = (0xff << (8-j
)) & 0xff;
121 memset(m
+ i
, 0, 16-i
);
124 static int inet6_guess_len(const union gen_addr
*addr
)
127 static int inet6_matchp(const union gen_addr
*addr
,
128 const union gen_addr
*base
,
129 const union gen_addr
*mask
)
132 const char *a
= addr
->v6
.s6_addr
;
133 const char *b
= base
->v6
.s6_addr
;
134 const char *m
= mask
->v6
.s6_addr
;
136 for (i
= 0; i
< 16; i
++)
137 if ((a
[i
] & m
[i
]) != b
[i
]) return 0;
141 static int inet6_rev_parsecomp(const char *p
, size_t n
)
143 if (n
!= 1) return -1;
144 else if ('0' <= *p
&& *p
<= '9') return *p
- '0';
145 else if ('a' <= *p
&& *p
<= 'f') return *p
- 'a' + 10;
146 else if ('A' <= *p
&& *p
<= 'F') return *p
- 'a' + 10;
150 static void inet6_rev_mkaddr(union gen_addr
*addr
, const byte
*ipv
)
152 unsigned char *a
= addr
->v6
.s6_addr
;
155 for (i
= 0; i
< 16; i
++)
156 a
[i
] = (ipv
[31-2*i
] << 4) | (ipv
[30-2*i
] << 0);
159 static char *inet6_rev_mkname(struct sockaddr
*sa
, char *buf
)
161 unsigned char *a
= SIN6(sa
)->sin6_addr
.s6_addr
+ 16;
165 for (i
= 0; i
< 16; i
++) {
167 for (j
= 0; j
< 2; j
++) {
168 if (i
|| j
) *buf
++ = '.';
170 if (y
< 10) *buf
++ = y
+ '0';
171 else *buf
++ = y
- 10 + 'a';
178 const afinfo adns__inet6_afinfo
= {
179 AF_INET6
, 128, ':', 32, 1, adns_r_aaaa
,
180 inet6_sockaddr_to_inaddr
, inet6_prefix_mask
, inet6_guess_len
, inet6_matchp
,
181 inet6_rev_parsecomp
, inet6_rev_mkaddr
, inet6_rev_mkname