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