4
* Copyright (c) 2000 Dug Song <dugsong@monkey.org>
6
* $Id: route-linux.c,v 1.12 2002/02/08 07:41:04 dugsong Exp $
11
#include <sys/types.h>
12
#include <sys/ioctl.h>
13
#include <sys/socket.h>
16
#include <asm/types.h>
17
#include <linux/netlink.h>
18
#include <linux/rtnetlink.h>
20
#include <net/route.h>
31
#define PROC_ROUTE_FILE "/proc/net/route"
41
struct sockaddr_nl snl;
44
if ((r = calloc(1, sizeof(*r))) == NULL)
47
if ((r->fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
48
return (route_close(r));
50
if ((r->nlfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) < 0)
51
return (route_close(r));
53
memset(&snl, 0, sizeof(snl));
54
snl.nl_family = AF_NETLINK;
56
if (bind(r->nlfd, (struct sockaddr *)&snl, sizeof(snl)) < 0)
57
return (route_close(r));
63
route_add(route_t *r, const struct route_entry *entry)
67
memset(&rt, 0, sizeof(rt));
69
if (addr_ntos(&entry->route_dst, &rt.rt_dst) < 0 ||
70
addr_ntos(&entry->route_gw, &rt.rt_gateway) < 0)
73
if (entry->route_dst.addr_bits < IP_ADDR_BITS) {
74
rt.rt_flags = RTF_UP | RTF_GATEWAY;
75
if (addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
78
rt.rt_flags = RTF_UP | RTF_HOST | RTF_GATEWAY;
79
addr_btos(IP_ADDR_BITS, &rt.rt_genmask);
81
return (ioctl(r->fd, SIOCADDRT, &rt));
85
route_delete(route_t *r, const struct route_entry *entry)
89
memset(&rt, 0, sizeof(rt));
91
if (addr_ntos(&entry->route_dst, &rt.rt_dst) < 0)
94
if (entry->route_dst.addr_bits < IP_ADDR_BITS) {
96
if (addr_btos(entry->route_dst.addr_bits, &rt.rt_genmask) < 0)
99
rt.rt_flags = RTF_UP | RTF_HOST;
100
addr_btos(IP_ADDR_BITS, &rt.rt_genmask);
102
return (ioctl(r->fd, SIOCDELRT, &rt));
106
route_get(route_t *r, struct route_entry *entry)
109
struct nlmsghdr *nmsg;
112
struct sockaddr_nl snl;
118
if (entry->route_dst.addr_type != ADDR_TYPE_IP) {
122
memset(buf, 0, sizeof(buf));
124
nmsg = (struct nlmsghdr *)buf;
125
nmsg->nlmsg_len = NLMSG_LENGTH(sizeof(*nmsg)) +
126
RTA_LENGTH(IP_ADDR_LEN);
127
nmsg->nlmsg_flags = NLM_F_REQUEST;
128
nmsg->nlmsg_type = RTM_GETROUTE;
129
nmsg->nlmsg_seq = ++seq;
131
rmsg = (struct rtmsg *)(nmsg + 1);
132
rmsg->rtm_family = AF_INET;
133
rmsg->rtm_dst_len = entry->route_dst.addr_bits;
136
rta->rta_type = RTA_DST;
137
rta->rta_len = RTA_LENGTH(IP_ADDR_LEN);
139
/* XXX - gross hack for default route */
140
if (entry->route_dst.addr_ip == IP_ADDR_ANY) {
141
i = htonl(0x60060606);
142
memcpy(RTA_DATA(rta), &i, IP_ADDR_LEN);
144
memcpy(RTA_DATA(rta), &entry->route_dst.addr_ip, IP_ADDR_LEN);
146
memset(&snl, 0, sizeof(snl));
147
snl.nl_family = AF_NETLINK;
150
iov.iov_len = nmsg->nlmsg_len;
152
memset(&msg, 0, sizeof(msg));
154
msg.msg_namelen = sizeof(snl);
158
if (sendmsg(r->nlfd, &msg, 0) < 0)
162
iov.iov_len = sizeof(buf);
164
if ((i = recvmsg(r->nlfd, &msg, 0)) <= 0)
167
if (nmsg->nlmsg_len < sizeof(*nmsg) || nmsg->nlmsg_len > i ||
168
nmsg->nlmsg_seq != seq) {
172
if (nmsg->nlmsg_type == NLMSG_ERROR)
175
i -= NLMSG_LENGTH(sizeof(*nmsg));
177
while (RTA_OK(rta, i)) {
178
if (rta->rta_type == RTA_GATEWAY) {
179
entry->route_gw.addr_type = ADDR_TYPE_IP;
180
memcpy(&entry->route_gw.addr_ip,
181
RTA_DATA(rta), IP_ADDR_LEN);
182
entry->route_gw.addr_bits = IP_ADDR_BITS;
185
rta = RTA_NEXT(rta, i);
193
route_loop(route_t *r, route_handler callback, void *arg)
196
char buf[BUFSIZ], ifbuf[16];
197
int i, iflags, refcnt, use, metric, mss, win, irtt, ret;
198
struct route_entry entry;
201
entry.route_dst.addr_type = entry.route_gw.addr_type = ADDR_TYPE_IP;
202
entry.route_dst.addr_bits = entry.route_gw.addr_bits = IP_ADDR_BITS;
204
if ((fp = fopen(PROC_ROUTE_FILE, "r")) == NULL)
208
while (fgets(buf, sizeof(buf), fp) != NULL) {
210
"%16s %X %X %X %d %d %d %X %d %d %d\n",
211
ifbuf, &entry.route_dst.addr_ip, &entry.route_gw.addr_ip,
212
&iflags, &refcnt, &use, &metric, &mask, &mss, &win, &irtt);
214
if (i < 10 || !(iflags & RTF_UP))
217
if (entry.route_gw.addr_ip == IP_ADDR_ANY)
220
entry.route_dst.addr_type = entry.route_gw.addr_type =
223
if (addr_mtob(&mask, IP_ADDR_LEN,
224
&entry.route_dst.addr_bits) < 0)
227
if ((ret = callback(&entry, arg)) != 0)
240
route_close(route_t *r)