domingo, 10 de noviembre de 2013

Talking to a router in RIP version 1 using a C program in linux part 2

Ok. I updated the programs so that it finally works.

You need to setup a permission to be able to broadcast a RIP packet (255.255.255.255 address as destination).

   int optval = 1;
int broadcastEnable=1;

if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(broadcastEnable))
            < 0)
        perror ("BROADCAST");


You also need to align the structs so that the required frame will output frame.

I created these two strcuts that will go after the UDP part:

typedef struct  {
    long ip;
    long pad;
    long pad2;
    long metric;
}__attribute__((packed, aligned(1))) route_t;

typedef struct  {
    char cmd;
    char version;
    short pad;
    short addrFamily;
    short pad2;
    route_t routes;
} __attribute__((packed, aligned(1))) rip_t;

The way to align them is this __attribute__((packed, aligned(1))) ;

Also the command line is like this: ./rawudp 1.1.1.1 1 The entry you want to use and the metric.

The checksum is defaulted to zero. It means it is disabled.

The RIP frame is available in the page 18 of : http://www.ietf.org/rfc/rfc1058.txt


/*
   Code also from Gabriel Serme

*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define LEN 512

typedef unsigned short u16;
typedef unsigned long u32;

typedef struct  {
    long ip;
    long pad;
    long pad2;
    long metric;
}__attribute__((packed, aligned(1))) route_t;

typedef struct  {
    char cmd;
    char version;
    short pad;
    short addrFamily;
    short pad2;
    route_t routes;
} __attribute__((packed, aligned(1))) rip_t;

unsigned short csum (unsigned short *buf, int nwords);




int main(int argc, char * argv[])
{


    if(argc != 3)
    {
        printf("- Usage %s <IP > <metric> \n", argv[0]);
        exit(1);
    }else{
        printf ("Arguments : \n"
                "\tip     : %s\n"
                "\tmetric : %s\n",
                argv[1], argv[2]);
    }
    int PSOURCE = 520;
    int PDEST = 520;
    char *IPADDR = argv[1];
    char *METRIC = argv[2];

    int s;
    rip_t *rip_route=malloc(sizeof(rip_t));
    route_t route1,route2;

    struct sockaddr_in daddr, saddr, answerip;
    char packet[LEN];
    /* point the iphdr to the beginning of the packet */
    struct iphdr *ip = (struct iphdr *)packet;
    struct udphdr *udp = (struct udphdr *)((void *) ip + sizeof(struct iphdr));
    struct dnshdr *dns = (struct dnshdr *)((void *) udp + sizeof(struct udphdr));

    if ((s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
        perror("error:");
        exit(EXIT_FAILURE);
    }

    daddr.sin_family = AF_INET;
    saddr.sin_family = AF_INET;
    daddr.sin_port = htons(520);
    saddr.sin_port = htons(520);
    saddr.sin_addr.s_addr=inet_addr("192.168.1.104");
daddr.sin_addr.s_addr=inet_addr("192.168.1.105");
    //inet_pton(AF_INET, SOURCE, (struct in_addr *)&saddr.sin_addr);
//inet_pton(AF_INET, DEST,   (struct in_addr *)&daddr.sin_addr);
   

    ip->ihl = 5; //header length
    ip->version = 4;
    ip->tos = 0x0;
    ip->id = htons(31337 + (rand()%100));;
    ip->frag_off = 0; /* No fragmentattion */
    ip->ttl = 255; /* default value */
    ip->protocol = 17; //IPPROTO_RAW; /* protocol at L4 */
    ip->check = 0; /* not needed in iphdr */
    ip->saddr = saddr.sin_addr.s_addr;
    ip->daddr = daddr.sin_addr.s_addr;

    udp->source = htons(PSOURCE);
    udp->dest = htons (PDEST);

    route1.ip=inet_addr(IPADDR);
    route1.pad=0;
    route1.pad2=0;
    route1.metric=htonl(atoi(METRIC));



//http://www.ietf.org/rfc/rfc1058.txt page 18
rip_route->cmd=2;
rip_route->version=1;
rip_route->pad=0;
rip_route->addrFamily=htons(AF_INET);
rip_route->pad2=0;
rip_route->routes=route1;

    int sizedata = sizeof(rip_t);
    memcpy(((void *) udp) + sizeof(struct udphdr), rip_route, sizedata);

    int sizeudpdata = sizeof(struct udphdr) + sizedata;
    ip->tot_len = htons(sizeudpdata + sizeof(struct iphdr)); /* 16 byte value */
    udp->len = htons(sizeudpdata);
    udp->check = 0;

   int optval = 1;
int broadcastEnable=1;

if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(broadcastEnable))
            < 0)
        perror ("BROADCAST");
        int sizepacket = sizeof(struct iphdr) + sizeudpdata;
        if (sendto(s, (char *)packet, sizepacket, 0, (struct sockaddr *)&daddr, (socklen_t)sizeof(daddr)) < 0)
            perror("packet send error:");
        else
            printf("Sent packet\n");
       
    exit(EXIT_SUCCESS);
}

/* Not my code */
unsigned short csum (unsigned short *buf, int nwords)
{
    unsigned long sum;

    for (sum = 0; nwords > 0; nwords--)
        sum += *buf++;

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);
    return ~sum;
}

I changed my ip addresses. The router config is like this:

Building configuration...                                                      
                                                                               
Current configuration:                                                        
!                                                                              
version 12.1                                                                  
service timestamps debug uptime                                                
service timestamps log uptime                                                  
no service password-encryption                                                
!                                                                              
hostname Router                                                                
!                                                                              
                                   
!                                                                              
!                                                                              
!                                                                              
!                                                                              
!                                                                              
ip subnet-zero                                                                
!                                                                              
!                                                                              
!                                                                              
interface Loopback0                                                            
 ip address 10.10.10.10 255.255.255.0                                          
 no ip split-horizon                                                          
!                                                                              
interface Ethernet0                                                            
 ip address 192.168.1.105 255.255.255.0                                        
!                                                                              
interface Ethernet1                                                            
 ip address 1.2.3.4 255.255.255.0                                              
!                                                                              
interface Serial0                                                              
 no ip address                                                                
 shutdown                                                                      
!                                                                              
interface Serial1                                                              
 no ip address                                                                
 shutdown                                                                      
!                                                                              
router rip                                                                    
 version 1                                                                    
 no validate-update-source                                                    
 network 10.0.0.0                                                              
 network 192.168.1.0                                                          
 network 192.168.2.0                                                          
!                                                                              
ip classless                                                                  
no ip http server                                                              
!                                                                              
!                                                                              
!                                                                              
line con 0                                                                    
 transport input none                                                          
line aux 0                                                                    
line vty 0 4                                                                  
                                                         
 login                                                                        
!                                                                              
end

Running the program:  ./rawudp 1.1.1.1 1

Will produce:
05:23:27: RIP: received v1 update from 192.168.1.104 on Ethernet0               
05:23:27:      1.1.1.1 in 1 hops                                                
05:23:30: RIP: sending v1 update to 255.255.255.255 via Ethernet0 (192.168.1.10)
05:23:30: RIP: build update entries                                             
05:23:30:       network 1.0.0.0 metric 2                                        
05:23:30:       network 10.0.0.0 metric 1 

You need to do a 

Router#debug ip rip                                                             
RIP protocol debugging is on 


No hay comentarios:

Publicar un comentario