1 /* $KAME: prefix.c,v 1.9 2001/07/02 14:36:49 itojun Exp $ */
2 /* $FreeBSD: src/usr.sbin/faithd/prefix.c,v 1.1.2.2 2002/04/28 05:40:29 suz Exp $ */
3 /* $DragonFly: src/usr.sbin/faithd/prefix.c,v 1.4 2003/11/16 14:10:45 eirikn Exp $ */
6 * Copyright (C) 2000 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
45 #define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
51 static int prefix_set(const char *, struct prefix
*, int);
52 static struct config
*config_load1(const char *);
54 static void config_show1(const struct config
*);
55 static void config_show(void);
58 struct config
*config_list
= NULL
;
60 const int niflags
= NI_NUMERICHOST
| NI_WITHSCOPEID
;
62 const int niflags
= NI_NUMERICHOST
;
66 prefix_set(const char *s
, struct prefix
*prefix
, int slash
)
69 struct addrinfo hints
, *res
= NULL
;
81 memset(&hints
, 0, sizeof(hints
));
82 hints
.ai_family
= PF_UNSPEC
;
83 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
84 hints
.ai_flags
= AI_NUMERICHOST
;
85 if (getaddrinfo(p
, "0", &hints
, &res
))
87 if (res
->ai_next
|| res
->ai_addrlen
> sizeof(prefix
->a
))
89 memcpy(&prefix
->a
, res
->ai_addr
, res
->ai_addrlen
);
91 switch (prefix
->a
.ss_family
) {
94 a
= (char *)&((struct sockaddr_in
*)&prefix
->a
)->sin_addr
;
98 a
= (char *)&((struct sockaddr_in6
*)&prefix
->a
)->sin6_addr
;
108 prefix
->l
= (int)strtoul(q
, &r
, 10);
111 if (prefix
->l
< 0 || prefix
->l
> max
)
131 prefix_string(const struct prefix
*prefix
)
133 static char buf
[NI_MAXHOST
+ 20];
134 char hbuf
[NI_MAXHOST
];
136 if (getnameinfo((const struct sockaddr
*)&prefix
->a
, prefix
->a
.ss_len
,
137 hbuf
, sizeof(hbuf
), NULL
, 0, niflags
))
139 snprintf(buf
, sizeof(buf
), "%s/%d", hbuf
, prefix
->l
);
144 prefix_match(const struct prefix
*prefix
, const struct sockaddr
*sa
)
146 struct sockaddr_storage a
, b
;
150 if (prefix
->a
.ss_family
!= sa
->sa_family
||
151 prefix
->a
.ss_len
!= sa
->sa_len
)
154 if (prefix
->a
.ss_len
> sizeof(a
) || sa
->sa_len
> sizeof(b
))
157 switch (prefix
->a
.ss_family
) {
159 off
= offsetof(struct sockaddr_in
, sin_addr
);
162 off
= offsetof(struct sockaddr_in6
, sin6_addr
);
165 if (memcmp(&prefix
->a
, sa
, prefix
->a
.ss_len
) != 0)
171 memcpy(&a
, &prefix
->a
, prefix
->a
.ss_len
);
172 memcpy(&b
, sa
, sa
->sa_len
);
173 l
= prefix
->l
/ 8 + (prefix
->l
% 8 ? 1 : 0);
176 if (off
+ l
> a
.ss_len
)
179 pa
= ((char *)&a
) + off
;
180 pb
= ((char *)&b
) + off
;
182 pa
[prefix
->l
/ 8] &= 0xff00 >> (prefix
->l
% 8);
183 pb
[prefix
->l
/ 8] &= 0xff00 >> (prefix
->l
% 8);
185 if (memcmp(pa
, pb
, l
) != 0)
192 * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
193 * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
195 static struct config
*
196 config_load1(const char *line
)
204 if (strlen(line
) + 1 > sizeof(buf
))
206 strlcpy(buf
, line
, sizeof(buf
));
208 p
= strchr(buf
, '\n');
212 p
= strchr(buf
, '#');
215 if (strlen(buf
) == 0)
219 memset(token
, 0, sizeof(token
));
220 for (i
= 0; i
< sizeof(token
) / sizeof(token
[0]); i
++) {
221 token
[i
] = strtok(p
, "\t ");
223 if (token
[i
] == NULL
)
227 if (strtok(p
, "\t ") != NULL
)
229 /* insufficient tokens */
238 conf
= (struct config
*)malloc(sizeof(*conf
));
241 memset(conf
, 0, sizeof(*conf
));
243 if (strcasecmp(token
[1], "permit") == 0)
245 else if (strcasecmp(token
[1], "deny") == 0)
248 /* invalid keyword is considered as "deny" */
252 if (prefix_set(token
[0], &conf
->match
, 1) < 0)
254 if (prefix_set(token
[2], &conf
->dest
, 1) < 0)
257 if (prefix_set(token
[3], &conf
->src
, 0) < 0)
269 config_load(const char *configfile
)
273 struct config
*conf
, *p
;
274 struct config sentinel
;
279 configfile
= _PATH_PREFIX_CONF
;
280 fp
= fopen(configfile
, "r");
285 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
286 conf
= config_load1(buf
);
292 config_list
= sentinel
.next
;
300 config_show1(const struct config
*conf
)
304 p
= prefix_string(&conf
->match
);
305 printf("%s", p
? p
: "?");
312 p
= prefix_string(&conf
->dest
);
313 printf(" %s", p
? p
: "?");
323 for (conf
= config_list
; conf
; conf
= conf
->next
)
328 const struct config
*
329 config_match(struct sockaddr
*sa1
, struct sockaddr
*sa2
)
331 static struct config conf
;
332 const struct config
*p
;
334 if (sa1
->sa_len
> sizeof(conf
.match
.a
) ||
335 sa2
->sa_len
> sizeof(conf
.dest
.a
))
338 memset(&conf
, 0, sizeof(conf
));
341 memcpy(&conf
.match
.a
, sa1
, sa1
->sa_len
);
342 memcpy(&conf
.dest
.a
, sa2
, sa2
->sa_len
);
346 for (p
= config_list
; p
; p
= p
->next
)
347 if (prefix_match(&p
->match
, sa1
) && prefix_match(&p
->dest
, sa2
))