solaris.c revision 87c3980e28619b2b20d03f92d14b18fd89c183ca
/*
* Copyright (C) 1993-2001, 2003 by Darren Reed.
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/dditypes.h>
#include <sys/autoconf.h>
#include <sys/byteorder.h>
#if SOLARIS2 >= 6
# include <net/if_types.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/if_ether.h>
#include "ip_compat.h"
#include "ipl.h"
#include "ip_fil.h"
#include "ip_nat.h"
#include "ip_frag.h"
#include "ip_auth.h"
#include "ip_state.h"
#if SOLARIS2 >= 10
#include "pfild.h"
#endif
extern struct filterstats frstats[];
extern int fr_running;
extern int fr_flags;
#ifdef IPFILTER_SYNC
#endif
void *, void **));
#if SOLARIS2 < 10
#endif
IPLOOKUP_NAME, NULL };
#if SOLARIS2 >= 7
void fr_slowtimer __P((void *));
static timeout_id_t synctimeoutid = 0;
#else
void fr_slowtimer __P((void));
int fr_timer_id;
static int synctimeoutid = 0;
#endif
#ifndef IRE_ILL_CN
#ifdef IPFDEBUG
#endif
#endif
static struct cb_ops ipf_cb_ops = {
nodev, /* strategy */
nodev, /* print */
nodev, /* dump */
#ifdef IPFILTER_SYNC
iplwrite, /* write */
#else
nodev, /* write */
#endif
iplioctl, /* ioctl */
nodev, /* devmap */
nodev, /* mmap */
nodev, /* segmap */
nochpoll, /* poll */
NULL,
#if SOLARIS2 > 4
nodev, /* aread */
nodev, /* awrite */
#endif
};
0,
#if SOLARIS2 >= 10
#else
#endif
nodev, /* reset */
(struct bus_ops *)0
};
extern struct mod_ops mod_driverops;
#if SOLARIS2 >= 6
{ 0, 0 },
{ IFT_OTHER, 0 },
{ IFT_1822, 0 },
{ IFT_HDH1822, 0 },
{ IFT_X25DDN, 0 },
{ IFT_X25, 0 },
{ IFT_ETHER, 14 },
{ IFT_ISO88023, 0 },
{ IFT_ISO88024, 0 },
{ IFT_ISO88025, 0 },
{ IFT_ISO88026, 0 },
{ IFT_STARLAN, 0 },
{ IFT_P10, 0 },
{ IFT_P80, 0 },
{ IFT_HY, 0 },
{ IFT_FDDI, 24 },
{ IFT_LAPB, 0 },
{ IFT_SDLC, 0 },
{ IFT_T1, 0 },
{ IFT_CEPT, 0 },
{ IFT_ISDNBASIC, 0 },
{ IFT_ISDNPRIMARY, 0 },
{ IFT_PTPSERIAL, 0 },
{ IFT_PPP, 0 },
{ IFT_LOOP, 0 },
{ IFT_EON, 0 },
{ IFT_XETHER, 0 },
{ IFT_NSIP, 0 },
{ IFT_SLIP, 0 },
{ IFT_ULTRA, 0 },
{ IFT_DS3, 0 },
{ IFT_SIP, 0 },
{ IFT_FRELAY, 0 },
{ IFT_RS232, 0 },
{ IFT_PARA, 0 },
{ IFT_ARCNET, 0 },
{ IFT_ARCNETPLUS, 0 },
{ IFT_ATM, 0 },
{ IFT_MIOX25, 0 },
{ IFT_SONET, 0 },
{ IFT_X25PLE, 0 },
{ IFT_ISO88022LLC, 0 },
{ IFT_LOCALTALK, 0 },
{ IFT_SMDSDXI, 0 },
{ IFT_FRELAYDCE, 0 },
{ IFT_V35, 0 },
{ IFT_HSSI, 0 },
{ IFT_HIPPI, 0 },
{ IFT_MODEM, 0 },
{ IFT_AAL5, 0 },
{ IFT_SONETPATH, 0 },
{ IFT_SONETVT, 0 },
{ IFT_SMDSICIP, 0 },
{ IFT_PROPVIRTUAL, 0 },
{ IFT_PROPMUX, 0 },
};
#endif /* SOLARIS2 >= 6 */
int _init()
{
int status;
/*
* Initialize mutex's
*/
if (status != 0) {
}
return status;
}
int _fini(void)
{
int status;
if (status != 0)
return status;
return status;
}
{
int status;
return status;
}
#if SOLARIS2 < 10
static int ipf_identify(dip)
{
#ifdef IPFDEBUG
#endif
return (DDI_IDENTIFIED);
return (DDI_NOT_IDENTIFIED);
}
#endif
{
char *s;
int i;
int instance;
#ifdef IPFDEBUG
#endif
switch (cmd)
{
case DDI_ATTACH:
/* Only one instance of ipf (instance 0) can be attached.*/
if (instance > 0)
return DDI_FAILURE;
if (fr_running != 0)
return DDI_FAILURE;
if (pfilinterface != PFIL_INTERFACE) {
#ifdef IPFDEBUG
#endif
return DDI_FAILURE;
}
1) != DDI_PROP_SUCCESS) {
#ifdef IPFDEBUG
#endif
return DDI_FAILURE;
}
for (i = 0; ((s = ipf_devfiles[i]) != NULL); i++) {
s = strrchr(s, '/');
if (s == NULL)
continue;
s++;
DDI_PSEUDO, 0) ==
DDI_FAILURE) {
return DDI_FAILURE;
}
}
ipf_dev_info = dip;
/*
* Lock people out while we set things up.
*/
#ifdef IPFDEBUG
#endif
goto attach_failed;
}
goto attach_failed;
}
#ifdef USE_INET6
goto attach_failed;
}
#endif
goto attach_failed;
}
drv_usectohz(500000));
fr_running = 1;
return DDI_SUCCESS;
/* NOTREACHED */
default:
return DDI_FAILURE;
}
#ifdef IPFDEBUG
#endif
/*
* Use our own detach routine to toss
* away any stuff we allocated above.
*/
return DDI_FAILURE;
}
{
int i;
#ifdef IPFDEBUG
#endif
switch (cmd) {
case DDI_DETACH:
#ifdef IPFDEBUG
"or already detached");
#endif
break;
}
/*
* Make sure we're the only one's modifying things. With
* this lock others should just fall out of the loop.
*/
if (fr_running <= 0) {
return DDI_FAILURE;
}
fr_running = -2;
#ifdef USE_INET6
#endif
if (fr_timer_id != 0) {
(void) untimeout(fr_timer_id);
fr_timer_id = 0;
}
/*
* Undo what we did in ipf_attach, freeing resources
* and removing things we installed. The system
* framework guarantees we are not active with this devinfo
* node in any other entry points at this time.
*/
i = ddi_get_instance(dip);
if (i > 0) {
#ifdef IPFDEBUG
#endif
return DDI_FAILURE;
}
if (!ipldetach()) {
#ifdef IPFDEBUG
#endif
return (DDI_SUCCESS);
}
#ifdef IPFDEBUG
#endif
break;
default:
return DDI_FAILURE;
}
#ifdef IPFDEBUG
#endif
return DDI_FAILURE;
}
/*ARGSUSED*/
{
int error;
if (fr_running <= 0)
return DDI_FAILURE;
error = DDI_FAILURE;
#ifdef IPFDEBUG
#endif
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
*result = ipf_dev_info;
error = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2INSTANCE:
*result = (void *)0;
error = DDI_SUCCESS;
break;
default:
break;
}
return (error);
}
/*
* look for bad consistancies between the list of interfaces the filter knows
* about and those which are currently configured.
*/
/*ARGSUSED*/
int hlen;
void *il;
int out;
{
frsync();
/*
* Resync. any NAT `connections' using this interface and its IP #.
*/
fr_natsync(il);
return 0;
}
/*
* look for bad consistancies between the list of interfaces the filter knows
* about and those which are currently configured.
*/
int ipfsync()
{
frsync();
/*
* Resync. any NAT `connections' using this interface and its IP #.
*/
return 0;
}
#ifndef IRE_ILL_CN
#ifdef IPFDEBUG
{
printf("ire: ll_hdr_mp %p rfq %p stq %p src_addr %x max_frag %d\n",
# if SOLARIS2 >= 8
NULL,
# else
# endif
printf("ire: mask %x addr %x gateway_addr %x type %d\n",
printf("ire: ll_hdr_length %d ll_hdr_saved_mp %p\n",
# if SOLARIS2 >= 8
# else
# endif
);
}
#endif
#endif /* IRE_ILL_CN */
/*
* Function: fr_fastroute
* Returns: 0: success;
* -1: failed
* Parameters:
* mb: the message block where ip head starts
* mpp: the pointer to the pointer of the orignal
* packet message
* fin: packet information
* fdp: destination interface information
* if it is NULL, no interface information provided.
*
* pfil_make_lay2_packet to search route, make lay-2 header
* ,and identify output queue for the IP packet.
* The destination address depends on the following conditions:
* 1: for fastroute rule, fdp is passed in as NULL, so the
* destination address is the IP Packet's destination address
* the interface name, this address is the as destination
* address. Otherwise IP Packet's destination address is used
*/
{
#ifndef IRE_ILL_CN
u_char *s;
#else
#endif
#ifndef sparc
#endif
#ifndef IRE_ILL_CN
#ifdef USE_INET6
#endif
#endif
/*
* If this is a duplicate mblk then we want ip to point at that
* data, not the original, if and only if it is already pointing at
* the current mblk data.
*/
/*
* If there is another M_PROTO, we don't want it
*/
}
/*
* In case we're here due to "to <if>" being used with
* "keep state", check that we're going in the correct
* direction.
*/
goto bad_fastroute;
}
#ifndef IRE_ILL_CN
if (!fdp) {
if (!ipif)
goto bad_fastroute;
#if SOLARIS2 > 5
#else
#endif
if (!ir)
}
else
#if SOLARIS2 >= 6
}
#ifdef USE_INET6
}
#endif
#else
#endif
#if SOLARIS2 < 8
if (dir)
#else
if (dir)
#endif
if (!ir)
goto bad_fastroute;
#if SOLARIS2 < 8
#else
#endif
if (
#if SOLARIS2 >= 6
(dohwcksum &&
#endif
s -= hlen;
} else {
if (!mp2)
goto bad_fastroute;
}
}
if (q)
q = q->q_next;
if (!q)
goto bad_fastroute;
goto bad_fastroute;
#else /* IRE_ILL_CN */
}
#ifdef USE_INET6
}
#endif
else
goto bad_fastroute;
{
goto bad_fastroute;
}
/*
* TODO: assign fin->fin_ifp = ?
* The ? can be get from mb->b_queue depending on
* what will be done when replacing of s_ill_t.
*/
#endif /* IRE_ILL_CN */
}
#ifndef sparc
}
#endif
#ifndef IRE_ILL_CN
#if SOLARIS2 >= 6
if ((p == IPPROTO_TCP) && dohwcksum &&
u_32_t t;
t += 30;
t = (t & 0xffff) + (t >> 16);
}
#endif
#else /* IRE_ILL_CN */
pfil_send_dl_packet(q, mb);
#endif /* IRE_ILL_CN */
fr_frouteok[0]++;
return 0;
fr_frouteok[1]++;
return -1;
}
#if SOLARIS2 >= 10
/*
* Function: addrset_match_v4
* Returns: boolean_t
* Parameters: addr - the IP address of interest
* setp - pointer to an address set (generated by pfild)
*
* Support function for fr_verifysrc used on Solaris 10 and later.
* Try to match an IPv4 address against an address set.
* Returns true iff the specified address is a member of the set.
* Note that addr is passed in network byte order; we convert it to host byte
* order for searching the table.
*/
struct pfil_ifaddrset *setp;
{
/* binary search */
low = 0;
else
return B_TRUE;
}
return B_FALSE;
}
/*
* Function: addrset_match_v6
* Returns: boolean_t
* Parameters: addr - the IP address of interest
* setp - pointer to an address set (generated by pfild)
*
* Support function for fr_verifysrc used on Solaris 10 and later.
* Try to match an IPv6 address against an address set.
* Returns true iff the specified address is a member of the set.
*/
struct pfil_ifaddrset *setp;
{
/* binary search */
low = 0;
else
return B_TRUE;
}
return B_FALSE;
}
#endif
/*
* Function: fr_verifysrc
* Returns: int (really boolean)
* Parameters: fin - packet information
*
* Check whether the packet has a valid source address for the interface on
* which the packet arrived, implementing the "fr_chksrc" feature.
* Returns true iff the packet's source address is valid.
* Pre-Solaris 10, we call into the routing code to make the determination.
* On Solaris 10 and later, we have a valid address set from pfild to check
* against.
*/
int fr_verifysrc(fin)
{
#if SOLARIS2 >= 10
struct pfil_ifaddrset *setp;
/* Warn here? pfild might not be running. */
return 0;
}
if (!setp)
return 0;
return 0; /* malformed set */
return 0; /* malformed set */
} else
return 0;
#else
#if SOLARIS2 >= 6
#else
#endif
if (!dir)
return 0;
#endif /* SOLARIS2 >= 10 */
}
#if (SOLARIS2 < 7)
void fr_slowtimer()
#else
/*ARGSUSED*/
#endif
{
if (fr_running <= 0) {
if (fr_running == -1)
drv_usectohz(500000));
else
fr_timer_id = NULL;
return;
}
fr_natexpire();
fr_ticks++;
else
fr_timer_id = NULL;
}