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