summaryrefslogtreecommitdiff
path: root/src/iplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/iplist.c')
-rw-r--r--src/iplist.c225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/iplist.c b/src/iplist.c
new file mode 100644
index 0000000..0f93636
--- /dev/null
+++ b/src/iplist.c
@@ -0,0 +1,225 @@
+/*-
+ * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.sbin/ppp/iplist.c,v 1.10.26.1 2010/12/21 17:10:29 kensmith Exp $
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <termios.h>
+
+#include "log.h"
+#include "defs.h"
+#include "iplist.h"
+
+static int
+do_inet_aton(const char *start, const char *end, struct in_addr *ip)
+{
+ char ipstr[16];
+
+ if (end - start > 15) {
+ log_Printf(LogWARN, "%.*s: Invalid IP address\n", (int)(end-start), start);
+ return 0;
+ }
+ strncpy(ipstr, start, end-start);
+ ipstr[end-start] = '\0';
+ return inet_aton(ipstr, ip);
+}
+
+static void
+iplist_first(struct iplist *list)
+{
+ list->cur.pos = -1;
+}
+
+static int
+iplist_setrange(struct iplist *list, char *range)
+{
+ char *ptr, *to;
+
+ if ((ptr = strpbrk(range, ",-")) == NULL) {
+ if (!inet_aton(range, &list->cur.ip))
+ return 0;
+ list->cur.lstart = ntohl(list->cur.ip.s_addr);
+ list->cur.nItems = 1;
+ } else {
+ if (!do_inet_aton(range, ptr, &list->cur.ip))
+ return 0;
+ if (*ptr == ',') {
+ list->cur.lstart = ntohl(list->cur.ip.s_addr);
+ list->cur.nItems = 1;
+ } else {
+ struct in_addr endip;
+
+ to = ptr+1;
+ if ((ptr = strpbrk(to, ",-")) == NULL)
+ ptr = to + strlen(to);
+ if (*to == '-')
+ return 0;
+ if (!do_inet_aton(to, ptr, &endip))
+ return 0;
+ list->cur.lstart = ntohl(list->cur.ip.s_addr);
+ list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1;
+ if (list->cur.nItems < 1)
+ return 0;
+ }
+ }
+ list->cur.srcitem = 0;
+ list->cur.srcptr = range;
+ return 1;
+}
+
+static int
+iplist_nextrange(struct iplist *list)
+{
+ char *ptr, *to, *end;
+
+ ptr = list->cur.srcptr;
+ if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL)
+ ptr++;
+ else
+ ptr = list->src;
+
+ while (*ptr != '\0' && !iplist_setrange(list, ptr)) {
+ if ((end = strchr(ptr, ',')) == NULL)
+ end = ptr + strlen(ptr);
+ if (end == ptr)
+ return 0;
+ log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n",
+ (int)(end - ptr), ptr);
+ to = ptr;
+ do
+ *to = *end++;
+ while (*to++ != '\0');
+ if (*ptr == '\0')
+ ptr = list->src;
+ }
+
+ return 1;
+}
+
+struct in_addr
+iplist_next(struct iplist *list)
+{
+ if (list->cur.pos == -1) {
+ list->cur.srcptr = NULL;
+ if (!iplist_nextrange(list)) {
+ list->cur.ip.s_addr = INADDR_ANY;
+ return list->cur.ip;
+ }
+ } else if (++list->cur.srcitem == list->cur.nItems) {
+ if (!iplist_nextrange(list)) {
+ list->cur.ip.s_addr = INADDR_ANY;
+ list->cur.pos = -1;
+ return list->cur.ip;
+ }
+ } else
+ list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
+ list->cur.pos++;
+
+ return list->cur.ip;
+}
+
+int
+iplist_setsrc(struct iplist *list, const char *src)
+{
+ strncpy(list->src, src, sizeof list->src - 1);
+ list->src[sizeof list->src - 1] = '\0';
+ list->cur.srcptr = list->src;
+ do {
+ if (iplist_nextrange(list))
+ list->nItems += list->cur.nItems;
+ else
+ return 0;
+ } while (list->cur.srcptr != list->src);
+ return 1;
+}
+
+void
+iplist_reset(struct iplist *list)
+{
+ list->src[0] = '\0';
+ list->nItems = 0;
+ list->cur.pos = -1;
+}
+
+struct in_addr
+iplist_setcurpos(struct iplist *list, long pos)
+{
+ if (pos < 0 || (unsigned)pos >= list->nItems) {
+ list->cur.pos = -1;
+ list->cur.ip.s_addr = INADDR_ANY;
+ return list->cur.ip;
+ }
+
+ list->cur.srcptr = NULL;
+ list->cur.pos = 0;
+ while (1) {
+ iplist_nextrange(list);
+ if (pos < (int)list->cur.nItems) {
+ if (pos) {
+ list->cur.srcitem = pos;
+ list->cur.pos += pos;
+ list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem);
+ }
+ break;
+ }
+ pos -= list->cur.nItems;
+ list->cur.pos += list->cur.nItems;
+ }
+
+ return list->cur.ip;
+}
+
+struct in_addr
+iplist_setrandpos(struct iplist *list)
+{
+ randinit();
+ return iplist_setcurpos(list, random() % list->nItems);
+}
+
+int
+iplist_ip2pos(struct iplist *list, struct in_addr ip)
+{
+ struct iplist_cur cur;
+ u_long f;
+ int result;
+
+ result = -1;
+ memcpy(&cur, &list->cur, sizeof cur);
+
+ for (iplist_first(list), f = 0; f < list->nItems; f++)
+ if (iplist_next(list).s_addr == ip.s_addr) {
+ result = list->cur.pos;
+ break;
+ }
+
+ memcpy(&list->cur, &cur, sizeof list->cur);
+ return result;
+}