4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2001 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <sys/sysmacros.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <net/pppoe.h>
40 * These two macros extract the version and type fields respectively from
41 * the first byte of the PPPoE header.
43 #define POE_VERS(x) (((x) >> 4) & 0x0f)
44 #define POE_TYPE(x) ((x) & 0x0f)
46 typedef void interpret_func_t(uint8_t *, uint16_t);
48 typedef struct taginfo
{
51 interpret_func_t
*interpret_tagvalue
;
55 static char *pppoe_codetoname(int, boolean_t
);
56 static taginfo_t
*pppoe_gettaginfo(uint16_t);
57 static void print_hexdata(char *, uint8_t *, uint16_t);
58 static void print_utf8string(char *, char *, uint16_t);
59 static char *print_linetag(char *);
60 static interpret_func_t interpret_tags
;
61 static interpret_func_t interpret_hexdata
;
62 static interpret_func_t interpret_service
;
63 static interpret_func_t interpret_access
;
64 static interpret_func_t interpret_cookie
;
65 static interpret_func_t interpret_vendor
;
66 static interpret_func_t interpret_relay
;
67 static interpret_func_t interpret_error
;
68 static interpret_func_t interpret_hurl
;
69 static interpret_func_t interpret_motm
;
70 static interpret_func_t interpret_rteadd
;
73 static taginfo_t taginfo_array
[] = {
74 { "End-Of-List", POETT_END
, interpret_hexdata
},
75 { "Service-Name", POETT_SERVICE
, interpret_service
},
76 { "AC-Name", POETT_ACCESS
, interpret_access
},
77 { "Host-Uniq", POETT_UNIQ
, interpret_hexdata
},
78 { "AC-Cookie", POETT_COOKIE
, interpret_cookie
},
79 { "Vendor-Specific", POETT_VENDOR
, interpret_vendor
},
80 { "Relay-Session-Id", POETT_RELAY
, interpret_relay
},
81 { "Service-Name-Error", POETT_NAMERR
, interpret_error
},
82 { "AC-System-Error", POETT_SYSERR
, interpret_error
},
83 { "Generic-Error", POETT_GENERR
, interpret_error
},
84 { "Multicast-Capable", POETT_MULTI
, interpret_hexdata
},
85 { "Host-URL", POETT_HURL
, interpret_hurl
},
86 { "Message-Of-The-Minute", POETT_MOTM
, interpret_motm
},
87 { "IP-Route-Add", POETT_RTEADD
, interpret_rteadd
},
88 { "Unknown TAG", 0, NULL
}
93 interpret_pppoe(int flags
, poep_t
*poep
, int len
)
95 uint8_t code
= poep
->poep_code
;
98 if (len
< sizeof (poep_t
))
101 payload
= (uint8_t *)poep
+ sizeof (poep_t
);
104 (void) sprintf(get_sum_line(), "PPPoE %s",
105 pppoe_codetoname(code
, B_FALSE
));
106 } else { /* flags & F_DTAIL */
107 show_header("PPPoE: ", "PPP Over Ethernet", len
);
110 (void) sprintf(get_line(0, 0),
111 "Version = %d", POE_VERS(poep
->poep_version_type
));
113 (void) sprintf(get_line(0, 0),
114 "Type = %d", POE_TYPE(poep
->poep_version_type
));
116 (void) sprintf(get_line(0, 0),
117 "Code = %d (%s)", code
, pppoe_codetoname(code
, B_TRUE
));
119 (void) sprintf(get_line(0, 0),
120 "Session Id = %d", ntohs(poep
->poep_session_id
));
122 (void) sprintf(get_line(0, 0),
123 "Length = %d bytes", ntohs(poep
->poep_length
));
127 len
-= sizeof (poep_t
);
128 len
= MIN(len
, ntohs(poep
->poep_length
));
130 if (poep
->poep_code
!= 0 && poep
->poep_length
> 0) {
131 interpret_tags(payload
, len
);
135 if (poep
->poep_code
== 0) {
136 return (interpret_ppp(flags
, payload
, len
));
143 * interpret_tags() prints PPPoE Discovery Stage TAGs in detail.
146 interpret_tags(uint8_t *payload
, uint16_t length
)
148 uint8_t *tagptr
= payload
;
154 while (length
>= POET_HDRLEN
) {
155 tag_type
= POET_GET_TYPE(tagptr
);
156 tag_length
= POET_GET_LENG(tagptr
);
158 tinfo
= pppoe_gettaginfo(tag_type
);
160 show_header("PPPoE: ", tinfo
->tag_name
,
161 tag_length
+ POET_HDRLEN
);
163 (void) sprintf(get_line(0, 0),
164 "Tag Type = %d", tag_type
);
166 (void) sprintf(get_line(0, 0),
167 "Tag Length = %d bytes", tag_length
);
169 length
-= POET_HDRLEN
;
170 if (tag_length
> length
) {
171 (void) sprintf(get_line(0, 0),
172 "Warning: Truncated Packet");
178 * unknown tags or tags which should always have 0 length
179 * are not interpreted any further.
181 tag_value
= POET_DATA(tagptr
);
182 if (tag_length
!= 0 && tinfo
->interpret_tagvalue
!= NULL
)
183 tinfo
->interpret_tagvalue(tag_value
, tag_length
);
186 length
-= tag_length
;
187 tagptr
= POET_NEXT(tagptr
);
192 pppoe_codetoname(int code
, boolean_t verbose
)
202 name
= "Active Discovery Offer";
208 name
= "Active Discovery Initiation";
214 name
= "Active Discovery Request";
220 name
= "Active Discovery Session-Confirmation";
226 name
= "Active Discovery Terminate";
232 name
= "Active Discovery Message";
238 name
= "Active Discovery Network";
243 name
= "Unknown Code";
250 pppoe_gettaginfo(uint16_t type
)
252 taginfo_t
*taginfo_ptr
= &taginfo_array
[0];
255 while (taginfo_ptr
->tag_type
!= type
&&
256 taginfo_ptr
->interpret_tagvalue
!= NULL
) {
257 taginfo_ptr
= &taginfo_array
[++i
];
260 return (taginfo_ptr
);
264 interpret_hexdata(uint8_t *tag_value
, uint16_t tag_length
)
268 endofline
= print_linetag("Data = ");
269 print_hexdata(endofline
, tag_value
, tag_length
);
273 interpret_service(uint8_t *tag_value
, uint16_t tag_length
)
277 endofline
= print_linetag("Service Name = ");
278 print_utf8string(endofline
, (char *)tag_value
, tag_length
);
282 interpret_access(uint8_t *tag_value
, uint16_t tag_length
)
286 endofline
= print_linetag("AC Name = ");
287 print_utf8string(endofline
, (char *)tag_value
, tag_length
);
291 interpret_cookie(uint8_t *tag_value
, uint16_t tag_length
)
295 endofline
= print_linetag("Cookie = ");
296 print_hexdata(endofline
, tag_value
, tag_length
);
300 interpret_vendor(uint8_t *tag_value
, uint16_t tag_length
)
302 uint8_t *vendor_data
;
306 vendorid
= ntohl(*(uint32_t *)tag_value
);
307 (void) sprintf(get_line(0, 0),
308 "Vendor ID = %d", vendorid
);
310 if (tag_length
> 4) {
311 vendor_data
= tag_value
+ 4;
312 endofline
= print_linetag("Vendor Data = ");
313 print_hexdata(endofline
, vendor_data
, tag_length
- 4);
318 interpret_relay(uint8_t *tag_value
, uint16_t tag_length
)
322 endofline
= print_linetag("ID = ");
323 print_hexdata(endofline
, tag_value
, tag_length
);
327 interpret_error(uint8_t *tag_value
, uint16_t tag_length
)
331 endofline
= print_linetag("Error = ");
332 print_utf8string(endofline
, (char *)tag_value
, tag_length
);
336 interpret_hurl(uint8_t *tag_value
, uint16_t tag_length
)
340 endofline
= print_linetag("URL = ");
341 print_utf8string(endofline
, (char *)tag_value
, tag_length
);
345 interpret_motm(uint8_t *tag_value
, uint16_t tag_length
)
349 endofline
= print_linetag("Message = ");
350 print_utf8string(endofline
, (char *)tag_value
, tag_length
);
354 interpret_rteadd(uint8_t *tag_value
, uint16_t tag_length
)
356 char dest
[INET_ADDRSTRLEN
];
357 char mask
[INET_ADDRSTRLEN
];
358 char gateway
[INET_ADDRSTRLEN
];
361 if (tag_length
== 16) {
362 (void) inet_ntop(AF_INET
, tag_value
, dest
,
364 (void) inet_ntop(AF_INET
, &tag_value
[4], mask
,
366 (void) inet_ntop(AF_INET
, &tag_value
[8], gateway
,
368 metric
= ntohl(*(uint32_t *)&tag_value
[12]);
369 sprintf(get_line(0, 0),
370 "Destination\tNetmask\tGateway\tMetric");
371 sprintf(get_line(0, 0),
372 "%s\t%s\t%s\t%d", dest
, mask
, gateway
, metric
);
377 print_hexdata(char *line
, uint8_t *data
, uint16_t length
)
381 line
+= sprintf(line
, "0x");
383 while (index
< length
) {
384 line
+= sprintf(line
, "%02x", data
[index
++]);
389 print_utf8string(char *firstline
, char *string
, uint16_t length
)
391 (void) sprintf(firstline
, "%.*s", length
, string
);
395 print_linetag(char *string
)
397 char *line
= get_line(0, 0);
398 return (line
+ sprintf(line
, string
));