]> The Tcpdump Group git mirrors - tcpdump/blob - print-radius.c
RADIUS: Fixup the previous commit.
[tcpdump] / print-radius.c
1 /*
2 * Copyright (C) 2000 Alfredo Andres Omella. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * 3. The names of the authors may not be used to endorse or promote
15 * products derived from this software without specific prior
16 * written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23 /* \summary: Radius protocol printer */
24
25 /*
26 * Radius printer routines as specified on:
27 *
28 * RFC 2865:
29 * "Remote Authentication Dial In User Service (RADIUS)"
30 *
31 * RFC 2866:
32 * "RADIUS Accounting"
33 *
34 * RFC 2867:
35 * "RADIUS Accounting Modifications for Tunnel Protocol Support"
36 *
37 * RFC 2868:
38 * "RADIUS Attributes for Tunnel Protocol Support"
39 *
40 * RFC 2869:
41 * "RADIUS Extensions"
42 *
43 * RFC 3162:
44 * "RADIUS and IPv6"
45 *
46 * RFC 3580:
47 * "IEEE 802.1X Remote Authentication Dial In User Service (RADIUS)"
48 * "Usage Guidelines"
49 *
50 * RFC 4072:
51 * "Diameter Extensible Authentication Protocol (EAP) Application"
52 *
53 * RFC 4675:
54 * "RADIUS Attributes for Virtual LAN and Priority Support"
55 *
56 * RFC 4818:
57 * "RADIUS Delegated-IPv6-Prefix Attribute"
58 *
59 * RFC 4849:
60 * "RADIUS Filter Rule Attribute"
61 *
62 * RFC 5090:
63 * "RADIUS Extension for Digest Authentication"
64 *
65 * RFC 5176:
66 * "Dynamic Authorization Extensions to RADIUS"
67 *
68 * RFC 5447:
69 * "Diameter Mobile IPv6"
70 *
71 * RFC 5580:
72 * "Carrying Location Objects in RADIUS and Diameter"
73 *
74 * RFC 6572:
75 * "RADIUS Support for Proxy Mobile IPv6"
76 *
77 * RFC 7155:
78 * "Diameter Network Access Server Application"
79 *
80 * Alfredo Andres Omella (aandres@s21sec.com) v0.1 2000/09/15
81 *
82 * TODO: Among other things to print ok MacIntosh and Vendor values
83 */
84
85 #ifdef HAVE_CONFIG_H
86 #include <config.h>
87 #endif
88
89 #include "netdissect-stdinc.h"
90
91 #include <string.h>
92
93 #include "netdissect-ctype.h"
94
95 #include "netdissect.h"
96 #include "addrtoname.h"
97 #include "extract.h"
98 #include "oui.h"
99 #include "ntp.h"
100
101
102 #define TAM_SIZE(x) (sizeof(x)/sizeof(x[0]) )
103
104 #define PRINT_HEX(bytes_len, ptr_data) \
105 while(bytes_len) \
106 { \
107 ND_PRINT("%02X", *ptr_data ); \
108 ptr_data++; \
109 bytes_len--; \
110 }
111
112
113 /* Radius packet codes */
114 #define RADCMD_ACCESS_REQ 1 /* Access-Request */
115 #define RADCMD_ACCESS_ACC 2 /* Access-Accept */
116 #define RADCMD_ACCESS_REJ 3 /* Access-Reject */
117 #define RADCMD_ACCOUN_REQ 4 /* Accounting-Request */
118 #define RADCMD_ACCOUN_RES 5 /* Accounting-Response */
119 #define RADCMD_ACCESS_CHA 11 /* Access-Challenge */
120 #define RADCMD_STATUS_SER 12 /* Status-Server */
121 #define RADCMD_STATUS_CLI 13 /* Status-Client */
122 #define RADCMD_DISCON_REQ 40 /* Disconnect-Request */
123 #define RADCMD_DISCON_ACK 41 /* Disconnect-ACK */
124 #define RADCMD_DISCON_NAK 42 /* Disconnect-NAK */
125 #define RADCMD_COA_REQ 43 /* CoA-Request */
126 #define RADCMD_COA_ACK 44 /* CoA-ACK */
127 #define RADCMD_COA_NAK 45 /* CoA-NAK */
128 #define RADCMD_RESERVED 255 /* Reserved */
129
130 static const struct tok radius_command_values[] = {
131 { RADCMD_ACCESS_REQ, "Access-Request" },
132 { RADCMD_ACCESS_ACC, "Access-Accept" },
133 { RADCMD_ACCESS_REJ, "Access-Reject" },
134 { RADCMD_ACCOUN_REQ, "Accounting-Request" },
135 { RADCMD_ACCOUN_RES, "Accounting-Response" },
136 { RADCMD_ACCESS_CHA, "Access-Challenge" },
137 { RADCMD_STATUS_SER, "Status-Server" },
138 { RADCMD_STATUS_CLI, "Status-Client" },
139 { RADCMD_DISCON_REQ, "Disconnect-Request" },
140 { RADCMD_DISCON_ACK, "Disconnect-ACK" },
141 { RADCMD_DISCON_NAK, "Disconnect-NAK" },
142 { RADCMD_COA_REQ, "CoA-Request" },
143 { RADCMD_COA_ACK, "CoA-ACK" },
144 { RADCMD_COA_NAK, "CoA-NAK" },
145 { RADCMD_RESERVED, "Reserved" },
146 { 0, NULL}
147 };
148
149 /********************************/
150 /* Begin Radius Attribute types */
151 /********************************/
152 #define SERV_TYPE 6
153 #define FRM_IPADDR 8
154 #define LOG_IPHOST 14
155 #define LOG_SERVICE 15
156 #define FRM_IPX 23
157 #define SESSION_TIMEOUT 27
158 #define IDLE_TIMEOUT 28
159 #define FRM_ATALK_LINK 37
160 #define FRM_ATALK_NETWORK 38
161
162 #define ACCT_DELAY 41
163 #define ACCT_SESSION_TIME 46
164
165 #define EGRESS_VLAN_ID 56
166 #define EGRESS_VLAN_NAME 58
167
168 #define TUNNEL_TYPE 64
169 #define TUNNEL_MEDIUM 65
170 #define TUNNEL_CLIENT_END 66
171 #define TUNNEL_SERVER_END 67
172 #define TUNNEL_PASS 69
173
174 #define ARAP_PASS 70
175 #define ARAP_FEATURES 71
176
177 #define EAP_MESSAGE 79
178
179 #define TUNNEL_PRIV_GROUP 81
180 #define TUNNEL_ASSIGN_ID 82
181 #define TUNNEL_PREFERENCE 83
182
183 #define ARAP_CHALLENGE_RESP 84
184 #define ACCT_INT_INTERVAL 85
185
186 #define TUNNEL_CLIENT_AUTH 90
187 #define TUNNEL_SERVER_AUTH 91
188
189 #define ERROR_CAUSE 101
190 /********************************/
191 /* End Radius Attribute types */
192 /********************************/
193
194 #define RFC4675_TAGGED 0x31
195 #define RFC4675_UNTAGGED 0x32
196
197 static const struct tok rfc4675_tagged[] = {
198 { RFC4675_TAGGED, "Tagged" },
199 { RFC4675_UNTAGGED, "Untagged" },
200 { 0, NULL}
201 };
202
203
204 static void print_attr_string(netdissect_options *, const u_char *, u_int, u_short );
205 static void print_attr_num(netdissect_options *, const u_char *, u_int, u_short );
206 static void print_vendor_attr(netdissect_options *, const u_char *, u_int, u_short );
207 static void print_attr_address(netdissect_options *, const u_char *, u_int, u_short);
208 static void print_attr_address6(netdissect_options *, const u_char *, u_int, u_short);
209 static void print_attr_netmask6(netdissect_options *, const u_char *, u_int, u_short);
210 static void print_attr_mip6_home_link_prefix(netdissect_options *, const u_char *, u_int, u_short);
211 static void print_attr_operator_name(netdissect_options *, const u_char *, u_int, u_short);
212 static void print_attr_location_information(netdissect_options *, const u_char *, u_int, u_short);
213 static void print_attr_location_data(netdissect_options *, const u_char *, u_int, u_short);
214 static void print_basic_location_policy_rules(netdissect_options *, const u_char *, u_int, u_short);
215 static void print_attr_time(netdissect_options *, const u_char *, u_int, u_short);
216 static void print_attr_vector64(netdissect_options *, register const u_char *, u_int, u_short);
217 static void print_attr_strange(netdissect_options *, const u_char *, u_int, u_short);
218
219
220 struct radius_hdr { nd_uint8_t code; /* Radius packet code */
221 nd_uint8_t id; /* Radius packet id */
222 nd_uint16_t len; /* Radius total length */
223 nd_byte auth[16]; /* Authenticator */
224 };
225
226 #define MIN_RADIUS_LEN 20
227
228 struct radius_attr { nd_uint8_t type; /* Attribute type */
229 nd_uint8_t len; /* Attribute length */
230 };
231
232
233 /* Service-Type Attribute standard values */
234 static const char *serv_type[]={ NULL,
235 "Login",
236 "Framed",
237 "Callback Login",
238 "Callback Framed",
239 "Outbound",
240 "Administrative",
241 "NAS Prompt",
242 "Authenticate Only",
243 "Callback NAS Prompt",
244 "Call Check",
245 "Callback Administrative",
246 };
247
248 /* Framed-Protocol Attribute standard values */
249 static const char *frm_proto[]={ NULL,
250 "PPP",
251 "SLIP",
252 "ARAP",
253 "Gandalf proprietary",
254 "Xylogics IPX/SLIP",
255 "X.75 Synchronous",
256 };
257
258 /* Framed-Routing Attribute standard values */
259 static const char *frm_routing[]={ "None",
260 "Send",
261 "Listen",
262 "Send&Listen",
263 };
264
265 /* Framed-Compression Attribute standard values */
266 static const char *frm_comp[]={ "None",
267 "VJ TCP/IP",
268 "IPX",
269 "Stac-LZS",
270 };
271
272 /* Login-Service Attribute standard values */
273 static const char *login_serv[]={ "Telnet",
274 "Rlogin",
275 "TCP Clear",
276 "PortMaster(proprietary)",
277 "LAT",
278 "X.25-PAD",
279 "X.25-T3POS",
280 "Unassigned",
281 "TCP Clear Quiet",
282 };
283
284
285 /* Termination-Action Attribute standard values */
286 static const char *term_action[]={ "Default",
287 "RADIUS-Request",
288 };
289
290 /* Ingress-Filters Attribute standard values */
291 static const char *ingress_filters[]={ NULL,
292 "Enabled",
293 "Disabled",
294 };
295
296 /* NAS-Port-Type Attribute standard values */
297 static const char *nas_port_type[]={ "Async",
298 "Sync",
299 "ISDN Sync",
300 "ISDN Async V.120",
301 "ISDN Async V.110",
302 "Virtual",
303 "PIAFS",
304 "HDLC Clear Channel",
305 "X.25",
306 "X.75",
307 "G.3 Fax",
308 "SDSL",
309 "ADSL-CAP",
310 "ADSL-DMT",
311 "ISDN-DSL",
312 "Ethernet",
313 "xDSL",
314 "Cable",
315 "Wireless - Other",
316 "Wireless - IEEE 802.11",
317 };
318
319 /* Acct-Status-Type Accounting Attribute standard values */
320 static const char *acct_status[]={ NULL,
321 "Start",
322 "Stop",
323 "Interim-Update",
324 "Unassigned",
325 "Unassigned",
326 "Unassigned",
327 "Accounting-On",
328 "Accounting-Off",
329 "Tunnel-Start",
330 "Tunnel-Stop",
331 "Tunnel-Reject",
332 "Tunnel-Link-Start",
333 "Tunnel-Link-Stop",
334 "Tunnel-Link-Reject",
335 "Failed",
336 };
337
338 /* Acct-Authentic Accounting Attribute standard values */
339 static const char *acct_auth[]={ NULL,
340 "RADIUS",
341 "Local",
342 "Remote",
343 };
344
345 /* Acct-Terminate-Cause Accounting Attribute standard values */
346 static const char *acct_term[]={ NULL,
347 "User Request",
348 "Lost Carrier",
349 "Lost Service",
350 "Idle Timeout",
351 "Session Timeout",
352 "Admin Reset",
353 "Admin Reboot",
354 "Port Error",
355 "NAS Error",
356 "NAS Request",
357 "NAS Reboot",
358 "Port Unneeded",
359 "Port Preempted",
360 "Port Suspended",
361 "Service Unavailable",
362 "Callback",
363 "User Error",
364 "Host Request",
365 };
366
367 /* Tunnel-Type Attribute standard values */
368 static const char *tunnel_type[]={ NULL,
369 "PPTP",
370 "L2F",
371 "L2TP",
372 "ATMP",
373 "VTP",
374 "AH",
375 "IP-IP",
376 "MIN-IP-IP",
377 "ESP",
378 "GRE",
379 "DVS",
380 "IP-in-IP Tunneling",
381 "VLAN",
382 };
383
384 /* Tunnel-Medium-Type Attribute standard values */
385 static const char *tunnel_medium[]={ NULL,
386 "IPv4",
387 "IPv6",
388 "NSAP",
389 "HDLC",
390 "BBN 1822",
391 "802",
392 "E.163",
393 "E.164",
394 "F.69",
395 "X.121",
396 "IPX",
397 "Appletalk",
398 "Decnet IV",
399 "Banyan Vines",
400 "E.164 with NSAP subaddress",
401 };
402
403 /* ARAP-Zone-Access Attribute standard values */
404 static const char *arap_zone[]={ NULL,
405 "Only access to dfl zone",
406 "Use zone filter inc.",
407 "Not used",
408 "Use zone filter exc.",
409 };
410
411 static const char *prompt[]={ "No Echo",
412 "Echo",
413 };
414
415 /* Error-Cause standard values */
416 #define ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED 201
417 #define ERROR_CAUSE_INVALID_EAP_PACKET 202
418 #define ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE 401
419 #define ERROR_CAUSE_MISSING_ATTRIBUTE 402
420 #define ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH 403
421 #define ERROR_CAUSE_INVALID_REQUEST 404
422 #define ERROR_CAUSE_UNSUPPORTED_SERVICE 405
423 #define ERROR_CAUSE_UNSUPPORTED_EXTENSION 406
424 #define ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE 407
425 #define ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED 501
426 #define ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE 502
427 #define ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND 503
428 #define ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE 504
429 #define ERROR_CAUSE_PROXY_PROCESSING_ERROR 505
430 #define ERROR_CAUSE_RESOURCES_UNAVAILABLE 506
431 #define ERROR_CAUSE_REQUEST_INITIATED 507
432 #define ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED 508
433 #define ERROR_CAUSE_LOCATION_INFO_REQUIRED 509
434 static const struct tok errorcausetype[] = {
435 { ERROR_CAUSE_RESIDUAL_CONTEXT_REMOVED, "Residual Session Context Removed" },
436 { ERROR_CAUSE_INVALID_EAP_PACKET, "Invalid EAP Packet (Ignored)" },
437 { ERROR_CAUSE_UNSUPPORTED_ATTRIBUTE, "Unsupported Attribute" },
438 { ERROR_CAUSE_MISSING_ATTRIBUTE, "Missing Attribute" },
439 { ERROR_CAUSE_NAS_IDENTIFICATION_MISMATCH, "NAS Identification Mismatch" },
440 { ERROR_CAUSE_INVALID_REQUEST, "Invalid Request" },
441 { ERROR_CAUSE_UNSUPPORTED_SERVICE, "Unsupported Service" },
442 { ERROR_CAUSE_UNSUPPORTED_EXTENSION, "Unsupported Extension" },
443 { ERROR_CAUSE_INVALID_ATTRIBUTE_VALUE, "Invalid Attribute Value" },
444 { ERROR_CAUSE_ADMINISTRATIVELY_PROHIBITED, "Administratively Prohibited" },
445 { ERROR_CAUSE_PROXY_REQUEST_NOT_ROUTABLE, "Request Not Routable (Proxy)" },
446 { ERROR_CAUSE_SESSION_CONTEXT_NOT_FOUND, "Session Context Not Found" },
447 { ERROR_CAUSE_SESSION_CONTEXT_NOT_REMOVABLE, "Session Context Not Removable" },
448 { ERROR_CAUSE_PROXY_PROCESSING_ERROR, "Other Proxy Processing Error" },
449 { ERROR_CAUSE_RESOURCES_UNAVAILABLE, "Resources Unavailable" },
450 { ERROR_CAUSE_REQUEST_INITIATED, "Request Initiated" },
451 { ERROR_CAUSE_MULTIPLE_SESSION_SELECTION_UNSUPPORTED, "Multiple Session Selection Unsupported" },
452 { ERROR_CAUSE_LOCATION_INFO_REQUIRED, "Location Info Required" },
453 { 0, NULL }
454 };
455
456 /* MIP6-Feature-Vector standard values */
457 /* https://www.iana.org/assignments/aaa-parameters/aaa-parameters.xhtml */
458 #define MIP6_INTEGRATED 0x0000000000000001
459 #define LOCAL_HOME_AGENT_ASSIGNMENT 0x0000000000000002
460 #define PMIP6_SUPPORTED 0x0000010000000000
461 #define IP4_HOA_SUPPORTED 0x0000020000000000
462 #define LOCAL_MAG_ROUTING_SUPPORTED 0x0000040000000000
463 #define ASSIGN_LOCAL_IP 0x0000080000000000
464 #define MIP4_SUPPORTED 0x0000100000000000
465 #define OPTIMIZED_IDLE_MODE_MOBILITY 0x0000200000000000
466 #define GTPv2_SUPPORTED 0x0000400000000000
467 #define IP4_TRANSPORT_SUPPORTED 0x0000800000000000
468 #define IP4_HOA_ONLY_SUPPORTED 0x0001000000000000
469 #define INTER_MAG_ROUTING_SUPPORTED 0x0002000000000000
470 static const struct mip6_feature_vector {
471 uint64_t v;
472 const char *s;
473 } mip6_feature_vector[] = {
474 { MIP6_INTEGRATED, "MIP6_INTEGRATED" },
475 { LOCAL_HOME_AGENT_ASSIGNMENT, "LOCAL_HOME_AGENT_ASSIGNMENT" },
476 { PMIP6_SUPPORTED, "PMIP6_SUPPORTED" },
477 { IP4_HOA_SUPPORTED, "IP4_HOA_SUPPORTED" },
478 { LOCAL_MAG_ROUTING_SUPPORTED, "LOCAL_MAG_ROUTING_SUPPORTED" },
479 { ASSIGN_LOCAL_IP, "ASSIGN_LOCAL_IP" },
480 { MIP4_SUPPORTED, "MIP4_SUPPORTED" },
481 { OPTIMIZED_IDLE_MODE_MOBILITY, "OPTIMIZED_IDLE_MODE_MOBILITY" },
482 { GTPv2_SUPPORTED, "GTPv2_SUPPORTED" },
483 { IP4_TRANSPORT_SUPPORTED, "IP4_TRANSPORT_SUPPORTED" },
484 { IP4_HOA_ONLY_SUPPORTED, "IP4_HOA_ONLY_SUPPORTED" },
485 { INTER_MAG_ROUTING_SUPPORTED, "INTER_MAG_ROUTING_SUPPORTED" },
486 };
487
488 #define OPERATOR_NAME_TADIG 0x30
489 #define OPERATOR_NAME_REALM 0x31
490 #define OPERATOR_NAME_E212 0x32
491 #define OPERATOR_NAME_ICC 0x33
492 static const struct tok operator_name_vector[] = {
493 { OPERATOR_NAME_TADIG, "TADIG" },
494 { OPERATOR_NAME_REALM, "REALM" },
495 { OPERATOR_NAME_E212, "E212" },
496 { OPERATOR_NAME_ICC, "ICC" },
497 { 0, NULL }
498 };
499
500 #define LOCATION_INFORMATION_CODE_CIVIC 0
501 #define LOCATION_INFORMATION_CODE_GEOSPATIAL 1
502 static const struct tok location_information_code_vector[] = {
503 { LOCATION_INFORMATION_CODE_CIVIC , "Civic" },
504 { LOCATION_INFORMATION_CODE_GEOSPATIAL, "Geospatial" },
505 { 0, NULL }
506 };
507
508 #define LOCATION_INFORMATION_ENTITY_USER 0
509 #define LOCATION_INFORMATION_ENTITY_RADIUS 1
510 static const struct tok location_information_entity_vector[] = {
511 { LOCATION_INFORMATION_ENTITY_USER, "User" },
512 { LOCATION_INFORMATION_ENTITY_RADIUS, "RADIUS" },
513 { 0, NULL }
514 };
515
516 static const struct tok blpr_bm[] = {
517 { 0x0001, "MBZ-15" },
518 { 0x0002, "MBZ-14" },
519 { 0x0004, "MBZ-13" },
520 { 0x0008, "MBZ-12" },
521 { 0x0010, "MBZ-11" },
522 { 0x0020, "MBZ-10" },
523 { 0x0040, "MBZ-9" },
524 { 0x0080, "MBZ-8" },
525 { 0x0100, "MBZ-7" },
526 { 0x0200, "MBZ-6" },
527 { 0x0400, "MBZ-5" },
528 { 0x0800, "MBZ-4" },
529 { 0x1000, "MBZ-3" },
530 { 0x2000, "MBZ-2" },
531 { 0x4000, "MBZ-1" },
532 { 0x8000, "Retransmission Allowed" },
533 { 0, NULL }
534 };
535
536 static const struct attrtype {
537 const char *name; /* Attribute name */
538 const char **subtypes; /* Standard Values (if any) */
539 u_char siz_subtypes; /* Size of total standard values */
540 u_char first_subtype; /* First standard value is 0 or 1 */
541 void (*print_func)(netdissect_options *, const u_char *, u_int, u_short);
542 } attr_type[]=
543 {
544 { NULL, NULL, 0, 0, NULL },
545 { "User-Name", NULL, 0, 0, print_attr_string },
546 { "User-Password", NULL, 0, 0, NULL },
547 { "CHAP-Password", NULL, 0, 0, NULL },
548 { "NAS-IP-Address", NULL, 0, 0, print_attr_address },
549 { "NAS-Port", NULL, 0, 0, print_attr_num },
550 { "Service-Type", serv_type, TAM_SIZE(serv_type)-1, 1, print_attr_num },
551 { "Framed-Protocol", frm_proto, TAM_SIZE(frm_proto)-1, 1, print_attr_num },
552 { "Framed-IP-Address", NULL, 0, 0, print_attr_address },
553 { "Framed-IP-Netmask", NULL, 0, 0, print_attr_address },
554 { "Framed-Routing", frm_routing, TAM_SIZE(frm_routing), 0, print_attr_num },
555 { "Filter-Id", NULL, 0, 0, print_attr_string },
556 { "Framed-MTU", NULL, 0, 0, print_attr_num },
557 { "Framed-Compression", frm_comp, TAM_SIZE(frm_comp), 0, print_attr_num },
558 { "Login-IP-Host", NULL, 0, 0, print_attr_address },
559 { "Login-Service", login_serv, TAM_SIZE(login_serv), 0, print_attr_num },
560 { "Login-TCP-Port", NULL, 0, 0, print_attr_num },
561 { "Unassigned", NULL, 0, 0, NULL }, /*17*/
562 { "Reply-Message", NULL, 0, 0, print_attr_string },
563 { "Callback-Number", NULL, 0, 0, print_attr_string },
564 { "Callback-Id", NULL, 0, 0, print_attr_string },
565 { "Unassigned", NULL, 0, 0, NULL }, /*21*/
566 { "Framed-Route", NULL, 0, 0, print_attr_string },
567 { "Framed-IPX-Network", NULL, 0, 0, print_attr_num },
568 { "State", NULL, 0, 0, print_attr_string },
569 { "Class", NULL, 0, 0, print_attr_string },
570 { "Vendor-Specific", NULL, 0, 0, print_vendor_attr },
571 { "Session-Timeout", NULL, 0, 0, print_attr_num },
572 { "Idle-Timeout", NULL, 0, 0, print_attr_num },
573 { "Termination-Action", term_action, TAM_SIZE(term_action), 0, print_attr_num },
574 { "Called-Station-Id", NULL, 0, 0, print_attr_string },
575 { "Calling-Station-Id", NULL, 0, 0, print_attr_string },
576 { "NAS-Identifier", NULL, 0, 0, print_attr_string },
577 { "Proxy-State", NULL, 0, 0, print_attr_string },
578 { "Login-LAT-Service", NULL, 0, 0, print_attr_string },
579 { "Login-LAT-Node", NULL, 0, 0, print_attr_string },
580 { "Login-LAT-Group", NULL, 0, 0, print_attr_string },
581 { "Framed-AppleTalk-Link", NULL, 0, 0, print_attr_num },
582 { "Framed-AppleTalk-Network", NULL, 0, 0, print_attr_num },
583 { "Framed-AppleTalk-Zone", NULL, 0, 0, print_attr_string },
584 { "Acct-Status-Type", acct_status, TAM_SIZE(acct_status)-1, 1, print_attr_num },
585 { "Acct-Delay-Time", NULL, 0, 0, print_attr_num },
586 { "Acct-Input-Octets", NULL, 0, 0, print_attr_num },
587 { "Acct-Output-Octets", NULL, 0, 0, print_attr_num },
588 { "Acct-Session-Id", NULL, 0, 0, print_attr_string },
589 { "Acct-Authentic", acct_auth, TAM_SIZE(acct_auth)-1, 1, print_attr_num },
590 { "Acct-Session-Time", NULL, 0, 0, print_attr_num },
591 { "Acct-Input-Packets", NULL, 0, 0, print_attr_num },
592 { "Acct-Output-Packets", NULL, 0, 0, print_attr_num },
593 { "Acct-Terminate-Cause", acct_term, TAM_SIZE(acct_term)-1, 1, print_attr_num },
594 { "Acct-Multi-Session-Id", NULL, 0, 0, print_attr_string },
595 { "Acct-Link-Count", NULL, 0, 0, print_attr_num },
596 { "Acct-Input-Gigawords", NULL, 0, 0, print_attr_num },
597 { "Acct-Output-Gigawords", NULL, 0, 0, print_attr_num },
598 { "Unassigned", NULL, 0, 0, NULL }, /*54*/
599 { "Event-Timestamp", NULL, 0, 0, print_attr_time },
600 { "Egress-VLANID", NULL, 0, 0, print_attr_num },
601 { "Ingress-Filters", ingress_filters, TAM_SIZE(ingress_filters)-1, 1, print_attr_num },
602 { "Egress-VLAN-Name", NULL, 0, 0, print_attr_string },
603 { "User-Priority-Table", NULL, 0, 0, NULL },
604 { "CHAP-Challenge", NULL, 0, 0, print_attr_string },
605 { "NAS-Port-Type", nas_port_type, TAM_SIZE(nas_port_type), 0, print_attr_num },
606 { "Port-Limit", NULL, 0, 0, print_attr_num },
607 { "Login-LAT-Port", NULL, 0, 0, print_attr_string }, /*63*/
608 { "Tunnel-Type", tunnel_type, TAM_SIZE(tunnel_type)-1, 1, print_attr_num },
609 { "Tunnel-Medium-Type", tunnel_medium, TAM_SIZE(tunnel_medium)-1, 1, print_attr_num },
610 { "Tunnel-Client-Endpoint", NULL, 0, 0, print_attr_string },
611 { "Tunnel-Server-Endpoint", NULL, 0, 0, print_attr_string },
612 { "Acct-Tunnel-Connection", NULL, 0, 0, print_attr_string },
613 { "Tunnel-Password", NULL, 0, 0, print_attr_string },
614 { "ARAP-Password", NULL, 0, 0, print_attr_strange },
615 { "ARAP-Features", NULL, 0, 0, print_attr_strange },
616 { "ARAP-Zone-Access", arap_zone, TAM_SIZE(arap_zone)-1, 1, print_attr_num }, /*72*/
617 { "ARAP-Security", NULL, 0, 0, print_attr_string },
618 { "ARAP-Security-Data", NULL, 0, 0, print_attr_string },
619 { "Password-Retry", NULL, 0, 0, print_attr_num },
620 { "Prompt", prompt, TAM_SIZE(prompt), 0, print_attr_num },
621 { "Connect-Info", NULL, 0, 0, print_attr_string },
622 { "Configuration-Token", NULL, 0, 0, print_attr_string },
623 { "EAP-Message", NULL, 0, 0, print_attr_string },
624 { "Message-Authenticator", NULL, 0, 0, print_attr_string }, /*80*/
625 { "Tunnel-Private-Group-ID", NULL, 0, 0, print_attr_string },
626 { "Tunnel-Assignment-ID", NULL, 0, 0, print_attr_string },
627 { "Tunnel-Preference", NULL, 0, 0, print_attr_num },
628 { "ARAP-Challenge-Response", NULL, 0, 0, print_attr_strange },
629 { "Acct-Interim-Interval", NULL, 0, 0, print_attr_num },
630 { "Acct-Tunnel-Packets-Lost", NULL, 0, 0, print_attr_num }, /*86*/
631 { "NAS-Port-Id", NULL, 0, 0, print_attr_string },
632 { "Framed-Pool", NULL, 0, 0, print_attr_string },
633 { "CUI", NULL, 0, 0, print_attr_string },
634 { "Tunnel-Client-Auth-ID", NULL, 0, 0, print_attr_string },
635 { "Tunnel-Server-Auth-ID", NULL, 0, 0, print_attr_string },
636 { "NAS-Filter-Rule", NULL, 0, 0, print_attr_string },
637 { "Unassigned", NULL, 0, 0, NULL }, /*93*/
638 { "Originating-Line-Info", NULL, 0, 0, NULL },
639 { "NAS-IPv6-Address", NULL, 0, 0, print_attr_address6 },
640 { "Framed-Interface-ID", NULL, 0, 0, NULL },
641 { "Framed-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 },
642 { "Login-IPv6-Host", NULL, 0, 0, print_attr_address6 },
643 { "Framed-IPv6-Route", NULL, 0, 0, print_attr_string },
644 { "Framed-IPv6-Pool", NULL, 0, 0, print_attr_string },
645 { "Error-Cause", NULL, 0, 0, print_attr_strange },
646 { "EAP-Key-Name", NULL, 0, 0, NULL },
647 { "Digest-Response", NULL, 0, 0, print_attr_string },
648 { "Digest-Realm", NULL, 0, 0, print_attr_string },
649 { "Digest-Nonce", NULL, 0, 0, print_attr_string },
650 { "Digest-Response-Auth", NULL, 0, 0, print_attr_string },
651 { "Digest-Nextnonce", NULL, 0, 0, print_attr_string },
652 { "Digest-Method", NULL, 0, 0, print_attr_string },
653 { "Digest-URI", NULL, 0, 0, print_attr_string },
654 { "Digest-Qop", NULL, 0, 0, print_attr_string },
655 { "Digest-Algorithm", NULL, 0, 0, print_attr_string },
656 { "Digest-Entity-Body-Hash", NULL, 0, 0, print_attr_string },
657 { "Digest-CNonce", NULL, 0, 0, print_attr_string },
658 { "Digest-Nonce-Count", NULL, 0, 0, print_attr_string },
659 { "Digest-Username", NULL, 0, 0, print_attr_string },
660 { "Digest-Opaque", NULL, 0, 0, print_attr_string },
661 { "Digest-Auth-Param", NULL, 0, 0, print_attr_string },
662 { "Digest-AKA-Auts", NULL, 0, 0, print_attr_string },
663 { "Digest-Domain", NULL, 0, 0, print_attr_string },
664 { "Digest-Stale", NULL, 0, 0, print_attr_string },
665 { "Digest-HA1", NULL, 0, 0, print_attr_string },
666 { "SIP-AOR", NULL, 0, 0, print_attr_string },
667 { "Delegated-IPv6-Prefix", NULL, 0, 0, print_attr_netmask6 },
668 { "MIP6-Feature-Vector", NULL, 0, 0, print_attr_vector64 },
669 { "MIP6-Home-Link-Prefix", NULL, 0, 0, print_attr_mip6_home_link_prefix },
670 { "Operator-Name", NULL, 0, 0, print_attr_operator_name },
671 { "Location-Information", NULL, 0, 0, print_attr_location_information },
672 { "Location-Data", NULL, 0, 0, print_attr_location_data },
673 { "Basic-Location-Policy-Rules", NULL, 0, 0, print_basic_location_policy_rules }
674 };
675
676
677 /*****************************/
678 /* Print an attribute string */
679 /* value pointed by 'data' */
680 /* and 'length' size. */
681 /*****************************/
682 /* Returns nothing. */
683 /*****************************/
684 static void
685 print_attr_string(netdissect_options *ndo,
686 const u_char *data, u_int length, u_short attr_code)
687 {
688 u_int i;
689
690 ND_TCHECK_LEN(data, length);
691
692 switch(attr_code)
693 {
694 case TUNNEL_PASS:
695 if (length < 3)
696 goto trunc;
697 if (GET_U_1(data) && (GET_U_1(data) <= 0x1F))
698 ND_PRINT("Tag[%u] ", GET_U_1(data));
699 else
700 ND_PRINT("Tag[Unused] ");
701 data++;
702 length--;
703 ND_PRINT("Salt %u ", GET_BE_U_2(data));
704 data+=2;
705 length-=2;
706 break;
707 case TUNNEL_CLIENT_END:
708 case TUNNEL_SERVER_END:
709 case TUNNEL_PRIV_GROUP:
710 case TUNNEL_ASSIGN_ID:
711 case TUNNEL_CLIENT_AUTH:
712 case TUNNEL_SERVER_AUTH:
713 if (GET_U_1(data) <= 0x1F)
714 {
715 if (length < 1)
716 goto trunc;
717 if (GET_U_1(data))
718 ND_PRINT("Tag[%u] ", GET_U_1(data));
719 else
720 ND_PRINT("Tag[Unused] ");
721 data++;
722 length--;
723 }
724 break;
725 case EGRESS_VLAN_NAME:
726 if (length < 1)
727 goto trunc;
728 ND_PRINT("%s (0x%02x) ",
729 tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
730 GET_U_1(data));
731 data++;
732 length--;
733 break;
734 case EAP_MESSAGE:
735 if (length < 1)
736 goto trunc;
737 eap_print(ndo, data, length);
738 return;
739 }
740
741 for (i=0; i < length && GET_U_1(data); i++, data++)
742 ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
743
744 return;
745
746 trunc:
747 nd_print_trunc(ndo);
748 }
749
750 /*
751 * print vendor specific attributes
752 */
753 static void
754 print_vendor_attr(netdissect_options *ndo,
755 const u_char *data, u_int length, u_short attr_code _U_)
756 {
757 u_int idx;
758 u_int vendor_id;
759 u_int vendor_type;
760 u_int vendor_length;
761
762 if (length < 4)
763 goto trunc;
764 ND_TCHECK_4(data);
765 vendor_id = GET_BE_U_4(data);
766 data+=4;
767 length-=4;
768
769 ND_PRINT("Vendor: %s (%u)",
770 tok2str(smi_values,"Unknown",vendor_id),
771 vendor_id);
772
773 while (length >= 2) {
774 ND_TCHECK_2(data);
775
776 vendor_type = GET_U_1(data);
777 vendor_length = GET_U_1(data + 1);
778
779 if (vendor_length < 2)
780 {
781 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, must be >= 2)",
782 vendor_type,
783 vendor_length);
784 return;
785 }
786 if (vendor_length > length)
787 {
788 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u (bogus, goes past end of vendor-specific attribute)",
789 vendor_type,
790 vendor_length);
791 return;
792 }
793 data+=2;
794 vendor_length-=2;
795 length-=2;
796 ND_TCHECK_LEN(data, vendor_length);
797
798 ND_PRINT("\n\t Vendor Attribute: %u, Length: %u, Value: ",
799 vendor_type,
800 vendor_length);
801 for (idx = 0; idx < vendor_length ; idx++, data++)
802 ND_PRINT("%c", ND_ASCII_ISPRINT(GET_U_1(data)) ? GET_U_1(data) : '.');
803 length-=vendor_length;
804 }
805 return;
806
807 trunc:
808 nd_print_trunc(ndo);
809 }
810
811 /******************************/
812 /* Print an attribute numeric */
813 /* value pointed by 'data' */
814 /* and 'length' size. */
815 /******************************/
816 /* Returns nothing. */
817 /******************************/
818 static void
819 print_attr_num(netdissect_options *ndo,
820 const u_char *data, u_int length, u_short attr_code)
821 {
822 uint32_t timeout;
823
824 if (length != 4)
825 {
826 ND_PRINT("ERROR: length %u != 4", length);
827 return;
828 }
829
830 ND_TCHECK_4(data);
831 /* This attribute has standard values */
832 if (attr_type[attr_code].siz_subtypes)
833 {
834 static const char **table;
835 uint32_t data_value;
836 table = attr_type[attr_code].subtypes;
837
838 if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) )
839 {
840 if (!GET_U_1(data))
841 ND_PRINT("Tag[Unused] ");
842 else
843 ND_PRINT("Tag[%u] ", GET_U_1(data));
844 data++;
845 data_value = GET_BE_U_3(data);
846 }
847 else
848 {
849 data_value = GET_BE_U_4(data);
850 }
851 if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 +
852 attr_type[attr_code].first_subtype) &&
853 data_value >= attr_type[attr_code].first_subtype )
854 ND_PRINT("%s", table[data_value]);
855 else
856 ND_PRINT("#%u", data_value);
857 }
858 else
859 {
860 switch(attr_code) /* Be aware of special cases... */
861 {
862 case FRM_IPX:
863 if (GET_BE_U_4(data) == 0xFFFFFFFE )
864 ND_PRINT("NAS Select");
865 else
866 ND_PRINT("%u", GET_BE_U_4(data));
867 break;
868
869 case SESSION_TIMEOUT:
870 case IDLE_TIMEOUT:
871 case ACCT_DELAY:
872 case ACCT_SESSION_TIME:
873 case ACCT_INT_INTERVAL:
874 timeout = GET_BE_U_4(data);
875 if ( timeout < 60 )
876 ND_PRINT("%02d secs", timeout);
877 else
878 {
879 if ( timeout < 3600 )
880 ND_PRINT("%02d:%02d min",
881 timeout / 60, timeout % 60);
882 else
883 ND_PRINT("%02d:%02d:%02d hours",
884 timeout / 3600, (timeout % 3600) / 60,
885 timeout % 60);
886 }
887 break;
888
889 case FRM_ATALK_LINK:
890 if (GET_BE_U_4(data))
891 ND_PRINT("%u", GET_BE_U_4(data));
892 else
893 ND_PRINT("Unnumbered");
894 break;
895
896 case FRM_ATALK_NETWORK:
897 if (GET_BE_U_4(data))
898 ND_PRINT("%u", GET_BE_U_4(data));
899 else
900 ND_PRINT("NAS assigned");
901 break;
902
903 case TUNNEL_PREFERENCE:
904 if (GET_U_1(data))
905 ND_PRINT("Tag[%u] ", GET_U_1(data));
906 else
907 ND_PRINT("Tag[Unused] ");
908 data++;
909 ND_PRINT("%u", GET_BE_U_3(data));
910 break;
911
912 case EGRESS_VLAN_ID:
913 ND_PRINT("%s (0x%02x) ",
914 tok2str(rfc4675_tagged,"Unknown tag",GET_U_1(data)),
915 GET_U_1(data));
916 data++;
917 ND_PRINT("%u", GET_BE_U_3(data));
918 break;
919
920 default:
921 ND_PRINT("%u", GET_BE_U_4(data));
922 break;
923
924 } /* switch */
925
926 } /* if-else */
927
928 return;
929
930 trunc:
931 nd_print_trunc(ndo);
932 }
933
934 /*****************************/
935 /* Print an attribute IPv4 */
936 /* address value pointed by */
937 /* 'data' and 'length' size. */
938 /*****************************/
939 /* Returns nothing. */
940 /*****************************/
941 static void
942 print_attr_address(netdissect_options *ndo,
943 const u_char *data, u_int length, u_short attr_code)
944 {
945 if (length != 4)
946 {
947 ND_PRINT("ERROR: length %u != 4", length);
948 return;
949 }
950
951 ND_TCHECK_4(data);
952
953 switch(attr_code)
954 {
955 case FRM_IPADDR:
956 case LOG_IPHOST:
957 if (GET_BE_U_4(data) == 0xFFFFFFFF )
958 ND_PRINT("User Selected");
959 else
960 if (GET_BE_U_4(data) == 0xFFFFFFFE )
961 ND_PRINT("NAS Select");
962 else
963 ND_PRINT("%s",GET_IPADDR_STRING(data));
964 break;
965
966 default:
967 ND_PRINT("%s", GET_IPADDR_STRING(data));
968 break;
969 }
970
971 return;
972
973 trunc:
974 nd_print_trunc(ndo);
975 }
976
977 /*****************************/
978 /* Print an attribute IPv6 */
979 /* address value pointed by */
980 /* 'data' and 'length' size. */
981 /*****************************/
982 /* Returns nothing. */
983 /*****************************/
984 static void
985 print_attr_address6(netdissect_options *ndo,
986 const u_char *data, u_int length, u_short attr_code _U_)
987 {
988 if (length != 16)
989 {
990 ND_PRINT("ERROR: length %u != 16", length);
991 return;
992 }
993
994 ND_TCHECK_16(data);
995
996 ND_PRINT("%s", GET_IP6ADDR_STRING(data));
997
998 return;
999
1000 trunc:
1001 nd_print_trunc(ndo);
1002 }
1003
1004 static void
1005 print_attr_netmask6(netdissect_options *ndo,
1006 const u_char *data, u_int length, u_short attr_code _U_)
1007 {
1008 u_char data2[16];
1009
1010 if (length < 2 || length > 18)
1011 {
1012 ND_PRINT("ERROR: length %u not in range (2..18)", length);
1013 return;
1014 }
1015 ND_TCHECK_LEN(data, length);
1016 if (GET_U_1(data + 1) > 128)
1017 {
1018 ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data + 1));
1019 return;
1020 }
1021
1022 memset(data2, 0, sizeof(data2));
1023 if (length > 2)
1024 memcpy(data2, data+2, length-2);
1025
1026 ND_PRINT("%s/%u", ip6addr_string(ndo, data2), GET_U_1(data + 1));
1027
1028 if (GET_U_1(data + 1) > 8 * (length - 2))
1029 ND_PRINT(" (inconsistent prefix length)");
1030
1031 return;
1032
1033 trunc:
1034 nd_print_trunc(ndo);
1035 }
1036
1037 static void
1038 print_attr_mip6_home_link_prefix(netdissect_options *ndo,
1039 const u_char *data, u_int length, u_short attr_code _U_)
1040 {
1041 if (length != 17)
1042 {
1043 ND_PRINT("ERROR: length %u != 17", length);
1044 return;
1045 }
1046 ND_TCHECK_LEN(data, length);
1047 if (GET_U_1(data) > 128)
1048 {
1049 ND_PRINT("ERROR: netmask %u not in range (0..128)", GET_U_1(data));
1050 return;
1051 }
1052
1053 ND_PRINT("%s/%u", GET_IP6ADDR_STRING(data + 1), GET_U_1(data));
1054
1055 return;
1056
1057 trunc:
1058 nd_print_trunc(ndo);
1059 }
1060
1061 static void
1062 print_attr_operator_name(netdissect_options *ndo,
1063 const u_char *data, u_int length, u_short attr_code _U_)
1064 {
1065 u_int namespace_value;
1066
1067 ND_TCHECK_LEN(data, length);
1068 if (length < 2)
1069 {
1070 ND_PRINT("ERROR: length %u < 2", length);
1071 return;
1072 }
1073 namespace_value = GET_U_1(data);
1074 data++;
1075 ND_PRINT("[%s] ", tok2str(operator_name_vector, "unknown namespace %u", namespace_value));
1076
1077 nd_printn(ndo, data, length - 1, NULL);
1078
1079 return;
1080
1081 trunc:
1082 nd_print_trunc(ndo);
1083 }
1084
1085 static void
1086 print_attr_location_information(netdissect_options *ndo,
1087 const u_char *data, u_int length, u_short attr_code _U_)
1088 {
1089 uint16_t index;
1090 uint8_t code, entity;
1091
1092 ND_TCHECK_LEN(data, length);
1093 if (length < 21)
1094 {
1095 ND_PRINT("ERROR: length %u < 21", length);
1096 return;
1097 }
1098
1099 index = GET_BE_U_2(data);
1100 data += 2;
1101
1102 code = GET_U_1(data);
1103 data++;
1104
1105 entity = GET_U_1(data);
1106 data++;
1107
1108 ND_PRINT("index %u, code %s, entity %s, ",
1109 index,
1110 tok2str(location_information_code_vector, "Unknown (%u)", code),
1111 tok2str(location_information_entity_vector, "Unknown (%u)", entity)
1112 );
1113
1114 ND_PRINT("sighting time ");
1115 p_ntp_time(ndo, (const struct l_fixedpt *)data);
1116 ND_PRINT(", ");
1117 data += 8;
1118
1119 ND_PRINT("time to live ");
1120 p_ntp_time(ndo, (const struct l_fixedpt *)data);
1121 ND_PRINT(", ");
1122 data += 8;
1123
1124 ND_PRINT("method \"");
1125 nd_printn(ndo, data, length - 20, NULL);
1126 ND_PRINT("\"");
1127
1128 return;
1129
1130 trunc:
1131 nd_print_trunc(ndo);
1132 }
1133
1134 static void
1135 print_attr_location_data(netdissect_options *ndo,
1136 const u_char *data, u_int length, u_short attr_code _U_)
1137 {
1138 uint16_t index;
1139
1140 ND_TCHECK_LEN(data, length);
1141 if (length < 3)
1142 {
1143 ND_PRINT("ERROR: length %u < 3", length);
1144 return;
1145 }
1146
1147 index = GET_BE_U_2(data);
1148 data += 2;
1149 ND_PRINT("index %u, location", index);
1150
1151 /* The Location field of the String field of the Location-Data attribute
1152 * can have two completely different structures depending on the value of
1153 * the Code field of a Location-Info attribute, which supposedly precedes
1154 * the current attribute. Unfortunately, this choice of encoding makes it
1155 * non-trivial to decode the Location field without preserving some state
1156 * between the attributes.
1157 */
1158 hex_and_ascii_print(ndo, "\n\t ", data, length - 2);
1159
1160 return;
1161
1162 trunc:
1163 nd_print_trunc(ndo);
1164 }
1165
1166 static void
1167 print_basic_location_policy_rules(netdissect_options *ndo,
1168 const u_char *data, u_int length, u_short attr_code _U_)
1169 {
1170 uint16_t flags;
1171
1172 ND_TCHECK_LEN(data, length);
1173 if (length < 10)
1174 {
1175 ND_PRINT("ERROR: length %u < 10", length);
1176 return;
1177 }
1178
1179 flags = GET_BE_U_2(data);
1180 data += 2;
1181 ND_PRINT("flags [%s], ", bittok2str(blpr_bm, "none", flags));
1182
1183 ND_PRINT("retention expires ");
1184 p_ntp_time(ndo, (const struct l_fixedpt *)data);
1185 data += 8;
1186
1187 if (length > 10) {
1188 ND_PRINT(", note well \"");
1189 nd_printn(ndo, data, length - 10, NULL);
1190 ND_PRINT("\"");
1191 }
1192
1193 return;
1194
1195 trunc:
1196 nd_print_trunc(ndo);
1197 }
1198
1199
1200 /*************************************/
1201 /* Print an attribute of 'secs since */
1202 /* January 1, 1970 00:00 UTC' value */
1203 /* pointed by 'data' and 'length' */
1204 /* size. */
1205 /*************************************/
1206 /* Returns nothing. */
1207 /*************************************/
1208 static void
1209 print_attr_time(netdissect_options *ndo,
1210 const u_char *data, u_int length, u_short attr_code _U_)
1211 {
1212 time_t attr_time;
1213 char string[26];
1214
1215 if (length != 4)
1216 {
1217 ND_PRINT("ERROR: length %u != 4", length);
1218 return;
1219 }
1220
1221 ND_TCHECK_4(data);
1222
1223 attr_time = GET_BE_U_4(data);
1224 strlcpy(string, ctime(&attr_time), sizeof(string));
1225 /* Get rid of the newline */
1226 string[24] = '\0';
1227 ND_PRINT("%.24s", string);
1228 return;
1229
1230 trunc:
1231 nd_print_trunc(ndo);
1232 }
1233
1234 static void
1235 print_attr_vector64(netdissect_options *ndo,
1236 register const u_char *data, u_int length, u_short attr_code _U_)
1237 {
1238 uint64_t data_value, i;
1239 const char *sep = "";
1240
1241 if (length != 8)
1242 {
1243 ND_PRINT("ERROR: length %u != 8", length);
1244 return;
1245 }
1246
1247 ND_PRINT("[");
1248
1249 data_value = GET_BE_U_8(data);
1250 /* Print the 64-bit field in a format similar to bittok2str(), less
1251 * flagging any unknown bits. This way it should be easier to replace
1252 * the custom code with a library function later.
1253 */
1254 for (i = 0; i < TAM_SIZE(mip6_feature_vector); i++) {
1255 if (data_value & mip6_feature_vector[i].v) {
1256 ND_PRINT("%s%s", sep, mip6_feature_vector[i].s);
1257 sep = ", ";
1258 }
1259 }
1260
1261 ND_PRINT("]");
1262
1263 return;
1264 }
1265
1266 /***********************************/
1267 /* Print an attribute of 'strange' */
1268 /* data format pointed by 'data' */
1269 /* and 'length' size. */
1270 /***********************************/
1271 /* Returns nothing. */
1272 /***********************************/
1273 static void
1274 print_attr_strange(netdissect_options *ndo,
1275 const u_char *data, u_int length, u_short attr_code)
1276 {
1277 u_short len_data;
1278 u_int error_cause_value;
1279
1280 switch(attr_code)
1281 {
1282 case ARAP_PASS:
1283 if (length != 16)
1284 {
1285 ND_PRINT("ERROR: length %u != 16", length);
1286 return;
1287 }
1288 ND_PRINT("User_challenge (");
1289 ND_TCHECK_8(data);
1290 len_data = 8;
1291 PRINT_HEX(len_data, data);
1292 ND_PRINT(") User_resp(");
1293 ND_TCHECK_8(data);
1294 len_data = 8;
1295 PRINT_HEX(len_data, data);
1296 ND_PRINT(")");
1297 break;
1298
1299 case ARAP_FEATURES:
1300 if (length != 14)
1301 {
1302 ND_PRINT("ERROR: length %u != 14", length);
1303 return;
1304 }
1305 ND_TCHECK_1(data);
1306 if (GET_U_1(data))
1307 ND_PRINT("User can change password");
1308 else
1309 ND_PRINT("User cannot change password");
1310 data++;
1311 ND_TCHECK_1(data);
1312 ND_PRINT(", Min password length: %u", GET_U_1(data));
1313 data++;
1314 ND_PRINT(", created at: ");
1315 ND_TCHECK_4(data);
1316 len_data = 4;
1317 PRINT_HEX(len_data, data);
1318 ND_PRINT(", expires in: ");
1319 ND_TCHECK_4(data);
1320 len_data = 4;
1321 PRINT_HEX(len_data, data);
1322 ND_PRINT(", Current Time: ");
1323 ND_TCHECK_4(data);
1324 len_data = 4;
1325 PRINT_HEX(len_data, data);
1326 break;
1327
1328 case ARAP_CHALLENGE_RESP:
1329 if (length < 8)
1330 {
1331 ND_PRINT("ERROR: length %u != 8", length);
1332 return;
1333 }
1334 ND_TCHECK_8(data);
1335 len_data = 8;
1336 PRINT_HEX(len_data, data);
1337 break;
1338
1339 case ERROR_CAUSE:
1340 if (length != 4)
1341 {
1342 ND_PRINT("Error: length %u != 4", length);
1343 return;
1344 }
1345 ND_TCHECK_4(data);
1346
1347 error_cause_value = GET_BE_U_4(data);
1348 ND_PRINT("Error cause %u: %s", error_cause_value, tok2str(errorcausetype, "Error-Cause %u not known", error_cause_value));
1349 break;
1350 }
1351 return;
1352
1353 trunc:
1354 nd_print_trunc(ndo);
1355 }
1356
1357 static void
1358 radius_attrs_print(netdissect_options *ndo,
1359 const u_char *attr, u_int length)
1360 {
1361 const struct radius_attr *rad_attr = (const struct radius_attr *)attr;
1362 const char *attr_string;
1363 uint8_t type, len;
1364
1365 while (length > 0)
1366 {
1367 if (length < 2)
1368 goto trunc;
1369 ND_TCHECK_SIZE(rad_attr);
1370
1371 type = GET_U_1(rad_attr->type);
1372 len = GET_U_1(rad_attr->len);
1373 if (type != 0 && type < TAM_SIZE(attr_type))
1374 attr_string = attr_type[type].name;
1375 else
1376 attr_string = "Unknown";
1377
1378 ND_PRINT("\n\t %s Attribute (%u), length: %u",
1379 attr_string,
1380 type,
1381 len);
1382 if (len < 2)
1383 {
1384 ND_PRINT(" (bogus, must be >= 2)");
1385 return;
1386 }
1387 if (len > length)
1388 {
1389 ND_PRINT(" (bogus, goes past end of packet)");
1390 return;
1391 }
1392 ND_PRINT(", Value: ");
1393
1394 if (type < TAM_SIZE(attr_type))
1395 {
1396 if (len > 2)
1397 {
1398 if ( attr_type[type].print_func )
1399 (*attr_type[type].print_func)(
1400 ndo, ((const u_char *)(rad_attr+1)),
1401 len - 2, type);
1402 }
1403 }
1404 /* do we also want to see a hex dump ? */
1405 if (ndo->ndo_vflag> 1)
1406 print_unknown_data(ndo, (const u_char *)rad_attr+2, "\n\t ", (len)-2);
1407
1408 length-=(len);
1409 rad_attr = (const struct radius_attr *)( ((const char *)(rad_attr))+len);
1410 }
1411 return;
1412
1413 trunc:
1414 nd_print_trunc(ndo);
1415 }
1416
1417 void
1418 radius_print(netdissect_options *ndo,
1419 const u_char *dat, u_int length)
1420 {
1421 const struct radius_hdr *rad;
1422 u_int len, auth_idx;
1423
1424 ndo->ndo_protocol = "radius";
1425 ND_TCHECK_LEN(dat, MIN_RADIUS_LEN);
1426 rad = (const struct radius_hdr *)dat;
1427 len = GET_BE_U_2(rad->len);
1428
1429 if (len < MIN_RADIUS_LEN)
1430 {
1431 nd_print_trunc(ndo);
1432 return;
1433 }
1434
1435 if (len > length)
1436 len = length;
1437
1438 if (ndo->ndo_vflag < 1) {
1439 ND_PRINT("RADIUS, %s (%u), id: 0x%02x length: %u",
1440 tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
1441 GET_U_1(rad->code),
1442 GET_U_1(rad->id),
1443 len);
1444 return;
1445 }
1446 else {
1447 ND_PRINT("RADIUS, length: %u\n\t%s (%u), id: 0x%02x, Authenticator: ",
1448 len,
1449 tok2str(radius_command_values,"Unknown Command",GET_U_1(rad->code)),
1450 GET_U_1(rad->code),
1451 GET_U_1(rad->id));
1452
1453 for(auth_idx=0; auth_idx < 16; auth_idx++)
1454 ND_PRINT("%02x", rad->auth[auth_idx]);
1455 }
1456
1457 if (len > MIN_RADIUS_LEN)
1458 radius_attrs_print(ndo, dat + MIN_RADIUS_LEN, len - MIN_RADIUS_LEN);
1459 return;
1460
1461 trunc:
1462 nd_print_trunc(ndo);
1463 }