static void cleanup(int sig) { int i; int rounds = (cleanup_src_own*5 + cleanup_src_host*5); fprintf(stderr, "Cleaning up and re-arping targets...\n"); for (i = 0; i < rounds; i++) { struct host *target = hosts; for(;target->ip;target++) { uint8_t *src_ha = NULL; if (!(target->flags & HOST_TARGET)) continue; if (!(target->flags & HOST_ACTIVE)) continue; struct host *model = hosts; for(;model->ip;model++) { if (!(model->flags & HOST_ACTIVE)) continue; int fw = arp_find(target->ip, &target->mac); int bw = poison_reverse; if (!(model->flags & HOST_MODEL)) continue; if (cleanup_src_own && (i%2 || !cleanup_src_host)) { src_ha = my_ha; } /* XXX - on BSD, requires ETHERSPOOF kernel. */ if (fw) { arp_send(l, ARPOP_REPLY, (u_int8_t *)&model->mac, model->ip, (target->ip ? (u_int8_t *)&target->mac : brd_ha), target->ip, src_ha); /* we have to wait a moment before sending the next packet */ usleep(ARP_PAUSE); } if (bw) { arp_send(l, ARPOP_REPLY, (u_int8_t *)&target->mac, target->ip, (u_int8_t *)&model->mac, model->ip, src_ha); usleep(ARP_PAUSE); } } } } exit(0); }
static void cleanup(int sig) { killed = 1; printf( "Restoring arp table ...\n" ); int i, j; struct ether_addr gateway_mac; if( netmap == NULL ) { if( arp_lookup( gateway_ip, &gateway_mac, iface ) == 0 ) { for( i = 0; i < 3; i++ ) { /* XXX - on BSD, requires ETHERSPOOF kernel. */ arp_send( lnet, ARPOP_REPLY, (unsigned char *)&gateway_mac, gateway_ip, (unsigned char *)&target_mac, target_ip ); sleep(1); } } } else { if( arp_lookup( gateway_ip, &gateway_mac, iface ) == 0 ) { for( i = 0; i < 3; i++ ) { for( j = 0; j < netmap->bucketCount; j++ ) { Entry* hentry = netmap->buckets[j]; while( hentry != NULL ) { Entry *next = hentry->next; network_entry_t *entry = ( network_entry_t * )hentry->value; arp_send( lnet, ARPOP_REPLY, (unsigned char *)&gateway_mac, gateway_ip, entry->mac, entry->address ); hentry = next; } } sleep(1); } } hashmapFree( netmap ); } exit(0); }
//------------------------------------------------------------------------ // This re-sends an ARP request if there was no response to // the first one. It is called every 0.5 seconds. If there // is no response after 2 re-tries, the datagram that IP was // trying to send is deleted //----------------------------------------------------------------------- void arp_retransmit(void) { static UCHAR idata retries = 0; if ((waiting_for_arp) && (wait.timer)) { wait.timer--; if (wait.timer == 0) { retries++; if (retries <= 2) { if (debug) serial_send("ARP: Re-sending ARP broadcast\r"); arp_send(NULL, wait.ipaddr, ARP_REQUEST); wait.timer = ARP_TIMEOUT; } else { if (debug) serial_send("ARP: Gave up waiting for response\r"); wait.timer = 0; waiting_for_arp = 0; free(wait.buf); } } } }
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { __be32 saddr = 0; u8 dst_ha[MAX_ADDR_LEN], *dst_hw = NULL; struct net_device *dev = neigh->dev; __be32 target = *(__be32 *)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { rcu_read_unlock(); return; } switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: /* By default announce any local IP */ if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) saddr = ip_hdr(skb)->saddr; break; case 1: /* Restrict announcements of saddr in same subnet */ if (!skb) break; saddr = ip_hdr(skb)->saddr; if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: /* Avoid secondary IPs, get a primary/preferred one */ break; } rcu_read_unlock(); if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); probes -= neigh->parms->ucast_probes; if (probes < 0) { if (!(neigh->nud_state & NUD_VALID)) pr_debug("trying to ucast probe in NUD_INVALID\n"); neigh_ha_snapshot(dst_ha, neigh, dev); dst_hw = dst_ha; } else { probes -= neigh->parms->app_probes; if (probes < 0) { #ifdef CONFIG_ARPD neigh_app_ns(neigh); #endif return; } } arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_hw, dev->dev_addr, NULL); }
//------------------------------------------------------------------------ // Find the ethernet hardware address for the given ip address // If destination IP is on my subnet then we want the eth // address of destination, otherwise we want eth addr of gateway. // Look in ARP cache first. If not found there, send ARP request. // Return pointer to the hardware address or NULL if not found // See "TCP/IP Illustrated, Volume 1" Sect 4.5 //------------------------------------------------------------------------ UCHAR xdata * arp_resolve(ULONG dest_ipaddr) { UCHAR i; // If destination IP is not on my subnet then we really want eth addr // of gateway, not destination IP if ((dest_ipaddr ^ my_ipaddr) & my_subnet) { if (gateway_ipaddr == 0) { return (NULL); } else dest_ipaddr = gateway_ipaddr; } // See if IP addr of interest is in ARP cache for (i=0; i < CACHESIZE; i++) { if (arp_cache[i].ipaddr == dest_ipaddr) return (&arp_cache[i].hwaddr[0]); } // Not in cache so broadcast ARP request arp_send(NULL, dest_ipaddr, ARP_REQUEST); // Set a flag to indicate that an IP datagram is waiting // to be sent waiting_for_arp = TRUE; // Null means that we have sent an ARP request return (NULL); }
/*Does all handling of incoming ARP packets, returns 1 if successful*/ int handle_ARP_packet(struct sr_instance* sr, uint8_t* packet, int len, char* interface){ int minLenARP = sizeof(struct sr_ethernet_hdr) + sizeof(struct sr_arp_hdr); if (len < minLenARP){ fprintf(stderr, "Failed to access ARP header, too small\n"); drop_packet = 1; //return; } if (drop_packet == 0){ if (destinedToRouter(dest_ip)){ sr_ethernet_hdr_t* ethernet_hdr = (sr_ethernet_hdr_t*)packet; sr_arp_hdr_t* arp_header = (sr_arp_hdr_t*)(packet + (uint8_t) eth_size); if (ntohl(arp_header->ar_op) == arp_op_reply){//We have a ARP reply //process reply //move entries from ARP request queue to ARP cache struct sr_arpreq* req; req = sr_arpcache_insert(&(sr->cache), arp_header->ar_sha, ntohl(arp_header->ar_sip)); if (req!=NULL){ struct sr_packet* traverser = req->packets; while(traverser != NULL){ //normal IP forward, no errors detected //change old contents struct sr_arpentry *arp_entry; arp_entry = sr_arpcache_lookup(&(sr->cache),dest_ip); sr_ip_hdr_t* ip_header = (sr_ip_hdr_t*)(packet + (uint8_t) eth_size); sr_ethernet_hdr_t* out_eth = (sr_ethernet_hdr_t*)packet; uint16_t modCksum = cksum(ip_header, sizeof(struct sr_ip_hdr)); int ret = ip_forward(sr,packet,len,out_eth,arp_entry->mac, dest_ip, modCksum,interface); if (ret!= 0){ fprintf(stderr, "Didn't send ip packet properly\n"); } traverser = traverser->next; } sr_arpreq_destroy(&(sr->cache), req); } }else{ //process ARP request and send reply //(they want our MAC address) so sends reply packet int ret = arp_send(sr,packet,len, ethernet_hdr,arp_header,dest_ip); if (ret!= 0){ fprintf(stderr, "Didn't send arp packet properly\n"); } } }else{ //pass //forward packet } } return 1; }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c; intf = NULL; spoof_ip = target_ip = 0; while ((c = getopt(argc, argv, "i:t:h?V")) != -1) { switch (c) { case 'i': intf = optarg; break; case 't': if ((target_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1) usage(); break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); if ((spoof_ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) usage(); if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) errx(1, "%s", pcap_ebuf); if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) errx(1, "%s", libnet_ebuf); if (target_ip != 0 && !arp_find(target_ip, &target_mac)) errx(1, "couldn't arp for host %s", libnet_addr2name4(target_ip, LIBNET_DONT_RESOLVE)); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); for (;;) { arp_send(l, ARPOP_REPLY, NULL, spoof_ip, (target_ip ? (u_int8_t *)&target_mac : NULL), target_ip); sleep(2); } /* NOTREACHED */ exit(0); }
static void br_do_proxy_arp(struct sk_buff *skb, struct net_bridge *br, u16 vid, struct net_bridge_port *p) { struct net_device *dev = br->dev; struct neighbour *n; struct arphdr *parp; u8 *arpptr, *sha; __be32 sip, tip; BR_INPUT_SKB_CB(skb)->proxyarp_replied = false; if (dev->flags & IFF_NOARP) return; if (!pskb_may_pull(skb, arp_hdr_len(dev))) { dev->stats.tx_dropped++; return; } parp = arp_hdr(skb); if (parp->ar_pro != htons(ETH_P_IP) || parp->ar_op != htons(ARPOP_REQUEST) || parp->ar_hln != dev->addr_len || parp->ar_pln != 4) return; arpptr = (u8 *)parp + sizeof(struct arphdr); sha = arpptr; arpptr += dev->addr_len; /* sha */ memcpy(&sip, arpptr, sizeof(sip)); arpptr += sizeof(sip); arpptr += dev->addr_len; /* tha */ memcpy(&tip, arpptr, sizeof(tip)); if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) return; n = neigh_lookup(&arp_tbl, &tip, dev); if (n) { struct net_bridge_fdb_entry *f; if (!(n->nud_state & NUD_VALID)) { neigh_release(n); return; } f = __br_fdb_get(br, n->ha, vid); if (f && ((p->flags & BR_PROXYARP) || (f->dst && (f->dst->flags & BR_PROXYARP_WIFI)))) { arp_send(ARPOP_REPLY, ETH_P_ARP, sip, skb->dev, tip, sha, n->ha, sha); BR_INPUT_SKB_CB(skb)->proxyarp_replied = true; } neigh_release(n); } }
s32 mpls_echo_info_get(void * buf) { s32 err = 0; struct fib_mg_res ret = {0}; mpls_echo_sys_req * req = (mpls_echo_sys_req *)buf ; mpls_echo_sys_res * res = (mpls_echo_sys_res *)buf; err = fib_mg_lookup(req->vrfid, req->addr, req->plen, &ret); if (err) { res->count = 0; return err; } if (!ret.neigh) { ret.neigh = __neigh_arp_lookup(&arp_tbl, &ret.nexthop, NULL, ret.dev, NEIGHBOUR_CREAT); read_lock_bh(&ret.neigh->lock); if (!(ret.neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) { res->saddr = inet_select_addr(ret.dev, ret.nexthop, RT_SCOPE_LINK); arp_send(ARPOP_REQUEST, ETH_P_ARP, ret.nexthop, ret.dev, res->saddr, ret.neigh->ha, ret.dev->dev_addr, NULL); read_unlock_bh(&ret.neigh->lock); return 0; } read_unlock_bh(&ret.neigh->lock); } memcpy((void *)res->dest, (void *)ret.neigh->ha, ETH_ALEN); if (ret.dev) { res->oif = ret.dev->ifindex; res->saddr = inet_select_addr(ret.dev, ret.nexthop, RT_SCOPE_LINK); memcpy((void *)res->source, (void *)ret.dev->dev_addr, ret.dev->addr_len); } res->nexthop = ret.nexthop; res->count = ret.count; if (FIB_MG_TYPE_FTN_BASIC == ret.type) { res->labels[0] = ret.glabel; res->labels[1] = ret.glabel2; } else { res->labels[0] = ret.label; res->labels[1] = ret.glabel; res->labels[1] = ret.glabel2; } return 0; }
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { u32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; u32 target = *(u32*)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev = in_dev_get(dev); if (!in_dev) return; switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: /* By default announce any local IP */ if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL) saddr = skb->nh.iph->saddr; break; case 1: /* Restrict announcements of saddr in same subnet */ if (!skb) break; saddr = skb->nh.iph->saddr; if (inet_addr_type(saddr) == RTN_LOCAL) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: /* Avoid secondary IPs, get a primary/preferred one */ break; } if (in_dev) in_dev_put(in_dev); if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); if ((probes -= neigh->parms->ucast_probes) < 0) { if (!(neigh->nud_state&NUD_VALID)) printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); dst_ha = neigh->ha; read_lock_bh(&neigh->lock); } else if ((probes -= neigh->parms->app_probes) < 0) { #ifdef CONFIG_ARPD neigh_app_ns(neigh); #endif return; } arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL); if (dst_ha) read_unlock_bh(&neigh->lock); }
/* function taken from net/ipv4/devinet.c */ static void inetdev_send_gratuitous_arp(struct net_device *dev, struct in_device *in_dev) { struct in_ifaddr *ifa; for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { arp_send(ARPOP_REQUEST, ETH_P_ARP, ifa->ifa_local, dev, ifa->ifa_local, NULL, dev->dev_addr, NULL); } }
static void cleanup(int sig) { int i; if (arp_find(spoof_ip, &spoof_mac)) { for (i = 0; i < 3; i++) { /* XXX - on BSD, requires ETHERSPOOF kernel. */ arp_send(l, ARPOP_REPLY, (u_int8_t *)&spoof_mac, spoof_ip, (target_ip ? (u_int8_t *)&target_mac : NULL), target_ip); sleep(1); } } exit(0); }
static void rlb_update_client(struct rlb_client_info *client_info) { int i = 0; if (client_info->slave == NULL) { return; } for (i=0; i<RLB_ARP_BURST_SIZE; i++) { arp_send(ARPOP_REPLY, ETH_P_ARP, client_info->ip_dst, client_info->slave->dev, client_info->ip_src, client_info->mac_dst, client_info->slave->dev->dev_addr, client_info->mac_dst); } }
static int ebt_target_reply(struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { struct ebt_arpreply_info *info = (void *)data; const __be32 *siptr, *diptr; __be32 _sip, _dip; const struct arphdr *ap; struct arphdr _ah; const unsigned char *shp; unsigned char _sha[ETH_ALEN]; ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); if (ap == NULL) return EBT_DROP; if (ap->ar_op != htons(ARPOP_REQUEST) || ap->ar_hln != ETH_ALEN || ap->ar_pro != htons(ETH_P_IP) || ap->ar_pln != 4) return EBT_CONTINUE; shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha); if (shp == NULL) return EBT_DROP; siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN, sizeof(_sip), &_sip); if (siptr == NULL) return EBT_DROP; diptr = skb_header_pointer(skb, sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip), sizeof(_dip), &_dip); if (diptr == NULL) return EBT_DROP; arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)in, *diptr, shp, info->mac, shp); return info->target; }
static unsigned int ebt_arpreply_tg(struct sk_buff *skb, const struct xt_action_param *par) { const struct ebt_arpreply_info *info = par->targinfo; const __be32 *siptr, *diptr; __be32 _sip, _dip; const struct arphdr *ap; struct arphdr _ah; const unsigned char *shp; unsigned char _sha[ETH_ALEN]; ap = skb_header_pointer(skb, 0, sizeof(_ah), &_ah); if (ap == NULL) return EBT_DROP; if (ap->ar_op != htons(ARPOP_REQUEST) || ap->ar_hln != ETH_ALEN || ap->ar_pro != htons(ETH_P_IP) || ap->ar_pln != 4) return EBT_CONTINUE; shp = skb_header_pointer(skb, sizeof(_ah), ETH_ALEN, &_sha); if (shp == NULL) return EBT_DROP; siptr = skb_header_pointer(skb, sizeof(_ah) + ETH_ALEN, sizeof(_sip), &_sip); if (siptr == NULL) return EBT_DROP; diptr = skb_header_pointer(skb, sizeof(_ah) + 2 * ETH_ALEN + sizeof(_sip), sizeof(_dip), &_dip); if (diptr == NULL) return EBT_DROP; arp_send(ARPOP_REPLY, ETH_P_ARP, *siptr, (struct net_device *)xt_in(par), *diptr, shp, info->mac, shp); return info->target; }
static int arp_find(in_addr_t ip, struct ether_addr *mac) { int i = 0; do { if (arp_cache_lookup(ip, mac, intf) == 0) return (1); #ifdef __linux__ /* XXX - force the kernel to arp. feh. */ arp_force(ip); #else arp_send(l, ARPOP_REQUEST, NULL, 0, NULL, ip, NULL); #endif usleep(10000); } while (i++ < 3); return (0); }
static int arp_proc(struct netbuf *buf) { int ret = 0; switch (buf->cmd) { case ARP_CMD_MACADDR: memcpy(my_macaddr, buf->option.common.macaddr.addr, MACADDR_SIZE); break; case ARP_CMD_IPADDR: my_ipaddr = buf->option.common.ipaddr.addr; break; case ARP_CMD_RECV: ret = arp_recv(buf); break; case ARP_CMD_SEND: ret = arp_send(buf); break; default: break; } return ret; }
//------------------------------------------------------------------------ // This re-sends an ARP request if there was no response to // the first one. It is called every 0.5 seconds. If there // is no response after 2 re-tries, the datagram that IP was // trying to send is deleted //----------------------------------------------------------------------- void arp_retransmit(void) { static UCHAR idata retries = 0; if ((waiting_for_arp) && (wait.timer)) { wait.timer--; if (wait.timer == 0) { retries++; if (retries <= 2) { arp_send(NULL, wait.ipaddr, ARP_REQUEST); wait.timer = ARP_TIMEOUT; } else { wait.timer = 0; waiting_for_arp = 0; // free(wait.buf); } } } }
static int arp_process(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct in_device *in_dev = in_dev_get(dev); struct arphdr *arp; unsigned char *arp_ptr; struct rtable *rt; unsigned char *sha; __be32 sip, tip; u16 dev_type = dev->type; int addr_type; struct neighbour *n; struct net *net = dev_net(dev); /* arp_rcv below verifies the ARP header and verifies the device * is ARP'able. */ if (in_dev == NULL) goto out; arp = arp_hdr(skb); switch (dev_type) { default: if (arp->ar_pro != htons(ETH_P_IP) || htons(dev_type) != arp->ar_hrd) goto out; break; case ARPHRD_ETHER: case ARPHRD_IEEE802_TR: case ARPHRD_FDDI: case ARPHRD_IEEE802: /* * ETHERNET, Token Ring and Fibre Channel (which are IEEE 802 * devices, according to RFC 2625) devices will accept ARP * hardware types of either 1 (Ethernet) or 6 (IEEE 802.2). * This is the case also of FDDI, where the RFC 1390 says that * FDDI devices should accept ARP hardware of (1) Ethernet, * however, to be more robust, we'll accept both 1 (Ethernet) * or 6 (IEEE 802.2) */ if ((arp->ar_hrd != htons(ARPHRD_ETHER) && arp->ar_hrd != htons(ARPHRD_IEEE802)) || arp->ar_pro != htons(ETH_P_IP)) goto out; break; case ARPHRD_AX25: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_AX25)) goto out; break; case ARPHRD_NETROM: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_NETROM)) goto out; break; } /* Understand only these message types */ if (arp->ar_op != htons(ARPOP_REPLY) && arp->ar_op != htons(ARPOP_REQUEST)) goto out; /* * Extract fields */ arp_ptr= (unsigned char *)(arp+1); sha = arp_ptr; arp_ptr += dev->addr_len; memcpy(&sip, arp_ptr, 4); arp_ptr += 4; arp_ptr += dev->addr_len; memcpy(&tip, arp_ptr, 4); /* * Check for bad requests for 127.x.x.x and requests for multicast * addresses. If this is one such, delete it. */ if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) goto out; /* * Special case: We must set Frame Relay source Q.922 address */ if (dev_type == ARPHRD_DLCI) sha = dev->broadcast; /* * Process entry. The idea here is we want to send a reply if it is a * request for us or if it is a request for someone else that we hold * a proxy for. We want to add an entry to our cache if it is a reply * to us or if it is a request for our address. * (The assumption for this last is that if someone is requesting our * address, they are probably intending to talk to us, so it saves time * if we cache their address. Their address is also probably not in * our cache, since ours is not in their cache.) * * Putting this another way, we only care about replies if they are to * us, in which case we add them to the cache. For requests, we care * about those for us and those for our proxies. We reply to both, * and in the case of requests for us we add the requester to the arp * cache. */ /* Special case: IPv4 duplicate address detection packet (RFC2131) */ if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(net, tip) == RTN_LOCAL && !arp_ignore(in_dev, sip, tip)) arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev->dev_addr, sha); goto out; } if (arp->ar_op == htons(ARPOP_REQUEST) && ip_route_input(skb, tip, sip, 0, dev) == 0) { rt = skb->rtable; addr_type = rt->rt_type; if (addr_type == RTN_LOCAL) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) { int dont_send = 0; if (!dont_send) dont_send |= arp_ignore(in_dev,sip,tip); if (!dont_send && IN_DEV_ARPFILTER(in_dev)) dont_send |= arp_filter(sip,tip,dev); if (!dont_send) arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); neigh_release(n); } goto out; } else if (IN_DEV_FORWARD(in_dev)) { if (addr_type == RTN_UNICAST && rt->u.dst.dev != dev && (arp_fwd_proxy(in_dev, rt) || pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) neigh_release(n); if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || skb->pkt_type == PACKET_HOST || in_dev->arp_parms->proxy_delay == 0) { arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha); } else { pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); in_dev_put(in_dev); return 0; } goto out; } } } /* Update our ARP tables */ n = __neigh_lookup(&arp_tbl, &sip, dev, 0); if (IPV4_DEVCONF_ALL(dev_net(dev), ARP_ACCEPT)) { /* Unsolicited ARP is not accepted by default. It is possible, that this option should be enabled for some devices (strip is candidate) */ if (n == NULL && arp->ar_op == htons(ARPOP_REPLY) && inet_addr_type(net, sip) == RTN_UNICAST) n = __neigh_lookup(&arp_tbl, &sip, dev, 1); } if (n) { int state = NUD_REACHABLE; int override; /* If several different ARP replies follows back-to-back, use the FIRST one. It is possible, if several proxy agents are active. Taking the first reply prevents arp trashing and chooses the fastest router. */ override = time_after(jiffies, n->updated + n->parms->locktime); /* Broadcast replies and request packets do not assert neighbour reachability. */ if (arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST) state = NUD_STALE; neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0); neigh_release(n); }
s32 mpls_echo_input(struct sk_buff * skb) { s32 err = 0; s32 temp = 0; u32 saddr = 0; struct timeval tv; mpls_echo_hdr * echo; struct ethhdr * eth ; struct fib_mg_res res ; struct iphdr *iph = skb->nh.iph; struct udphdr * udph = skb->h.uh; echo = (mpls_echo_hdr *)(skb->data + sizeof(struct udphdr)); skb_push(skb, iph->ihl * 4); err = fib_mg_lookup(if_dev_vrf(skb->dev)->vrf_id, iph->saddr, 32, &res); if (err) { printk("mpls_echo_input -fib_mg_lookup drop.\n"); goto drop; } temp = iph->daddr; iph->daddr = iph->saddr; if (res.dev) { iph->saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK); } else { iph->saddr = temp; } iph->ttl = 255; iph->check = 0; iph->check = ip_fast_csum(iph, iph->ihl); echo->type = MPLS_ECHO_REPLY; do_gettimeofday(&tv); echo->t_rcvd[0] = htonl(tv.tv_sec+JAN_1970); echo->t_rcvd[1] = NTPFRAC(tv.tv_usec); temp = udph->source; udph->source = udph->dest; udph->dest = temp; if (MPLS_MODE_DO_NOT_REPLY == echo->mode) { printk("mpls_echo_input -not reply mode drop.\n"); goto drop; } if (MPLS_MODE_IPX_UDP_ALERT == echo->mode) { //Push router alert to ip option. } skb->protocol = htons(ETH_P_IP); if (FIB_MG_TYPE_FTN_BASIC == res.type) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel, 1); } if (2 == res.count) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel2, 0); } } } else { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.label, 1); if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel)) { skb_push_label(skb, 128, res.glabel, 0); } if (3 == res.count) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel2, 0); } } } if (MPLS_MODE_CTRL_CHANNEL == echo->mode) { skb_push_label(skb, 128, 1, 0); } skb->nh.raw = skb->data; skb->dev = res.dev; if (!res.neigh) { res.neigh = __neigh_arp_lookup(&arp_tbl, &res.nexthop, NULL, res.dev, NEIGHBOUR_CREAT); } read_lock_bh(&res.neigh->lock); if (!(res.neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) { saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK); arp_send(ARPOP_REQUEST, ETH_P_ARP, res.nexthop, res.dev, saddr, res.neigh->ha, res.dev->dev_addr, NULL); read_unlock_bh(&res.neigh->lock); printk("mpls_echo_input -neigh invalid drop.\n"); goto drop; } eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); eth->h_proto = (ETH_P_802_3 != skb->protocol) ? htons(skb->protocol) : htons(skb->len); memcpy(eth->h_source, res.dev->dev_addr, res.dev->addr_len); memcpy(eth->h_dest, res.neigh->ha, res.dev->addr_len); skb->mac.raw = skb->data ; skb->mac_len = ETH_HLEN; read_unlock_bh(&res.neigh->lock); neigh_release(res.neigh); dev_queue_xmit(skb); return 0; drop: kfree_skb(skb); return -1; }
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, size_t len) { FAR struct tcp_conn_s *conn = (FAR struct tcp_conn_s *)psock->s_conn; struct send_s state; net_lock_t save; int err; int ret = OK; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { ndbg("ERROR: Invalid socket\n"); err = EBADF; goto errout; } /* If this is an un-connected socket, then return ENOTCONN */ if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) { ndbg("ERROR: Not connected\n"); err = ENOTCONN; goto errout; } /* Make sure that we have the IP address mapping */ conn = (FAR struct tcp_conn_s *)psock->s_conn; DEBUGASSERT(conn); #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND #ifdef CONFIG_NET_ICMPv6_NEIGHBOR if (psock->s_domain == PF_INET) #endif { /* Make sure that the IP address mapping is in the ARP table */ ret = arp_send(conn->u.ipv4.raddr); } #endif /* CONFIG_NET_ARP_SEND */ #ifdef CONFIG_NET_ICMPv6_NEIGHBOR #ifdef CONFIG_NET_ARP_SEND else #endif { /* Make sure that the IP address mapping is in the Neighbor Table */ ret = icmpv6_neighbor(conn->u.ipv6.raddr); } #endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ /* Did we successfully get the address mapping? */ if (ret < 0) { ndbg("ERROR: Not reachable\n"); err = ENETUNREACH; goto errout; } #endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */ /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); /* Perform the TCP send operation */ /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ save = net_lock(); memset(&state, 0, sizeof(struct send_s)); (void)sem_init(&state.snd_sem, 0, 0); /* Doesn't really fail */ state.snd_sock = psock; /* Socket descriptor to use */ state.snd_buflen = len; /* Number of bytes to send */ state.snd_buffer = buf; /* Buffer to send from */ if (len > 0) { /* Allocate resources to receive a callback */ state.snd_cb = tcp_callback_alloc(conn); if (state.snd_cb) { /* Get the initial sequence number that will be used */ state.snd_isn = tcp_getsequence(conn->sndseq); /* There is no outstanding, unacknowledged data after this * initial sequence number. */ conn->unacked = 0; /* Set the initial time for calculating timeouts */ #ifdef CONFIG_NET_SOCKOPTS state.snd_time = clock_systimer(); #endif /* Set up the callback in the connection */ state.snd_cb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL | TCP_DISCONN_EVENTS); state.snd_cb->priv = (FAR void *)&state; state.snd_cb->event = tcpsend_interrupt; /* Notify the device driver of the availability of TX data */ send_txnotify(psock, conn); /* Wait for the send to complete or an error to occur: NOTES: (1) * net_lockedwait will also terminate if a signal is received, (2) interrupts * may be disabled! They will be re-enabled while the task sleeps and * automatically re-enabled when the task restarts. */ ret = net_lockedwait(&state.snd_sem); /* Make sure that no further interrupts are processed */ tcp_callback_free(conn, state.snd_cb); } } sem_destroy(&state.snd_sem); net_unlock(save); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signalled by negative errno values * for the send length */ if (state.snd_sent < 0) { err = state.snd_sent; goto errout; } /* If net_lockedwait failed, then we were probably reawakened by a signal. In * this case, net_lockedwait will have set errno appropriately. */ if (ret < 0) { err = -ret; goto errout; } /* Return the number of bytes actually sent */ return state.snd_sent; errout: set_errno(err); return ERROR; }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c, netmask = 0, ifaddr = 0, nhosts = 0, i = 0; network_entry_t *entry; iface = NULL; gateway_ip = target_ip = 0; printf( "dSploit ArpSpoofer.\n\n" ); while( (c = getopt(argc, argv, "i:t:h?V")) != -1) { switch (c) { case 'i': iface = optarg; break; case 't': if ((target_ip = libnet_name2addr4(lnet, optarg, LIBNET_RESOLVE)) == -1) exit(1); break; default: return 1; } } argc -= optind; argv += optind; if (argc != 1) return 1; if( ( gateway_ip = libnet_name2addr4( lnet, argv[0], LIBNET_RESOLVE ) ) == -1 ) { printf( "[ERROR] Unable to resolve gateway ip.\n" ); return 1; } if( iface == NULL && (iface = pcap_lookupdev(pcap_ebuf)) == NULL ) { printf( "[ERROR] Unable to lookup network interface ( %s ).\n", pcap_ebuf ); return 1; } if( ( lnet = libnet_init(LIBNET_LINK, iface, libnet_ebuf) ) == NULL ) { printf( "[ERROR] Unable to initialize libnet ( %s ).\n", libnet_ebuf ); return 1; } signal( SIGHUP, cleanup ); signal( SIGINT, cleanup ); signal( SIGTERM, cleanup ); our_mac = ( struct ether_addr * )libnet_get_hwaddr( lnet ); if( our_mac == NULL ) { printf( "[ERROR] Unable to retrieve local hardware address libnet ( %s ).\n", libnet_geterror( lnet ) ); return 1; } if( net_get_details( iface, &netmask, &ifaddr, &nhosts ) != 0 ) exit( 1 ); printf( "netmask = %s\n", inet_ntoa( *( struct in_addr *)&netmask ) ); printf( "ifaddr = %s\n", inet_ntoa( *( struct in_addr *)&ifaddr ) ); printf( "gateway = %s\n", inet_ntoa( *( struct in_addr *)&gateway_ip ) ); printf( "hosts = %d\n", nhosts ); // force the arp cache to be populated net_wake( iface, nhosts, ifaddr, netmask, gateway_ip ); // if the target is the gateway itself, we switch to subnet mode, // otherwise if the target was set, we are in single ip spoofing mode. if( target_ip != 0 && target_ip != gateway_ip ) { if( target_ip != 0 && arp_lookup( target_ip, &target_mac, iface ) != 0 ) { printf( "[ERROR] Couldn't find a cached MAC address for %s, try to wait a little bit and then try again or restart the network discovery.\n", libnet_addr2name4(target_ip, LIBNET_DONT_RESOLVE) ); return 1; } printf( "\nSingle target mode.\n" ); while( killed == 0 ) { arp_send( lnet, ARPOP_REPLY, (unsigned char *)our_mac, gateway_ip, (unsigned char *)&target_mac, target_ip ); sleep(1); } } // whole network spoofing else { printf( "\nSubnet mode.\n" ); netmap = net_get_mapping( iface, nhosts, ifaddr, netmask, gateway_ip, &i ); if( i == 0 ) { printf( "[ERROR] No alive endpoints found.\n" ); return 1; } while( killed == 0 ) { for( i = 1; i <= nhosts && killed == 0; i++ ) { target_ip = ( ifaddr & netmask ) | htonl(i); entry = hashmapGet( netmap, (void *)target_ip ); if( entry && killed == 0 ) { arp_send( lnet, ARPOP_REPLY, (unsigned char *)our_mac, gateway_ip, (unsigned char *)&entry->mac, target_ip ); } } sleep(1); } } return 0; }
static int arp_process(struct sk_buff *skb) { struct net_device *dev = skb->dev; struct in_device *in_dev = __in_dev_get_rcu(dev); struct arphdr *arp; unsigned char *arp_ptr; struct rtable *rt; unsigned char *sha; __be32 sip, tip; u16 dev_type = dev->type; int addr_type; struct neighbour *n; struct net *net = dev_net(dev); if (in_dev == NULL) goto out; arp = arp_hdr(skb); switch (dev_type) { default: if (arp->ar_pro != htons(ETH_P_IP) || htons(dev_type) != arp->ar_hrd) goto out; break; case ARPHRD_ETHER: case ARPHRD_IEEE802_TR: case ARPHRD_FDDI: case ARPHRD_IEEE802: if ((arp->ar_hrd != htons(ARPHRD_ETHER) && arp->ar_hrd != htons(ARPHRD_IEEE802)) || arp->ar_pro != htons(ETH_P_IP)) goto out; break; case ARPHRD_AX25: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_AX25)) goto out; break; case ARPHRD_NETROM: if (arp->ar_pro != htons(AX25_P_IP) || arp->ar_hrd != htons(ARPHRD_NETROM)) goto out; break; } if (arp->ar_op != htons(ARPOP_REPLY) && arp->ar_op != htons(ARPOP_REQUEST)) goto out; arp_ptr = (unsigned char *)(arp + 1); sha = arp_ptr; arp_ptr += dev->addr_len; memcpy(&sip, arp_ptr, 4); arp_ptr += 4; arp_ptr += dev->addr_len; memcpy(&tip, arp_ptr, 4); if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) goto out; if (dev_type == ARPHRD_DLCI) sha = dev->broadcast; if (sip == 0) { if (arp->ar_op == htons(ARPOP_REQUEST) && inet_addr_type(net, tip) == RTN_LOCAL && !arp_ignore(in_dev, sip, tip)) arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev->dev_addr, sha); goto out; } if (arp->ar_op == htons(ARPOP_REQUEST) && ip_route_input_noref(skb, tip, sip, 0, dev) == 0) { rt = skb_rtable(skb); addr_type = rt->rt_type; if (addr_type == RTN_LOCAL) { int dont_send; dont_send = arp_ignore(in_dev, sip, tip); if (!dont_send && IN_DEV_ARPFILTER(in_dev)) dont_send = arp_filter(sip, tip, dev); if (!dont_send) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) { arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev->dev_addr, sha); neigh_release(n); } } goto out; } else if (IN_DEV_FORWARD(in_dev)) { if (addr_type == RTN_UNICAST && (arp_fwd_proxy(in_dev, dev, rt) || arp_fwd_pvlan(in_dev, dev, rt, sip, tip) || (rt->dst.dev != dev && pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) { n = neigh_event_ns(&arp_tbl, sha, &sip, dev); if (n) neigh_release(n); if (NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED || skb->pkt_type == PACKET_HOST || in_dev->arp_parms->proxy_delay == 0) { arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha, dev->dev_addr, sha); } else { pneigh_enqueue(&arp_tbl, in_dev->arp_parms, skb); return 0; } goto out; } } } n = __neigh_lookup(&arp_tbl, &sip, dev, 0); if (IN_DEV_ARP_ACCEPT(in_dev)) { if (n == NULL && (arp->ar_op == htons(ARPOP_REPLY) || (arp->ar_op == htons(ARPOP_REQUEST) && tip == sip)) && inet_addr_type(net, sip) == RTN_UNICAST) n = __neigh_lookup(&arp_tbl, &sip, dev, 1); } if (n) { int state = NUD_REACHABLE; int override; override = time_after(jiffies, n->updated + n->parms->locktime); if (arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST) state = NUD_STALE; neigh_update(n, sha, state, override ? NEIGH_UPDATE_F_OVERRIDE : 0); neigh_release(n); }
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { __be32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; __be32 target = *(__be32 *)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev; #ifdef CONFIG_HTC_NETWORK_CNE __be32 dev_addr = 0; dev_addr = inet_select_addr(dev, target, RT_SCOPE_LINK); #endif rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { rcu_read_unlock(); return; } switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) saddr = ip_hdr(skb)->saddr; break; case 1: if (!skb) break; saddr = ip_hdr(skb)->saddr; if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: break; } rcu_read_unlock(); if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); probes -= neigh->parms->ucast_probes; if (probes < 0) { if (!(neigh->nud_state & NUD_VALID)) printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); dst_ha = neigh->ha; read_lock_bh(&neigh->lock); } else { probes -= neigh->parms->app_probes; if (probes < 0) { #ifdef CONFIG_ARPD neigh_app_ns(neigh); #endif return; } } #ifdef CONFIG_HTC_NETWORK_CNE if (dev_addr != saddr) { printk(KERN_DEBUG "CnE detects wrong sender IP in ARP\n"); saddr = dev_addr; } #endif arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL); if (dst_ha) read_unlock_bh(&neigh->lock); }
ssize_t psock_sendto(FAR struct socket *psock, FAR const void *buf, size_t len, int flags, FAR const struct sockaddr *to, socklen_t tolen) { #ifdef CONFIG_NET_UDP FAR struct udp_conn_s *conn; #ifdef CONFIG_NET_IPv6 FAR const struct sockaddr_in6 *into = (const struct sockaddr_in6 *)to; #else FAR const struct sockaddr_in *into = (const struct sockaddr_in *)to; #endif struct sendto_s state; net_lock_t save; int ret; #endif int err; /* If to is NULL or tolen is zero, then this function is same as send (for * connected socket types) */ if (!to || !tolen) { #ifdef CONFIG_NET_TCP return psock_send(psock, buf, len, flags); #else ndbg("ERROR: No to address\n"); err = EINVAL; goto errout; #endif } /* Verify that a valid address has been provided */ #ifdef CONFIG_NET_IPv6 if (to->sa_family != AF_INET6 || tolen < sizeof(struct sockaddr_in6)) #else if (to->sa_family != AF_INET || tolen < sizeof(struct sockaddr_in)) #endif { ndbg("ERROR: Invalid address\n"); err = EBADF; goto errout; } /* Verify that the psock corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { ndbg("ERROR: Invalid socket\n"); err = EBADF; goto errout; } /* If this is a connected socket, then return EISCONN */ if (psock->s_type != SOCK_DGRAM) { ndbg("ERROR: Connected socket\n"); err = EISCONN; goto errout; } /* Make sure that the IP address mapping is in the ARP table */ #ifdef CONFIG_NET_ARP_SEND ret = arp_send(into->sin_addr.s_addr); if (ret < 0) { ndbg("ERROR: Not reachable\n"); err = ENETUNREACH; goto errout; } #endif /* Perform the UDP sendto operation */ #ifdef CONFIG_NET_UDP /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ save = net_lock(); memset(&state, 0, sizeof(struct sendto_s)); sem_init(&state.st_sem, 0, 0); state.st_buflen = len; state.st_buffer = buf; /* Set the initial time for calculating timeouts */ #ifdef CONFIG_NET_SENDTO_TIMEOUT state.st_sock = psock; state.st_time = clock_systimer(); #endif /* Setup the UDP socket */ conn = (FAR struct udp_conn_s *)psock->s_conn; ret = udp_connect(conn, into); if (ret < 0) { net_unlock(save); err = -ret; goto errout; } /* Set up the callback in the connection */ state.st_cb = udp_callback_alloc(conn); if (state.st_cb) { state.st_cb->flags = UDP_POLL; state.st_cb->priv = (void*)&state; state.st_cb->event = sendto_interrupt; /* Notify the device driver of the availabilty of TX data */ netdev_txnotify(conn->ripaddr); /* Wait for either the receive to complete or for an error/timeout to occur. * NOTES: (1) net_lockedwait will also terminate if a signal is received, (2) * interrupts may be disabled! They will be re-enabled while the task sleeps * and automatically re-enabled when the task restarts. */ net_lockedwait(&state.st_sem); /* Make sure that no further interrupts are processed */ udp_callback_free(conn, state.st_cb); } net_unlock(save); sem_destroy(&state.st_sem); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for errors */ if (state.st_sndlen < 0) { err = -state.st_sndlen; goto errout; } /* Success */ return state.st_sndlen; #else err = ENOSYS; #endif errout: set_errno(err); return ERROR; }
ssize_t net_sendfile(int outfd, struct file *infile, off_t *offset, size_t count) { FAR struct socket *psock = sockfd_socket(outfd); FAR struct tcp_conn_s *conn; struct sendfile_s state; net_lock_t save; int err; /* Verify that the sockfd corresponds to valid, allocated socket */ if (!psock || psock->s_crefs <= 0) { ndbg("ERROR: Invalid socket\n"); err = EBADF; goto errout; } /* If this is an un-connected socket, then return ENOTCONN */ if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) { ndbg("ERROR: Not connected\n"); err = ENOTCONN; goto errout; } /* Make sure that we have the IP address mapping */ conn = (FAR struct tcp_conn_s *)psock->s_conn; DEBUGASSERT(conn); #if defined(CONFIG_NET_ARP_SEND) || defined(CONFIG_NET_ICMPv6_NEIGHBOR) #ifdef CONFIG_NET_ARP_SEND #ifdef CONFIG_NET_ICMPv6_NEIGHBOR if (psock->s_domain == PF_INET) #endif { /* Make sure that the IP address mapping is in the ARP table */ ret = arp_send(conn->u.ipv4.raddr); } #endif /* CONFIG_NET_ARP_SEND */ #ifdef CONFIG_NET_ICMPv6_NEIGHBOR #ifdef CONFIG_NET_ARP_SEND else #endif { /* Make sure that the IP address mapping is in the Neighbor Table */ ret = icmpv6_neighbor(conn->u.ipv6.raddr); } #endif /* CONFIG_NET_ICMPv6_NEIGHBOR */ /* Did we successfully get the address mapping? */ if (ret < 0) { ndbg("ERROR: Not reachable\n"); err = ENETUNREACH; goto errout; } #endif /* CONFIG_NET_ARP_SEND || CONFIG_NET_ICMPv6_NEIGHBOR */ /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); /* Initialize the state structure. This is done with interrupts * disabled because we don't want anything to happen until we * are ready. */ save = net_lock(); memset(&state, 0, sizeof(struct sendfile_s)); sem_init(&state. snd_sem, 0, 0); /* Doesn't really fail */ state.snd_sock = psock; /* Socket descriptor to use */ state.snd_foffset = offset ? *offset : 0; /* Input file offset */ state.snd_flen = count; /* Number of bytes to send */ state.snd_file = infile; /* File to read from */ /* Allocate resources to receive a callback */ state.snd_datacb = tcp_callback_alloc(conn); if (state.snd_datacb == NULL) { nlldbg("Failed to allocate data callback\n"); err = ENOMEM; goto errout_locked; } state.snd_ackcb = tcp_callback_alloc(conn); if (state.snd_ackcb == NULL) { nlldbg("Failed to allocate ack callback\n"); err = ENOMEM; goto errout_datacb; } /* Get the initial sequence number that will be used */ state.snd_isn = tcp_getsequence(conn->sndseq); /* There is no outstanding, unacknowledged data after this * initial sequence number. */ conn->unacked = 0; #ifdef CONFIG_NET_SOCKOPTS /* Set the initial time for calculating timeouts */ state.snd_time = clock_systimer(); #endif /* Set up the ACK callback in the connection */ state.snd_ackcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_DISCONN_EVENTS); state.snd_ackcb->priv = (FAR void *)&state; state.snd_ackcb->event = ack_interrupt; /* Perform the TCP send operation */ do { state.snd_datacb->flags = TCP_POLL; state.snd_datacb->priv = (FAR void *)&state; state.snd_datacb->event = sendfile_interrupt; /* Notify the device driver of the availability of TX data */ sendfile_txnotify(psock, conn); net_lockedwait(&state.snd_sem); } while (state.snd_sent >= 0 && state.snd_acked < state.snd_flen); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); tcp_callback_free(conn, state.snd_ackcb); errout_datacb: tcp_callback_free(conn, state.snd_datacb); errout_locked: sem_destroy(&state. snd_sem); net_unlock(save); errout: if (err) { set_errno(err); return ERROR; } else if (state.snd_sent < 0) { set_errno(-state.snd_sent); return ERROR; } else { return state.snd_sent; } }
int main(int argc, char *argv[]) { extern char *optarg; extern int optind; char pcap_ebuf[PCAP_ERRBUF_SIZE]; char libnet_ebuf[LIBNET_ERRBUF_SIZE]; int c; int n_scan_hosts = 0; char *scan_prefix = NULL; int scan_prefix_length = 32; char *cleanup_src = NULL; in_addr_t target_addr; intf = NULL; poison_reverse = 0; poison_mesh = 0; n_hosts = 0; /* allocate enough memory for target list */ hosts = calloc( argc+1, sizeof(struct host) ); while ((c = getopt(argc, argv, "vrmi:s:t:c:h?V")) != -1) { switch (c) { case 'v': verbose = 1; break; case 'i': intf = optarg; break; case 't': target_addr = libnet_name2addr4(l, optarg, LIBNET_RESOLVE); if (target_addr == -1) { usage(); } else { host_add(target_addr, HOST_TARGET); } break; case 'r': poison_reverse = 1; break; case 'm': poison_mesh = 1; break; case 's': scan_prefix = strchr(optarg, '/'); if (scan_prefix) { *scan_prefix = '\0'; scan_prefix_length = atoi(scan_prefix+1); if (scan_prefix_length < 0 || scan_prefix_length > 32) { usage(); } } n_scan_hosts += (1<<(32-scan_prefix_length)); /* we need some more memory to store the target data */ int mem = (argc+1 + n_scan_hosts) * sizeof(struct host); hosts = realloc( hosts, mem ); hosts[n_hosts].ip = (uint32_t)0; subnet_add(inet_addr(optarg), scan_prefix_length, HOST_TARGET); break; case 'c': cleanup_src = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (!cleanup_src || strcmp(cleanup_src, "own")==0) { /* default! */ /* only use our own hw address when cleaning up, * not jeopardizing any bridges on the way to our * target */ cleanup_src_own = 1; cleanup_src_host = 0; } else if (strcmp(cleanup_src, "host")==0) { /* only use the target hw address when cleaning up; * this can screw up some bridges and scramble access * for our own host, however it resets the arp table * more reliably */ cleanup_src_own = 0; cleanup_src_host = 1; } else if (strcmp(cleanup_src, "both")==0) { cleanup_src_own = 1; cleanup_src_host = 1; } else { errx(1, "Invalid parameter to -c: use 'own' (default), 'host' or 'both'."); usage(); } while (argc--) { if ((target_addr = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1) { errx(1, "Invalid address: %s", argv[0]); usage(); } host_add(target_addr, HOST_MODEL); argv++; } if (poison_mesh) { struct host *host = hosts; for(;host->ip; host++) { host->flags |= (HOST_TARGET|HOST_MODEL); } } if (poison_reverse && active_targets() <= 0) { errx(1, "Spoofing the reverse path (-r) is only available when specifying at least one target (-t/-s)."); usage(); } if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL) errx(1, "%s", pcap_ebuf); if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL) errx(1, "%s", libnet_ebuf); fprintf(stderr, "Scanning %d hw addresses...\n", n_hosts); struct host *target = hosts; for (; target->ip; target++) { if (verbose) { fprintf(stderr, "Looking up host %s...\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); } int arp_status = arp_find(target->ip, &target->mac); if (arp_status && /* just make sure we are not getting an empty or broadcast address */ (memcmp(&target->mac, zero_ha, sizeof(struct ether_addr)) != 0) && (memcmp(&target->mac, brd_ha, sizeof(struct ether_addr)) != 0)) { target->flags |= HOST_ACTIVE; if (target->flags & HOST_SUBNET) { fprintf(stderr, "Found host in subnet %s: %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE), ether_ntoa((struct ether_addr *)&target->mac)); } } else { target->flags &= (~HOST_ACTIVE); if (! (target->flags & HOST_SUBNET)) { fprintf(stderr, "Unable to find specified host %s\n", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); } if (poison_reverse && target->flags & HOST_MODEL) { errx(1, "couldn't arp for spoof host %s", libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE)); usage(); } } } if ((my_ha = (u_int8_t *)libnet_get_hwaddr(l)) == NULL) { errx(1, "Unable to determine own mac address"); } if (active_targets() == 0) { errx(1, "No target hosts found."); } signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGTERM, cleanup); fprintf(stderr, "Starting spoofing process...\n"); for (;;) { struct host *target = hosts; for(;target->ip; target++) { if (!(target->flags & HOST_TARGET)) continue; if (!(target->flags & HOST_ACTIVE)) continue; struct host *model = hosts; for (;model->ip; model++) { if (!(model->flags & HOST_ACTIVE)) continue; if (!(model->flags & HOST_MODEL)) continue; if (target->ip != model->ip) { arp_send(l, ARPOP_REPLY, my_ha, model->ip, (target->ip ? (u_int8_t *)&target->mac : brd_ha), target->ip, my_ha); usleep(ARP_PAUSE); if (poison_reverse) { arp_send(l, ARPOP_REPLY, my_ha, target->ip, (uint8_t *)&model->mac, model->ip, my_ha); usleep(ARP_PAUSE); } } } } sleep(2); } /* NOTREACHED */ exit(0); }
int icmp_ping(in_addr_t addr, uint16_t id, uint16_t seqno, uint16_t datalen, int dsecs) { struct icmp_ping_s state; net_lock_t save; #ifdef CONFIG_NET_ARP_SEND int ret; /* Make sure that the IP address mapping is in the ARP table */ ret = arp_send(addr); if (ret < 0) { ndbg("ERROR: Not reachable\n"); return -ENETUNREACH; } #endif /* Initialize the state structure */ sem_init(&state.png_sem, 0, 0); state.png_ticks = DSEC2TICK(dsecs); /* System ticks to wait */ state.png_result = -ENOMEM; /* Assume allocation failure */ state.png_addr = addr; /* Address of the peer to be ping'ed */ state.png_id = id; /* The ID to use in the ECHO request */ state.png_seqno = seqno; /* The seqno to use in the ECHO request */ state.png_datlen = datalen; /* The length of data to send in the ECHO request */ state.png_sent = false; /* ECHO request not yet sent */ save = net_lock(); state.png_time = clock_systimer(); /* Set up the callback */ state.png_cb = icmp_callback_alloc(); if (state.png_cb) { state.png_cb->flags = (ICMP_POLL | ICMP_ECHOREPLY); state.png_cb->priv = (void*)&state; state.png_cb->event = ping_interrupt; state.png_result = -EINTR; /* Assume sem-wait interrupted by signal */ /* Notify the device driver of the availability of TX data */ #ifdef CONFIG_NETDEV_MULTINIC netdev_ipv4_txnotify(g_ipv4_allzeroaddr, state.png_addr); #else netdev_ipv4_txnotify(state.png_addr); #endif /* Wait for either the full round trip transfer to complete or * for timeout to occur. (1) net_lockedwait will also terminate if a * signal is received, (2) interrupts may be disabled! They will * be re-enabled while the task sleeps and automatically * re-enabled when the task restarts. */ nllvdbg("Start time: 0x%08x seqno: %d\n", state.png_time, seqno); net_lockedwait(&state.png_sem); icmp_callback_free(state.png_cb); } net_unlock(save); /* Return the negated error number in the event of a failure, or the * sequence number of the ECHO reply on success. */ if (!state.png_result) { nllvdbg("Return seqno=%d\n", state.png_seqno); return (int)state.png_seqno; } else { nlldbg("Return error=%d\n", -state.png_result); return state.png_result; } }
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, size_t len) { FAR struct tcp_conn_s *conn; net_lock_t save; ssize_t result = 0; int err; int ret = OK; if (!psock || psock->s_crefs <= 0) { ndbg("ERROR: Invalid socket\n"); err = EBADF; goto errout; } if (psock->s_type != SOCK_STREAM || !_SS_ISCONNECTED(psock->s_flags)) { ndbg("ERROR: Not connected\n"); err = ENOTCONN; goto errout; } /* Make sure that the IP address mapping is in the ARP table */ conn = (FAR struct tcp_conn_s *)psock->s_conn; #ifdef CONFIG_NET_ARP_SEND ret = arp_send(conn->ripaddr); if (ret < 0) { ndbg("ERROR: Not reachable\n"); err = ENETUNREACH; goto errout; } #endif /* Dump the incoming buffer */ BUF_DUMP("psock_tcp_send", buf, len); /* Set the socket state to sending */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_SEND); save = net_lock(); if (len > 0) { /* Allocate resources to receive a callback */ if (!psock->s_sndcb) { psock->s_sndcb = tcp_callback_alloc(conn); } /* Test if the callback has been allocated */ if (!psock->s_sndcb) { /* A buffer allocation error occurred */ ndbg("ERROR: Failed to allocate callback\n"); result = -ENOMEM; } else { FAR struct tcp_wrbuffer_s *wrb; /* Set up the callback in the connection */ psock->s_sndcb->flags = (TCP_ACKDATA | TCP_REXMIT | TCP_POLL | TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT); psock->s_sndcb->priv = (void*)psock; psock->s_sndcb->event = psock_send_interrupt; /* Allocate an write buffer */ wrb = tcp_wrbuffer_alloc(); if (wrb) { /* Initialize the write buffer */ WRB_SEQNO(wrb) = (unsigned)-1; WRB_NRTX(wrb) = 0; WRB_COPYIN(wrb, (FAR uint8_t *)buf, len); /* Dump I/O buffer chain */ WRB_DUMP("I/O buffer chain", wrb, WRB_PKTLEN(wrb), 0); /* psock_send_interrupt() will send data in FIFO order from the * conn->write_q */ sq_addlast(&wrb->wb_node, &conn->write_q); nvdbg("Queued WRB=%p pktlen=%u write_q(%p,%p)\n", wrb, WRB_PKTLEN(wrb), conn->write_q.head, conn->write_q.tail); /* Notify the device driver of the availability of TX data */ #ifdef CONFIG_NET_MULTILINK netdev_txnotify(conn->lipaddr, conn->ripaddr); #else netdev_txnotify(conn->ripaddr); #endif result = len; } /* A buffer allocation error occurred */ else { ndbg("ERROR: Failed to allocate write buffer\n"); result = -ENOMEM; } } } net_unlock(save); /* Set the socket state to idle */ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); /* Check for a errors. Errors are signaled by negative errno values * for the send length */ if (result < 0) { err = result; goto errout; } /* If net_lockedwait failed, then we were probably reawakened by a signal. * In this case, net_lockedwait will have set errno appropriately. */ if (ret < 0) { err = -ret; goto errout; } /* Return the number of bytes actually sent */ return result; errout: set_errno(err); return ERROR; }
//------------------------------------------------------------------------ // This handles incoming ARP messages // See "TCP/IP Illustrated, Volume 1" Sect 4.4 // Todo: Resolve problem of trying to add to a full cache //------------------------------------------------------------------------ void arp_rcve(UCHAR xdata * inbuf) { UCHAR idata i, cached, oldest; UINT idata minimum; ARP_HEADER xdata * arp; arp = (ARP_HEADER xdata *)(inbuf + 14); cached = FALSE; // Print message if (debug) { if (arp->message_type == ARP_REQUEST) serial_send("ARP: Request rcvd\r"); else serial_send("ARP: Response rcvd\r"); } // Validate incoming frame if ((arp->hardware_type != DIX_ETHERNET) || (arp->protocol_type != IP_PACKET)) return; // Search ARP cache for senders IP address // If found, update entry and restart timer for (i=0; i < CACHESIZE; i++) { if (arp_cache[i].ipaddr == arp->source_ipaddr) { memcpy(&arp_cache[i].hwaddr[0], &arp->source_hwaddr[0], 6); arp_cache[i].timer = CACHETIME; cached = TRUE; if (debug) serial_send("ARP: Cache entry updated\r"); break; } } if (arp->dest_ipaddr != my_ipaddr) return; // At this point we know the the frame is addressed to me // If not already in cache then add entry and start timer if (cached == FALSE) { // Find first blank space and add entry // Blank entries are indicated by ip addr = 0 for (i=0; i < CACHESIZE; i++) { if (arp_cache[i].ipaddr == 0) { arp_cache[i].ipaddr = arp->source_ipaddr; memcpy(&arp_cache[i].hwaddr[0], &arp->source_hwaddr[0], 6); arp_cache[i].timer = CACHETIME; if (debug) serial_send("ARP: New cache entry added\r"); break; } } // If no blank entries in arp cache then sort cache // to find oldest entry and replace it if (i == CACHESIZE) { // Oldest entry is the one with lowest timer value minimum = 0xFFFF; for (i=0; i < CACHESIZE; i++) { if (arp_cache[i].timer < minimum) { minimum = arp_cache[i].timer; oldest = i; } } // "oldest" is now index of oldest entry, so replace it arp_cache[oldest].ipaddr = arp->source_ipaddr; memcpy(&arp_cache[oldest].hwaddr[0], &arp->source_hwaddr[0], 6); arp_cache[oldest].timer = CACHETIME; if (debug) serial_send("ARP: Cache full, so replaced oldest\r"); } } // If we are waiting for an arp response and the arp response // that just came in is addressed to me and is from the host // we are waiting for, then send the message-in-waiting if (arp->message_type == ARP_RESPONSE) { if ((waiting_for_arp) && (wait.ipaddr == arp->source_ipaddr)) { waiting_for_arp = FALSE; ip_send(wait.buf, wait.ipaddr, wait.proto_id, wait.len); } } else if (arp->message_type == ARP_REQUEST) { // Send ARP response if (debug) serial_send("ARP: Sending response\r"); arp_send(arp->source_hwaddr, arp->source_ipaddr, ARP_RESPONSE); } }