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 * 2650479Speter * $FreeBSD: releng/11.0/usr.sbin/ppp/iplist.c 134789 2004-09-05 01:46:52Z brian $ 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> 3546686Sbrian#include <termios.h> 3631690Sbrian 3731690Sbrian#include "log.h" 3831690Sbrian#include "defs.h" 3931690Sbrian#include "iplist.h" 4031690Sbrian 4131690Sbrianstatic int 4231690Sbriando_inet_aton(const char *start, const char *end, struct in_addr *ip) 4331690Sbrian{ 4437010Sbrian char ipstr[16]; 4531690Sbrian 4631690Sbrian if (end - start > 15) { 4737210Sbrian log_Printf(LogWARN, "%.*s: Invalid IP address\n", (int)(end-start), start); 4831690Sbrian return 0; 4931690Sbrian } 5031690Sbrian strncpy(ipstr, start, end-start); 5131690Sbrian ipstr[end-start] = '\0'; 5231690Sbrian return inet_aton(ipstr, ip); 5331690Sbrian} 5431690Sbrian 5531690Sbrianstatic void 5631690Sbrianiplist_first(struct iplist *list) 5731690Sbrian{ 5831690Sbrian list->cur.pos = -1; 5931690Sbrian} 6031690Sbrian 6131690Sbrianstatic int 6231690Sbrianiplist_setrange(struct iplist *list, char *range) 6331690Sbrian{ 6431690Sbrian char *ptr, *to; 6531690Sbrian 6631690Sbrian if ((ptr = strpbrk(range, ",-")) == NULL) { 6731690Sbrian if (!inet_aton(range, &list->cur.ip)) 6831690Sbrian return 0; 6931690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 7031690Sbrian list->cur.nItems = 1; 7131690Sbrian } else { 7231690Sbrian if (!do_inet_aton(range, ptr, &list->cur.ip)) 7331690Sbrian return 0; 7431690Sbrian if (*ptr == ',') { 7531690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 7631690Sbrian list->cur.nItems = 1; 7731690Sbrian } else { 7831690Sbrian struct in_addr endip; 7931690Sbrian 8031690Sbrian to = ptr+1; 8131690Sbrian if ((ptr = strpbrk(to, ",-")) == NULL) 8231690Sbrian ptr = to + strlen(to); 8331690Sbrian if (*to == '-') 8431690Sbrian return 0; 8531690Sbrian if (!do_inet_aton(to, ptr, &endip)) 8631690Sbrian return 0; 8731690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 8831690Sbrian list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 8931690Sbrian if (list->cur.nItems < 1) 9031690Sbrian return 0; 9131690Sbrian } 9231690Sbrian } 9331690Sbrian list->cur.srcitem = 0; 9431690Sbrian list->cur.srcptr = range; 9531690Sbrian return 1; 9631690Sbrian} 9731690Sbrian 9831690Sbrianstatic int 9931690Sbrianiplist_nextrange(struct iplist *list) 10031690Sbrian{ 10131690Sbrian char *ptr, *to, *end; 10231690Sbrian 10331690Sbrian ptr = list->cur.srcptr; 10431690Sbrian if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 10531690Sbrian ptr++; 10631690Sbrian else 10731690Sbrian ptr = list->src; 10831690Sbrian 10931690Sbrian while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 11031690Sbrian if ((end = strchr(ptr, ',')) == NULL) 11131690Sbrian end = ptr + strlen(ptr); 11231690Sbrian if (end == ptr) 11331690Sbrian return 0; 11437210Sbrian log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n", 11537210Sbrian (int)(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{ 15231962Sbrian strncpy(list->src, src, sizeof list->src - 1); 15331962Sbrian 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 17337210Sbrianiplist_setcurpos(struct iplist *list, long pos) 17431690Sbrian{ 175134789Sbrian if (pos < 0 || (unsigned)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); 185134789Sbrian if (pos < (int)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; 21137210Sbrian u_long f; 21237210Sbrian int result; 21331690Sbrian 21431690Sbrian result = -1; 21531962Sbrian memcpy(&cur, &list->cur, sizeof cur); 21631690Sbrian 21731690Sbrian for (iplist_first(list), f = 0; f < list->nItems; f++) 21831690Sbrian if (iplist_next(list).s_addr == ip.s_addr) { 21931690Sbrian result = list->cur.pos; 22031690Sbrian break; 22131690Sbrian } 22231690Sbrian 22331962Sbrian memcpy(&list->cur, &cur, sizeof list->cur); 22431690Sbrian return result; 22531690Sbrian} 226