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.