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>