xref: /freebsd/usr.sbin/ppp/iplist.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
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