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 $ */
5 * Copyright (C) 2000 WIDE Project.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
44 #define offsetof(type, member) ((size_t)(u_long)(&((type *)0)->member))
50 static int prefix_set(const char *, struct prefix
*, int);
51 static struct config
*config_load1(const char *);
53 static void config_show1(const struct config
*);
54 static void config_show(void);
57 struct config
*config_list
= NULL
;
59 const int niflags
= NI_NUMERICHOST
| NI_WITHSCOPEID
;
61 const int niflags
= NI_NUMERICHOST
;
65 prefix_set(const char *s
, struct prefix
*prefix
, int slash
)
68 struct addrinfo hints
, *res
= NULL
;
79 memset(&hints
, 0, sizeof(hints
));
80 hints
.ai_family
= PF_UNSPEC
;
81 hints
.ai_socktype
= SOCK_DGRAM
; /*dummy*/
82 hints
.ai_flags
= AI_NUMERICHOST
;
83 if (getaddrinfo(p
, "0", &hints
, &res
))
85 if (res
->ai_next
|| res
->ai_addrlen
> sizeof(prefix
->a
))
87 memcpy(&prefix
->a
, res
->ai_addr
, res
->ai_addrlen
);
89 switch (prefix
->a
.ss_family
) {
103 prefix
->l
= (int)strtoul(q
, &r
, 10);
106 if (prefix
->l
< 0 || prefix
->l
> max
)
126 prefix_string(const struct prefix
*prefix
)
128 static char buf
[NI_MAXHOST
+ 20];
129 char hbuf
[NI_MAXHOST
];
131 if (getnameinfo((const struct sockaddr
*)&prefix
->a
, prefix
->a
.ss_len
,
132 hbuf
, sizeof(hbuf
), NULL
, 0, niflags
))
134 snprintf(buf
, sizeof(buf
), "%s/%d", hbuf
, prefix
->l
);
139 prefix_match(const struct prefix
*prefix
, const struct sockaddr
*sa
)
141 struct sockaddr_storage a
, b
;
145 if (prefix
->a
.ss_family
!= sa
->sa_family
||
146 prefix
->a
.ss_len
!= sa
->sa_len
)
149 if (prefix
->a
.ss_len
> sizeof(a
) || sa
->sa_len
> sizeof(b
))
152 switch (prefix
->a
.ss_family
) {
154 off
= offsetof(struct sockaddr_in
, sin_addr
);
157 off
= offsetof(struct sockaddr_in6
, sin6_addr
);
160 if (memcmp(&prefix
->a
, sa
, prefix
->a
.ss_len
) != 0)
166 memcpy(&a
, &prefix
->a
, prefix
->a
.ss_len
);
167 memcpy(&b
, sa
, sa
->sa_len
);
168 l
= prefix
->l
/ 8 + (prefix
->l
% 8 ? 1 : 0);
171 if (off
+ l
> a
.ss_len
)
174 pa
= ((char *)&a
) + off
;
175 pb
= ((char *)&b
) + off
;
177 pa
[prefix
->l
/ 8] &= 0xff00 >> (prefix
->l
% 8);
178 pb
[prefix
->l
/ 8] &= 0xff00 >> (prefix
->l
% 8);
180 if (memcmp(pa
, pb
, l
) != 0)
187 * prefix/prefixlen permit/deny prefix/prefixlen [srcaddr]
188 * 3ffe::/16 permit 10.0.0.0/8 10.1.1.1
190 static struct config
*
191 config_load1(const char *line
)
199 if (strlen(line
) + 1 > sizeof(buf
))
201 strlcpy(buf
, line
, sizeof(buf
));
203 p
= strchr(buf
, '\n');
207 p
= strchr(buf
, '#');
210 if (strlen(buf
) == 0)
214 memset(token
, 0, sizeof(token
));
215 for (i
= 0; i
< sizeof(token
) / sizeof(token
[0]); i
++) {
216 token
[i
] = strtok(p
, "\t ");
218 if (token
[i
] == NULL
)
222 if (strtok(p
, "\t ") != NULL
)
224 /* insufficient tokens */
233 conf
= (struct config
*)malloc(sizeof(*conf
));
236 memset(conf
, 0, sizeof(*conf
));
238 if (strcasecmp(token
[1], "permit") == 0)
240 else if (strcasecmp(token
[1], "deny") == 0)
243 /* invalid keyword is considered as "deny" */
247 if (prefix_set(token
[0], &conf
->match
, 1) < 0)
249 if (prefix_set(token
[2], &conf
->dest
, 1) < 0)
252 if (prefix_set(token
[3], &conf
->src
, 0) < 0)
264 config_load(const char *configfile
)
268 struct config
*conf
, *p
;
269 struct config sentinel
;
274 configfile
= _PATH_PREFIX_CONF
;
275 fp
= fopen(configfile
, "r");
280 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
281 conf
= config_load1(buf
);
287 config_list
= sentinel
.next
;
295 config_show1(const struct config
*conf
)
299 p
= prefix_string(&conf
->match
);
300 printf("%s", p
? p
: "?");
307 p
= prefix_string(&conf
->dest
);
308 printf(" %s", p
? p
: "?");
318 for (conf
= config_list
; conf
; conf
= conf
->next
)
323 const struct config
*
324 config_match(struct sockaddr
*sa1
, struct sockaddr
*sa2
)
326 static struct config conf
;
327 const struct config
*p
;
329 if (sa1
->sa_len
> sizeof(conf
.match
.a
) ||
330 sa2
->sa_len
> sizeof(conf
.dest
.a
))
333 memset(&conf
, 0, sizeof(conf
));
336 memcpy(&conf
.match
.a
, sa1
, sa1
->sa_len
);
337 memcpy(&conf
.dest
.a
, sa2
, sa2
->sa_len
);
341 for (p
= config_list
; p
; p
= p
->next
)
342 if (prefix_match(&p
->match
, sa1
) && prefix_match(&p
->dest
, sa2
))