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