/* 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; } }
/* 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); }
/*=========================================================================== 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() */
/* 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); } }