iplist.c revision 31690
131690Sbrian/* 231690Sbrian * $Id:$ 331690Sbrian */ 431690Sbrian 531690Sbrian#include <sys/types.h> 631690Sbrian#include <netinet/in.h> 731690Sbrian#include <arpa/inet.h> 831690Sbrian 931690Sbrian#include <stdlib.h> 1031690Sbrian#include <string.h> 1131690Sbrian 1231690Sbrian#include "command.h" 1331690Sbrian#include "mbuf.h" 1431690Sbrian#include "log.h" 1531690Sbrian#include "defs.h" 1631690Sbrian#include "iplist.h" 1731690Sbrian 1831690Sbrianstatic int 1931690Sbriando_inet_aton(const char *start, const char *end, struct in_addr *ip) 2031690Sbrian{ 2131690Sbrian static char ipstr[16]; 2231690Sbrian 2331690Sbrian if (end - start > 15) { 2431690Sbrian LogPrintf(LogWARN, "%.*s: Invalid IP address\n", end-start, start); 2531690Sbrian return 0; 2631690Sbrian } 2731690Sbrian strncpy(ipstr, start, end-start); 2831690Sbrian ipstr[end-start] = '\0'; 2931690Sbrian return inet_aton(ipstr, ip); 3031690Sbrian} 3131690Sbrian 3231690Sbrianstatic void 3331690Sbrianiplist_first(struct iplist *list) 3431690Sbrian{ 3531690Sbrian list->cur.pos = -1; 3631690Sbrian} 3731690Sbrian 3831690Sbrianstatic int 3931690Sbrianiplist_setrange(struct iplist *list, char *range) 4031690Sbrian{ 4131690Sbrian char *ptr, *to; 4231690Sbrian 4331690Sbrian if ((ptr = strpbrk(range, ",-")) == NULL) { 4431690Sbrian if (!inet_aton(range, &list->cur.ip)) 4531690Sbrian return 0; 4631690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 4731690Sbrian list->cur.nItems = 1; 4831690Sbrian } else { 4931690Sbrian if (!do_inet_aton(range, ptr, &list->cur.ip)) 5031690Sbrian return 0; 5131690Sbrian if (*ptr == ',') { 5231690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 5331690Sbrian list->cur.nItems = 1; 5431690Sbrian } else { 5531690Sbrian struct in_addr endip; 5631690Sbrian 5731690Sbrian to = ptr+1; 5831690Sbrian if ((ptr = strpbrk(to, ",-")) == NULL) 5931690Sbrian ptr = to + strlen(to); 6031690Sbrian if (*to == '-') 6131690Sbrian return 0; 6231690Sbrian if (!do_inet_aton(to, ptr, &endip)) 6331690Sbrian return 0; 6431690Sbrian list->cur.lstart = ntohl(list->cur.ip.s_addr); 6531690Sbrian list->cur.nItems = ntohl(endip.s_addr) - list->cur.lstart + 1; 6631690Sbrian if (list->cur.nItems < 1) 6731690Sbrian return 0; 6831690Sbrian } 6931690Sbrian } 7031690Sbrian list->cur.srcitem = 0; 7131690Sbrian list->cur.srcptr = range; 7231690Sbrian return 1; 7331690Sbrian} 7431690Sbrian 7531690Sbrianstatic int 7631690Sbrianiplist_nextrange(struct iplist *list) 7731690Sbrian{ 7831690Sbrian char *ptr, *to, *end; 7931690Sbrian 8031690Sbrian ptr = list->cur.srcptr; 8131690Sbrian if (ptr != NULL && (ptr = strchr(ptr, ',')) != NULL) 8231690Sbrian ptr++; 8331690Sbrian else 8431690Sbrian ptr = list->src; 8531690Sbrian 8631690Sbrian while (*ptr != '\0' && !iplist_setrange(list, ptr)) { 8731690Sbrian if ((end = strchr(ptr, ',')) == NULL) 8831690Sbrian end = ptr + strlen(ptr); 8931690Sbrian if (end == ptr) 9031690Sbrian return 0; 9131690Sbrian LogPrintf(LogWARN, "%.*s: Invalid IP range (skipping)\n", end - ptr, ptr); 9231690Sbrian to = ptr; 9331690Sbrian do 9431690Sbrian *to = *end++; 9531690Sbrian while (*to++ != '\0'); 9631690Sbrian if (*ptr == '\0') 9731690Sbrian ptr = list->src; 9831690Sbrian } 9931690Sbrian 10031690Sbrian return 1; 10131690Sbrian} 10231690Sbrian 10331690Sbrianstruct in_addr 10431690Sbrianiplist_next(struct iplist *list) 10531690Sbrian{ 10631690Sbrian if (list->cur.pos == -1) { 10731690Sbrian list->cur.srcptr = NULL; 10831690Sbrian if (!iplist_nextrange(list)) { 10931690Sbrian list->cur.ip.s_addr = INADDR_ANY; 11031690Sbrian return list->cur.ip; 11131690Sbrian } 11231690Sbrian } else if (++list->cur.srcitem == list->cur.nItems) { 11331690Sbrian if (!iplist_nextrange(list)) { 11431690Sbrian list->cur.ip.s_addr = INADDR_ANY; 11531690Sbrian list->cur.pos = -1; 11631690Sbrian return list->cur.ip; 11731690Sbrian } 11831690Sbrian } else 11931690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 12031690Sbrian list->cur.pos++; 12131690Sbrian 12231690Sbrian return list->cur.ip; 12331690Sbrian} 12431690Sbrian 12531690Sbrianint 12631690Sbrianiplist_setsrc(struct iplist *list, const char *src) 12731690Sbrian{ 12831690Sbrian strncpy(list->src, src, sizeof(list->src)); 12931690Sbrian list->src[sizeof(list->src)-1] = '\0'; 13031690Sbrian list->cur.srcptr = list->src; 13131690Sbrian do { 13231690Sbrian if (iplist_nextrange(list)) 13331690Sbrian list->nItems += list->cur.nItems; 13431690Sbrian else 13531690Sbrian return 0; 13631690Sbrian } while (list->cur.srcptr != list->src); 13731690Sbrian return 1; 13831690Sbrian} 13931690Sbrian 14031690Sbrianvoid 14131690Sbrianiplist_reset(struct iplist *list) 14231690Sbrian{ 14331690Sbrian list->src[0] = '\0'; 14431690Sbrian list->nItems = 0; 14531690Sbrian list->cur.pos = -1; 14631690Sbrian} 14731690Sbrian 14831690Sbrianstruct in_addr 14931690Sbrianiplist_setcurpos(struct iplist *list, int pos) 15031690Sbrian{ 15131690Sbrian if (pos < 0 || pos >= list->nItems) { 15231690Sbrian list->cur.pos = -1; 15331690Sbrian list->cur.ip.s_addr = INADDR_ANY; 15431690Sbrian return list->cur.ip; 15531690Sbrian } 15631690Sbrian 15731690Sbrian list->cur.srcptr = NULL; 15831690Sbrian list->cur.pos = 0; 15931690Sbrian while (1) { 16031690Sbrian iplist_nextrange(list); 16131690Sbrian if (pos < list->cur.nItems) { 16231690Sbrian if (pos) { 16331690Sbrian list->cur.srcitem = pos; 16431690Sbrian list->cur.pos += pos; 16531690Sbrian list->cur.ip.s_addr = htonl(list->cur.lstart + list->cur.srcitem); 16631690Sbrian } 16731690Sbrian break; 16831690Sbrian } 16931690Sbrian pos -= list->cur.nItems; 17031690Sbrian list->cur.pos += list->cur.nItems; 17131690Sbrian } 17231690Sbrian 17331690Sbrian return list->cur.ip; 17431690Sbrian} 17531690Sbrian 17631690Sbrianstruct in_addr 17731690Sbrianiplist_setrandpos(struct iplist *list) 17831690Sbrian{ 17931690Sbrian randinit(); 18031690Sbrian return iplist_setcurpos(list, random() % list->nItems); 18131690Sbrian} 18231690Sbrian 18331690Sbrianint 18431690Sbrianiplist_ip2pos(struct iplist *list, struct in_addr ip) 18531690Sbrian{ 18631690Sbrian struct iplist_cur cur; 18731690Sbrian int f, result; 18831690Sbrian 18931690Sbrian result = -1; 19031690Sbrian memcpy(&cur, &list->cur, sizeof(cur)); 19131690Sbrian 19231690Sbrian for (iplist_first(list), f = 0; f < list->nItems; f++) 19331690Sbrian if (iplist_next(list).s_addr == ip.s_addr) { 19431690Sbrian result = list->cur.pos; 19531690Sbrian break; 19631690Sbrian } 19731690Sbrian 19831690Sbrian memcpy(&list->cur, &cur, sizeof(list->cur)); 19931690Sbrian return result; 20031690Sbrian} 201