Esempio n. 1
0
/* Check remote password */
static int
chkrpass(
    struct mbuf *bp)
{
    char *lbuf;
    uint16 len;
    int rval = 0;

    len = len_p(bp);
    if(Rempass == 0 || *Rempass == 0 || strlen(Rempass) != len)
        return rval;
    lbuf = (char *) mallocw(len);
    pullup(&bp,lbuf,len);
    if(strncmp(Rempass,lbuf,len) == 0)
        rval = 1;
    free(lbuf);
    return rval;
}
Esempio n. 2
0
/* Dump a UDP header */
void
udp_dump(
FILE *fp,
struct mbuf **bpp,
int32 source,int32 dest,
int check)              /* If 0, bypass checksum verify */
{
	struct udp udp;
	struct pseudo_header ph;
	uint csum;

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

	fprintf(fp,"UDP:");

	/* Compute checksum */
	ph.source = source;
	ph.dest = dest;
	ph.protocol = UDP_PTCL;
	ph.length = len_p(*bpp);
	if((csum = cksum(&ph,*bpp,ph.length)) == 0)
		check = 0;      /* No checksum error */

	ntohudp(&udp,bpp);

	fprintf(fp," len %u",udp.length);
	fprintf(fp," %u->%u",udp.source,udp.dest);
	if(udp.length > UDPHDR)
		fprintf(fp," Data %u",udp.length - UDPHDR);
	if(udp.checksum == 0)
		check = 0;
	if(check)
		fprintf(fp," CHECKSUM ERROR (%u)",csum);

	putc('\n',fp);

	switch(udp.dest){
	case IPPORT_RIP:
		rip_dump(fp,bpp);
	}

}
Esempio n. 3
0
/* Encode a packet in SLIP format */
static
struct mbuf *
slip_encode(struct mbuf **bpp)
{
	struct mbuf *lbp;       /* Mbuf containing line-ready packet */
	register uint8 *cp;
	int c;

	/* Allocate output mbuf that's twice as long as the packet.
	 * This is a worst-case guess (consider a packet full of FR_ENDs!)
	 */
	lbp = alloc_mbuf(2*len_p(*bpp) + 2);
	if(lbp == NULL){
		/* No space; drop */
		free_p(bpp);
		return NULL;
	}
	cp = lbp->data;

	/* Flush out any line garbage */
	*cp++ = FR_END;

	/* Copy input to output, escaping special characters */
	while((c = PULLCHAR(bpp)) != -1){
		switch(c){
		case FR_ESC:
			*cp++ = FR_ESC;
			*cp++ = T_FR_ESC;
			break;
		case FR_END:
			*cp++ = FR_ESC;
			*cp++ = T_FR_END;
			break;
		default:
			*cp++ = c;
		}
	}
	*cp++ = FR_END;
	lbp->cnt = cp - lbp->data;
	return lbp;
}
Esempio n. 4
0
/* Dump packet bytes, no interpretation */
void
raw_dump(
struct iface *ifp,
int direction,
struct mbuf *bp)
{
	struct mbuf *tbp;
	FILE *fp;

	if((fp = ifp->trfp) == NULL)
		return;
	fprintf(fp,"\n******* raw packet dump (%s)\n",
	 ((direction & IF_TRACE_OUT) ? "send" : "recv"));
	dup_p(&tbp,bp,0,len_p(bp));
	if(tbp != NULL)
		hex_dump(fp,&tbp);
	else
		fprintf(fp,nospace);
	fprintf(fp,"*******\n");
	free_p(&tbp);
}
Esempio n. 5
0
File: ip.c Progetto: zidier215/tcpip
/* 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);
}
Esempio n. 6
0
/* Process remote command */
static void
uremote(
    struct iface *iface,
    struct udp_cb *up,
    int cnt)
{

    struct mbuf *bp;
    struct socket fsock;
    char command;
    int32 addr;

    recv_udp(up,&fsock,&bp);
    command = PULLCHAR(&bp);
    switch(command & 0xff) {
    case SYS__EXIT:
        if(chkrpass(bp) == 0) {
            logmsg(NULL,"%s - Remote exit PASSWORD FAIL",
                   pinet_udp(&fsock));
        } else {
            logmsg(NULL,"%s - Remote exit PASSWORD OK",
                   pinet_udp(&fsock));
            main_exit = 1;
        }
        break;
    case KICK__ME:
        if(len_p(bp) >= sizeof(int32))
            addr = pull32(&bp);
        else
            addr = fsock.address;
        kick(addr);
        /*** smtptick((void *)addr); ***/
        break;
    }
    free_p(&bp);
}
Esempio n. 7
0
File: ip.c Progetto: zidier215/tcpip
/* Send an IP datagram. Modeled after the example interface on p 32 of
 * RFC 791
 */
