Statistics
| Branch: | Tag: | Revision:

one / src / vnm / AddressRange.cc @ 1772a358

History | View | Annotate | Download (38.3 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems                */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

    
17
#include "AddressRange.h"
18
#include "Attribute.h"
19
#include "VirtualNetworkPool.h"
20
#include "NebulaUtil.h"
21

    
22
#include <arpa/inet.h>
23
#include <algorithm>
24

    
25
using namespace std;
26

    
27
/* ************************************************************************** */
28
/* ************************************************************************** */
29

    
30
string AddressRange::type_to_str(AddressType ob)
31
{
32
    switch (ob)
33
    {
34
        case ETHER: return "ETHER"; break;
35
        case IP4:   return "IP4"  ; break;
36
        case IP6:   return "IP6"  ; break;
37
        case IP4_6: return "IP4_6"; break;
38
        default:    return "";
39
    }
40
};
41

    
42
/* -------------------------------------------------------------------------- */
43

    
44
AddressRange::AddressType AddressRange::str_to_type(string& str_type)
45
{
46
    one_util::toupper(str_type);
47

    
48
    if (str_type == "ETHER")
49
    {
50
        return ETHER;
51
    }
52
    else if (str_type == "IP4")
53
    {
54
        return IP4;
55
    }
56
    else if (str_type == "IP6")
57
    {
58
        return IP6;
59
    }
60
    else if (str_type == "IP4_6")
61
    {
62
        return IP4_6;
63
    }
64
    else
65
    {
66
        return NONE;
67
    }
68
}
69

    
70
/* ************************************************************************** */
71
/* ************************************************************************** */
72

    
73
int AddressRange::from_attr(VectorAttribute *vattr, string& error_msg)
74
{
75
    string value;
76

    
77
    attr = vattr;
78

    
79
    /* ------------------------- AR Type & Size ---------------------------- */
80

    
81
    value = vattr->vector_value("TYPE");
82
    type  = str_to_type(value);
83

    
84
    if (type == NONE)
85
    {
86
        error_msg = "Unknown or missing address range TYPE.";
87
        return -1;
88
    }
89

    
90
    if ( vattr->vector_value("SIZE", size) != 0 || size <= 0 )
91
    {
92
        error_msg = "Wrong SIZE for address range";
93
        return -1;
94
    }
95

    
96
    /* -------------------- MAC & IPv4 start addresses ---------------------- */
97

    
98
    bool do_mac = false;
99

    
100
    value = vattr->vector_value("MAC");
101

    
102
    if (value.empty())
103
    {
104
        do_mac = true;
105
        mac[1] = VirtualNetworkPool::mac_prefix();
106
    }
107
    else
108
    {
109
        if (mac_to_i(value, mac) == -1)
110
        {
111
            error_msg = "Wrong format for MAC attribute";
112
            return -1;
113
        };
114
    }
115

    
116
    switch(type)
117
    {
118
        case ETHER:
119
        case IP6:
120
            vattr->remove("IP");
121

    
122
            if (do_mac)
123
            {
124
                srand(time(0));
125

    
126
                mac[0] = rand() & 0x0000FFFF;
127
                mac[0]+= (rand()<<16) & 0xFFFF0000;
128
            }
129
            break;
130

    
131
        case IP4:
132
        case IP4_6:
133
            value = vattr->vector_value("IP");
134

    
135
            if (value.empty() || ip_to_i(value, ip) == -1)
136
            {
137
                error_msg = "Wrong or empty IP attribute";
138
                return -1;
139
            }
140

    
141
            if (do_mac)
142
            {
143
                mac[0] = ip;
144
            }
145
            break;
146

    
147
        default:
148
            return -1;
149
    }
150

    
151
    /* -------------------------- IP6 prefixes ------------------------------ */
152

    
153
    value = vattr->vector_value("GLOBAL_PREFIX");
154

    
155
    if (prefix6_to_i(value, global6) != 0 )
156
    {
157
        error_msg = "Wrong format for IP6 global address prefix";
158
        return -1;
159
    }
160

    
161
    value = vattr->vector_value("ULA_PREFIX");
162

    
163
    if (prefix6_to_i(value, ula6) != 0 )
164
    {
165
        error_msg = "Wrong format for IP6 unique local address prefix";
166
        return -1;
167
    }
168

    
169
    /* ------------------------- Security Groups ---------------------------- */
170

    
171
    value = vattr->vector_value("SECURITY_GROUPS");
172

    
173
    if (value.empty())
174
    {
175
        security_groups.clear();
176
    }
177
    else
178
    {
179
        one_util::split_unique(value, ',', security_groups);
180
    }
181

    
182
    /* ------------------------ AR Internal Data ---------------------------- */
183

    
184
    vattr->replace("AR_ID", id);
185

    
186
    vattr->remove("ALLOCATED");
187

    
188
    vattr->remove("USED_LEASES");
189

    
190
    vattr->remove("LEASES");
191

    
192
    vattr->remove("PARENT_NETWORK_AR_ID");
193

    
194
    vattr->remove("PARENT_NETWORK");
195

    
196
    if (do_mac) //Need to add MAC to the attribute
197
    {
198
        set_mac(0, attr);
199
    }
200

    
201
    return 0;
202
}
203

    
204
/* -------------------------------------------------------------------------- */
205
/* -------------------------------------------------------------------------- */
206

    
207
int AddressRange::update_attributes(
208
        VectorAttribute *   vup,
209
        bool                keep_restricted,
210
        string&             error_msg)
211
{
212
    /* --------------- Do not allow to modify a reservation ------- */
213

    
214
    int pid;
215
    bool is_reservation = (get_attribute("PARENT_NETWORK_AR_ID", pid) == 0);
216

    
217
    if (keep_restricted && restricted_set)
218
    {
219
        remove_restricted(vup);
220
    }
221

    
222
    /* --------------- Copy non-update attributes ----------------- */
223

    
224
    vup->replace("TYPE", attr->vector_value("TYPE"));
225

    
226
    vup->replace("MAC", attr->vector_value("MAC"));
227

    
228
    vup->remove("IP");
229

    
230
    if (type & 0x00000002)
231
    {
232
        vup->replace("IP", attr->vector_value("IP"));
233
    }
234

    
235
    /* ----------------- Remove internal attributes ----------------- */
236

    
237
    vup->replace("AR_ID", attr->vector_value("AR_ID"));
238

    
239
    vup->replace("ALLOCATED", attr->vector_value("ALLOCATED"));
240

    
241
    vup->remove("USED_LEASES");
242

    
243
    vup->remove("LEASES");
244

    
245
    vup->remove("PARENT_NETWORK_AR_ID");
246

    
247
    if (is_reservation)
248
    {
249
        vup->replace("PARENT_NETWORK_AR_ID",
250
                attr->vector_value("PARENT_NETWORK_AR_ID"));
251
    }
252

    
253
    /* ------ Remove non-persistent attributes, generated in to_xml() ------ */
254

    
255
    vup->remove("MAC_END");
256

    
257
    vup->remove("IP_END");
258

    
259
    vup->remove("IP6_ULA");
260

    
261
    vup->remove("IP6_ULA_END");
262

    
263
    vup->remove("IP6_GLOBAL");
264

    
265
    vup->remove("IP6_GLOBAL_END");
266

    
267
    /* ----------------- restricted attributes ----------------- */
268

    
269
    if (keep_restricted && restricted_set)
270
    {
271
        VectorAttribute va_aux(*attr);
272
        remove_all_except_restricted(&va_aux);
273

    
274
        vup->merge(&va_aux, true);
275
    }
276

    
277
    /* ----------------- update known attributes ----------------- */
278

    
279
    unsigned int new_size;
280

    
281
    if (vup->vector_value("SIZE", new_size) == 0)
282
    {
283
        if (is_reservation && new_size != size)
284
        {
285
            error_msg = "The SIZE of a reservation cannot be changed.";
286
            return -1;
287
        }
288

    
289
        if (allocated.upper_bound(new_size-1) != allocated.end())
290
        {
291
            error_msg = "New SIZE cannot be applied. There are used leases"
292
                    " that would fall outside the range.";
293

    
294
            return -1;
295
        }
296
    }
297
    else
298
    {
299
        new_size = size;
300
    }
301

    
302
    string new_global = vup->vector_value("GLOBAL_PREFIX");
303

    
304
    if (prefix6_to_i(new_global, global6) != 0 )
305
    {
306
        error_msg = "Wrong format for IP6 global address prefix";
307
        return -1;
308
    }
309

    
310
    string new_ula = vup->vector_value("ULA_PREFIX");
311

    
312
    if (prefix6_to_i(new_ula, ula6) != 0 )
313
    {
314
        error_msg = "Wrong format for IP6 unique local address prefix";
315
        return -1;
316
    }
317

    
318
    size = new_size;
319

    
320
    vup->replace("SIZE", size);
321

    
322
    vup->replace("GLOBAL_PREFIX", new_global);
323
    vup->replace("ULA_PREFIX", new_ula);
324

    
325
    string value = vup->vector_value("SECURITY_GROUPS");
326

    
327
    security_groups.clear();
328

    
329
    if (!value.empty())
330
    {
331
        one_util::split_unique(value, ',', security_groups);
332
    }
333

    
334
    /* Replace with the new attributes */
335

    
336
    attr->replace(vup->value());
337

    
338
    return 0;
339
}
340

    
341
/* -------------------------------------------------------------------------- */
342
/* -------------------------------------------------------------------------- */
343

    
344
int AddressRange::from_vattr_db(VectorAttribute *vattr)
345
{
346
    string value;
347
    int    rc = 0;
348

    
349
    this->attr = vattr;
350

    
351
    rc += vattr->vector_value("AR_ID", id);
352

    
353
    value = vattr->vector_value("TYPE");
354
    type  = str_to_type(value);
355

    
356
    rc += vattr->vector_value("SIZE", size);
357

    
358
    rc += mac_to_i(vattr->vector_value("MAC"), mac);
359

    
360
    if (type & 0x00000002)
361
    {
362
        rc += ip_to_i(vattr->vector_value("IP"), ip);
363
    }
364

    
365
    rc += prefix6_to_i(vattr->vector_value("GLOBAL_PREFIX"), global6);
366

    
367
    rc += prefix6_to_i(vattr->vector_value("ULA_PREFIX"), ula6);
368

    
369
    rc += attr_to_allocated(vattr->vector_value("ALLOCATED"));
370

    
371
    value = vattr->vector_value("SECURITY_GROUPS");
372

    
373
    security_groups.clear();
374

    
375
    if (!value.empty())
376
    {
377
        one_util::split_unique(value, ',', security_groups);
378
    }
379

    
380
    if (type == NONE)
381
    {
382
        rc = -1;
383
    }
384

    
385
    return rc;
386
}
387

    
388
/* -------------------------------------------------------------------------- */
389
/* -------------------------------------------------------------------------- */
390

    
391
void AddressRange::addr_to_xml(unsigned int index, unsigned int rsize,
392
        ostringstream& oss) const
393
{
394
    unsigned int new_mac[2];
395
    string       ip6_s;
396

    
397
    new_mac[0] = mac[0] + index;
398
    new_mac[1] = mac[1];
399

    
400
    oss << "<ADDRESS>"
401
        << "<MAC>" << mac_to_s(new_mac) << "</MAC>";
402

    
403
    if ( ip != 0 )
404
    {
405
        oss << "<IP>" << ip_to_s(ip + index) << "</IP>";
406
    }
407

    
408
    if (ula6[1] != 0 || ula6[0] != 0 )
409
    {
410
        oss << "<IP6_ULA>" << ip6_to_s(ula6, new_mac, ip6_s) << "</IP6_ULA>";
411
    }
412

    
413
    if (global6[1] != 0 || global6[0] != 0)
414
    {
415
        oss << "<IP6_GLOBAL>" << ip6_to_s(global6, new_mac, ip6_s)
416
            << "</IP6_GLOBAL>";
417
    }
418

    
419
    oss << "<SIZE>" << rsize << "</SIZE>"
420
        << "</ADDRESS>";
421
}
422

    
423
/* -------------------------------------------------------------------------- */
424
/* -------------------------------------------------------------------------- */
425

    
426
void AddressRange::to_xml(ostringstream &oss) const
427
{
428
    const map<string,string>& ar_attrs = attr->value();
429
    map<string,string>::const_iterator it;
430

    
431
    string       aux_st;
432
    unsigned int mac_end[2];
433

    
434
    oss << "<AR>";
435

    
436
    for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
437
    {
438
        if ( it->first == "ALLOCATED" )
439
        {
440
            continue;
441
        }
442

    
443
        oss << "<" << it->first << ">"
444
            << one_util::escape_xml(it->second)
445
            << "</"<< it->first << ">";
446
    }
447

    
448
    mac_end[1] = mac[1];
449
    mac_end[0] = (mac[0] + size - 1);
450

    
451
    oss << "<MAC_END>" << one_util::escape_xml(mac_to_s(mac_end))<<"</MAC_END>";
452

    
453
    aux_st = attr->vector_value("IP");
454

    
455
    if (aux_st != "")
456
    {
457
        unsigned int ip_i;
458

    
459
        if (ip_to_i(aux_st, ip_i) == 0)
460
        {
461
            oss << "<IP_END>" << one_util::escape_xml(ip_to_s(ip_i + size - 1))
462
                << "</IP_END>";
463
        }
464
    }
465

    
466
    if (type & 0x00000004)
467
    {
468
        string ip6_s;
469

    
470
        if (ula6[1] != 0 || ula6[0] != 0 )
471
        {
472
            ip6_to_s(ula6, mac, ip6_s);
473
            oss << "<IP6_ULA>" << one_util::escape_xml(ip6_s) << "</IP6_ULA>";
474

    
475
            ip6_to_s(ula6, mac_end, ip6_s);
476
            oss << "<IP6_ULA_END>" << one_util::escape_xml(ip6_s)
477
                << "</IP6_ULA_END>";
478
        }
479

    
480
        if (global6[1] != 0 || global6[0] != 0 )
481
        {
482
            ip6_to_s(global6, mac, ip6_s);
483
            oss << "<IP6_GLOBAL>" << one_util::escape_xml(ip6_s)
484
                << "</IP6_GLOBAL>";
485

    
486
            ip6_to_s(global6, mac_end, ip6_s);
487
            oss << "<IP6_GLOBAL_END>" << one_util::escape_xml(ip6_s)
488
                << "</IP6_GLOBAL_END>";
489
        }
490
    }
491

    
492
    oss << "<USED_LEASES>" << get_used_addr() << "</USED_LEASES>";
493
    oss << "</AR>";
494
}
495

    
496
/* -------------------------------------------------------------------------- */
497
/* -------------------------------------------------------------------------- */
498

    
499
void AddressRange::to_xml(ostringstream &oss, const vector<int>& vms,
500
        const vector<int>& vns, const vector<int>& vrs) const
501
{
502
    const map<string,string>&          ar_attrs = attr->value();
503
    map<string,string>::const_iterator it;
504

    
505
    int          rc;
506
    unsigned int mac_end[2];
507
    string       aux_st;
508

    
509
    bool all_vms = (vms.size() == 1 && vms[0] == -1);
510
    bool all_vns = (vns.size() == 1 && vns[0] == -1);
511
    bool all_vrs = (vrs.size() == 1 && vrs[0] == -1);
512

    
513
    oss << "<AR>";
514

    
515
    for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
516
    {
517
        if ( it->first == "ALLOCATED" )
518
        {
519
            continue;
520
        }
521

    
522
        oss << "<" << it->first << ">"
523
            << one_util::escape_xml(it->second)
524
            << "</"<< it->first << ">";
525
    }
526

    
527
    mac_end[1] = mac[1];
528
    mac_end[0] = (mac[0] + size - 1);
529

    
530
    oss << "<MAC_END>" << one_util::escape_xml(mac_to_s(mac_end))<<"</MAC_END>";
531

    
532
    aux_st = attr->vector_value("IP");
533

    
534
    if (aux_st != "")
535
    {
536
        unsigned int ip_i;
537

    
538
        rc = ip_to_i(aux_st, ip_i);
539

    
540
        if (rc == 0)
541
        {
542
            oss << "<IP_END>" << one_util::escape_xml(ip_to_s(ip_i + size - 1))
543
                << "</IP_END>";
544
        }
545
    }
546

    
547
    if (type & 0x00000004)
548
    {
549
        string ip6_s;
550

    
551
        if (ula6[1] != 0 || ula6[0] != 0 ) /* Unique Local Address */
552
        {
553
            ip6_to_s(ula6, mac, ip6_s);
554
            oss << "<IP6_ULA>" << one_util::escape_xml(ip6_s) << "</IP6_ULA>";
555

    
556
            ip6_to_s(ula6, mac_end, ip6_s);
557
            oss << "<IP6_ULA_END>" << one_util::escape_xml(ip6_s) << "</IP6_ULA_END>";
558
        }
559

    
560
        if (global6[1] != 0 || global6[0] != 0 ) /* Glocal Unicast */
561
        {
562
            ip6_to_s(global6, mac, ip6_s);
563
            oss << "<IP6_GLOBAL>" << one_util::escape_xml(ip6_s) << "</IP6_GLOBAL>";
564

    
565
            ip6_to_s(global6, mac_end, ip6_s);
566
            oss << "<IP6_GLOBAL_END>" << one_util::escape_xml(ip6_s) << "</IP6_GLOBAL_END>";
567
        }
568
    }
569

    
570
    oss << "<USED_LEASES>" << get_used_addr() << "</USED_LEASES>";
571

    
572
    if (allocated.empty())
573
    {
574
        oss << "<LEASES/>";
575
    }
576
    else
577
    {
578
        map<unsigned int, long long>::const_iterator it;
579

    
580
        VectorAttribute lease("LEASE");
581
        bool            is_in;
582

    
583
        oss << "<LEASES>";
584

    
585
        for (it = allocated.begin(); it != allocated.end(); it++)
586
        {
587
            lease.clear();
588

    
589
            is_in = false;
590

    
591
            if (it->second & PoolObjectSQL::VM)
592
            {
593
                int vmid = it->second & 0x00000000FFFFFFFFLL;
594

    
595
                if (all_vms || (find(vms.begin(),vms.end(),vmid) != vms.end()))
596
                {
597
                    lease.replace("VM", vmid);
598
                    is_in = true;
599
                }
600
            }
601
            else if (it->second & PoolObjectSQL::NET)
602
            {
603
                int vnid = it->second & 0x00000000FFFFFFFFLL;
604

    
605
                if (all_vns || (find(vns.begin(),vns.end(),vnid) != vns.end()))
606
                {
607
                    lease.replace("VNET", vnid);
608
                    is_in = true;
609
                }
610
            }
611
            else if (it->second & PoolObjectSQL::VROUTER)
612
            {
613
                int oid = it->second & 0x00000000FFFFFFFFLL;
614

    
615
                if (all_vrs || (find(vrs.begin(),vrs.end(),oid) != vrs.end()))
616
                {
617
                    lease.replace("VROUTER", oid);
618
                    is_in = true;
619
                }
620
            }
621

    
622
            if (!is_in)
623
            {
624
                continue;
625
            }
626

    
627
            set_mac(it->first, &lease);
628

    
629
            if (type & 0x00000002 )
630
            {
631
                set_ip(it->first, &lease);
632
            }
633

    
634
            if (type & 0x00000004)
635
            {
636
                set_ip6(it->first, &lease);
637
            }
638

    
639
            lease.to_xml(oss);
640
        }
641

    
642
        oss << "</LEASES>";
643
    }
644

    
645
    oss << "</AR>";
646
}
647

    
648
/* ************************************************************************** */
649
/* ************************************************************************** */
650

    
651
int AddressRange::mac_to_i(string mac, unsigned int i_mac[]) const
652
{
653
    istringstream iss;
654

    
655
    size_t pos   = 0;
656
    int    count = 0;
657

    
658
    unsigned int tmp;
659

    
660
    while ( (pos = mac.find(':')) !=  string::npos )
661
    {
662
        mac.replace(pos,1," ");
663
        count++;
664
    }
665

    
666
    if (count != 5)
667
    {
668
        return -1;
669
    }
670

    
671
    iss.str(mac);
672

    
673
    i_mac[1] = 0;
674
    i_mac[0] = 0;
675

    
676
    iss >> hex >> i_mac[1] >> ws >> hex >> tmp >> ws;
677
    i_mac[1] <<= 8;
678
    i_mac[1] += tmp;
679

    
680
    for (int i=0;i<4;i++)
681
    {
682
        iss >> hex >> tmp >> ws;
683

    
684
        i_mac[0] <<= 8;
685
        i_mac[0] += tmp;
686
    }
687

    
688
    return 0;
689
}
690

    
691
/* -------------------------------------------------------------------------- */
692
/* -------------------------------------------------------------------------- */
693

    
694
string AddressRange::mac_to_s(const unsigned int i_mac[]) const
695
{
696
    ostringstream oss;
697
    unsigned int  temp_byte;
698

    
699
    for (int i=5;i>=0;i--)
700
    {
701
        if ( i < 4 )
702
        {
703
            temp_byte = i_mac[0];
704
            temp_byte >>= i*8;
705
        }
706
        else
707
        {
708
            temp_byte = i_mac[1];
709
            temp_byte >>= (i%4)*8;
710
        }
711

    
712
        temp_byte &= 255;
713

    
714
        oss.width(2);
715
        oss.fill('0');
716
        oss << hex << temp_byte;
717

    
718
        if(i!=0)
719
        {
720
            oss << ":";
721
        }
722
    }
723

    
724
    return oss.str();
725
}
726

    
727
/* -------------------------------------------------------------------------- */
728
/* -------------------------------------------------------------------------- */
729

    
730
int AddressRange::ip_to_i(const string& _ip, unsigned int& i_ip) const
731
{
732
    istringstream iss;
733
    size_t        pos=0;
734
    int           count = 0;
735
    unsigned int  tmp;
736

    
737
    string ip = _ip;
738

    
739
    if ( ip.find_first_not_of("0123456789.") != std::string::npos )
740
    {
741
        return -1;
742
    }
743

    
744
    while ( (pos = ip.find('.')) !=  string::npos )
745
    {
746
        ip.replace(pos,1," ");
747
        count++;
748
    }
749

    
750
    if (count != 3)
751
    {
752
        return -1;
753
    }
754

    
755
    iss.str(ip);
756

    
757
    i_ip = 0;
758

    
759
    for (int i=0;i<4;i++)
760
    {
761
        iss >> dec >> tmp >> ws;
762

    
763
        if ( tmp > 255 || iss.fail() )
764
        {
765
            return -1;
766
        }
767

    
768
        i_ip <<= 8;
769
        i_ip += tmp;
770
    }
771

    
772
    return 0;
773
}
774

    
775
/* -------------------------------------------------------------------------- */
776
/* -------------------------------------------------------------------------- */
777

    
778
string AddressRange::ip_to_s(unsigned int i_ip) const
779
{
780
    ostringstream oss;
781
    unsigned int  temp_byte;
782

    
783
    for (int index=0;index<4;index++)
784
    {
785
        temp_byte =   i_ip;
786
        temp_byte >>= (24-index*8);
787
        temp_byte &=  255;
788

    
789
        oss << temp_byte;
790

    
791
        if(index!=3)
792
        {
793
            oss << ".";
794
        }
795
    }
796

    
797
    return oss.str();
798
}
799

    
800
/* -------------------------------------------------------------------------- */
801
/* -------------------------------------------------------------------------- */
802

    
803
int AddressRange::prefix6_to_i(const string& prefix, unsigned int ip[]) const
804
{
805
    struct in6_addr s6;
806

    
807
    if (prefix.empty())
808
    {
809
        ip[1] = ip[0] = 0;
810
        return 0;
811
    }
812

    
813
    int rc = inet_pton(AF_INET6, prefix.c_str(), &s6);
814

    
815
    if ( rc != 1 )
816
    {
817
        return -1;
818
    }
819

    
820
    ip[1] = ntohl(s6.s6_addr32[0]);
821
    ip[0] = ntohl(s6.s6_addr32[1]);
822

    
823
    return 0;
824
}
825

    
826
/* -------------------------------------------------------------------------- */
827
/* -------------------------------------------------------------------------- */
828

    
829
int AddressRange::ip6_to_s(const unsigned int prefix[], const unsigned int mac[], string& ip6_s) const
830
{
831
    unsigned int eui64[2];
832
    unsigned int mlow = mac[0];
833

    
834
    struct in6_addr ip6;
835
    char dst[INET6_ADDRSTRLEN];
836

    
837
    eui64[1] = ((mac[1]+512)<<16) + ((mlow & 0xFF000000)>>16) + 0x000000FF;
838
    eui64[0] = 4261412864 + (mlow & 0x00FFFFFF);
839

    
840
    ip6.s6_addr32[2] = htonl(eui64[1]);
841
    ip6.s6_addr32[3] = htonl(eui64[0]);
842

    
843
    ip6.s6_addr32[0] = htonl(prefix[1]);
844
    ip6.s6_addr32[1] = htonl(prefix[0]);
845

    
846
    if ( inet_ntop(AF_INET6, &ip6, dst, INET6_ADDRSTRLEN) != 0 )
847
    {
848
        ip6_s = dst;
849
        return 0;
850
    }
851

    
852
    return -1;
853
}
854

    
855
/* ************************************************************************** */
856
/* ************************************************************************** */
857

    
858
bool AddressRange::is_valid_mac(unsigned int& index, const string& mac_s,
859
    bool check_free)
860
{
861
    unsigned int mac_i[2];
862

    
863
    if (mac_to_i(mac_s, mac_i) == -1)
864
    {
865
        return false;
866
    }
867

    
868
    if ((mac_i[1] != mac[1]) || (mac_i[0] < mac[0]))
869
    {
870
        return false;
871
    }
872

    
873
    index = mac_i[0] - mac[0];
874

    
875
    if ((check_free && allocated.count(index) != 0) || (index >= size))
876
    {
877
        return false;
878
    }
879

    
880
    return true;
881
}
882

    
883
/* -------------------------------------------------------------------------- */
884
/* -------------------------------------------------------------------------- */
885

    
886
bool AddressRange::is_valid_ip(unsigned int& index, const string& ip_s,
887
    bool check_free)
888
{
889
    if (!(type & 0x00000002))//Not of type IP4 or IP4_6
890
    {
891
        return false;
892
    }
893

    
894
    unsigned int ip_i;
895

    
896
    if (ip_to_i(ip_s, ip_i) == -1)
897
    {
898
        return false;
899
    }
900

    
901
    if (ip_i < ip)
902
    {
903
        return false;
904
    }
905

    
906
    index = ip_i - ip;
907

    
908
    if ((check_free && allocated.count(index) != 0) || (index >= size))
909
    {
910
        return false;
911
    }
912

    
913
    return true;
914
}
915

    
916
/* -------------------------------------------------------------------------- */
917
/* -------------------------------------------------------------------------- */
918

    
919
void AddressRange::set_mac(unsigned int addr_index, VectorAttribute * nic) const
920
{
921
    unsigned int new_mac[2];
922

    
923
    new_mac[0] = mac[0] + addr_index;
924
    new_mac[1] = mac[1];
925

    
926
    nic->replace("MAC", mac_to_s(new_mac));
927
}
928

    
929
/* -------------------------------------------------------------------------- */
930
/* -------------------------------------------------------------------------- */
931

    
932
void AddressRange::set_ip(unsigned int addr_index, VectorAttribute * nic) const
933
{
934
    nic->replace("IP", ip_to_s(ip + addr_index));
935
}
936

    
937
/* -------------------------------------------------------------------------- */
938
/* -------------------------------------------------------------------------- */
939

    
940
void AddressRange::set_ip6(unsigned int addr_index, VectorAttribute * nic) const
941
{
942
    unsigned int new_mac[2];
943
    string       ip6_s;
944

    
945
    new_mac[0] = mac[0] + addr_index;
946
    new_mac[1] = mac[1];
947

    
948
    /* Link Local */
949
    unsigned int local_prefix[2] = {0, 0xfe800000};
950

    
951
    if (ip6_to_s(local_prefix, new_mac, ip6_s) == 0)
952
    {
953
        nic->replace("IP6_LINK", ip6_s);
954
    }
955

    
956
    if (ula6[1] != 0 || ula6[0] != 0 ) /* Unique Local Address */
957
    {
958
        if (ip6_to_s(ula6, new_mac, ip6_s) == 0)
959
        {
960
            nic->replace("IP6_ULA", ip6_s);
961
        }
962
    }
963

    
964
    if (global6[1] != 0 || global6[0] != 0 ) /* Global Unicast */
965
    {
966
        if (ip6_to_s(global6, new_mac, ip6_s) == 0)
967
        {
968
            nic->replace("IP6_GLOBAL", ip6_s);
969
        }
970
    }
971
}
972

    
973
/* -------------------------------------------------------------------------- */
974
/* -------------------------------------------------------------------------- */
975

    
976
void AddressRange::set_vnet(VectorAttribute *nic, const vector<string> &inherit) const
977
{
978
    nic->replace("AR_ID", id);
979

    
980
    string vn_mad = attr->vector_value("VN_MAD");
981
    string bridge = attr->vector_value("BRIDGE");
982
    string vlanid = attr->vector_value("VLAN_ID");
983
    string phydev = attr->vector_value("PHYDEV");
984

    
985
    if (!vn_mad.empty())
986
    {
987
        nic->replace("VN_MAD", vn_mad);
988
    }
989

    
990
    if (!bridge.empty())
991
    {
992
        nic->replace("BRIDGE", bridge);
993
    }
994

    
995
    if (!phydev.empty())
996
    {
997
        nic->replace("PHYDEV", phydev);
998
    }
999

    
1000
    if (!vlanid.empty())
1001
    {
1002
        nic->replace("VLAN_ID", vlanid);
1003
    }
1004

    
1005
    vector<string>::const_iterator it;
1006

    
1007
    for (it = inherit.begin(); it != inherit.end(); it++)
1008
    {
1009
        string inherit_val = attr->vector_value((*it).c_str());
1010

    
1011
        if (!inherit_val.empty())
1012
        {
1013
            nic->replace((*it).c_str(), inherit_val);
1014
        }
1015
    }
1016
}
1017

    
1018
/* ************************************************************************** */
1019
/* ************************************************************************** */
1020

    
1021
void AddressRange::allocated_to_attr()
1022
{
1023
    if (allocated.empty())
1024
    {
1025
        attr->replace("ALLOCATED", "");
1026
        return;
1027
    }
1028

    
1029
    map<unsigned int, long long>::const_iterator it;
1030

    
1031
    ostringstream oss;
1032

    
1033
    for (it = allocated.begin(); it != allocated.end(); it++)
1034
    {
1035
        oss << " " << it->first << " " << it->second;
1036
    }
1037

    
1038
    attr->replace("ALLOCATED", oss.str());
1039
}
1040

    
1041
/* -------------------------------------------------------------------------- */
1042

    
1043
int AddressRange::attr_to_allocated(const string& allocated_s)
1044
{
1045
    if (allocated_s.empty())
1046
    {
1047
        allocated.clear();
1048
        return 0;
1049
    }
1050

    
1051
    istringstream iss(allocated_s);
1052
    unsigned int  addr_index;
1053
    long long     object_pack;
1054

    
1055
    while (!iss.eof())
1056
    {
1057
        iss >> ws >> addr_index >> ws >> object_pack;
1058

    
1059
        if (iss.fail())
1060
        {
1061
            return -1;
1062
        }
1063

    
1064
        allocated.insert(make_pair(addr_index,object_pack));
1065
    }
1066

    
1067
    if ( get_used_addr() > size )
1068
    {
1069
        return -1;
1070
    }
1071

    
1072
    return 0;
1073
}
1074

    
1075
/* -------------------------------------------------------------------------- */
1076

    
1077
void AddressRange::set_allocated_addr(PoolObjectSQL::ObjectType ot, int obid,
1078
    unsigned int addr_index)
1079
{
1080
    long long lobid = obid & 0x00000000FFFFFFFFLL;
1081

    
1082
    allocated.insert(make_pair(addr_index,ot|lobid));
1083

    
1084
    allocated_to_attr();
1085
}
1086

    
1087
/* -------------------------------------------------------------------------- */
1088

    
1089
int AddressRange::free_allocated_addr(PoolObjectSQL::ObjectType ot, int obid,
1090
    unsigned int addr_index)
1091
{
1092
    long long lobid = obid & 0x00000000FFFFFFFFLL;
1093

    
1094
    map<unsigned int, long long>::iterator it;
1095

    
1096
    it = allocated.find(addr_index);
1097

    
1098
    if (it != allocated.end() && it->second == (ot|lobid))
1099
    {
1100
        allocated.erase(it);
1101
        allocated_to_attr();
1102

    
1103
        return 0;
1104
    }
1105

    
1106
    return -1;
1107
}
1108

    
1109
/* ************************************************************************** */
1110
/* ************************************************************************** */
1111

    
1112
void AddressRange::allocate_by_index(unsigned int index,
1113
    PoolObjectSQL::ObjectType ot,
1114
    int                       obid,
1115
    VectorAttribute*          nic,
1116
    const vector<string>&     inherit)
1117
{
1118
    set_mac(index, nic);
1119

    
1120
    if (type & 0x00000002 )
1121
    {
1122
        set_ip(index, nic);
1123
    }
1124

    
1125
    if (type & 0x00000004)
1126
    {
1127
        set_ip6(index, nic);
1128
    }
1129

    
1130
    set_vnet(nic, inherit);
1131

    
1132
    set_allocated_addr(ot, obid, index);
1133
}
1134

    
1135
/* -------------------------------------------------------------------------- */
1136
/* -------------------------------------------------------------------------- */
1137

    
1138
int AddressRange::allocate_addr(
1139
    PoolObjectSQL::ObjectType ot,
1140
    int                       obid,
1141
    VectorAttribute*          nic,
1142
    const vector<string>&     inherit)
1143
{
1144
    unsigned int index;
1145
    string       error_msg;
1146

    
1147
    if ( get_used_addr() >= size )
1148
    {
1149
        return -1;
1150
    }
1151

    
1152
    if ( get_addr(index, 1, error_msg) != 0 )
1153
    {
1154
        return -1;
1155
    }
1156

    
1157
    allocate_by_index(index, ot, obid, nic, inherit);
1158

    
1159
    return 0;
1160
}
1161

    
1162
/* -------------------------------------------------------------------------- */
1163
/* -------------------------------------------------------------------------- */
1164

    
1165
int AddressRange::allocate_by_mac(
1166
    const string&             mac_s,
1167
    PoolObjectSQL::ObjectType ot,
1168
    int                       obid,
1169
    VectorAttribute*          nic,
1170
    const vector<string>&     inherit)
1171
{
1172
    string error_msg;
1173
    unsigned int index;
1174

    
1175
    if (!is_valid_mac(index, mac_s, true))
1176
    {
1177
        return -1;
1178
    }
1179

    
1180
    if (allocate_addr(index, 1, error_msg) != 0)
1181
    {
1182
        return -1;
1183
    }
1184

    
1185
    allocate_by_index(index, ot, obid, nic, inherit);
1186

    
1187
    return 0;
1188
}
1189

    
1190
/* -------------------------------------------------------------------------- */
1191
/* -------------------------------------------------------------------------- */
1192

    
1193
int AddressRange::allocate_by_ip(
1194
    const string&             ip_s,
1195
    PoolObjectSQL::ObjectType ot,
1196
    int                       obid,
1197
    VectorAttribute*          nic,
1198
    const vector<string>&     inherit)
1199
{
1200
    string error_msg;
1201
    unsigned int index;
1202

    
1203
    if (!is_valid_ip(index, ip_s, true))
1204
    {
1205
        return -1;
1206
    }
1207

    
1208
    if (allocate_addr(index, 1, error_msg) != 0)
1209
    {
1210
        return -1;
1211
    }
1212

    
1213
    allocate_by_index(index, ot, obid, nic, inherit);
1214

    
1215
    return 0;
1216
}
1217

    
1218
/* -------------------------------------------------------------------------- */
1219
/* -------------------------------------------------------------------------- */
1220

    
1221
int AddressRange::free_addr(PoolObjectSQL::ObjectType ot, int obid,
1222
    const string& mac_s)
1223
{
1224
    string error_msg;
1225
    unsigned int mac_i[2];
1226

    
1227
    mac_to_i(mac_s, mac_i);
1228

    
1229
    unsigned int index = mac_i[0] - mac[0];
1230

    
1231
    if (index < 0 || index >= size)
1232
    {
1233
        return -1;
1234
    }
1235

    
1236
    if (free_addr(index, error_msg) != 0)
1237
    {
1238
        return -1;
1239
    }
1240

    
1241
    return free_allocated_addr(ot, obid, index);
1242
}
1243

    
1244
/* -------------------------------------------------------------------------- */
1245
/* -------------------------------------------------------------------------- */
1246

    
1247
int AddressRange::free_addr_by_ip(PoolObjectSQL::ObjectType ot, int obid,
1248
    const string& ip_s)
1249
{
1250
    string error_msg;
1251

    
1252
    if (!(type & 0x00000002))//Not of type IP4 or IP4_6
1253
    {
1254
        return -1;
1255
    }
1256

    
1257
    unsigned int ip_i;
1258

    
1259
    if (ip_to_i(ip_s, ip_i) == -1)
1260
    {
1261
        return -1;
1262
    }
1263

    
1264
    unsigned int index = ip_i - ip;
1265

    
1266
    if (index < 0 || index >= size)
1267
    {
1268
        return -1;
1269
    }
1270

    
1271
    if (free_addr(index, error_msg) != 0)
1272
    {
1273
        return -1;
1274
    }
1275

    
1276
    return free_allocated_addr(ot, obid, index);
1277
}
1278

    
1279
/* -------------------------------------------------------------------------- */
1280
/* -------------------------------------------------------------------------- */
1281

    
1282
int AddressRange::free_addr_by_owner(PoolObjectSQL::ObjectType ot, int obid)
1283
{
1284
    map<unsigned int, long long>::iterator it = allocated.begin();
1285

    
1286
    long long obj_pack = ot | (obid & 0x00000000FFFFFFFFLL);
1287

    
1288
    int freed = 0;
1289

    
1290
    string error_msg;
1291

    
1292
    while (it != allocated.end())
1293
    {
1294
        if (it->second == obj_pack && free_addr(it->first, error_msg) == 0)
1295
        {
1296
            map<unsigned int, long long>::iterator prev_it = it++;
1297

    
1298
            allocated.erase(prev_it);
1299

    
1300
            freed++;
1301
        }
1302
        else
1303
        {
1304
            it++;
1305
        }
1306
    }
1307

    
1308
    allocated_to_attr();
1309

    
1310
    return freed;
1311
}
1312

    
1313
/* -------------------------------------------------------------------------- */
1314
/* -------------------------------------------------------------------------- */
1315

    
1316
int AddressRange::free_addr_by_range(PoolObjectSQL::ObjectType ot, int obid,
1317
    const string& mac_s, unsigned int rsize)
1318
{
1319
    int freed = 0;
1320

    
1321
    unsigned int mac_i[2];
1322

    
1323
    mac_to_i(mac_s, mac_i);
1324

    
1325
    unsigned int index = mac_i[0] - mac[0];
1326

    
1327
    string error_msg;
1328

    
1329
    if ((0 <= index) && (index < size))
1330
    {
1331
        map<unsigned int, long long>::iterator it = allocated.find(index);
1332

    
1333
        if (it == allocated.end())
1334
        {
1335
            return freed;
1336
        }
1337

    
1338
        long long obj_pack = ot | (obid & 0x00000000FFFFFFFFLL);
1339

    
1340
        for (unsigned int i=0; i<rsize; i++)
1341
        {
1342
            if (it != allocated.end() && it->second == obj_pack &&
1343
                     free_addr(it->first, error_msg) == 0)
1344
            {
1345
                map<unsigned int, long long>::iterator prev_it = it++;
1346

    
1347
                allocated.erase(prev_it);
1348

    
1349
                freed++;
1350
            }
1351
            else
1352
            {
1353
                it++;
1354
            }
1355
        }
1356

    
1357
        allocated_to_attr();
1358
    }
1359

    
1360
    return freed;
1361
}
1362

    
1363
/* -------------------------------------------------------------------------- */
1364
/* -------------------------------------------------------------------------- */
1365

    
1366
const char * AddressRange::SG_RULE_ATTRIBUTES[] = {
1367
    "AR_ID",
1368
    "TYPE",
1369
    "SIZE",
1370
    "MAC",
1371
    "IP"};
1372

    
1373
const int  AddressRange::NUM_SG_RULE_ATTRIBUTES = 5;
1374

    
1375
void AddressRange::process_security_rule(VectorAttribute * rule)
1376
{
1377
    for ( int i = 0; i < NUM_SG_RULE_ATTRIBUTES; i++ )
1378
    {
1379
        string st = attr->vector_value(SG_RULE_ATTRIBUTES[i]);
1380

    
1381
        if ( st != "" )
1382
        {
1383
            rule->replace(SG_RULE_ATTRIBUTES[i], st);
1384
        }
1385
    }
1386
}
1387

    
1388
/* -------------------------------------------------------------------------- */
1389
/* -------------------------------------------------------------------------- */
1390

    
1391
int AddressRange::hold_by_ip(const string& ip_s)
1392
{
1393
    string error_msg;
1394
    unsigned int index;
1395

    
1396
    if (!is_valid_ip(index, ip_s, true))
1397
    {
1398
        return -1;
1399
    }
1400

    
1401
    if (allocate_addr(index, 1, error_msg) != 0)
1402
    {
1403
        return -1;
1404
    }
1405

    
1406
    set_allocated_addr(PoolObjectSQL::VM, -1, index);
1407

    
1408
    return 0;
1409
}
1410

    
1411
/* -------------------------------------------------------------------------- */
1412
/* -------------------------------------------------------------------------- */
1413

    
1414
int AddressRange::hold_by_mac(const string& mac_s)
1415
{
1416
    unsigned int index;
1417
    string error_msg;
1418

    
1419
    if (!is_valid_mac(index, mac_s, true))
1420
    {
1421
        return -1;
1422
    }
1423

    
1424
    if (allocate_addr(index, 1, error_msg) != 0)
1425
    {
1426
        return -1;
1427
    }
1428

    
1429
    set_allocated_addr(PoolObjectSQL::VM, -1, index);
1430

    
1431
    return 0;
1432
}
1433

    
1434
/* -------------------------------------------------------------------------- */
1435
/* -------------------------------------------------------------------------- */
1436

    
1437
int AddressRange::reserve_addr(int vid, unsigned int rsize, AddressRange *rar)
1438
{
1439
    unsigned int first_index;
1440
    string error_msg;
1441

    
1442
    if (rsize > get_free_addr())
1443
    {
1444
        return -1;
1445
    }
1446

    
1447
    if ( get_addr(first_index, rsize, error_msg) != 0 )
1448
    {
1449
        return -1;
1450
    }
1451

    
1452
    for (unsigned int j=0, i=first_index; j<rsize; j++, i++)
1453
    {
1454
        set_allocated_addr(PoolObjectSQL::NET, vid, i);
1455
    }
1456

    
1457
    VectorAttribute * new_ar = attr->clone();
1458
    string            errmsg;
1459

    
1460
    set_mac(first_index, new_ar);
1461

    
1462
    if (type & 0x00000002 )
1463
    {
1464
        set_ip(first_index, new_ar);
1465
    }
1466

    
1467
    new_ar->replace("SIZE",rsize);
1468

    
1469
    rar->from_vattr(new_ar, errmsg);
1470

    
1471
    new_ar->replace("PARENT_NETWORK_AR_ID",id);
1472

    
1473
    return 0;
1474
}
1475

    
1476
/* -------------------------------------------------------------------------- */
1477
/* -------------------------------------------------------------------------- */
1478

    
1479
int AddressRange::reserve_addr_by_index(int vid, unsigned int rsize,
1480
    unsigned int sindex, AddressRange *rar)
1481
{
1482
    string error_msg;
1483

    
1484
    /* ----------------- Allocate the new AR from sindex -------------------- */
1485

    
1486
    for (unsigned int j=sindex; j< (sindex+rsize) ; j++)
1487
    {
1488
        if (allocated.count(j) != 0)
1489
        {
1490
            return -1;
1491
        }
1492
    }
1493

    
1494
    if (allocate_addr(sindex, rsize, error_msg) != 0)
1495
    {
1496
        return -1;
1497
    }
1498

    
1499
    for (unsigned int j=sindex; j< (sindex+rsize); j++)
1500
    {
1501
        set_allocated_addr(PoolObjectSQL::NET, vid, j);
1502
    }
1503

    
1504
    /* ------------------------- Initialize the new AR ---------------------- */
1505

    
1506
    VectorAttribute * new_ar = attr->clone();
1507
    string            errmsg;
1508

    
1509
    set_mac(sindex, new_ar);
1510

    
1511
    if (type & 0x00000002 )
1512
    {
1513
        set_ip(sindex, new_ar);
1514
    }
1515

    
1516
    new_ar->replace("SIZE",rsize);
1517

    
1518
    rar->from_vattr(new_ar, errmsg);
1519

    
1520
    new_ar->replace("PARENT_NETWORK_AR_ID",id);
1521

    
1522
    return 0;
1523
}
1524

    
1525
/* -------------------------------------------------------------------------- */
1526
/* -------------------------------------------------------------------------- */
1527

    
1528
int AddressRange::reserve_addr_by_ip(int vid, unsigned int rsize,
1529
    const string& ip_s, AddressRange *rar)
1530
{
1531
    unsigned int sindex;
1532

    
1533
    if (!is_valid_ip(sindex, ip_s, false))
1534
    {
1535
        return -1;
1536
    }
1537

    
1538
    return reserve_addr_by_index(vid, rsize, sindex, rar);
1539
}
1540

    
1541
/* -------------------------------------------------------------------------- */
1542
/* -------------------------------------------------------------------------- */
1543

    
1544
int AddressRange::reserve_addr_by_mac(int vid, unsigned int rsize,
1545
    const string& mac_s, AddressRange *rar)
1546
{
1547
    unsigned int sindex;
1548

    
1549
    if (!is_valid_mac(sindex, mac_s, false))
1550
    {
1551
        return -1;
1552
    }
1553

    
1554
    return reserve_addr_by_index(vid, rsize, sindex, rar);
1555
}
1556

    
1557
/* ************************************************************************** */
1558
/* ************************************************************************** */
1559

    
1560
bool AddressRange::restricted_set = false;
1561

    
1562
set<string> AddressRange::restricted_attributes;
1563

    
1564
bool AddressRange::check(string& rs_attr) const
1565
{
1566
    if (!restricted_set)
1567
    {
1568
        return false;
1569
    }
1570

    
1571
    const map<string,string>& ar_attrs = attr->value();
1572
    map<string,string>::const_iterator it;
1573

    
1574
    for (it=ar_attrs.begin(); it != ar_attrs.end(); it++)
1575
    {
1576
        if (restricted_attributes.count(it->first) > 0)
1577
        {
1578
            rs_attr = it->first;
1579
            return true;
1580
        }
1581
    }
1582

    
1583
    return false;
1584
};
1585

    
1586
void AddressRange::set_restricted_attributes(vector<const SingleAttribute *>& rattrs)
1587
{
1588
    if (restricted_set)
1589
    {
1590
        return;
1591
    }
1592

    
1593
    restricted_set = true;
1594

    
1595
    for (unsigned int i = 0 ; i < rattrs.size() ; i++ )
1596
    {
1597
        string attr_s = rattrs[i]->value();
1598

    
1599
        restricted_attributes.insert(one_util::toupper(attr_s));
1600
    }
1601
};
1602

    
1603
/* -------------------------------------------------------------------------- */
1604
/* -------------------------------------------------------------------------- */
1605

    
1606
void AddressRange::remove_restricted(VectorAttribute* va)
1607
{
1608
    set<string>::const_iterator it;
1609
    size_t pos;
1610

    
1611
    for (it=restricted_attributes.begin(); it!=restricted_attributes.end(); it++)
1612
    {
1613
        pos = it->find("AR/");
1614

    
1615
        if (pos != string::npos)
1616
        {
1617
            va->remove( it->substr(pos+3) );
1618
        }
1619
    }
1620
}
1621

    
1622
/* -------------------------------------------------------------------------- */
1623
/* -------------------------------------------------------------------------- */
1624

    
1625
void AddressRange::remove_all_except_restricted(VectorAttribute* va)
1626
{
1627
    map<string,string>::iterator it;
1628
    map<string,string> vals = va->value();
1629

    
1630
    ostringstream oss;
1631

    
1632
    for(it = vals.begin(); it != vals.end(); it++)
1633
    {
1634
        oss.str("");
1635
        oss << "AR/" << it->first;
1636

    
1637
        if (restricted_attributes.count(oss.str()) == 0)
1638
        {
1639
            va->remove(it->first);
1640
        }
1641
    }
1642
}