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