ip_rpcb_pxy.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Copyright (C) 2002-2003 by Ryan Beasley <ryanb@goddamnbastard.org>
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * See the IPFILTER.LICENCE file for details on licencing.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * This is an in-kernel application proxy for Sun's RPCBIND (nee portmap)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * protocol as defined in RFC1833. It is far from complete, mostly
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * lacking in less-likely corner cases, but it's definitely functional.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Invocation:
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * rdr <int> <e_ip>/32 port <e_p> -> <i_ip> port <i_p> udp proxy rpcbu
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * If the host running IP Filter is the same as the RPC server, it's
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * perfectly legal for both the internal and external addresses and ports
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * When triggered by appropriate IP NAT rules, this proxy works by
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * examining data contained in received packets. Requests and replies are
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * modified, NAT and state table entries created, etc., as necessary.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * TODO / NOTES
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Must implement locking to protect proxy session data.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Fragmentation isn't supported.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Only supports UDP.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Doesn't support multiple RPC records in a single request.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Errors should be more fine-grained. (e.g., malloc failure vs.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * illegal RPCB request / reply)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o Even with the limit on the total amount of recorded transactions,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * should there be a timeout on transaction removal?
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o There is a potential collision between cloning, wildcard NAT and
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * state entries. There should be an appr_getport routine for
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * to avoid this.
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * o The enclosed hack of STREAMS support is pretty sick and most likely
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * $Id: ip_rpcb_pxy.c,v 2.17 2003/07/01 18:30:21 darrenr Exp $
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Function prototypes
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenkint ippr_rpcb_new __P((fr_info_t *, ap_session_t *, nat_t *));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkint ippr_rpcb_in __P((fr_info_t *, ap_session_t *, nat_t *));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkint ippr_rpcb_out __P((fr_info_t *, ap_session_t *, nat_t *));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void ippr_rpcb_flush __P((rpcb_session_t *));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_decodereq __P((fr_info_t *, nat_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_skipauth __P((rpc_msg_t *, xdr_auth_t *, u_32_t **));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_insert __P((rpcb_session_t *, rpcb_xact_t *));
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenkstatic int ippr_rpcb_xdrrpcb __P((rpc_msg_t *, u_32_t *, rpcb_args_t *));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_getuaddr __P((rpc_msg_t *, xdr_uaddr_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_modreq __P((fr_info_t *, nat_t *, rpc_msg_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_decoderep __P((fr_info_t *, nat_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rpcb_session_t *, rpc_msg_t *, rpcb_xact_t **));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic rpcb_xact_t * ippr_rpcb_lookup __P((rpcb_session_t *, u_32_t));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void ippr_rpcb_deref __P((rpcb_session_t *, rpcb_xact_t *));
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenkstatic int ippr_rpcb_getproto __P((rpc_msg_t *, xdr_proto_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_getnat __P((fr_info_t *, nat_t *, u_int, u_int));
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_modv3 __P((fr_info_t *, nat_t *, rpc_msg_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int ippr_rpcb_modv4 __P((fr_info_t *, nat_t *, rpc_msg_t *,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic void ippr_rpcb_fixlen __P((fr_info_t *, int));
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk * Global variables
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic frentry_t rpcbfr; /* Skeleton rule for reference by entities
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk this proxy creates. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenkstatic int rpcbcnt; /* Upper bound of allocated RPCB sessions. */
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk /* XXX rpcbcnt still requires locking. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Since rpc_msg contains only pointers, one should use this macro as a
dff2cc5646d4437ab9e0cb1dcb59da65462a5938jeff.schenk * handy way to get to the goods. (In case you're wondering about the name,
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * this started as BYTEREF -> BREF -> B.)
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk * Public subroutines
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* -------------------------------------------------------------------- */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Function: ippr_rpcb_init */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Returns: int - 0 == success */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Parameters: (void) */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Initialize the filter rule entry and session limiter. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* -------------------------------------------------------------------- */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk rpcbfr.fr_flags = FR_PASS|FR_QUICK|FR_KEEPSTATE;
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk MUTEX_INIT(&rpcbfr.fr_lock, "ipf Sun RPCB proxy rule lock");
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* -------------------------------------------------------------------- */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Function: ippr_rpcb_fini */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Returns: void */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Parameters: (void) */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* Destroy rpcbfr's mutex to avoid a lock leak. */
5b64d5d44892834ba97f003080f3467299b7c5c5jeff.schenk/* -------------------------------------------------------------------- */
mb_t *m;
int rv;
switch(rv)
return(rv);
mb_t *m;
diff = 0;
switch(rv)
return(diff);
/* address rewrite/modification */
int mod;
mod = 0;
if ((B(p++) != RPCB_CALL) ||
(B(p++) != RPCB_MSG_VERSION) ||
(B(p++) != RPCB_PROG))
xdr = B(p);
case RPCB_GETADDR:
case RPCB_GETADDRLIST:
return(mod);
p = *buf;
++rpcbcnt;
u_32_t *p;
u_32_t **p;
char *c, *i, *b, *pp;
*(char **)p += XDRALIGN(l);
* Expected format: a.b.c.d.e.f where [a-d] correspond to bytes of
b = uastr;
if (isdigit(*c)) {
dd = 0;
if (dd != 0)
t = ippr_rpcb_atoi(b);
t = ippr_rpcb_atoi(b);
/* Simple version of atoi(3) ripped from ip_rcmd_pxy.c. */
static u_int
char *ptr;
register char *s = ptr, c;
register u_int i = 0;
mb_t *m;
int diff;
bogo = 0;
if (diff != 0) {
return(diff);
if (B(p++) != RPCB_REPLY)
case RPCB_MSG_DENIED:
case RPCB_MSG_ACCEPTED:
case RPCB_RES_PMAP:
if (xdr == 0)
case RPCB_RES_STRING:
case RPCB_RES_LIST:
cnt = 0;
xdr = B(p++);
++cnt;
if (rv != 0)
static rpcb_xact_t *
return(NULL);
return(rx);
--rpcbcnt;
u_32_t **p;
int nflags;
* XXX nat_delete is private to ip_nat.c. Should
mb_t *m;
int diff;
if (diff != 0)
return(diff);
mb_t *m;
diff = 0;
if (diff != 0) {
if (diff != 0)
return(diff);
int len;
#undef B