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