iplist.c revision 37210
131921Sbrian/*- 231921Sbrian * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 331921Sbrian * All rights reserved. 431921Sbrian * 531921Sbrian * Redistribution and use in source and binary forms, with or without 631921Sbrian * modification, are permitted provided that the following conditions 731921Sbrian * are met: 831921Sbrian * 1. Redistributions of source code must retain the above copyright 931921Sbrian * notice, this list of conditions and the following disclaimer. 1031921Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1131921Sbrian * notice, this list of conditions and the following disclaimer in the 1231921Sbrian * documentation and/or other materials provided with the distribution. 1331921Sbrian * 1431921Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1531921Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1631921Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1731921Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1831921Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1931921Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2031921Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2131921Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2231921Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2331921Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2431921Sbrian * SUCH DAMAGE. 2531921Sbrian * 2637210Sbrian * $Id: iplist.c,v 1.6 1998/06/15 19:06:47 brian Exp $ 2731690Sbrian */ 2831690Sbrian 2931690Sbrian#include <sys/types.h> 3031690Sbrian#include <netinet/in.h> 3131690Sbrian#include <arpa/inet.h> 3231690Sbrian 3331690Sbrian#include <stdlib.h> 3431690Sbrian#include <string.h> 3531690Sbrian 3631690Sbrian#include "log.h" 3731690Sbrian#include "defs.h" 3831690Sbrian#include "iplist.h" 3931690Sbrian 4031690Sbrianstatic int 4131690Sbriando_inet_aton(const char *start, const char *end, struct in_addr *ip) 4231690Sbrian{ 4337010Sbrian char ipstr[16]; 4431690Sbrian 4531690Sbrian if (end - start > 15) { 4637210Sbrian log_Printf(LogWARN, "%.*s: Invalid IP address\n", (int)(end-start), start); 4731690Sbrian return 0; 4831690Sbrian } 4931690Sbrian strncpy(ipstr, start, end-start); 5031690Sbrian ipstr[end-start] = '\0'; 5131690Sbrian return inet_aton(ipstr, ip); 5231690Sbrian} 5331690Sbrian 5431690Sbrianstatic void 5531690Sbrianiplist_first(struct iplist *list) 5631690Sbrian{ 5731690Sbrian list->cur.pos = -1; 5831690Sbrian} 5931690Sbrian 6031690Sbrianstatic int 6131690Sbrianiplist_setrange(struct iplist *list, char *range) 6231690Sbrian{ 6331690Sbrian char *ptr, *to; 6431690Sbrian 6531690Sbrian if ((ptr = strpbrk(range, ",-")) == NULL) { 6631690Sbrian if (!inet_aton(range, &list->cur.ip)) 6731690Sbrian return 0; 6831690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 6931690Sbrian list->cur.nItems = 1; 7031690Sbrian } else { 7131690Sbrian if (!do_inet_aton(range, ptr, &list->cur.ip)) 7231690Sbrian return 0; 7331690Sbrian if (*ptr == ',') { 7431690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 7531690Sbrian list->cur.nItems = 1; 7631690Sbrian } else { 7731690Sbrian struct in_addr endip; 7831690Sbrian 7931690Sbrian to = ptr+1; 8031690Sbrian if ((ptr = strpbrk(to, ",-")) == NULL) 8131690Sbrian ptr = to + strlen(to); 8231690Sbrian if (*to == '-') 8331690Sbrian return 0; 8431690Sbrian if (!do_inet_aton(to, ptr, &endip)) 8531690Sbrian return 0; 8631690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 8731690Sbrian list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 8831690Sbrian if (list->cur.nItems < 1) 8931690Sbrian return 0; 9031690Sbrian } 9131690Sbrian } 9231690Sbrian list->cur.srcitem = 0; 9331690Sbrian list->cur.srcptr = range; 9431690Sbrian return 1; 9531690Sbrian} 9631690Sbrian 9731690Sbrianstatic int 9831690Sbrianiplist_nextrange(struct iplist *list) 9931690Sbrian{ 10031690Sbrian char *ptr, *to, *end; 10131690Sbrian 10231690Sbrian ptr = list->cur.srcptr; 10331690Sbrian if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 10431690Sbrian ptr++; 10531690Sbrian else 10631690Sbrian ptr = list->src; 10731690Sbrian 10831690Sbrian while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 10931690Sbrian if ((end = strchr(ptr, ',')) == NULL) 11031690Sbrian end = ptr + strlen(ptr); 11131690Sbrian if (end == ptr) 11231690Sbrian return 0; 11337210Sbrian log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n", 11437210Sbrian (int)(end - ptr), ptr); 11531690Sbrian to = ptr; 11631690Sbrian do 11731690Sbrian *to = *end++; 11831690Sbrian while (*to++ != '\0'); 11931690Sbrian if (*ptr == '\0') 12031690Sbrian ptr = list->src; 12131690Sbrian } 12231690Sbrian 12331690Sbrian return 1; 12431690Sbrian} 12531690Sbrian 12631690Sbrianstruct in_addr 12731690Sbrianiplist_next(struct iplist *list) 12831690Sbrian{ 12931690Sbrian if (list->cur.pos == -1) { 13031690Sbrian list->cur.srcptr = NULL; 13131690Sbrian if (!iplist_nextrange(list)) { 13231690Sbrian list->cur.ip.s_addr = INADDR_ANY; 13331690Sbrian return list->cur.ip; 13431690Sbrian } 13531690Sbrian } else if (++list->cur.srcitem == list->cur.nItems) { 13631690Sbrian if (!iplist_nextrange(list)) { 13731690Sbrian list->cur.ip.s_addr = INADDR_ANY; 13831690Sbrian list->cur.pos = -1; 13931690Sbrian return list->cur.ip; 14031690Sbrian } 14131690Sbrian } else 14231690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 14331690Sbrian list->cur.pos++; 14431690Sbrian 14531690Sbrian return list->cur.ip; 14631690Sbrian} 14731690Sbrian 14831690Sbrianint 14931690Sbrianiplist_setsrc(struct iplist *list, const char *src) 15031690Sbrian{ 15131962Sbrian strncpy(list->src, src, sizeof list->src - 1); 15231962Sbrian list->src[sizeof list->src - 1] = '\0'; 15331690Sbrian list->cur.srcptr = list->src; 15431690Sbrian do { 15531690Sbrian if (iplist_nextrange(list)) 15631690Sbrian list->nItems += list->cur.nItems; 15731690Sbrian else 15831690Sbrian return 0; 15931690Sbrian } while (list->cur.srcptr != list->src); 16031690Sbrian return 1; 16131690Sbrian} 16231690Sbrian 16331690Sbrianvoid 16431690Sbrianiplist_reset(struct iplist *list) 16531690Sbrian{ 16631690Sbrian list->src[0] = '\0'; 16731690Sbrian list->nItems = 0; 16831690Sbrian list->cur.pos = -1; 16931690Sbrian} 17031690Sbrian 17131690Sbrianstruct in_addr 17237210Sbrianiplist_setcurpos(struct iplist *list, long pos) 17331690Sbrian{ 17431690Sbrian if (pos < 0 || pos >= list->nItems) { 17531690Sbrian list->cur.pos = -1; 17631690Sbrian list->cur.ip.s_addr = INADDR_ANY; 17731690Sbrian return list->cur.ip; 17831690Sbrian } 17931690Sbrian 18031690Sbrian list->cur.srcptr = NULL; 18131690Sbrian list->cur.pos = 0; 18231690Sbrian while (1) { 18331690Sbrian iplist_nextrange(list); 18431690Sbrian if (pos < list->cur.nItems) { 18531690Sbrian if (pos) { 18631690Sbrian list->cur.srcitem = pos; 18731690Sbrian list->cur.pos += pos; 18831690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 18931690Sbrian } 19031690Sbrian break; 19131690Sbrian } 19231690Sbrian pos -= list->cur.nItems; 19331690Sbrian list->cur.pos += list->cur.nItems; 19431690Sbrian } 19531690Sbrian 19631690Sbrian return list->cur.ip; 19731690Sbrian} 19831690Sbrian 19931690Sbrianstruct in_addr 20031690Sbrianiplist_setrandpos(struct iplist *list) 20131690Sbrian{ 20231690Sbrian randinit(); 20331690Sbrian return iplist_setcurpos(list, random() % list->nItems); 20431690Sbrian} 20531690Sbrian 20631690Sbrianint 20731690Sbrianiplist_ip2pos(struct iplist *list, struct in_addr ip) 20831690Sbrian{ 20931690Sbrian struct iplist_cur cur; 21037210Sbrian u_long f; 21137210Sbrian int result; 21231690Sbrian 21331690Sbrian result = -1; 21431962Sbrian memcpy(&cur, &list->cur, sizeof cur); 21531690Sbrian 21631690Sbrian for (iplist_first(list), f = 0; f < list->nItems; f++) 21731690Sbrian if (iplist_next(list).s_addr == ip.s_addr) { 21831690Sbrian result = list->cur.pos; 21931690Sbrian break; 22031690Sbrian } 22131690Sbrian 22231962Sbrian memcpy(&list->cur, &cur, sizeof list->cur); 22331690Sbrian return result; 22431690Sbrian} 225