4343
4444#define VERSION "v0.2"
4545
46+ #define PROTOVERSION 0x13370103
47+
4648#define MTU 1600
4749
4850#define PERROR (x ) do { perror(x); exit(1); } while (0)
@@ -148,6 +150,29 @@ struct sock_fprog the_filter = {
148150 the_BPF ,
149151};
150152
153+ int sane (unsigned char x )
154+ {
155+ return ((x >= 0x20 ) && (x < 0x80 ));
156+ }
157+
158+ int hexdump (void * buf , int len )
159+ {
160+ unsigned char * b = buf ;
161+ int i ,j ;
162+
163+ for (i = 0 ; i < (len + 15 )/16 * 16 ; i ++ ) {
164+ if (i < len ) printf ("%02x " ,b [i ]); else printf (" " );
165+ if (i %8 == 7 ) printf (" " );
166+ if (i %16 == 15 ) {
167+ for (j = i - 15 ; (j < i ) && (j < len ); j ++ )
168+ printf ("%c" , sane (b [j ]) ? b [j ] : '.' );
169+ printf ("\n" );
170+ }
171+ }
172+ }
173+
174+
175+
151176void usage ()
152177{
153178 fprintf (stderr , "Usage: etherpuppet {-s port|-c targetip:port} [-B|-S|-M <arg>] [-C] -i iface\n"
@@ -160,7 +185,8 @@ void usage()
160185 "-B : do not use any BPF. Etherpuppet may see its own traffic!\n"
161186 "-S : build BPF filter with SSH_CONNECTION environment variable\n"
162187 "-M src:sp,dst:dp : BPF filter manual configuration\n"
163- "-C : don't copy real interface parameters to virtual interface\n" );
188+ "-C : don't copy real interface parameters to virtual interface\n"
189+ "-d : increase debug level (can be used more than once" );
164190 exit (0 );
165191}
166192
@@ -189,8 +215,9 @@ int main(int argc, char *argv[])
189215 struct sockaddr_in sin , sin2 ;
190216 struct sockaddr_ll sll ;
191217 struct ifreq ifr ;
192- int s , s2 , sinlen , sin2len , port , PORT , l , ifidx , m , n ;
218+ int s , s2 , sinlen , sin2len , sll_len , port , PORT , l , ifidx , m , n , v ;
193219 short int h ;
220+ short sll_hatype ;
194221 struct hostent * host ;
195222
196223 struct sigaction sa ;
@@ -208,6 +235,7 @@ int main(int argc, char *argv[])
208235
209236 int MASTER = 0 , CONFIG = 1 ;
210237 int MODE = 0 , DEBUG = 0 ;
238+ int PPP = 0 ;
211239
212240 int BPF = BPF_AUTO ;
213241
@@ -217,7 +245,7 @@ int main(int argc, char *argv[])
217245 sigaddset (& sa .sa_mask , SIGINT );
218246 sa .sa_flags = SA_SIGINFO | SA_ONESHOT | SA_RESTART ;
219247
220- while ((c = getopt (argc , argv , "ms:c:i:I:hdBSMC:v " )) != -1 ) {
248+ while ((c = getopt (argc , argv , "ms:c:i:I:hdBSMCv " )) != -1 ) {
221249 switch (c ) {
222250 case 'v' :
223251 version ();
@@ -289,6 +317,8 @@ int main(int argc, char *argv[])
289317 sin2 .sin_addr = * (struct in_addr * )host -> h_addr ;
290318 printf ("Connecting to %s:%i...\n" , inet_ntoa (sin2 .sin_addr .s_addr ), ntohs (sin2 .sin_port ));
291319 if (connect (s , (struct sockaddr * )& sin2 , sizeof (sin2 )) == -1 ) PERROR ("connect" );
320+ v = PROTOVERSION ;
321+ if (send (s , & v , sizeof (l ), 0 ) == -1 ) PERROR ("send PROTOVERSION" );
292322 }
293323 else {
294324 printf ("Waiting for connection on port %i...\n" , PORT );
@@ -298,6 +328,17 @@ int main(int argc, char *argv[])
298328 if (s2 == -1 ) PERROR ("accept" );
299329 close (s );
300330 s = s2 ;
331+ if (recv (s , & v , sizeof (l ), 0 ) == -1 ) PERROR ("recv PROTOVERSION" );
332+ if (v != PROTOVERSION )
333+ ERROR ("Protocol version mismatch local=%08x (%i.%i) remote=%08x (%i.%i)\n" ,
334+ PROTOVERSION , (PROTOVERSION >> 8 ) & 0xff , PROTOVERSION & 0xff ,
335+ v , (v >>8 )& 0xff , v & 0xff );
336+ else
337+ printf ("Protocol version ok. local=%08x (%i.%i) remote=%08x (%i.%i)\n" ,
338+ PROTOVERSION , (PROTOVERSION >> 8 ) & 0xff , PROTOVERSION & 0xff ,
339+ v , (v >>8 )& 0xff , v & 0xff );
340+
341+
301342 }
302343
303344 sinlen = sizeof (sin );
@@ -310,10 +351,29 @@ int main(int argc, char *argv[])
310351 /* Create virtual interface */
311352 if ( (s2 = open ("/dev/net/tun" ,O_RDWR )) < 0 ) PERROR ("open" );
312353
354+ l = recv (s , & sll_hatype , sizeof (sll_hatype ),0 );
355+ if (l == -1 ) PERROR ("recv linktype" );
356+ sll_hatype = ntohs (sll_hatype );
357+
358+ switch (sll_hatype ) {
359+ case 1 :
360+ printf ("Remote linktype is %i (Ethernet)\n" , sll_hatype );
361+ break ;
362+ case 512 :
363+ printf ("Remote linktype is %i (PPP)\n" , sll_hatype );
364+ PPP = 1 ;
365+ break ;
366+ default :
367+ printf ("Remote linktype %i is unknown. Using Ethernet.\n" , sll_hatype );
368+ }
369+
313370 memset (& ifr , 0 , sizeof (ifr ));
314- ifr .ifr_flags = IFF_TAP ;
371+ if (PPP )
372+ ifr .ifr_flags = IFF_TUN ;
373+ else
374+ ifr .ifr_flags = IFF_TAP ;
315375 strncpy (ifr .ifr_name , ifname_opt , IFNAMSIZ );
316- if (ioctl (s2 , TUNSETIFF , (void * )& ifr ) < 0 ) PERROR ("ioctl" );
376+ if (ioctl (s2 , TUNSETIFF , (void * )& ifr ) < 0 ) PERROR ("ioctl TUNSETIFF " );
317377 memset (ifname ,0 ,IFNAMSIZ + 1 );
318378 strncpy (ifname , ifr .ifr_name , IFNAMSIZ );
319379
@@ -403,14 +463,25 @@ int main(int argc, char *argv[])
403463
404464
405465 strncpy (ifr .ifr_name , iface , IF_NAMESIZE );
406- if (ioctl (s2 , SIOCGIFINDEX , & ifr ) == -1 ) PERROR ("ioctl" );
466+ if (ioctl (s2 , SIOCGIFINDEX , & ifr ) == -1 ) PERROR ("ioctl SIOCGIFINDEX " );
407467 ifidx = ifr .ifr_ifindex ;
408468
409469 sll .sll_family = AF_PACKET ;
410470 sll .sll_protocol = htons (ETH_P_ALL );
411471 sll .sll_ifindex = ifidx ;
412472
413473 if (bind (s2 , (struct sockaddr * )& sll , sizeof (sll )) == -1 ) PERROR ("bind" );
474+
475+ sll_len = sizeof (sll );
476+ if (getsockname (s2 , (struct sockaddr * )& sll , & sll_len ) == -1 ) PERROR ("getsockname" );
477+ printf ("Sending remote linktype: %i\n" , sll .sll_hatype );
478+ if (sll .sll_hatype == 512 ) {
479+ printf ("PPP mode\n" );
480+ PPP = 1 ;
481+ }
482+
483+ sll_hatype = htons (sll .sll_hatype );
484+ send (s , & sll_hatype , sizeof (sll_hatype ),0 );
414485 }
415486
416487
@@ -431,12 +502,13 @@ int main(int argc, char *argv[])
431502
432503
433504 /* Send interface parameters */
434- cmd = CMD_CMD | CMD_IFREQ ;
505+ cmd = htons ( CMD_CMD | CMD_IFREQ ) ;
435506 for (ireq = 0 ; ireq < sizeof (ifclone_get_ioctl )/sizeof (int ); ireq ++ ) {
436507 memset (& ifr , 0 , sizeof (ifr ));
437508 strncpy (ifr .ifr_name , iface , IFNAMSIZ );
438509 req = ifclone_set_ioctl [ireq ];
439- ioctl (s , ifclone_get_ioctl [ireq ], & ifr );
510+ if (ioctl (s , ifclone_get_ioctl [ireq ], & ifr ) == -1 )
511+ PERROR2 ("ioctl get" );
440512 send (s , & cmd , 2 , 0 );
441513 send (s , & req , 4 , 0 );
442514 if ((req != SIOCSIFHWADDR ) && (req != SIOCSIFMTU ))
@@ -454,12 +526,13 @@ int main(int argc, char *argv[])
454526 if (DEBUG ) write (1 ,">" , 1 );
455527 l = 0 ; /* BEEUUURK! */
456528 while (l < 2 ) {
457- if ((m = read (s , buf + l , 2 - l )) == -1 ) PERROR2 ("read(1) " );
529+ if ((m = read (s , buf + l , 2 - l )) == -1 ) PERROR2 ("read length " );
458530 if (m == 0 ) longjmp (env , JMP_PEERCLOSED );
459531 l += m ;
460532 }
461- n = * (short * )buf ;
462- if (DEBUG ) printf ("%i\n" ,n );
533+ n = ntohs (* (short * )buf );
534+ if (DEBUG >= 2 ) printf ("Received a %i %s\n" , n & 0x7fff ,
535+ n & 0x8000 ? "command" :"byte packet" );
463536 if (n & CMD_CMD ) { /* Command from the peer */
464537 switch (n & 0x7fff ) {
465538 case CMD_IFREQ :
@@ -468,7 +541,7 @@ int main(int argc, char *argv[])
468541 if (CONFIG ) {
469542 strncpy (ifr .ifr_name , ifname , IFNAMSIZ );
470543 if (ioctl (s , req , & ifr ) == -1 )
471- PERROR2 ("ioctl" );
544+ PERROR3 ("ioctl set " );
472545 }
473546 printf ("Configure request [%04x] %s\n" ,
474547 req , CONFIG ? "applied" : "ignored" );
@@ -478,29 +551,51 @@ int main(int argc, char *argv[])
478551 }
479552 }
480553 else { /* data */
481- if (n > MTU ) n = MTU ;
554+ if (n > MTU ) {
555+ printf ("WARNING: truncated packet (%i > %i) . This should not happen\n" , n , MTU );
556+ n = MTU ;
557+ }
482558 l = 0 ;
483559 while (l < n ) {
484- if ((m = read (s , buf + 4 + l , n - l )) == -1 ) PERROR2 ("read(2) " );
560+ if ((m = read (s , buf + 2 + l , n - l )) == -1 ) PERROR2 ("read packet data " );
485561 l += m ;
486562 }
487- if (MASTER )
488- * (short * )buf = * (short * )(buf + 16 );
489- if (write (s2 , MASTER ? buf : buf + 4 , MASTER ? n + 4 : n ) == -1 )
490- PERROR3 ("write" );
563+ if (DEBUG >= 5 ) hexdump (buf + 2 , l );
564+ if (MASTER ) {
565+ if (DEBUG >= 3 ) printf ("Protocol = %04x\n" ,ntohs (* (short * )(buf + 2 )));
566+ if (write (s2 , buf , n + 2 ) == -1 )
567+ PERROR3 ("write" );
568+ }
569+ else {
570+ bzero (& sll , sizeof (sll ));
571+ sll .sll_family = AF_PACKET ;
572+ sll .sll_protocol = * (short * )(buf + 2 ); /* htons(ntohs()) = Id */
573+ if (DEBUG >= 3 ) printf ("Protocol = %04x\n" ,ntohs (sll .sll_protocol ));
574+ sll .sll_ifindex = ifidx ;
575+ if (sendto (s2 , buf + 4 , n + 2 , 0 , (struct sockaddr * )& sll , sizeof (sll )) == -1 ) PERROR2 ("sendto" );
576+ }
491577 }
492578 }
493579 if (FD_ISSET (s2 , & readset )) {
494580 if (DEBUG ) write (1 ,"<" , 1 );
495- if ((l = read (s2 , MASTER ? buf : buf + 4 , MTU )) == -1 ) {
496- PERROR3 ("read(0)" );
497- continue ;
581+ if (MASTER ) {
582+ l = read (s2 , buf , MTU );
583+ if (l == -1 ) PERROR3 ("read" );
584+ l -= 2 ;
585+ }
586+ else {
587+ sll_len = sizeof (sll );
588+ l = recvfrom (s2 , buf + 4 , MTU , 0 , (struct sockaddr * )& sll , & sll_len );
589+ * (short * )(buf + 2 ) = sll .sll_protocol ; /* htons(ntohs()) = Id */
590+ if (DEBUG > 4 ) printf ("Protocol = %04x\n" , ntohs (sll .sll_protocol ));
591+ if (l == -1 ) PERROR3 ("recvfrom" );
592+ l += 2 ;
498593 }
499- h = MASTER ? l - 4 : l ;
594+ * ( short * ) buf = htons ( l ) ;
500595
501- if (DEBUG ) printf ( "%i\n" , h );
502- if (send ( s , ( void * ) & h , 2 , 0 ) == -1 ) PERROR2 ( "send(1)" );
503- if (send ( s , buf + 4 , h , 0 ) == -1 ) PERROR2 ( "send(2)" );
596+ if (send ( s , buf , l + 2 , 0 ) == -1 ) PERROR2 ( "send" );
597+ if (DEBUG >= 3 ) printf ( "Sending %i bytes:\n" , l );
598+ if (DEBUG >= 5 ) hexdump ( buf + 2 , l );
504599 }
505600 }
506601 case JMP_ERROR :
0 commit comments