Annotation of embedaddon/miniupnpd/bsd/getroute.c, revision 1.1.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>