STATUS ifUnnumberedSet ( char *pIfName, /* Name of interface to configure */ char *pDstIp, /* Destination address of the point to point link */ char *pBorrowedIp, /* The borrowed IP address/router ID */ char *pDstMac /* Destination MAC address */ ) { int s, ret; struct ifnet *ifp; struct sockaddr_in sock; if(!(ifp = ifunit (pIfName))) return (ERROR); /* * Make sure that the interface with the "real" * pBorrowedIp is already brought up. */ bzero ((char *)&sock, sizeof (struct sockaddr_in)); sock.sin_family = AF_INET; sock.sin_len = sizeof (struct sockaddr_in); sock.sin_addr.s_addr = inet_addr (pBorrowedIp); if (!ifa_ifwithaddr ((struct sockaddr *)&sock)) return (EINVAL); /* We manually configure the interface to be IFF_UNNUMBERED */ s = splnet (); ifp->if_flags &= ~IFF_BROADCAST; ifp->if_flags |= IFF_UNNUMBERED; /* It's defined as IFF_POINTOPOINT */ splx (s); ret = ifAddrAdd (pIfName, pBorrowedIp, pDstIp, 0); if (ret != OK) return (ret); /* * For ethernet devices, we need to complete the route entry * just created by the above operation. The ATF_INCOMPLETE flag * will change the routing entry to contain the MAC address * of the destination's ethernet device. */ if (pDstMac != (char *)NULL) ret = arpAdd (pDstIp, pDstMac, ATF_PERM | ATF_INCOMPLETE); return (ret); }
/* Configure a virtual IP interface. */ void ssh_virtual_adapter_configure( SshInterceptor interceptor, SshInterceptorIfnum adapter_ifnum, SshVirtualAdapterState adapter_state, SshUInt32 num_addresses, SshIpAddr addresses, SshVirtualAdapterParams params, SshVirtualAdapterStatusCB callback, void *context) { VxWorksVa *va; char *addrstr; SshIpAddr ipaddr; int i, addrlen, mask, oldflags, newflags; int inet_up = 0; #if defined(WITH_IPV6) && defined(INET6) int inet6_up = 0; #endif /* defined(WITH_IPV6) && defined(INET6) */ SSH_DEBUG(SSH_D_HIGHOK, ("configure ifnum %d", (int)adapter_ifnum)); if (!(va = vxworks_va_find_va(adapter_ifnum))) { SSH_TRACE( SSH_D_ERROR, ("trying to get status of a nonexistent ifnum %d", (int)adapter_ifnum)); if (callback) callback( SSH_VIRTUAL_ADAPTER_ERROR_NONEXISTENT, adapter_ifnum, NULL, SSH_VIRTUAL_ADAPTER_STATE_UNDEFINED, NULL, context); return; } /* Check addresses to determine IFF_INET_UP and IFF_INET6_UP status */ if (adapter_state != SSH_VIRTUAL_ADAPTER_STATE_DOWN && addresses) { for (i = 0; i < num_addresses; i++) { ipaddr = &addresses[i]; if (SSH_IP_IS4(ipaddr)) inet_up = 1; #if defined(WITH_IPV6) && defined(INET6) else if (SSH_IP_IS6(ipaddr)) inet6_up = 1; #endif /* defined(WITH_IPV6) && defined(INET6) */ } } /* Clear addresses if new addresses are being configured or interface is being turned off */ if (addresses || adapter_state == SSH_VIRTUAL_ADAPTER_STATE_DOWN) { for (i = 0; i < va->ip4addr_num; i++) { addrstr = va->ip4addr_tab[i]; SSH_DEBUG( SSH_D_MIDOK, ("deleting IPv4 address %s on %s, ifnum %d", addrstr, va->name, (int)va->ifnum)); if (ifAddrDelete(va->name, addrstr) != OK) SSH_TRACE( SSH_D_ERROR, ("%s: deleting IPv4 address %s failed", va->name, addrstr)); } va->ip4addr_num = 0; if (ifRouteDelete(vxworks_va_devname, va->end.devObject.unit) == ERROR) SSH_TRACE(SSH_D_ERROR, ("%s: deleting IPv4 routes failed", va->name)); #if defined(WITH_IPV6) && defined(INET6) for (i = 0; i < va->ip6addr_num; i++) { addrstr = va->ip6addr_tab[i]; SSH_DEBUG( SSH_D_MIDOK, ("deleting IPv6 address %s on %s, ifnum %d", addrstr, va->name, (int)va->ifnum)); if (if6AddrDelete(va->name, addrstr) != OK) SSH_TRACE( SSH_D_ERROR, ("%s: deleting IPv6 address %s failed", va->name, addrstr)); } va->ip6addr_num = 0; #endif /* defined(WITH_IPV6) && defined(INET6) */ } /* Set interface status. */ if (ifFlagGet(va->name, &oldflags) != OK) { SSH_TRACE(SSH_D_ERROR, ("%s: cannot get interface flags")); return; } newflags = oldflags; if (inet_up #if defined(WITH_IPV6) && defined(INET6) || inet6_up #endif /* defined(WITH_IPV6) && defined(INET6) */ ) newflags |= IFF_UP; else newflags &= ~IFF_UP; #if VXWORKS_NETVER >= 55122 if (inet_up) newflags |= IFF_INET_UP; else newflags &= ~IFF_INET_UP; #if defined(WITH_IPV6) && defined(INET6) if (inet6_up) newflags |= IFF_INET6_UP; else newflags &= ~IFF_INET6_UP; #endif /* defined(WITH_IPV6) && defined(INET6) */ #endif /* VXWORKS_NETVER >= 55122 */ if (newflags != oldflags && ifFlagSet(va->name, newflags) != OK) { SSH_TRACE(SSH_D_ERROR, ("%s: cannot set interface flags")); return; } /* Add addresses if the addresses parameter is non-NULL and interface is not being turned off */ if (addresses && adapter_state != SSH_VIRTUAL_ADAPTER_STATE_DOWN) { for (i = 0; i < num_addresses; i++) { ipaddr = &addresses[i]; if (SSH_IP_IS4(ipaddr)) { if (va->ip4addr_num >= sizeof va->ip4addr_tab / sizeof va->ip4addr_tab[0]) { SSH_TRACE( SSH_D_ERROR, ("%s: too many IPv4 addresses, ignoring some", va->name)); break; } addrstr = va->ip4addr_tab[va->ip4addr_num]; addrlen = sizeof va->ip4addr_tab[va->ip4addr_num]; ssh_ipaddr_print(ipaddr, addrstr, addrlen); SSH_DEBUG( SSH_D_MIDOK, ("adding IPv4 address %s on %s, ifnum %d", addrstr, va->name, (int)va->ifnum)); mask = ~((1 << (32 - SSH_IP_MASK_LEN(ipaddr))) - 1) & 0xffffffff; if (ifAddrAdd(va->name, addrstr, NULL, mask) != OK) { SSH_TRACE( SSH_D_ERROR, ("%s: adding IPv4 address %s failed", va->name, addrstr)); continue; } va->ip4addr_num++; } #if defined(WITH_IPV6) && defined(INET6) else if (SSH_IP_IS6(ipaddr)) { if (va->ip6addr_num >= sizeof va->ip6addr_tab / sizeof va->ip6addr_tab[0]) { SSH_TRACE( SSH_D_ERROR, ("%s: too many IPv6 addresses, ignoring some", va->name)); break; } addrstr = va->ip6addr_tab[va->ip6addr_num]; addrlen = sizeof va->ip6addr_tab[va->ip6addr_num]; ssh_ipaddr_print(ipaddr, addrstr, addrlen); SSH_DEBUG( SSH_D_MIDOK, ("adding IPv6 address %s on %s, ifnum %d", addrstr, va->name, (int)va->ifnum)); if (if6AddrAdd(va->name, addrstr, SSH_IP_MASK_LEN(ipaddr), 0) != OK) { SSH_TRACE( SSH_D_ERROR, ("%s: adding IPv6 address %s failed", va->name, addrstr)); continue; } va->ip6addr_num++; } #endif /* defined(WITH_IPV6) && defined(INET6) */ } } /* Change MTU */ if (params && params->mtu > 0) MIB_VAR_UPDATE(va->end.pMib2Tbl, M2_varId_ifMtu, (ULONG)params->mtu); /* Toggle IFF_UP twice to cause an interface event with up-to-date addresses in effect. */ if (ifFlagGet(va->name, &oldflags) != OK) { SSH_TRACE(SSH_D_ERROR, ("%s: cannot get interface flags")); vxworks_va_report( va, SSH_VIRTUAL_ADAPTER_ERROR_UNKNOWN_ERROR, callback, context); return; } newflags = oldflags ^ IFF_UP; if (ifFlagSet(va->name, newflags) != OK) { SSH_TRACE(SSH_D_ERROR, ("%s: cannot set interface flags")); vxworks_va_report( va, SSH_VIRTUAL_ADAPTER_ERROR_UNKNOWN_ERROR, callback, context); return; } newflags ^= IFF_UP; if (ifFlagSet(va->name, newflags) != OK) { SSH_TRACE(SSH_D_ERROR, ("%s: cannot set interface flags")); vxworks_va_report( va, SSH_VIRTUAL_ADAPTER_ERROR_UNKNOWN_ERROR, callback, context); return; } SSH_DEBUG( SSH_D_HIGHOK, ("configured %s, ifnum %d", va->name, (int)va->ifnum)); vxworks_va_report(va, SSH_VIRTUAL_ADAPTER_ERROR_OK, callback, context); }