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