dlpi_io.c revision 196ebda38376ba4822e6aeaae805d74b2cbeaaf5
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <stropts.h>
#include <string.h> /* strpbrk */
#include <fcntl.h>
#include <unistd.h>
#include <unistd.h>
#include <stdlib.h>
#include <dhcpmsg.h>
#include <libinetutil.h>
#include "dlprims.h"
#include "dlpi_io.h"
#include "v4_sum_impl.h"
/*
* dhcp_dlpi_open(): opens a DLPI stream to the given interface and returns
* information purpose about that interface.
*
* input: const char *: the name of the interface to open
* dl_info_ack_t *: a place to store information about the interface
* size_t: the size of dl_info_ack_t
* t_uscalar_t: the sap to bind to on this interface
* output: int: the open file descriptor on success, -1 on failure
*/
int
{
int fd;
int is_style2 = 0;
return (-1);
}
if (ifsp.ifsp_modcnt != 0) {
"specified with an interface name");
return (-1);
}
/* try dlpi style1 interface first; if it fails, try style 2 */
/* try style 2 interface */
/*
* temporary hack: if the style-2 open of the /dev link fails,
* diskless boot to succeed without necessarily pre-creating the
* /dev links, by taking advantage of devfs's ability to create
* /devices nodes for h/w devices on demand. this is to avoid
* the need to fiddle with packaging scripts to boot off a new
* NIC device. when /dev links are created on demand, this
* work-around may be removed.
*/
{
}
}
if (fd == -1) {
return (-1);
}
is_style2 = 1;
}
/*
* okay, so we've got an open DLPI stream now. make sure that
* it's DL_VERSION_2, DL_STYLE2, and that it's connectionless.
* from there, attach to the appropriate ppa, bind to dl_sap,
* and get ready to roll.
*/
return (-1);
}
return (-1);
}
"dhcp_dlpi_open: %s is DL_STYLE %lx, not DL_STYLE2",
return (-1);
}
"which is not supported", device_name,
return (-1);
}
return (-1);
}
return (-1);
}
/*
* we call this again since some of the information obtained
* previously was not valid since we had not yet attached (in
* particular, our MAC address) (but we needed to check the
* STYLE before we did the attach)
*/
return (-1);
}
return (-1);
}
return (fd);
}
/*
* dhcp_dlpi_close(): closes a previously opened DLPI stream
*
* input: int: the file descriptor of the DLPI stream
* output: int: 0 on success, -1 on failure
*/
int
dhcp_dlpi_close(int fd)
{
/* don't bother dismantling. it will happen automatically */
}
/*
* dlpi_recvfrom(): receives data on a DLPI stream
*
* input: int: the socket to receive the data on
* void *: a buffer to store the data in
* size_t: the size of the buffer
* struct sockaddr_in *: if non-NULL, sender's IP address is filled in
* struct sockaddr_in *: if non-NULL, recipient's IP address
* output: ssize_t: the number of bytes read on success, -1 on failure
*/
struct sockaddr_in *to)
{
void *data_buffer;
if (data_buffer == NULL) {
return (-1);
}
if (data_length == -1)
return (-1);
/*
* since we're just pulling data off the wire, what we have
* may look nothing like a DHCP packet. note that this
* shouldn't happen (pfmod should have tossed it already).
*/
return (-1);
}
/*
* verify checksums
*/
"ipv4 checksum");
return (-1);
}
"UDP checksum");
return (-1);
}
}
}
return (data_length);
}
/*
* dlpi_recv_link(): receives raw data on a DLPI stream
*
* input: int: the DLPI stream to receive the data on
* void *: a buffer to store the data in
* size_t: the size of the buffer
* uint32_t: flags (see dlpi_io.h)
* output: ssize_t: the number of bytes received on success, -1 on failure
*/
{
int getmsg_flags = 0;
char ctrlbuf[1024];
case MORECTL:
case MOREDATA:
if ((flags & DLPI_RECV_SHORT) == 0)
"data on streamhead");
break;
case -1:
return (-1);
default:
break;
}
}
/*
* dlpi_sendto(): sends UDP packets on a DLPI stream
*
* input: int: the socket to send the packet on
* void *: a buffer to send
* size_t: the size of the buffer
* struct sockaddr_in *: the IP address to send the data to
* uchar_t *: the link-layer destination address
* size_t: the size of the link-layer destination address
* output: ssize_t: the number of bytes sent on success, -1 on failure
*/
{
void *data_buffer;
/*
* TODO: someday we might want to support `to' not being
* the same as INADDR_BROADCAST. we don't need the support
* right now, but it's annoying to have a general interface
* that only supports a specific function.
*/
return (-1);
}
/*
* we allocate one extra byte here in case the UDP checksum
* routine needs it to get the packet length to be even.
*/
if (data_buffer == NULL) {
return (-1);
}
/*
* build the ipv4 header. assume that our source address is 0
* (since we wouldn't be using DLPI if we could actually send
* packets an easier way). note that we only need to set nonzero
* fields since we got calloc()'d memory above.
*/
/*
* From a purist's perspective, we should set the TTL to 1 for
* limited broadcasts. But operational experience (cisco routers)
* has shown that doing so results in the relay agent dropping our
* packets. These same devices (ciscos) also don't set the TTL
* to MAXTTL on the unicast side of the relay agent. Thus, the only
* safe thing to do is to always set the ttl to MAXTTL. Sigh.
*/
== -1) {
return (-1);
}
return (buf_len);
}
/*
* dlpi_send_link(): sends raw data down a DLPI stream
*
* input: int: the DLPI stream to send the data on
* void *: the raw data to send
* size_t: the size of the raw data
* uchar_t *: the link-layer destination address
* size_t: the size of the link-layer destination address
* output: ssize_t: 0 on success, -1 on failure
*/
{
/*
* allocate the control part of the message and fill it in.
* all we really indicate is the destination address
*/
return (-1);
}
return (retval);
}
/*
* set_packet_filter(): sets the current packet filter on a DLPI stream
*
* input: int: the DLPI stream to set the packet filter on
* filter_func_t *: the filter to use
* void *: an argument to pass to the filter function
* const char *: a text description of the filter's purpose
* output: void
*/
void
const char *filter_name)
{
struct packetfilt pf;
/*
* if this ioctl() fails, we're really hosed. the best we can
* really do is play on.
*/
else
/*
* clean out any potential cruft on the descriptor that
* appeared before we were able to set the filter
*/
}
/*
*
* input: ushort_t *: a place to store the packet filter code
* void *: not used
* output: ushort_t *: two bytes past the last byte in the packet filter
*/
/* ARGSUSED */
ushort_t *
{
/*
*/
/*
* make sure the IP packet doesn't have any options. 2nd
* nibble is the header length field.
* TODO: if we decide to handle options, this code goes away.
*/
*pfp++ = ENF_PUSHWORD + 0;
/*
* if there's a fragment offset, or if the IP_MF bit is lit,
* pitch the packet. this pitches all fragments.
* TODO: if we decide to handle fragments, this code goes away.
*/
/*
* make sure the packet is for the DHCP client port -- 22nd
* byte is the UDP port number.
*/
return (pfp);
}
/*
* build_broadcast_dest(): builds a DLPI destination address for the broadcast
* address for use in DL_UNITDATA_REQs
*
* input: dl_info_ack_t *: information about the interface
* uchar_t *: set to the length of the returned address
* output: uchar_t *: the broadcast address (dynamically allocated)
*/
uchar_t *
{
return (NULL);
} else {
}
return (dest_addr);
}