iplist.c revision 31921
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 * 2631921Sbrian * $Id$ 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 "command.h" 3731690Sbrian#include "mbuf.h" 3831690Sbrian#include "log.h" 3931690Sbrian#include "defs.h" 4031690Sbrian#include "iplist.h" 4131690Sbrian 4231690Sbrianstatic int 4331690Sbriando_inet_aton(const char *start, const char *end, struct in_addr *ip) 4431690Sbrian{ 4531690Sbrian static char ipstr[16]; 4631690Sbrian 4731690Sbrian if (end - start > 15) { 4831690Sbrian LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start); 4931690Sbrian return 0; 5031690Sbrian } 5131690Sbrian strncpy(ipstr, start, end-start); 5231690Sbrian ipstr[end-start] = '\0'; 5331690Sbrian return inet_aton(ipstr, ip); 5431690Sbrian} 5531690Sbrian 5631690Sbrianstatic void 5731690Sbrianiplist_first(struct iplist *list) 5831690Sbrian{ 5931690Sbrian list->cur.pos = -1; 6031690Sbrian} 6131690Sbrian 6231690Sbrianstatic int 6331690Sbrianiplist_setrange(struct iplist *list, char *range) 6431690Sbrian{ 6531690Sbrian char *ptr, *to; 6631690Sbrian 6731690Sbrian if ((ptr = strpbrk(range, ",-")) == NULL) { 6831690Sbrian if (!inet_aton(range, &list->cur.ip)) 6931690Sbrian return 0; 7031690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 7131690Sbrian list->cur.nItems = 1; 7231690Sbrian } else { 7331690Sbrian if (!do_inet_aton(range, ptr, &list->cur.ip)) 7431690Sbrian return 0; 7531690Sbrian if (*ptr == ',') { 7631690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 7731690Sbrian list->cur.nItems = 1; 7831690Sbrian } else { 7931690Sbrian struct in_addr endip; 8031690Sbrian 8131690Sbrian to = ptr+1; 8231690Sbrian if ((ptr = strpbrk(to, ",-")) == NULL) 8331690Sbrian ptr = to + strlen(to); 8431690Sbrian if (*to == '-') 8531690Sbrian return 0; 8631690Sbrian if (!do_inet_aton(to, ptr, &endip)) 8731690Sbrian return 0; 8831690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 8931690Sbrian list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 9031690Sbrian if (list->cur.nItems < 1) 9131690Sbrian return 0; 9231690Sbrian } 9331690Sbrian } 9431690Sbrian list->cur.srcitem = 0; 9531690Sbrian list->cur.srcptr = range; 9631690Sbrian return 1; 9731690Sbrian} 9831690Sbrian 9931690Sbrianstatic int 10031690Sbrianiplist_nextrange(struct iplist *list) 10131690Sbrian{ 10231690Sbrian char *ptr, *to, *end; 10331690Sbrian 10431690Sbrian ptr = list->cur.srcptr; 10531690Sbrian if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 10631690Sbrian ptr++; 10731690Sbrian else 10831690Sbrian ptr = list->src; 10931690Sbrian 11031690Sbrian while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 11131690Sbrian if ((end = strchr(ptr, ',')) == NULL) 11231690Sbrian end = ptr + strlen(ptr); 11331690Sbrian if (end == ptr) 11431690Sbrian return 0; 11531690Sbrian LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr); 11631690Sbrian to = ptr; 11731690Sbrian do 11831690Sbrian *to = *end++; 11931690Sbrian while (*to++ != '\0'); 12031690Sbrian if (*ptr == '\0') 12131690Sbrian ptr = list->src; 12231690Sbrian } 12331690Sbrian 12431690Sbrian return 1; 12531690Sbrian} 12631690Sbrian 12731690Sbrianstruct in_addr 12831690Sbrianiplist_next(struct iplist *list) 12931690Sbrian{ 13031690Sbrian if (list->cur.pos == -1) { 13131690Sbrian list->cur.srcptr = NULL; 13231690Sbrian if (!iplist_nextrange(list)) { 13331690Sbrian list->cur.ip.s_addr = INADDR_ANY; 13431690Sbrian return list->cur.ip; 13531690Sbrian } 13631690Sbrian } else if (++list->cur.srcitem == list->cur.nItems) { 13731690Sbrian if (!iplist_nextrange(list)) { 13831690Sbrian list->cur.ip.s_addr = INADDR_ANY; 13931690Sbrian list->cur.pos = -1; 14031690Sbrian return list->cur.ip; 14131690Sbrian } 14231690Sbrian } else 14331690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 14431690Sbrian list->cur.pos++; 14531690Sbrian 14631690Sbrian return list->cur.ip; 14731690Sbrian} 14831690Sbrian 14931690Sbrianint 15031690Sbrianiplist_setsrc(struct iplist *list, const char *src) 15131690Sbrian{ 15231690Sbrian strncpy(list->src, src, sizeof(list->src)); 15331690Sbrian list->src[sizeof(list->src)-1] = '\0'; 15431690Sbrian list->cur.srcptr = list->src; 15531690Sbrian do { 15631690Sbrian if (iplist_nextrange(list)) 15731690Sbrian list->nItems += list->cur.nItems; 15831690Sbrian else 15931690Sbrian return 0; 16031690Sbrian } while (list->cur.srcptr != list->src); 16131690Sbrian return 1; 16231690Sbrian} 16331690Sbrian 16431690Sbrianvoid 16531690Sbrianiplist_reset(struct iplist *list) 16631690Sbrian{ 16731690Sbrian list->src[0] = '\0'; 16831690Sbrian list->nItems = 0; 16931690Sbrian list->cur.pos = -1; 17031690Sbrian} 17131690Sbrian 17231690Sbrianstruct in_addr 17331690Sbrianiplist_setcurpos(struct iplist *list, int pos) 17431690Sbrian{ 17531690Sbrian if (pos < 0 || pos >= list->nItems) { 17631690Sbrian list->cur.pos = -1; 17731690Sbrian list->cur.ip.s_addr = INADDR_ANY; 17831690Sbrian return list->cur.ip; 17931690Sbrian } 18031690Sbrian 18131690Sbrian list->cur.srcptr = NULL; 18231690Sbrian list->cur.pos = 0; 18331690Sbrian while (1) { 18431690Sbrian iplist_nextrange(list); 18531690Sbrian if (pos < list->cur.nItems) { 18631690Sbrian if (pos) { 18731690Sbrian list->cur.srcitem = pos; 18831690Sbrian list->cur.pos += pos; 18931690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 19031690Sbrian } 19131690Sbrian break; 19231690Sbrian } 19331690Sbrian pos -= list->cur.nItems; 19431690Sbrian list->cur.pos += list->cur.nItems; 19531690Sbrian } 19631690Sbrian 19731690Sbrian return list->cur.ip; 19831690Sbrian} 19931690Sbrian 20031690Sbrianstruct in_addr 20131690Sbrianiplist_setrandpos(struct iplist *list) 20231690Sbrian{ 20331690Sbrian randinit(); 20431690Sbrian return iplist_setcurpos(list, random() % list->nItems); 20531690Sbrian} 20631690Sbrian 20731690Sbrianint 20831690Sbrianiplist_ip2pos(struct iplist *list, struct in_addr ip) 20931690Sbrian{ 21031690Sbrian struct iplist_cur cur; 21131690Sbrian int f, result; 21231690Sbrian 21331690Sbrian result = -1; 21431690Sbrian 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 22231690Sbrian memcpy(&list->cur, &cur, sizeof(list->cur)); 22331690Sbrian return result; 22431690Sbrian} 225