4.3BSD-UWisc/src/sys/rpc/subr_kudp.c

Compare this file to the similar file:
Show the results in this format:

#ifndef lint
static char rcs_id[] =
	{"$Header: subr_kudp.c,v 1.1 86/09/05 09:17:27 tadl Exp $"};
#endif not lint
/*
 * RCS Info
 *	$Locker: tadl $
 */
/* NFSSRC @(#)subr_kudp.c	2.4 86/05/13 */
#ifndef lint
static char sccsid[] = "@(#)subr_kudp.c 1.1 86/02/03 Copyr 1984 Sun Micro";
#endif

/*
 * subr_kudp.c
 * Subroutines to do UDP/IP sendto and recvfrom in the kernel
 *
 * Copyright (C) 1984, Sun Microsystems, Inc.
 */
#include "../h/param.h"
#include "../h/socket.h"
#include "../h/socketvar.h"
#include "../h/mbuf.h"
#include "../h/errno.h"
#include "../net/if.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_pcb.h"
#include "../rpc/types.h"
#include "../rpc/xdr.h"
#include "../rpc/auth.h"
#include "../rpc/clnt.h"

struct mbuf     *mclgetx();

/*
 * General kernel udp stuff.
 * The routines below are used by both the client and the server side
 * rpc code.
 */

/*
 * Kernel recvfrom.
 * Pull address mbuf and data mbuf chain off socket receive queue.
 */
struct mbuf *
ku_recvfrom(so, from)
	register struct socket *so;
	struct sockaddr_in *from;
{
	register struct mbuf	*m;
	register struct mbuf	*m0;
	int		len = 0;

#ifdef RPCDEBUG
	rpc_debug(4, "urrecvfrom so=%X\n", so);
#endif
	sblock(&so->so_rcv);
	m = so->so_rcv.sb_mb;
	if (m == NULL) {
		printf("ku_recvfrom: sb_mb is NULL\n");
		sbunlock(&so->so_rcv);
		return (m);
	}

	*from = *mtod(m, struct sockaddr_in *);
	sbfree(&so->so_rcv, m);
	so->so_rcv.sb_mb = m->m_act;
	MFREE(m, m0);
	if (m0 == NULL) {
		printf("ku_recvfrom: no body!\n");
		sbunlock(&so->so_rcv);
		return (m0);
	}
	/*
	 * Walk down mbuf chain till m_next is NULL ( end of packet )
	 * free socket buffer space as we go
	 * The next datagram is pointed to by m_act
	 */
	m = m0;
	for (;;) {
		sbfree(&so->so_rcv, m);
		len += m->m_len;
		if (m->m_next == NULL) {
			break;
		}
		m = m->m_next;
	}
	if (len > UDPMSGSIZE) {
		printf("ku_recvfrom: len = %d\n", len);
	}

#ifdef RPCDEBUG
	rpc_debug(4, "urrecvfrom %d from %X\n", len, from->sin_addr.s_addr);
#endif
	sbunlock(&so->so_rcv);
	return (m0);
}

int Sendtries = 0;
int Sendok = 0;

/*
 * Kernel sendto.
 * Set addr and send off via UDP.
 * Use ku_fastsend if possible.
 */
int
ku_sendto_mbuf(so, m, addr)
	struct socket *so;
	struct mbuf *m;
	struct sockaddr_in *addr;
{
	register struct inpcb *inp = sotoinpcb(so);
	int error;
	int s;
        struct in_addr laddr;

#ifdef RPCDEBUG
	rpc_debug(4, "ku_sendto_mbuf %X\n", addr->sin_addr.s_addr);
#endif
	Sendtries++;
	if ((error = ku_fastsend(so, m, addr)) == 0) {
		Sendok++;
		return (0);
	}
	/*
	 *  if ku_fastsend returns -2, then we can try to send m the
	 *  slow way.  else m was freed and we return ENOBUFS.
	 */
	if (error != -2) {
#ifdef RPCDEBUG
		rpc_debug(3, "ku_sendto_mbuf: fastsend failed\n");
#endif
		return (ENOBUFS);
	}
	s = splnet();
        laddr = inp->inp_laddr;
	if (error = in_pcbsetaddr(inp, addr)) {
		printf("pcbsetaddr failed %d\n", error);
		(void) splx(s);
		m_freem(m);
		return (error);
	}
	error = udp_output(inp, m);
	in_pcbdisconnect(inp);
        inp->inp_laddr = laddr;
#ifdef RPCDEBUG
	rpc_debug(4, "ku_sendto returning %d\n", error);
#endif
	Sendok++;
	(void) splx(s);
	return (error);
}

#ifdef RPCDEBUG
int rpcdebug = 2;

/*VARARGS2*/
rpc_debug(level, str, a1, a2, a3, a4, a5, a6, a7, a8, a9)
        int level;
        char *str;
        int a1, a2, a3, a4, a5, a6, a7, a8, a9;
{

        if (level <= rpcdebug)
                printf(str, a1, a2, a3, a4, a5, a6, a7, a8, a9);
}
#endif