1c39934eaSBrian Somers /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
4c39934eaSBrian Somers * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5c39934eaSBrian Somers * All rights reserved.
6c39934eaSBrian Somers *
7c39934eaSBrian Somers * Redistribution and use in source and binary forms, with or without
8c39934eaSBrian Somers * modification, are permitted provided that the following conditions
9c39934eaSBrian Somers * are met:
10c39934eaSBrian Somers * 1. Redistributions of source code must retain the above copyright
11c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer.
12c39934eaSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright
13c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer in the
14c39934eaSBrian Somers * documentation and/or other materials provided with the distribution.
15c39934eaSBrian Somers *
16c39934eaSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c39934eaSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c39934eaSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c39934eaSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c39934eaSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c39934eaSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c39934eaSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c39934eaSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c39934eaSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c39934eaSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c39934eaSBrian Somers * SUCH DAMAGE.
27bcc332bdSBrian Somers */
28bcc332bdSBrian Somers
29bcc332bdSBrian Somers #include <sys/types.h>
30bcc332bdSBrian Somers #include <netinet/in.h>
31bcc332bdSBrian Somers #include <arpa/inet.h>
32bcc332bdSBrian Somers
33bcc332bdSBrian Somers #include <stdlib.h>
34bcc332bdSBrian Somers #include <string.h>
355d9e6103SBrian Somers #include <termios.h>
36bcc332bdSBrian Somers
37bcc332bdSBrian Somers #include "log.h"
38bcc332bdSBrian Somers #include "defs.h"
39bcc332bdSBrian Somers #include "iplist.h"
40bcc332bdSBrian Somers
41bcc332bdSBrian Somers static int
do_inet_aton(const char * start,const char * end,struct in_addr * ip)42bcc332bdSBrian Somers do_inet_aton(const char *start, const char *end, struct in_addr *ip)
43bcc332bdSBrian Somers {
44d93d3a9cSBrian Somers char ipstr[16];
45bcc332bdSBrian Somers
46bcc332bdSBrian Somers if (end - start > 15) {
473a2e4f62SBrian Somers log_Printf(LogWARN, "%.*s: Invalid IP address\n", (int)(end-start), start);
48bcc332bdSBrian Somers return 0;
49bcc332bdSBrian Somers }
50bcc332bdSBrian Somers strncpy(ipstr, start, end-start);
51bcc332bdSBrian Somers ipstr[end-start] = '\0';
52bcc332bdSBrian Somers return inet_aton(ipstr, ip);
53bcc332bdSBrian Somers }
54bcc332bdSBrian Somers
55bcc332bdSBrian Somers static void
iplist_first(struct iplist * list)56bcc332bdSBrian Somers iplist_first(struct iplist *list)
57bcc332bdSBrian Somers {
58bcc332bdSBrian Somers list->cur.pos = -1;
59bcc332bdSBrian Somers }
60bcc332bdSBrian Somers
61bcc332bdSBrian Somers static int
iplist_setrange(struct iplist * list,char * range)62bcc332bdSBrian Somers iplist_setrange(struct iplist *list, char *range)
63bcc332bdSBrian Somers {
64bcc332bdSBrian Somers char *ptr, *to;
65bcc332bdSBrian Somers
66bcc332bdSBrian Somers if ((ptr = strpbrk(range, ",-")) == NULL) {
67bcc332bdSBrian Somers if (!inet_aton(range, &list->cur.ip))
68bcc332bdSBrian Somers return 0;
69bcc332bdSBrian Somers list->cur.lstart = ntohl(list->cur.ip.s_addr);
70bcc332bdSBrian Somers list->cur.nItems = 1;
71bcc332bdSBrian Somers } else {
72bcc332bdSBrian Somers if (!do_inet_aton(range, ptr, &list->cur.ip))
73bcc332bdSBrian Somers return 0;
74bcc332bdSBrian Somers if (*ptr == ',') {
75bcc332bdSBrian Somers list->cur.lstart = ntohl(list->cur.ip.s_addr);
76bcc332bdSBrian Somers list->cur.nItems = 1;
77bcc332bdSBrian Somers } else {
78bcc332bdSBrian Somers struct in_addr endip;
79bcc332bdSBrian Somers
80bcc332bdSBrian Somers to = ptr+1;
81bcc332bdSBrian Somers if ((ptr = strpbrk(to, ",-")) == NULL)
82bcc332bdSBrian Somers ptr = to + strlen(to);
83bcc332bdSBrian Somers if (*to == '-')
84bcc332bdSBrian Somers return 0;
85bcc332bdSBrian Somers if (!do_inet_aton(to, ptr, &endip))
86bcc332bdSBrian Somers return 0;
87bcc332bdSBrian Somers list->cur.lstart = ntohl(list->cur.ip.s_addr);
88bcc332bdSBrian Somers list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1;
89bcc332bdSBrian Somers if (list->cur.nItems < 1)
90bcc332bdSBrian Somers return 0;
91bcc332bdSBrian Somers }
92bcc332bdSBrian Somers }
93bcc332bdSBrian Somers list->cur.srcitem = 0;
94bcc332bdSBrian Somers list->cur.srcptr = range;
95bcc332bdSBrian Somers return 1;
96bcc332bdSBrian Somers }
97bcc332bdSBrian Somers
98bcc332bdSBrian Somers static int
iplist_nextrange(struct iplist * list)99bcc332bdSBrian Somers iplist_nextrange(struct iplist *list)
100bcc332bdSBrian Somers {
101bcc332bdSBrian Somers char *ptr, *to, *end;
102bcc332bdSBrian Somers
103bcc332bdSBrian Somers ptr = list->cur.srcptr;
104bcc332bdSBrian Somers if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL)
105bcc332bdSBrian Somers ptr++;
106bcc332bdSBrian Somers else
107bcc332bdSBrian Somers ptr = list->src;
108bcc332bdSBrian Somers
109bcc332bdSBrian Somers while (*ptr != '\0' && !iplist_setrange(list, ptr)) {
110bcc332bdSBrian Somers if ((end = strchr(ptr, ',')) == NULL)
111bcc332bdSBrian Somers end = ptr + strlen(ptr);
112bcc332bdSBrian Somers if (end == ptr)
113bcc332bdSBrian Somers return 0;
1143a2e4f62SBrian Somers log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n",
1153a2e4f62SBrian Somers (int)(end - ptr), ptr);
116bcc332bdSBrian Somers to = ptr;
117bcc332bdSBrian Somers do
118bcc332bdSBrian Somers *to = *end++;
119bcc332bdSBrian Somers while (*to++ != '\0');
120bcc332bdSBrian Somers if (*ptr == '\0')
121bcc332bdSBrian Somers ptr = list->src;
122bcc332bdSBrian Somers }
123bcc332bdSBrian Somers
124bcc332bdSBrian Somers return 1;
125bcc332bdSBrian Somers }
126bcc332bdSBrian Somers
127bcc332bdSBrian Somers struct in_addr
iplist_next(struct iplist * list)128bcc332bdSBrian Somers iplist_next(struct iplist *list)
129bcc332bdSBrian Somers {
130bcc332bdSBrian Somers if (list->cur.pos == -1) {
131bcc332bdSBrian Somers list->cur.srcptr = NULL;
132bcc332bdSBrian Somers if (!iplist_nextrange(list)) {
133bcc332bdSBrian Somers list->cur.ip.s_addr = INADDR_ANY;
134bcc332bdSBrian Somers return list->cur.ip;
135bcc332bdSBrian Somers }
136bcc332bdSBrian Somers } else if (++list->cur.srcitem == list->cur.nItems) {
137bcc332bdSBrian Somers if (!iplist_nextrange(list)) {
138bcc332bdSBrian Somers list->cur.ip.s_addr = INADDR_ANY;
139bcc332bdSBrian Somers list->cur.pos = -1;
140bcc332bdSBrian Somers return list->cur.ip;
141bcc332bdSBrian Somers }
142bcc332bdSBrian Somers } else
143bcc332bdSBrian Somers list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
144bcc332bdSBrian Somers list->cur.pos++;
145bcc332bdSBrian Somers
146bcc332bdSBrian Somers return list->cur.ip;
147bcc332bdSBrian Somers }
148bcc332bdSBrian Somers
149bcc332bdSBrian Somers int
iplist_setsrc(struct iplist * list,const char * src)150bcc332bdSBrian Somers iplist_setsrc(struct iplist *list, const char *src)
151bcc332bdSBrian Somers {
15270ee81ffSBrian Somers strncpy(list->src, src, sizeof list->src - 1);
15370ee81ffSBrian Somers list->src[sizeof list->src - 1] = '\0';
154bcc332bdSBrian Somers list->cur.srcptr = list->src;
155bcc332bdSBrian Somers do {
156bcc332bdSBrian Somers if (iplist_nextrange(list))
157bcc332bdSBrian Somers list->nItems += list->cur.nItems;
158bcc332bdSBrian Somers else
159bcc332bdSBrian Somers return 0;
160bcc332bdSBrian Somers } while (list->cur.srcptr != list->src);
161bcc332bdSBrian Somers return 1;
162bcc332bdSBrian Somers }
163bcc332bdSBrian Somers
164bcc332bdSBrian Somers void
iplist_reset(struct iplist * list)165bcc332bdSBrian Somers iplist_reset(struct iplist *list)
166bcc332bdSBrian Somers {
167bcc332bdSBrian Somers list->src[0] = '\0';
168bcc332bdSBrian Somers list->nItems = 0;
169bcc332bdSBrian Somers list->cur.pos = -1;
170bcc332bdSBrian Somers }
171bcc332bdSBrian Somers
172bcc332bdSBrian Somers struct in_addr
iplist_setcurpos(struct iplist * list,long pos)1733a2e4f62SBrian Somers iplist_setcurpos(struct iplist *list, long pos)
174bcc332bdSBrian Somers {
175057f1760SBrian Somers if (pos < 0 || (unsigned)pos >= list->nItems) {
176bcc332bdSBrian Somers list->cur.pos = -1;
177bcc332bdSBrian Somers list->cur.ip.s_addr = INADDR_ANY;
178bcc332bdSBrian Somers return list->cur.ip;
179bcc332bdSBrian Somers }
180bcc332bdSBrian Somers
181bcc332bdSBrian Somers list->cur.srcptr = NULL;
182bcc332bdSBrian Somers list->cur.pos = 0;
183bcc332bdSBrian Somers while (1) {
184bcc332bdSBrian Somers iplist_nextrange(list);
185057f1760SBrian Somers if (pos < (int)list->cur.nItems) {
186bcc332bdSBrian Somers if (pos) {
187bcc332bdSBrian Somers list->cur.srcitem = pos;
188bcc332bdSBrian Somers list->cur.pos += pos;
189bcc332bdSBrian Somers list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
190bcc332bdSBrian Somers }
191bcc332bdSBrian Somers break;
192bcc332bdSBrian Somers }
193bcc332bdSBrian Somers pos -= list->cur.nItems;
194bcc332bdSBrian Somers list->cur.pos += list->cur.nItems;
195bcc332bdSBrian Somers }
196bcc332bdSBrian Somers
197bcc332bdSBrian Somers return list->cur.ip;
198bcc332bdSBrian Somers }
199bcc332bdSBrian Somers
200bcc332bdSBrian Somers struct in_addr
iplist_setrandpos(struct iplist * list)201bcc332bdSBrian Somers iplist_setrandpos(struct iplist *list)
202bcc332bdSBrian Somers {
203bcc332bdSBrian Somers randinit();
204bcc332bdSBrian Somers return iplist_setcurpos(list, random() % list->nItems);
205bcc332bdSBrian Somers }
206bcc332bdSBrian Somers
207bcc332bdSBrian Somers int
iplist_ip2pos(struct iplist * list,struct in_addr ip)208bcc332bdSBrian Somers iplist_ip2pos(struct iplist *list, struct in_addr ip)
209bcc332bdSBrian Somers {
210bcc332bdSBrian Somers struct iplist_cur cur;
2113a2e4f62SBrian Somers u_long f;
2123a2e4f62SBrian Somers int result;
213bcc332bdSBrian Somers
214bcc332bdSBrian Somers result = -1;
21570ee81ffSBrian Somers memcpy(&cur, &list->cur, sizeof cur);
216bcc332bdSBrian Somers
217bcc332bdSBrian Somers for (iplist_first(list), f = 0; f < list->nItems; f++)
218bcc332bdSBrian Somers if (iplist_next(list).s_addr == ip.s_addr) {
219bcc332bdSBrian Somers result = list->cur.pos;
220bcc332bdSBrian Somers break;
221bcc332bdSBrian Somers }
222bcc332bdSBrian Somers
22370ee81ffSBrian Somers memcpy(&list->cur, &cur, sizeof list->cur);
224bcc332bdSBrian Somers return result;
225bcc332bdSBrian Somers }
226