dict_base_proto.c 131 KB
Newer Older
Sebastien Decugis's avatar
Sebastien Decugis committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/*********************************************************************************************************
* Software License Agreement (BSD License)                                                               *
* Author: Sebastien Decugis <sdecugis@nict.go.jp>							 *
*													 *
* Copyright (c) 2009, WIDE Project and NICT								 *
* All rights reserved.											 *
* 													 *
* Redistribution and use of this software in source and binary forms, with or without modification, are  *
* permitted provided that the following conditions are met:						 *
* 													 *
* * Redistributions of source code must retain the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer.										 *
*    													 *
* * Redistributions in binary form must reproduce the above 						 *
*   copyright notice, this list of conditions and the 							 *
*   following disclaimer in the documentation and/or other						 *
*   materials provided with the distribution.								 *
* 													 *
* * Neither the name of the WIDE Project or NICT nor the 						 *
*   names of its contributors may be used to endorse or 						 *
*   promote products derived from this software without 						 *
*   specific prior written permission of WIDE Project and 						 *
*   NICT.												 *
* 													 *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 	 *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 	 *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF   *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
*********************************************************************************************************/

/* Diameter Base protocol definitions.
 */

39
#include "fD.h"
Sebastien Decugis's avatar
Sebastien Decugis committed
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

#include <netinet/in.h>
#include <sys/socket.h>

/* The pointer for the global dictionary (initialized from main) */
struct dictionary * fd_g_dict = NULL;

/* The functions to encode and interpret the derived types defined in the base protocol */

/* Address AVP <-> struct sockaddr_storage */
static int Address_encode(void * data, union avp_value * avp_value)
{
	sSS * ss = (sSS *) data;
	uint16_t AddressType = 0;
	size_t	size = 0;
	unsigned char * buf = NULL;
	
	TRACE_ENTRY("%p %p", data, avp_value);
	CHECK_PARAMS( data && avp_value  );
	
	switch (ss->ss_family) {
		case AF_INET:
			{
				/* We are encoding an IP address */
				sSA4 * sin = (sSA4 *)ss;
				
				AddressType = 1;/* see http://www.iana.org/assignments/address-family-numbers/ */
				size = 6;	/* 2 for AddressType + 4 for data */
				
				CHECK_MALLOC(  buf = malloc(size)  );
				
				/* may not work because of alignment: *(uint32_t *)(buf+2) = htonl(sin->sin_addr.s_addr); */
				memcpy(buf + 2, &sin->sin_addr.s_addr, 4);
			}
			break;
				
		case AF_INET6:
			{
				/* We are encoding an IPv6 address */
				sSA6 * sin6 = (sSA6 *)ss;
				
				AddressType = 2;/* see http://www.iana.org/assignments/address-family-numbers/ */
				size = 18;	/* 2 for AddressType + 16 for data */
				
				CHECK_MALLOC(  buf = malloc(size)  );
				
				/* The order is already good here */
				memcpy(buf + 2, &sin6->sin6_addr.s6_addr, 16);
			}
			break;
				
		default:
			CHECK_PARAMS( AddressType = 0 );
	}
	
	*(uint16_t *)buf = htons(AddressType);

	avp_value->os.len = size;
	avp_value->os.data = buf;
	
	return 0;
}

static int Address_interpret(union avp_value * avp_value, void * interpreted)
{
	uint16_t AddressType = 0;
	unsigned char * buf;
	
	TRACE_ENTRY("%p %p", avp_value, interpreted);
	
	CHECK_PARAMS( avp_value && interpreted && (avp_value->os.len >= 2)  );
	
	AddressType = ntohs(*(uint16_t *)avp_value->os.data);
	buf = &avp_value->os.data[2];
	
	switch (AddressType) {
		case 1 /* IP */:
			{
				sSA4 * sin = (sSA4 *)interpreted;
				
				CHECK_PARAMS(  avp_value->os.len == 6  );
				
				sin->sin_family = AF_INET;
				/* sin->sin_addr.s_addr = ntohl( * (uint32_t *) buf); -- may not work because of bad alignment */
				memcpy(&sin->sin_addr.s_addr, buf, 4);
			}
			break;
				
		case 2 /* IP6 */:
			{
				sSA6 * sin6 = (sSA6 *)interpreted;
				
				CHECK_PARAMS(  avp_value->os.len == 18  );
				
				sin6->sin6_family = AF_INET6;
				memcpy(&sin6->sin6_addr.s6_addr, buf, 16);
			}
			break;
				
		default:
			CHECK_PARAMS( AddressType = 0 );
	}
	
	return 0;
}

