2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/types.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
42 do_inet_aton(const char *start
, const char *end
, struct in_addr
*ip
)
46 if (end
- start
> 15) {
47 log_Printf(LogWARN
, "%.*s: Invalid IP address\n", (int)(end
-start
), start
);
50 strncpy(ipstr
, start
, end
-start
);
51 ipstr
[end
-start
] = '\0';
52 return inet_aton(ipstr
, ip
);
56 iplist_first(struct iplist
*list
)
62 iplist_setrange(struct iplist
*list
, char *range
)
66 if ((ptr
= strpbrk(range
, ",-")) == NULL
) {
67 if (!inet_aton(range
, &list
->cur
.ip
))
69 list
->cur
.lstart
= ntohl(list
->cur
.ip
.s_addr
);
72 if (!do_inet_aton(range
, ptr
, &list
->cur
.ip
))
75 list
->cur
.lstart
= ntohl(list
->cur
.ip
.s_addr
);
81 if ((ptr
= strpbrk(to
, ",-")) == NULL
)
82 ptr
= to
+ strlen(to
);
85 if (!do_inet_aton(to
, ptr
, &endip
))
87 list
->cur
.lstart
= ntohl(list
->cur
.ip
.s_addr
);
88 list
->cur
.nItems
= ntohl(endip
.s_addr
) - list
->cur
.lstart
+ 1;
89 if (list
->cur
.nItems
< 1)
93 list
->cur
.srcitem
= 0;
94 list
->cur
.srcptr
= range
;
99 iplist_nextrange(struct iplist
*list
)
101 char *ptr
, *to
, *end
;
103 ptr
= list
->cur
.srcptr
;
104 if (ptr
!= NULL
&& (ptr
= strchr(ptr
, ',')) != NULL
)
109 while (*ptr
!= '\0' && !iplist_setrange(list
, ptr
)) {
110 if ((end
= strchr(ptr
, ',')) == NULL
)
111 end
= ptr
+ strlen(ptr
);
114 log_Printf(LogWARN
, "%.*s: Invalid IP range (skipping)\n",
115 (int)(end
- ptr
), ptr
);
119 while (*to
++ != '\0');
128 iplist_next(struct iplist
*list
)
130 if (list
->cur
.pos
== -1) {
131 list
->cur
.srcptr
= NULL
;
132 if (!iplist_nextrange(list
)) {
133 list
->cur
.ip
.s_addr
= INADDR_ANY
;
136 } else if (++list
->cur
.srcitem
== list
->cur
.nItems
) {
137 if (!iplist_nextrange(list
)) {
138 list
->cur
.ip
.s_addr
= INADDR_ANY
;
143 list
->cur
.ip
.s_addr
= htonl(list
->cur
.lstart
+ list
->cur
.srcitem
);
150 iplist_setsrc(struct iplist
*list
, const char *src
)
152 strncpy(list
->src
, src
, sizeof list
->src
- 1);
153 list
->src
[sizeof list
->src
- 1] = '\0';
154 list
->cur
.srcptr
= list
->src
;
156 if (iplist_nextrange(list
))
157 list
->nItems
+= list
->cur
.nItems
;
160 } while (list
->cur
.srcptr
!= list
->src
);
165 iplist_reset(struct iplist
*list
)
173 iplist_setcurpos(struct iplist
*list
, long pos
)
175 if (pos
< 0 || (unsigned)pos
>= list
->nItems
) {
177 list
->cur
.ip
.s_addr
= INADDR_ANY
;
181 list
->cur
.srcptr
= NULL
;
184 iplist_nextrange(list
);
185 if (pos
< (int)list
->cur
.nItems
) {
187 list
->cur
.srcitem
= pos
;
188 list
->cur
.pos
+= pos
;
189 list
->cur
.ip
.s_addr
= htonl(list
->cur
.lstart
+ list
->cur
.srcitem
);
193 pos
-= list
->cur
.nItems
;
194 list
->cur
.pos
+= list
->cur
.nItems
;
201 iplist_setrandpos(struct iplist
*list
)
204 return iplist_setcurpos(list
, random() % list
->nItems
);
208 iplist_ip2pos(struct iplist
*list
, struct in_addr ip
)
210 struct iplist_cur cur
;
215 memcpy(&cur
, &list
->cur
, sizeof cur
);
217 for (iplist_first(list
), f
= 0; f
< list
->nItems
; f
++)
218 if (iplist_next(list
).s_addr
== ip
.s_addr
) {
219 result
= list
->cur
.pos
;
223 memcpy(&list
->cur
, &cur
, sizeof list
->cur
);