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.6 1998/06/15 19:06:47 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 "log.h" 37 #include "defs.h" 38 #include "iplist.h" 39 40 static int 41 do_inet_aton(const char *start, const char *end, struct in_addr *ip) 42 { 43 char ipstr[16]; 44 45 if (end - start > 15) { 46 log_Printf(LogWARN, "%.*s: Invalid IP address\n", (int)(end-start), start); 47 return 0; 48 } 49 strncpy(ipstr, start, end-start); 50 ipstr[end-start] = '\0'; 51 return inet_aton(ipstr, ip); 52 } 53 54 static void 55 iplist_first(struct iplist *list) 56 { 57 list->cur.pos = -1; 58 } 59 60 static int 61 iplist_setrange(struct iplist *list, char *range) 62 { 63 char *ptr, *to; 64 65 if ((ptr = strpbrk(range, ",-")) == NULL) { 66 if (!inet_aton(range, &list->cur.ip)) 67 return 0; 68 list->cur.lstart = ntohl(list->cur.ip.s_addr); 69 list->cur.nItems = 1; 70 } else { 71 if (!do_inet_aton(range, ptr, &list->cur.ip)) 72 return 0; 73 if (*ptr == ',') { 74 list->cur.lstart = ntohl(list->cur.ip.s_addr); 75 list->cur.nItems = 1; 76 } else { 77 struct in_addr endip; 78 79 to = ptr+1; 80 if ((ptr = strpbrk(to, ",-")) == NULL) 81 ptr = to + strlen(to); 82 if (*to == '-') 83 return 0; 84 if (!do_inet_aton(to, ptr, &endip)) 85 return 0; 86 list->cur.lstart = ntohl(list->cur.ip.s_addr); 87 list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 88 if (list->cur.nItems < 1) 89 return 0; 90 } 91 } 92 list->cur.srcitem = 0; 93 list->cur.srcptr = range; 94 return 1; 95 } 96 97 static int 98 iplist_nextrange(struct iplist *list) 99 { 100 char *ptr, *to, *end; 101 102 ptr = list->cur.srcptr; 103 if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 104 ptr++; 105 else 106 ptr = list->src; 107 108 while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 109 if ((end = strchr(ptr, ',')) == NULL) 110 end = ptr + strlen(ptr); 111 if (end == ptr) 112 return 0; 113 log_Printf(LogWARN, "%.*s: Invalid IP range (skipping)\n", 114 (int)(end - ptr), ptr); 115 to = ptr; 116 do 117 *to = *end++; 118 while (*to++ != '\0'); 119 if (*ptr == '\0') 120 ptr = list->src; 121 } 122 123 return 1; 124 } 125 126 struct in_addr 127 iplist_next(struct iplist *list) 128 { 129 if (list->cur.pos == -1) { 130 list->cur.srcptr = NULL; 131 if (!iplist_nextrange(list)) { 132 list->cur.ip.s_addr = INADDR_ANY; 133 return list->cur.ip; 134 } 135 } else if (++list->cur.srcitem == list->cur.nItems) { 136 if (!iplist_nextrange(list)) { 137 list->cur.ip.s_addr = INADDR_ANY; 138 list->cur.pos = -1; 139 return list->cur.ip; 140 } 141 } else 142 list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 143 list->cur.pos++; 144 145 return list->cur.ip; 146 } 147 148 int 149 iplist_setsrc(struct iplist *list, const char *src) 150 { 151 strncpy(list->src, src, sizeof list->src - 1); 152 list->src[sizeof list->src - 1] = '\0'; 153 list->cur.srcptr = list->src; 154 do { 155 if (iplist_nextrange(list)) 156 list->nItems += list->cur.nItems; 157 else 158 return 0; 159 } while (list->cur.srcptr != list->src); 160 return 1; 161 } 162 163 void 164 iplist_reset(struct iplist *list) 165 { 166 list->src[0] = '\0'; 167 list->nItems = 0; 168 list->cur.pos = -1; 169 } 170 171 struct in_addr 172 iplist_setcurpos(struct iplist *list, long pos) 173 { 174 if (pos < 0 || pos >= list->nItems) { 175 list->cur.pos = -1; 176 list->cur.ip.s_addr = INADDR_ANY; 177 return list->cur.ip; 178 } 179 180 list->cur.srcptr = NULL; 181 list->cur.pos = 0; 182 while (1) { 183 iplist_nextrange(list); 184 if (pos < list->cur.nItems) { 185 if (pos) { 186 list->cur.srcitem = pos; 187 list->cur.pos += pos; 188 list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 189 } 190 break; 191 } 192 pos -= list->cur.nItems; 193 list->cur.pos += list->cur.nItems; 194 } 195 196 return list->cur.ip; 197 } 198 199 struct in_addr 200 iplist_setrandpos(struct iplist *list) 201 { 202 randinit(); 203 return iplist_setcurpos(list, random() % list->nItems); 204 } 205 206 int 207 iplist_ip2pos(struct iplist *list, struct in_addr ip) 208 { 209 struct iplist_cur cur; 210 u_long f; 211 int 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