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.