V10/sys/inet/ip_device.c

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

/*
 * ip device driver; each minor device is one protocol.
 * so tcp would be placed on top of ip minor device #6.
 */

#include "sys/param.h"
#include "sys/stream.h"
#include "sys/conf.h"
#include "sys/inet/in.h"
#include "sys/inet/ip_var.h"

extern	int ipcnt;		/* number of ip devices */
long	ipdopen();
int	ipdclose(), ipdput(), ipdosrv();
static	struct qinit ipdrinit = { noput, NULL, ipdopen, ipdclose, 0, 0 };
	struct qinit ipdwinit = { ipdput, ipdosrv, ipdopen, ipdclose,
				  IP_BODY_LIMIT, 129 };
struct	streamtab ipdinfo = { &ipdrinit, &ipdwinit };

struct cdevsw ipcdev = cstrinit(&ipdinfo);

struct queue *ipdstate[256];
int ipprintfs;

long
ipdopen(q, dev)
register struct queue *q;
dev_t dev;
{
	dev = minor(dev);
	if(ipdstate[dev])
		return(0);
	ipdstate[dev] = q;
	q->ptr = (caddr_t)dev;
	q->flag |= QDELIM;
	WR(q)->ptr = (caddr_t)dev;
	WR(q)->flag |= QNOENB;
	return(1);
}

ipdclose(q)
register struct queue *q;
{
	ipdstate[(int)q->ptr] = 0;
}

ipdput(q, bp)
register struct queue *q;
register struct block *bp;
{
	struct foo{
		u_long dst;
		u_long gate;
	} foo;
	int i;
	struct block *bp1;

	switch(bp->type){
	case M_DATA:
		putq(q, bp);
		if (bp->class&S_DELIM)
			qenable(q);
		return;

	case M_IOCTL:
		bp->type = M_IOCACK;
		switch(stiocom(bp)){
		case IPIOROUTE:
			bcopy(stiodata(bp), &foo, sizeof(struct foo));
			if(ip_doroute(foo.dst, foo.gate))
				bp->type = M_IOCNAK;
			break;
		case IPIOGETIFS:
			i = *(int *)(stiodata(bp));
			if(i>=ipcnt) {
				bp->type = M_IOCNAK;
				break;
			}
			bp1 = allocb(sizeof(struct ipif));
			if (bp1 == 0) {
				bp->type = M_IOCNAK;
				break;
			}
			freeb(bp);
			bp = bp1;
			bp->type = M_IOCACK;
			bp->wptr = (u_char *)stiodata(bp);
			*(struct ipif *)(bp->wptr) = ipif[i];
			bp->wptr += sizeof(struct ipif);
			break;
		default:
			bp->type = M_IOCNAK;
			break;
		}
		qreply(q, bp);
		return;

	default:
		freeb(bp);
		return;
	}
}

ipdrint(bp, dev)
register struct block *bp;
unsigned dev;
{
	register struct block *bp1;
	register struct queue *nq;

	if ((nq = ipdstate[dev]) == NULL) {
		bp_free(bp);
		return;
	}
	nq = nq->next;	/* optimization */
	if(nq->flag&QFULL){
		bp_free(bp);
		if(ipprintfs)
			printf("ipdrint: QFULL\n");
		ipstat.ips_qfull++;
		return;
	}
	while(bp){
		bp1 = bp->next;
		if (bp1==NULL)
			bp->class |= S_DELIM;
		else
			bp->class &=~ S_DELIM;
		(*nq->qinfo->putp)(nq, bp);
		bp = bp1;
	}
}

ipdosrv(q)
struct queue *q;
{
	register struct block *bp, *tail, *head;

	head = tail = NULL;
	while(bp = getq(q)){
		if (bp->type != M_DATA)
			panic("ipdosrv");
		bp->next = NULL;
		if (head == NULL)
			head = bp;
		else
			tail->next = bp;
		tail = bp;
		if (bp->class&S_DELIM) {
			ip_output(head, (struct block *)0, 0);
			head = tail = NULL;
		}
	}
	if (head)
		bp_putback(q, head);
}