int
ip_send(
int32 source,			/* source address */
int32 dest,			/* Destination address */
char protocol,			/* Protocol */
char tos,			/* Type of service */
char ttl,			/* Time-to-live */
struct mbuf **bpp,		/* Data portion of datagram */
uint16 length,			/* Optional length of data portion */
uint16 id,			/* Optional identification */
char df				/* Don't-fragment flag */
){
	struct ip ip;			/* IP header */

	ipOutRequests++;

	if(bpp == NULL)
		return -1;
	if(source == INADDR_ANY)
		source = locaddr(dest);
	if(length == 0 && *bpp != NULL)
		length = len_p(*bpp);
	if(id == 0)
		id = Id_cntr++;
	if(ttl == 0)
		ttl = ipDefaultTTL;

	/* Fill in IP header */
	ip.version = IPVERSION;
	ip.tos = tos;
	ip.length = IPLEN + length;
	ip.id = id;
	ip.offset = 0;
	ip.flags.mf = 0;
	ip.flags.df = df;
	ip.flags.congest = 0;
	ip.ttl = ttl;
	ip.protocol = protocol;
	ip.source = source;
	ip.dest = dest;
	ip.optlen = 0;
	if(Ip_trace)
		dumpip(NULL,&ip,*bpp,0);

	htonip(&ip,bpp,IP_CS_NEW);
	if(ismyaddr(ip.dest)){
		/* Pretend it has been sent by the loopback interface before
		 * it appears in the receive queue
		 */
#ifdef	SIM
		net_sim(bpp);
#else
		net_route(&Loopback,bpp);
#endif
		Loopback.ipsndcnt++;
		Loopback.rawsndcnt++;
		Loopback.lastsent = secclock();
	} else
		net_route(NULL,bpp);
	return 0;
}
Esempio n. 8
0
File: ip.c Progetto: zidier215/tcpip
/* Reassemble incoming IP fragments and dispatch completed datagrams
 * to the proper transport module
 */
