/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_NETI_H
#define	_SYS_NETI_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <netinet/in.h>
#include <sys/int_types.h>
#include <sys/queue.h>
#include <sys/hook_impl.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	NETINFO_VERSION 1

/*
 * Network hooks framework stack protocol name
 */
#define	NHF_INET	"NHF_INET"
#define	NHF_INET6	"NHF_INET6"
#define	NHF_ARP		"NHF_ARP"

/*
 * Event identification
 */
#define	NH_PHYSICAL_IN	"PHYSICAL_IN"
#define	NH_PHYSICAL_OUT	"PHYSICAL_OUT"
#define	NH_FORWARDING	"FORWARDING"
#define	NH_LOOPBACK_IN	"LOOPBACK_IN"
#define	NH_LOOPBACK_OUT	"LOOPBACK_OUT"
#define	NH_NIC_EVENTS	"NIC_EVENTS"

/*
 * Network NIC hardware checksum capability
 */
#define	NET_HCK_NONE   	0x00
#define	NET_HCK_L3_FULL	0x01
#define	NET_HCK_L3_PART	0x02
#define	NET_HCK_L4_FULL	0x10
#define	NET_HCK_L4_PART	0x20

#define	NET_IS_HCK_L3_FULL(n, x)                                             \
	((net_ispartialchecksum(n, x) & NET_HCK_L3_FULL) == NET_HCK_L3_FULL)
#define	NET_IS_HCK_L3_PART(n, x)                                             \
	((net_ispartialchecksum(n, x) & NET_HCK_L3_PART) == NET_HCK_L3_PART)
#define	NET_IS_HCK_L4_FULL(n, x)                                             \
	((net_ispartialchecksum(n, x) & NET_HCK_L4_FULL) == NET_HCK_L4_FULL)
#define	NET_IS_HCK_L4_PART(n, x)                                             \
	((net_ispartialchecksum(n, x) & NET_HCK_L4_PART) == NET_HCK_L4_PART)
#define	NET_IS_HCK_L34_FULL(n, x)                                            \
	((net_ispartialchecksum(n, x) & (NET_HCK_L3_FULL|NET_HCK_L4_FULL))   \
	    == (NET_HCK_L3_FULL | NET_HCK_L4_FULL))

typedef uintptr_t	phy_if_t;
typedef intptr_t	lif_if_t;
typedef uintptr_t	net_ifdata_t;

struct net_data;
typedef struct net_data *net_data_t;

/*
 * Netinfo interface specification
 *
 * Netinfo provides an extensible and easy to use interface for
 * accessing data and functionality already embedded within network
 * code that exists within the kernel.
 */
typedef enum net_ifaddr {
	NA_ADDRESS = 1,
	NA_PEER,
	NA_BROADCAST,
	NA_NETMASK
} net_ifaddr_t;


typedef enum inject {
	NI_QUEUE_IN = 1,
	NI_QUEUE_OUT,
	NI_DIRECT_OUT
} inject_t;

typedef struct net_inject {
	mblk_t			*ni_packet;
	struct sockaddr_storage	ni_addr;
	phy_if_t		ni_physical;
} net_inject_t;


/*
 * net_info_t public interface
 */
typedef struct net_info {
	int		neti_version;
	char		*neti_protocol;
	int		(*neti_getifname)(phy_if_t, char *, const size_t);
	int		(*neti_getmtu)(phy_if_t, lif_if_t);
	int		(*neti_getpmtuenabled)(void);
	int		(*neti_getlifaddr)(phy_if_t, lif_if_t, size_t,
			    net_ifaddr_t [], void *);
	phy_if_t	(*neti_phygetnext)(phy_if_t);
	phy_if_t	(*neti_phylookup)(const char *);
	lif_if_t	(*neti_lifgetnext)(phy_if_t, lif_if_t);
	int		(*neti_inject)(inject_t, net_inject_t *);
	phy_if_t	(*neti_routeto)(struct sockaddr *);
	int		(*neti_ispartialchecksum)(mblk_t *);
	int		(*neti_isvalidchecksum)(mblk_t *);
} net_info_t;


/*
 * Private data structures
 */
struct net_data {
	LIST_ENTRY(net_data)		netd_list;
	net_info_t			netd_info;
	int				netd_refcnt;
	hook_family_int_t		*netd_hooks;
};


typedef struct injection_s {
	net_inject_t	inj_data;
	boolean_t	inj_isv6;
} injection_t;

/*
 * The ipif_id space is [0,MAX) but this interface wants to return [1,MAX] as
 * a valid range of logical interface numbers so that it can return 0 to mean
 * "end of list" with net_lifgetnext.  Changing ipif_id's to use the [1,MAX]
 * space is something to be considered for the future, if it is worthwhile.
 */
#define	MAP_IPIF_ID(x)		((x) + 1)
#define	UNMAP_IPIF_ID(x)	(((x) > 0) ? (x) - 1 : (x))


/*
 * Data management functions
 */
extern net_data_t net_register(const net_info_t *);
extern int net_unregister(net_data_t);
extern net_data_t net_lookup(const char *);
extern int net_release(net_data_t);
extern net_data_t net_walk(net_data_t);

/*
 * Accessor functions
 */
extern int net_register_family(net_data_t, hook_family_t *);
extern int net_unregister_family(net_data_t, hook_family_t *);
extern hook_event_token_t net_register_event(net_data_t, hook_event_t *);
extern int net_unregister_event(net_data_t, hook_event_t *);
extern int net_register_hook(net_data_t, char *, hook_t *);
extern int net_unregister_hook(net_data_t, char *, hook_t *);
extern int net_getifname(net_data_t, phy_if_t, char *, const size_t);
extern int net_getmtu(net_data_t, phy_if_t, lif_if_t);
extern int net_getpmtuenabled(net_data_t);
extern int net_getlifaddr(net_data_t, phy_if_t, lif_if_t,
    int, net_ifaddr_t [], void *);
extern phy_if_t net_phygetnext(net_data_t, phy_if_t);
extern phy_if_t net_phylookup(net_data_t, const char *);
extern lif_if_t net_lifgetnext(net_data_t, phy_if_t, lif_if_t);
extern int net_inject(net_data_t, inject_t, net_inject_t *);
extern phy_if_t net_routeto(net_data_t, struct sockaddr *);
extern int net_ispartialchecksum(net_data_t, mblk_t *);
extern int net_isvalidchecksum(net_data_t, mblk_t *);

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_NETI_H */