1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 2001 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <string.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 34*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 35*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 36*7c478bd9Sstevel@tonic-gate #include <net/pppoe.h> 37*7c478bd9Sstevel@tonic-gate #include "snoop.h" 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate /* 40*7c478bd9Sstevel@tonic-gate * These two macros extract the version and type fields respectively from 41*7c478bd9Sstevel@tonic-gate * the first byte of the PPPoE header. 42*7c478bd9Sstevel@tonic-gate */ 43*7c478bd9Sstevel@tonic-gate #define POE_VERS(x) (((x) >> 4) & 0x0f) 44*7c478bd9Sstevel@tonic-gate #define POE_TYPE(x) ((x) & 0x0f) 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate typedef void interpret_func_t(uint8_t *, uint16_t); 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate typedef struct taginfo { 49*7c478bd9Sstevel@tonic-gate char *tag_name; 50*7c478bd9Sstevel@tonic-gate uint16_t tag_type; 51*7c478bd9Sstevel@tonic-gate interpret_func_t *interpret_tagvalue; 52*7c478bd9Sstevel@tonic-gate } taginfo_t; 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate static char *pppoe_codetoname(int, boolean_t); 56*7c478bd9Sstevel@tonic-gate static taginfo_t *pppoe_gettaginfo(uint16_t); 57*7c478bd9Sstevel@tonic-gate static void print_hexdata(char *, uint8_t *, uint16_t); 58*7c478bd9Sstevel@tonic-gate static void print_utf8string(char *, char *, uint16_t); 59*7c478bd9Sstevel@tonic-gate static char *print_linetag(char *); 60*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_tags; 61*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_hexdata; 62*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_service; 63*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_access; 64*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_cookie; 65*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_vendor; 66*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_relay; 67*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_error; 68*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_hurl; 69*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_motm; 70*7c478bd9Sstevel@tonic-gate static interpret_func_t interpret_rteadd; 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate static taginfo_t taginfo_array[] = { 74*7c478bd9Sstevel@tonic-gate { "End-Of-List", POETT_END, interpret_hexdata }, 75*7c478bd9Sstevel@tonic-gate { "Service-Name", POETT_SERVICE, interpret_service }, 76*7c478bd9Sstevel@tonic-gate { "AC-Name", POETT_ACCESS, interpret_access }, 77*7c478bd9Sstevel@tonic-gate { "Host-Uniq", POETT_UNIQ, interpret_hexdata }, 78*7c478bd9Sstevel@tonic-gate { "AC-Cookie", POETT_COOKIE, interpret_cookie }, 79*7c478bd9Sstevel@tonic-gate { "Vendor-Specific", POETT_VENDOR, interpret_vendor }, 80*7c478bd9Sstevel@tonic-gate { "Relay-Session-Id", POETT_RELAY, interpret_relay }, 81*7c478bd9Sstevel@tonic-gate { "Service-Name-Error", POETT_NAMERR, interpret_error }, 82*7c478bd9Sstevel@tonic-gate { "AC-System-Error", POETT_SYSERR, interpret_error }, 83*7c478bd9Sstevel@tonic-gate { "Generic-Error", POETT_GENERR, interpret_error }, 84*7c478bd9Sstevel@tonic-gate { "Multicast-Capable", POETT_MULTI, interpret_hexdata }, 85*7c478bd9Sstevel@tonic-gate { "Host-URL", POETT_HURL, interpret_hurl }, 86*7c478bd9Sstevel@tonic-gate { "Message-Of-The-Minute", POETT_MOTM, interpret_motm }, 87*7c478bd9Sstevel@tonic-gate { "IP-Route-Add", POETT_RTEADD, interpret_rteadd }, 88*7c478bd9Sstevel@tonic-gate { "Unknown TAG", 0, NULL } 89*7c478bd9Sstevel@tonic-gate }; 90*7c478bd9Sstevel@tonic-gate 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gate int 93*7c478bd9Sstevel@tonic-gate interpret_pppoe(int flags, poep_t *poep, int len) 94*7c478bd9Sstevel@tonic-gate { 95*7c478bd9Sstevel@tonic-gate uint8_t code = poep->poep_code; 96*7c478bd9Sstevel@tonic-gate uint8_t *payload; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate if (len < sizeof (poep_t)) 99*7c478bd9Sstevel@tonic-gate return (len); 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate payload = (uint8_t *)poep + sizeof (poep_t); 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 104*7c478bd9Sstevel@tonic-gate (void) sprintf(get_sum_line(), "PPPoE %s", 105*7c478bd9Sstevel@tonic-gate pppoe_codetoname(code, B_FALSE)); 106*7c478bd9Sstevel@tonic-gate } else { /* flags & F_DTAIL */ 107*7c478bd9Sstevel@tonic-gate show_header("PPPoE: ", "PPP Over Ethernet", len); 108*7c478bd9Sstevel@tonic-gate show_space(); 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 111*7c478bd9Sstevel@tonic-gate "Version = %d", POE_VERS(poep->poep_version_type)); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 114*7c478bd9Sstevel@tonic-gate "Type = %d", POE_TYPE(poep->poep_version_type)); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 117*7c478bd9Sstevel@tonic-gate "Code = %d (%s)", code, pppoe_codetoname(code, B_TRUE)); 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 120*7c478bd9Sstevel@tonic-gate "Session Id = %d", ntohs(poep->poep_session_id)); 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 123*7c478bd9Sstevel@tonic-gate "Length = %d bytes", ntohs(poep->poep_length)); 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate show_space(); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate len -= sizeof (poep_t); 128*7c478bd9Sstevel@tonic-gate len = MIN(len, ntohs(poep->poep_length)); 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate if (poep->poep_code != 0 && poep->poep_length > 0) { 131*7c478bd9Sstevel@tonic-gate interpret_tags(payload, len); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate 135*7c478bd9Sstevel@tonic-gate if (poep->poep_code == 0) { 136*7c478bd9Sstevel@tonic-gate return (interpret_ppp(flags, payload, len)); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate return (len); 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * interpret_tags() prints PPPoE Discovery Stage TAGs in detail. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate static void 146*7c478bd9Sstevel@tonic-gate interpret_tags(uint8_t *payload, uint16_t length) 147*7c478bd9Sstevel@tonic-gate { 148*7c478bd9Sstevel@tonic-gate uint8_t *tagptr = payload; 149*7c478bd9Sstevel@tonic-gate uint16_t tag_length; 150*7c478bd9Sstevel@tonic-gate uint16_t tag_type; 151*7c478bd9Sstevel@tonic-gate uint8_t *tag_value; 152*7c478bd9Sstevel@tonic-gate taginfo_t *tinfo; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate while (length >= POET_HDRLEN) { 155*7c478bd9Sstevel@tonic-gate tag_type = POET_GET_TYPE(tagptr); 156*7c478bd9Sstevel@tonic-gate tag_length = POET_GET_LENG(tagptr); 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate tinfo = pppoe_gettaginfo(tag_type); 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate show_header("PPPoE: ", tinfo->tag_name, 161*7c478bd9Sstevel@tonic-gate tag_length + POET_HDRLEN); 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 164*7c478bd9Sstevel@tonic-gate "Tag Type = %d", tag_type); 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 167*7c478bd9Sstevel@tonic-gate "Tag Length = %d bytes", tag_length); 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate length -= POET_HDRLEN; 170*7c478bd9Sstevel@tonic-gate if (tag_length > length) { 171*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 172*7c478bd9Sstevel@tonic-gate "Warning: Truncated Packet"); 173*7c478bd9Sstevel@tonic-gate show_space(); 174*7c478bd9Sstevel@tonic-gate break; 175*7c478bd9Sstevel@tonic-gate } 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate /* 178*7c478bd9Sstevel@tonic-gate * unknown tags or tags which should always have 0 length 179*7c478bd9Sstevel@tonic-gate * are not interpreted any further. 180*7c478bd9Sstevel@tonic-gate */ 181*7c478bd9Sstevel@tonic-gate tag_value = POET_DATA(tagptr); 182*7c478bd9Sstevel@tonic-gate if (tag_length != 0 && tinfo->interpret_tagvalue != NULL) 183*7c478bd9Sstevel@tonic-gate tinfo->interpret_tagvalue(tag_value, tag_length); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate show_space(); 186*7c478bd9Sstevel@tonic-gate length -= tag_length; 187*7c478bd9Sstevel@tonic-gate tagptr = POET_NEXT(tagptr); 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate static char * 192*7c478bd9Sstevel@tonic-gate pppoe_codetoname(int code, boolean_t verbose) 193*7c478bd9Sstevel@tonic-gate { 194*7c478bd9Sstevel@tonic-gate char *name; 195*7c478bd9Sstevel@tonic-gate 196*7c478bd9Sstevel@tonic-gate switch (code) { 197*7c478bd9Sstevel@tonic-gate case POECODE_DATA: 198*7c478bd9Sstevel@tonic-gate name = "Session"; 199*7c478bd9Sstevel@tonic-gate break; 200*7c478bd9Sstevel@tonic-gate case POECODE_PADO: 201*7c478bd9Sstevel@tonic-gate if (verbose) 202*7c478bd9Sstevel@tonic-gate name = "Active Discovery Offer"; 203*7c478bd9Sstevel@tonic-gate else 204*7c478bd9Sstevel@tonic-gate name = "PADO"; 205*7c478bd9Sstevel@tonic-gate break; 206*7c478bd9Sstevel@tonic-gate case POECODE_PADI: 207*7c478bd9Sstevel@tonic-gate if (verbose) 208*7c478bd9Sstevel@tonic-gate name = "Active Discovery Initiation"; 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate name = "PADI"; 211*7c478bd9Sstevel@tonic-gate break; 212*7c478bd9Sstevel@tonic-gate case POECODE_PADR: 213*7c478bd9Sstevel@tonic-gate if (verbose) 214*7c478bd9Sstevel@tonic-gate name = "Active Discovery Request"; 215*7c478bd9Sstevel@tonic-gate else 216*7c478bd9Sstevel@tonic-gate name = "PADR"; 217*7c478bd9Sstevel@tonic-gate break; 218*7c478bd9Sstevel@tonic-gate case POECODE_PADS: 219*7c478bd9Sstevel@tonic-gate if (verbose) 220*7c478bd9Sstevel@tonic-gate name = "Active Discovery Session-Confirmation"; 221*7c478bd9Sstevel@tonic-gate else 222*7c478bd9Sstevel@tonic-gate name = "PADS"; 223*7c478bd9Sstevel@tonic-gate break; 224*7c478bd9Sstevel@tonic-gate case POECODE_PADT: 225*7c478bd9Sstevel@tonic-gate if (verbose) 226*7c478bd9Sstevel@tonic-gate name = "Active Discovery Terminate"; 227*7c478bd9Sstevel@tonic-gate else 228*7c478bd9Sstevel@tonic-gate name = "PADT"; 229*7c478bd9Sstevel@tonic-gate break; 230*7c478bd9Sstevel@tonic-gate case POECODE_PADM: 231*7c478bd9Sstevel@tonic-gate if (verbose) 232*7c478bd9Sstevel@tonic-gate name = "Active Discovery Message"; 233*7c478bd9Sstevel@tonic-gate else 234*7c478bd9Sstevel@tonic-gate name = "PADM"; 235*7c478bd9Sstevel@tonic-gate break; 236*7c478bd9Sstevel@tonic-gate case POECODE_PADN: 237*7c478bd9Sstevel@tonic-gate if (verbose) 238*7c478bd9Sstevel@tonic-gate name = "Active Discovery Network"; 239*7c478bd9Sstevel@tonic-gate else 240*7c478bd9Sstevel@tonic-gate name = "PADN"; 241*7c478bd9Sstevel@tonic-gate break; 242*7c478bd9Sstevel@tonic-gate default: 243*7c478bd9Sstevel@tonic-gate name = "Unknown Code"; 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate return (name); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate static taginfo_t * 250*7c478bd9Sstevel@tonic-gate pppoe_gettaginfo(uint16_t type) 251*7c478bd9Sstevel@tonic-gate { 252*7c478bd9Sstevel@tonic-gate taginfo_t *taginfo_ptr = &taginfo_array[0]; 253*7c478bd9Sstevel@tonic-gate int i = 0; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate while (taginfo_ptr->tag_type != type && 256*7c478bd9Sstevel@tonic-gate taginfo_ptr->interpret_tagvalue != NULL) { 257*7c478bd9Sstevel@tonic-gate taginfo_ptr = &taginfo_array[++i]; 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate return (taginfo_ptr); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate static void 264*7c478bd9Sstevel@tonic-gate interpret_hexdata(uint8_t *tag_value, uint16_t tag_length) 265*7c478bd9Sstevel@tonic-gate { 266*7c478bd9Sstevel@tonic-gate char *endofline; 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Data = "); 269*7c478bd9Sstevel@tonic-gate print_hexdata(endofline, tag_value, tag_length); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate static void 273*7c478bd9Sstevel@tonic-gate interpret_service(uint8_t *tag_value, uint16_t tag_length) 274*7c478bd9Sstevel@tonic-gate { 275*7c478bd9Sstevel@tonic-gate char *endofline; 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Service Name = "); 278*7c478bd9Sstevel@tonic-gate print_utf8string(endofline, (char *)tag_value, tag_length); 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate 281*7c478bd9Sstevel@tonic-gate static void 282*7c478bd9Sstevel@tonic-gate interpret_access(uint8_t *tag_value, uint16_t tag_length) 283*7c478bd9Sstevel@tonic-gate { 284*7c478bd9Sstevel@tonic-gate char *endofline; 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate endofline = print_linetag("AC Name = "); 287*7c478bd9Sstevel@tonic-gate print_utf8string(endofline, (char *)tag_value, tag_length); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate static void 291*7c478bd9Sstevel@tonic-gate interpret_cookie(uint8_t *tag_value, uint16_t tag_length) 292*7c478bd9Sstevel@tonic-gate { 293*7c478bd9Sstevel@tonic-gate char *endofline; 294*7c478bd9Sstevel@tonic-gate 295*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Cookie = "); 296*7c478bd9Sstevel@tonic-gate print_hexdata(endofline, tag_value, tag_length); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate static void 300*7c478bd9Sstevel@tonic-gate interpret_vendor(uint8_t *tag_value, uint16_t tag_length) 301*7c478bd9Sstevel@tonic-gate { 302*7c478bd9Sstevel@tonic-gate uint8_t *vendor_data; 303*7c478bd9Sstevel@tonic-gate uint32_t vendorid; 304*7c478bd9Sstevel@tonic-gate char *endofline; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate vendorid = ntohl(*(uint32_t *)tag_value); 307*7c478bd9Sstevel@tonic-gate (void) sprintf(get_line(0, 0), 308*7c478bd9Sstevel@tonic-gate "Vendor ID = %d", vendorid); 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate if (tag_length > 4) { 311*7c478bd9Sstevel@tonic-gate vendor_data = tag_value + 4; 312*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Vendor Data = "); 313*7c478bd9Sstevel@tonic-gate print_hexdata(endofline, vendor_data, tag_length - 4); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate static void 318*7c478bd9Sstevel@tonic-gate interpret_relay(uint8_t *tag_value, uint16_t tag_length) 319*7c478bd9Sstevel@tonic-gate { 320*7c478bd9Sstevel@tonic-gate char *endofline; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate endofline = print_linetag("ID = "); 323*7c478bd9Sstevel@tonic-gate print_hexdata(endofline, tag_value, tag_length); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate 326*7c478bd9Sstevel@tonic-gate static void 327*7c478bd9Sstevel@tonic-gate interpret_error(uint8_t *tag_value, uint16_t tag_length) 328*7c478bd9Sstevel@tonic-gate { 329*7c478bd9Sstevel@tonic-gate char *endofline; 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Error = "); 332*7c478bd9Sstevel@tonic-gate print_utf8string(endofline, (char *)tag_value, tag_length); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate static void 336*7c478bd9Sstevel@tonic-gate interpret_hurl(uint8_t *tag_value, uint16_t tag_length) 337*7c478bd9Sstevel@tonic-gate { 338*7c478bd9Sstevel@tonic-gate char *endofline; 339*7c478bd9Sstevel@tonic-gate 340*7c478bd9Sstevel@tonic-gate endofline = print_linetag("URL = "); 341*7c478bd9Sstevel@tonic-gate print_utf8string(endofline, (char *)tag_value, tag_length); 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate static void 345*7c478bd9Sstevel@tonic-gate interpret_motm(uint8_t *tag_value, uint16_t tag_length) 346*7c478bd9Sstevel@tonic-gate { 347*7c478bd9Sstevel@tonic-gate char *endofline; 348*7c478bd9Sstevel@tonic-gate 349*7c478bd9Sstevel@tonic-gate endofline = print_linetag("Message = "); 350*7c478bd9Sstevel@tonic-gate print_utf8string(endofline, (char *)tag_value, tag_length); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate static void 354*7c478bd9Sstevel@tonic-gate interpret_rteadd(uint8_t *tag_value, uint16_t tag_length) 355*7c478bd9Sstevel@tonic-gate { 356*7c478bd9Sstevel@tonic-gate char dest[INET_ADDRSTRLEN]; 357*7c478bd9Sstevel@tonic-gate char mask[INET_ADDRSTRLEN]; 358*7c478bd9Sstevel@tonic-gate char gateway[INET_ADDRSTRLEN]; 359*7c478bd9Sstevel@tonic-gate uint32_t metric; 360*7c478bd9Sstevel@tonic-gate 361*7c478bd9Sstevel@tonic-gate if (tag_length == 16) { 362*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, tag_value, dest, 363*7c478bd9Sstevel@tonic-gate INET_ADDRSTRLEN); 364*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, &tag_value[4], mask, 365*7c478bd9Sstevel@tonic-gate INET_ADDRSTRLEN); 366*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, &tag_value[8], gateway, 367*7c478bd9Sstevel@tonic-gate INET_ADDRSTRLEN); 368*7c478bd9Sstevel@tonic-gate metric = ntohl(*(uint32_t *)&tag_value[12]); 369*7c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 370*7c478bd9Sstevel@tonic-gate "Destination\tNetmask\tGateway\tMetric"); 371*7c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 372*7c478bd9Sstevel@tonic-gate "%s\t%s\t%s\t%d", dest, mask, gateway, metric); 373*7c478bd9Sstevel@tonic-gate } 374*7c478bd9Sstevel@tonic-gate } 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate static void 377*7c478bd9Sstevel@tonic-gate print_hexdata(char *line, uint8_t *data, uint16_t length) 378*7c478bd9Sstevel@tonic-gate { 379*7c478bd9Sstevel@tonic-gate uint16_t index = 0; 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate line += sprintf(line, "0x"); 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate while (index < length) { 384*7c478bd9Sstevel@tonic-gate line += sprintf(line, "%02x", data[index++]); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate } 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate static void 389*7c478bd9Sstevel@tonic-gate print_utf8string(char *firstline, char *string, uint16_t length) 390*7c478bd9Sstevel@tonic-gate { 391*7c478bd9Sstevel@tonic-gate (void) sprintf(firstline, "%.*s", length, string); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate 394*7c478bd9Sstevel@tonic-gate static char * 395*7c478bd9Sstevel@tonic-gate print_linetag(char *string) 396*7c478bd9Sstevel@tonic-gate { 397*7c478bd9Sstevel@tonic-gate char *line = get_line(0, 0); 398*7c478bd9Sstevel@tonic-gate return (line + sprintf(line, string)); 399*7c478bd9Sstevel@tonic-gate } 400