void
ip_recv(
struct iface *iface,	/* Incoming interface */
struct ip *ip,		/* Extracted IP header */
struct mbuf **bpp,	/* Data portion */
int rxbroadcast,	/* True if received on subnet broadcast address */
int32 spi		/* Security association, if any */
){
	/* Function to call with completed datagram */
	register struct raw_ip *rp;
	struct mbuf *bp1;
	int rxcnt = 0;
	register struct iplink *ipp;

	/* If we have a complete packet, call the next layer
	 * to handle the result. Note that fraghandle passes back
	 * a length field that does NOT include the IP header
	 */
	if(bpp == NULL || fraghandle(ip,bpp) == -1)
		return;		/* Not done yet */

	/* Trim data segment if necessary. */
	trim_mbuf(bpp,ip->length - (IPLEN + ip->optlen));

	ipInDelivers++;
	if(Ip_trace)
		dumpip(iface,ip,*bpp,spi);

	for(rp = Raw_ip;rp != NULL;rp = rp->next){
		if(rp->protocol != ip->protocol)
			continue;
		rxcnt++;
		/* Duplicate the data portion, and put the header back on */
		dup_p(&bp1,*bpp,0,len_p(*bpp));
		if(bp1 != NULL){
			htonip(ip,&bp1,IP_CS_OLD);
			enqueue(&rp->rcvq,&bp1);
			if(rp->r_upcall != NULL)
				(*rp->r_upcall)(rp);
		} else {
			free_p(&bp1);
		}
	}
	/* Look it up in the transport protocol table */
	for(ipp = Iplink;ipp->funct != NULL;ipp++){
		if(ipp->proto == ip->protocol)
			break;
	}
	if(ipp->funct != NULL){
		/* Found, call transport protocol */
		(*ipp->funct)(iface,ip,bpp,rxbroadcast,spi);
	} else {
		/* Not found */
		if(rxcnt == 0){
			/* Send an ICMP Protocol Unknown response... */
			ipInUnknownProtos++;
			/* ...unless it's a broadcast */
			if(!rxbroadcast){
				icmp_output(ip,*bpp,ICMP_DEST_UNREACH,
				 ICMP_PROT_UNREACH,NULL);
			}
		}
		free_p(bpp);
	}
}
Esempio n. 9
0
void
dump(
struct iface *ifp,
int direction,
struct mbuf *bp
){
	struct mbuf *tbp;
	uint size;
	time_t timer;
	char *cp;
	struct iftype *ift;
	FILE *fp;

	if(ifp == NULL || (ifp->trace & direction) == 0
	 || (fp = ifp->trfp) == NULL)
		return; /* Nothing to trace */

	ift = ifp->iftype;
	switch(direction){
	case IF_TRACE_IN:
		if((ifp->trace & IF_TRACE_NOBC)
		 && ift != NULL
		 && (ift->addrtest != NULL)
		 && (*ift->addrtest)(ifp,bp) == 0)
			return;         /* broadcasts are suppressed */
		timer = (time_t) secclock();
		cp = ctime(&timer);
		cp[24] = '\0';
		fprintf(fp,"\n%s - %s recv:\n",cp,ifp->name);
		break;
	case IF_TRACE_OUT:
		timer = (time_t) secclock();
		cp = ctime(&timer);
		cp[24] = '\0';
		fprintf(fp,"\n%s - %s sent:\n",cp,ifp->name);
		break;
	}
	if(bp == NULL || (size = len_p(bp)) == 0){
		fprintf(fp,"empty packet!!\n");
		return;
	}
	dup_p(&tbp,bp,0,size);
	if(tbp == NULL){
		fprintf(fp,nospace);
		return;
	}
	if(ift != NULL && ift->trace != NULL)
		(*ift->trace)(fp,&tbp,1);
	if(ifp->trace & IF_TRACE_ASCII){
		/* Dump only data portion of packet in ascii */
		ascii_dump(fp,&tbp);
	} else if(ifp->trace & IF_TRACE_HEX){
		/* Dump entire packet in hex/ascii */
		free_p(&tbp);
		dup_p(&tbp,bp,0,len_p(bp));
		if(tbp != NULL)
			hex_dump(fp,&tbp);
		else
			fprintf(fp,nospace);
	}
	free_p(&tbp);
}
Esempio n. 10
0
/* Return an ICMP response to the sender of a datagram.
 * Unlike most routines, the callER frees the mbuf.
 */
