Permalink
Browse files

linux support

  • Loading branch information...
1 parent 50f5561 commit 13f5d49d4298bdaa09d3b0c3112c2a5af33870b8 @postwait committed Apr 6, 2013
Showing with 353 additions and 1 deletion.
  1. +0 −1 IFEheader.h
  2. +88 −0 arpcache-proc.cc
  3. +265 −0 ife-sockpacket.cc
View
@@ -4,7 +4,6 @@
#include <node_object_wrap.h>
#include <v8.h>
-#include <sys/dtrace.h>
#include <sys/types.h>
#include <sys/mman.h>
View
@@ -0,0 +1,88 @@
+/* Copyright (c) 1995, Theo Schlossnagle. All rights reserved. */
+/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
+
+#include "ife.h"
+#include "ife-icmp-support.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <netinet/if_ether.h>
+
+static int arpcache_psize = 0;
+static arp_entry *arpcache_private = NULL;
+
+const unsigned char ff_ff_ff_ff_ff_ff[ETH_ALEN] =
+ { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+
+int sample_arp_cache(arp_entry **l)
+{
+ char line[200];
+ char ip[100];
+ int hw_type, flags;
+ char hw_address[100]; /* MAC address */
+ char mask[100];
+ char device[100];
+ FILE *fp;
+ int num,count=0;
+ int tmp_size;
+
+ if(l) *l = NULL;
+ /* read the arp cache entries from the kernel via /proc */
+ if ((fp = fopen("/proc/net/arp", "r")) == NULL) {
+ return -1;
+ }
+
+ /* start with the assumption that the old size is the new size */
+ tmp_size = arpcache_psize;
+
+ if (fgets(line, sizeof(line), fp) != (char *) NULL){ /* skip first line */
+ strcpy(mask, "-");
+ strcpy(device, "-");
+
+ /* read cache entries line by line */
+ for ( count=0; fgets(line, sizeof(line), fp);){
+ unsigned int *h, hint[ETH_ALEN];
+ num = sscanf(line, "%s 0x%x 0x%x %100s %100s %100s",
+ ip, &hw_type, &flags, hw_address, mask, device);
+ if (num < 6)
+ break;
+
+ if( count+1 > tmp_size ){
+ if( tmp_size > 0 ){
+ tmp_size *= 2;
+ arpcache_private = (arp_entry *)realloc(arpcache_private,
+ sizeof(arp_entry)*(tmp_size+1));
+ } else {
+ tmp_size = 2;
+ arpcache_private = (arp_entry *)malloc(sizeof(arp_entry)*(tmp_size+1));
+ }
+ }
+ arpcache_private[count].ipaddr.s_addr = inet_addr( ip );
+ h = hint;
+ sscanf(hw_address, "%02x:%02x:%02x:%02x:%02x:%02x",
+ h, h+1, h+2, h+3, h+4, h+5);
+ memcpy(arpcache_private[count].mac, hint, ETH_ALEN);
+ count++;
+ }
+ }
+
+ if( count == 0 ){
+ if(arpcache_private) free(arpcache_private);
+ arpcache_psize = 0;
+ arpcache_private = (arp_entry *)malloc(sizeof(arp_entry));
+ arpcache_private[0].ipaddr.s_addr = 0;
+ } else {
+ arpcache_psize = count;
+ arpcache_private[count].ipaddr.s_addr = 0;
+ }
+ fclose(fp);
+ if(l) *l = arpcache_private;
+ return count;
+}
View
@@ -0,0 +1,265 @@
+/* Copyright (c) 1995, Theo Schlossnagle. All rights reserved. */
+/* Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. */
+
+#include "ife.h"
+#include "ife-icmp-support.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <netinet/if_ether.h>
+
+static int _if_sock=-1;
+static char _if_error_none[] = "";
+static char _if_error_exists[] = "IP alias exists";
+static char _if_error_noneleft[] = "To many VIPs";
+static char _if_error_setip[] = "ioctl error setting IP address";
+static char _if_error_setbroadcast[] = "ioctl error setting broadcast";
+static char _if_error_setnetmask[] = "ioctl error setting netmask";
+static char _if_error_setrunning[] = "ioctl error running|stopping interface";
+static char _if_error_nosuchinterface[] = "No such interface";
+static char _if_error_illegalinterface[] = "Illegal interface";
+static char *_if_error=_if_error_none;
+
+int if_initialize() {
+ if((_if_sock = socket (AF_INET, SOCK_PACKET, htons(ETH_P_RARP))) == -1) {
+ return -1;
+ }
+ return 0;
+}
+char *if_error() {
+ return _if_error;
+}
+
+int
+if_send_spoof_request(const char *dev,
+ unsigned int new_ip, unsigned int r_ip,
+ const unsigned char *remote_mac,
+ int count,int icmp) {
+ int i;
+ struct ifreq ifr;
+ struct sockaddr iface;
+ struct ethhdr *eth;
+ struct arphdr *arp;
+ unsigned char *cp, *dest_mac;
+ static unsigned char buffer[60];
+ static unsigned char my_mac[ETH_ALEN];
+ static unsigned char bc_mac[ETH_ALEN] =
+ {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ);
+ if(ioctl(_if_sock, SIOCGIFHWADDR, &ifr) == -1) {
+ return 0;
+ }
+ memcpy(my_mac, &((struct sockaddr *)&ifr.ifr_hwaddr)->sa_data, ETH_ALEN);
+ memset(buffer, 0, 60);
+ eth = (struct ethhdr *)buffer;
+ memcpy(eth->h_source, my_mac, ETH_ALEN);
+ memcpy(eth->h_dest, bc_mac, ETH_ALEN);
+ eth->h_proto = htons(ETH_P_ARP);
+ arp = (struct arphdr *)(eth+1);
+ arp->ar_hrd = htons(ARPHRD_ETHER);
+ arp->ar_pro = htons(ETH_P_IP);
+ arp->ar_hln = ETH_ALEN;
+ arp->ar_pln = 4;
+ arp->ar_op = htons(ARPOP_REPLY);
+ cp = (unsigned char *)(arp+1);
+ memcpy(cp, my_mac, ETH_ALEN); cp+=ETH_ALEN;
+ memcpy(cp, &new_ip, 4); cp+=4;
+ dest_mac = cp;
+ memcpy(cp, bc_mac, ETH_ALEN); cp+=ETH_ALEN;
+ memcpy(cp, &r_ip, 4); cp+=4;
+ memset(&iface, 0, sizeof(struct sockaddr));
+ strncpy(iface.sa_data, dev, sizeof(iface.sa_data));
+
+ for(i=0;i<count;i++)
+ sendto(_if_sock, buffer, 60, 0, (struct sockaddr *)&iface, sizeof(iface));
+
+ if(remote_mac) {
+ memcpy(dest_mac, remote_mac, ETH_ALEN);
+ memcpy(eth->h_dest, remote_mac, ETH_ALEN);
+ for(i=0;i<count;i++)
+ sendto(_if_sock, buffer, 60, 0, (struct sockaddr *)&iface, sizeof(iface));
+ if (icmp) {
+ compose_ping(buffer, my_mac, remote_mac, new_ip, r_ip);
+ sendto(_if_sock, buffer, 42, 0,
+ (struct sockaddr *)&iface, sizeof(iface));
+ }
+ }
+ return i;
+}
+int
+if_list_ips(struct interface *ifs,
+ int size) {
+ int count=0;
+ struct ifconf d;
+ struct ifreq *ifr, *end, *cur, *temp;
+ struct in_addr ipaddr;
+ char buffer[128];
+
+ /* temporary storage for getting broadcast address */
+ temp= (struct ifreq *)buffer;
+
+ d.ifc_len= 4096;
+ d.ifc_buf= (char *)malloc (d.ifc_len);
+ if(ioctl (_if_sock, SIOCGIFCONF, &d) == -1) {
+ free(d.ifc_buf);
+ return 0;
+ }
+
+ ifr=(struct ifreq *)d.ifc_req;
+ end=(struct ifreq *)((char *) ifr + d.ifc_len);
+ while((ifr<end) && (count<size)) {
+ cur= ifr;
+ ifr=(struct ifreq *)((char *)&ifr[1]);
+ if(cur->ifr_addr.sa_family != AF_INET)
+ continue;
+ memcpy(&ipaddr, &(((struct sockaddr_in *)&cur->ifr_addr)->sin_addr),
+ sizeof(struct in_addr));
+ memcpy(temp, cur, sizeof(struct ifreq));
+ if(ioctl (_if_sock, SIOCGIFFLAGS, (char *) cur) < 0)
+ continue;
+ if((cur->ifr_flags & IFF_UP) && (cur->ifr_flags & IFF_BROADCAST)) {
+ memcpy(&ifs[count].ipaddr, &ipaddr, sizeof(struct in_addr));
+ if(ioctl(_if_sock, SIOCGIFBRDADDR, (char *)temp) != -1)
+ memcpy(&ifs[count].bcast,
+ &(((struct sockaddr_in *)&temp->ifr_addr)->sin_addr),
+ sizeof(struct in_addr));
+ if(ioctl(_if_sock, SIOCGIFNETMASK, (char *)temp) != -1)
+ memcpy(&ifs[count].netmask,
+ &(((struct sockaddr_in *)&temp->ifr_addr)->sin_addr),
+ sizeof(struct in_addr));
+ strncpy(ifs[count].ifname, cur->ifr_ifrn.ifrn_name, IFNAMSIZ);
+ count++;
+ }
+ }
+ free(d.ifc_buf);
+ return count;
+}
+
+int
+if_down(struct interface *areq) {
+ int ic, i, iname, ipaddr, inamlen;
+ struct ifreq ifr;
+ struct interface ifs[1024];
+
+ ic = if_list_ips(ifs, 1024);
+ if(!areq->ifname[0] && !areq->ipaddr.s_addr) {
+ _if_error = _if_error_illegalinterface;
+ return -1;
+ }
+ inamlen = strlen(areq->ifname);
+ for(i=0;i<1024;i++) {
+ iname=ipaddr=0;
+ if(!areq->ifname[0] ||
+ (!strncmp(areq->ifname, ifs[i].ifname, inamlen) &&
+ (ifs[i].ifname[inamlen]==':' || ifs[i].ifname[inamlen]=='\0')))
+ iname=1;
+ if((areq->ipaddr.s_addr==0) ||
+ (areq->ipaddr.s_addr==ifs[i].ipaddr.s_addr))
+ ipaddr=1;
+ if(iname && ipaddr) {
+ strcpy(ifr.ifr_name, ifs[i].ifname);
+ if(ioctl(_if_sock, SIOCGIFFLAGS, (char *)&ifr) > -1) {
+ ifr.ifr_flags &= ~(IFF_RUNNING | IFF_UP);
+ if(ioctl(_if_sock, SIOCSIFFLAGS, (char *)&ifr) > -1) {
+ _if_error=_if_error_none;
+ memcpy(areq, &ifs[i], sizeof(struct interface));
+ return 0;
+ }
+ _if_error = _if_error_setrunning;
+ return -1;
+ }
+ }
+ }
+ _if_error = _if_error_nosuchinterface;
+ return -1;
+}
+
+int
+if_up(struct interface *areq) {
+ int i, ic, ifnamsiz;
+ int vin[1024];
+ struct ifreq ifr, ifq;
+ struct interface ifs[1024];
+ struct interface realreq;
+
+ memcpy(&realreq, areq, sizeof(struct interface));
+ realreq.ifname[0]='\0';
+ vin[0]=-1; /* Linux screws up if you down ethx:0 */
+ for(i=1;i<1024;i++) vin[i]=i;
+ ic = if_list_ips(ifs, 1024);
+ ifnamsiz = strlen(areq->ifname);
+ for(i=0; i<ic; i++) {
+ if(!memcmp(&ifs[i].ipaddr, &(areq->ipaddr), sizeof(struct in_addr))) {
+ _if_error = _if_error_exists;
+ return 1;
+ }
+ if(!strncmp(ifs[i].ifname, areq->ifname, ifnamsiz)) {
+ if(ifs[i].ifname[ifnamsiz] == '\0') {
+ snprintf(realreq.ifname, IFNAMSIZ, "%s:%d", areq->ifname, 0);
+ } else {
+ if(ifs[i].ifname[ifnamsiz] == ':') {
+ int tvin;
+ tvin = atoi(ifs[i].ifname + ifnamsiz + 1);
+ vin[tvin]=-1;
+ }
+ }
+ }
+ }
+ if(realreq.ifname[0] == '\0') {
+ /* Nobody is here */
+ memcpy(realreq.ifname, areq->ifname, IFNAMSIZ);
+ } else {
+ i=0;
+ while(vin[i]==-1)
+ i++;
+ if(i>1023) {
+ _if_error = _if_error_noneleft;
+ return -i;
+ }
+ snprintf(realreq.ifname, IFNAMSIZ, "%s:%d", areq->ifname, vin[i]);
+ memcpy(areq->ifname, realreq.ifname, IFNAMSIZ);
+ }
+ memcpy(ifr.ifr_name, realreq.ifname, IFNAMSIZ);
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr =
+ areq->ipaddr.s_addr;
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_port = 0;
+
+ if(ioctl( _if_sock, SIOCSIFADDR, (char *)&ifr) != -1) {
+ memcpy(ifq.ifr_name, realreq.ifname, IFNAMSIZ);
+ if(ioctl( _if_sock, SIOCGIFFLAGS, (char *)&ifq) != -1) {
+ if(ifq.ifr_flags & IFF_RUNNING) {
+ ifr.ifr_flags = ifq.ifr_flags | IFF_UP;
+ if(ioctl( _if_sock, SIOCSIFFLAGS, (char *)&ifr) != -1) {
+ ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_addr.s_addr =
+ areq->bcast.s_addr;
+ ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&ifr.ifr_broadaddr)->sin_port = 0;
+ if(ioctl( _if_sock, SIOCSIFBRDADDR, (char *)&ifr) != -1) {
+ ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr =
+ areq->netmask.s_addr;
+ ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_port = 0;
+ if(ioctl( _if_sock, SIOCSIFNETMASK, (char *)&ifr) != -1) {
+ ifr.ifr_flags = ifq.ifr_flags | IFF_BROADCAST;
+ if(ioctl( _if_sock, SIOCSIFFLAGS, (char *)&ifr) != -1) {
+ return 0;
+ }
+ } else {
+ _if_error = _if_error_setnetmask;
+ }
+ } else {
+ _if_error = _if_error_setbroadcast;
+ }
+ } else {
+ _if_error = _if_error_setrunning;
+ }
+ }
+ }
+ } else {
+ _if_error = _if_error_setip;
+ }
+ return -1;
+}

0 comments on commit 13f5d49

Please sign in to comment.