简体   繁体   中英

Send a single RIPv2 datagram using UDP from and to a specific port?

I have an assignment to make a Routing Information Protocol sniffer and a program in C/C++ capable of sending custom RIP entry using the information gathered from the sniffer.

I'm running both in a school provided Ubuntu Virtualbox image, which is connected via "Internal Network" option to a BSD image running a routing daemon generating RIP traffic.

I got to the part where I need to send the custom packet to the "router" but I hit a wall when trying to send it from port 520.

From the RFC 1058 describing the RIP protocol I gathered that in order for a router to acknowledge a new route, the RIP message has to come from and to the port 520.

I can send my packet to port 520 of the router just fine, but the source port is always a random port assigned by system after my binding fails with an errno message "Cannot assign requested address".

The packet itself looks just fine in WireShark, with the exception of the source port which is for example 60818.

I am doing the following in my response program:

#define ROUTERADDR "10.0.0.1"

int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in router;
router.sin_family      = AF_INET;
router.sin_port        = htons(520);
router.sin_addr.s_addr = inet_addr(ROUTERADDR);

bind    (fd, (struct sockaddr*)&router, sizeof(router));
connect (fd, (struct sockaddr*)&router, sizeof(router));

send(fd, &payload, sizeof(payload), 0);
close(fd);

Binding to a port < 1024 requires root permission, unless you add your executable to CAP_NET_BIND_SERVICE capability as below.

setcap 'cap_net_bind_service=+ep' /path/to/executable

There is another issue in your code, where you are trying to bind to router's address. You need to bind to the specific local address or INADDR_ANY, as shown below.

struct sockaddr_in local, router;
local.sin_family = AF_INET;
local.sin_port = htons(520);
local.sin_addr.s_addr = htonl(INADDR_ANY);
bind    (fd, (struct sockaddr*)&local, sizeof(local));

router.sin_family      = AF_INET;
router.sin_port        = htons(520);
router.sin_addr.s_addr = inet_addr(ROUTERADDR);
connect (fd, (struct sockaddr*)&router, sizeof(router));

You should check the return value of your system calls, so you know when things don't work, as in your case the bind() call likely fails.

In your case bind() would fail because you try to bind to a port on the remote address you're sending to , which you cannot do.

bind() specifies the local endpoint you want to use, thus you should specify one of the local IP addresses you want to send from . Or you can bind the socket to any local address, using INADDR_ANY . so you might want to create another struct sockaddr_in and do it like this:

struct sockaddr_in my_addr;
my_addr.sin_family      = AF_INET;
my_addr.sin_port        = htons(520);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(fd, (struct sockaddr*)&my_addr, sizeof(my_addr)) != 0) {
   perror("bind() failed");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM