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