35c135a0a2ae77f1563bcab5600e46792057254c
1 /* strongSwan IPsec interfaces management
2 * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security
3 * 2009 Heiko Hund - Astaro AG
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 #include <constants.h>
27 #include "interfaces.h"
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <linux/rtnetlink.h>
35 #ifdef HAVE_SYS_SOCKIO_H
36 #include <sys/sockio.h>
40 * Get the default route information via rtnetlink
43 get_defaultroute(defaultroute_t
*defaultroute
)
54 uint32_t best_metric
= ~0;
58 memset(&rtu
, 0, sizeof(rtu
));
59 rtu
.m
.nh
.nlmsg_len
= NLMSG_LENGTH(sizeof(rtu
.m
.rt
));
60 rtu
.m
.nh
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
61 rtu
.m
.nh
.nlmsg_type
= RTM_GETROUTE
;
62 rtu
.m
.rt
.rtm_family
= AF_INET
;
63 rtu
.m
.rt
.rtm_table
= RT_TABLE_UNSPEC
;
64 rtu
.m
.rt
.rtm_protocol
= RTPROT_UNSPEC
;
65 rtu
.m
.rt
.rtm_type
= RTN_UNICAST
;
67 fd
= socket(AF_NETLINK
, SOCK_DGRAM
, NETLINK_ROUTE
);
70 plog("could not create rtnetlink socket");
74 if (send(fd
, &rtu
, rtu
.m
.nh
.nlmsg_len
, 0) == -1)
76 plog("could not write to rtnetlink socket");
81 msglen
= recv(fd
, &rtu
, sizeof(rtu
), MSG_WAITALL
);
84 plog("could not read from rtnetlink socket");
91 for (nh
= &rtu
.m
.nh
; NLMSG_OK(nh
, msglen
); nh
= NLMSG_NEXT(nh
, msglen
))
95 uint32_t rtalen
, metric
= 0;
96 struct in_addr gw
= { .s_addr
= INADDR_ANY
};
99 if (nh
->nlmsg_type
== NLMSG_ERROR
)
101 plog("error from rtnetlink");
105 if (nh
->nlmsg_type
== NLMSG_DONE
)
109 if ( rt
->rtm_dst_len
!= 0
110 || (rt
->rtm_table
!= RT_TABLE_MAIN
111 && rt
->rtm_table
!= RT_TABLE_DEFAULT
) )
115 rtalen
= RTM_PAYLOAD(nh
);
116 while ( RTA_OK(rta
, rtalen
) )
118 switch (rta
->rta_type
)
121 gw
= *(struct in_addr
*) RTA_DATA(rta
);
124 iface_idx
= *(int *) RTA_DATA(rta
);
127 metric
= *(uint32_t *) RTA_DATA(rta
);
130 rta
= RTA_NEXT(rta
, rtalen
);
133 if (metric
< best_metric
138 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
141 plog("could not open AF_INET socket");
144 memset(&req
, 0, sizeof(req
));
145 req
.ifr_ifindex
= iface_idx
;
146 if (ioctl(fd
, SIOCGIFNAME
, &req
) < 0 ||
147 ioctl(fd
, SIOCGIFADDR
, &req
) < 0)
149 plog("could not read interface data, ignoring route");
154 strncpy(defaultroute
->iface
, req
.ifr_name
, IFNAMSIZ
);
155 defaultroute
->iface
[IFNAMSIZ
-1] = '\0';
156 defaultroute
->addr
.u
.v4
= *((struct sockaddr_in
*) &req
.ifr_addr
);
157 defaultroute
->nexthop
.u
.v4
.sin_family
= AF_INET
;
159 if (gw
.s_addr
== INADDR_ANY
)
161 if (ioctl(fd
, SIOCGIFDSTADDR
, &req
) < 0 ||
162 ((struct sockaddr_in
*) &req
.ifr_dstaddr
)->sin_addr
.s_addr
== INADDR_ANY
)
164 DBG_log("Ignoring default route to device %s because we can't get it's destination",
170 defaultroute
->nexthop
.u
.v4
= *((struct sockaddr_in
*) &req
.ifr_dstaddr
);
173 defaultroute
->nexthop
.u
.v4
.sin_addr
= gw
;
180 addrtot(&defaultroute
->addr
, 0, addr
, sizeof(addr
));
181 addrtot(&defaultroute
->nexthop
, 0, nexthop
, sizeof(nexthop
));
184 ( !defaultroute
->defined
185 ?
"Default route found: iface=%s, addr=%s, nexthop=%s"
186 : "Better default route: iface=%s, addr=%s, nexthop=%s"
187 ), defaultroute
->iface
, addr
, nexthop
191 best_metric
= metric
;
192 defaultroute
->defined
= TRUE
;
195 defaultroute
->supported
= TRUE
;
197 if (!defaultroute
->defined
)
198 plog("no default route - cannot cope with %%defaultroute!!!");
201 #else /* !START_PLUTO */
204 * Pluto disabled, fall back to %any
207 get_defaultroute(defaultroute_t
*defaultroute
)
209 defaultroute
->supported
= FALSE
;
211 #endif /* START_PLUTO */