OSDN Git Service

2013.10.24
[uclinux-h8/uClinux-dist.git] / freeswan / lib / goodmask.c
1 /*
2  * minor utilities for subnet-mask manipulation
3  * Copyright (C) 1998, 1999  Henry Spencer.
4  * 
5  * This library is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Library General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.  See <http://www.fsf.org/copyleft/lgpl.txt>.
9  * 
10  * This library is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
13  * License for more details.
14  *
15  * RCSID $Id: goodmask.c,v 1.7 2000/02/16 18:54:24 henry Exp $
16  */
17 #include "internal.h"
18 #include "freeswan.h"
19
20 /*
21  - goodmask - is this a good (^1*0*$) subnet mask?
22  * You are not expected to understand this.  See Henry S. Warren Jr, 
23  * "Functions realizable with word-parallel logical and two's-complement
24  * addition instructions", CACM 20.6 (June 1977), p.439.
25  */
26 int                             /* predicate */
27 goodmask(mask)
28 struct in_addr mask;
29 {
30         unsigned long x = ntohl(mask.s_addr);
31         /* clear rightmost contiguous string of 1-bits */
32 #       define  CRCS1B(x)       (((x|(x-1))+1)&x)
33 #       define  TOPBIT          (1UL << 31)
34
35         /* either zero, or has one string of 1-bits which is left-justified */
36         if (x == 0 || (CRCS1B(x) == 0 && (x&TOPBIT)))
37                 return 1;
38         return 0;
39 }
40
41 /*
42  - masktobits - how many bits in this mask?
43  * The algorithm is essentially a binary search, but highly optimized
44  * for this particular task.
45  */
46 int                             /* -1 means !goodmask() */
47 masktobits(mask)
48 struct in_addr mask;
49 {
50         unsigned long m = ntohl(mask.s_addr);
51         int masklen;
52
53         if (!goodmask(mask))
54                 return -1;
55
56         if (m&0x00000001UL)
57                 return 32;
58         masklen = 0;
59         if (m&(0x0000ffffUL<<1)) {      /* <<1 for 1-origin numbering */
60                 masklen |= 0x10;
61                 m <<= 16;
62         }
63         if (m&(0x00ff0000UL<<1)) {
64                 masklen |= 0x08;
65                 m <<= 8;
66         }
67         if (m&(0x0f000000UL<<1)) {
68                 masklen |= 0x04;
69                 m <<= 4;
70         }
71         if (m&(0x30000000UL<<1)) {
72                 masklen |= 0x02;
73                 m <<= 2;
74         }
75         if (m&(0x40000000UL<<1))
76                 masklen |= 0x01;
77
78         return masklen;
79 }
80
81 /*
82  - bitstomask - return a mask with this many high bits on
83  */
84 struct in_addr
85 bitstomask(n)
86 int n;
87 {
88         struct in_addr result;
89
90         if (n > 0 && n <= ABITS)
91                 result.s_addr = htonl(~((1UL << (ABITS - n)) - 1));
92         else if (n == 0)
93                 result.s_addr = 0;
94         else
95                 result.s_addr = 0;      /* best error report we can do */
96         return result;
97 }