/* * process an IP packet destined to someone else... * ARGUMENT: in_pkt - pointer to incoming packet * * Error processing: Check for conditions that generate ICMP packets. * For example, TTL expired, redirect, mulformed packets, ... * DF set and fragment,.. etc. * * Fragment processing: Check whether fragment is necessary .. condition already checked. * * Forward packet and fragments (could be multicasting) */ int IPProcessForwardingPacket(gpacket_t *in_pkt) { gpacket_t *pkt_frags[MAX_FRAGMENTS]; ip_packet_t *ip_pkt = (ip_packet_t *)in_pkt->data.data; int num_frags, i, need_frag; char tmpbuf[MAX_TMPBUF_LEN]; verbose(2, "[IPProcessForwardingPacket]:: checking for any IP errors.."); // all the validation and ICMP generation, processing is // done in this function... if (IPCheck4Errors(in_pkt) == EXIT_FAILURE) return EXIT_FAILURE; // find the route... if it does not exist, should we send a // ICMP network/host unreachable message -- CHECK?? if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), in_pkt->frame.nxth_ip_addr, &(in_pkt->frame.dst_interface)) == EXIT_FAILURE) return EXIT_FAILURE; // check for redirection?? -- the output interface is already found // by the previous command.. if needed the following routine sends the // redirects but the packet is sent to destination.. // TODO: Check the RFC for conformance?? IPCheck4Redirection(in_pkt); // check for fragmentation -- this should return three conditions: // FRAGS_NONE, FRAGS_ERROR, MORE_FRAGS need_frag = IPCheck4Fragmentation(in_pkt); switch (need_frag) { case FRAGS_NONE: verbose(2, "[IPProcessForwardingPacket]:: sending packet to GNET.."); // compute the checksum before sending out.. the fragmentation routine does this inside it. ip_pkt->ip_cksum = 0; ip_pkt->ip_cksum = htons(checksum((uchar *)ip_pkt, ip_pkt->ip_hdr_len *2)); if (IPSend2Output(in_pkt) == EXIT_FAILURE) { verbose(1, "[IPProcessForwardingPacket]:: WARNING: IPProcessForwardingPacket(): Could not forward packets "); return EXIT_FAILURE; } break; case FRAGS_ERROR: verbose(2, "[IPProcessForwardingPacket]:: unreachable on packet from %s", IP2Dot(tmpbuf, gNtohl((tmpbuf+20), ip_pkt->ip_src))); ICMPProcessFragNeeded(in_pkt); break; case MORE_FRAGS: // fragment processing... num_frags = fragmentIPPacket(in_pkt, pkt_frags); verbose(2, "[IPProcessForwardingPacket]:: IP packet needs fragmentation"); // forward each fragment for (i = 0; i < num_frags; i++) { if (IPSend2Output(pkt_frags[i]) == EXIT_FAILURE) { verbose(1, "[IPProcessForwardingPacket]:: processForwardIPPacket(): Could not forward packets "); return EXIT_FAILURE; } } deallocateFragments(pkt_frags, num_frags); break; default: return EXIT_FAILURE; } return EXIT_SUCCESS; }
/* * this function processes the IP packets that are reinjected into the * IP layer by ICMP, UDP, and other higher-layers. * There can be two scenarios. The packet can be a reply for an original * query OR it can be a new one. The processing performed by this function depends * on the packet type.. * IMPORTANT: src_prot is the source protocol number. */ int IPOutgoingPacket(gpacket_t *pkt, uchar *dst_ip, int size, int newflag, int src_prot) { ip_packet_t *ip_pkt = (ip_packet_t *)pkt->data.data; ushort cksum; char tmpbuf[MAX_TMPBUF_LEN]; uchar iface_ip_addr[4]; int status; ip_pkt->ip_ttl = 64; // set TTL to default value ip_pkt->ip_cksum = 0; // reset the checksum field ip_pkt->ip_prot = src_prot; // set the protocol field if (newflag == 0) { //if broadcast packet we set the address for 255.255.255.255 if(pkt->frame.bcast == TRUE) { //set ip to find route eg. 192.168.2.255 COPY_IP(ip_pkt->ip_dst, gHtonl(tmpbuf, dst_ip)); // find the nexthop and interface and fill them in the "meta" frame // NOTE: the packet itself is not modified by this lookup! if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), pkt->frame.nxth_ip_addr, &(pkt->frame.dst_interface)) == EXIT_FAILURE) return EXIT_FAILURE; //find interface IP if ((status = findInterfaceIP(MTU_tbl, pkt->frame.dst_interface, iface_ip_addr)) == EXIT_FAILURE) { error("[IPOutgoingPacket]:: couldn't find interface "); return EXIT_FAILURE; } // the outgoing packet should have the interface IP as source COPY_IP(ip_pkt->ip_src, gHtonl(tmpbuf, iface_ip_addr)); //set broadcast IP = 255.255.255.255 uchar bcast_ip[] = IP_BCAST_ADDR; COPY_IP(ip_pkt->ip_dst, gHtonl(tmpbuf, bcast_ip)); } else { COPY_IP(ip_pkt->ip_dst, ip_pkt->ip_src); // set dst to original src COPY_IP(ip_pkt->ip_src, gHtonl(tmpbuf, pkt->frame.src_ip_addr)); // set src to me // find the nexthop and interface and fill them in the "meta" frame // NOTE: the packet itself is not modified by this lookup! if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), pkt->frame.nxth_ip_addr, &(pkt->frame.dst_interface)) == EXIT_FAILURE) return EXIT_FAILURE; } } else if (newflag == 1) { // non REPLY PACKET -- this is a new packet; set all fields ip_pkt->ip_version = 4; ip_pkt->ip_hdr_len = 5; ip_pkt->ip_tos = 0; ip_pkt->ip_identifier = IP_OFFMASK & random(); RESET_DF_BITS(ip_pkt->ip_frag_off); RESET_MF_BITS(ip_pkt->ip_frag_off); ip_pkt->ip_frag_off = 0; COPY_IP(ip_pkt->ip_dst, gHtonl(tmpbuf, dst_ip)); ip_pkt->ip_pkt_len = htons(size + ip_pkt->ip_hdr_len * 4); //printGPacket(pkt, 3, "IP_ROUTINE"); //for debug verbose(2, "[IPOutgoingPacket]:: lookup next hop "); // find the nexthop and interface and fill them in the "meta" frame // NOTE: the packet itself is not modified by this lookup! if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), pkt->frame.nxth_ip_addr, &(pkt->frame.dst_interface)) == EXIT_FAILURE) { error("[IPOutgoingPacket]:: couldn't find route entry "); return EXIT_FAILURE; } verbose(2, "[IPOutgoingPacket]:: lookup MTU of nexthop"); // lookup the IP address of the destination interface.. if ((status = findInterfaceIP(MTU_tbl, pkt->frame.dst_interface, iface_ip_addr)) == EXIT_FAILURE) { error("[IPOutgoingPacket]:: couldn't find interface "); return EXIT_FAILURE; } // the outgoing packet should have the interface IP as source COPY_IP(ip_pkt->ip_src, gHtonl(tmpbuf, iface_ip_addr)); //if broadcast packet we set the address for 255.255.255.255 if(pkt->frame.bcast == TRUE) { //set broadcast IP = uchar bcast_ip[] = IP_BCAST_ADDR; COPY_IP(ip_pkt->ip_dst, gHtonl(tmpbuf, bcast_ip)); } verbose(2, "[IPOutgoingPacket]:: almost one processing the IP header."); } else { error("[IPOutgoingPacket]:: unknown outgoing packet action.. packet discarded "); return EXIT_FAILURE; } // compute the new checksum cksum = checksum((uchar *)ip_pkt, ip_pkt->ip_hdr_len*2); ip_pkt->ip_cksum = htons(cksum); pkt->data.header.prot = htons(IP_PROTOCOL); //FOR DEBUG if(src_prot == OSPF_PROTOCOL) //specific modifications for OSPF_PROTOCOL { ospfhdr_t *ospfhdr = (ospfhdr_t *)((uchar *)ip_pkt + ip_pkt->ip_hdr_len*4); if (ospfhdr->type == OSPF_LINK_STATUS_UPDATE && (COMPARE_IP(ospfhdr->ip_src, gHtonl(tmpbuf, iface_ip_addr))) == 0) { printGPacket(pkt, 3, "IP_ROUTINE"); verbose(2,"[DEBUG] Retransmission of LSA pkt, not broadcasting\n"); //return EXIT_SUCCESS; } } IPSend2Output(pkt); verbose(2, "[IPOutgoingPacket]:: IP packet sent to output queue.. "); return EXIT_SUCCESS; }
/* * this function processes the IP packets that are reinjected into the * IP layer by ICMP, UDP, and other higher-layers. * There can be two scenarios. The packet can be a reply for an original * query OR it can be a new one. The processing performed by this function depends * on the packet type.. * IMPORTANT: src_prot is the source protocol number. */ int IPOutgoingPacket(gpacket_t *pkt, uchar *dst_ip, int size, int newflag, int src_prot) { ip_packet_t *ip_pkt = (ip_packet_t *)pkt->data.data; ushort cksum; char tmpbuf[MAX_TMPBUF_LEN]; uchar iface_ip_addr[4]; int status; ip_pkt->ip_ttl = 64; // set TTL to default value ip_pkt->ip_cksum = 0; // reset the checksum field ip_pkt->ip_prot = src_prot; // set the protocol field if (newflag == 0) { COPY_IP(ip_pkt->ip_dst, ip_pkt->ip_src); // set dst to original src COPY_IP(ip_pkt->ip_src, gHtonl(tmpbuf, pkt->frame.src_ip_addr)); // set src to me // find the nexthop and interface and fill them in the "meta" frame // NOTE: the packet itself is not modified by this lookup! if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), pkt->frame.nxth_ip_addr, &(pkt->frame.dst_interface)) == EXIT_FAILURE) return EXIT_FAILURE; } else if (newflag == 1) { // non REPLY PACKET -- this is a new packet; set all fields ip_pkt->ip_version = 4; ip_pkt->ip_hdr_len = 5; ip_pkt->ip_tos = 0; ip_pkt->ip_identifier = IP_OFFMASK & random(); RESET_DF_BITS(ip_pkt->ip_frag_off); RESET_MF_BITS(ip_pkt->ip_frag_off); ip_pkt->ip_frag_off = 0; COPY_IP(ip_pkt->ip_dst, gHtonl(tmpbuf, dst_ip)); ip_pkt->ip_pkt_len = htons(size + ip_pkt->ip_hdr_len * 4); verbose(2, "[IPOutgoingPacket]:: lookup next hop "); // find the nexthop and interface and fill them in the "meta" frame // NOTE: the packet itself is not modified by this lookup! if (findRouteEntry(route_tbl, gNtohl(tmpbuf, ip_pkt->ip_dst), pkt->frame.nxth_ip_addr, &(pkt->frame.dst_interface)) == EXIT_FAILURE) return EXIT_FAILURE; verbose(2, "[IPOutgoingPacket]:: lookup MTU of nexthop"); // lookup the IP address of the destination interface.. if ((status = findInterfaceIP(MTU_tbl, pkt->frame.dst_interface, iface_ip_addr)) == EXIT_FAILURE) return EXIT_FAILURE; // the outgoing packet should have the interface IP as source COPY_IP(ip_pkt->ip_src, gHtonl(tmpbuf, iface_ip_addr)); verbose(2, "[IPOutgoingPacket]:: almost one processing the IP header."); } else { error("[IPOutgoingPacket]:: unknown outgoing packet action.. packet discarded "); return EXIT_FAILURE; } // compute the new checksum cksum = checksum((uchar *)ip_pkt, ip_pkt->ip_hdr_len*2); ip_pkt->ip_cksum = htons(cksum); pkt->data.header.prot = htons(IP_PROTOCOL); IPSend2Output(pkt); verbose(2, "[IPOutgoingPacket]:: IP packet sent to output queue.. "); return EXIT_SUCCESS; }