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