146
/* Dump the content of an Address AVP */
147
148
static void Address_dump(union avp_value * avp_value)
{
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
	union {
		sSA	sa;
		sSS	ss;
		sSA4	sin;
		sSA6	sin6;
	} s;
	uint16_t fam;
	
	memset(&s, 0, sizeof(s));
	
	/* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */
	if (avp_value->os.len < 2) {
		fd_log_debug("[invalid length: %d]", avp_value->os.len);
		return;
	}
	
	/* Following octets are the address in network byte order already */
	fam = avp_value->os.data[0] << 8 | avp_value->os.data[1];
	switch (fam) {
		case 1:
			/* IP */
			s.sa.sa_family = AF_INET;
			if (avp_value->os.len != 6) {
				fd_log_debug("[invalid IP length: %d]", avp_value->os.len);
				return;
			}
			memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4);
			break;
		case 2:
			/* IP6 */
			s.sa.sa_family = AF_INET6;
			if (avp_value->os.len != 18) {
				fd_log_debug("[invalid IP6 length: %d]", avp_value->os.len);
				return;
			}
			memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16);
			break;
		default:
			fd_log_debug("[unsupported family: 0x%hx]", fam);
			return;
	}

	sSA_DUMP_NODE(&s.sa, NI_NUMERICHOST);
192
193
194
195
196
197
198
199
200
201
202
}

static void UTF8String_dump(union avp_value * avp_value)
{
	size_t len = avp_value->os.len;
	if (len > 42)
		len = 42; /* avoid very long strings */
	fd_log_debug("%.*s", len, avp_value->os.data);
}


Sebastien Decugis's avatar
Sebastien Decugis committed
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269


#define CHECK_dict_new( _type, _data, _parent, _ref )				\
	CHECK_FCT(  fd_dict_new( dict, (_type), (_data), (_parent), (_ref))  );

#define CHECK_dict_search( _type, _criteria, _what, _result )					\
	CHECK_FCT(  fd_dict_search( dict, (_type), (_criteria), (_what), (_result), ENOENT)  );

struct local_rules_definition {
	char 			*avp_name;
	enum rule_position	position;
	int 			min;
	int			max;
};

#define RULE_ORDER( _position ) ((((_position) == RULE_FIXED_HEAD) || ((_position) == RULE_FIXED_TAIL)) ? 1 : 0 )

#define PARSE_loc_rules( _rulearray, _parent) {						\
	int __ar;									\
	for (__ar=0; __ar < sizeof(_rulearray) / sizeof((_rulearray)[0]); __ar++) {	\
		struct dict_rule_data __data = { NULL, 					\
			(_rulearray)[__ar].position,					\
			0, 								\
			(_rulearray)[__ar].min,						\
			(_rulearray)[__ar].max};					\
		__data.rule_order = RULE_ORDER(__data.rule_position);			\
		CHECK_FCT(  fd_dict_search( 						\
			dict,								\
			DICT_AVP, 							\
			AVP_BY_NAME, 							\
			(_rulearray)[__ar].avp_name, 					\
			&__data.rule_avp, 0 ) );					\
		if ( !__data.rule_avp ) {						\
			TRACE_DEBUG(INFO, "AVP Not found: '%s'", (_rulearray)[__ar].avp_name );	\
			return ENOENT;							\
		}									\
		CHECK_FCT_DO( fd_dict_new( dict, DICT_RULE, &__data, _parent, NULL),	\
			{								\
				TRACE_DEBUG(INFO, "Error on rule with AVP '%s'",	\
					 (_rulearray)[__ar].avp_name );			\
				return EINVAL;						\
			} );								\
	}										\
}

