#include <sys/ioctl.h>
#include <net/if.h>
-#if defined(__FreeBSD__) && __FreeBSD__ >= 3
#include <net/if_var.h>
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
#include <netinet/in.h>
#include <netinet6/in6_var.h>
-#endif
#include <net/route.h>
#include <stdlib.h>
#include <ifaddrs.h>
#include <net/if.h>
#endif
+#include <fcntl.h>
#include "var.h"
#include "misc.h"
#include "gcmalloc.h"
#include "nattraversal.h"
-#ifdef __linux__
-#include <linux/types.h>
-#include <linux/rtnetlink.h>
-#ifndef HAVE_GETIFADDRS
-#define HAVE_GETIFADDRS
-#define NEED_LINUX_GETIFADDRS
-#endif
-#endif
-
#ifndef HAVE_GETIFADDRS
static unsigned int if_maxindex __P((void));
#endif
static int suitable_ifaddr6 __P((const char *, const struct sockaddr *));
#endif
-#ifdef NEED_LINUX_GETIFADDRS
-
-/* We could do this _much_ better. kame racoon in its current form
- * will esentially die at frequent changes of address configuration.
- */
-
-struct ifaddrs
-{
- struct ifaddrs *ifa_next;
- char ifa_name[16];
- int ifa_ifindex;
- struct sockaddr *ifa_addr;
- struct sockaddr_storage ifa_addrbuf;
-};
-
-static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len)
-{
- while (RTA_OK(rta, len)) {
- if (rta->rta_type <= max)
- tb[rta->rta_type] = rta;
- rta = RTA_NEXT(rta,len);
- }
- return 0;
-}
-
-static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
-{
- char buf[8192];
- struct sockaddr_nl nladdr;
- struct iovec iov = { buf, sizeof(buf) };
- struct ifaddrmsg *m;
- struct rtattr * rta_tb[IFA_MAX+1];
- struct ifaddrs *I;
-
- while (1) {
- int status;
- struct nlmsghdr *h;
-
- struct msghdr msg = {
- (void*)&nladdr, sizeof(nladdr),
- &iov, 1,
- NULL, 0,
- 0
- };
-
- status = recvmsg(fd, &msg, 0);
-
- if (status < 0)
- continue;
-
- if (status == 0)
- return;
-
- if (nladdr.nl_pid) /* Message not from kernel */
- continue;
-
- h = (struct nlmsghdr*)buf;
- while (NLMSG_OK(h, status)) {
- if (h->nlmsg_seq != seq)
- goto skip_it;
-
- if (h->nlmsg_type == NLMSG_DONE)
- return;
-
- if (h->nlmsg_type == NLMSG_ERROR)
- return;
-
- if (h->nlmsg_type != RTM_NEWADDR)
- goto skip_it;
-
- m = NLMSG_DATA(h);
-
- if (m->ifa_family != AF_INET &&
- m->ifa_family != AF_INET6)
- goto skip_it;
-
- if (m->ifa_flags&IFA_F_TENTATIVE)
- goto skip_it;
-
- memset(rta_tb, 0, sizeof(rta_tb));
- parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));
-
- if (rta_tb[IFA_LOCAL] == NULL)
- rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
- if (rta_tb[IFA_LOCAL] == NULL)
- goto skip_it;
-
- I = malloc(sizeof(struct ifaddrs));
- if (!I)
- return;
- memset(I, 0, sizeof(*I));
-
- I->ifa_ifindex = m->ifa_index;
- I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
- I->ifa_addr->sa_family = m->ifa_family;
- if (m->ifa_family == AF_INET) {
- struct sockaddr_in *sin = (void*)I->ifa_addr;
- memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
- } else {
- struct sockaddr_in6 *sin = (void*)I->ifa_addr;
- memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
- if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
- sin->sin6_scope_id = I->ifa_ifindex;
- }
- I->ifa_next = *ifa;
- *ifa = I;
-
-skip_it:
- h = NLMSG_NEXT(h, status);
- }
- if (msg.msg_flags & MSG_TRUNC)
- continue;
- }
- return;
-}
-
-static int getifaddrs(struct ifaddrs **ifa0)
-{
- struct {
- struct nlmsghdr nlh;
- struct rtgenmsg g;
- } req;
- struct sockaddr_nl nladdr;
- static __u32 seq;
- struct ifaddrs *i;
- int fd;
-
- fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
- if (fd < 0)
- return -1;
-
- memset(&nladdr, 0, sizeof(nladdr));
- nladdr.nl_family = AF_NETLINK;
-
- req.nlh.nlmsg_len = sizeof(req);
- req.nlh.nlmsg_type = RTM_GETADDR;
- req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
- req.nlh.nlmsg_pid = 0;
- req.nlh.nlmsg_seq = ++seq;
- req.g.rtgen_family = AF_UNSPEC;
-
- if (sendto(fd, (void*)&req, sizeof(req), 0, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
- close(fd);
- return -1;
- }
-
- *ifa0 = NULL;
-
- recvaddrs(fd, ifa0, seq);
-
- close(fd);
-
- fd = socket(AF_INET, SOCK_DGRAM, 0);
-
- for (i=*ifa0; i; i = i->ifa_next) {
- struct ifreq ifr;
- ifr.ifr_ifindex = i->ifa_ifindex;
- ioctl(fd, SIOCGIFNAME, (void*)&ifr);
- memcpy(i->ifa_name, ifr.ifr_name, 16);
- }
- close(fd);
-
- return 0;
-}
-
-static void freeifaddrs(struct ifaddrs *ifa0)
-{
- struct ifaddrs *i;
-
- while (ifa0) {
- i = ifa0;
- ifa0 = i->ifa_next;
- free(i);
- }
-}
-
-#endif
-
#ifndef HAVE_GETIFADDRS
static unsigned int
if_maxindex()
if (q->udp_encap && !udp_encap
|| !q->udp_encap && udp_encap)
continue;
- if (addr->sa_family != q->addr->sa_family)
+ if (addr->sa_family != q->addr->ss_family)
continue;
- if (getnameinfo(q->addr, sysdep_sa_len(q->addr), h2, sizeof(h2),
+ if (getnameinfo((struct sockaddr *)q->addr, sysdep_sa_len((struct sockaddr *)q->addr), h2, sizeof(h2),
NULL, 0, NI_NUMERICHOST | niflags) != 0)
return NULL;
if (strcmp(h1, h2) == 0)
#ifdef HAVE_GETIFADDRS
struct myaddrs *p, *q;
struct ifaddrs *ifa0, *ifap;
-#ifdef INET6
- struct sockaddr_in6 *sin6;
-#endif
char addr1[NI_MAXHOST];
p->sock = -1;
p->in_use = 1;
- if (getnameinfo(p->addr, p->addr->sa_len,
+ if (getnameinfo((struct sockaddr *)p->addr, p->addr->ss_len,
addr1, sizeof(addr1),
NULL, 0,
NI_NUMERICHOST | niflags))
const char *ifname;
const struct sockaddr *ifaddr;
{
-#ifdef ENABLE_HYBRID
+#if 0 //we need to be able to do nested ipsec for BTMM... stub out ifdef ENABLE_HYBRID
/* Exclude any address we got through ISAKMP mode config */
if (exclude_cfg_addr(ifaddr) == 0)
return 0;
const char *ifname;
const struct sockaddr *ifaddr;
{
-#ifndef __linux__
struct in6_ifreq ifr6;
int s;
-#endif
if (ifaddr->sa_family != AF_INET6)
return 0;
-#ifndef __linux__
s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == -1) {
plog(LLV_ERROR, LOCATION, NULL,
return 0;
}
+ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to put IPv6 socket in non-blocking mode\n");
+ }
+
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ifname, sizeof(ifr6.ifr_name));
- ifr6.ifr_addr = *(const struct sockaddr_in6 *)ifaddr;
+ memcpy(&ifr6.ifr_addr, ifaddr, sizeof(struct sockaddr_in6)); // Wcast-align fix - copy instread of assign with cast
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
plog(LLV_ERROR, LOCATION, NULL,
|| ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DETACHED
|| ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_ANYCAST)
return 0;
-#endif
/* suitable */
return 1;
int
update_myaddrs()
-{
-#ifdef __linux__
- char msg[BUFSIZ];
+{
+ struct rtmessage { // Wcast-align fix - force alignment
+ struct rt_msghdr rtm;
+ char discard[BUFSIZ];
+ } msg;
+
int len;
- struct nlmsghdr *h = (void*)msg;
- len = read(lcconf->rtsock, msg, sizeof(msg));
- if (len < 0)
- return errno == ENOBUFS;
- if (len < sizeof(*h))
- return 0;
- if (h->nlmsg_pid) /* not from kernel! */
- return 0;
- if (h->nlmsg_type == RTM_NEWLINK)
- return 0;
- plog(LLV_DEBUG, LOCATION, NULL,
- "netlink signals update interface address list\n");
- return 1;
-#else
- char msg[BUFSIZ];
- int len;
- struct rt_msghdr *rtm;
- len = read(lcconf->rtsock, msg, sizeof(msg));
- if (len < 0) {
+ while((len = read(lcconf->rtsock, &msg, sizeof(msg))) < 0) {
+ if (errno == EINTR)
+ continue;
plog(LLV_ERROR, LOCATION, NULL,
"read(PF_ROUTE) failed: %s\n",
strerror(errno));
return 0;
}
- rtm = (struct rt_msghdr *)msg;
- if (len < rtm->rtm_msglen) {
+ if (len < msg.rtm.rtm_msglen) {
plog(LLV_ERROR, LOCATION, NULL,
"read(PF_ROUTE) short read\n");
return 0;
}
- if (rtm->rtm_version != RTM_VERSION) {
+ if (msg.rtm.rtm_version != RTM_VERSION) {
plog(LLV_ERROR, LOCATION, NULL,
"routing socket version mismatch\n");
close(lcconf->rtsock);
lcconf->rtsock = -1;
return 0;
}
- switch (rtm->rtm_type) {
+ switch (msg.rtm.rtm_type) {
case RTM_NEWADDR:
case RTM_DELADDR:
case RTM_DELETE:
/* ignore this message silently */
return 0;
default:
- plog(LLV_DEBUG, LOCATION, NULL,
- "msg %d not interesting\n", rtm->rtm_type);
+ //plog(LLV_DEBUG, LOCATION, NULL,
+ // "msg %d not interesting\n", msg.rtm.rtm_type);
return 0;
}
/* XXX more filters here? */
- plog(LLV_DEBUG, LOCATION, NULL,
- "caught rtm:%d, need update interface address list\n",
- rtm->rtm_type);
+ //plog(LLV_DEBUG, LOCATION, NULL,
+ // "caught rtm:%d, need update interface address list\n",
+ // msg.rtm.rtm_type);
return 1;
-#endif /* __linux__ */
}
/*
*/
u_short
getmyaddrsport(local)
- struct sockaddr *local;
+ struct sockaddr_storage *local;
{
struct myaddrs *p, *bestmatch = NULL;
u_short bestmatch_port = PORT_ISAKMP;
continue;
}
- switch (p->addr->sa_family) {
+ switch (p->addr->ss_family) {
case AF_INET:
if (((struct sockaddr_in *)p->addr)->sin_port == PORT_ISAKMP) {
bestmatch = p;
#endif
default:
plog(LLV_ERROR, LOCATION, NULL,
- "unsupported AF %d\n", p->addr->sa_family);
+ "unsupported AF %d\n", p->addr->ss_family);
continue;
}
}
/* Copy the whole structure and set the differences. */
memcpy (new, old, sizeof (*new));
- new->addr = dupsaddr (old->addr);
+ new->addr = dupsaddr ((struct sockaddr *)old->addr);
if (new->addr == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to allocate buffer for duplicate addr.\n");
{
if (myaddr->addr)
racoon_free(myaddr->addr);
-#ifdef __APPLE__
if (myaddr->ifname)
racoon_free(myaddr->ifname);
-#endif
racoon_free(myaddr);
}
strerror(errno));
return -1;
}
-
-#ifdef __linux__
- {
- struct sockaddr_nl nl;
- u_int addr_len;
-
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- nl.nl_groups = RTMGRP_IPV4_IFADDR|RTMGRP_LINK;
-
- if (bind(lcconf->rtsock, (struct sockaddr*)&nl, sizeof(nl)) < 0) {
- plog(LLV_ERROR, LOCATION, NULL,
- "bind(PF_NETLINK) failed: %s\n",
- strerror(errno));
- return -1;
- }
- addr_len = sizeof(nl);
- if (getsockname(lcconf->rtsock, (struct sockaddr*)&nl, &addr_len) < 0) {
+
+ if (fcntl(lcconf->rtsock, F_SETFL, O_NONBLOCK) == -1) {
plog(LLV_ERROR, LOCATION, NULL,
- "getsockname(PF_NETLINK) failed: %s\n",
- strerror(errno));
- return -1;
+ "failed to put PF_ROUTE socket in non-blocking mode\n");
}
- }
-#endif
if (lcconf->myaddrs == NULL && lcconf->autograbaddr == 1) {
grab_myaddrs();
struct sockaddr *my;
{
struct myaddrs *p, *lastresort = NULL;
-#if defined(INET6) && defined(__linux__)
- struct myaddrs *match_wo_scope_id = NULL;
- int check_wo_scope_id = (my->sa_family == AF_INET6) &&
- IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)my)->sin6_addr);
-#endif
for (p = lcconf->myaddrs; p; p = p->next) {
if (p->addr == NULL)
continue;
- if (my->sa_family == p->addr->sa_family) {
+ if (my->sa_family == p->addr->ss_family) {
lastresort = p;
} else continue;
- if (sysdep_sa_len(my) == sysdep_sa_len(p->addr)
+ if (sysdep_sa_len(my) == sysdep_sa_len((struct sockaddr *)p->addr)
&& memcmp(my, p->addr, sysdep_sa_len(my)) == 0) {
break;
}
-#if defined(INET6) && defined(__linux__)
- if (check_wo_scope_id && IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)p->addr)->sin6_addr) &&
- /* XXX: this depends on sin6_scope_id to be last
- * item in struct sockaddr_in6 */
- memcmp(my, p->addr,
- sysdep_sa_len(my) - sizeof(uint32_t)) == 0) {
- match_wo_scope_id = p;
- }
-#endif
}
-#if defined(INET6) && defined(__linux__)
- if (!p)
- p = match_wo_scope_id;
-#endif
if (!p)
p = lastresort;
if (!p) {