ftp.nice.ch/pub/next/unix/communication/ps_if.NIHS.bs.tar.gz#/ps_if/if_ps.c

This is if_ps.c in view mode; [Download] [Up]

#include <sys/param.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/buf.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/errno.h>
#include <sys/syslog.h>
#include <sys/file.h>
#include <sys/uio.h>
#include <sys/conf.h>

#include <kernserv/prototypes.h>
#include <kernserv/machine/spl.h>
#include <kernserv/kern_server_types.h>
#include <kernserv/kalloc.h>

#include <net/if.h>
#include <net/netif.h>
#include <net/netisr.h>
#include <net/route.h>

#ifdef INET
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/in_var.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#endif

#include "if_ps.h"

netif_t	loopback;

#if	0
int	printf(char *fmt,...);
int	suser(void);
#endif
kern_server_t instance;
#define PSDEBUG	if (psdebug) printf
int	psdebug = 0;

int	psoutput(netif_t ifp,netbuf_t nb,void *address);
netbuf_t psgetbuf(netif_t);
int	pscontrol(netif_t, const char *, void *);

static inline int
nbq_full(struct nb_queue* nbq)
{
    if (nbq->head == 0)
	    return nbq->tail == QUEUE_SIZE - 1;
    else
	    return nbq->head - 1 == nbq->tail;
}

static inline int
nbq_empty(struct nb_queue* nbq)
{
    return nbq->head == nbq->tail;
}

static inline netbuf_t
nbq_dequeue(struct nb_queue* nbq)
{
    int s = splimp();
    if (nbq_empty(nbq))
    {
	return NULL;
    }
    else
    {
	netbuf_t ret = nbq->queue[nbq->head];
	if (nbq->head == QUEUE_SIZE - 1)
		nbq->head = 0;
	else
		nbq->head++;
	return ret;
    }
    splx(s);
}

static inline int
nbq_enqueue(struct nb_queue* nbq, netbuf_t nb)
{
    int s = splimp();
    if (nbq_full(nbq))
    {
	return -1;
    }
    else
    {
	nbq->queue[nbq->tail] = nb;
	if (nbq->tail == QUEUE_SIZE - 1)
		nbq->tail = 0;
	else
		nbq->tail++;
    }
    splx(s);
	return 0;
}


extern	int	inet_queueq(netif_t,netbuf_t);

int	psoutput( netif_t ifp,netbuf_t nb,void *address)
{
	int		s;
	struct	psprivate	*pspr;
	struct	nb_queue	*nbq;
	struct	sockaddr	*dst=(struct sockaddr *)address;

	pspr = (struct psprivate *)if_private(ifp);
	nbq = pspr->nbq;
	
	switch(dst->sa_family) {
	case AF_INET:
		s = splimp();
		if(nbq_enqueue(nbq,nb) < 0) {
			nb_free(nb);
			splx(s);
	        if_oerrors_set(ifp, if_oerrors(ifp) + 1);
			return ENOBUFS;
		}
	
		splx(s);
		break;
	default:
		PSDEBUG ("Unkown protocol: psoutput\n");
		nb_free(nb);
		return EAFNOSUPPORT;
	}
	
	s = splimp();
	if ((nb = nbq_dequeue(nbq)) == NULL) {
		splx(s);
		return ENOBUFS;
	}
	splx(s);

    if_opackets_set(ifp, if_opackets(ifp) + 1);

	inet_queue( ifp, nb);
	return 0;
}

/*
 * get buffer - return newly allocated netbuffer
 */
netbuf_t
psgetbuf(netif_t ifp)
{
    struct ifnet* ifn = (struct ifnet*)ifp;
	int		len;
    len = MAX(ifn->if_mtu, PSMTU) + sizeof (struct ifnet *);
    return nb_alloc(len);
}

/*
 * Process an unix-ioctl request.
 */
int
psifioctl(ifp, cmd, data, flag)
    register netif_t ifp;
	int	cmd;
	caddr_t	data;
	int	flag;
{
	int		error = 0, s;
    register struct ifaddr *ifa = (struct ifaddr *)data;
    register struct ifreq *ifr = (struct ifreq *)data;

	s = splimp();
	switch(cmd) {
    case SIOCSIFFLAGS:
		if_flags_set(ifp, (if_flags(ifp) & IFF_CANTCHANGE)
					 | (ifr->ifr_flags & ~IFF_CANTCHANGE));
		
		break;
    case SIOCSIFADDR:
		if (ifa->ifa_addr.sa_family != AF_INET)
			error = EAFNOSUPPORT;
		if_flags_set( ifp, if_flags(ifp)|(IFF_UP|IFF_RUNNING));

		break;

	default:
		error = EINVAL;
	}
	splx(s);
	return (error);
}

union ifr_ifru {
	short	ifru_flags;
	short   ifru_mtu;
	u_long  ifru_asyncmap;
	int     ifru_metric;
	caddr_t ifru_data;
};


int pscontrol(ifp, cmd, data)
netif_t ifp;
const char* cmd;
void* data;
{
	if (!strcmp(cmd, "unix-ioctl")) {
		if_ioctl_t* ctl = (if_ioctl_t*)data;
		return psifioctl(ifp,
						 ctl->ioctl_command,
						 ctl->ioctl_data);
	}
    else if (!strcmp(cmd, "setaddr")) {
		struct sockaddr_in *sin = (struct sockaddr_in *)data;
		if (sin->sin_family != AF_INET)
			return EAFNOSUPPORT;
		if_flags_set(ifp, if_flags(ifp) | IFF_UP | IFF_RUNNING);
		return 0;
	}
    else if (!strcmp(cmd, "setflags")) {
		register union ifr_ifru *ifr = (union ifr_ifru *)data;
		if (!suser())
			return EPERM;
		if_flags_set(ifp, ifr->ifru_flags);
		return 0;
	}
    else {
		printf("Invalid ps control %s\n", cmd);
		return EINVAL;
	}
}

extern int ipforwarding;
extern int ipsendredirects;

void
psattach(unused)
	int unused;
{
	register int i;

	for (i = 0; i < NPS; i++) {
		struct	psprivate	*psprivate;

		psprivate = (struct psprivate *)kalloc(sizeof(*psprivate));
		ps_if[i] = if_attach(NULL,NULL, psoutput, 
					  psgetbuf, pscontrol, "ps", i, "Internet Protocol", 
					  PSMTU, IFF_LOOPBACK,
					  NETIFCLASS_VIRTUAL, psprivate);
		((struct psprivate *)if_private(ps_if[i]))->nbq = &nbq[i];
	}

	printf( "Pseudo Device for NEXTSTEP by Hideo \"Sir MaNMOS\" Morishita\n");
}

/*
 * Detach the pseudo device
 */
void
psdetach( void)
{
	int		i;
	void	*pr;
	for( i=0; i<NPS; i++) {
		pr = if_private(ps_if[i]);
		kfree(pr,sizeof(struct psprivate));
		if_detach( (netif_t)ps_if[i]);
	}
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.