void arp_send(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, const unsigned char *dest_hw, const unsigned char *src_hw, const unsigned char *target_hw) { struct sk_buff *skb; if (dev->flags&IFF_NOARP) return; skb = arp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw); if (skb == NULL) return; arp_xmit(skb); }
/* simple fn for IP/Ethernet arp the most common */ struct pdu *arp_ie_simple_create(struct frame *framep, uint16_t oper, char *sha, char *spa, char *tha, char *tpa) { uint8_t bsha[6], btha[6]; uint8_t bspa[4], btpa[4]; /* convert strings */ if (!parse_mac_string(sha, bsha)) return NULL; if (!parse_mac_string(tha, btha)) return NULL; if (!parse_ip_string(spa, bspa)) return NULL; if (!parse_ip_string(tpa, btpa)) return NULL; /* return results of arp_create */ return arp_create(framep, ARP_HTYPE_ETHERNET, ETYPE_IP, 6, 4, oper, bsha, bspa, btha, btpa); }
/* * Create and send an arp packet. */ void arp_send(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, const unsigned char *dest_hw, const unsigned char *src_hw, const unsigned char *target_hw) { struct sk_buff *skb; /* * No arp on this interface. */ if (dev->flags&IFF_NOARP) return; printk(KERN_INFO "[mtk_net]arp_send type = %d, dev = %s\n", type, dev->name); skb = arp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw); if (skb == NULL) return; arp_xmit(skb); }
/* Create and send an arp packet. */ static void arp_send_dst(int type, int ptype, __be32 dest_ip, struct net_device *dev, __be32 src_ip, const unsigned char *dest_hw, const unsigned char *src_hw, const unsigned char *target_hw, struct dst_entry *dst) { struct sk_buff *skb; /* arp on this interface. */ if (dev->flags & IFF_NOARP) return; skb = arp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw); if (!skb) return; skb_dst_set(skb, dst_clone(dst)); arp_xmit(skb); }
/* * Create and send an arp packet. */ void arp_send(int type, int ptype, u32 dest_ip, struct net_device *dev, u32 src_ip, unsigned char *dest_hw, unsigned char *src_hw, unsigned char *target_hw) { struct sk_buff *skb; /* * No arp on this interface. */ if (dev->flags&IFF_NOARP) return; skb = arp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw); if (skb == NULL) { return; } arp_xmit(skb); }
/*--------------------------------------------------------------------- * Method: arp_queue_flush * *---------------------------------------------------------------------*/ static void arp_queue_flush(struct sr_instance *sr, struct arp_queue *queue) { assert(queue); struct arpq_entry *entry = queue->first; struct arpq_entry *temp = NULL; struct frame_t *arp_req; while(entry) { if( time(NULL) - ARP_REQUEST_TIMEOUT > entry->arpq_last_req) { if(entry->arpq_num_reqs >= ARP_MAX_REQ) { temp = entry; printf("TOO MANY ARP REQUESTS\n"); arpq_packets_icmpsend(sr, &entry->arpq_packets); } else if (entry->arpq_packets.first) { struct queued_packet *old_packet = entry->arpq_packets.first; arp_req = arp_create(sr, old_packet->outgoing, old_packet->outgoing->iface, ARP_REQUEST); sr_send_packet(sr, (uint8_t *)arp_req->frame, arp_req->len, old_packet->outgoing->iface->name); destroy_frame_t(arp_req); entry->arpq_last_req = time(NULL); entry->arpq_num_reqs++; } } entry = entry->next; if(temp) { if (temp->prev) (temp->prev)->next = temp->next; else queue->first = temp->next; if (temp->next) (temp->next)->prev = temp->prev; else queue->last = temp->prev; free(temp); temp = NULL; } } }
/* * Create and send an arp packet. */ void arp_send(int type, int ptype, u32 dest_ip, struct net_device *dev, u32 src_ip, unsigned char *dest_hw, unsigned char *src_hw, unsigned char *target_hw) { struct sk_buff *skb; /* * No arp on this interface. */ if (dev->flags&IFF_NOARP) return; skb = arp_create(type, ptype, dest_ip, dev, src_ip, dest_hw, src_hw, target_hw); if (skb == NULL) { return; } /*start of AU8D01166 add by z67625 优化QOS毛刺现象 arp 优先级设置为最高*/ skb->nfmark = (skb->nfmark & 0xFFFFFF00) | 0x00000013; /*end of AU8D01166 add by z67625 优化QOS毛刺现象 arp 优先级设置为最高*/ arp_xmit(skb); }
/** * batadv_bla_send_claim - sends a claim frame according to the provided info * @bat_priv: the bat priv with all the soft interface information * @mac: the mac address to be announced within the claim * @vid: the VLAN ID * @claimtype: the type of the claim (CLAIM, UNCLAIM, ANNOUNCE, ...) */ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, unsigned short vid, int claimtype) { struct sk_buff *skb; struct ethhdr *ethhdr; struct batadv_hard_iface *primary_if; struct net_device *soft_iface; uint8_t *hw_src; struct batadv_bla_claim_dst local_claim_dest; __be32 zeroip = 0; primary_if = batadv_primary_if_get_selected(bat_priv); if (!primary_if) return; memcpy(&local_claim_dest, &bat_priv->bla.claim_dest, sizeof(local_claim_dest)); local_claim_dest.type = claimtype; soft_iface = primary_if->soft_iface; skb = arp_create(ARPOP_REPLY, ETH_P_ARP, /* IP DST: 0.0.0.0 */ zeroip, primary_if->soft_iface, /* IP SRC: 0.0.0.0 */ zeroip, /* Ethernet DST: Broadcast */ NULL, /* Ethernet SRC/HW SRC: originator mac */ primary_if->net_dev->dev_addr, /* HW DST: FF:43:05:XX:YY:YY * with XX = claim type * and YY:YY = group id */ (uint8_t *)&local_claim_dest); if (!skb) goto out; ethhdr = (struct ethhdr *)skb->data; hw_src = (uint8_t *)ethhdr + ETH_HLEN + sizeof(struct arphdr); /* now we pretend that the client would have sent this ... */ switch (claimtype) { case BATADV_CLAIM_TYPE_CLAIM: /* normal claim frame * set Ethernet SRC to the clients mac */ ether_addr_copy(ethhdr->h_source, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): CLAIM %pM on vid %d\n", mac, BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_UNCLAIM: /* unclaim frame * set HW SRC to the clients mac */ ether_addr_copy(hw_src, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_ANNOUNCE: /* announcement frame * set HW SRC to the special mac containg the crc */ ether_addr_copy(hw_src, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", ethhdr->h_source, BATADV_PRINT_VID(vid)); break; case BATADV_CLAIM_TYPE_REQUEST: /* request frame * set HW SRC and header destination to the receiving backbone * gws mac */ ether_addr_copy(hw_src, mac); ether_addr_copy(ethhdr->h_dest, mac); batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", ethhdr->h_source, ethhdr->h_dest, BATADV_PRINT_VID(vid)); break; } if (vid & BATADV_VLAN_HAS_TAG) skb = vlan_insert_tag(skb, htons(ETH_P_8021Q), vid & VLAN_VID_MASK); skb_reset_mac_header(skb); skb->protocol = eth_type_trans(skb, soft_iface); batadv_inc_counter(bat_priv, BATADV_CNT_RX); batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, skb->len + ETH_HLEN); soft_iface->last_rx = jiffies; netif_rx(skb); out: if (primary_if) batadv_hardif_free_ref(primary_if); }
void sr_handlepacket(struct sr_instance* sr, uint8_t* packet/* lent */, unsigned int len, char* interface/* lent */) { /* REQUIRES */ assert(sr); assert(packet); assert(interface); printf("*** -> Received packet of length %d \n",len); if( len < ETHER_HDR_LEN ) { printf("Bogus packet length\n"); return; } struct sr_if *iface; struct frame_t *incoming = create_frame_t(sr, packet, len, interface); struct frame_t *outgoing = NULL; /* First, deal with ARP cache timeouts */ arp_cache_flush(&sr_arp_cache); arp_queue_flush(sr, &sr_arp_queue); /* Do we only need to cache ARP replies, or src MAC/IP on regular IP packets too, etc? */ /* Also, do we need to worry about fragmentation? */ /* Then actually handle the packet */ /* Start by determining protocol */ if (incoming->ip_header){ /* sanity checks */ if ( incoming->ip_header->ip_v != 4 ){ printf("IP packet not IPv4\n"); return; } compute_ip_checksum(incoming); /* Check the checksum */ if( incoming->ip_header->ip_sum != 0 ) { fprintf(stderr, "IP checksum incorrect, packet was dropped\n"); return; } //set checksum back to what it was compute_ip_checksum(incoming); /* Are we the destination? */ if (iface = if_dst_check(sr, incoming->to_ip)){ //we could change this to just take incoming and then get to_ip /* Is this an ICMP packet? */ if (incoming->icmp_header){ printf("received ICMP datagram\n"); compute_icmp_checksum(incoming); if(incoming->icmp_header->icmp_type == ECHO_REQUEST && incoming->icmp_header->icmp_sum == 0){ outgoing = generate_icmp_echo(incoming); printf("received ICMP echo request\n"); } else printf("Dropped packet--we don't deal with that code, or invalid checksum\n"); } else{ outgoing = generate_icmp_error(incoming, DEST_UNREACH, PORT_UNREACH); printf("A packet for me! Flattering, but wrong.\n"); } } else { /* Has it timed out? */ if (incoming->ip_header->ip_ttl <= 0){ int err = 0; //make sure it's not an ICMP error packet alrady if (incoming->ip_header->ip_p == IPPROTO_ICMP){ incoming->icmp_header = ((void *) incoming->ip_header + incoming->ip_hl); uint8_t code = incoming->icmp_header->icmp_type; //don't send ICMP error messages about ICMP error messages if (code == DEST_UNREACH || code == TIME_EXCEEDED || code == 12 || code == 31) //12 and 31 indicate bad IP header and datagram conversion error, respectively err = 1; } if (!err){ outgoing = generate_icmp_error(incoming, TIME_EXCEEDED, TIME_INTRANSIT); printf("Slowpoke. TTL exceeded.\n"); } } else { /* update and forward packet; if necessary, add it to queue */ struct arpc_entry *incache; uint32_t arpc_ip; outgoing = update_ip_hdr(sr, incoming, &arpc_ip); incache = arp_cache_lookup(sr_arp_cache.first, arpc_ip); if (!incache){ struct arpq_entry *entry = arp_queue_lookup(sr_arp_queue.first, outgoing->to_ip); struct arpq_entry *temp_entry = NULL; if ( entry ){ //if we've already sent an ARP request about this IP if( time(NULL) - 1 > entry->arpq_last_req ) { if(entry->arpq_num_reqs >= ARP_MAX_REQ) { printf("Too many ARP requests\n"); arpq_packets_icmpsend(sr, &entry->arpq_packets); destroy_arpq_entry(entry); return; } else if (entry->arpq_packets.first) { struct frame_t *arp_req; struct queued_packet *old_packet = entry->arpq_packets.first; entry->arpq_last_req = time(NULL); entry->arpq_num_reqs++; } } assert( (entry->arpq_packets).first ); if (!arpq_add_packet(entry, outgoing, len, incoming->from_MAC, incoming->iface)) printf("ARP queue packet add failed\n"); else printf("added packet to queue\n"); } /* else, there are no outstanding ARP requests for this particular IP */ else { printf("outgoing ip is %d\n", ntohl(outgoing->to_ip)); temp_entry = arpq_add_entry(&sr_arp_queue, outgoing->iface, outgoing, outgoing->to_ip, outgoing->ip_len, incoming->from_MAC, incoming->iface); } free(outgoing->frame); /* make ARP request */ outgoing = arp_create(sr, outgoing, outgoing->iface, ARP_REQUEST); //send datagram will now point to an ARP packet, not to the IP datagram if (temp_entry){ temp_entry->arpq_next_hop = outgoing->to_ip; } printf("sending ARP request\n"); } else{ printf("got the MAC, can actually send this packet\n"); memcpy(outgoing->to_MAC, incache->arpc_mac, ETHER_ADDR_LEN); encapsulate(outgoing); } } } } else if ( incoming->arp_header ) { printf("received ARP packet\n"); struct sr_arphdr *arp_header = incoming->arp_header; uint8_t in_cache = 0; struct arpc_entry *arpc_ent = arp_cache_lookup(sr_arp_cache.first, arp_header->ar_sip); printf("checking the cache\n"); if( arpc_ent ) { arp_cache_update(arpc_ent, arp_header->ar_sha); printf("updated cache\n"); in_cache = 1; } struct sr_if *target_if = if_dst_check(sr, arp_header->ar_tip); printf("checking the target\n"); if( target_if ) { printf("It's for us\n"); if( !in_cache ) { if( arp_cache_add(&sr_arp_cache, arp_header->ar_sha, arp_header->ar_sip) ) { printf("added to cache\n"); printf("ip is %d\n", ntohl(arp_header->ar_sip)); struct arpq_entry *new_ent; if( new_ent = arpq_next_hop_lookup(sr_arp_queue.first, arp_header->ar_sip) ) arpq_entry_clear(sr, &sr_arp_queue, new_ent, arp_header->ar_sha); } else perror("ARP request not added to cache"); } if( ntohs(arp_header->ar_op) == ARP_REQUEST ){ outgoing = arp_create(sr, incoming, incoming->iface, ARP_REPLY); printf("created ARP reply\n"); assert(outgoing); } } } else perror("Unknown protocol"); //send datagram, if appropriate if (outgoing != NULL){ sr_send_packet(sr, (uint8_t *)outgoing->frame, outgoing->len, outgoing->iface->name); printf("sent packet of length %d on iface %s\n", outgoing->len, outgoing->iface->name); } if (outgoing != NULL) destroy_frame_t(outgoing); }/* end sr_handlepacket */