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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
/*
* comparisons
* Copyright (C) 2000 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: sameaddr.c,v 1.10.14.1 2005/11/17 01:44:12 mcr Exp $
*/
#include "internal.h"
#include "openswan.h"
#include "constants.h"
static int samenbits(const ip_address *a, const ip_address *b, int n);
/*
- addrcmp - compare two addresses
* Caution, the order of the tests is subtle: doing type test before
* size test can yield cases where a<b, b<c, but a>c.
*/
int /* like memcmp */
addrcmp(a, b)
const ip_address *a;
const ip_address *b;
{
int at = addrtypeof(a);
int bt = addrtypeof(b);
const unsigned char *ap;
const unsigned char *bp;
size_t as = addrbytesptr(a, &ap);
size_t bs = addrbytesptr(b, &bp);
size_t n = (as < bs) ? as : bs; /* min(as, bs) */
int c = memcmp(ap, bp, n);
if (c != 0) /* bytes differ */
return (c < 0) ? -1 : 1;
if (as != bs) /* comparison incomplete: lexical order */
return (as < bs) ? -1 : 1;
if (at != bt) /* bytes same but not same type: break tie */
return (at < bt) ? -1 : 1;
return 0;
}
/*
- sameaddr - are two addresses the same?
*/
bool
sameaddr(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrcmp(a, b) == 0) ? 1 : 0;
}
/*
- samesubnet - are two subnets the same?
*/
bool
samesubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (!sameaddr(&a->addr, &b->addr)) /* also does type check */
return 0;
if (a->maskbits != b->maskbits)
return 0;
return 1;
}
/*
- subnetishost - is a subnet in fact a single host?
*/
bool
subnetishost(a)
const ip_subnet *a;
{
return (a->maskbits == addrlenof(&a->addr)*8) ? 1 : 0;
}
/*
- samesaid - are two SA IDs the same?
*/
bool
samesaid(a, b)
const ip_said *a;
const ip_said *b;
{
if (a->spi != b->spi) /* test first, most likely to be different */
return 0;
if (!sameaddr(&a->dst, &b->dst))
return 0;
if (a->proto != b->proto)
return 0;
return 1;
}
/*
- sameaddrtype - do two addresses have the same type?
*/
bool
sameaddrtype(a, b)
const ip_address *a;
const ip_address *b;
{
return (addrtypeof(a) == addrtypeof(b)) ? 1 : 0;
}
/*
- samesubnettype - do two subnets have the same type?
*/
bool
samesubnettype(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
return (subnettypeof(a) == subnettypeof(b)) ? 1 : 0;
}
/*
- addrinsubnet - is this address in this subnet?
*/
bool
addrinsubnet(a, s)
const ip_address *a;
const ip_subnet *s;
{
if (addrtypeof(a) != subnettypeof(s))
return 0;
if (!samenbits(a, &s->addr, s->maskbits))
return 0;
return 1;
}
/*
- subnetinsubnet - is one subnet within another?
*/
bool
subnetinsubnet(a, b)
const ip_subnet *a;
const ip_subnet *b;
{
if (subnettypeof(a) != subnettypeof(b))
return 0;
if (a->maskbits < b->maskbits) /* a is bigger than b */
return 0;
if (!samenbits(&a->addr, &b->addr, b->maskbits))
return 0;
return 1;
}
/*
- samenbits - do two addresses have the same first n bits?
*/
static bool
samenbits(a, b, nbits)
const ip_address *a;
const ip_address *b;
int nbits;
{
const unsigned char *ap;
const unsigned char *bp;
size_t n;
int m;
if (addrtypeof(a) != addrtypeof(b))
return 0; /* arbitrary */
n = addrbytesptr(a, &ap);
if (n == 0)
return 0; /* arbitrary */
(void) addrbytesptr(b, &bp);
if (nbits > n*8)
return 0; /* "can't happen" */
for (; nbits >= 8 && *ap == *bp; nbits -= 8, ap++, bp++)
continue;
if (nbits >= 8)
return 0;
if (nbits > 0) { /* partial byte */
m = ~(0xff >> nbits);
if ((*ap & m) != (*bp & m))
return 0;
}
return 1;
}
|