1/* $Id: ifacewatcher.c,v 1.8 2014/04/18 08:23:51 nanard Exp $ */ 2/* Project MiniUPnP 3 * web : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ 4 * (c) 2011 Thomas BERNARD 5 * This software is subject to the conditions detailed 6 * in the LICENCE file provided within the distribution */ 7 8#include "../config.h" 9 10#include <sys/types.h> 11#include <sys/time.h> 12#include <sys/socket.h> 13#include <net/if.h> 14#include <net/route.h> 15#include <syslog.h> 16#include <signal.h> 17 18#define SALIGN (sizeof(long) - 1) 19#define SA_RLEN(sa) (SA_LEN(sa) ? ((SA_LEN(sa) + SALIGN) & ~SALIGN) : (SALIGN + 1)) 20 21#include "../upnputils.h" 22#include "../upnpglobalvars.h" 23 24extern volatile sig_atomic_t should_send_public_address_change_notif; 25 26int 27OpenAndConfInterfaceWatchSocket(void) 28{ 29 int s; 30 31 /*s = socket(PF_ROUTE, SOCK_RAW, AF_INET);*/ 32 s = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC); 33/* The family parameter may be AF_UNSPEC which will provide routing informa- 34 * tion for all address families, or can be restricted to a specific address 35 * family by specifying which one is desired. There can be more than one 36 * routing socket open per system. */ 37 if(s < 0) { 38 syslog(LOG_ERR, "OpenAndConfInterfaceWatchSocket socket: %m"); 39 } 40 return s; 41} 42 43void 44ProcessInterfaceWatchNotify(int s) 45{ 46 char buf[4096]; 47 ssize_t len; 48 char tmp[64]; 49 struct rt_msghdr * rtm; 50 struct if_msghdr * ifm; 51 struct ifa_msghdr * ifam; 52#ifdef RTM_IFANNOUNCE 53 struct if_announcemsghdr * ifanm; 54#endif 55 char * p; 56 struct sockaddr * sa; 57 unsigned int ext_if_name_index = 0; 58 59 len = recv(s, buf, sizeof(buf), 0); 60 if(len < 0) { 61 syslog(LOG_ERR, "ProcessInterfaceWatchNotify recv: %m"); 62 return; 63 } 64 if(ext_if_name) { 65 ext_if_name_index = if_nametoindex(ext_if_name); 66 } 67 rtm = (struct rt_msghdr *)buf; 68 syslog(LOG_DEBUG, "%u rt_msg : msglen=%d version=%d type=%d", (unsigned)len, 69 rtm->rtm_msglen, rtm->rtm_version, rtm->rtm_type); 70 switch(rtm->rtm_type) { 71 case RTM_IFINFO: /* iface going up/down etc. */ 72 ifm = (struct if_msghdr *)buf; 73 syslog(LOG_DEBUG, " RTM_IFINFO: addrs=%x flags=%x index=%hu", 74 ifm->ifm_addrs, ifm->ifm_flags, ifm->ifm_index); 75 break; 76 case RTM_ADD: /* Add Route */ 77 syslog(LOG_DEBUG, " RTM_ADD"); 78 break; 79 case RTM_DELETE: /* Delete Route */ 80 syslog(LOG_DEBUG, " RTM_DELETE"); 81 break; 82 case RTM_CHANGE: /* Change Metrics or flags */ 83 syslog(LOG_DEBUG, " RTM_CHANGE"); 84 break; 85 case RTM_GET: /* Report Metrics */ 86 syslog(LOG_DEBUG, " RTM_GET"); 87 break; 88#ifdef RTM_IFANNOUNCE 89 case RTM_IFANNOUNCE: /* iface arrival/departure */ 90 ifanm = (struct if_announcemsghdr *)buf; 91 syslog(LOG_DEBUG, " RTM_IFANNOUNCE: index=%hu what=%hu ifname=%s", 92 ifanm->ifan_index, ifanm->ifan_what, ifanm->ifan_name); 93 break; 94#endif 95#ifdef RTM_IEEE80211 96 case RTM_IEEE80211: /* IEEE80211 wireless event */ 97 syslog(LOG_DEBUG, " RTM_IEEE80211"); 98 break; 99#endif 100 case RTM_NEWADDR: /* address being added to iface */ 101 ifam = (struct ifa_msghdr *)buf; 102 syslog(LOG_DEBUG, " RTM_NEWADDR: addrs=%x flags=%x index=%hu", 103 ifam->ifam_addrs, ifam->ifam_flags, ifam->ifam_index); 104 p = buf + sizeof(struct ifa_msghdr); 105 while(p < buf + len) { 106 sa = (struct sockaddr *)p; 107 sockaddr_to_string(sa, tmp, sizeof(tmp)); 108 syslog(LOG_DEBUG, " %s", tmp); 109 p += SA_RLEN(sa); 110 } 111 if(ifam->ifam_index == ext_if_name_index) { 112 should_send_public_address_change_notif = 1; 113 } 114 break; 115 case RTM_DELADDR: /* address being removed from iface */ 116 ifam = (struct ifa_msghdr *)buf; 117 if(ifam->ifam_index == ext_if_name_index) { 118 should_send_public_address_change_notif = 1; 119 } 120 break; 121 default: 122 syslog(LOG_DEBUG, "unprocessed RTM message type=%d", rtm->rtm_type); 123 } 124} 125 126