int
icmp_output(
struct ip *ip,          /* Header of offending datagram */
struct mbuf *data,      /* Data portion of datagram - FREED BY CALLER */
uint8 type,             /* Codes to send */
uint8 code,
union icmp_args *args
){
	struct mbuf *bp;
	struct icmp icmp;       /* ICMP protocol header */
	uint dlen;              /* Length of data portion of offending pkt */
	uint length;            /* Total length of reply */

	if(ip == NULL)
		return -1;
	if(ip->protocol == ICMP_PTCL){
		/* Peek at type field of ICMP header to see if it's safe to
		 * return an ICMP message
		 */
		switch(data->data[0]){
		case ICMP_ECHO_REPLY:
		case ICMP_ECHO:
		case ICMP_TIMESTAMP:
		case ICMP_TIME_REPLY:
		case ICMP_INFO_RQST:
		case ICMP_INFO_REPLY:
			break;  /* These are all safe */
		default:
			/* Never send an ICMP error message about another
			 * ICMP error message!
			 */
			return -1;
		}
	}
	/* Compute amount of original datagram to return.
	 * We return the original IP header, and up to 8 bytes past that.
	 */
	dlen = min(8,len_p(data));
	length = dlen + ICMPLEN + IPLEN + ip->optlen;
	/* Take excerpt from data portion */
	if(data != NULL && dup_p(&bp,data,0,dlen) == 0)
		return -1;      /* The caller will free data */

	/* Recreate and tack on offending IP header */
	htonip(ip,&bp,IP_CS_NEW);
	icmp.type = type;
	icmp.code = code;
	icmp.args.unused = 0;
	switch(icmp.type){
	case ICMP_PARAM_PROB:
		icmpOutParmProbs++;
		icmp.args.pointer = args->pointer;
		break;
	case ICMP_REDIRECT:
		icmpOutRedirects++;
		icmp.args.address = args->address;
		break;
	case ICMP_ECHO:
		icmpOutEchos++;
		break;
	case ICMP_ECHO_REPLY:
		icmpOutEchoReps++;
		break;
	case ICMP_INFO_RQST:
		break;
	case ICMP_INFO_REPLY:
		break;
	case ICMP_TIMESTAMP:
		icmpOutTimestamps++;
		break;
	case ICMP_TIME_REPLY:
		icmpOutTimestampReps++;
		icmp.args.echo.id = args->echo.id;
		icmp.args.echo.seq = args->echo.seq;
		break;
	case ICMP_ADDR_MASK:
		icmpOutAddrMasks++;
		break;
	case ICMP_ADDR_MASK_REPLY:
		icmpOutAddrMaskReps++;
		break;
	case ICMP_DEST_UNREACH:
		if(icmp.code == ICMP_FRAG_NEEDED)
			icmp.args.mtu = args->mtu;
		icmpOutDestUnreachs++;
		break;
	case ICMP_TIME_EXCEED:
		icmpOutTimeExcds++;
		break;
	case ICMP_QUENCH:
		icmpOutSrcQuenchs++;
		break;
	}
	icmpOutMsgs++;
	/* Now stick on the ICMP header */
	htonicmp(&icmp,&bp);
	return ip_send(INADDR_ANY,ip->source,ICMP_PTCL,ip->tos,0,&bp,length,0,0);
}
Esempio n. 11
0
/* Pull TCP header off mbuf */
int
ntohtcp(
struct tcp *tcph,
struct mbuf **bpp
){
	int hdrlen,i,optlen,kind;
	register int flags;
	uint8 hdrbuf[TCPLEN],*cp;
	uint8 options[TCP_MAXOPT];

	memset(tcph,0,sizeof(struct tcp));
	i = pullup(bpp,hdrbuf,TCPLEN);
	/* Note that the results will be garbage if the header is too short.
	 * We don't check for this because returned ICMP messages will be
	 * truncated, and we at least want to get the port numbers.
	 */
	tcph->source = get16(&hdrbuf[0]);
	tcph->dest = get16(&hdrbuf[2]);
	tcph->seq = get32(&hdrbuf[4]);
	tcph->ack = get32(&hdrbuf[8]);
	hdrlen = (hdrbuf[12] & 0xf0) >> 2;
	flags = hdrbuf[13];
	tcph->flags.congest = (flags & 64) ? 1 : 0;
	tcph->flags.urg = (flags & 32) ? 1 : 0;
	tcph->flags.ack = (flags & 16) ? 1 : 0;
	tcph->flags.psh = (flags & 8) ? 1 : 0;
	tcph->flags.rst = (flags & 4) ? 1 : 0;
	tcph->flags.syn = (flags & 2) ? 1 : 0;
	tcph->flags.fin = (flags & 1) ? 1 : 0;
	tcph->wnd = get16(&hdrbuf[14]);
	tcph->checksum = get16(&hdrbuf[16]);
	tcph->up = get16(&hdrbuf[18]);
	optlen = hdrlen - TCPLEN;

	/* Check for option field */
	if(i < TCPLEN || hdrlen < TCPLEN)
		return -1;	/* Header smaller than legal minimum */
	if(optlen == 0)
		return (int)hdrlen;	/* No options, all done */

	if(optlen > len_p(*bpp)){
		/* Remainder too short for options length specified */
		return -1;
	}
	pullup(bpp,options,optlen);	/* "Can't fail" */
	/* Process options */
	for(cp=options,i=optlen; i > 0;){
		kind = *cp++;
		i--;
		/* Process single-byte options */
		switch(kind){
		case EOL_KIND:
			return (int)hdrlen;	/* End of options list */
		case NOOP_KIND:
			continue;	/* Go look for next option */
		}
		/* All other options have a length field */
		optlen = *cp++;

		/* Process valid multi-byte options */
		switch(kind){
		case MSS_KIND:
			if(optlen == MSS_LENGTH){
				tcph->mss = get16(cp);
				tcph->flags.mss = 1;
			}
			break;
		case WSCALE_KIND:
			if(optlen == WSCALE_LENGTH){
				tcph->wsopt = *cp;
				tcph->flags.wscale = 1;
			}
			break;
		case TSTAMP_KIND:
			if(optlen == TSTAMP_LENGTH){
				tcph->tsval = get32(cp);
				tcph->tsecr = get32(cp+4);
				tcph->flags.tstamp = 1;
			}
			break;
		}
		optlen = max(2,optlen);	/* Enforce legal minimum */
		i -= optlen;
		cp += optlen - 2;
	}
	return (int)hdrlen;
}
Esempio n. 12
0
/* Convert TCP header in host format into mbuf ready for transmission,
 * link in data (if any).
 *
 * If checksum field is zero, recompute it, otherwise take the value
 * in the host header.
 */
