/* * Adds address to the list of addresses maintained for interface. */ void add_address(struct preflist *pl, struct interface *ifp) { /* * Note: The first address of link local list is always used * as the * source address of a packet if no address is * specified through * Interface configuration. */ if (IN6_IS_ADDR_LINKLOCAL(&(pl->pl_pref.prf_addr))) { if (ifp->if_lladdr) { pl->pl_next = ifp->if_lladdr->pl_next; ifp->if_lladdr->pl_next = pl; } else { pl->pl_next = ifp->if_lladdr; ifp->if_lladdr = pl; } } else if (IN6_IS_ADDR_SITELOCAL(&(pl->pl_pref.prf_addr))) { pl->pl_next = ifp->if_sladdr; ifp->if_sladdr = pl; } else { /* never a multicast address. already checked * in get_address() */ if (ifp->if_ip6addr) { pl->pl_next = ifp->if_ip6addr->pl_next; ifp->if_ip6addr->pl_next = pl; } else { pl->pl_next = ifp->if_ip6addr; ifp->if_ip6addr = pl; } } return; }
/** Determines the IPv6 scope of a specified address. * * @param[in] v6Addr - The IPv6 address to be checked. * * @return The ipv6 scope of the address. * * @remarks The @p v6Addr parameter must be pointer to a 16-byte IPv6 * address in binary form. * * @internal */ static int setScopeFromAddress(const struct in6_addr * v6Addr) { if (IN6_IS_ADDR_MULTICAST(v6Addr)) { if (IN6_IS_ADDR_MC_GLOBAL(v6Addr)) return SLP_SCOPE_GLOBAL; if (IN6_IS_ADDR_MC_ORGLOCAL(v6Addr)) return SLP_SCOPE_ORG_LOCAL; if (IN6_IS_ADDR_MC_SITELOCAL(v6Addr)) return SLP_SCOPE_SITE_LOCAL; if (IN6_IS_ADDR_MC_NODELOCAL(v6Addr)) return SLP_SCOPE_NODE_LOCAL; if (IN6_IS_ADDR_MC_LINKLOCAL(v6Addr)) return SLP_SCOPE_LINK_LOCAL; } if (IN6_IS_ADDR_SITELOCAL(v6Addr)) return SLP_SCOPE_SITE_LOCAL; if (SLP_IN6_IS_ADDR_LOOPBACK(v6Addr)) return SLP_SCOPE_NODE_LOCAL; if (IN6_IS_ADDR_LINKLOCAL(v6Addr)) return SLP_SCOPE_LINK_LOCAL; return 0; }
int get_host_addr(void *addr, unsigned int addrlen, const char *host, unsigned short port) { struct addrinfo hint = {0}; struct addrinfo *addrlink = NULL; struct addrinfo *tmp = NULL; unsigned short *lpport = (unsigned short *)((char*)addr + 1 + sizeof(unsigned short)); hint.ai_flags = AI_CANONNAME; if(getaddrinfo(host, NULL, &hint, &addrlink) != 0) { return -1; } for(tmp = addrlink; tmp != NULL; tmp = tmp->ai_next) { if(tmp->ai_family == AF_INET6) { if(IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&((struct sockaddr_in6 *)tmp->ai_addr)->sin6_addr) ) { continue; } } ((char*)addr)[0] = (char)(tmp->ai_addrlen > addrlen ? addrlen : tmp->ai_addrlen); memcpy((char*)addr+1, tmp->ai_addr, ((char*)addr)[0]); *lpport = htons(port); break; } freeaddrinfo(addrlink); return 0; }
bool sockaddr_isAddrSiteLocal(const struct sockaddr * sa) { if (sa->sa_family == AF_INET) { return false; }else if (sa->sa_family == AF_INET6) { return IN6_IS_ADDR_SITELOCAL(&((struct sockaddr_in6*)sa)->sin6_addr); } return false; }
enum ip_addr_type get_ipv6_addr_type(const struct sockaddr_in6 *ip) { if (IN6_IS_ADDR_LOOPBACK(ip)) { return ADDR_TYPE_IPV6_LOOPBACK; } else if (IN6_IS_ADDR_SITELOCAL(ip)) { return ADDR_TYPE_IPV6_SITE_LOCAL; } else { return ADDR_TYPE_IPV6_OTHER; } }
bool BNetworkAddress::IsSiteLocal() const { switch (fAddress.ss_family) { case AF_INET6: return IN6_IS_ADDR_SITELOCAL(&((sockaddr_in6&)fAddress).sin6_addr); default: return false; } }
int sock_send(int fd, char * addr, char * buf, int buflen, int port,int iface) { struct addrinfo inforemote,*remote; char addrStr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")+5]; char portStr[10]; int i; char packaddr[16]; char ifaceStr[10]; strcpy(addrStr,addr); itoa(port,portStr,10); itoa(iface,ifaceStr,10); inet_pton6(addrStr,packaddr); if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)packaddr) ||IN6_IS_ADDR_SITELOCAL((struct in6_addr*)packaddr)) strcat(strcat(addrStr,"%"),ifaceStr); #if 0 /* if (IN6_IS_ADDR_MULTICAST((IN6_ADDR*)addr)) { ipmreq.ipv6mr_interface=4; memcpy(&ipmreq.ipv6mr_multiaddr,addr,16); if(setsockopt(fd,IPPROTO_IPV6,IPV6_ADD_MEMBERSHIP,(char*)&ipmreq,sizeof(ipmreq))) return -1; //WSAGetLastError(); //int hops=8; //if(setsockopt(fd,IPPROTO_IPV6,IPV6_MULTICAST_HOPS,(char*)&hops,sizeof(hops))) // return -1; //WSAGetLastError(); }*/ #endif memset(&inforemote, 0, sizeof(inforemote)); inforemote.ai_flags=AI_NUMERICHOST; inforemote.ai_family=PF_INET6; inforemote.ai_socktype=SOCK_DGRAM; inforemote.ai_protocol=IPPROTO_IPV6; //inet_ntop6(addr,addrStr); if(getaddrinfo(addrStr,portStr,&inforemote,&remote)) return 0; if (i=sendto(fd,buf,buflen,0,remote->ai_addr,remote->ai_addrlen)) { freeaddrinfo(remote); if (i<0) displayError(WSAGetLastError()); return 0; } /* if((setsockopt(fd,IPPROTO_IPV6,IPV6_DROP_MEMBERSHIP,(char*)&ipmreq,sizeof(ipmreq)))) return WSAGetLastError();*/ freeaddrinfo(remote); return i; }
/** Return IPv6 address scope */ static int li_scope6(struct in6_addr const *ip6) { if (IN6_IS_ADDR_V4MAPPED(ip6) || IN6_IS_ADDR_V4COMPAT(ip6)) { uint32_t ip4 = *(uint32_t *)(ip6->s6_addr + 12); return li_scope4(ip4); } else if (IN6_IS_ADDR_LOOPBACK(ip6)) return LI_SCOPE_HOST; else if (IN6_IS_ADDR_LINKLOCAL(ip6)) return LI_SCOPE_LINK; else if (IN6_IS_ADDR_SITELOCAL(ip6)) return LI_SCOPE_SITE; else return LI_SCOPE_GLOBAL; }
int sock_send(int fd, char * addr, char * buf, int buflen, int port,int iface) { ADDRINFO inforemote,*remote; char addrStr[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")+5]; char portStr[10]; int i; char packaddr[16]; char ifaceStr[10]; memset(addrStr, 0, sizeof(addrStr)); memset(portStr, 0, sizeof(portStr)); memset(packaddr, 0, sizeof(packaddr)); memset(ifaceStr, 0, sizeof(ifaceStr)); strcpy(addrStr,addr); itoa(port,portStr,10); itoa(iface,ifaceStr,10); inet_pton6(addrStr,packaddr); if(IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)packaddr) ||IN6_IS_ADDR_SITELOCAL((struct in6_addr*)packaddr)) strcat(strcat(addrStr,"%"),ifaceStr); memset(&inforemote, 0, sizeof(inforemote)); inforemote.ai_flags=AI_NUMERICHOST; inforemote.ai_family=PF_INET6; inforemote.ai_socktype=SOCK_DGRAM; inforemote.ai_protocol=IPPROTO_IPV6; //inet_ntop6(addr,addrStr); if(getaddrinfo(addrStr,portStr,&inforemote,&remote)) return 0; i=sendto(fd,buf,buflen,0,remote->ai_addr,remote->ai_addrlen); freeaddrinfo(remote); if (i==SOCKET_ERROR) { error_message_set(WSAGetLastError()); return LOWLEVEL_ERROR_UNSPEC; } return LOWLEVEL_NO_ERROR; }
/* * Find the interface with address addr. */ struct interface * if_ifwithaddr(struct preflist *addr, struct interface *ifp) { register struct interface *inf; register struct preflist *pl = NULL; #define equal( a1, a2 ) \ ((bcmp((char *)&a1->pl_pref.prf_addr, (char *)&a2->pl_pref.prf_addr, \ sizeof(struct in6_addr)) == 0) && \ (a1->pl_pref.prf_len == a2->pl_pref.prf_len)) for (inf = ifnet; inf; inf = inf->if_next) { if (inf->if_flag & IFF_POINTOPOINT) continue; /* ignore */ if (IN6_IS_ADDR_LINKLOCAL(&addr->pl_pref.prf_addr)) pl = inf->if_lladdr; else if (IN6_IS_ADDR_GLOBAL(&addr->pl_pref.prf_addr)) pl = inf->if_ip6addr; else if (IN6_IS_ADDR_SITELOCAL(&addr->pl_pref.prf_addr)) pl = inf->if_sladdr; /* else ? */ for (; pl; pl = pl->pl_next) { if (equal(pl, addr)) { if (inf == ifp) { pl->pl_flag = PL_OLDADDR; return (inf); } else if (pl->pl_flag == PL_DELADDR) continue; /* duplicated address, ignore */ if (!IN6_IS_ADDR_LINKLOCAL(&addr->pl_pref.prf_addr)) return (inf); } } } return ((struct interface *)NULL); }
/* * Find the point-to-point interface with destination address addr. */ struct interface * if_ifwithdstaddr(struct preflist *addr, struct interface *ifp) { register struct interface *inf; register struct preflist *pl = NULL; /* Unknown Address of the other side */ if (IN6_IS_ADDR_UNSPECIFIED(&addr->pl_dest)) return (struct interface *)NULL; for (inf = ifnet; inf; inf = inf->if_next) { if ((inf->if_flag & IFF_POINTOPOINT) == 0) continue; if (IN6_IS_ADDR_LINKLOCAL(&addr->pl_pref.prf_addr)) pl = inf->if_lladdr; else if (IN6_IS_ADDR_GLOBAL(&addr->pl_pref.prf_addr)) pl = inf->if_ip6addr; else if (IN6_IS_ADDR_SITELOCAL(&addr->pl_pref.prf_addr)) pl = inf->if_sladdr; /* else ? */ for (; pl; pl = pl->pl_next) { if (IN6_ARE_ADDR_EQUAL(&pl->pl_dest, &addr->pl_dest)) { if ((inf == ifp) && (equal(pl, addr))) { pl->pl_flag = PL_OLDADDR; return (inf); } else if (pl->pl_flag == PL_DELADDR) continue; /* duplicated address, ignore */ if (!IN6_IS_ADDR_LINKLOCAL(&addr->pl_pref.prf_addr)) return (inf); } } } return ((struct interface *)NULL); }
bool bbcp_NetAddrInfo::isPrivate() { unsigned char *ipV4 = 0; // For IPV6 addresses we will use the macro unless it is mapped // if (IP.Addr.sa_family == AF_INET6) {if ((IN6_IS_ADDR_V4MAPPED(&IP.v6.sin6_addr))) ipV4 = (unsigned char *)&IP.v6.sin6_addr.s6_addr32[3]; else {if ((IN6_IS_ADDR_LINKLOCAL(&IP.v6.sin6_addr)) || (IN6_IS_ADDR_SITELOCAL(&IP.v6.sin6_addr)) || (IN6_IS_ADDR_LOOPBACK (&IP.v6.sin6_addr))) return true; return false; } } // If this is not an IPV4 address then we will consider it private // if (!ipV4) {if (IP.Addr.sa_family != AF_INET) return true; ipV4 = (unsigned char *)&IP.v4.sin_addr.s_addr; } // For IPV4 we use the RFC definition of private. Note that this includes // mapped addresses which, as odd as it is, we could get. // if (ipV4[0] == 10 || (ipV4[0] == 172 && ipV4[1] >= 16 && ipV4[1] <= 31) || (ipV4[0] == 192 && ipV4[1] == 168) || (ipV4[0] == 169 && ipV4[1] == 254) || ipV4[0] == 127) return true; // Not a local address // return false; }
int _load_v6(netsnmp_container *container, int idx_offset) { FILE *in; char line[80], addr[33], if_name[IFNAMSIZ]; u_char *buf; int if_index, pfx_len, scope, flags, rc = 0; size_t in_len, out_len; netsnmp_ipaddress_entry *entry; _ioctl_extras *extras; static int log_open_err = 1; netsnmp_assert(NULL != container); #define PROCFILE "/proc/net/if_inet6" if (!(in = fopen(PROCFILE, "r"))) { if (1 == log_open_err) { snmp_log(LOG_ERR,"could not open " PROCFILE "\n"); log_open_err = 0; } return -2; } /* * if we hadn't been able to open file and turned of err logging, * turn it back on now that we opened the file. */ if (0 == log_open_err) log_open_err = 1; /* * address index prefix_len scope status if_name */ while (fgets(line, sizeof(line), in)) { /* * fe800000000000000200e8fffe5b5c93 05 40 20 80 eth0 * A D P S F I * A: address * D: device number * P: prefix len * S: scope (see include/net/ipv6.h, net/ipv6/addrconf.c) * F: flags (see include/linux/rtnetlink.h, net/ipv6/addrconf.c) * I: interface */ rc = sscanf(line, "%32s %02x %02x %02x %02x %8s\n", addr, &if_index, &pfx_len, &scope, &flags, if_name); if( 6 != rc ) { snmp_log(LOG_ERR, PROCFILE " data format error (%d!=6), line ==|%s|\n", rc, line); continue; } DEBUGMSGTL(("access:ipaddress:container", "addr %s, index %d, pfx %d, scope %d, flags 0x%X, name %s\n", addr, if_index, pfx_len, scope, flags, if_name)); /* */ entry = netsnmp_access_ipaddress_entry_create(); if(NULL == entry) { rc = -3; break; } in_len = entry->ia_address_len = sizeof(entry->ia_address); netsnmp_assert(16 == in_len); out_len = 0; buf = entry->ia_address; if(1 != snmp_hex_to_binary(&buf, &in_len, &out_len, 0, addr)) { snmp_log(LOG_ERR,"error parsing '%s', skipping\n", entry->ia_address); netsnmp_access_ipaddress_entry_free(entry); continue; } netsnmp_assert(16 == out_len); entry->ia_address_len = out_len; entry->ns_ia_index = ++idx_offset; /* * save if name */ extras = netsnmp_ioctl_ipaddress_extras_get(entry); memcpy(extras->name, if_name, sizeof(extras->name)); extras->flags = flags; /* * yyy-rks: optimization: create a socket outside the loop and use * netsnmp_access_interface_ioctl_ifindex_get() here, since * netsnmp_access_interface_index_find will open/close a socket * every time it is called. */ entry->if_index = netsnmp_access_interface_index_find(if_name); /* #define IPADDRESSSTATUSTC_PREFERRED 1 #define IPADDRESSSTATUSTC_DEPRECATED 2 #define IPADDRESSSTATUSTC_INVALID 3 #define IPADDRESSSTATUSTC_INACCESSIBLE 4 #define IPADDRESSSTATUSTC_UNKNOWN 5 #define IPADDRESSSTATUSTC_TENTATIVE 6 #define IPADDRESSSTATUSTC_DUPLICATE 7 */ if(flags & IFA_F_PERMANENT) entry->ia_status = IPADDRESSSTATUSTC_PREFERRED; /* ?? */ else if(flags & IFA_F_DEPRECATED) entry->ia_status = IPADDRESSSTATUSTC_DEPRECATED; else if(flags & IFA_F_TENTATIVE) entry->ia_status = IPADDRESSSTATUSTC_TENTATIVE; else { entry->ia_status = IPADDRESSSTATUSTC_UNKNOWN; DEBUGMSGTL(("access:ipaddress:ipv6", "unknown flags 0x%x\n", flags)); } /* * if it's not multi, it must be uni. * (an ipv6 address is never broadcast) */ if (IN6_IS_ADDR_MULTICAST(entry->ia_address)) entry->ia_type = IPADDRESSTYPE_ANYCAST; else entry->ia_type = IPADDRESSTYPE_UNICAST; entry->ia_prefix_len = pfx_len; /* * can we figure out if an address is from DHCP? * use manual until then... * *#define IPADDRESSORIGINTC_OTHER 1 *#define IPADDRESSORIGINTC_MANUAL 2 *#define IPADDRESSORIGINTC_DHCP 4 *#define IPADDRESSORIGINTC_LINKLAYER 5 *#define IPADDRESSORIGINTC_RANDOM 6 * * are 'local' address assigned by link layer?? */ if (IN6_IS_ADDR_LINKLOCAL(entry->ia_address) || IN6_IS_ADDR_SITELOCAL(entry->ia_address)) entry->ia_origin = IPADDRESSORIGINTC_LINKLAYER; else entry->ia_origin = IPADDRESSORIGINTC_MANUAL; /* xxx-rks: what can we do with scope? */ /* * add entry to container */ CONTAINER_INSERT(container, entry); } fclose(in); if(rc<0) return rc; return idx_offset; }
int get_destination_ip( struct task_details *plan) { int rc = RC_NORMAL, sysrc, errlen; struct addrinfo hints, *host_recs = 0, *walk, *match4 = 0, *match6 = 0, *next_host_rec = 0, *dup_list = 0; struct sockaddr_in *sa4 = 0; struct sockaddr_in6 *sa6 = 0; /* --- */ plan->dest6.sin6_family = AF_INET6; plan->dest6.sin6_port = 0; plan->dest6.sin6_flowinfo = 0; plan->dest6.sin6_addr = in6addr_loopback; plan->dest6.sin6_scope_id = SCOPE_LINK; plan->dest4.sin_family = AF_INET; plan->dest4.sin_port = 0; plan->dest4.sin_addr.s_addr = 0; /* --- */ sysrc = inet_pton( AF_INET, plan->target_host, &plan->dest4.sin_addr); if( sysrc == 1) { plan->found_family = AF_INET; if( plan->debug >= DEBUG_MEDIUM) fprintf( stderr, "Found '%s' is a V4 IP address.\n", plan->target_host); } else if( sysrc) rc = ERR_OPT_CONFIG; else { sysrc = inet_pton( AF_INET6, plan->target_host, &plan->dest6.sin6_addr); if( sysrc == 1) { plan->found_family = AF_INET6; if( plan->debug >= DEBUG_MEDIUM) fprintf( stderr, "Found '%s' is a V6 IP address.\n", plan->target_host); } else if( sysrc) rc = ERR_OPT_CONFIG; else { if( plan->debug >= DEBUG_MEDIUM) fprintf( stderr, "Looks like a hostname, need to look it up.\n"); hints.ai_flags = AI_CANONNAME; if( (plan->use_ip & DO_IPV4) && (plan->use_ip & DO_IPV6)) hints.ai_family = AF_UNSPEC; else if( plan->use_ip & DO_IPV6) hints.ai_family = AF_INET6; else hints.ai_family = AF_INET; hints.ai_socktype = 0; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_addr = 0; hints.ai_canonname = 0; hints.ai_next = 0; sysrc = getaddrinfo( plan->target_host, 0, &hints, &host_recs); if( !sysrc) { if( plan->debug >= DEBUG_HIGH) fprintf( stderr, "...getaddrinfo() call worked, scan the host records to find the one we want...\n"); match4 = match6 = 0; for( walk = host_recs; rc == RC_NORMAL && walk; walk = walk->ai_next) { next_host_rec = (struct addrinfo *) malloc( sizeof *next_host_rec); if( !next_host_rec) rc = ERR_MALLOC_FAILED; else { if( !dup_list) dup_list = next_host_rec; else dup_list->ai_next = next_host_rec; next_host_rec->ai_flags = walk->ai_flags; next_host_rec->ai_family = walk->ai_family; next_host_rec->ai_socktype = walk->ai_socktype; next_host_rec->ai_protocol = walk->ai_protocol; next_host_rec->ai_addrlen = walk->ai_addrlen; next_host_rec->ai_addr = (struct sockaddr *) malloc( next_host_rec->ai_addrlen); if( next_host_rec->ai_addr) memcpy( walk->ai_addr, next_host_rec->ai_addr, next_host_rec->ai_addrlen); next_host_rec->ai_canonname = strdup( walk->ai_canonname); next_host_rec->ai_next = 0; if( !next_host_rec->ai_canonname || !next_host_rec->ai_addr) rc = ERR_MALLOC_FAILED; } } if( rc == RC_NORMAL) { freeaddrinfo( host_recs); host_recs = dup_list; for( walk = host_recs; walk; ) { if( plan->debug >= DEBUG_NOISY) fprintf( stderr, "hr --> %x %x/%x/%x %x %x %d %s\n", walk->ai_flags, walk->ai_family, AF_INET, AF_INET6, walk->ai_socktype, walk->ai_protocol, walk->ai_addrlen, walk->ai_canonname); if( !match4 && walk->ai_family == AF_INET) match4 = walk; if( !match6 && walk->ai_family == AF_INET6) match6 = walk; if( match4 && match6) walk = 0; else walk = walk->ai_next; } if( (plan->use_ip & DO_IPV4) && match4) { sa4 = (struct sockaddr_in *) match4->ai_addr; plan->dest4.sin_addr = sa4->sin_addr; plan->found_family = AF_INET; } else if( (plan->use_ip & DO_IPV6) && match6) { sa6 = (struct sockaddr_in6 *) match6->ai_addr; plan->dest6.sin6_addr = sa6->sin6_addr; plan->found_family = AF_INET6; plan->dest6.sin6_scope_id = sa6->sin6_scope_id; } if( plan->debug >= DEBUG_NOISY) fprintf( stderr, "match4:%d/%d match6:%d/%d\n", !!match4, !!sa4, !!match6, !!sa6); } else { if( sysrc == EAI_MEMORY) rc = ERR_MALLOC_FAILED; else rc = ERR_GETHOST_FAILED; } } } } if( !strcmp( plan->target_host, IPV6_LOOPBACK_ADDRESS)) plan->dest6.sin6_scope_id = SCOPE_LOOP; else if( IN6_IS_ADDR_LINKLOCAL( &plan->dest6.sin6_addr)) plan->dest6.sin6_scope_id = SCOPE_LINK; else if( IN6_IS_ADDR_SITELOCAL( &plan->dest6.sin6_addr)) plan->dest6.sin6_scope_id = SCOPE_SITE; else plan->dest6.sin6_scope_id = SCOPE_GLOBAL; if( rc == ERR_GETHOST_FAILED) { errlen = strlen( ERRMSG_GETHOST_FAILED) + strlen( plan->target_host); plan->err_msg = (char *) malloc( errlen); if( !plan->err_msg) rc = ERR_MALLOC_FAILED; else snprintf( plan->err_msg, errlen, ERRMSG_GETHOST_FAILED, plan->target_host); } else if( rc == ERR_OPT_CONFIG) { errlen = strlen( ERRMSG_INET_PTON) + strlen( plan->target_host); plan->err_msg = (char *) malloc( errlen); if( !plan->err_msg) rc = ERR_MALLOC_FAILED; else snprintf( plan->err_msg, errlen, ERRMSG_INET_PTON, plan->target_host); } return( rc); }
/** * Query device driver for information */ bool network::query(bool accumulate) { struct ifaddrs* ifaddr; if (getifaddrs(&ifaddr) == -1 || ifaddr == nullptr) { return false; } m_status.previous = m_status.current; m_status.current.transmitted = 0; m_status.current.received = 0; m_status.current.time = std::chrono::system_clock::now(); m_status.ip6 = NO_IP6; for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if (ifa->ifa_addr == nullptr) { continue; } if (m_interface.compare(0, m_interface.length(), ifa->ifa_name) != 0) { if (!accumulate || (ifa->ifa_data == nullptr && ifa->ifa_addr->sa_family != AF_PACKET)) { continue; } } struct sockaddr_in6* sa6; switch (ifa->ifa_addr->sa_family) { case AF_INET: char ip_buffer[NI_MAXHOST]; getnameinfo(ifa->ifa_addr, sizeof(sockaddr_in), ip_buffer, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST); m_status.ip = string{ip_buffer}; break; case AF_INET6: char ip6_buffer[INET_ADDRSTRLEN]; sa6 = reinterpret_cast<decltype(sa6)>(ifa->ifa_addr); if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr)) { continue; } if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr)) { continue; } if ((((unsigned char*)sa6->sin6_addr.s6_addr)[0] & 0xFE) == 0xFC) { /* Skip Unique Local Addresses (fc00::/7) */ continue; } if (inet_ntop(AF_INET6, &sa6->sin6_addr, ip6_buffer, NI_MAXHOST) == 0) { m_log.warn("inet_ntop() " + string(strerror(errno))); continue; } m_status.ip6 = string{ip6_buffer}; break; case AF_PACKET: if (ifa->ifa_data == nullptr) { continue; } struct rtnl_link_stats* link_state = reinterpret_cast<decltype(link_state)>(ifa->ifa_data); if (link_state == nullptr) { continue; } m_status.current.transmitted += link_state->tx_bytes; m_status.current.received += link_state->rx_bytes; break; } } freeifaddrs(ifaddr); return true; }
static int get_real_ip(char*nmode, char *ip) { struct ifaddrs *ifap0, *ifap; char buf[NI_MAXHOST]; struct sockaddr_in *addr4; struct sockaddr_in6 *addr6; int family; char *IPV6_FLAG=NULL; IPV6_FLAG = cfg_get_param_string(F_CFG_IPV6); if (strcmp(IPV6_FLAG, "0") == 0){ family=AF_INET; }else{ family=AF_INET6; } if(NULL == ip) { //strcpy (ip, ""); return -1; } if(getifaddrs(&ifap0)) { return -1; } for(ifap=ifap0;ifap!=NULL;ifap=ifap->ifa_next){ if(strcmp(nmode, ifap->ifa_name) != 0) continue; if(ifap->ifa_addr == NULL) continue; if ((ifap->ifa_flags & IFF_UP) == 0) continue; if(family != ifap->ifa_addr->sa_family) continue; if(AF_INET == ifap->ifa_addr->sa_family) { addr4 = (struct sockaddr_in *)ifap->ifa_addr; if ( NULL != inet_ntop(ifap->ifa_addr->sa_family, (void *)&(addr4->sin_addr), buf, NI_MAXHOST) ){ strcpy(ip, buf); cfg_debug ("iface %s's ipaddress is %s\n", nmode, ip); freeifaddrs(ifap0); return 0; } else break; }else if(AF_INET6 == ifap->ifa_addr->sa_family) { addr6 = (struct sockaddr_in6 *)ifap->ifa_addr; if(IN6_IS_ADDR_MULTICAST(&addr6->sin6_addr)){ continue; } if(IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)){ continue; } if(IN6_IS_ADDR_LOOPBACK(&addr6->sin6_addr)){ continue; } if(IN6_IS_ADDR_UNSPECIFIED(&addr6->sin6_addr)){ continue; } if(IN6_IS_ADDR_SITELOCAL(&addr6->sin6_addr)){ continue; } if(NULL != inet_ntop(ifap->ifa_addr->sa_family, (void *)&(addr6->sin6_addr), buf, NI_MAXHOST)){ strcpy(ip, buf); cfg_debug ("iface %s's ipaddress is %s\n", nmode, ip); freeifaddrs(ifap0); return 0; } else break; } } freeifaddrs(ifap0); return -1; }
int util_my_ip_address(char *buf, size_t buflen, int all) { int ret = -1; char tmp[INET6_ADDRSTRLEN + 1]; #if defined(_WIN32) || defined(__CYGWIN__) PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, pInfo = NULL; ULONG ulBufferLength = 0; DWORD dwRet; PIP_ADAPTER_UNICAST_ADDRESS pUniAddr; buf[0] = '\0'; do { dwRet = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAdapterAddresses, &ulBufferLength); if (dwRet == ERROR_BUFFER_OVERFLOW) { if (pAdapterAddresses) free(pAdapterAddresses); pAdapterAddresses = malloc(ulBufferLength); if (!pAdapterAddresses) { return -1; } } } while (dwRet == ERROR_BUFFER_OVERFLOW); if (dwRet != ERROR_SUCCESS && dwRet != ERROR_NO_DATA) { if (pAdapterAddresses) free(pAdapterAddresses); return -1; } int break_out = 0; for (pInfo = pAdapterAddresses; pInfo; pInfo = pInfo->Next) { for (pUniAddr = pInfo->FirstUnicastAddress; pUniAddr; pUniAddr = pUniAddr->Next) { DWORD dwLen = sizeof(tmp); int rc = WSAAddressToString(pUniAddr->Address.lpSockaddr, pUniAddr->Address.iSockaddrLength, NULL, (LPTSTR)tmp, &dwLen); if (rc) continue; char *percent = strchr(tmp, '%'); if (percent) *percent = '\0'; /* First check if there's enough space in buf. */ if (strlen(tmp) + strlen(buf) + 2 > buflen) { /* Buffer too small. Try next address and see if it fits. */ continue; } /* There's enough space to hold the address plus the semicolon. */ if (strlen(buf) > 0) strcat(buf, ";"); strcat(buf, tmp); ret = 0; if (!all) { break_out = 1; break; } } if (break_out) break; } free(pAdapterAddresses); #else struct ifaddrs *addrs, *a; struct sockaddr_in *sin; struct sockaddr_in6 *sin6; uint32_t x; buf[0] = '\0'; if (getifaddrs(&addrs)) { perror("getifaddrs() failed"); return -1; } for (a = addrs; a; a = a->ifa_next) { if (!a->ifa_addr) continue; if (a->ifa_addr->sa_family == AF_INET) { sin = (struct sockaddr_in *)a->ifa_addr; x = ntohl(sin->sin_addr.s_addr); if (IN_MULTICAST(x) || INADDR_ANY == x || INADDR_NONE == x || ((x & 0xff000000) == 0x7f000000) || (((x & 0xff000000) == 0xa9000000) && ((x & 0x00ff0000) == 0x00fe0000))) { continue; } if (util_inet_ntop(sin->sin_family, a->ifa_addr, tmp, sizeof(tmp))) { break; } } else if (a->ifa_addr->sa_family == AF_INET6) { sin6 = (struct sockaddr_in6 *)a->ifa_addr; if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) || IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) || IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) || IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) { continue; } if (util_inet_ntop(sin6->sin6_family, a->ifa_addr, tmp, sizeof(tmp))) { break; } } else { continue; } if (strlen(tmp) + strlen(buf) + 2 > buflen) break; if (buf[0] != '\0') strcat(buf, ";"); strcat(buf, tmp); ret = 0; if (!all) break; } if (addrs) freeifaddrs(addrs); #endif return ret; }
HRESULT RefreshIPv6CfgDialog(HWND hwndDlg) { HRESULT hr = S_OK; ULONG ulBufferSize = 0; DWORD dwRetVal; TCHAR szAddr[INET6_ADDRSTRLEN]; TCHAR szAddrNotAvail[INET6_ADDRSTRLEN]; BOOL bDefaultGateway = FALSE; BOOL bPrefGlobal = FALSE; BOOL bPrefLinkLocal = FALSE; BOOL bPrefSiteLocal = FALSE; BOOL b6to4 = FALSE; BOOL bAuto1 = FALSE; BOOL bAuto2 = FALSE; BOOL bAuto3 = FALSE; PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL, pThisAdapterAddresses; PIP_ADAPTER_UNICAST_ADDRESS pUnicastAddresses; char szAdapterName[MAX_ADAPTERNAME_STR]; // Get IP address info dwRetVal = GetAdaptersAddresses(AF_INET6,GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL,NULL,&ulBufferSize); if (dwRetVal != ERROR_BUFFER_OVERFLOW) { DEBUGMSG(ZONE_ERROR, (TEXT("NETUIQC: Error from GetAdaptersAddresses():%u"),dwRetVal)); hr = E_FAIL; goto exit; } pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(ulBufferSize); if (pAdapterAddresses == NULL) { hr = E_FAIL; goto exit; } dwRetVal = GetAdaptersAddresses(AF_INET6,GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL,pAdapterAddresses,&ulBufferSize); if (dwRetVal != ERROR_SUCCESS) { DEBUGMSG(ZONE_ERROR, (TEXT("NETUIQC: Error from GetAdaptersAddresses():%u"),dwRetVal)); hr = E_FAIL; goto exit; } // Get our adapter name if (GetAdapterNameA(hwndDlg,szAdapterName,sizeof(szAdapterName)) != S_OK) { DEBUGMSG(ZONE_ERROR, (TEXT("Error getting adapter name"))); hr = E_FAIL; goto exit; } // Walk adapter list for (pThisAdapterAddresses = pAdapterAddresses; pThisAdapterAddresses; pThisAdapterAddresses = pThisAdapterAddresses->Next) { BOOL bCurrentAdapter; DEBUGMSG(ZONE_MISC,(TEXT("GetAdaptersAddresses adapter <%s>\n"),pThisAdapterAddresses->FriendlyName)); if (! strcmp(szAdapterName,pThisAdapterAddresses->AdapterName)) { // IPv6 stack will return address info even if media disconnected. Don't display // addresses in this case. if (!(pThisAdapterAddresses->OperStatus & IfOperStatusUp)) { DEBUGMSG(ZONE_MISC,(TEXT("GetAdaptersAddresses -- Media Disconnected\n"))); break; } bCurrentAdapter = TRUE; if (GetIPv6DefaultGateway(pThisAdapterAddresses, szAddr)) { UpdateIPv6AddressField(hwndDlg, IDC_V6GATEWAY_LBL_INF, szAddr); bDefaultGateway = TRUE; } } else { bCurrentAdapter = FALSE; if (pThisAdapterAddresses->IfType != IF_TYPE_TUNNEL) { // Skip other non tunneling adapters continue; } // TBD - For tunneling interfaces, we want to choose the one matching the v4 address on this interface } for (pUnicastAddresses = pThisAdapterAddresses->FirstUnicastAddress ; pUnicastAddresses; pUnicastAddresses = pUnicastAddresses->Next) { PSOCKADDR_IN6 pSA = (PSOCKADDR_IN6)pUnicastAddresses->Address.lpSockaddr; ULONG AddrFieldLbl; GetIPv6AddressString(szAddr, pSA); DEBUGMSG(ZONE_MISC,(TEXT(" GetAdaptersAddresses return addr <%s>\n"),szAddr)); AddrFieldLbl = 0; if (IN6_IS_ADDR_SITELOCAL(&pSA->sin6_addr)) { if (bCurrentAdapter) { AddrFieldLbl = IDC_V6PREFSITEADDR_LBL_INF; bPrefSiteLocal = TRUE; } else if (IN6_IS_ADDR_ISATAP(&pSA->sin6_addr)) { AddrFieldLbl = IDC_V6TUNNELADDR_LBL_INF2; bAuto2 = TRUE; } } else if (IN6_IS_ADDR_LINKLOCAL(&pSA->sin6_addr)) { if (bCurrentAdapter) { AddrFieldLbl = IDC_V6PREFLINKADDR_LBL_INF; bPrefLinkLocal = TRUE; } else if (IN6_IS_ADDR_ISATAP(&pSA->sin6_addr)) { AddrFieldLbl = IDC_V6TUNNELADDR_LBL_INF3; bAuto3 = TRUE; } } else { if (bCurrentAdapter) { AddrFieldLbl = IDC_V6PREFGLOBADDR_LBL_INF; bPrefGlobal = TRUE; } else if (IN6_IS_ADDR_6TO4(&pSA->sin6_addr)) { AddrFieldLbl = IDC_V66TO4ADDR_LBL_INF; b6to4 = TRUE; } else if (IN6_IS_ADDR_ISATAP(&pSA->sin6_addr)) { AddrFieldLbl = IDC_V6TUNNELADDR_LBL_INF1; bAuto1 = TRUE; } } if (AddrFieldLbl) UpdateIPv6AddressField(hwndDlg, AddrFieldLbl, szAddr); } } exit: // Display address not available for fields we couldn't populate LoadString(v_hInst, IDS_QC_V6_ADDR_UNAVAIL, szAddrNotAvail, INET6_ADDRSTRLEN); if (!bDefaultGateway) UpdateIPv6AddressField(hwndDlg, IDC_V6GATEWAY_LBL_INF, szAddrNotAvail); if (!bPrefGlobal) UpdateIPv6AddressField(hwndDlg, IDC_V6PREFGLOBADDR_LBL_INF, szAddrNotAvail); if (!bPrefSiteLocal) UpdateIPv6AddressField(hwndDlg, IDC_V6PREFSITEADDR_LBL_INF, szAddrNotAvail); if (!bPrefLinkLocal) UpdateIPv6AddressField(hwndDlg, IDC_V6PREFLINKADDR_LBL_INF, szAddrNotAvail); if (!b6to4) UpdateIPv6AddressField(hwndDlg, IDC_V66TO4ADDR_LBL_INF, szAddrNotAvail); if (!bAuto1) UpdateIPv6AddressField(hwndDlg, IDC_V6TUNNELADDR_LBL_INF1, szAddrNotAvail); if (!bAuto2) UpdateIPv6AddressField(hwndDlg, IDC_V6TUNNELADDR_LBL_INF2, szAddrNotAvail); if (!bAuto3) UpdateIPv6AddressField(hwndDlg, IDC_V6TUNNELADDR_LBL_INF3, szAddrNotAvail); if (pAdapterAddresses) { free(pAdapterAddresses); } return hr; }
/* * Reads a linux sockaddr and does any necessary translation. * Linux sockaddrs don't have a length field, only a family. * Copy the osockaddr structure pointed to by osa to kernel, adjust * family and convert to sockaddr. */ static int linux_getsockaddr(struct sockaddr **sap, const struct osockaddr *osa, int salen) { struct sockaddr *sa; struct osockaddr *kosa; #ifdef INET6 struct sockaddr_in6 *sin6; int oldv6size; #endif char *name; int bdom, error, hdrlen, namelen; if (salen < 2 || salen > UCHAR_MAX || !osa) return (EINVAL); #ifdef INET6 oldv6size = 0; /* * Check for old (pre-RFC2553) sockaddr_in6. We may accept it * if it's a v4-mapped address, so reserve the proper space * for it. */ if (salen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) { salen += sizeof(uint32_t); oldv6size = 1; } #endif kosa = malloc(salen, M_SONAME, M_WAITOK); if ((error = copyin(osa, kosa, salen))) goto out; bdom = linux_to_bsd_domain(kosa->sa_family); if (bdom == -1) { error = EAFNOSUPPORT; goto out; } #ifdef INET6 /* * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, * which lacks the scope id compared with RFC2553 one. If we detect * the situation, reject the address and write a message to system log. * * Still accept addresses for which the scope id is not used. */ if (oldv6size) { if (bdom == AF_INET6) { sin6 = (struct sockaddr_in6 *)kosa; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { sin6->sin6_scope_id = 0; } else { log(LOG_DEBUG, "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); error = EINVAL; goto out; } } else salen -= sizeof(uint32_t); } #endif if (bdom == AF_INET) { if (salen < sizeof(struct sockaddr_in)) { error = EINVAL; goto out; } salen = sizeof(struct sockaddr_in); } if (bdom == AF_LOCAL && salen > sizeof(struct sockaddr_un)) { hdrlen = offsetof(struct sockaddr_un, sun_path); name = ((struct sockaddr_un *)kosa)->sun_path; if (*name == '\0') { /* * Linux abstract namespace starts with a NULL byte. * XXX We do not support abstract namespace yet. */ namelen = strnlen(name + 1, salen - hdrlen - 1) + 1; } else namelen = strnlen(name, salen - hdrlen); salen = hdrlen + namelen; if (salen > sizeof(struct sockaddr_un)) { error = ENAMETOOLONG; goto out; } }
/* * Copy the osockaddr structure pointed to by osa to kernel, adjust * family and convert to sockaddr. */ static int do_sa_get(struct sockaddr **sap, const struct osockaddr *osa, int *osalen, struct malloc_type *mtype) { int error=0, bdom; struct sockaddr *sa; struct osockaddr *kosa; int alloclen; #ifdef INET6 int oldv6size; struct sockaddr_in6 *sin6; #endif if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) return (EINVAL); alloclen = *osalen; #ifdef INET6 oldv6size = 0; /* * Check for old (pre-RFC2553) sockaddr_in6. We may accept it * if it's a v4-mapped address, so reserve the proper space * for it. */ if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) { alloclen = sizeof (struct sockaddr_in6); oldv6size = 1; } #endif kosa = malloc(alloclen, mtype, M_WAITOK); if ((error = copyin(osa, kosa, *osalen))) goto out; bdom = linux_to_bsd_domain(kosa->sa_family); if (bdom == -1) { error = EAFNOSUPPORT; goto out; } #ifdef INET6 /* * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6, * which lacks the scope id compared with RFC2553 one. If we detect * the situation, reject the address and write a message to system log. * * Still accept addresses for which the scope id is not used. */ if (oldv6size && bdom == AF_INET6) { sin6 = (struct sockaddr_in6 *)kosa; if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) || (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) && !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) && !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) && !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) { sin6->sin6_scope_id = 0; } else { log(LOG_DEBUG, "obsolete pre-RFC2553 sockaddr_in6 rejected\n"); error = EINVAL; goto out; } } else #endif if (bdom == AF_INET) { alloclen = sizeof(struct sockaddr_in); if (*osalen < alloclen) { error = EINVAL; goto out; } } sa = (struct sockaddr *) kosa; sa->sa_family = bdom; sa->sa_len = alloclen; *sap = sa; *osalen = alloclen; return (0); out: free(kosa, mtype); return (error); }
/*Look if the source ip address is local to the subnet*/ int watch_bogon(char* buffer, uint16_t vlan_id, struct ether_header* eptr, struct ip6_hdr* ipptr) { struct ether_addr* eth_addr = (struct ether_addr*) eptr->ether_shost; struct in6_addr* ip_addr = &ipptr->ip6_src; char str_ip[IP6_STR_SIZE]; router_list_t *tmp = routers; int find = 0; ipv6_ntoa(str_ip, *ip_addr); while( tmp != NULL) { prefix_t *ptmp = tmp->prefixes; while(ptmp != NULL) { if(IN6_ARE_PRE_EQUAL(ip_addr, &(ptmp->prefix))) find = 1; ptmp = ptmp->next; } tmp = tmp->next; } if (!find && !IN6_IS_ADDR_UNSPECIFIED(ip_addr)&&!IN6_IS_ADDR_LINKLOCAL(ip_addr)&&!IN6_IS_ADDR_MULTICAST(ip_addr)&&!IN6_IS_ADDR_SITELOCAL(ip_addr)) { snprintf (buffer, NOTIFY_BUFFER_SIZE, "VLAN%d: bogon %s %s",vlan_id,ether_ntoa(eth_addr),str_ip); notify(1, buffer, "bogon", eth_addr, str_ip, NULL); return 1; } else return 0; }
/* * Forms the packet according to mode of operation. */ void send_update(struct interface *ifp, struct msghdr *mh, int state, unsigned int agronly) { int max_entries, num_entries; int metric_out, poisonf; int need_nhp = 0; struct in6_addr *addrp, *current_nhp, *new_nhp; struct rip6 *pkt; struct route_entry *rp; struct rt_plen *rtp, *drt; struct tree_node *node; struct rte_stat *stat; struct gateway *gp; struct nexthop_rte *nhrp; /* nexthop list */ struct aggregate *agp; struct route_entry r_tmp; const int nohopout = 0; if (snd_data == NULL) return; if (!(ifp->if_flag & IFF_RUNNING)) return; /* doesn't have any linklocal */ if (mh == NULL) { /* unsolicited */ mh = &smsgh; bzero(mh, sizeof(smsgh)); } mh->msg_iov = &siov; /* overwrite does no harm */ mh->msg_iovlen = 1; mh->msg_flags = 0; /* clear */ mh->msg_iov->iov_base = snd_data; pkt = (struct rip6 *)snd_data; max_entries = get_max_rte(ifp); need_nhp = 0; ONCE_FOR_EACH_PACKET; /* gendefault: if generate then no other RTE is needed */ if ((stat = ifp->if_config->int_dstat) != NULL) { if (!state) { /* regular update */ /* default route cannot be aggregated further */ bzero((void *)&r_tmp, sizeof(r_tmp)); r_tmp.rip6_metric = stat->rts_metric + ifp->if_config->int_metric_out; if (r_tmp.rip6_metric > HOPCOUNT_INFINITY) r_tmp.rip6_metric = HOPCOUNT_INFINITY; r_tmp.rip6_rtag = htons(stat->rts_tagval); new_nhp = current_nhp; CHECK_NHOP(r_tmp); WRITE_PAIR(r_tmp); } goto lastone; /* and return */ } /* init aggregate list */ for (agp = ifp->if_config->int_aggr; agp; agp = agp->agr_next) agp->agr_sent = AGR_NOTSENT; /* propagate default */ if (ifp->if_config->int_propagate && (drt = locate_local_route(&default_rte, &node)) != NULL && (drt->rp_state & RTS6_STATIC) == 0 && /* learn from neighbour */ (!state || drt->rp_state & state) && !agronly) { /* sanity check omitted */ if (drt->rp_gway->gw_ifp == ifp) { /* same interface */ switch (ifp->if_config->int_scheme) { case RT6_NOHORZN: /* no intelligence */ metric_out = drt->rp_metric + ifp->if_config->int_metric_out; break; case RT6_HORZN: goto loop; /* no need to advertise */ default: /* case RT6_POISON: */ metric_out = HOPCOUNT_INFINITY; break; } } else { /* other interface */ metric_out = drt->rp_metric + ifp->if_config->int_metric_out; } CHECK_AGR(&drt->rp_leaf->key); /* This is 1st. RTE, any aggregation has not been sent yet */ if (agp) { r_tmp.rip6_prflen = agp->agr_pref.prf_len; r_tmp.rip6_addr = agp->agr_pref.prf_addr; r_tmp.rip6_metric = agp->agr_stat.rts_metric + ifp->if_config->int_metric_out; r_tmp.rip6_rtag = htons(agp->agr_stat.rts_tagval); agp->agr_sent = AGR_SENT; } else { r_tmp.rip6_prflen = 0; /* DEFAULT ROUTE drt->rp_len */ r_tmp.rip6_addr = drt->rp_leaf->key; r_tmp.rip6_metric = metric_out; r_tmp.rip6_rtag = htons(drt->rp_tag); } if (r_tmp.rip6_metric > HOPCOUNT_INFINITY) r_tmp.rip6_metric = HOPCOUNT_INFINITY; new_nhp = &ci_info(ifp->if_cinfo).ipi6_addr; CHECK_NHOP(r_tmp); WRITE_PAIR(r_tmp); } /* end propagate */ loop: for (gp = gway; gp; gp = gp->gw_next) { if (!(gp->gw_ifp) || (gp->gw_ifp->if_flag & IFF_UP) == 0) continue; if (gp->gw_ifp == ifp) { switch (ifp->if_config->int_scheme) { case RT6_NOHORZN: /* no intelligence */ poisonf = 0; break; case RT6_HORZN: continue; /* never reached */ default: /* case RT6_POISON: */ poisonf = 1; break; } } else poisonf = 0; for (rtp = gp->gw_dest; rtp; rtp = rtp->rp_ndst) { if (state && (rtp->rp_state & state) == 0) continue; addrp = &(rtp->rp_leaf->key); if (IN6_IS_ADDR_SITELOCAL(addrp) && !(ifp->if_config->int_site)) continue; if (IN6_IS_ADDR_UNSPECIFIED(addrp) && rtp->rp_len == MAX_PREFLEN) continue; /* already propagated */ CHECK_AGR(addrp); if (agp) { if (agp->agr_sent == AGR_SENT) continue; /* already sent */ r_tmp.rip6_prflen = agp->agr_pref.prf_len; r_tmp.rip6_addr = agp->agr_pref.prf_addr; r_tmp.rip6_metric = agp->agr_stat.rts_metric + ifp->if_config->int_metric_out; r_tmp.rip6_rtag = htons(agp->agr_stat.rts_tagval); agp->agr_sent = AGR_SENT; } else { if (agronly) continue; /* send only aggregation */ r_tmp.rip6_prflen = rtp->rp_len; r_tmp.rip6_addr = *addrp; r_tmp.rip6_metric = poisonf ? HOPCOUNT_INFINITY : rtp->rp_metric + ifp->if_config->int_metric_out; r_tmp.rip6_rtag = htons(rtp->rp_tag); } if (r_tmp.rip6_metric > HOPCOUNT_INFINITY) r_tmp.rip6_metric = HOPCOUNT_INFINITY; new_nhp = &ci_info(ifp->if_cinfo).ipi6_addr; CHECK_NHOP(r_tmp); WRITE_PAIR(r_tmp); } /* for each rtp */ } /* for each gateway */ lastone: if (num_entries) { mh->msg_iov->iov_len = ((char *)rp - (char *)mh->msg_iov->iov_base); send_message(mh, ifp, agronly); } return; }
/*++ Routine Name: GetIPv6DefaultGateway Routine Description: Retrieve the IPv6 default gateway for a given adapter. This uses the IPv6 IOCTL interface to query the route table. In future releases, this should be done through IPHLPAPI, since the IOCTL interface can change from release to release. However, v6 compatible routines for retrieving route table info have not been defined yet... Arguments: pAA: Adapter address struct returned from GetAdaptersAddresses() szAddr: String buffer to hold address (must be INET6_ADDRSTRLEN chars) Return Value: TRUE if successful, FALSE if default gateway could not be retrieved. --*/ BOOL GetIPv6DefaultGateway(PIP_ADAPTER_ADDRESSES pAA, TCHAR *szAddr) { HANDLE hIPv6; IPV6_QUERY_ROUTE_TABLE QueryRouteTable, NextQueryRouteTable; IPV6_INFO_ROUTE_TABLE RTE; ULONG ulBytesReturned; SOCKADDR_IN6 Addr; BOOL bRet = FALSE; hIPv6 = CreateFileW( DD_IPV6_DEVICE_NAME, GENERIC_WRITE, // access mode FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // security attributes OPEN_EXISTING, 0, // flags & attributes NULL); // template file if (hIPv6 == INVALID_HANDLE_VALUE) { DEBUGMSG(ZONE_ERROR,(TEXT("!Error opening IPv6 driver to get default gateway\r\n"))); return FALSE; } NextQueryRouteTable.Neighbor.IF.Index = 0; for (;;) { QueryRouteTable = NextQueryRouteTable; if (!DeviceIoControl( hIPv6, IOCTL_IPV6_QUERY_ROUTE_TABLE, &QueryRouteTable, sizeof(QueryRouteTable), &RTE, sizeof(RTE), &ulBytesReturned, NULL)) { DEBUGMSG(ZONE_ERROR,(TEXT("!Error querying IPv6 driver to get default gateway\r\n"))); break; } NextQueryRouteTable = RTE.Next; if (QueryRouteTable.Neighbor.IF.Index != 0) { RTE.This = QueryRouteTable; if ((RTE.This.PrefixLength == 0) && (pAA->Ipv6IfIndex == RTE.This.Neighbor.IF.Index)) { // Found a valid router Addr.sin6_family = AF_INET6; Addr.sin6_addr = RTE.This.Neighbor.Address; Addr.sin6_port = 0; if (IN6_IS_ADDR_LINKLOCAL(&(Addr.sin6_addr))) { Addr.sin6_scope_id = pAA->ZoneIndices[ScopeLevelLink]; } else if (IN6_IS_ADDR_SITELOCAL(&(Addr.sin6_addr))) { Addr.sin6_scope_id = pAA->ZoneIndices[ScopeLevelSite]; } else { Addr.sin6_scope_id = 0; } GetIPv6AddressString(szAddr,&Addr); bRet = TRUE; break; } } if (NextQueryRouteTable.Neighbor.IF.Index == 0) break; } CloseHandle(hIPv6); return bRet; }