1/* $NetBSD: alist_new.c,v 1.1.1.2 2012/07/22 13:44:38 darrenr Exp $ */ 2 3/* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * Id: alist_new.c,v 1.1.1.2 2012/07/22 13:44:38 darrenr Exp $ 9 */ 10 11#include "ipf.h" 12#include <ctype.h> 13 14alist_t * 15alist_new(int family, char *host) 16{ 17 int a, b, c, d, bits; 18 char *slash; 19 alist_t *al; 20 u_int mask; 21 22 if (family == AF_UNSPEC) { 23 if (strchr(host, ':') != NULL) 24 family = AF_INET6; 25 else 26 family = AF_INET; 27 } 28 if (family != AF_INET && family != AF_INET6) 29 return NULL; 30 31 al = calloc(1, sizeof(*al)); 32 if (al == NULL) { 33 fprintf(stderr, "alist_new out of memory\n"); 34 return NULL; 35 } 36 37 while (ISSPACE(*host)) 38 host++; 39 40 if (*host == '!') { 41 al->al_not = 1; 42 host++; 43 while (ISSPACE(*host)) 44 host++; 45 } 46 47 bits = -1; 48 slash = strchr(host, '/'); 49 if (slash != NULL) { 50 *slash = '\0'; 51 bits = atoi(slash + 1); 52 } 53 54 if (family == AF_INET) { 55 if (bits > 32) 56 goto bad; 57 58 a = b = c = d = -1; 59 sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d); 60 61 if (bits > 0 && bits < 33) { 62 mask = 0xffffffff << (32 - bits); 63 } else if (b == -1) { 64 mask = 0xff000000; 65 b = c = d = 0; 66 } else if (c == -1) { 67 mask = 0xffff0000; 68 c = d = 0; 69 } else if (d == -1) { 70 mask = 0xffffff00; 71 d = 0; 72 } else { 73 mask = 0xffffffff; 74 } 75 al->al_mask = htonl(mask); 76 } else { 77 if (bits > 128) 78 goto bad; 79 fill6bits(bits, al->al_i6mask.i6); 80 } 81 82 if (gethost(family, host, &al->al_i6addr) == -1) { 83 if (slash != NULL) 84 *slash = '/'; 85 fprintf(stderr, "Cannot parse hostname\n"); 86 goto bad; 87 } 88 al->al_family = family; 89 if (slash != NULL) 90 *slash = '/'; 91 return al; 92bad: 93 free(al); 94 return NULL; 95} 96