modules/up/src/rpsl/rpsl/rpsl_attr.cc
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- print
- searchMethod
- searchNextMethod
- startMandatoryCheck
- missingMandatoryOption
- searchOption
- searchNextOption
- searchOption
- validateArgs
- reset
- searchAttr
- validate
- print
- print
- print
1 // $Id: rpsl_attr.cc,v 1.1.1.1 2000/03/10 16:32:23 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 "rpsl_attr.hh"
38 #include "object.hh"
39 #include "schema.hh"
40
41 //// printing ////////////////////////////////////////////////////////
42
43 ostream &Attr::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
44 if (object && object->contents)
45 out.write(object->getTextAt(offset), len);
46 return out;
47 }
48
49 ostream &AttrGeneric::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
50 out << type->name() << ":\t" << *items;
51 return out;
52 }
53
54 ostream &AttrImport::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
55 out << "import: ";
56 if (fromProt && fromProt->name && strcasecmp(fromProt->name, "BGP4"))
57 out << "protocol " << fromProt->name << " ";
58 if (intoProt && intoProt->name && strcasecmp(intoProt->name, "BGP4"))
59 out << "into " << intoProt->name << " ";
60 out << *policy;
61 return out;
62 }
63
64 ostream &AttrExport::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
65 out << "export: " << *policy;
66 return out;
67 }
68
69 ostream &AttrDefault::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
70 out << "default:\tto " << *peering << "\n";
71
72 if (!action->isEmpty())
73 out << " \t " << *action << "\n";
74
75 if (filter && typeid(filter) != typeid(FilterANY))
76 out << " \t networks " << *filter;
77
78 return out;
79 }
80
81 ostream &AttrFilter::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
82 out << "filter: " << *filter;
83
84 return out;
85 }
86
87 ostream &AttrPeering::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
88 out << "peering: " << *peering;
89
90 return out;
91 }
92
93 ostream &AttrIfAddr::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
94 static char buffer[128];
95 out << "ifaddr:\t" << int2quad(buffer, ifaddr.get_ipaddr())
96 << " masklen " << ifaddr.get_length();
97 return out;
98 }
99
100 ostream &AttrPeerOption::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
101 out << option << "(" << *args << ")";
102 return out;
103 }
104
105 ostream &AttrPeer::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
106 out << "peer:\t" << protocol->name
107 << " " << *peer << " ";
108 for (AttrPeerOption *nd = options->head(); nd; ) {
109 nd->print(out);
110 nd = options->next(nd);
111 if (nd)
112 out << ", ";
113 }
114 return out;
115 }
116
117 ostream &AttrTypedef::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
118 if (type)
119 out << "typedef: " << name << " " << *type;
120 else
121 out << "typedef: " << name << "<error in type spec>";
122 return out;
123 }
124
125 ostream &AttrProtocol::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
126 out << "protocol: " << name;
127 for (AttrProtocolOption *nd = options->head(); nd; nd = options->next(nd)) {
128 nd->print(out);
129 out << "\n ";
130 }
131 return out;
132 }
133
134 ostream &AttrProtocolOption::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
135 out << (optional ? " optional " : " mandatory ") << *option << " ";
136 return out;
137 }
138
139 ostream &AttrMethod::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
140 out << name << "(";
141 for (RPTypeNode *n = args->head(); n; ) {
142 out << *n->type;
143 n = args->next(n);
144 if (n)
145 out << ", ";
146 }
147 if (varargs)
148 out << ", ...";
149 out << ")";
150 return out;
151 }
152
153 ostream &AttrRPAttr::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
154 out << "rp-attribute: " << name;
155 for (AttrMethod *nd = methods->head(); nd; nd = methods->next(nd))
156 out << " " << *nd;
157 return out;
158 }
159
160 ostream &AttrAttr::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
161 out << "attr: " << _name << " syntax(?) ?";
162
163 return out;
164 }
165
166
167
168
169
170
171
172
173 const AttrMethod *AttrRPAttr::searchMethod(const char *name) const {
/* [<][>][^][v][top][bottom][index][help] */
174 char buffer[1024] = "";
175
176 if (!isalpha(*name))
177 strcpy(buffer, "operator");
178
179 strcat(buffer, name);
180
181 // return method or NULL
182 for (AttrMethod *m = methods->head(); m; m = methods->next(m))
183 if (!strcasecmp(m->name, buffer))
184 return m;
185
186 return NULL;
187 }
188
189 const AttrMethod *AttrRPAttr::searchNextMethod(const AttrMethod *last) const {
/* [<][>][^][v][top][bottom][index][help] */
190 // return method or NULL
191 const AttrMethod *m = last;
192
193 if (!last)
194 return NULL;
195
196 for (m = methods->next(m); m; m = methods->next(m))
197 if (!strcasecmp(m->name, last->name))
198 return m;
199
200 return NULL;
201 }
202
203 void AttrProtocol::startMandatoryCheck() {
/* [<][>][^][v][top][bottom][index][help] */
204 for (AttrProtocolOption *m = options->head(); m; m = options->next(m))
205 m->found = false;
206 }
207
208 const AttrProtocolOption *AttrProtocol::missingMandatoryOption() {
/* [<][>][^][v][top][bottom][index][help] */
209 AttrProtocolOption *m, *n;
210
211 for (m = options->head(); m; m = options->next(m)) {
212 if (! m->found && ! m->optional)
213 return m;
214 if (m->found)
215 for (n = options->next(m); n; n = options->next(n))
216 if (!strcasecmp(m->option->name, n->option->name))
217 n->found = true;
218 }
219
220 return NULL;
221 }
222
223 const AttrProtocolOption *AttrProtocol::searchOption(const char *name) const {
/* [<][>][^][v][top][bottom][index][help] */
224 // return method or NULL
225 for (AttrProtocolOption *m = options->head(); m; m = options->next(m))
226 if (!strcasecmp(m->option->name, name)) {
227 m->found = true;
228 return m;
229 }
230
231 return NULL;
232 }
233
234 const AttrProtocolOption *AttrProtocol::searchNextOption
/* [<][>][^][v][top][bottom][index][help] */
235 (const AttrProtocolOption *last) const {
236 // return method or NULL
237 AttrProtocolOption *m = (AttrProtocolOption *) last;
238
239 if (!last)
240 return NULL;
241
242 for (m = options->next(m); m; m = options->next(m))
243 if (!strcasecmp(m->option->name, last->option->name)) {
244 m->found = true;
245 return m;
246 }
247
248 return NULL;
249 }
250
251 const AttrPeerOption *AttrPeer::searchOption(const char *name) const {
/* [<][>][^][v][top][bottom][index][help] */
252 // return method or NULL
253 for (AttrPeerOption *m = options->head(); m; m = options->next(m))
254 if (!strcasecmp(m->option, name))
255 return m;
256
257 return NULL;
258 }
259
260 bool AttrMethod::validateArgs(ItemList *actualArgs, int &position,
/* [<][>][^][v][top][bottom][index][help] */
261 const RPType *&correctType) const {
262 RPTypeNode *tnode = args->head();
263 Item *arg = actualArgs->head();
264 position = 0;
265 Item *arg2;
266
267 if (!tnode && !arg)
268 return true;
269
270 if (!tnode)
271 return false;
272
273 position = 1;
274 correctType = tnode->type;
275 while (correctType && arg) {
276 if (!correctType->validate(arg)) {
277 arg2 = correctType->typeCast(arg);
278 if (arg2) {
279 actualArgs->insertAfter(arg, arg2);
280 actualArgs->remove(arg);
281 delete arg;
282 arg = arg2;
283 } else
284 return false;
285 }
286
287 position++;
288 arg = actualArgs->next(arg);
289 tnode = args->next(tnode);
290 correctType = tnode ? tnode->type : NULL;
291 }
292
293 if (!correctType && arg && varargs) { // extra args
294 tnode = args->tail();
295 correctType = tnode->type;
296 while (correctType && arg) {
297 if (!correctType->validate(arg)) {
298 arg2 = correctType->typeCast(arg);
299 if (arg2) {
300 actualArgs->insertAfter(arg, arg2);
301 actualArgs->remove(arg);
302 delete arg;
303 arg = arg2;
304 } else
305 return false;
306 }
307
308 arg = actualArgs->next(arg);
309 position++;
310 }
311 correctType = (RPType *) NULL;
312 }
313
314 if (!correctType && !arg)
315 return true;
316
317 position = 0;
318 return false;
319 }
320
321 void AttrClass::reset() {
/* [<][>][^][v][top][bottom][index][help] */
322 for (int i = 0; i < attribs.size(); ++i)
323 attribs[i]->reset();
324 }
325
326 AttrAttr* AttrClass::searchAttr(const char *name) {
/* [<][>][^][v][top][bottom][index][help] */
327 for (int i = 0; i < attribs.size(); ++i)
328 if (!strcasecmp(name, attribs[i]->name())) {
329 attribs[i]->touch();
330 return attribs[i];
331 }
332
333 return NULL;
334 }
335
336 bool AttrClass::validate(string &errors) {
/* [<][>][^][v][top][bottom][index][help] */
337 // return true if valid i.e. no error
338 static char buffer[1024];
339 bool result = true;
340
341 for (int i = 0; i < attribs.size(); ++i) {
342 if (!attribs[i]->testKey()) {
343 sprintf(buffer, "***Error: key attribute %s is not specified.\n",
344 attribs[i]->name());
345 errors += buffer;
346 result = false;
347 }
348 if ((!schema.isForgiving() || attribs[i]->isKey())
349 && !attribs[i]->testMandatory()) {
350 sprintf(buffer, "***Error: mandatory attribute %s is not specified.\n",
351 attribs[i]->name());
352 errors += buffer;
353 result = false;
354 }
355 if ((!schema.isForgiving() || attribs[i]->isKey())
356 && !attribs[i]->testSingleValued()) {
357 sprintf(buffer,
358 "***Error: single-valued attribute %s occurs multiple times.\n",
359 attribs[i]->name());
360 errors += buffer;
361 result = false;
362 }
363 if (!attribs[i]->testGenerated()) {
364 sprintf(buffer,
365 "***Error: generated attribute %s cannot appear in an update.\n",
366 attribs[i]->name());
367 errors += buffer;
368 result = false;
369 }
370
371 }
372 return result;
373 }
374
375 ostream& AttrClass::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
376 }
377
378 ostream& AttrMntRoutes::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
379 out << "mnt-routes:";
380 for (MntPrfxPair *p = mntPrfxList->head(); p; p = mntPrfxList->next(p)) {
381 out << " " << p->mnt;
382 if (p->prefixes)
383 out << " " << p->prefixes;
384 out << ",\n";
385 }
386 }
387
388 ostream& AttrTRLabel::print(ostream &out) const {
/* [<][>][^][v][top][bottom][index][help] */
389 out << "transaction-label: "
390 << *source << " " << *seq << " " << *stamp;
391 }
392