int fd_dict_base_protocol(struct dictionary * dict)
{
	TRACE_ENTRY("%p", dict);
	CHECK_PARAMS(dict);
	
	/* Vendors section */
	{
		/* The base RFC has no vendor information */
		;
	}
	
	/* Applications section */
	{
		/* base accounting application */
		{
			struct dict_application_data data = {          3, "Diameter Base Accounting" 	};
			CHECK_dict_new( DICT_APPLICATION, &data, NULL, NULL);
		}
		
		/* relay application */
		{
			struct dict_application_data data  = { 0xffffffff, "Relay" 				};
270
271
272
			#if AI_RELAY != 0xffffffff
			#error "AI_RELAY definition mismatch"
			#endif
Sebastien Decugis's avatar
Sebastien Decugis committed
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
			CHECK_dict_new( DICT_APPLICATION, &data , NULL, NULL);
		}
	}
	
	/* Derived AVP types section */
	{
		/* Address */
		{
			/*
				The Address format is derived from the OctetString AVP Base
				Format.  It is a discriminated union, representing, for example a
				32-bit (IPv4) [RFC791] or 128-bit (IPv6) [RFC4291] address, most
				significant octet first.  The first two octets of the Address AVP
				represents the AddressType, which contains an Address Family
				defined in [IANAADFAM].  The AddressType is used to discriminate
				the content and format of the remaining octets.
			*/
290
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Address"		, Address_interpret	, Address_encode,	Address_dump	};
Sebastien Decugis's avatar
Sebastien Decugis committed
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
		
		/* Time */
		{
			/*
				The Time format is derived from the OctetString AVP Base Format.
				The string MUST contain four octets, in the same format as the
				first four bytes are in the NTP timestamp format.  The NTP
				Timestamp format is defined in chapter 3 of [RFC4330].

				This represents the number of seconds since 0h on 1 January 1900
				with respect to the Coordinated Universal Time (UTC).

				On 6h 28m 16s UTC, 7 February 2036 the time value will overflow.
				SNTP [RFC4330] describes a procedure to extend the time to 2104.
				This procedure MUST be supported by all DIAMETER nodes.
			*/
309
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"Time"			, NULL			, NULL		, NULL		};
Sebastien Decugis's avatar
Sebastien Decugis committed
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
		
		/* UTF8String */
		{
			/*
				The UTF8String format is derived from the OctetString AVP Base
				Format.  This is a human readable string represented using the
				ISO/IEC IS 10646-1 character set, encoded as an OctetString using
				the UTF-8 [RFC3629] transformation format described in RFC 3629.

				Since additional code points are added by amendments to the 10646
				standard from time to time, implementations MUST be prepared to
				encounter any code point from 0x00000001 to 0x7fffffff.  Byte
				sequences that do not correspond to the valid encoding of a code
				point into UTF-8 charset or are outside this range are prohibited.

				The use of control codes SHOULD be avoided.  When it is necessary
				to represent a new line, the control code sequence CR LF SHOULD be
				used.

				The use of leading or trailing white space SHOULD be avoided.

				For code points not directly supported by user interface hardware
				or software, an alternative means of entry and display, such as
				hexadecimal, MAY be provided.

				For information encoded in 7-bit US-ASCII, the UTF-8 charset is
				identical to the US-ASCII charset.

				UTF-8 may require multiple bytes to represent a single character /
				code point; thus the length of an UTF8String in octets may be
				different from the number of characters encoded.

				Note that the AVP Length field of an UTF8String is measured in
				octets, not characters.
			*/
347
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"UTF8String"		, NULL			, NULL	, UTF8String_dump	};
Sebastien Decugis's avatar
Sebastien Decugis committed
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
		
		/* DiameterIdentity */
		{
			/*
				The DiameterIdentity format is derived from the OctetString AVP
				Base Format.

                				DiameterIdentity  = FQDN


				DiameterIdentity value is used to uniquely identify a Diameter
				node for purposes of duplicate connection and routing loop
				detection.

				The contents of the string MUST be the FQDN of the Diameter node.
				If multiple Diameter nodes run on the same host, each Diameter
				node MUST be assigned a unique DiameterIdentity.  If a Diameter

				node can be identified by several FQDNs, a single FQDN should be
				picked at startup, and used as the only DiameterIdentity for that
				node, whatever the connection it is sent on.  Note that in this
				document, DiameterIdentity is in ASCII form in order to be
				compatible with existing DNS infrastructure.  See Appendix D for
				interactions between the Diameter protocol and Internationalized
				Domain Name (IDNs).
			*/
376
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterIdentity"	, NULL			, NULL		, UTF8String_dump	};
Sebastien Decugis's avatar
Sebastien Decugis committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
		
		/* DiameterURI */
		{
			/*
				The DiameterURI MUST follow the Uniform Resource Identifiers (URI)
				syntax [RFC3986] rules specified below:

				 "aaa://" FQDN [ port ] [ transport ] [ protocol ]

                				 ; No transport security

				 "aaas://" FQDN [ port ] [ transport ] [ protocol ]

                				 ; Transport security used

				 FQDN               = Fully Qualified Host Name

				 port               = ":" 1*DIGIT

                				 ; One of the ports used to listen for
                				 ; incoming connections.
                				 ; If absent,
                				 ; the default Diameter port (3868) is
                				 ; assumed.

				 transport          = ";transport=" transport-protocol

                				 ; One of the transports used to listen
                				 ; for incoming connections.  If absent,
                				 ; the default SCTP [RFC2960] protocol is
                				 ; assumed. UDP MUST NOT be used when
                				 ; the aaa-protocol field is set to
                				 ; diameter.

				transport-protocol = ( "tcp" / "sctp" / "udp" )

				protocol           = ";protocol=" aaa-protocol

                				 ; If absent, the default AAA protocol
                				 ; is diameter.

				aaa-protocol       = ( "diameter" / "radius" / "tacacs+" )

				The following are examples of valid Diameter host identities:

				aaa://host.example.com;transport=tcp
				aaa://host.example.com:6666;transport=tcp
				aaa://host.example.com;protocol=diameter
				aaa://host.example.com:6666;protocol=diameter
				aaa://host.example.com:6666;transport=tcp;protocol=diameter
				aaa://host.example.com:1813;transport=udp;protocol=radius
			*/
431
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"DiameterURI"		, NULL			, NULL		, UTF8String_dump	};
Sebastien Decugis's avatar
Sebastien Decugis committed
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
		
		/* Enumerated */
		{
			/*
				Enumerated is derived from the Integer32 AVP Base Format.  The
				definition contains a list of valid values and their
				interpretation and is described in the Diameter application
				introducing the AVP.
			*/
			
			/* We don't use a generic "Enumerated" type in waaad. Instead, we define
			 * types of the form "Enumerated(<avpname>)" where <avpname> is replaced 
			 * by the name of the AVP to which the type applies.
			 *  Example: Enumerated(Disconnect-Cause)
			 */
			;
		}
		
		/* IPFilterRule */
		{
			/*
				The IPFilterRule format is derived from the OctetString AVP Base
				Format and uses the ASCII charset.  The rule syntax is a modified
				subset of ipfw(8) from FreeBSD.  Packets may be filtered based on
				the following information that is associated with it:

				    Direction                          (in or out)
				    Source and destination IP address  (possibly masked)
				    Protocol
				    Source and destination port        (lists or ranges)
				    TCP flags
				    IP fragment flag
				    IP options
				    ICMP types

				Rules for the appropriate direction are evaluated in order, with
				the first matched rule terminating the evaluation.  Each packet is
				evaluated once.  If no rule matches, the packet is dropped if the
				last rule evaluated was a permit, and passed if the last rule was
				a deny.

				IPFilterRule filters MUST follow the format:
				
				    action dir proto from src to dst [options]
				
			(...skipped loooong explanation...)
				
				There is one kind of packet that the access device MUST always
				discard, that is an IP fragment with a fragment offset of one.
				This is a valid packet, but it only has one use, to try to
				circumvent firewalls.

				An access device that is unable to interpret or apply a deny rule
				MUST terminate the session.  An access device that is unable to
				interpret or apply a permit rule MAY apply a more restrictive
				rule.  An access device MAY apply deny rules of its own before the
				supplied rules, for example to protect the access device owner's
				infrastructure.
			*/
493
			struct dict_type_data data = { AVP_TYPE_OCTETSTRING,	"IPFilterRule"		, NULL			, NULL		, UTF8String_dump	};
Sebastien Decugis's avatar
Sebastien Decugis committed
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
			CHECK_dict_new( DICT_TYPE, &data , NULL, NULL);
		}
	}
	
	/* AVP section */
	{
		struct dict_object * Address_type;
		struct dict_object * UTF8String_type;
		struct dict_object * DiameterIdentity_type;
		struct dict_object * DiameterURI_type;
		struct dict_object * Time_type;
		
		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Address", &Address_type);
		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "UTF8String", &UTF8String_type);
		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterIdentity", &DiameterIdentity_type);
		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "DiameterURI", &DiameterURI_type);
		CHECK_dict_search( DICT_TYPE, TYPE_BY_NAME, "Time", &Time_type);
		
		/* Vendor-Id */
		{
			/*
				The Vendor-Id AVP (AVP Code 266) is of type Unsigned32 and contains
				the IANA "SMI Network Management Private Enterprise Codes" [RFC3232]
				value assigned to the vendor of the Diameter device.  It is
				envisioned that the combination of the Vendor-Id, Product-Name
				(Section 5.3.7) and the Firmware-Revision (Section 5.3.4) AVPs may
				provide useful debugging information.

				A Vendor-Id value of zero in the CER or CEA messages is reserved and
				indicates that this field is ignored.
			*/
			struct dict_avp_data data = { 
					266, 					/* Code */
					#if AC_VENDOR_ID != 266
					#error "AC_VENDOR_ID definition mismatch"
					#endif
					0, 					/* Vendor */
					"Vendor-Id", 				/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY, 			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data, NULL, NULL);
		}
		
		/* Firmware-Revision */
		{
			/*
				The Firmware-Revision AVP (AVP Code 267) is of type Unsigned32 and is
				used to inform a Diameter peer of the firmware revision of the
				issuing device.

				For devices that do not have a firmware revision (general purpose
				computers running Diameter software modules, for instance), the
				revision of the Diameter software module may be reported instead.
			*/
			struct dict_avp_data data = { 
					267, 					/* Code */
					#if AC_FIRMWARE_REVISION != 267
					#error "AC_FIRMWARE_REVISION definition mismatch"
					#endif
					0, 					/* Vendor */
					"Firmware-Revision", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					0,		 			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
		}
		
		/* Host-IP-Address */
		{
			/*
				The Host-IP-Address AVP (AVP Code 257) is of type Address and is used
				to inform a Diameter peer of the sender's IP address.  All source
				addresses that a Diameter node expects to use with SCTP [RFC2960]
				MUST be advertised in the CER and CEA messages by including a
				Host-IP- Address AVP for each address.  This AVP MUST ONLY be used in
				the CER and CEA messages.
			*/
			struct dict_avp_data data = { 
					257, 					/* Code */
					#if AC_HOST_IP_ADDRESS != 257
					#error "AC_HOST_IP_ADDRESS definition mismatch"
					#endif
					0, 					/* Vendor */
					"Host-IP-Address", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , Address_type, NULL);
		}
		
		/* Supported-Vendor-Id */
		{
			/*
				The Supported-Vendor-Id AVP (AVP Code 265) is of type Unsigned32 and
				contains the IANA "SMI Network Management Private Enterprise Codes"
				[RFC3232] value assigned to a vendor other than the device vendor but
				including the application vendor.  This is used in the CER and CEA
				messages in order to inform the peer that the sender supports (a
				subset of) the vendor-specific AVPs defined by the vendor identified
				in this AVP.  The value of this AVP SHOULD NOT be set to zero.
				Multiple instances of this AVP containing the same value SHOULD NOT
				be sent.
			*/
			struct dict_avp_data data = { 
					265, 					/* Code */
					#if AC_SUPPORTED_VENDOR_ID != 265
					#error "AC_SUPPORTED_VENDOR_ID definition mismatch"
					#endif
					0, 					/* Vendor */
					"Supported-Vendor-Id", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
		}
		
		/* Product-Name */
		{
			/*
				The Product-Name AVP (AVP Code 269) is of type UTF8String, and
				contains the vendor assigned name for the product.  The Product-Name
				AVP SHOULD remain constant across firmware revisions for the same
				product.
			*/
			struct dict_avp_data data = { 
					269, 					/* Code */
					#if AC_PRODUCT_NAME != 269
					#error "AC_PRODUCT_NAME definition mismatch"
					#endif
					0, 					/* Vendor */
					"Product-Name", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					0,					/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , UTF8String_type, NULL);
		}
		
		/* Disconnect-Cause */
		{
			/*
				The Disconnect-Cause AVP (AVP Code 273) is of type Enumerated.  A
				Diameter node MUST include this AVP in the Disconnect-Peer-Request
				message to inform the peer of the reason for its intention to
				shutdown the transport connection.  The following values are
				supported:

				REBOOTING                         0
				A scheduled reboot is imminent. Receiver of DPR with above result
				code MAY attempt reconnection.

				BUSY                              1
				The peer's internal resources are constrained, and it has
				determined that the transport connection needs to be closed.
				Receiver of DPR with above result code SHOULD NOT attempt
				reconnection.

				DO_NOT_WANT_TO_TALK_TO_YOU        2
				The peer has determined that it does not see a need for the
				transport connection to exist, since it does not expect any
				messages to be exchanged in the near future. Receiver of DPR
				with above result code SHOULD NOT attempt reconnection.
			*/
			struct dict_object 	* 	type;
663
			struct dict_type_data 		tdata = { AVP_TYPE_INTEGER32,	"Enumerated(Disconnect-Cause)"	, NULL, NULL, NULL };
Sebastien Decugis's avatar
Sebastien Decugis committed
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
			struct dict_enumval_data 	t_0 = { "REBOOTING", 			{ .i32 = 0 }};
			struct dict_enumval_data 	t_1 = { "BUSY", 			{ .i32 = 1 }};
			struct dict_enumval_data 	t_2 = { "DO_NOT_WANT_TO_TALK_TO_YOU", 	{ .i32 = 2 }};
			struct dict_avp_data 		data = { 
					273, 					/* Code */
					#if AC_DISCONNECT_CAUSE != 273
					#error "AC_DISCONNECT_CAUSE definition mismatch"
					#endif
					0, 					/* Vendor */
					"Disconnect-Cause", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_INTEGER32 			/* base type of data */
					};
			/* Create the Enumerated type, and then the AVP */
			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
			CHECK_dict_new( DICT_ENUMVAL, &t_2 , type, NULL);
			CHECK_dict_new( DICT_AVP, &data , type, NULL);
		}
		
		/* Origin-Host */
		{
			/*
				The Origin-Host AVP (AVP Code 264) is of type DiameterIdentity, and
				MUST be present in all Diameter messages.  This AVP identifies the
				endpoint that originated the Diameter message.  Relay agents MUST NOT
				modify this AVP.

				The value of the Origin-Host AVP is guaranteed to be unique within a
				single host.

				Note that the Origin-Host AVP may resolve to more than one address as
				the Diameter peer may support more than one address.

				This AVP SHOULD be placed as close to the Diameter header as
				possible.
			*/
			struct dict_avp_data data = { 
					264, 					/* Code */
					#if AC_ORIGIN_HOST != 264
					#error "AC_ORIGIN_HOST definition mismatch"
					#endif
					0, 					/* Vendor */
					"Origin-Host", 				/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
		}
		
		/* Origin-Realm */
		{
			/*
				The Origin-Realm AVP (AVP Code 296) is of type DiameterIdentity.
				This AVP contains the Realm of the originator of any Diameter message
				and MUST be present in all messages.

				This AVP SHOULD be placed as close to the Diameter header as
				possible.
			*/
			struct dict_avp_data data = { 
					296, 					/* Code */
					#if AC_ORIGIN_REALM != 296
					#error "AC_ORIGIN_REALM definition mismatch"
					#endif
					0, 					/* Vendor */
					"Origin-Realm", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
		}
		
		/* Destination-Host */
		{
			/*
				The Destination-Host AVP (AVP Code 293) is of type DiameterIdentity.
				This AVP MUST be present in all unsolicited agent initiated messages,
				MAY be present in request messages, and MUST NOT be present in Answer
				messages.

				The absence of the Destination-Host AVP will cause a message to be
				sent to any Diameter server supporting the application within the
				realm specified in Destination-Realm AVP.

				This AVP SHOULD be placed as close to the Diameter header as
				possible.
			*/
			struct dict_avp_data data = { 
					293, 					/* Code */
					#if AC_DESTINATION_HOST != 293
					#error "AC_DESTINATION_HOST definition mismatch"
					#endif
					0, 					/* Vendor */
					"Destination-Host", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
		}
		
		/* Destination-Realm */
		{
			/*
				The Destination-Realm AVP (AVP Code 283) is of type DiameterIdentity,
				and contains the realm the message is to be routed to.  The
				Destination-Realm AVP MUST NOT be present in Answer messages.
				Diameter Clients insert the realm portion of the User-Name AVP.
				Diameter servers initiating a request message use the value of the
				Origin-Realm AVP from a previous message received from the intended
				target host (unless it is known a priori).  When present, the
				Destination-Realm AVP is used to perform message routing decisions.

				Request messages whose ABNF does not list the Destination-Realm AVP
				as a mandatory AVP are inherently non-routable messages.

				This AVP SHOULD be placed as close to the Diameter header as
				possible.
			*/
			struct dict_avp_data data = { 
					283, 					/* Code */
					#if AC_DESTINATION_REALM != 283
					#error "AC_DESTINATION_REALM definition mismatch"
					#endif
					0, 					/* Vendor */
					"Destination-Realm", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
		}
		
		/* Route-Record */
		{
			/*
				The Route-Record AVP (AVP Code 282) is of type DiameterIdentity.  The
				identity added in this AVP MUST be the same as the one received in
				the Origin-Host of the Capabilities Exchange message.
			*/
			struct dict_avp_data data = { 
					282, 					/* Code */
					#if AC_ROUTE_RECORD != 282
					#error "AC_ROUTE_RECORD definition mismatch"
					#endif
					0, 					/* Vendor */
					"Route-Record", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , DiameterIdentity_type, NULL);
		}
		
		/* Proxy-Host */
		{
			/*
				The Proxy-Host AVP (AVP Code 280) is of type DiameterIdentity.  This
				AVP contains the identity of the host that added the Proxy-Info AVP.
			*/
			struct dict_avp_data adata = { 
					280, 					/* Code */
					#if AC_PROXY_HOST != 280
					#error "AC_PROXY_HOST definition mismatch"
					#endif
					0, 					/* Vendor */
					"Proxy-Host", 				/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &adata , DiameterIdentity_type, NULL);
		}
		
		/* Proxy-State */
		{
			/*
				The Proxy-State AVP (AVP Code 33) is of type OctetString, and
				contains state local information, and MUST be treated as opaque data.
			*/
			struct dict_avp_data adata = { 
					33, 					/* Code */
					#if AC_PROXY_STATE != 33
					#error "AC_PROXY_STATE definition mismatch"
					#endif
					0, 					/* Vendor */
					"Proxy-State", 				/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_OCTETSTRING 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &adata , NULL, NULL);
		}
			
		/* Proxy-Info */
		{
			/*
				The Proxy-Info AVP (AVP Code 284) is of type Grouped.  The Grouped
				Data field has the following ABNF grammar:

				 Proxy-Info ::= < AVP Header: 284 >
                				{ Proxy-Host }
                				{ Proxy-State }
        				      * [ AVP ]
			*/
			struct dict_object * avp;
			struct dict_avp_data data = { 
					284, 					/* Code */
					#if AC_PROXY_INFO != 284
					#error "AC_PROXY_INFO definition mismatch"
					#endif
					0, 					/* Vendor */
					"Proxy-Info", 				/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_GROUPED 			/* base type of data */
					};
			struct local_rules_definition rules[] = 
						{ 	 {  "Proxy-Host", 			RULE_REQUIRED, -1, 1 }
							,{  "Proxy-State",			RULE_REQUIRED, -1, 1 }
						};
			
			CHECK_dict_new( DICT_AVP, &data , NULL, &avp);
			PARSE_loc_rules( rules, avp );
		}
		
		/* Auth-Application-Id */
		{
			/*
				The Auth-Application-Id AVP (AVP Code 258) is of type Unsigned32 and
				is used in order to advertise support of the Authentication and
				Authorization portion of an application (see Section 2.4).  If
				present in a message other than CER and CEA, the value of the Auth-
				Application-Id AVP MUST match the Application Id present in the
				Diameter message header.
			*/
			struct dict_avp_data data = { 
					258, 					/* Code */
					#if AC_AUTH_APPLICATION_ID != 258
					#error "AC_AUTH_APPLICATION_ID definition mismatch"
					#endif
					0, 					/* Vendor */
					"Auth-Application-Id", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
		}
		
		/* Acct-Application-Id */
		{
			/*
				The Acct-Application-Id AVP (AVP Code 259) is of type Unsigned32 and
				is used in order to advertise support of the Accounting portion of an
				application (see Section 2.4).  If present in a message other than
				CER and CEA, the value of the Acct-Application-Id AVP MUST match the
				Application Id present in the Diameter message header.
			*/
			struct dict_avp_data data = { 
					259, 					/* Code */
					#if AC_ACCT_APPLICATION_ID != 259
					#error "AC_ACCT_APPLICATION_ID definition mismatch"
					#endif
					0, 					/* Vendor */
					"Acct-Application-Id", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			CHECK_dict_new( DICT_AVP, &data , NULL, NULL);
		}
		
		/* Inband-Security-Id */
		{
			/*
				The Inband-Security-Id AVP (AVP Code 299) is of type Unsigned32 and
				is used in order to advertise support of the Security portion of the
				application.

				Currently, the following values are supported, but there is ample
				room to add new security Ids.


				NO_INBAND_SECURITY 0

				This peer does not support TLS.  This is the default value, if the
				AVP is omitted.

				TLS 1

				This node supports TLS security, as defined by [RFC4346].
			*/
			
			/* Although the RFC does not specify an "Enumerated" type here, we go forward and create one.
			 * This is the reason for the "*" in the type name
			 */
			
			struct dict_object 	* 	type;
968
			struct dict_type_data	 	tdata = { AVP_TYPE_UNSIGNED32,	"Enumerated*(Inband-Security-Id)"	, NULL, NULL, NULL };
969
970
			struct dict_enumval_data 	t_0 = { "NO_INBAND_SECURITY", 		{ .u32 = ACV_ISI_NO_INBAND_SECURITY }};
			struct dict_enumval_data 	t_1 = { "TLS", 			{ .u32 = ACV_ISI_TLS }};
Sebastien Decugis's avatar
Sebastien Decugis committed
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
			struct dict_avp_data 		data = { 
					299, 					/* Code */
					#if AC_INBAND_SECURITY_ID != 299
					#error "AC_INBAND_SECURITY_ID definition mismatch"
					#endif
					0, 					/* Vendor */
					"Inband-Security-Id", 			/* Name */
					AVP_FLAG_VENDOR | AVP_FLAG_MANDATORY, 	/* Fixed flags */
					AVP_FLAG_MANDATORY,			/* Fixed flag values */
					AVP_TYPE_UNSIGNED32 			/* base type of data */
					};
			/* Create the Enumerated type, and then the AVP */
			CHECK_dict_new( DICT_TYPE, &tdata , NULL, &type);
			CHECK_dict_new( DICT_ENUMVAL, &t_0 , type, NULL);
			CHECK_dict_new( DICT_ENUMVAL, &t_1 , type, NULL);
			CHECK_dict_new( DICT_AVP, &data , type, NULL);
		}
		
		/* Vendor-Specific-Application-Id */
		{
			/*
				The Vendor-Specific-Application-Id AVP (AVP Code 260) is of type
				Grouped and is used to advertise support of a vendor-specific
				Diameter Application.  Exactly one instance of either Auth-
				Application-Id or Acct-Application-Id AVP MUST be present.  The
				Application Id carried by either Auth-Application-Id or Acct-
				Application-Id AVP MUST comply with vendor specific Application Id
				assignment described in Sec 11.3.  It MUST also match the Application
				Id present in the diameter header except when used in a CER or CEA
				messages.
For faster browsing, not all history is shown. View entire blame