## 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

       1 //  $Id: prefix.cc,v 1.1.1.1 2000/03/10 16:32:24 engin Exp $
       2 //
       3 //  Copyright (c) 1994 by the University of Southern California
       4 //  All rights reserved.
       5 //
       6 //  Permission to use, copy, modify, and distribute this software and its
       7 //  documentation in source and binary forms for lawful non-commercial
       8 //  purposes and without fee is hereby granted, provided that the above
       9 //  copyright notice appear in all copies and that both the copyright
      10 //  notice and this permission notice appear in supporting documentation,
      11 //  and that any documentation, advertising materials, and other materials
      12 //  related to such distribution and use acknowledge that the software was
      13 //  developed by the University of Southern California, Information
      14 //  Sciences Institute. The name of the USC may not be used to endorse or
      15 //  promote products derived from this software without specific prior
      16 //  written permission.
      17 //
      18 //  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
      19 //  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
      20 //  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
      21 //  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
      22 //  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
      23 //  TITLE, AND NON-INFRINGEMENT.
      24 //
      25 //  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
      26 //  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
      27 //  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
      28 //  OR PERFORMANCE OF THIS SOFTWARE.
      29 //
      30 //  Questions concerning this software should be directed to
      31 //  ratoolset@isi.edu.
      32 //
      33 //  Author(s): Cengiz Alaettinoglu <cengiz@ISI.EDU>
      34
      35 #include "config.h"
      36 #include <cstdio>
      37 #include <cstring>
      38 #include <iostream.h>
      39 #include "prefix.hh"
      40
      41 char PrefixRange::formattingbuffer[128];
      42
      43 char* int2quad(char *buffer, unsigned int i) {
         /* [<][>][^][v][top][bottom][index][help] */
      44    sprintf(buffer, "%d.%d.%d.%d",
      45            (i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8)  & 0xFF, i & 0xFF);
      46    return buffer;
      47 }
      48
      49 unsigned int quad2int(char *quad) {
         /* [<][>][^][v][top][bottom][index][help] */
      50    unsigned int i;
      51    unsigned int i1, i2, i3, i4;
      52
      53    sscanf(quad, "%u.%u.%u.%u", &i1, &i2, &i3, &i4);
      54    i = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
      55    return i;
      56 }
      57
      58 ostream& operator<<(ostream& stream, const PrefixRange& p) {
      59    stream << p.get_text();
      60    return stream;
      61 }
      62
      63 /*
      64 // Added const to PrefixRange& p by wlee@isi.edu
      65 const ostream& operator<<(ostream& stream, const PrefixRange& p) {
      66   stream << p.get_text();
      67    return stream;
      68 }
      69 */
      70
      71 PrefixRange::PrefixRange(void) :
         /* [<][>][^][v][top][bottom][index][help] */
      72   ipaddr(0),
      73   length(0),
      74   n(0),
      75   m(0)
      76 {
      77 }
      78
      79 // Added by wlee@isi.edu
      80 PrefixRange::PrefixRange(const PrefixRange &p) :
         /* [<][>][^][v][top][bottom][index][help] */
      81   ipaddr(p.ipaddr),
      82   length(p.length),
      83   n(p.n),
      84   m(p.m)
      85 {
      86 }
      87
      88 PrefixRange::PrefixRange(unsigned int ipaddr, unsigned char length,
         /* [<][>][^][v][top][bottom][index][help] */
      89                  unsigned char n, unsigned char m) :
      90   ipaddr(ipaddr),
      91   length(length),
      92   n(n),
      93   m(m)
      94 {
      95 }
      96
      97 PrefixRange::PrefixRange(char *name) :
         /* [<][>][^][v][top][bottom][index][help] */
      98   ipaddr(0),
      99   length(0),
     100   n(0),
     101   m(0)
     102 {
     103   parse(name);
     104 }
     105
     106 void PrefixRange::parse(char *name)
         /* [<][>][^][v][top][bottom][index][help] */
     107 {
     108   unsigned int i1, i2, i3, i4, uiLength = 0, uiN = 0, uiM = 0;
     109   unsigned int mask;
     110   char ch = ' ';
     111
     112   char *p;
     113   if (strstr(name, "^+"))
     114     // Inclusive more specific operation
     115     sscanf(name, "%u.%u.%u.%u/%u^%c", &i1, &i2, &i3, &i4, &uiLength, &ch);
     116   else if (p = strstr(name, "^-"))
     117      sscanf(name, "%u.%u.%u.%u/%u^%c", &i1, &i2, &i3, &i4, &uiLength, &ch);
     118   else if (p = strchr(name, '-'))
     119      sscanf(name, "%u.%u.%u.%u/%u^%u-%u",
     120             &i1, &i2, &i3, &i4, &uiLength, &uiN, &uiM);
     121   else if (p = strchr(name, '^')) {
     122      sscanf(name, "%u.%u.%u.%u/%u^%u",
     123             &i1, &i2, &i3, &i4, &uiLength, &uiN);
     124      uiM = uiN;
     125   } else
     126      sscanf(name, "%u.%u.%u.%u/%u", &i1, &i2, &i3, &i4, &uiLength);
     127
     128   length = uiLength;
     129   n      = uiN;
     130   m      = uiM;
     131
     132   switch (ch)
     133     {
     134     case '+':
     135       // inclusive more specifics operator
     136       n = length;
     137       m = 32;
     138       break;
     139     case '-':
     140       // exclusive more specifics operator
     141       n = length + 1;
     142       m = 32;
     143       break;
     144     default:
     145       if (n == 0) n = length;
     146       if (m == 0) m = n;
     147       break;
     148     }
     149
     150   ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
     151
     152   if (length == 0)
     153     mask = 0;
     154   else
     155     mask = ~ (0u) << (32 - length);
     156
     157   ipaddr &= mask;
     158 }
     159
     160 void PrefixRange::define(unsigned int ipaddr, unsigned char length,
         /* [<][>][^][v][top][bottom][index][help] */
     161                      unsigned char n, unsigned char m)
     162 {
     163   this->ipaddr = ipaddr;
     164   this->length = length;
     165   this->n      = n;
     166   this->m      = m;
     167 }
     168
     169 bool PrefixRange::makeMoreSpecific(int code, int _n, int _m) {
         /* [<][>][^][v][top][bottom][index][help] */
     170    // we got ipaddr/length ^n-m  ^_n-_m
     171    // not defined if m < n
     172    // ipaddr/length^max(n,_n)-_m othewise
     173
     174    switch (code) {
     175    case 0: // ^-
     176       n++;
     177       m = 32;
     178       break;
     179    case 1: // ^+
     180       m = 32;
     181       break;
     182    default: // ^n-m
     183       if (_m < n || _m < n)
     184          return false;
     185       n = (_n >? n);
     186       m = _m;
     187    }
     188
     189    return true;
     190 }
     191
     192 void PrefixRange::print(void)
         /* [<][>][^][v][top][bottom][index][help] */
     193 {
     194   cout << get_text();
     195 }
     196
     197 int PrefixRange::valid(void)
         /* [<][>][^][v][top][bottom][index][help] */
     198 {
     199   if ((length <= n) && (n <= m)) return 1;
     200   return 0;
     201 }
     202
     203 PrefixRange& PrefixRange::operator=(const PrefixRange& other)
     204 {
     205   ipaddr = other.ipaddr;
     206   length = other.length;
     207   n      = other.n;
     208   m      = other.m;
     209 }
     210
     211 // Does it make sense for the more/less specifics operators???
     212 int PrefixRange::operator<(const PrefixRange& other) const
     213 {
     214   return ipaddr < other.ipaddr ||
     215     (ipaddr == other.ipaddr && length < other.length);
     216 }
     217
     218 // Does it make sense for the more/less specifics operators???
     219 int PrefixRange::operator<=(const PrefixRange& other) const
     220 {
     221   return ipaddr < other.ipaddr ||
     222     (ipaddr == other.ipaddr && length <= other.length);
     223 }
     224
     225 int PrefixRange::operator==(const PrefixRange& other) const
     226 {
     227   return ipaddr == other.ipaddr && length == other.length &&
     228          n == other.n && m == other.m;
     229 }
     230
     231 int PrefixRange::compare(const PrefixRange& other) const
         /* [<][>][^][v][top][bottom][index][help] */
     232 {
     233   if (*this < other)  return -1;
     234   if (*this == other) return 0;
     235   return 1;
     236 }
     237
     238 int PrefixRange::contains(const PrefixRange& other) const
         /* [<][>][^][v][top][bottom][index][help] */
     239 {
     240    return (length <= other.length && n <= other.n && m >= other.m
     241            && ipaddr == (other.ipaddr & get_mask()));
     242 }
     243
     244 unsigned int PrefixRange::get_mask() const
         /* [<][>][^][v][top][bottom][index][help] */
     245 {
     246   int mask;
     247
     248   if (length == 0)
     249     mask = 0;
     250   else
     251     mask = ~ (0u) << (32 - length);
     252
     253   return mask;
     254 }
     255
     256 char *PrefixRange::get_text(char *buffer) const
         /* [<][>][^][v][top][bottom][index][help] */
     257 {
     258   int2quad(buffer, ipaddr);
     259   sprintf(buffer + strlen(buffer), "/%u", length);
     260
     261   if ((length == n) && (n == m))
     262     // just one route
     263     ;
     264   else
     265     if ((length == n) && (m == 32))
     266       // inclusive more specifics operator
     267       strcat(buffer, "^+");
     268     else
     269       if ((length == n - 1) && (m == 32))
     270         // exclusive more specifics operator
     271         strcat(buffer, "^-");
     272       else
     273         if (n == m)
     274           sprintf(buffer + strlen(buffer), "^%u", n);
     275         else
     276           sprintf(buffer + strlen(buffer), "^%u-%u", n, m);
     277   return buffer;
     278 }
     279
     280 static unsigned long long int bits[] = { 0x100000000ULL,
     281                      0x080000000, 0x040000000, 0x020000000, 0x010000000,
     282                      0x008000000, 0x004000000, 0x002000000, 0x001000000,
     283                      0x000800000, 0x000400000, 0x000200000, 0x000100000,
     284                      0x000080000, 0x000040000, 0x000020000, 0x000010000,
     285                      0x000008000, 0x000004000, 0x000002000, 0x000001000,
     286                      0x000000800, 0x000000400, 0x000000200, 0x000000100,
     287                      0x000000080, 0x000000040, 0x000000020, 0x000000010,
     288                      0x000000008, 0x000000004, 0x000000002, 0x000000001
     289 };
     290
     291 unsigned long long int PrefixRange::get_range() const {
         /* [<][>][^][v][top][bottom][index][help] */
     292    unsigned long long int range = 0;
     293    for (int i = n; i <= m; ++i)
     294       range |= bits[i];
     295    return range;
     296 }
     297
     298
     299 char *Prefix::get_text(char *buffer) const {
         /* [<][>][^][v][top][bottom][index][help] */
     300   int2quad(buffer, ipaddr);
     301   sprintf(buffer + strlen(buffer), "/%u", length);
     302   return buffer;
     303 }
     304
     305 char *IPAddr::get_text(char *buffer) const {
         /* [<][>][^][v][top][bottom][index][help] */
     306   int2quad(buffer, ipaddr);
     307   return buffer;
     308 }
     309
     310 Prefix::Prefix(char *name) {
         /* [<][>][^][v][top][bottom][index][help] */
     311    unsigned int i1, i2, i3, i4, i5;
     312
     313    sscanf(name, "%u.%u.%u.%u/%u", &i1, &i2, &i3, &i4, &i5);
     314    ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
     315    length = n = m = i5;
     316
     317    int mask;
     318    if (length == 0)
     319       mask = 0;
     320    else
     321       mask = ~ (0u) << (32 - length);
     322
     323    ipaddr &= mask;
     324 }
     325
     326 IPAddr::IPAddr(char *name) {
         /* [<][>][^][v][top][bottom][index][help] */
     327    unsigned int i1, i2, i3, i4;
     328
     329    sscanf(name, "%u.%u.%u.%u", &i1, &i2, &i3, &i4);
     330    ipaddr = i4 + (i3 << 8) + (i2 << 16) + (i1 << 24);
     331    length = n = m = 32;
     332 }
     333
     334 PrefixRange NullPrefixRange("0.0.0.0/32^32-32");
     335 Prefix      NullPrefix("0.0.0.0/32");
     336 IPAddr      NullIPAddr("0.0.0.0");

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