ip_netinfo.c revision 3e87ae1286f5b1197022556087b75e516d68b22b
/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <inet/ipsec_impl.h>
#include <inet/ipclassifier.h>
#include <inet/ipp_common.h>
#include <inet/ip_ftable.h>
/*
* IPv4 netinfo entry point declarations.
*/
const size_t);
static int ip_getpmtuenabled(net_handle_t);
size_t, net_ifaddr_t [], void *);
zoneid_t *);
uint64_t *);
struct sockaddr *);
const size_t);
size_t, net_ifaddr_t [], void *);
zoneid_t *);
uint64_t *);
struct sockaddr *);
static int net_no_getpmtuenabled(net_handle_t);
struct sockaddr *);
size_t, net_ifaddr_t [], void *);
zoneid_t *);
uint64_t *);
/* Netinfo private functions */
static int ip_getifname_impl(phy_if_t, char *,
ip_stack_t *);
ip_stack_t *);
ip_stack_t *);
ip_stack_t *);
void *);
ip_stack_t *);
ip_stack_t *);
static void ip_ni_queue_in_func(void *);
static void ip_ni_queue_out_func(void *);
static net_protocol_t ipv4info = {
};
static net_protocol_t ipv6info = {
};
static net_protocol_t arp_netinfo = {
};
/*
* The taskq eventq_queue_in is used to process the upside inject messages.
* The taskq eventq_queue_out is used to process the downside inject messages.
* The taskq eventq_queue_nic is used to process the nic event messages.
*/
/*
* Initialize queues for inject.
*/
void
{
if (eventq_queue_out == NULL) {
if (eventq_queue_out == NULL)
"ddi_taskq_create failed for IP_INJECT_QUEUE_OUT");
}
if (eventq_queue_in == NULL) {
if (eventq_queue_in == NULL)
"ddi_taskq_create failed for IP_INJECT_QUEUE_IN");
}
if (eventq_queue_nic == NULL) {
if (eventq_queue_nic == NULL)
"ddi_taskq_create failed for IP_NIC_EVENT_QUEUE");
}
}
/*
* Destroy inject queues
*/
void
{
if (eventq_queue_nic != NULL) {
}
if (eventq_queue_in != NULL) {
}
if (eventq_queue_out != NULL) {
}
}
/*
* Register IPv4 and IPv6 netinfo functions and initialize queues for inject.
*/
void
{
}
/*
* Unregister IPv4 and IPv6 functions.
*/
void
{
}
}
}
}
/*
* Initialize IPv4 hooks family the event
*/
void
{
!= 0) {
"net_family_register failed for ipv4");
}
"net_event_register failed for ipv4/physical_in");
}
"net_event_register failed for ipv4/physical_out");
}
"net_event_register failed for ipv4/forwarding");
}
"net_event_register failed for ipv4/loopback_in");
}
"net_event_register failed for ipv4/loopback_out");
}
"net_event_register failed for ipv4/nic_events");
}
}
}
void
{
}
}
}
}
}
}
&ipst->ips_ip4_observe);
}
&ipst->ips_ipv4root);
}
void
{
&ipst->ips_ip4_forwarding_event) == 0)
}
&ipst->ips_ip4_physical_in_event) == 0)
}
&ipst->ips_ip4_physical_out_event) == 0)
}
&ipst->ips_ip4_loopback_in_event) == 0)
}
&ipst->ips_ip4_loopback_out_event) == 0)
}
&ipst->ips_ip4_nic_events) == 0)
}
&ipst->ips_ip4_observe) == 0)
}
&ipst->ips_ipv4root);
}
/*
* Initialize IPv6 hooks family and event
*/
void
{
!= 0) {
"net_family_register failed for ipv6");
}
"net_event_register failed for ipv6/physical_in");
}
"net_event_register failed for ipv6/physical_out");
}
"net_event_register failed for ipv6/forwarding");
}
"net_event_register failed for ipv6/loopback_in");
}
"net_event_register failed for ipv6/loopback_out");
}
"net_event_register failed for ipv6/nic_events");
}
}
}
void
{
}
}
}
}
}
}
&ipst->ips_ip6_observe);
}
&ipst->ips_ipv6root);
}
void
{
&ipst->ips_ip6_forwarding_event) == 0)
}
&ipst->ips_ip6_physical_in_event) == 0)
}
&ipst->ips_ip6_physical_out_event) == 0)
}
&ipst->ips_ip6_loopback_in_event) == 0)
}
&ipst->ips_ip6_loopback_out_event) == 0)
}
&ipst->ips_ip6_nic_events) == 0)
}
&ipst->ips_ip6_observe) == 0)
}
&ipst->ips_ipv6root);
}
/*
* Determine the name of an IPv4 interface
*/
static int
{
}
/*
* Determine the name of an IPv6 interface
*/
static int
{
}
/*
* Shared implementation to determine the name of a given network interface
*/
/* ARGSUSED */
static int
{
return (1);
return (0);
}
/*
* Determine the MTU of an IPv4 network interface
*/
static int
{
netstack_t *ns;
}
/*
* Determine the MTU of an IPv6 network interface
*/
static int
{
netstack_t *ns;
}
/*
* Shared implementation to determine the MTU of a network interface
*/
/* ARGSUSED */
static int
{
int mtu;
return (0);
if (mtu == 0) {
return (0);
}
}
return (mtu);
}
/*
* Determine if path MTU discovery is enabled for IP
*/
static int
{
netstack_t *ns;
}
/*
* Get next interface from the current list of IPv4 physical network interfaces
*/
static phy_if_t
{
netstack_t *ns;
}
/*
* Get next interface from the current list of IPv6 physical network interfaces
*/
static phy_if_t
{
netstack_t *ns;
}
/*
* Determine if a network interface name exists for IPv4
*/
static phy_if_t
{
netstack_t *ns;
}
/*
* Determine if a network interface name exists for IPv6
*/
static phy_if_t
{
netstack_t *ns;
}
/*
* Implement looking up an ill_t based on the name supplied and matching
* it up with either IPv4 or IPv6. ill_get_ifindex_by_name() is not used
* because it does not match on the address family in addition to the name.
*/
static phy_if_t
{
return (0);
return (phy);
}
/*
* Get next interface from the current list of IPv4 logical network interfaces
*/
static lif_if_t
{
netstack_t *ns;
ns->netstack_ip));
}
/*
* Get next interface from the current list of IPv6 logical network interfaces
*/
static lif_if_t
{
netstack_t *ns;
ns->netstack_ip));
}
/*
* Shared implementation to get next interface from the current list of
* logical network interfaces
*/
static lif_if_t
{
return (0);
if (ifdata != 0) {
} else {
oldidx = 0;
}
return (0);
}
/*
* It's safe to iterate the ill_ipif list when holding an ill_lock.
* And it's also safe to access ipif_id without ipif refhold.
* See the field access rules in ip.h.
*/
if (!IPIF_CAN_LOOKUP(ipif))
continue;
if (nextok) {
break;
}
}
return (0);
return (MAP_IPIF_ID(newidx));
}
/*
* Inject an IPv4 packet to or from an interface
*/
static int
{
netstack_t *ns;
}
/*
* Inject an IPv6 packet to or from an interface
*/
static int
{
netstack_t *ns;
}
/*
* Shared implementation to inject a packet to or from an interface
* Return value:
* 0: successful
* -1: memory allocation failed
* 1: other errors
*/
static int
{
void (* func)(void *);
switch (style) {
case NI_QUEUE_IN:
return (-1);
/*
* deliver up into the kernel, immitating its reception by a
* network interface, add to list and schedule timeout
*/
break;
case NI_QUEUE_OUT:
return (-1);
/*
* deliver out of the kernel, as if it were being sent via a
* raw socket so that IPFilter will see it again, add to list
* and schedule timeout
*/
break;
case NI_DIRECT_OUT: {
/*
* ipfil_sendpkt was provided by surya to ease the
* problems associated with sending out a packet.
*/
case 0 :
case EINPROGRESS:
return (0);
case ECOMM :
case ENONET :
return (1);
default :
return (1);
}
/* NOTREACHED */
}
default:
return (1);
}
DDI_SLEEP) == DDI_FAILURE) {
ip2dbg(("ip_inject: ddi_taskq_dispatch failed\n"));
return (1);
}
return (0);
}
/*
* Find the interface used for traffic to a given IPv4 address
*/
static phy_if_t
{
netstack_t *ns;
return (0);
}
/*
* Find the interface used for traffic to a given IPv6 address
*/
static phy_if_t
{
netstack_t *ns;
return (0);
}
/*
* Find the interface used for traffic to an address.
* a value at the top. The alternative would end up with two bunches
* of assignments, with each bunch setting half to NULL.
*/
static phy_if_t
{
} else {
}
/*
* For some destinations, we have routes that are dead ends, so
* return to indicate that no physical interface can be used to
* reach the destination.
*/
return (NULL);
}
if (nexthop_ire == NULL) {
return (0);
}
return (0);
}
} else {
}
}
return (phy_if);
}
/*
* Determine if checksumming is being used for the given packet.
*
* Return value:
* NET_HCK_NONE: full checksum recalculation is required
* NET_HCK_L3_FULL: full layer 3 checksum
* NET_HCK_L4_FULL: full layer 4 checksum
* NET_HCK_L4_PART: partial layer 4 checksum
*/
/*ARGSUSED*/
static int
{
int ret = 0;
ret |= (int)NET_HCK_L4_FULL;
ret |= (int)NET_HCK_L3_FULL;
}
ret |= (int)NET_HCK_L4_PART;
ret |= (int)NET_HCK_L3_FULL;
}
return (ret);
}
/*
* Return true or false, indicating whether the network and transport
* headers are correct. Use the capabilities flags and flags set in the
* dblk_t to determine whether or not the checksum is valid.
*
* Return:
* 0: the checksum was incorrect
* 1: the original checksum was correct
*/
/*ARGSUSED*/
static int
{
unsigned char *wptr;
int hlen;
int ret;
if (dohwcksum &&
return (1);
/*
* Check that the mblk being passed in has enough data in it
* before blindly checking ip_cksum.
*/
return (0);
return (0);
} else {
}
ret = 1;
else
ret = 0;
return (ret);
}
/*
* Unsupported with IPv6
*/
/*ARGSUSED*/
static int
{
return (-1);
}
/*
* Determine the network addresses for an IPv4 interface
*/
static int
{
netstack_t *ns;
}
/*
* Determine the network addresses for an IPv6 interface
*/
static int
{
netstack_t *ns;
}
/*
* Shared implementation to determine the network addresses for an interface
*/
/* ARGSUSED */
static int
{
struct sockaddr_in6 *sin6;
struct sockaddr_in *sin;
int i;
return (1);
ip2dbg(("ip_getlifaddr_impl failed type %d\n",
type[i]));
return (1);
}
}
} else {
return (1);
ip2dbg(("ip_getlifaddr_impl failed type %d\n",
type[i]));
return (1);
}
}
}
return (0);
}
/*
* ip_getlifaddr private function
*/
static int
{
void *src_addr;
int mem_size;
switch (type) {
case NA_ADDRESS:
break;
case NA_PEER:
break;
case NA_BROADCAST:
break;
case NA_NETMASK:
break;
default:
return (-1);
/*NOTREACHED*/
}
} else {
switch (type) {
case NA_ADDRESS:
break;
case NA_PEER:
break;
case NA_BROADCAST:
break;
case NA_NETMASK:
break;
default:
return (-1);
/*NOTREACHED*/
}
}
return (1);
}
/*
* address
*/
static int
{
return (-1);
return (0);
}
/*
* Determine the zoneid associated with an IPv4 address
*/
static int
{
}
/*
* Determine the zoneid associated with an IPv6 address
*/
static int
{
}
/*
* The behaviour here mirrors that for the SIOCFLIFFLAGS ioctl where the
* union of all of the relevant flags is returned.
*/
static int
{
return (-1);
return (-1);
}
return (0);
}
static int
{
}
static int
{
}
/*
* Deliver packet up into the kernel, immitating its reception by a
* network interface.
*/
static void
ip_ni_queue_in_func(void *inject)
{
}
/*
* Deliver out of the kernel, as if it were being sent via a
* raw socket so that IPFilter will see it again.
*/
static void
ip_ni_queue_out_func(void *inject)
{
}
/*
* Shared implementation for inject via ip_output and ip_input
*/
static void
{
if (out == 0) {
return;
}
} else {
}
} else {
} else {
}
ixa_cleanup(&ixas);
}
}
/*
* taskq function for nic events.
*/
void
ip_ne_queue_func(void *arg)
{
netstack_t *ns;
goto done;
goto done;
done:
}
/*
* Initialize ARP hook family and events
*/
void
{
!= 0) {
"net_family_register failed for arp");
}
"net_event_register failed for arp/physical_in");
}
"net_event_register failed for arp/physical_out");
}
"net_event_register failed for arp/nic_events");
}
}
void
{
&ipst->ips_arp_nic_events) == 0)
}
&ipst->ips_arp_physical_out_event) == 0)
}
&ipst->ips_arp_physical_in_event) == 0)
}
&ipst->ips_arproot);
}
void
{
}
}
}
}
/* netinfo routines for the unsupported cases */
/* ARGSUSED */
int
{
return (-1);
}
/* ARGSUSED */
static int
{
return (-1);
}
/* ARGSUSED */
static lif_if_t
{
return (-1);
}
/* ARGSUSED */
static int
{
return (-1);
}
/* ARGSUSED */
static phy_if_t
{
return ((phy_if_t)-1);
}
/* ARGSUSED */
static int
{
return (-1);
}
/* ARGSUSED */
static int
{
return (-1);
}
/* ARGSUSED */
static int
{
return (-1);
}
/* ARGSUSED */
static int
{
return (-1);
}