/* Handle IP packets encapsulated inside IP */ void ipip_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 ){ net_route(&Encap,bpp); }
/* Process SLIP line input */ void slip_rx( struct iface *iface) { int c; struct mbuf *bp; register struct slip *sp; int cdev; uint8 *cp; uint8 buf[4096]; int cnt; int xdev; xdev = iface->xdev; sp = &Slip[xdev]; cdev = sp->iface->dev; cnt = (*sp->get)(cdev,cp=buf,sizeof(buf)); while(--cnt >= 0){ if((bp = slip_decode(sp,*cp++)) == NULL) continue; /* More to come */ if (sp->iface->trace & IF_TRACE_RAW) raw_dump(sp->iface,IF_TRACE_IN,bp); if(sp->slcomp){ if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) { if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) { free_p(&bp); sp->errors++; continue; } } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) { bp->data[0] &= 0x4f; if ( slhc_remember(sp->slcomp, &bp) <= 0 ) { free_p(&bp); sp->errors++; continue; } } } net_route( sp->iface, &bp); /* Especially on slow machines, serial I/O can be quite * compute intensive, so release the machine before we * do the next packet. This will allow this packet to * go on toward its ultimate destination. [Karn] */ kwait(NULL); } }
static void ipip_receive(void *argp) { int addrlen; int hdr_len; int l; int32 ipaddr; struct edv_t *edv; struct iface *ifp; struct ip *ipptr; struct mbuf *bp; struct sockaddr_in addr; uint8 buf[MAX_FRAME]; uint8 *bufptr; ifp = (struct iface *) argp; edv = (struct edv_t *) ifp->edv; addrlen = sizeof(addr); l = recvfrom(edv->fd, (char *) (bufptr = buf), sizeof(buf), 0, (struct sockaddr *) &addr, &addrlen); if (edv->type == USE_IP) { if (l <= sizeof(struct ip)) goto Fail; ipptr = (struct ip *) bufptr; hdr_len = 4 * ipptr->ip_hl; bufptr += hdr_len; l -= hdr_len; } if (l <= 0) goto Fail; if ((ipaddr = get32(bufptr + 12)) && ismyaddr(ipaddr) == NULL) rt_add(ipaddr, 32, (int32) ntohl(addr.sin_addr.s_addr), ifp, 1L, 0x7fffffff / 1000, 0); bp = qdata(bufptr, l); net_route(ifp, &bp); return; Fail: ifp->crcerrors++; }
static void ethertap_recv(void *argp) { int l; struct edv_t *edv; struct ethertap_packet ethertap_packet; struct iface *ifp; struct mbuf *bp; ifp = (struct iface *) argp; edv = (struct edv_t *) ifp->edv; l = read(edv->fd, ðertap_packet, sizeof(ethertap_packet)) - sizeof(ethertap_packet.ethernet_header); if (l <= 0 || ethertap_packet.ethernet_header[14] != 0x08 || ethertap_packet.ethernet_header[15] != 0x00) { goto Fail; } bp = qdata(ethertap_packet.data, l); net_route(ifp, &bp); return; Fail: ifp->crcerrors++; }
/* 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; }
/* 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); }