Example #1
0
File: ip.c Project: zidier215/tcpip
/* 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;
	}
}
Example #2
0
File: ip.c Project: 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);
}
Example #3
0
/*===========================================================================

FUNCTION DSSICMP_WRITE()

DESCRIPTION
  Send DSM item out to ICMP (write to ICMP socket). The actual write is
  performed in icmp_output() in icmp.c This function is the ICMP
  specific dss_sendto()

DEPENDENCIES
  None. 

PARAMETERS  
  protocol_ctl_block_type pcb       -   protocol control block 
  struct sockaddr_in      *ta_ptr   -   destination socket info 
  dsm_item_type           *item_ptr -  ptr to head of dsm memory pool items 

RETURN VALUE
  Length of item written. 

SIDE EFFECTS
  None.

===========================================================================*/
extern sint15 dssicmp_write
(
  protocol_ctl_block_type pcb,                   /* protocol control block */
  struct sockaddr_in      *ta_ptr,              /* destination socket info */
  dsm_item_type           *item_ptr,/*ptr to head of dsm memory pool items */
  ps_meta_info_type *meta_info_ptr              /* ptr to meta info        */
)
{
  struct icmp_cb *  icmp_cb_ptr;
  uint32  *dest_ip_ptr;                          /* Ptr to dest IP address */
  struct scb_s *    scb_ptr;
  struct icmp       icmp_hdr;
  uint16            length;                                    
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/

  MSG_LOW("In dssicmp_write (@ %p)", dssicmp_write, 0, 0);

  /*-------------------------------------------------------------------------
    Since the meta infomation is not used, free the item
  -------------------------------------------------------------------------*/
  PS_META_INFO_FREE(&meta_info_ptr);

  /*-------------------------------------------------------------------------
    Setup the socket and ICMP control block pointers.
  ------------------------------------------------------------------------*/
  icmp_cb_ptr = pcb.icb;
  scb_ptr = icmp_cb_ptr->scb_ptr;

  /*-------------------------------------------------------------------------
    Use destination information from dsm_item chain. If not possible. 
    use the information in scb (may be stale).                        
  ------------------------------------------------------------------------*/
  if (ta_ptr != NULL) 
  {
    dest_ip_ptr = &(ta_ptr->sin_addr.s_addr);
    MSG_LOW("Using parameter ta_ptr", 0, 0, 0);
  }
  else
  {
    dest_ip_ptr = &(scb_ptr->servname.address); 
    MSG_LOW("Using the server addr in SCB", 0, 0, 0);
  }
  MSG_LOW("destination IP address: %x", *dest_ip_ptr, 0, 0);

  /*-------------------------------------------------------------------------
    Fill in all the known header fields, but not the checksum.
  ------------------------------------------------------------------------*/
  icmp_hdr.info.type = icmp_cb_ptr->type;
  icmp_hdr.info.code = icmp_cb_ptr->code;

  MSG_LOW("ICMP header successfully assembled", 0, 0, 0);

  /*-------------------------------------------------------------------------
    Collect length information and pass it down to icmp_output(). 
  ------------------------------------------------------------------------*/

  /*-------------------------------------------------------------------------
    Call icmp_output, which will make up the icmp header and send the 
    packet to IP.
  -------------------------------------------------------------------------*/
  length = dsm_length_packet(item_ptr);

  MSG_LOW("calling icmp_output(%d bytes), item length = %d", 
          length, 
          item_ptr->used, 
          0);
#ifdef FEATURE_DSM_MEM_CHK
  item_ptr->tracer = DSM_IP_SND_PROC;
#endif //FEATURE_DSM_MEM_CHK
  icmp_output( dest_ip_ptr, &icmp_hdr, item_ptr, icmp_cb_ptr, 0);

  /*-------------------------------------------------------------------------
    Return number of bytes sent out.
  ------------------------------------------------------------------------*/
  return (length);
}/* dssicmp_write() */
Example #4
0
File: ip.c Project: 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);
	}
}