void
htontcp(
struct tcp *tcph,
struct mbuf **bpp,	/* Data in, packet out */
int32 ipsrc,		/* For computing header checksum */
int32 ipdest
){
	uint16 hdrlen;
	register uint8 *cp;

	if(bpp == NULL)
		return;
	hdrlen = TCPLEN;
	if(tcph->flags.mss)
		hdrlen += MSS_LENGTH;
	if(tcph->flags.tstamp)
		hdrlen += TSTAMP_LENGTH;
	if(tcph->flags.wscale)
		hdrlen += WSCALE_LENGTH;

	hdrlen = (hdrlen + 3) & 0xfc;	/* Round up to multiple of 4 */
	pushdown(bpp,NULL,hdrlen);
	cp = (*bpp)->data;
	memset(cp,0,hdrlen);
	cp = put16(cp,tcph->source);
	cp = put16(cp,tcph->dest);
	cp = put32(cp,tcph->seq);
	cp = put32(cp,tcph->ack);
	*cp++ = hdrlen << 2;	/* Offset field */
	*cp = 0;
	if(tcph->flags.congest)
		*cp |= 64;
	if(tcph->flags.urg)
		*cp |= 32;
	if(tcph->flags.ack)
		*cp |= 16;
	if(tcph->flags.psh)
		*cp |= 8;
	if(tcph->flags.rst)
		*cp |= 4;
	if(tcph->flags.syn)
		*cp |= 2;
	if(tcph->flags.fin)
		*cp |= 1;
	cp++;
	cp = put16(cp,tcph->wnd);
	cp = put16(cp,tcph->checksum);
	cp = put16(cp,tcph->up);

	/* Write options, if any */
	if(tcph->flags.mss){
		*cp++ = MSS_KIND;
		*cp++ = MSS_LENGTH;
		cp = put16(cp,tcph->mss);
	}
	if(tcph->flags.tstamp){
		*cp++ = TSTAMP_KIND;
		*cp++ = TSTAMP_LENGTH;
		cp = put32(cp,tcph->tsval);
		cp = put32(cp,tcph->tsecr);
	}
	if(tcph->flags.wscale){
		*cp++ = WSCALE_KIND;
		*cp++ = WSCALE_LENGTH;
		*cp++ = tcph->wsopt;
	}
	if(tcph->checksum == 0){
		/* Recompute header checksum */
		struct pseudo_header ph;

		ph.source = ipsrc;
		ph.dest = ipdest;
		ph.protocol = TCP_PTCL;
		ph.length = len_p(*bpp);
		put16(&(*bpp)->data[16],cksum(&ph,*bpp,ph.length));
	}
}