diff options
Diffstat (limited to 'src/libfreeswan/goodmask.c')
-rw-r--r-- | src/libfreeswan/goodmask.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/src/libfreeswan/goodmask.c b/src/libfreeswan/goodmask.c new file mode 100644 index 000000000..fe7a42335 --- /dev/null +++ b/src/libfreeswan/goodmask.c @@ -0,0 +1,97 @@ +/* + * minor utilities for subnet-mask manipulation + * Copyright (C) 1998, 1999 Henry Spencer. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>. + * + * This library is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + * License for more details. + * + * RCSID $Id: goodmask.c,v 1.1 2004/03/15 20:35:26 as Exp $ + */ +#include "internal.h" +#include "freeswan.h" + +/* + - goodmask - is this a good (^1*0*$) subnet mask? + * You are not expected to understand this. See Henry S. Warren Jr, + * "Functions realizable with word-parallel logical and two's-complement + * addition instructions", CACM 20.6 (June 1977), p.439. + */ +int /* predicate */ +goodmask(mask) +struct in_addr mask; +{ + unsigned long x = ntohl(mask.s_addr); + /* clear rightmost contiguous string of 1-bits */ +# define CRCS1B(x) (((x|(x-1))+1)&x) +# define TOPBIT (1UL << 31) + + /* either zero, or has one string of 1-bits which is left-justified */ + if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT))) + return 1; + return 0; +} + +/* + - masktobits - how many bits in this mask? + * The algorithm is essentially a binary search, but highly optimized + * for this particular task. + */ +int /* -1 means !goodmask() */ +masktobits(mask) +struct in_addr mask; +{ + unsigned long m = ntohl(mask.s_addr); + int masklen; + + if (!goodmask(mask)) + return -1; + + if (m&0x00000001UL) + return 32; + masklen = 0; + if (m&(0x0000ffffUL<<1)) { /* <<1 for 1-origin numbering */ + masklen |= 0x10; + m <<= 16; + } + if (m&(0x00ff0000UL<<1)) { + masklen |= 0x08; + m <<= 8; + } + if (m&(0x0f000000UL<<1)) { + masklen |= 0x04; + m <<= 4; + } + if (m&(0x30000000UL<<1)) { + masklen |= 0x02; + m <<= 2; + } + if (m&(0x40000000UL<<1)) + masklen |= 0x01; + + return masklen; +} + +/* + - bitstomask - return a mask with this many high bits on + */ +struct in_addr +bitstomask(n) +int n; +{ + struct in_addr result; + + if (n > 0 && n <= ABITS) + result.s_addr = htonl(~((1UL << (ABITS - n)) - 1)); + else if (n == 0) + result.s_addr = 0; + else + result.s_addr = 0; /* best error report we can do */ + return result; +} |