snoop_dhcpv6.c revision 36e852a172cba914383d7341c988128b2c667fbd
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Dynamic Host Configuration Protocol version 6, for IPv6. Supports
* RFCs 3315, 3319, 3646, 3898, 4075, 4242, 4280, 4580, 4649, and 4704.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <dhcp_impl.h>
#include <dhcp_inittab.h>
#include "snoop.h"
static const char *mtype_to_str(uint8_t);
static const char *option_to_str(uint8_t);
static const char *duidtype_to_str(uint16_t);
static const char *status_to_str(uint16_t);
static const char *entr_to_str(uint32_t);
static const char *reconf_to_str(uint8_t);
static const char *authproto_to_str(uint8_t);
static const char *authrdm_to_str(uint8_t);
static const char *cwhat_to_str(uint8_t);
static const char *catype_to_str(uint8_t);
static void show_ascii(const uint8_t *, int, const char *);
static void show_address(const char *, const void *);
static void show_options(const uint8_t *, int);
int
{
if (len <= 0) {
return (0);
}
char linkstr[INET6_ADDRSTRLEN];
char peerstr[INET6_ADDRSTRLEN];
mtype_to_str(data[0]));
if (data[0] == DHCPV6_MSG_RELAY_FORW ||
data[0] == DHCPV6_MSG_RELAY_REPL) {
return (olen);
}
/* Not much in DHCPv6 is aligned. */
sizeof (linkstr)),
sizeof (peerstr)));
} else {
return (olen);
}
}
ias = 0;
ias++;
if (ias > 0)
" IAs=%u", ias);
sizeof (statuscode));
optlen -= sizeof (statuscode);
if (optlen > 0) {
}
}
}
show_header("DHCPv6: ",
"Dynamic Host Configuration Protocol Version 6", len);
show_space();
"Message type (msg-type) = %u (%s)", data[0],
mtype_to_str(data[0]));
if (data[0] == DHCPV6_MSG_RELAY_FORW ||
data[0] == DHCPV6_MSG_RELAY_REPL) {
get_line_remain());
return (olen);
}
} else {
get_line_remain());
return (olen);
}
}
show_space();
show_space();
}
return (olen);
}
static const char *
{
switch (mtype) {
case DHCPV6_MSG_SOLICIT:
return ("Solicit");
case DHCPV6_MSG_ADVERTISE:
return ("Advertise");
case DHCPV6_MSG_REQUEST:
return ("Request");
case DHCPV6_MSG_CONFIRM:
return ("Confirm");
case DHCPV6_MSG_RENEW:
return ("Renew");
case DHCPV6_MSG_REBIND:
return ("Rebind");
case DHCPV6_MSG_REPLY:
return ("Reply");
case DHCPV6_MSG_RELEASE:
return ("Release");
case DHCPV6_MSG_DECLINE:
return ("Decline");
case DHCPV6_MSG_RECONFIGURE:
return ("Reconfigure");
case DHCPV6_MSG_INFO_REQ:
return ("Information-Request");
case DHCPV6_MSG_RELAY_FORW:
return ("Relay-Forward");
case DHCPV6_MSG_RELAY_REPL:
return ("Relay-Reply");
default:
return ("Unknown");
}
}
static const char *
{
switch (mtype) {
case DHCPV6_OPT_CLIENTID:
return ("Client Identifier");
case DHCPV6_OPT_SERVERID:
return ("Server Identifier");
case DHCPV6_OPT_IA_NA:
return ("Identity Association for Non-temporary Addresses");
case DHCPV6_OPT_IA_TA:
return ("Identity Association for Temporary Addresses");
case DHCPV6_OPT_IAADDR:
return ("IA Address");
case DHCPV6_OPT_ORO:
return ("Option Request");
case DHCPV6_OPT_PREFERENCE:
return ("Preference");
case DHCPV6_OPT_ELAPSED_TIME:
return ("Elapsed Time");
case DHCPV6_OPT_RELAY_MSG:
return ("Relay Message");
case DHCPV6_OPT_AUTH:
return ("Authentication");
case DHCPV6_OPT_UNICAST:
return ("Server Unicast");
case DHCPV6_OPT_STATUS_CODE:
return ("Status Code");
case DHCPV6_OPT_RAPID_COMMIT:
return ("Rapid Commit");
case DHCPV6_OPT_USER_CLASS:
return ("User Class");
case DHCPV6_OPT_VENDOR_CLASS:
return ("Vendor Class");
case DHCPV6_OPT_VENDOR_OPT:
return ("Vendor-specific Information");
case DHCPV6_OPT_INTERFACE_ID:
return ("Interface-Id");
case DHCPV6_OPT_RECONF_MSG:
return ("Reconfigure Message");
case DHCPV6_OPT_RECONF_ACC:
return ("Reconfigure Accept");
case DHCPV6_OPT_SIP_NAMES:
return ("SIP Servers Domain Name List");
case DHCPV6_OPT_SIP_ADDR:
return ("SIP Servers IPv6 Address List");
case DHCPV6_OPT_DNS_ADDR:
return ("DNS Recursive Name Server");
case DHCPV6_OPT_DNS_SEARCH:
return ("Domain Search List");
case DHCPV6_OPT_IA_PD:
return ("Identity Association for Prefix Delegation");
case DHCPV6_OPT_IAPREFIX:
return ("IA_PD Prefix");
case DHCPV6_OPT_NIS_SERVERS:
return ("Network Information Service Servers");
case DHCPV6_OPT_NIS_DOMAIN:
return ("Network Information Service Domain Name");
case DHCPV6_OPT_SNTP_SERVERS:
return ("Simple Network Time Protocol Servers");
case DHCPV6_OPT_INFO_REFTIME:
return ("Information Refresh Time");
case DHCPV6_OPT_BCMCS_SRV_D:
return ("BCMCS Controller Domain Name List");
case DHCPV6_OPT_BCMCS_SRV_A:
return ("BCMCS Controller IPv6 Address");
case DHCPV6_OPT_GEOCONF_CVC:
return ("Civic Location");
case DHCPV6_OPT_REMOTE_ID:
return ("Relay Agent Remote-ID");
case DHCPV6_OPT_SUBSCRIBER:
return ("Relay Agent Subscriber-ID");
case DHCPV6_OPT_CLIENT_FQDN:
return ("Client FQDN");
default:
return ("Unknown");
}
}
static const char *
{
switch (dtype) {
case DHCPV6_DUID_LLT:
return ("Link-layer Address Plus Time");
case DHCPV6_DUID_EN:
return ("Enterprise Number");
case DHCPV6_DUID_LL:
return ("Link-layer Address");
default:
return ("Unknown");
}
}
static const char *
{
switch (status) {
case DHCPV6_STAT_SUCCESS:
return ("Success");
case DHCPV6_STAT_UNSPECFAIL:
return ("Failure, reason unspecified");
case DHCPV6_STAT_NOADDRS:
return ("No addresses for IAs");
case DHCPV6_STAT_NOBINDING:
return ("Client binding unavailable");
case DHCPV6_STAT_NOTONLINK:
return ("Prefix not on link");
case DHCPV6_STAT_USEMCAST:
return ("Use multicast");
case DHCPV6_STAT_NOPREFIX:
return ("No prefix available");
default:
return ("Unknown");
}
}
static const char *
{
switch (entr) {
case DHCPV6_SUN_ENT:
return ("Sun Microsystems");
default:
return ("Unknown");
}
}
static const char *
{
switch (msgtype) {
case DHCPV6_RECONF_RENEW:
return ("Renew");
case DHCPV6_RECONF_INFO:
return ("Information-request");
default:
return ("Unknown");
}
}
static const char *
{
switch (aproto) {
case DHCPV6_PROTO_DELAYED:
return ("Delayed");
case DHCPV6_PROTO_RECONFIG:
return ("Reconfigure Key");
default:
return ("Unknown");
}
}
static const char *
{
switch (aproto) {
case DHCPV6_PROTO_DELAYED:
case DHCPV6_PROTO_RECONFIG:
switch (aalg) {
case DHCPV6_ALG_HMAC_MD5:
return ("HMAC-MD5 Signature");
default:
return ("Unknown");
}
break;
default:
return ("Unknown");
}
}
static const char *
{
switch (ardm) {
case DHCPV6_RDM_MONOCNT:
return ("Monotonic Counter");
default:
return ("Unknown");
}
}
static const char *
{
switch (what) {
case DHCPV6_CWHAT_SERVER:
return ("Server");
case DHCPV6_CWHAT_NETWORK:
return ("Network");
case DHCPV6_CWHAT_CLIENT:
return ("Client");
default:
return ("Unknown");
}
}
static const char *
{
switch (catype) {
case CIVICADDR_LANG:
return ("Language; RFC 2277");
case CIVICADDR_A1:
return ("National division (state)");
case CIVICADDR_A2:
return ("County");
case CIVICADDR_A3:
return ("City");
case CIVICADDR_A4:
return ("City division");
case CIVICADDR_A5:
return ("Neighborhood");
case CIVICADDR_A6:
return ("Street group");
case CIVICADDR_PRD:
return ("Leading street direction");
case CIVICADDR_POD:
return ("Trailing street suffix");
case CIVICADDR_STS:
return ("Street suffix or type");
case CIVICADDR_HNO:
return ("House number");
case CIVICADDR_HNS:
return ("House number suffix");
case CIVICADDR_LMK:
return ("Landmark");
case CIVICADDR_LOC:
return ("Additional location information");
case CIVICADDR_NAM:
case CIVICADDR_PC:
case CIVICADDR_BLD:
return ("Building");
case CIVICADDR_UNIT:
case CIVICADDR_FLR:
return ("Floor");
case CIVICADDR_ROOM:
return ("Room number");
case CIVICADDR_TYPE:
return ("Place type");
case CIVICADDR_PCN:
return ("Postal community name");
case CIVICADDR_POBOX:
return ("Post office box");
case CIVICADDR_ADDL:
return ("Additional code");
case CIVICADDR_SEAT:
case CIVICADDR_ROAD:
return ("Primary road or street");
case CIVICADDR_RSEC:
return ("Road section");
case CIVICADDR_RBRA:
return ("Road branch");
case CIVICADDR_RSBR:
return ("Road sub-branch");
case CIVICADDR_SPRE:
return ("Street name pre-modifier");
case CIVICADDR_SPOST:
return ("Street name post-modifier");
case CIVICADDR_SCRIPT:
return ("Script");
default:
return ("Unknown");
}
}
static void
{
int nlen;
int i;
char sep;
sep = '=';
while (len > 0) {
for (i = 0; i < 16 && i < len; i++)
name = "";
sep = ' ';
len -= i;
}
}
static void
{
int nlen;
int i;
char sep;
sep = '=';
while (len > 0) {
else
*bp++;
}
*bp = '\0';
sep = ' ';
name = "";
}
}
static void
{
char *hname;
char addrstr[INET6_ADDRSTRLEN];
} else {
}
}
static void
{
if (olen <= 0)
return;
} else {
}
}
static void
{
char *oldnest;
/*
* comparison doesn't work as expected.
*/
get_line_remain());
}
case DHCPV6_OPT_CLIENTID:
case DHCPV6_OPT_SERVERID:
break;
" DUID Type = %u (%s)", type,
break;
" Hardware Type = %u (%s)", val16,
}
if (type == DHCPV6_DUID_LLT) {
break;
}
if (type == DHCPV6_DUID_EN) {
break;
" Enterprise Number = %lu (%s)", val32,
entr_to_str(val32));
}
if (olen == 0)
break;
pr_err("interpret_dhcpv6: no mem");
while (--olen > 0) {
}
(type == DHCPV6_DUID_LLT ||
type == DHCPV6_DUID_LL) ?
" Link Layer Address = %s" :
" Identifier = %s", str);
break;
case DHCPV6_OPT_IA_NA:
case DHCPV6_OPT_IA_PD: {
break;
sizeof (d6in));
"Identity Association");
break;
}
case DHCPV6_OPT_IA_TA: {
break;
sizeof (d6it));
"Identity Association");
break;
}
case DHCPV6_OPT_IAADDR: {
break;
sizeof (d6ia));
" Preferred lifetime = %u seconds",
" Valid lifetime = %u seconds",
break;
}
case DHCPV6_OPT_ORO:
" Requested Option Code = %u (%s)", val16,
}
break;
case DHCPV6_OPT_PREFERENCE:
if (olen > 0) {
*data == 255 ?
" Preference = %u (immediate)" :
" Preference = %u", *data);
}
break;
case DHCPV6_OPT_ELAPSED_TIME:
" Elapsed Time = %u.%02u seconds",
}
break;
case DHCPV6_OPT_RELAY_MSG:
if (olen > 0) {
}
break;
case DHCPV6_OPT_AUTH: {
break;
" RDM Data");
if (olen > 0)
break;
}
case DHCPV6_OPT_UNICAST:
if (olen >= sizeof (in6_addr_t))
break;
case DHCPV6_OPT_STATUS_CODE:
break;
" Status Code = %u (%s)", val16,
if (olen > 0)
get_line_remain(), " Text = \"%.*s\"",
break;
case DHCPV6_OPT_VENDOR_CLASS:
break;
" Enterprise Number = %lu (%s)", val32,
entr_to_str(val32));
/* FALLTHROUGH */
case DHCPV6_OPT_USER_CLASS:
" Truncated class",
get_line_remain());
}
}
break;
case DHCPV6_OPT_VENDOR_OPT: {
break;
" Enterprise Number = %lu (%s)", val32,
entr_to_str(val32));
" Vendor Option truncated",
get_line_remain());
}
" Data");
}
}
break;
}
case DHCPV6_OPT_REMOTE_ID:
break;
" Enterprise Number = %lu (%s)", val32,
entr_to_str(val32));
/* FALLTHROUGH */
case DHCPV6_OPT_INTERFACE_ID:
case DHCPV6_OPT_SUBSCRIBER:
if (olen > 0)
break;
case DHCPV6_OPT_RECONF_MSG:
if (olen > 0) {
" Message Type = %u (%s)", *data,
reconf_to_str(*data));
}
break;
case DHCPV6_OPT_SIP_NAMES:
case DHCPV6_OPT_DNS_SEARCH:
case DHCPV6_OPT_NIS_DOMAIN:
case DHCPV6_OPT_BCMCS_SRV_D: {
char *sp2;
do {
*sp2++ = '\0';
" Name = %s", sp);
}
}
break;
}
case DHCPV6_OPT_SIP_ADDR:
case DHCPV6_OPT_DNS_ADDR:
case DHCPV6_OPT_NIS_SERVERS:
case DHCPV6_OPT_SNTP_SERVERS:
case DHCPV6_OPT_BCMCS_SRV_A:
while (olen >= sizeof (in6_addr_t)) {
data += sizeof (in6_addr_t);
olen -= sizeof (in6_addr_t);
}
break;
case DHCPV6_OPT_IAPREFIX: {
break;
" Preferred lifetime = %u seconds",
" Valid lifetime = %u seconds",
break;
}
case DHCPV6_OPT_INFO_REFTIME:
break;
break;
case DHCPV6_OPT_GEOCONF_CVC: {
int solen;
break;
while (olen >= 2) {
" CA Element = %u (%s)", *data,
catype_to_str(*data));
data += 2;
olen -= 2;
" CA Element truncated",
get_line_remain());
}
if (solen > 0) {
}
}
break;
}
case DHCPV6_OPT_CLIENT_FQDN: {
if (olen == 0)
break;
" Flags = %02x", *data);
"Perform AAAA RR updates", "No AAAA RR updates"));
"Server override updates",
"No server override updates"));
"Server performs no updates",
"Server performs updates"));
" FQDN = %s", str);
}
}
break;
}
}
}
if (len != 0) {
get_line_remain());
}
}