iplist.c revision 31953
1/*- 2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: iplist.c,v 1.2 1997/12/21 12:11:06 brian Exp $ 27 */ 28 29#include <sys/types.h> 30#include <netinet/in.h> 31#include <arpa/inet.h> 32 33#include <stdlib.h> 34#include <string.h> 35 36#include "command.h" 37#include "mbuf.h" 38#include "log.h" 39#include "defs.h" 40#include "iplist.h" 41 42static int 43do_inet_aton(const char *start, const char *end, struct in_addr *ip) 44{ 45 static char ipstr[16]; 46 47 if (end - start > 15) { 48 LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start); 49 return 0; 50 } 51 strncpy(ipstr, start, end-start); 52 ipstr[end-start] = '\0'; 53 return inet_aton(ipstr, ip); 54} 55 56static void 57iplist_first(struct iplist *list) 58{ 59 list->cur.pos = -1; 60} 61 62static int 63iplist_setrange(struct iplist *list, char *range) 64{ 65 char *ptr, *to; 66 67 if ((ptr = strpbrk(range, ",-")) == NULL) { 68 if (!inet_aton(range, &list->cur.ip)) 69 return 0; 70 list->cur.lstart = ntohl(list->cur.ip.s_addr); 71 list->cur.nItems = 1; 72 } else { 73 if (!do_inet_aton(range, ptr, &list->cur.ip)) 74 return 0; 75 if (*ptr == ',') { 76 list->cur.lstart = ntohl(list->cur.ip.s_addr); 77 list->cur.nItems = 1; 78 } else { 79 struct in_addr endip; 80 81 to = ptr+1; 82 if ((ptr = strpbrk(to, ",-")) == NULL) 83 ptr = to + strlen(to); 84 if (*to == '-') 85 return 0; 86 if (!do_inet_aton(to, ptr, &endip)) 87 return 0; 88 list->cur.lstart = ntohl(list->cur.ip.s_addr); 89 list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 90 if (list->cur.nItems < 1) 91 return 0; 92 } 93 } 94 list->cur.srcitem = 0; 95 list->cur.srcptr = range; 96 return 1; 97} 98 99static int 100iplist_nextrange(struct iplist *list) 101{ 102 char *ptr, *to, *end; 103 104 ptr = list->cur.srcptr; 105 if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 106 ptr++; 107 else 108 ptr = list->src; 109 110 while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 111 if ((end = strchr(ptr, ',')) == NULL) 112 end = ptr + strlen(ptr); 113 if (end == ptr) 114 return 0; 115 LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr); 116 to = ptr; 117 do 118 *to = *end++; 119 while (*to++ != '\0'); 120 if (*ptr == '\0') 121 ptr = list->src; 122 } 123 124 return 1; 125} 126 127struct in_addr 128iplist_next(struct iplist *list) 129{ 130 if (list->cur.pos == -1) { 131 list->cur.srcptr = NULL; 132 if (!iplist_nextrange(list)) { 133 list->cur.ip.s_addr = INADDR_ANY; 134 return list->cur.ip; 135 } 136 } else if (++list->cur.srcitem == list->cur.nItems) { 137 if (!iplist_nextrange(list)) { 138 list->cur.ip.s_addr = INADDR_ANY; 139 list->cur.pos = -1; 140 return list->cur.ip; 141 } 142 } else 143 list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 144 list->cur.pos++; 145 146 return list->cur.ip; 147} 148 149int 150iplist_setsrc(struct iplist *list, const char *src) 151{ 152 strncpy(list->src, src, sizeof(list->src)-1); 153 list->src[sizeof(list->src)-1] = '\0'; 154 list->cur.srcptr = list->src; 155 do { 156 if (iplist_nextrange(list)) 157 list->nItems += list->cur.nItems; 158 else 159 return 0; 160 } while (list->cur.srcptr != list->src); 161 return 1; 162} 163 164void 165iplist_reset(struct iplist *list) 166{ 167 list->src[0] = '\0'; 168 list->nItems = 0; 169 list->cur.pos = -1; 170} 171 172struct in_addr 173iplist_setcurpos(struct iplist *list, int pos) 174{ 175 if (pos < 0 || pos >= list->nItems) { 176 list->cur.pos = -1; 177 list->cur.ip.s_addr = INADDR_ANY; 178 return list->cur.ip; 179 } 180 181 list->cur.srcptr = NULL; 182 list->cur.pos = 0; 183 while (1) { 184 iplist_nextrange(list); 185 if (pos < list->cur.nItems) { 186 if (pos) { 187 list->cur.srcitem = pos; 188 list->cur.pos += pos; 189 list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 190 } 191 break; 192 } 193 pos -= list->cur.nItems; 194 list->cur.pos += list->cur.nItems; 195 } 196 197 return list->cur.ip; 198} 199 200struct in_addr 201iplist_setrandpos(struct iplist *list) 202{ 203 randinit(); 204 return iplist_setcurpos(list, random() % list->nItems); 205} 206 207int 208iplist_ip2pos(struct iplist *list, struct in_addr ip) 209{ 210 struct iplist_cur cur; 211 int f, result; 212 213 result = -1; 214 memcpy(&cur, &list->cur, sizeof(cur)); 215 216 for (iplist_first(list), f = 0; f < list->nItems; f++) 217 if (iplist_next(list).s_addr == ip.s_addr) { 218 result = list->cur.pos; 219 break; 220 } 221 222 memcpy(&list->cur, &cur, sizeof(list->cur)); 223 return result; 224} 225