Annotation of embedaddon/bird/lib/ip.h, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Internet Routing Daemon -- The Internet Protocol
! 3: *
! 4: * (c) 1998 Martin Mares <mj@ucw.cz>
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #ifndef _BIRD_IP_H_
! 10: #define _BIRD_IP_H_
! 11:
! 12: #include "lib/endian.h"
! 13: #include "lib/string.h"
! 14: #include "lib/bitops.h"
! 15: #include "lib/unaligned.h"
! 16:
! 17:
! 18: #define IP4_ALL_NODES ipa_build4(224, 0, 0, 1)
! 19: #define IP4_ALL_ROUTERS ipa_build4(224, 0, 0, 2)
! 20: #define IP4_OSPF_ALL_ROUTERS ipa_build4(224, 0, 0, 5)
! 21: #define IP4_OSPF_DES_ROUTERS ipa_build4(224, 0, 0, 6)
! 22: #define IP4_RIP_ROUTERS ipa_build4(224, 0, 0, 9)
! 23:
! 24: #define IP6_ALL_NODES ipa_build6(0xFF020000, 0, 0, 1)
! 25: #define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2)
! 26: #define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
! 27: #define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
! 28: #define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9)
! 29: #define IP6_BABEL_ROUTERS ipa_build6(0xFF020000, 0, 0, 0x00010006)
! 30:
! 31: #define IP4_NONE _MI4(0)
! 32: #define IP6_NONE _MI6(0,0,0,0)
! 33:
! 34: #define IP4_MIN_MTU 576
! 35: #define IP6_MIN_MTU 1280
! 36:
! 37: #define IP_PREC_INTERNET_CONTROL 0xc0
! 38:
! 39: #define IP4_HEADER_LENGTH 20
! 40: #define IP6_HEADER_LENGTH 40
! 41: #define UDP_HEADER_LENGTH 8
! 42:
! 43:
! 44: #ifdef IPV6
! 45: #define MAX_PREFIX_LENGTH 128
! 46: #define BITS_PER_IP_ADDRESS 128
! 47: #define STD_ADDRESS_P_LENGTH 39
! 48: #define SIZE_OF_IP_HEADER 40
! 49: #else
! 50: #define MAX_PREFIX_LENGTH 32
! 51: #define BITS_PER_IP_ADDRESS 32
! 52: #define STD_ADDRESS_P_LENGTH 15
! 53: #define SIZE_OF_IP_HEADER 24
! 54: #endif
! 55:
! 56:
! 57: #ifdef DEBUGGING
! 58:
! 59: typedef struct ip4_addr {
! 60: u32 addr;
! 61: } ip4_addr;
! 62:
! 63: #define _MI4(x) ((struct ip4_addr) { x })
! 64: #define _I(x) (x).addr
! 65:
! 66: #else
! 67:
! 68: typedef u32 ip4_addr;
! 69:
! 70: #define _MI4(x) (x)
! 71: #define _I(x) (x)
! 72:
! 73: #endif
! 74:
! 75:
! 76: typedef struct ip6_addr {
! 77: u32 addr[4];
! 78: } ip6_addr;
! 79:
! 80: #define _MI6(a,b,c,d) ((struct ip6_addr) {{ a, b, c, d }})
! 81: #define _I0(a) ((a).addr[0])
! 82: #define _I1(a) ((a).addr[1])
! 83: #define _I2(a) ((a).addr[2])
! 84: #define _I3(a) ((a).addr[3])
! 85:
! 86:
! 87: #ifdef IPV6
! 88:
! 89: /* Structure ip_addr may contain both IPv4 and IPv6 addresses */
! 90: typedef ip6_addr ip_addr;
! 91: #define IPA_NONE IP6_NONE
! 92:
! 93: #define ipa_from_ip4(x) _MI6(0,0,0xffff,_I(x))
! 94: #define ipa_from_ip6(x) x
! 95: #define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
! 96:
! 97: #define ipa_to_ip4(x) _MI4(_I3(x))
! 98: #define ipa_to_ip6(x) x
! 99: #define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
! 100:
! 101: #define ipa_is_ip4(a) ip6_is_v4mapped(a)
! 102:
! 103: #else
! 104:
! 105: /* Provisionary ip_addr definition same as ip4_addr */
! 106: typedef ip4_addr ip_addr;
! 107: #define IPA_NONE IP4_NONE
! 108:
! 109: #define ipa_from_ip4(x) x
! 110: #define ipa_from_ip6(x) IPA_NONE
! 111: #define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
! 112:
! 113: #define ipa_to_ip4(x) x
! 114: #define ipa_to_ip6(x) IP6_NONE
! 115: #define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
! 116:
! 117: #define ipa_is_ip4(a) 1
! 118:
! 119: #endif
! 120:
! 121:
! 122: /*
! 123: * Public constructors
! 124: */
! 125:
! 126: #define ip4_from_u32(x) _MI4(x)
! 127: #define ip4_to_u32(x) _I(x)
! 128:
! 129: #define ip4_build(a,b,c,d) _MI4(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
! 130: #define ip6_build(a,b,c,d) _MI6(a,b,c,d)
! 131:
! 132: #define ipa_build4(a,b,c,d) ipa_from_ip4(ip4_build(a,b,c,d))
! 133: #define ipa_build6(a,b,c,d) ipa_from_ip6(ip6_build(a,b,c,d))
! 134:
! 135:
! 136: /*
! 137: * Basic algebraic functions
! 138: */
! 139:
! 140: static inline int ip4_equal(ip4_addr a, ip4_addr b)
! 141: { return _I(a) == _I(b); }
! 142:
! 143: static inline int ip4_zero(ip4_addr a)
! 144: { return _I(a) == 0; }
! 145:
! 146: static inline int ip4_nonzero(ip4_addr a)
! 147: { return _I(a) != 0; }
! 148:
! 149: static inline ip4_addr ip4_and(ip4_addr a, ip4_addr b)
! 150: { return _MI4(_I(a) & _I(b)); }
! 151:
! 152: static inline ip4_addr ip4_or(ip4_addr a, ip4_addr b)
! 153: { return _MI4(_I(a) | _I(b)); }
! 154:
! 155: static inline ip4_addr ip4_xor(ip4_addr a, ip4_addr b)
! 156: { return _MI4(_I(a) ^ _I(b)); }
! 157:
! 158: static inline ip4_addr ip4_not(ip4_addr a)
! 159: { return _MI4(~_I(a)); }
! 160:
! 161:
! 162: static inline int ip6_equal(ip6_addr a, ip6_addr b)
! 163: { return _I0(a) == _I0(b) && _I1(a) == _I1(b) && _I2(a) == _I2(b) && _I3(a) == _I3(b); }
! 164:
! 165: static inline int ip6_zero(ip6_addr a)
! 166: { return !_I0(a) && !_I1(a) && !_I2(a) && !_I3(a); }
! 167:
! 168: static inline int ip6_nonzero(ip6_addr a)
! 169: { return _I0(a) || _I1(a) || _I2(a) || _I3(a); }
! 170:
! 171: static inline ip6_addr ip6_and(ip6_addr a, ip6_addr b)
! 172: { return _MI6(_I0(a) & _I0(b), _I1(a) & _I1(b), _I2(a) & _I2(b), _I3(a) & _I3(b)); }
! 173:
! 174: static inline ip6_addr ip6_or(ip6_addr a, ip6_addr b)
! 175: { return _MI6(_I0(a) | _I0(b), _I1(a) | _I1(b), _I2(a) | _I2(b), _I3(a) | _I3(b)); }
! 176:
! 177: static inline ip6_addr ip6_xor(ip6_addr a, ip6_addr b)
! 178: { return _MI6(_I0(a) ^ _I0(b), _I1(a) ^ _I1(b), _I2(a) ^ _I2(b), _I3(a) ^ _I3(b)); }
! 179:
! 180: static inline ip6_addr ip6_not(ip6_addr a)
! 181: { return _MI6(~_I0(a), ~_I1(a), ~_I2(a), ~_I3(a)); }
! 182:
! 183:
! 184: #ifdef IPV6
! 185: #define ipa_equal(x,y) ip6_equal(x,y)
! 186: #define ipa_zero(x) ip6_zero(x)
! 187: #define ipa_nonzero(x) ip6_nonzero(x)
! 188: #define ipa_and(x,y) ip6_and(x,y)
! 189: #define ipa_or(x,y) ip6_or(x,y)
! 190: #define ipa_xor(x,y) ip6_xor(x,y)
! 191: #define ipa_not(x) ip6_not(x)
! 192: #else
! 193: #define ipa_equal(x,y) ip4_equal(x,y)
! 194: #define ipa_zero(x) ip4_zero(x)
! 195: #define ipa_nonzero(x) ip4_nonzero(x)
! 196: #define ipa_and(x,y) ip4_and(x,y)
! 197: #define ipa_or(x,y) ip4_or(x,y)
! 198: #define ipa_xor(x,y) ip4_xor(x,y)
! 199: #define ipa_not(x) ip4_not(x)
! 200: #endif
! 201:
! 202:
! 203:
! 204: #ifdef IPV6
! 205: /*
! 206: * A zero address is either a token for invalid/unused, or the prefix of default
! 207: * routes. These functions should be used in the second case, where both IPv4
! 208: * and IPv6 zero addresses should be checked.
! 209: */
! 210:
! 211: static inline int ipa_zero2(ip_addr a)
! 212: { return !_I0(a) && !_I1(a) && ((_I2(a) == 0) || (_I2(a) == 0xffff)) && !_I3(a); }
! 213:
! 214: static inline int ipa_nonzero2(ip_addr a)
! 215: { return _I0(a) || _I1(a) || ((_I2(a) != 0) && (_I2(a) != 0xffff)) || _I3(a); }
! 216:
! 217: #else
! 218: #define ipa_zero2(x) ip4_zero(x)
! 219: #define ipa_nonzero2(x) ip4_nonzero(x)
! 220: #endif
! 221:
! 222:
! 223: /*
! 224: * Hash and compare functions
! 225: */
! 226:
! 227: static inline uint ip4_hash(ip4_addr a)
! 228: {
! 229: /* Returns a 16-bit value */
! 230: u32 x = _I(a);
! 231: x ^= x >> 16;
! 232: x ^= x << 10;
! 233: return x & 0xffff;
! 234: }
! 235:
! 236: static inline u32 ip4_hash32(ip4_addr a)
! 237: {
! 238: /* Returns a 32-bit value, although low-order bits are not mixed */
! 239: u32 x = _I(a);
! 240: x ^= x << 16;
! 241: x ^= x << 12;
! 242: return x;
! 243: }
! 244:
! 245: static inline uint ip6_hash(ip6_addr a)
! 246: {
! 247: /* Returns a 16-bit hash key */
! 248: u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a);
! 249: return (x ^ (x >> 16) ^ (x >> 8)) & 0xffff;
! 250: }
! 251:
! 252: static inline u32 ip6_hash32(ip6_addr a)
! 253: {
! 254: /* Returns a 32-bit hash key, although low-order bits are not mixed */
! 255: u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a);
! 256: return x ^ (x << 16) ^ (x << 24);
! 257: }
! 258:
! 259: static inline int ip4_compare(ip4_addr a, ip4_addr b)
! 260: { return (_I(a) > _I(b)) - (_I(a) < _I(b)); }
! 261:
! 262: int ip6_compare(ip6_addr a, ip6_addr b);
! 263:
! 264:
! 265: #ifdef IPV6
! 266: #define ipa_hash(x) ip6_hash(x)
! 267: #define ipa_hash32(x) ip6_hash32(x)
! 268: #define ipa_compare(x,y) ip6_compare(x,y)
! 269: #else
! 270: #define ipa_hash(x) ip4_hash(x)
! 271: #define ipa_hash32(x) ip4_hash32(x)
! 272: #define ipa_compare(x,y) ip4_compare(x,y)
! 273: #endif
! 274:
! 275:
! 276: /*
! 277: * IP address classification
! 278: */
! 279:
! 280: /* Address class */
! 281: #define IADDR_INVALID -1
! 282: #define IADDR_SCOPE_MASK 0xfff
! 283: #define IADDR_HOST 0x1000
! 284: #define IADDR_BROADCAST 0x2000
! 285: #define IADDR_MULTICAST 0x4000
! 286:
! 287: /* Address scope */
! 288: #define SCOPE_HOST 0
! 289: #define SCOPE_LINK 1
! 290: #define SCOPE_SITE 2
! 291: #define SCOPE_ORGANIZATION 3
! 292: #define SCOPE_UNIVERSE 4
! 293: #define SCOPE_UNDEFINED 5
! 294:
! 295: int ip4_classify(ip4_addr ad);
! 296: int ip6_classify(ip6_addr *a);
! 297:
! 298: static inline int ip6_is_link_local(ip6_addr a)
! 299: { return (_I0(a) & 0xffc00000) == 0xfe800000; }
! 300:
! 301: static inline int ip6_is_v4mapped(ip6_addr a)
! 302: { return _I0(a) == 0 && _I1(a) == 0 && _I2(a) == 0xffff; }
! 303:
! 304: #ifdef IPV6
! 305: #define ipa_classify(x) ip6_classify(&(x))
! 306: #define ipa_is_link_local(x) ip6_is_link_local(x)
! 307: #else
! 308: #define ipa_classify(x) ip4_classify(x)
! 309: #define ipa_is_link_local(x) 0
! 310: #endif
! 311:
! 312: static inline int ipa_classify_net(ip_addr a)
! 313: { return ipa_zero2(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); }
! 314:
! 315:
! 316: /*
! 317: * Miscellaneous IP prefix manipulation
! 318: */
! 319:
! 320: static inline ip4_addr ip4_mkmask(uint n)
! 321: { return _MI4(u32_mkmask(n)); }
! 322:
! 323: static inline int ip4_masklen(ip4_addr a)
! 324: { return u32_masklen(_I(a)); }
! 325:
! 326: ip6_addr ip6_mkmask(uint n);
! 327: int ip6_masklen(ip6_addr *a);
! 328:
! 329: /* ipX_pxlen() requires that x != y */
! 330: static inline uint ip4_pxlen(ip4_addr a, ip4_addr b)
! 331: { return 31 - u32_log2(_I(a) ^ _I(b)); }
! 332:
! 333: static inline uint ip6_pxlen(ip6_addr a, ip6_addr b)
! 334: {
! 335: int i = 0;
! 336: i += (a.addr[i] == b.addr[i]);
! 337: i += (a.addr[i] == b.addr[i]);
! 338: i += (a.addr[i] == b.addr[i]);
! 339: i += (a.addr[i] == b.addr[i]);
! 340: return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
! 341: }
! 342:
! 343: static inline u32 ip4_getbit(ip4_addr a, uint pos)
! 344: { return _I(a) & (0x80000000 >> pos); }
! 345:
! 346: static inline u32 ip6_getbit(ip6_addr a, uint pos)
! 347: { return a.addr[pos / 32] & (0x80000000 >> (pos % 32)); }
! 348:
! 349: static inline ip4_addr ip4_opposite_m1(ip4_addr a)
! 350: { return _MI4(_I(a) ^ 1); }
! 351:
! 352: static inline ip4_addr ip4_opposite_m2(ip4_addr a)
! 353: { return _MI4(_I(a) ^ 3); }
! 354:
! 355: static inline ip6_addr ip6_opposite_m1(ip6_addr a)
! 356: { return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 1); }
! 357:
! 358: static inline ip6_addr ip6_opposite_m2(ip6_addr a)
! 359: { return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 3); }
! 360:
! 361: ip4_addr ip4_class_mask(ip4_addr ad);
! 362:
! 363: #ifdef IPV6
! 364: #define ipa_mkmask(x) ip6_mkmask(x)
! 365: #define ipa_masklen(x) ip6_masklen(&x)
! 366: #define ipa_pxlen(x,y) ip6_pxlen(x,y)
! 367: #define ipa_getbit(x,n) ip6_getbit(x,n)
! 368: #define ipa_opposite_m1(x) ip6_opposite_m1(x)
! 369: #define ipa_opposite_m2(x) ip6_opposite_m2(x)
! 370: #else
! 371: #define ipa_mkmask(x) ip4_mkmask(x)
! 372: #define ipa_masklen(x) ip4_masklen(x)
! 373: #define ipa_pxlen(x,y) ip4_pxlen(x,y)
! 374: #define ipa_getbit(x,n) ip4_getbit(x,n)
! 375: #define ipa_opposite_m1(x) ip4_opposite_m1(x)
! 376: #define ipa_opposite_m2(x) ip4_opposite_m2(x)
! 377: #endif
! 378:
! 379:
! 380: /*
! 381: * Host/network order conversions
! 382: */
! 383:
! 384: static inline ip4_addr ip4_hton(ip4_addr a)
! 385: { return _MI4(htonl(_I(a))); }
! 386:
! 387: static inline ip4_addr ip4_ntoh(ip4_addr a)
! 388: { return _MI4(ntohl(_I(a))); }
! 389:
! 390: static inline ip6_addr ip6_hton(ip6_addr a)
! 391: { return _MI6(htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a))); }
! 392:
! 393: static inline ip6_addr ip6_ntoh(ip6_addr a)
! 394: { return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
! 395:
! 396: #ifdef IPV6
! 397: #define ipa_hton(x) x = ip6_hton(x)
! 398: #define ipa_ntoh(x) x = ip6_ntoh(x)
! 399: #else
! 400: #define ipa_hton(x) x = ip4_hton(x)
! 401: #define ipa_ntoh(x) x = ip4_ntoh(x)
! 402: #endif
! 403:
! 404:
! 405: /*
! 406: * Unaligned data access (in network order)
! 407: */
! 408:
! 409: static inline ip4_addr get_ip4(void *buf)
! 410: {
! 411: return _MI4(get_u32(buf));
! 412: }
! 413:
! 414: static inline ip6_addr get_ip6(void *buf)
! 415: {
! 416: ip6_addr a;
! 417: memcpy(&a, buf, 16);
! 418: return ip6_ntoh(a);
! 419: }
! 420:
! 421: static inline void * put_ip4(void *buf, ip4_addr a)
! 422: {
! 423: put_u32(buf, _I(a));
! 424: return buf+4;
! 425: }
! 426:
! 427: static inline void * put_ip6(void *buf, ip6_addr a)
! 428: {
! 429: a = ip6_hton(a);
! 430: memcpy(buf, &a, 16);
! 431: return buf+16;
! 432: }
! 433:
! 434: // XXXX these functions must be redesigned or removed
! 435: #ifdef IPV6
! 436: #define get_ipa(x) get_ip6(x)
! 437: #define put_ipa(x,y) put_ip6(x,y)
! 438: #else
! 439: #define get_ipa(x) get_ip4(x)
! 440: #define put_ipa(x,y) put_ip4(x,y)
! 441: #endif
! 442:
! 443:
! 444: /*
! 445: * Binary/text form conversions
! 446: */
! 447:
! 448: char *ip4_ntop(ip4_addr a, char *b);
! 449: char *ip6_ntop(ip6_addr a, char *b);
! 450:
! 451: static inline char * ip4_ntox(ip4_addr a, char *b)
! 452: { return b + bsprintf(b, "%08x", _I(a)); }
! 453:
! 454: static inline char * ip6_ntox(ip6_addr a, char *b)
! 455: { return b + bsprintf(b, "%08x.%08x.%08x.%08x", _I0(a), _I1(a), _I2(a), _I3(a)); }
! 456:
! 457: int ip4_pton(const char *a, ip4_addr *o);
! 458: int ip6_pton(const char *a, ip6_addr *o);
! 459:
! 460: // XXXX these functions must be redesigned or removed
! 461: #ifdef IPV6
! 462: #define ipa_ntop(x,y) ip6_ntop(x,y)
! 463: #define ipa_ntox(x,y) ip6_ntox(x,y)
! 464: #define ipa_pton(x,y) ip6_pton(x,y)
! 465: #else
! 466: #define ipa_ntop(x,y) ip4_ntop(x,y)
! 467: #define ipa_ntox(x,y) ip4_ntox(x,y)
! 468: #define ipa_pton(x,y) ip4_pton(x,y)
! 469: #endif
! 470:
! 471:
! 472: /*
! 473: * Miscellaneous
! 474: */
! 475:
! 476: // XXXX review this
! 477:
! 478: #define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
! 479: #define ipa_in_net(x,n,p) (ipa_zero(ipa_and(ipa_xor((n),(x)),ipa_mkmask(p))))
! 480: #define net_in_net(n1,l1,n2,l2) (((l1) >= (l2)) && (ipa_zero(ipa_and(ipa_xor((n1),(n2)),ipa_mkmask(l2)))))
! 481:
! 482: char *ip_scope_text(uint);
! 483:
! 484: struct prefix {
! 485: ip_addr addr;
! 486: uint len;
! 487: };
! 488:
! 489:
! 490: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>