nattymod.c revision fb87b5d22f7b8fbdd3a861267723144d852c7869
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Required include files.
*/
#include <sys/tpicommon.h>
#include <inet/udp_impl.h>
/*
* Design notes:
*
* - We assume that we're pushed on to a UDP instance that's bound to
* <addr>/4500. (This is done in in.iked.)
* - We assume that <addr> will not change on this instance.
* - With those two assumptions, we can make the following assertions:
* + We can cache not only the IRE, but also the address that we look
* up for the IRE.
* - We otherwise cache the ire in a manner similar to the conn_t structure
* in the main portions of TCP and IP.
*/
/* Structures. */
typedef struct nattyinfo
{
} nattyinfo_t;
/* Packet dropper for IP IPsec processing failures */
extern ipdropper_t ip_dropper;
/*
* Function prototypes.
*/
static int nattymodclose(queue_t *);
static void natty_ka_timeout_callback(void *v_sa);
/*
* Module linkage data
*/
static struct module_info nattymod_minfo = {
1970, /* mi_idnum */
"nattymod", /* mi_idname */
0, /* mi_minpsz */
INFPSZ, /* mi_maxpsz */
0, /* mi_hiwat */
0 /* mi_lowat */
};
static struct qinit nattymod_rinit = {
(int (*)())natty_rput, /* qi_putp */
NULL, /* qi_srvp */
nattymodopen, /* qi_qopen */
nattymodclose, /* qi_qclose */
NULL, /* qi_qadmin */
&nattymod_minfo, /* qi_minfo */
};
/*
* We don't worry much about the write-side here (except for the qtimeouts
* that send keepalives. Just putnext() and life is good. We only care about
* inbound packets.
*/
static struct qinit nattymod_winit = {
(int (*)())natty_wput, /* qi_putp */
NULL, /* qi_srvp */
NULL, /* qi_qopen */
NULL, /* qi_qclose */
NULL, /* qi_qadmin */
&nattymod_minfo, /* qi_minfo */
};
static struct streamtab nattymod_info = {
&nattymod_rinit, /* st_rdinit */
&nattymod_winit, /* st_wrinit */
};
"nattymod",
};
/*
* Module linkage information for the kernel.
*/
struct mod_ops mod_strmodops;
static struct modlstrmod modlstrmod = {
};
static struct modlinkage modlinkage = {
};
clock_t natty_ka_timeout = 0;
/*
* Standard module entry points.
*/
int
_init(void)
{
int error;
if (error != 0)
return (error);
}
int
_fini(void)
{
int error;
if (error == 0)
return (error);
}
int
{
}
/* ARGSUSED */
static int
{
return (EINVAL);
/* Use kmem_zalloc() to avoid initializing ni->* fields. */
/* Insert into list before packets are allowed to flow. */
return (0);
}
static int
{
/* Unlink from list. */
/* Unlinked from list means ==> no need to mutex. */
}
return (0);
}
static ipaddr_t
{
struct T_addr_ack *taa;
}
}
}
return (addr);
}
static void
{
/* I lost the race. */
return;
}
goto bail;
goto bail;
} else {
}
if (!cached) {
} else {
}
return;
bail:
/* Error getting address or ire. Make nattyinfo null and void. */
}
/* rput */
void
{
case M_DATA:
/* Shouldn't see M_DATA. UDP converts these to M_PROTO. */
break;
case M_PROTO:
case M_PCPROTO:
/* strip ip header, process, pass up */
natty_rput_other(q, mp);
return;
default:
return;
}
}
void
{
t_scalar_t t;
/* proto or pcproto from UDP */
if (t == T_UNITDATA_IND) {
natty_rput_pkt(q, mp);
return;
}
if (ni->ni_setup_done) {
return;
}
switch (t) {
case T_OPTMGMT_ACK:
if (ni->ni_rh_wait &&
}
break;
case T_ADDR_ACK:
}
break;
}
}
void
{
int ntries = 0;
#ifdef DEBUG
#endif
/* not fully set up */
return;
}
/* remember mp, may need it later */
return;
}
}
"Short packet");
return;
};
return;
}
/* IP headers */
if (pkt_len == 1) {
/* keep alive */
return;
}
if (pkt_len > 3) {
} else {
}
if (spi == 0) {
/*
* it's ike over 4500
* strip off marker and pass up
*/
return;
}
/*
* build new packet
*
* packet should be one mblk
* looks like [IP][UDP][ESP]
* via clever manipulation of mblk, becomes
* [IP][ESP]
*/
/* change fields */
/* len, protocol, cksum */
iph->ipha_hdr_checksum = 0;
/* we are v4 only */
AF_INET);
/* no associated sa error */
return;
}
if (ipsa->ipsa_natt_ka_timer == 0) {
}
/*
* If the cached ire is useless, try up to IRE_RETRIES number
* of times to get a new one.
*/
#define IRE_RETRIES 2
do {
return;
} else if (ntries < IRE_RETRIES) {
ntries++;
} else {
}
} while (ntries < IRE_RETRIES);
} else {
}
/* bad pkt */
}
static void
{
struct T_optmgmt_req *rp;
if (ni->ni_setup_done) {
return;
}
return;
}
return;
}
case T_SVR4_OPTMGMT_REQ:
/*
* Expect a T_optmgmt_req followed by an opthdr
* followed by an int (with the option value of interest).
* If the one request we're snooping for wouldn't fit,
* don't bother looking further.
*/
return;
}
if (((int *)(ohp + 1)) != 0) {
}
}
}
break;
case T_ADDR_REQ:
break;
}
}
static void
natty_ka_timeout_callback(void *v_sa)
{
struct T_unitdata_req *tudr;
queue_t *q;
/* clear out timer and return */
goto ntbail;
}
/*
* build packet
*
* [tudr][addr] + [1 byte of data (0xff)]
*/
/* natt timeouts are the least of our worries */
goto ntbail;
}
tudr->OPT_length = 0;
tudr->OPT_offset = 0;
if (ipsa->ipsa_remote_port != 0)
else
else
goto ntbail;
}
} else {
ipsa->ipsa_natt_ka_timer = 0;
}
q = ipsa->ipsa_natt_q;
if (q != NULL)
}
/*
* Called from ipif_down(), if this module's loaded (or it hits a modstub if
* not). Check all nattyinfos for the ipif pointer.
*/
void
{
continue;
}
}
}