modules/up/src/rpsl/rpsl/prefix.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. int2quad
  2. quad2int
  3. PrefixRange
  4. PrefixRange
  5. PrefixRange
  6. PrefixRange
  7. parse
  8. define
  9. makeMoreSpecific
  10. print
  11. valid
  12. compare
  13. contains
  14. get_mask
  15. get_text
  16. get_range
  17. get_text
  18. get_text
  19. Prefix
  20. IPAddr

//  $Id: prefix.cc,v 1.1.1.1 2000/03/10 16:32:24 engin Exp $
//
//  Copyright (c) 1994 by the University of Southern California
//  All rights reserved.
//
//  Permission to use, copy, modify, and distribute this software and its
//  documentation in source and binary forms for lawful non-commercial
//  purposes and without fee is hereby granted, provided that the above
//  copyright notice appear in all copies and that both the copyright
//  notice and this permission notice appear in supporting documentation,
//  and that any documentation, advertising materials, and other materials
//  related to such distribution and use acknowledge that the software was
//  developed by the University of Southern California, Information
//  Sciences Institute. The name of the USC may not be used to endorse or
//  promote products derived from this software without specific prior
//  written permission.
//
//  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
//  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
//  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
//  TITLE, AND NON-INFRINGEMENT.
//
//  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
//  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
//  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
//  OR PERFORMANCE OF THIS SOFTWARE.
//
//  Questions concerning this software should be directed to 
//  ratoolset@isi.edu.
//
//  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>

#include "config.h"
#include <cstdio>
#include <cstring>
#include <iostream.h>
#include "prefix.hh"

char PrefixRange::formattingbuffer[128];

char* int2quad(char *buffer, unsigned int i) {
/* [<][>][^][v][top][bottom][index][help] */
   sprintf(buffer, "%d.%d.%d.%d", 
           (i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8)  & 0xFF, i & 0xFF);
   return buffer;
}

unsigned int quad2int(char *quad) {
/* [<][>][^][v][top][bottom][index][help] */
   unsigned int i;
   unsigned int i1, i2, i3, i4;

   sscanf(quad, "%u.%u.%u.%u", &i1, &i2, &i3, &i4);
   i = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
   return i;
}

ostream& operator<<(ostream& stream, const PrefixRange& p) {
   stream << p.get_text();
   return stream;
}

/*
// Added const to PrefixRange& p by wlee@isi.edu
const ostream& operator<<(ostream& stream, const PrefixRange& p) {
  stream << p.get_text();
   return stream;
}
*/

PrefixRange::PrefixRange(void) : 
/* [<][>][^][v][top][bottom][index][help] */
  ipaddr(0), 
  length(0), 
  n(0), 
  m(0)
{
}

// Added by wlee@isi.edu
PrefixRange::PrefixRange(const PrefixRange &p) :
/* [<][>][^][v][top][bottom][index][help] */
  ipaddr(p.ipaddr),
  length(p.length),
  n(p.n),
  m(p.m)
{
}

PrefixRange::PrefixRange(unsigned int ipaddr, unsigned char length, 
/* [<][>][^][v][top][bottom][index][help] */
                 unsigned char n, unsigned char m) :
  ipaddr(ipaddr),
  length(length),
  n(n),
  m(m)
{
}

PrefixRange::PrefixRange(char *name) : 
/* [<][>][^][v][top][bottom][index][help] */
  ipaddr(0), 
  length(0), 
  n(0), 
  m(0)
{
  parse(name);
}

void PrefixRange::parse(char *name)
/* [<][>][^][v][top][bottom][index][help] */
{
  unsigned int i1, i2, i3, i4, uiLength = 0, uiN = 0, uiM = 0;
  unsigned int mask;
  char ch = ' ';

  char *p;
  if (strstr(name, "^+"))
    // Inclusive more specific operation
    sscanf(name, "%u.%u.%u.%u/%u^%c", &i1, &i2, &i3, &i4, &uiLength, &ch);
  else if (p = strstr(name, "^-"))
     sscanf(name, "%u.%u.%u.%u/%u^%c", &i1, &i2, &i3, &i4, &uiLength, &ch);
  else if (p = strchr(name, '-')) 
     sscanf(name, "%u.%u.%u.%u/%u^%u-%u", 
            &i1, &i2, &i3, &i4, &uiLength, &uiN, &uiM);
  else if (p = strchr(name, '^')) {
     sscanf(name, "%u.%u.%u.%u/%u^%u", 
            &i1, &i2, &i3, &i4, &uiLength, &uiN);
     uiM = uiN;
  } else
     sscanf(name, "%u.%u.%u.%u/%u", &i1, &i2, &i3, &i4, &uiLength);

  length = uiLength;
  n      = uiN;
  m      = uiM;

  switch (ch)
    {
    case '+':
      // inclusive more specifics operator
      n = length;
      m = 32;
      break;
    case '-':
      // exclusive more specifics operator
      n = length + 1;
      m = 32;
      break;
    default:
      if (n == 0) n = length;
      if (m == 0) m = n;
      break;
    }

  ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
  
  if (length == 0)
    mask = 0;
  else 
    mask = ~ (0u) << (32 - length);
  
  ipaddr &= mask;
}

void PrefixRange::define(unsigned int ipaddr, unsigned char length, 
/* [<][>][^][v][top][bottom][index][help] */
                     unsigned char n, unsigned char m)
{
  this->ipaddr = ipaddr;
  this->length = length;
  this->n      = n;
  this->m      = m;
}

