V9/sys/inet.old/ip_ld.c

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

/*
 * ip line discipline, to be pushed on an ethernet controller.
 * collects data till a delim, passes it to ip_input().
 */

#include "inet.h"
#include "arp.h"
#include "uarp.h"
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/stream.h"
#include "../h/ioctl.h"
#include "../h/ttyld.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/ubavar.h"
#include "../h/conf.h"
#include "../h/inet/in.h"
#include "../h/inet/ip_var.h"
#include "../h/inet/mbuf.h"
#include "../h/ethernet.h"

struct ipif ipif[NINET];
int Ninet = NINET;		/* let netstat find the number of interfaces */

int	ipopen(), ipiput(), ipisrv(), ipclose();
int	iposrv();
static	struct qinit iprinit = { ipiput, ipisrv, ipopen, ipclose, IP_MSG_LIMIT, 64};
static	struct qinit ipwinit = { putq, iposrv, ipopen, ipclose, 1024, 64 };
struct streamtab ipinfo = { &iprinit, &ipwinit };

ipopen(q, dev)
register struct queue *q;
{
	static int timing;
	register i;
	register struct ipif *fp;

	if (q->ptr)
		return(1);
	if(!timing){
		timing = 1;
		ip_slowtimo();
	}
	for (i=0; ipif[i].queue!=0 && i<NINET; i++)
		;
	if (i >= NINET)
		return(0);
	fp = &ipif[i];
	fp->queue = q;	/* that's the RD q */
	fp->flags = IFF_UP;
	fp->that = fp->thishost = 0;
	fp->ipackets = fp->opackets = fp->ierrors = fp->oerrors = 0;
	fp->mtu = 1500;
	fp->arp = -1;
	fp->dev = dev;
	q->flag |= QDELIM;
	WR(q)->flag |= QDELIM;
	q->ptr = (caddr_t)fp;
	WR(q)->ptr = (caddr_t)fp;
	q->flag |= QNOENB;	/* ipiput calls qenable() */
	return(1);
}

ipclose(q)
register struct queue *q;
{
	register struct ipif *ifp;

	ifp = (struct ipif *)q->ptr;
#if NARP > 0
	if (ifp->arp >= 0)
		arp_disable(ifp->arp);
#endif
	ifp->queue = 0;
	ifp->flags = 0;
}

ipisrv(q)
register struct queue *q;
{
	register struct block *bp, *head, *tail;
	register struct ipif *ifp;

	/* there is now a whole packet waiting
	 * on this queue; strip it off and pass to ip_input().
	 * things other than data or delims are forwarded directly
	 * by ipiput().
	 */
	head = tail = (struct block *) 0;
	ifp = (struct ipif *)q->ptr;
	while(bp = getq(q)){
		if(bp->type == M_DELIM){
			freeb(bp);
			if(head){
				MCHECK(head);
				if((ifp->flags & IFF_ARP)
				   && (head->wptr - head->rptr) >= sizeof(struct etherpup)){
					/* blow away ether header */
					head->rptr += sizeof(struct etherpup);
				}
				ip_input(head);
				ifp->ipackets++;
			} else {
				printf("ipisrv: no data\n");
				ifp->ierrors++;
			}
			head = tail = (struct block *) 0;
		} else if(bp->type == M_DATA){
			bp->next = (struct block *) 0;
			if(head == (struct block *) 0){
				head = bp;
			} else {
				tail->next = bp;
			}
			tail = bp;
		} else {
			printf("ipisrv: weird type %d\n", bp->type);
			(*q->next->qinfo->putp)(q->next, bp);
		}	
	}
	if(head)
		bp_putback(q, head);
}


ipiput(q, bp)
register struct queue *q;
register struct block *bp;
{
	switch(bp->type){
	case M_DATA:
		putq(q, bp);	/* putq does compression into blocks */
		break;
	case M_DELIM:
		putq(q, bp);
		qenable(q);
		break;
	default:
		(*q->next->qinfo->putp)(q->next, bp);
		break;
	}
		
}

iposrv(q)
register struct queue *q;
{
	struct x{
		unsigned int in;
		unsigned char en[6];
	} *xp;
	register union stmsg *sp;
	register struct block *bp;
	register struct ipif *ifp;
	register int *intp;

	ifp = (struct ipif *)q->ptr;
	while(bp = getq(q)){
		if(bp->type == M_IOCTL){
			sp = (union stmsg *)bp->rptr;
			switch(sp->ioc0.com){
			case IPIOARP:
#if NARP > 0
				if (ifp->arp >= 0)
					printf("IP: already arping\n");
				else {
					ifp->arp = arp_enable(ifp->dev,
							ETHERPUP_IPTYPE,
							sizeof(u_long), 1,
							&ifp->thishost);
					if (ifp->arp == -1) {
						bp->type = M_IOCNAK;
						qreply(q, bp);
						break;
					}
				}
#endif
				ifp->flags |= IFF_ARP;
				bp->type = M_IOCACK;
				bp->wptr = bp->rptr;
				qreply(q, bp);
				break;
			case IPIORESOLVE:
				xp = (struct x *)(sp->iocx.xxx);
#if NUARP > 0
				arp_install(xp->in, xp->en);
#endif
				bp->wptr = bp->rptr;
				bp->type = M_IOCACK;
				qreply(q, bp);
				break;
			case IPIOHOST:
				intp = (int *)(sp->iocx.xxx);
				ifp->that = *intp;
				ifp->flags |= IFF_HOST;
				bp->type = M_IOCACK;
				qreply(q, bp);
				ip_doroute(ifp->that, 0);
				break;
			case IPIOMTU:
				intp = (int *)(sp->iocx.xxx);
				ifp->that = *intp;
				ifp->mtu = *intp;
				bp->type = M_IOCACK;
				qreply(q, bp);
				break;
			case IPIONET:
				intp = (long *)(sp->iocx.xxx);
				ifp->that = *intp;
				ifp->mask = 0;
				ifp->flags &= (~IFF_HOST);
				bp->type = M_IOCACK;
				qreply(q, bp);
				ip_doroute(ifp->that, 0);
				break;
			case IPIOMASK:
				intp = (long *)(sp->iocx.xxx);
				ifp->mask = *intp;
				bp->type = M_IOCACK;
				qreply(q, bp);
				ip_doroute(ifp->that, 0);
				break;
			case IPIOLOCAL:
				intp = (int *)(sp->iocx.xxx);
				ifp->thishost = *intp;
				bp->type = M_IOCACK;
				qreply(q, bp);
				break;
			default:
				(*q->next->qinfo->putp)(q->next, bp);
				break;
			}
		} else {
			(*q->next->qinfo->putp)(q->next, bp);
			if(bp->type == M_DELIM)
				ifp->opackets++;
		}
	}
}

struct ipif *
ip_ifonnetof(dst)
unsigned long dst;
{
	extern ipprintfs;
	struct ipif *ifp;

	/* point-to-point links first */
	for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
		if((ifp->flags & IFF_UP) && (ifp->flags & IFF_HOST)){
			if(dst == ifp->that)
				return(ifp);
		}
	}
	/* now normal nets */
	for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
		if((ifp->flags & (IFF_UP|IFF_HOST)) == IFF_UP){
			if(in_netof(dst) == ifp->that)
				return(ifp);
		}
	}
	if(ipprintfs)
		printf("ifonnetof %x?\n", dst);
	return(0);
}

struct ipif *
ip_ifwithaddr(addr)
unsigned long addr;
{
	struct ipif *ifp;
	unsigned long net;

	net = in_netof(addr);
	for(ifp = &ipif[0]; ifp < &ipif[NINET]; ifp++){
		if(ifp->flags & IFF_UP){
			/* address of this host */
			if(addr == ifp->thishost)
				return(ifp);
			/* address of this host's network */
			if(addr == in_netof(ifp->thishost))
				return(ifp);
			/* address on a network simulated by this node */
			if(net == ifp->thishost)
				return(ifp);
		}
	}
	return(0);
}

ip_ldout(bp, dst, ifp)
register struct block *bp;
unsigned long dst;		/* host byte order */
register struct ipif *ifp;
{
#if NARP > 0 || NUARP > 0
	extern struct block *arp_resolve();
#endif
	register struct block *bp1;
	register struct queue *q;

	if(ifp->queue == 0){
		printf("ifp but no queue in ip_ldout\n");
		bp_free(bp);
		return(0);
	}
	q = WR(ifp->queue);
	if(q->next->flag & QFULL){
		bp_free(bp);
		ifp->oerrors++;
		return(1);
	}
#if NARP > 0
	if(ifp->flags & IFF_ARP){
		bp = arp_resolve(ifp->arp, bp, &dst);
		if(bp == 0)
			return(1);
	}
#endif
#if NUARP > 0
	if(ifp->flags & IFF_ARP){
		bp = arp_resolve(ifp->queue, bp, dst);
		if(bp == 0)
			return(1);
	}
#endif
	MCHECK(bp);
	while(bp){
		bp1 = bp->next;
		(*q->next->qinfo->putp)(q->next, bp);
		bp = bp1;
	}
	bp1 = allocb(0);
	if(bp1){
		bp1->type = M_DELIM;
		(*q->next->qinfo->putp)(q->next, bp1);
		ifp->opackets++;
	} else {
		printf("ip_ldout: no allocb for delim\n");
		ifp->oerrors++;
	}
	return(0);
}