Home | History | Annotate | Line # | Download | only in lib
      1 /*	$NetBSD: alist_new.c,v 1.2 2012/07/22 14:27:36 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 
     14 alist_t *
     15 alist_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;
     92 bad:
     93 	free(al);
     94 	return NULL;
     95 }
     96