bool PrefixRange::makeMoreSpecific(int code, int _n, int _m) {
/* [<][>][^][v][top][bottom][index][help] */
   // we got ipaddr/length ^n-m  ^_n-_m
   // not defined if m < n 
   // ipaddr/length^max(n,_n)-_m othewise

   switch (code) {
   case 0: // ^-
      n++;
      m = 32;
      break;
   case 1: // ^+
      m = 32;
      break;
   default: // ^n-m
      if (_m < n || _m < n)
         return false;
      n = (_n >? n);
      m = _m;
   }

   return true;
}

void PrefixRange::print(void)
/* [<][>][^][v][top][bottom][index][help] */
{
  cout << get_text();
}

int PrefixRange::valid(void)
/* [<][>][^][v][top][bottom][index][help] */
{
  if ((length <= n) && (n <= m)) return 1;
  return 0;
}

PrefixRange& PrefixRange::operator=(const PrefixRange& other)
{
  ipaddr = other.ipaddr;
  length = other.length;
  n      = other.n;
  m      = other.m;
}

// Does it make sense for the more/less specifics operators???
int PrefixRange::operator<(const PrefixRange& other) const
{
  return ipaddr < other.ipaddr || 
    (ipaddr == other.ipaddr && length < other.length);
}

// Does it make sense for the more/less specifics operators???
int PrefixRange::operator<=(const PrefixRange& other) const
{
  return ipaddr < other.ipaddr || 
    (ipaddr == other.ipaddr && length <= other.length);
}

int PrefixRange::operator==(const PrefixRange& other) const
{
  return ipaddr == other.ipaddr && length == other.length &&
         n == other.n && m == other.m;
}

int PrefixRange::compare(const PrefixRange& other) const
/* [<][>][^][v][top][bottom][index][help] */
{
  if (*this < other)  return -1;
  if (*this == other) return 0;
  return 1;
}

int PrefixRange::contains(const PrefixRange& other) const
/* [<][>][^][v][top][bottom][index][help] */
{
   return (length <= other.length && n <= other.n && m >= other.m
           && ipaddr == (other.ipaddr & get_mask()));
}

unsigned int PrefixRange::get_mask() const
/* [<][>][^][v][top][bottom][index][help] */
{  
  int mask;

  if (length == 0)
    mask = 0;
  else 
    mask = ~ (0u) << (32 - length);
  
  return mask;
}

char *PrefixRange::get_text(char *buffer) const
/* [<][>][^][v][top][bottom][index][help] */
{
  int2quad(buffer, ipaddr);
  sprintf(buffer + strlen(buffer), "/%u", length);

  if ((length == n) && (n == m))
    // just one route
    ;
  else
    if ((length == n) && (m == 32))
      // inclusive more specifics operator
      strcat(buffer, "^+");
    else
      if ((length == n - 1) && (m == 32))
        // exclusive more specifics operator
        strcat(buffer, "^-");
      else
        if (n == m)
          sprintf(buffer + strlen(buffer), "^%u", n);
        else
          sprintf(buffer + strlen(buffer), "^%u-%u", n, m);
  return buffer;
}

static unsigned long long int bits[] = { 0x100000000ULL,
                     0x080000000, 0x040000000, 0x020000000, 0x010000000,
                     0x008000000, 0x004000000, 0x002000000, 0x001000000,
                     0x000800000, 0x000400000, 0x000200000, 0x000100000,
                     0x000080000, 0x000040000, 0x000020000, 0x000010000,
                     0x000008000, 0x000004000, 0x000002000, 0x000001000,
                     0x000000800, 0x000000400, 0x000000200, 0x000000100,
                     0x000000080, 0x000000040, 0x000000020, 0x000000010,
                     0x000000008, 0x000000004, 0x000000002, 0x000000001
};

unsigned long long int PrefixRange::get_range() const {
/* [<][>][^][v][top][bottom][index][help] */
   unsigned long long int range = 0;
   for (int i = n; i <= m; ++i)
      range |= bits[i];
   return range;
}


char *Prefix::get_text(char *buffer) const {
/* [<][>][^][v][top][bottom][index][help] */
  int2quad(buffer, ipaddr);
  sprintf(buffer + strlen(buffer), "/%u", length);
  return buffer;  
}

char *IPAddr::get_text(char *buffer) const {
/* [<][>][^][v][top][bottom][index][help] */
  int2quad(buffer, ipaddr);
  return buffer;  
}

Prefix::Prefix(char *name) {
/* [<][>][^][v][top][bottom][index][help] */
   unsigned int i1, i2, i3, i4, i5;

   sscanf(name, "%u.%u.%u.%u/%u", &i1, &i2, &i3, &i4, &i5);
   ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
   length = n = m = i5;

   int mask;
   if (length == 0)
      mask = 0;
   else 
      mask = ~ (0u) << (32 - length);
  
   ipaddr &= mask;
}

IPAddr::IPAddr(char *name) {
/* [<][>][^][v][top][bottom][index][help] */
   unsigned int i1, i2, i3, i4;

   sscanf(name, "%u.%u.%u.%u", &i1, &i2, &i3, &i4);
   ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
   length = n = m = 32;
}

PrefixRange NullPrefixRange("0.0.0.0/32^32-32");
Prefix      NullPrefix("0.0.0.0/32");
IPAddr      NullIPAddr("0.0.0.0");

/* [<][>][^][v][top][bottom][index][help] */