Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / miniupnpd / bsd / getroute.c
blobe72f716185abde434dbde5913d4e6c4cdf34f1be
1 /* $Id: getroute.c,v 1.3 2013/02/06 13:11:45 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2013 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <stdio.h>
9 #include <syslog.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <net/if.h>
14 #include <net/route.h>
15 #include <netinet/in.h>
16 #ifdef AF_LINK
17 #include <net/if_dl.h>
18 #endif
20 #include "../config.h"
21 #include "../upnputils.h"
24 int
25 get_src_for_route_to(const struct sockaddr * dst,
26 void * src, size_t * src_len,
27 int * index)
29 int found = 0;
30 int s;
31 int l, i;
32 char * p;
33 struct sockaddr * sa;
34 struct {
35 struct rt_msghdr m_rtm;
36 char m_space[512];
37 } m_rtmsg;
38 #define rtm m_rtmsg.m_rtm
40 if(dst == NULL)
41 return -1;
42 #ifdef __APPLE__
43 if(dst->sa_family == AF_INET6) {
44 syslog(LOG_ERR, "Sorry, get_src_for_route_to() is known to fail with IPV6 on OS X...");
45 return -1;
47 #endif
48 s = socket(PF_ROUTE, SOCK_RAW, dst->sa_family);
49 if(s < 0) {
50 syslog(LOG_ERR, "socket(PF_ROUTE) failed : %m");
51 return -1;
53 memset(&rtm, 0, sizeof(rtm));
54 rtm.rtm_type = RTM_GET;
55 rtm.rtm_flags = RTF_UP;
56 rtm.rtm_version = RTM_VERSION;
57 rtm.rtm_seq = 1;
58 rtm.rtm_addrs = RTA_DST; /* destination address */
59 memcpy(m_rtmsg.m_space, dst, sizeof(struct sockaddr));
60 rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr);
61 if(write(s, &m_rtmsg, rtm.rtm_msglen) < 0) {
62 syslog(LOG_ERR, "write: %m");
63 close(s);
64 return -1;
67 do {
68 l = read(s, &m_rtmsg, sizeof(m_rtmsg));
69 if(l<0) {
70 syslog(LOG_ERR, "read: %m");
71 close(s);
72 return -1;
74 syslog(LOG_DEBUG, "read l=%d seq=%d pid=%d",
75 l, rtm.rtm_seq, rtm.rtm_pid);
76 } while(l > 0 && (rtm.rtm_pid != getpid() || rtm.rtm_seq != 1));
77 close(s);
78 p = m_rtmsg.m_space;
79 if(rtm.rtm_addrs) {
80 for(i=1; i<0x8000; i <<= 1) {
81 if(i & rtm.rtm_addrs) {
82 char tmp[256] = { 0 };
83 sa = (struct sockaddr *)p;
84 sockaddr_to_string(sa, tmp, sizeof(tmp));
85 syslog(LOG_DEBUG, "type=%d sa_len=%d sa_family=%d %s",
86 i, sa->sa_len, sa->sa_family, tmp);
87 if((i == RTA_DST || i == RTA_GATEWAY) &&
88 (src_len && src)) {
89 size_t len = 0;
90 void * paddr = NULL;
91 if(sa->sa_family == AF_INET) {
92 paddr = &((struct sockaddr_in *)sa)->sin_addr;
93 len = sizeof(struct in_addr);
94 } else if(sa->sa_family == AF_INET6) {
95 paddr = &((struct sockaddr_in6 *)sa)->sin6_addr;
96 len = sizeof(struct in6_addr);
98 if(paddr) {
99 if(*src_len < len) {
100 syslog(LOG_WARNING, "cannot copy src. %u<%u",
101 (unsigned)*src_len, (unsigned)len);
102 return -1;
104 memcpy(src, paddr, len);
105 *src_len = len;
106 found = 1;
109 #ifdef AF_LINK
110 if(sa->sa_family == AF_LINK) {
111 struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa;
112 if(index)
113 *index = sdl->sdl_index;
115 #endif
116 p += sa->sa_len;
120 return found ? 0 : -1;