V9/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 "inet.h"
#include "uarp.h"
#if NINET
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/stream.h"
#include "../h/ioctl.h"
#include "../h/buf.h"
#include "../h/conf.h"
#include "../h/inet/in.h"
#include "../h/inet/ip_var.h"
#include "../h/ttyld.h"

int	nodev(), ipdopen(), ipdclose(), ipdput(), ipdosrv();
static	struct qinit ipdrinit = { nodev, NULL, ipdopen, ipdclose, 0, 0 };
	struct qinit ipdwinit = { ipdput, ipdosrv, ipdopen, ipdclose,
				  IP_BODY_LIMIT, 129 };
struct	streamtab ipdinfo = { &ipdrinit, &ipdwinit };

struct queue *ipdstate[256];
int ipprintfs;

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;
{
	int dev;

	dev = (int)q->ptr;
	ipdstate[dev] = 0;
}

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

	switch(bp->type){
	case M_IOCTL:
		sp = (union stmsg *)(bp->rptr);
		bp->type = M_IOCACK;
		switch(sp->ioc0.com){
		case IPIOROUTE:
			bcopy(sp->iocx.xxx, &foo, sizeof(struct foo));
			if(ip_doroute(foo.dst, foo.gate))
				bp->type = M_IOCNAK;
			break;
		case IPIOGETIFS:
			i = *(int *)(sp->iocx.xxx);
			if(i>=NINET) {
				bp->type = M_IOCNAK;
				break;
			}
			bp1 = allocb(64);
			if (bp1 == 0) {
				bp->type = M_IOCNAK;
				break;
			}
			freeb(bp);
			bp = bp1;
			bp->type = M_IOCACK;
			sp = (struct stmsg *)(bp->rptr);
			bp->wptr = (u_char *)sp->iocx.xxx;
			*(struct ipif *)(bp->wptr) = ipif[i];
			bp->wptr += sizeof(struct ipif);
			break;
		default:
			bp->type = M_IOCNAK;
			break;
		}
		qreply(q, bp);
		return;
	case M_DATA:
		putq(q, bp);
		break;
	case M_DELIM:
		putq(q, bp);
		qenable(q);
		break;
	default:
		freeb(bp);
		break;
	}
}

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

	q = ipdstate[dev];
	if(q){
		if(q->next->flag&QFULL){
			bp_free(bp);
			if(ipprintfs)
				printf("ipdrint: QFULL\n");
			ipstat.ips_qfull++;
			return;
		}
		while(bp){
			bp1 = bp->next;
			(*q->next->qinfo->putp)(q->next, bp);
			bp = bp1;
		}
		bp = allocb(0);
		if(bp){
			bp->type = M_DELIM;
			(*q->next->qinfo->putp)(q->next, bp);
		} else {
			printf("ipdrint: no allocb for DELIM\n");
		}
	} else {
		bp_free(bp);
	}
}

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

	head = tail = 0;
	while(bp = getq(q)){
		bp->next = 0;
		if(bp->type != M_DATA){
			freeb(bp);
			if(head)
				ip_output(head, 0, 0);
			else
				printf("osrv, DELIM & no DATA\n");
			head = tail = 0;
		} else if(head == 0){
			head = tail = bp;
		} else {
			tail->next = bp;
			tail = bp;
		}
	}
	if (head)
		bp_putback(q, head);
}
#endif