packet.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <stdlib.h>
#include <dhcpmsg.h>
#include <stddef.h>
#include <assert.h>
#include "states.h"
#include "interface.h"
#include "agent.h"
#include "packet.h"
#include "util.h"
static void retransmit(iu_tq_t *, void *);
static int send_pkt_internal(struct ifslist *);
/*
* dhcp_type_ptob(): converts the DHCP packet type values in RFC2131 into
* values which can be used for recv_pkt()
*
* input: uchar_t: a DHCP packet type value, as defined in RFC2131
* output: dhcp_message_type_t: a packet type value for use with recv_pkt()
*/
static dhcp_message_type_t
{
/*
* note: the ordering here allows direct indexing of the table
* based on the RFC2131 packet type value passed in.
*/
static dhcp_message_type_t type_map[] = {
};
return (0);
}
/*
* pkt_type(): returns an integer representing the packet's type; only
* for use with outbound packets.
*
* input: PKT *: the packet to examine
* output: uchar_t: the packet type (0 if unknown)
*/
static uchar_t
{
/*
* this is a little dirty but it should get the job done.
* assumes that the type is in the statically allocated part
* of the options field.
*/
while (*option != CD_DHCP_TYPE) {
return (0);
option++;
}
return (option[2]);
}
/*
* init_pkt(): initializes and returns a packet of a given type
*
* input: struct ifslist *: the interface the packet will be going out
* uchar_t: the packet type (DHCP message type)
* output: dhcp_pkt_t *: a pointer to the initialized packet
*/
{
} else {
/*
* The mac address does not fit in the chaddr
* field, thus it can not be sent to the server,
* thus server can not unicast the reply. Per
* RFC 2131 4.4.1, client can set this bit in
* this bit, as it can respond to unicast responses
* from server using the 'ciaddr' address.
*/
}
/*
* since multiple dhcp leases may be maintained over the same dlpi
* device (e.g. "hme0" and "hme0:1"), make sure the xid is unique.
*/
do {
return (dpkt);
}
/*
* add_pkt_opt(): adds an option to a dhcp_pkt_t
*
* input: dhcp_pkt_t *: the packet to add the option to
* uchar_t: the type of option being added
* const void *: the value of that option
* uchar_t: the length of the value of the option
* output: void
*/
void
{
/* CD_END and CD_PAD options don't have a length field */
req_len--;
return;
"%d in packet", opt_type);
return;
}
if (opt_len > 0) {
}
}
/*
* add_pkt_opt16(): adds an option with a 16-bit value to a dhcp_pkt_t
*
* input: dhcp_pkt_t *: the packet to add the option to
* uchar_t: the type of option being added
* uint16_t: the value of that option
* output: void
*/
void
{
}
/*
* add_pkt_opt32(): adds an option with a 32-bit value to a dhcp_pkt_t
*
* input: dhcp_pkt_t *: the packet to add the option to
* uchar_t: the type of option being added
* uint32_t: the value of that option
* output: void
*/
void
{
}
/*
* get_pkt_times(): pulls the lease times out of a packet and stores them as
* host-byteorder relative times in the passed in parameters
*
* input: PKT_LIST *: the packet to pull the packet times from
* lease_t *: where to store the relative lease time in hbo
* lease_t *: where to store the relative t1 time in hbo
* lease_t *: where to store the relative t2 time in hbo
* output: void
*/
void
{
return;
return;
}
}
}
/*
*
* input: uint32_t: the number of seconds until lease expiration
* double: the approximate percentage of that time to return
* output: double: a number approximating (sec * pct)
*/
static double
{
}
/*
* free_pkt_list(): frees a packet list
*
* input: PKT_LIST **: the packet list to free
* output: void
*/
void
{
}
}
/*
* prepend_to_pkt_list(): prepends a packet to a packet list
*
* input: PKT_LIST **: the packet list
* PKT_LIST *: the packet to prepend
* output: void
*/
static void
{
}
/*
* remove_from_pkt_list(): removes a given packet from a packet list
*
* input: PKT_LIST **: the packet list
* PKT_LIST *: the packet to remove
* output: void
*/
void
{
return;
} else {
}
}
/*
* send_pkt_internal(): sends a packet out on an interface
*
* input: struct ifslist *: the interface to send the packet out on
* output: int: 1 if the packet is sent, 0 otherwise
*/
static int
{
/*
* if needed, schedule a retransmission timer, then attempt to
* send the packet. if we fail, then log the error. our
* return value should indicate whether or not we were
* successful in sending the request, independent of whether
* we could schedule a timer.
*/
if (ifsp->if_send_timeout != 0) {
"schedule retransmit timer for %s packet",
pkt_name);
else
}
/*
* set the `pkt->secs' field depending on the type of packet.
* it should be zero, except in the following cases:
*
* DISCOVER: set to the number of seconds since we started
* trying to obtain a lease.
*
* INFORM: set to the number of seconds since we started
* trying to get configuration parameters.
*
* REQUEST: if in the REQUESTING state, then same value as
* DISCOVER, otherwise the number of seconds
* since we started trying to obtain a lease.
*
* we also set `if_newstart_monosec', to the time we sent a
* REQUEST or DISCOVER packet, so we know the lease start
* time (the DISCOVER case is for handling BOOTP servers).
*/
case DISCOVER:
break;
case INFORM:
break;
case REQUEST:
break;
}
break;
default:
}
case BOUND:
case RENEWING:
case REBINDING:
dpkt->pkt_cur_len, 0,
sizeof (struct sockaddr_in));
break;
default:
break;
}
"%s packet to server", pkt_name);
else
"%s packet to server (will retry in %u seconds)",
return (0);
}
ifsp->if_packet_sent++;
return (1);
}
/*
* send_pkt(): sends a packet out on an interface
*
* input: struct ifslist *: the interface to send the packet out on
* dhcp_pkt_t *: the packet to send out
* in_addr_t: the destination IP address for the packet
* stop_func_t *: a pointer to function to indicate when to stop
* retransmitting the packet (if NULL, packet is
* not retransmitted)
* output: int: 1 if the packet was sent, 0 otherwise
*/
int
{
/*
* packets must be at least sizeof (PKT) or they may be dropped
* by routers. pad out the packet in this case.
*/
ifsp->if_packet_sent = 0;
/*
* TODO: dispose of this gruesome assumption (there's no real
* technical gain from doing so, but it would be cleaner)
*/
/*
* clear out any packets which had been previously received
* but not pulled off of the recv_packet queue.
*/
} else
return (send_pkt_internal(ifsp));
}
/*
* retransmit(): retransmits the current packet on an interface
*
* input: iu_tq_t *: unused
* void *: the struct ifslist * to send the packet on
* output: void
*/
/* ARGSUSED */
static void
{
(void) release_ifs(ifsp);
return;
}
/*
* check the callback to see if we should keep sending retransmissions
*/
return;
(void) send_pkt_internal(ifsp);
}
/*
* stop_pkt_retransmission(): stops retransmission of last sent packet
*
* input: struct ifslist *: the interface to stop retransmission on
* output: void
*/
void
{
(void) release_ifs(ifsp);
}
}
}
/*
* recv_pkt(): receives packets on an interface (put on ifsp->if_recv_pkt_list)
*
* input: struct ifslist *: the interface to receive packets on
* int: the file descriptor to receive the packet on
* dhcp_message_type_t: the types of packets to receive
* boolean_t: if B_TRUE, more than one packet can be received
* output: int: 1 if a packet was received successfully, 0 otherwise
*/
int
{
const char *recv_pkt_name;
/*
* collect replies. chain them up if the chain flag is set
* and we've already got one, otherwise drop the packet.
* calloc the PKT_LIST since dhcp_options_scan() relies on it
* being zeroed.
*/
goto failure;
}
case BOUND:
case RENEWING:
case REBINDING:
break;
default:
break;
}
if (retval == -1) {
goto failure;
}
case DHCP_WRONG_MSG_TYPE:
goto failure;
case DHCP_GARBLED_MSG_TYPE:
goto failure;
case DHCP_BAD_OPT_OVLD:
goto failure;
case 0:
break;
default:
goto failure;
}
/*
* make sure the packet we got in was one we were expecting --
* it needs to have the right type and to have the same xid.
*/
else
recv_pkt_type = 0;
goto failure;
}
/* the xid is opaque -- no byteorder work */
goto failure;
}
"%s packet, dropped", recv_pkt_name);
goto failure;
}
}
ifsp->if_received++;
return (1);
return (0);
}
/*
* next_retransmission(): returns the number of seconds until the next
* retransmission, based on the algorithm in RFC2131
*
* input: uint32_t: the number of milliseconds for the last retransmission
* output: uint32_t: the number of milliseconds until the next retransmission
*/
static uint32_t
{
/*
* start at 4, and increase by a factor of 2 up to 64. at each
* iteration, jitter the timeout by some fraction of a second.
*/
if (last_timeout_ms == 0)
else
}