qif.c revision ab25eeb551a4be927a4b6ae2cf8aff7ed17decb4
/*
* Copyright (C) 2000, 2003 by Darren Reed.
*
* See the IPFILTER.LICENCE file for details on licencing.
*
* Copyright 2006 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>
#include <sys/ethernet.h>
#if SOLARIS2 >= 6
# include <net/if_types.h>
# if SOLARIS2 >= 8
# endif
#endif
#include <netinet/in_systm.h>
#include "compat.h"
#include "qif.h"
#include "pfil.h"
#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 */
#if SOLARIS2 <= 6
# include <sys/kmem_impl.h>
#endif
#if SOLARIS2 >= 10
extern krwlock_t ill_g_lock;
#endif
static int qif_num = 0;
int qif_verbose = 0;
/* ------------------------------------------------------------------------ */
/* Function: qif_startup */
/* Returns: int - 0 == success, -1 == failure */
/* Parameters: None. */
/* */
/* Perform any initialisation of data structures related to managing qif's */
/* that is deemed necessary. */
/* ------------------------------------------------------------------------ */
int qif_startup()
{
return -1;
}
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_stop */
/* Returns: void */
/* Parameters: None. */
/* */
/* Deallocate all qif_t's allocated and clean up any other data structures */
/* required in order to 'shut down' this part of the pfil module. */
/* ------------------------------------------------------------------------ */
void qif_stop()
{
}
/* ------------------------------------------------------------------------ */
/* Function: q_to_ill */
/* Returns: void * - NULL == failure, else pointer to ill */
/* Parameters: rq(I) - pointer to STREAMS read queue */
/* Locks: pfil_rw */
/* */
/* Given a pointer to a queue, try and find the ill which owns it. */
/* ------------------------------------------------------------------------ */
{
#ifndef IRE_ILL_CN
if (rq) {
#if SOLARIS2 >= 10
#else
#endif
{
continue;
break;
break;
break;
break;
break;
}
}
#if SOLARIS2 >= 10
#endif
return ill;
#else /* IRE_ILL_CN */
if (!rq)
return 0;
break;
return ill;
#endif
}
#ifndef IRE_ILL_CN
/* ------------------------------------------------------------------------ */
/* Function: qif_ire_walker */
/* Returns: void */
/* Parameters: ire(I) - pointer to an ire_t */
/* arg(I) - pointer to a qif */
/* */
/* This function gets called by the ire-walking function for each ire in */
/* table. We enumerate through the ire looking for cached fastpath headers */
/* on a given NIC (the qif) so we can update qf_hl from its size. */
/* ------------------------------------------------------------------------ */
void
void *arg;
{
#if SOLARIS2 >= 6
#else
#endif
) {
#if SOLARIS2 >= 8
#else
#endif
if (m != NULL)
}
}
#endif
/* ------------------------------------------------------------------------ */
/* Function: qif_attach */
/* Returns: int - 0 == success, -1 == error in attaching qif_t to q */
/* Parameters: rq(I) - pointer to STREAMS read queue */
/* Write Lock: pfil_rw */
/* */
/* Attempt to bind a qif_t structure to a specific interface given the */
/* queue pointer. Assumes the queue already has a qif_t structure tagged */
/* against it. */
/* ------------------------------------------------------------------------ */
int
{
#ifdef IRE_ILL_CN
#else
#endif
/*
* Can we map the queue to a specific ill? If not, go no futher, we
* are only interested in being associated with queues that we can
* recognise as being used for IP communication of some sort.
*/
if (qif_verbose > 0)
"PFIL: cannot find interface for rq %p",
(void *)rq);
return -1;
}
#ifndef IRE_ILL_CN
#if SOLARIS2 < 8
#else
"!Unknown layer 2 header size for %s type %d sap %x\n",
}
#endif
#endif /* IRE_ILL_CN */
/*
* Protect against the qif_t being bound against an interface, twice
* by getting a lock on setting qf_bound and don't release it until
* all the information has been set with qf_bound finally set to 1
* after that.
*/
return 0;
}
#ifndef IRE_ILL_CN
#endif
#ifdef icmp_nextmtu
#endif
if (qif_verbose > 0)
#if SOLARIS2 <= 8
#else
# ifndef IRE_ILL_CN
# endif
#endif
return 0;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_new */
/* Returns: qif_t * - NULL == failure, else pointer to qif_t */
/* Parameters: q(I) - pointer to STREAMS queue */
/* */
/* Allocate a new qif struct, give it a unique number and add it to the */
/* list of registered qif_t's for the given queue. Along the way, if we */
/* find an existing qif_t for this queue, return that instead. */
/* ------------------------------------------------------------------------ */
qif_t *
queue_t *q;
int mflags;
{
(int)sizeof(qif_t));
return NULL;
}
return qif;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_delete */
/* Returns: void */
/* Parameters: None. */
/* Write Locks: pfil_rw */
/* */
/* Remove a qif structure from the list of recognised qif's. */
/* */
/* NOTE: The locking structure used here on qif's is to protect their use */
/* by the pkt.c functions for sending out a packet. It is possible that a */
/* packet will be processed on one queue and need to be output on another */
/* and given we cannot hold a lock across putnext() we need to use a P-V */
/* like algorithm for locking. The PT_* macros come from the PTY code. */
/* In the fullness of time, this function should be rewritten to make sure */
/* that it is not posible to find the qif before we call the PT_* macros */
/* and call qprocsoff(). */
/* ------------------------------------------------------------------------ */
/*ARGSUSED*/
void qif_delete(qif, q)
queue_t *q;
{
int rm = 0;
return;
rm = 1;
break;
}
}
if (rm) {
else {
}
}
return;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_iflookup */
/* Returns: void * - NULL == search failed, else pointer to qif_t */
/* Parameters: name(I) - pointer to the name */
/* sap(I) - SAP value */
/* Locks: pfil_rw */
/* */
/* Search the list of registered qif_t's for a match based on the name and */
/* the SAP and return a pointer to the matching entry. */
/* ------------------------------------------------------------------------ */
{
break;
return qif;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_update */
/* Returns: void */
/* Parameters: qif(I) - pointer to qif_t structure */
/* mp(I) - pointer to STREAMS message */
/* Locks: pfil_rw */
/* */
/* This function attempts to force an update of the qf_sap and qf_hl fields */
/* function should only be called if the mblk is a DL_IOC_HDR_INFO message. */
/* ------------------------------------------------------------------------ */
{
#ifdef IRE_ILL_CN
#else
#endif
return;
}
}
}
/*
* If we still have a 0 size expected fasthpath header length, check
* the ill structure to see if we can use it to now make a better
* guess about what to use.
*/
#ifndef IRE_ILL_CN
#if SOLARIS2 < 8
#else
#endif
}
#endif
}
/* ------------------------------------------------------------------------ */
/* Function: qif_walk */
/* Returns: qif_t * - NULL == search failed, else pointer to qif_t */
/* Parameters: qfp(IO) - pointer to the name */
/* */
/* NOTE: it is assumed the caller has a lock on pfil_rw */
/* */
/* Provide a function to enable the caller to enumerate through all of the */
/* qif_t's without being aware of the internal data structure used to store */
/* them in. */
/* ------------------------------------------------------------------------ */
{
return NULL;
else {
/*
* Make sure the pointer being passed in exists as a current
* object before returning its next value.
*/
break;
else
}
return *qfp;
}
/* ------------------------------------------------------------------------ */
/* Function: qif_ipmp_update */
/* Returns: void */
/* Parameters: ipmpconf(I) - pointer to an ill to match against */
/* */
/* Take an IPMP configuration string passed in to update the pfil config. */
/* The string may either indicate that an IPMP interface is to be deleted */
/* there is text after the '='. */
/* ------------------------------------------------------------------------ */
void qif_ipmp_update(char *ipmpconf)
{
char *s;
sap = ETHERTYPE_IP;
ipmpconf += 3;
#if SOLARIS2 >= 8
sap = IP6_DL_SAP;
ipmpconf += 3;
#else
return;
#endif
}
if (s != NULL) {
if (*(s + 1) == '\0')
*s = '\0';
else
*s++ = '\0';
}
return;
}
return;
}
break;
} else {
}
}
/* ------------------------------------------------------------------------ */
/* Function: qif_ipmp_delete */
/* Returns: void */
/* Parameters: qifname(I) - pointer to name of qif to delete */
/* */
/* Search for a qif structure that is named to match qifname, remove all */
/* references to it by others, delink and free it. */
/* ------------------------------------------------------------------------ */
void qif_ipmp_delete(char *qifname)
{
continue;
break;
}
}
}
}
/* ------------------------------------------------------------------------ */
/* Function: qif_ipmp_syncmaster */
/* Returns: void */
/* Parameters: updated(I) - pointer to updated qif structure */
/* Locks: pfil_rw */
/* */
/* This function rechecks all the qif structures that aren't defined for */
/* IPMP to see if they are indeed members of the group pointed to by */
/* updated. Ones that currently claim to be in updated are reset and */
/* rechecked in case they have become excluded. This function should be */
/* called for any new IPMP qif's created or when an IPMP qif changes. */
/* ------------------------------------------------------------------------ */
{
char *s, *t;
continue;
continue;
t = strchr(s, ',');
if (t != NULL)
*t = '\0';
if (t != NULL)
*t++ = ',';
s = t;
}
}
}
/* ------------------------------------------------------------------------ */
/* Function: qif_ipmp_syncslave */
/* Returns: void */
/* Parameters: target(I) - pointer to updated qif structure */
/* Locks: pfil_rw */
/* */
/* Check through the list of qif's to see if there is an IPMP with a member */
/* list that includes the one named by target. */
/* ------------------------------------------------------------------------ */
{
char *s, *t;
/*
* Recheck the entire list of qif's for any references to the one
*/
continue;
continue;
t = strchr(s, ',');
if (t != NULL)
*t = '\0';
if (t != NULL)
*t++ = ',';
s = t;
break;
}
}
}
/* ------------------------------------------------------------------------ */
/* Function: qif_hl_set */
/* Returns: void */
/* Parameters: ipmpconf(I) - string with header length setting for NIC */
/* */
/* For NICs that we cannot automatically determine the MAC header length of */
/* we provide a manual crook to achieve that with. The input syntax for */
/* the string is "[v4:|v6:]<ifname>=<length>" */
/* ------------------------------------------------------------------------ */
void qif_hl_set(char *ipmpconf)
{
char *s;
ipmpconf += 3;
#if SOLARIS2 >= 8
ipmpconf += 3;
#else
return;
#endif
}
if (s != NULL) {
if (*(s + 1) == '\0')
*s = '\0';
else
*s++ = '\0';
}
return;
break;
int hl = 0;
for (; *s != '\0'; s++) {
char c = *s;
if (c < '0' || c > '9')
return;
hl *= 10;
hl += c - '0';
}
}
}