1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
|
/*
* 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.12 2004/07/10 07:43:47 mcr Exp $
*/
#include "openswan.h"
#ifndef ABITS
#define ABITS 32 /* bits in an IPv4 address */
#endif
/*
- 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;
}
|