Annotation of embedaddon/miniupnpd/bsd/getroute.c, revision 1.1
1.1 ! misho 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 */
! 7:
! 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
! 19:
! 20: #include "../config.h"
! 21: #include "../upnputils.h"
! 22:
! 23:
! 24: int
! 25: get_src_for_route_to(const struct sockaddr * dst,
! 26: void * src, size_t * src_len,
! 27: int * index)
! 28: {
! 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
! 39:
! 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;
! 46: }
! 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;
! 52: }
! 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;
! 65: }
! 66:
! 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;
! 73: }
! 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);
! 97: }
! 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;
! 103: }
! 104: memcpy(src, paddr, len);
! 105: *src_len = len;
! 106: found = 1;
! 107: }
! 108: }
! 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;
! 114: }
! 115: #endif
! 116: p += sa->sa_len;
! 117: }
! 118: }
! 119: }
! 120: return found ? 0 : -1;
! 121: }
! 122:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>