/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipmip_if.c,v $ $Revision: 1.7.16.4 $ * $Source: /home/interpeak/CVSRoot/ipmip/src/ipmip_if.c,v $ * $Author: jsheng $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Joel Hortelius ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPCOM_SYSLOG_PRIORITY IPCOM_LOG_DEBUG2 #define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPMIP /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipmip_if_alloc *=========================================================================== * Description: Allocate and initialize the interface structure * Parameters: ctx - Context * proc - Process * ifsize - the size of the interface structure * ifname - The interface name * ifindex - The interface index. * cleanup - Function to be invoked prior to free. * Returns: The interface structure on success. */ IP_GLOBAL Ipmip_if_t * ipmip_if_alloc(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ip_size_t ifsize, const char *ifname, Ip_u32 ifindex, Ip_u8 type, Ip_u8 identity, Ipmip_if_cleanup_t cleanup) { Ipmip_if_t *iff = ipcom_calloc(1, ifsize); IPMIP_UNUSED_PARAMETER(ctx); IPMIP_UNUSED_PARAMETER(proc); if (iff == IP_NULL) return IP_NULL; iff->ifindex = ifindex; if (ifname) ipcom_strncpy(iff->ifname, ifname, IP_IFNAMSIZ); iff->type = type; iff->identity = identity; iff->lladdr = IP_NULL; iff->cleanup = cleanup; return iff; } /* *=========================================================================== * ipmip_if_free *=========================================================================== * Description: Destroy and free the interface specific data. * Parameters: ctx - Context * proc - Process * iff - the interface to destroy * Returns: */ IP_GLOBAL void ipmip_if_free(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff) { /* If we're in any list; remove us */ if (iff->next.head != IP_NULL) ipcom_list_remove(&iff->next); /* Invoke cleanup functionality */ if (iff->cleanup) (*iff->cleanup) (ctx, proc, iff); if (iff->lladdr) { ipcom_free(iff->lladdr); iff->lladdr = IP_NULL; } ipcom_free(iff); } /* *=========================================================================== * ipmip4_if_ioctl *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipmip_if_ioctl(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff, unsigned long ioctl, struct Ip_ifreq *ifreq) { if((IP_IFNAMSIZ - 1) < strlen(iff->ifname)) { return -1; } ipcom_strcpy(ifreq->ifr_name, iff->ifname); return ipmip_util_ioctl(ctx, proc, ioctl, ifreq); } /* *=========================================================================== * ipmip_if_get_flags *=========================================================================== * Description: Get the current interface flags. * Parameters: ctx - The context * proc - The process. * iff - The interface * flags - Where to store the flags. * Returns: IP_TRUE on success * */ IP_GLOBAL Ip_bool ipmip_if_get_flags(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff, Ip_u16 *flags) { struct Ip_ifreq ifreq; if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0) return IP_FALSE; *flags = ifreq.ifr_ifru.ifru_flags; return IP_TRUE; } /* *=========================================================================== * ipmip_if_set_flags *=========================================================================== * Description: Set the current interface flags. * Parameters: ctx - The context * proc - The process * iff - The interface * flags - The flags to set * Returns: IP_TRUE on success * */ IP_GLOBAL Ip_bool ipmip_if_set_flags(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff, Ip_u16 flags) { struct Ip_ifreq ifreq; if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0) return IP_FALSE; IP_BIT_SET(ifreq.ifr_ifru.ifru_flags, flags); if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0) return IP_FALSE; return IP_TRUE; } /* *=========================================================================== * ipmip_if_clear_flags *=========================================================================== * Description: Clear the current interface flags. * Parameters: iff - The interface * flags - The flags to clear * Returns: IP_TRUE on success * */ IP_GLOBAL Ip_bool ipmip_if_clear_flags(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff, Ip_u16 flags) { struct Ip_ifreq ifreq; if (ipmip_if_ioctl(ctx, proc, iff, IP_SIOCGIFFLAGS, &ifreq) < 0) return IP_FALSE; IP_BIT_CLR(ifreq.ifr_ifru.ifru_flags, flags); if (ipmip_util_ioctl(ctx, proc, IP_SIOCSIFFLAGS, &ifreq) < 0) return IP_FALSE; return IP_TRUE; } /* *=========================================================================== * ipmip_if_resolve_lla *=========================================================================== * Description: Resolve the LLA of the interface * Parameters: ctx - Context * proc - Process * iff - Interface * Returns: IP_TRUE on success; IP_FALSE otherwise. * */ IP_GLOBAL Ip_bool ipmip_if_resolve_lla(Ipmip_context_t *ctx, Ipmip_proc_t *proc, Ipmip_if_t *iff) { Ipmip_buffer_t req; Ipmip_buffer_t answer; struct Ip_ifinfomsg *ifi; struct Ip_nlmsghdr *nlh; int ret; Ip_size_t nlh_size; Ip_size_t addr_size = 0; Ip_u8 *addr_data = IP_NULL; ipmip_buffer_init(&req); ipmip_buffer_init(&answer); /**/ ipmip_netlink_nlmsghdr_request(&req, 0, 0, IP_RTM_GETLINK, 0); ifi = (struct Ip_ifinfomsg *)ipmip_buffer_offset(&req, ipmip_netlink_nlmsghdr_put(&req, IP_NULL, sizeof(*ifi))); ipcom_memset(ifi, 0, sizeof(*ifi)); ifi->ifi_family = IP_AF_LINK; ifi->ifi_index = iff->ifindex; ipmip_netlink_nlmsghdr_done(&req, 0); ret = ipmip_netlink_request(ctx, proc, ctx->nl_req, 0, 0, IPMIP_BUFFER_PTR(&req), &answer); ipmip_buffer_release(&req); if (ret < 0) return IP_FALSE; /* We've gotten an answer */ nlh = IPMIP_BUFFER_PTR(&answer); nlh_size = IPMIP_BUFFER_SIZE(&answer); /**/ while (IP_NLMSG_OK(nlh, nlh_size)) { /**/ if (nlh->nlmsg_type == IP_RTM_NEWLINK) { struct Ip_rtattr *iflap[IP_IFLA_MAX + 1]; Ip_u8 ll_type; Ip_u8 ll_subtype; /* Resolve this entry; I want the prefix length and the address */ ifi = IP_NLMSG_DATA(nlh); /* Parse */ ipmip_netlink_nlmsghdr_rta_parse(IP_IFLA_MAX + 1, IP_IFLA_RTA(ifi), IP_IFLA_PAYLOAD(nlh), iflap); if (ipmip_lladdr_arphdr_to_lltype(ifi->ifi_type, &ll_type, &ll_subtype)) { /* Need to subresolve any ethernet? */ if (ll_type == IPMIP_LLADDR_TYPE_MAC && ll_subtype == IPMIP_LLADDR_SUBTYPE_MAC_802_3) { struct Ip_rtattr *linfo = iflap[IP_IFLA_LINKINFO]; if (linfo) { linfo = ipmip_netlink_nlmsghdr_rta_find(IP_RTA_DATA(linfo), IP_RTA_PAYLOAD(linfo), IP_IFLA_INFO_KIND); if (linfo != IP_NULL) { if (ipcom_strcmp("vlan", IP_RTA_DATA(linfo)) == 0) ll_subtype = IPMIP_LLADDR_SUBTYPE_MAC_802_1Q; } } } /* Found one */ if (iflap[IP_IFLA_ADDRESS]) { /* Found a LLA address */ addr_size = IP_RTA_PAYLOAD(iflap[IP_IFLA_ADDRESS]); addr_data = IP_RTA_DATA(iflap[IP_IFLA_ADDRESS]); } /* Time to create */ /* Free old */ if (iff->lladdr != IP_NULL) ipcom_free(iff->lladdr); /* Initialize the structure; used in router advertisements */ iff->lladdr = ipmip_lladdr_build(IP_NULL, ll_type, ll_subtype, addr_data, addr_size); ipmip_buffer_release(&answer); return IP_TRUE; } else { IPCOM_LOG1(ERR, "UNSUCCESSFUL ARPHRD FOR %s", iff->ifname); } } /**/ nlh = IP_NLMSG_NEXT(nlh, nlh_size); } IPCOM_LOG1(ERR, "FAILED TO RESOLVE MAC FOR %s", iff->ifname); ipmip_buffer_release(&answer); return IP_FALSE; } /* *=========================================================================== * ipmip_if_findbyindex *=========================================================================== * Description: Locate an interface in our configuration based on index * Parameters: iflist - The list of interfaces * idx - The interface index * Returns: The interface pointer if it exists, IP_NULL otherwise. */ IP_GLOBAL Ipmip_if_t * ipmip_if_findbyindex(Ipcom_list *iflist, Ip_u32 idx) { Ipmip_if_t *iff; for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next)) { if (iff->ifindex == 0) continue; if (iff->ifindex == idx) return iff; } return IP_NULL; } /* *=========================================================================== * ipmip_if_findbyname *=========================================================================== * Description: Locate an interface in our configuration based on name. * Parameters: iflist - The list of interfaces. * ifname - The interface name * Returns: The interface pointer if it exists, IP_NULL otherwise. */ IP_GLOBAL Ipmip_if_t * ipmip_if_findbyname(Ipcom_list *iflist, const char *ifname) { Ipmip_if_t *iff; ip_assert(ifname); for (iff = IPCOM_LIST_FIRST(iflist); iff; iff = IPCOM_LIST_NEXT(&iff->next)) { if (*ifname == '\0' || ipcom_strcmp(iff->ifname, ifname) == 0) return iff; } return IP_NULL; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */