Пример #1
0
/* Decrement the IP TTL field in each packet on the send queue. If
 * a TTL goes to zero, discard the packet.
 */
void
ttldec(
struct iface *ifp
){
	struct mbuf *bp,*bpprev,*bpnext;
	struct qhdr qhdr;
	struct ip ip;

	bpprev = NULL;
	for(bp = ifp->outq; bp != NULL;bpprev = bp,bp = bpnext){
		bpnext = bp->anext;
		pullup(&bp,&qhdr,sizeof(qhdr));
		ntohip(&ip,&bp);
		if(--ip.ttl == 0){
			/* Drop packet */
			icmp_output(&ip,bp,ICMP_TIME_EXCEED,0,NULL);
			if(bpprev == NULL)	/* First on queue */
				ifp->outq = bpnext;
			else
				bpprev->anext = bpnext;
			free_p(&bp);
			bp = bpprev; 
			continue;
		}
		/* Put IP and queue headers back, restore to queue */
		htonip(&ip,&bp,0);
		pushdown(&bp,&qhdr,sizeof(qhdr));
		if(bpprev == NULL)	/* First on queue */
			ifp->outq = bp;
		else
			bpprev->anext = bp;
		bp->anext = bpnext;
	}
}
Пример #2
0
void
ip_dump(
FILE *fp,
struct mbuf **bpp,
int check
){
	struct ip ip;
	uint16 ip_len;
	uint16 csum;

	if(bpp == NULL || *bpp == NULL)
		return;	

	/* Sneak peek at IP header and find length */
	ip_len = ((*bpp)->data[0] & 0xf) << 2;
	if(ip_len < IPLEN){
		fprintf(fp,"IP: bad header\n");
		return;
	}
	if(check && cksum(NULL,*bpp,ip_len) != 0)
		fprintf(fp,"IP: CHECKSUM ERROR (%u)",csum);

	ntohip(&ip,bpp);	/* Can't fail, we've already checked ihl */
	ipldump(fp,&ip,bpp,check);
}
Пример #3
0
void
keep_things_going()
{
	void check_time(), ip_recv();
	struct interface *ifp;
	struct mbuf *bp;

	/* Service the loopback queue */
	if((bp = dequeue(&loopq)) != NULLBUF){
		struct ip ip;
#ifdef	TRACE
		dump(&loopback,IF_TRACE_IN,TRACE_IP,bp);		
#endif
		/* Extract IP header */
		ntohip(&ip,&bp);
		ip_recv(&ip,bp,0);
	}
	/* Service the interfaces */
#ifdef	SYS5
	do {
	io_active = 0;
#endif
	for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next){
		if(ifp->recv != NULLVFP)
			(*ifp->recv)(ifp);
	}
#ifdef	SYS5
	} while(io_active);
#endif

#ifdef	XOBBS
	/* service the W2XO PBBS code */
	axchk();
#endif



	/* Service the clock if it has ticked */
	check_time();

#ifdef	MSDOS
	/* Tell DoubleDos to let the other task run for awhile.
	 * If DoubleDos isn't active, this is a no-op
	 */
#ifndef PLUS
	giveup();
#endif
#else
	/* Wait until interrupt, then do it all over again */
	eihalt();
#endif
}
Пример #4
0
/* Execute random quench algorithm on an interface's output queue */
void
rquench(
struct iface *ifp,
int drop
){
	struct mbuf *bp,*bplast;
	int i;
	struct qhdr qhdr;
	struct ip ip;
	struct mbuf *bpdup;

	if((i = len_q(ifp->outq)) == 0)
		return;	/* Queue is empty */

	i = urandom(i);	/* Select a victim */

	/* Search for i-th message on queue */
	bplast = NULL;
	for(bp = ifp->outq;bp != NULL && i>0;i--,bplast=bp,bp=bp->anext)
		;
	if(bp == NULL)
		return;	/* "Can't happen" */

	/* Send a source quench */
	dup_p(&bpdup,bp,0,len_p(bp));
	pullup(&bpdup,&qhdr,sizeof(qhdr));
	ntohip(&ip,&bpdup);
	icmp_output(&ip,bpdup,ICMP_QUENCH,0,NULL);
	free_p(&bpdup);
	if(!drop)
		return;	/* All done */

	/* Drop the packet */
	if(bplast != NULL)
		bplast->anext = bp->anext;
	else
		ifp->outq = bp->anext;	/* First on list */
	free_p(&bp);
}
Пример #5
0
/* Process an incoming ICMP packet */
void
icmp_input(
struct iface *iface,    /* Incoming interface (ignored) */
struct ip *ip,          /* Pointer to decoded IP header structure */
struct mbuf **bpp,      /* Pointer to ICMP message */
int rxbroadcast,
int32 said
){
	struct icmplink *ipp;
	struct icmp icmp;       /* ICMP header */
	struct ip oip;          /* Offending datagram header */
	uint type;              /* Type of ICMP message */
	uint length;

	icmpInMsgs++;
	if(rxbroadcast){
		/* Broadcast ICMP packets are to be IGNORED !! */
		icmpInErrors++;
		free_p(bpp);
		return;
	}
	length = ip->length - IPLEN - ip->optlen;
	if(cksum(NULL,*bpp,length) != 0){
		/* Bad ICMP checksum; discard */
		icmpInErrors++;
		free_p(bpp);
		return;
	}
	ntohicmp(&icmp,bpp);

	/* Process the message. Some messages are passed up to the protocol
	 * module for handling, others are handled here.
	 */
	type = icmp.type;

	switch(type){
	case ICMP_TIME_EXCEED:  /* Time-to-live Exceeded */
	case ICMP_DEST_UNREACH: /* Destination Unreachable */
	case ICMP_QUENCH:       /* Source Quench */
	case ICMP_IPSP:         /* Bad security packet */
		switch(type){
		case ICMP_TIME_EXCEED:  /* Time-to-live Exceeded */
			icmpInTimeExcds++;
			break;
		case ICMP_DEST_UNREACH: /* Destination Unreachable */
			icmpInDestUnreachs++;
			break;
		case ICMP_QUENCH:       /* Source Quench */
			icmpInSrcQuenchs++;
			break;
		}
		ntohip(&oip,bpp);       /* Extract offending IP header */
		if(Icmp_trace){
			printf("ICMP from %s:",inet_ntoa(ip->source));
			printf(" dest %s %s",inet_ntoa(oip.dest),
			 smsg(Icmptypes,ICMP_TYPES,type));
			switch(type){
			case ICMP_TIME_EXCEED:
				printf(" %s\n",
				 smsg(Exceed,NEXCEED,icmp.code));
				break;
			case ICMP_DEST_UNREACH:
				printf(" %s\n",
				 smsg(Unreach,NUNREACH,icmp.code));
				break;
			case ICMP_IPSP:
				printf(" %s\n",smsg(Said_icmp,NIPSP,icmp.code));
				break;
			default:
				printf(" %u\n",icmp.code);
				break;
			}
		}
		for(ipp = Icmplink;ipp->funct != NULL;ipp++)
			if(ipp->proto == oip.protocol)
				break;
		if(ipp->funct != NULL){
			(*ipp->funct)(ip->source,oip.source,oip.dest,icmp.type,
			 icmp.code,bpp);
		}
		break;
	case ICMP_ECHO:         /* Echo Request */
		/* Change type to ECHO_REPLY, recompute checksum,
		 * and return datagram.
		 */
		icmpInEchos++;
		icmp.type = ICMP_ECHO_REPLY;
		htonicmp(&icmp,bpp);
		icmpOutEchoReps++;
		{
		int32 tmp = ip->source;
		ip->source = ip->dest;
		ip->dest = tmp;
		ip->ttl = (char) ipDefaultTTL;
		htonip(ip,bpp,IP_CS_NEW);
		icmpOutMsgs++;
		net_route(NULL,bpp);
		}
		return;
	case ICMP_REDIRECT:     /* Redirect */
		icmpInRedirects++;
		ntohip(&oip,bpp);       /* Extract offending IP header */
		if(Icmp_trace){
			printf("ICMP from %s:",inet_ntoa(ip->source));
			printf(" dest %s %s",inet_ntoa(oip.dest),
			 smsg(Icmptypes,ICMP_TYPES,type));
			printf(" new gateway %s\n",inet_ntoa(icmp.args.address));
		}
		break;
	case ICMP_PARAM_PROB:   /* Parameter Problem */
		icmpInParmProbs++;
		break;
	case ICMP_ECHO_REPLY:   /* Echo Reply */
		icmpInEchoReps++;
		echo_proc(ip->source,ip->dest,&icmp,bpp);
		break;
	case ICMP_TIMESTAMP:    /* Timestamp */
		icmpInTimestamps++;
		{
		int32 tmp;
		uint8 buf[12];
		struct timeval tv;
		if(pullup(bpp,buf,sizeof(buf)) != sizeof(buf)){
			free_p(bpp);
			return;
		}
		gettimeofday(&tv,0);
		tmp = (tv.tv_sec % 86400) * 1000 + tv.tv_usec / 1000;
		put32(&buf[4],tmp);     /* Receive Timestamp */
		put32(&buf[8],tmp);     /* Transmit Timestamp */
		pushdown(bpp,buf,sizeof(buf));
		icmp.type = ICMP_TIME_REPLY;
		htonicmp(&icmp,bpp);
		icmpOutTimestampReps++;
		tmp = ip->source;
		ip->source = ip->dest;
		ip->dest = tmp;
		ip->ttl = (char) ipDefaultTTL;
		htonip(ip,bpp,IP_CS_NEW);
		icmpOutMsgs++;
		net_route(NULL,bpp);
		return;
		}
	case ICMP_TIME_REPLY:   /* Timestamp Reply */
		icmpInTimestampReps++;
		break;
	case ICMP_INFO_RQST:    /* Information Request */
		break;
	case ICMP_INFO_REPLY:   /* Information Reply */
		break;
	}
	free_p(bpp);
}