Ejemplo n.º 1
0
static void add_nla_stream_to_msg(struct nl_msg *msg, void *nla, size_t nla_len)
{
	struct nlattr *tail;
	struct nlmsghdr *hdr;

	LOG_DBG_("%s: Appending %u bytes of user defined attributes\n",
		 __func__, nla_len);
	hdr = nlmsg_hdr(msg);
	tail = nlmsg_tail(hdr);
	/* nla is assumed to be padded correctly,
	 * so we dont bother with padding
	 */
	memcpy(tail, nla, nla_len);
	hdr->nlmsg_len += nla_len;
}
Ejemplo n.º 2
0
cps_api_return_code_t nas_os_update_route (cps_api_object_t obj, msg_type m_type)
{
    static char buff[NL_RT_MSG_BUFFER_LEN]; // Allocate from DS
    char            addr_str[INET6_ADDRSTRLEN];
    memset(buff,0,sizeof(buff));

    cps_api_object_attr_t prefix   = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_ROUTE_PREFIX);
    cps_api_object_attr_t af       = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_AF);
    cps_api_object_attr_t nh_count = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_NH_COUNT);
    cps_api_object_attr_t pref_len = cps_api_object_attr_get(obj, BASE_ROUTE_OBJ_ENTRY_PREFIX_LEN);

    if (prefix == CPS_API_ATTR_NULL || af == CPS_API_ATTR_NULL ||  pref_len == CPS_API_ATTR_NULL
        || (m_type != NAS_RT_DEL && nh_count == CPS_API_ATTR_NULL)) {
        EV_LOG(ERR, NAS_OS, ev_log_s_CRITICAL, "ROUTE-UPD", "Missing route params");
        return cps_api_ret_code_ERR;
    }

    struct nlmsghdr *nlh = (struct nlmsghdr *)
                         nlmsg_reserve((struct nlmsghdr *)buff,sizeof(buff),sizeof(struct nlmsghdr));
    struct rtmsg * rm = (struct rtmsg *) nlmsg_reserve(nlh,sizeof(buff),sizeof(struct rtmsg));

    uint16_t flags = nas_os_get_nl_flags(m_type);
    uint16_t type = (m_type == NAS_RT_DEL)?RTM_DELROUTE:RTM_NEWROUTE;

    nas_os_pack_nl_hdr(nlh, type, flags);

    rm->rtm_table = RT_TABLE_MAIN;
    rm->rtm_protocol = RTPROT_UNSPEC; // This could be assigned to correct owner in future

    /* For route delete, initialize scope to no-where and
     * this will get updated to link when Nh addr/ifx is provided.
     */
    if (type != RTM_DELROUTE)
        rm->rtm_scope = RT_SCOPE_UNIVERSE;
    else
        rm->rtm_scope = RT_SCOPE_NOWHERE;

    rm->rtm_type = RTN_UNICAST;

    rm->rtm_dst_len = cps_api_object_attr_data_u32(pref_len);
    rm->rtm_family = (unsigned char) cps_api_object_attr_data_u32(af);

    uint32_t addr_len = (rm->rtm_family == AF_INET)?HAL_INET4_LEN:HAL_INET6_LEN;
    nlmsg_add_attr(nlh,sizeof(buff),RTA_DST,cps_api_object_attr_data_bin(prefix),addr_len);

    uint32_t nhc = 0;
    if (nh_count != CPS_API_ATTR_NULL) nhc = cps_api_object_attr_data_u32(nh_count);

    EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","NH count:%d family:%s msg:%s for prefix:%s len:%d scope:%d", nhc,
           ((rm->rtm_family == AF_INET) ? "IPv4" : "IPv6"), ((m_type == NAS_RT_ADD) ? "Route-Add" : ((m_type == NAS_RT_DEL) ? "Route-Del" : "Route-Set")),
           ((rm->rtm_family == AF_INET) ?
            (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(prefix), addr_str, INET_ADDRSTRLEN)) :
            (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(prefix), addr_str, INET6_ADDRSTRLEN))),
           rm->rtm_dst_len, rm->rtm_scope);

    if (nhc == 1) {
        cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
                                     0, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);
        cps_api_object_attr_t gw = cps_api_object_e_get(obj,ids,ids_len);
        if (gw != CPS_API_ATTR_NULL) {
            nlmsg_add_attr(nlh,sizeof(buff),RTA_GATEWAY,cps_api_object_attr_data_bin(gw),addr_len);
            rm->rtm_scope = RT_SCOPE_UNIVERSE; // set scope to universe when gateway is specified
            EV_LOG(INFO, NAS_OS, 2,"ROUTE-UPD","NH:%s scope:%d",
                   ((rm->rtm_family == AF_INET) ?
                    (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(gw), addr_str, INET_ADDRSTRLEN)) :
                    (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(gw), addr_str, INET6_ADDRSTRLEN))),
                   rm->rtm_scope);
        } else {
            EV_LOG(INFO, NAS_OS, ev_log_s_MINOR, "ROUTE-UPD", "Missing Gateway, could be intf route");
            /*
             * This could be an interface route, do not return from here!
             */
        }

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
        cps_api_object_attr_t gwix = cps_api_object_e_get(obj,ids,ids_len);
        if (gwix != CPS_API_ATTR_NULL) {
            if (gw == CPS_API_ATTR_NULL) {
                rm->rtm_scope = RT_SCOPE_LINK;
            }

            EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","out-intf: %d scope:%d",
                   (int)cps_api_object_attr_data_u32(gwix), rm->rtm_scope);
            nas_nl_add_attr_int(nlh,sizeof(buff),RTA_OIF,gwix);
        }

        ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_WEIGHT;
        cps_api_object_attr_t weight = cps_api_object_e_get(obj,ids,ids_len);
        if (weight != CPS_API_ATTR_NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_PRIORITY,weight);

    } else if (nhc > 1){
        struct nlattr * attr_nh = nlmsg_nested_start(nlh, sizeof(buff));

        attr_nh->nla_len = 0;
        attr_nh->nla_type = RTA_MULTIPATH;
        size_t ix = 0;
        for (ix = 0; ix < nhc ; ++ix) {
            struct rtnexthop * rtnh =
                (struct rtnexthop * )nlmsg_reserve(nlh,sizeof(buff), sizeof(struct rtnexthop));
            memset(rtnh,0,sizeof(*rtnh));

            cps_api_attr_id_t ids[3] = { BASE_ROUTE_OBJ_ENTRY_NH_LIST,
                                         ix, BASE_ROUTE_OBJ_ENTRY_NH_LIST_NH_ADDR};
            const int ids_len = sizeof(ids)/sizeof(*ids);
            cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL) {
                nlmsg_add_attr(nlh,sizeof(buff),RTA_GATEWAY,
                               cps_api_object_attr_data_bin(attr),addr_len);
                rm->rtm_scope = RT_SCOPE_UNIVERSE; // set scope to universe when gateway is specified
                EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","MP-NH:%d %s scope:%d",ix,
                       ((rm->rtm_family == AF_INET) ?
                        (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(attr), addr_str, INET_ADDRSTRLEN)) :
                        (inet_ntop(rm->rtm_family, cps_api_object_attr_data_bin(attr), addr_str, INET6_ADDRSTRLEN))),
                       rm->rtm_scope);
            } else {
                EV_LOG(ERR, NAS_OS, ev_log_s_CRITICAL, "ROUTE-UPD", "Error - Missing Gateway");
                return cps_api_ret_code_ERR;
            }

            ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_IFINDEX;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL)
                rtnh->rtnh_ifindex = (int)cps_api_object_attr_data_u32(attr);

            ids[2] = BASE_ROUTE_OBJ_ENTRY_NH_LIST_WEIGHT;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr != CPS_API_ATTR_NULL) rtnh->rtnh_hops = (char)cps_api_object_attr_data_u32(attr);

            rtnh->rtnh_len = (char*)nlmsg_tail(nlh) - (char*)rtnh;
        }
        nlmsg_nested_end(nlh,attr_nh);
    }

    t_std_error rc = nl_do_set_request(nas_nl_sock_T_ROUTE,nlh,buff,sizeof(buff));
    int err_code = STD_ERR_EXT_PRIV (rc);
    EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","Netlink error_code %d", err_code);

    /*
     * Return success if the error is exist, in case of addition, or
     * no-exist, in case of deletion. This is because, kernel might have
     * deleted the route entries (when interface goes down) but has not sent netlink
     * events for those routes and RTM is trying to delete after that.
     * Similarly, during ip address configuration, kernel may add the routes
     * before RTM tries to configure kernel.
     *
     */
    if(err_code == ESRCH || err_code == EEXIST ) {
        EV_LOG(INFO, NAS_OS,2,"ROUTE-UPD","No such process or Entry already exists");
        /*
         * Kernel may or may not have the routes but NAS routing needs to be informed
         * as is from kernel netlink to program NPU for the route addition/deletion to
         * ensure stale routes are cleaned
         */
        if(err_code == ESRCH)
            nas_os_publish_route(RTM_DELROUTE, obj);
        else
            nas_os_publish_route(RTM_NEWROUTE, obj);
        rc = STD_ERR_OK;
    }

    return rc;

}
Ejemplo n.º 3
0
static cps_api_return_code_t _op(cps_api_operation_types_t op,void * context, cps_api_object_t obj, cps_api_object_t prev) {

    char buff[1024];
    memset(buff,0,sizeof(buff));
    cps_api_object_attr_t list[cps_api_if_ROUTE_A_MAX];
    cps_api_object_attr_fill_list(obj,0,list,sizeof(list)/sizeof(*list));

    if (list[cps_api_if_ROUTE_A_PREFIX]==NULL) return cps_api_ret_code_ERR;
    if (list[cps_api_if_ROUTE_A_PREFIX_LEN]==NULL) return cps_api_ret_code_ERR;
    if (list[cps_api_if_ROUTE_A_FAMILY]==NULL) return cps_api_ret_code_ERR;

    uint32_t prefix_len =  cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_PREFIX_LEN]);

    struct nlmsghdr *nlh = (struct nlmsghdr *) nlmsg_reserve((struct nlmsghdr *)buff,sizeof(buff),sizeof(struct nlmsghdr));
    struct rtmsg * rm = (struct rtmsg *) nlmsg_reserve(nlh,sizeof(buff),sizeof(struct rtmsg));

    //sizeof structure + attrs nlh->nlmsg_len
    nlh->nlmsg_pid = 0;
    nlh->nlmsg_seq = 0;
    nlh->nlmsg_type =RTM_NEWROUTE;
    nlh->nlmsg_flags =  NLM_F_REQUEST | NLM_F_ACK ;

    if (op==cps_api_oper_CREATE) {
        nlh->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
    }
    if (op==cps_api_oper_SET) {
        nlh->nlmsg_flags |=NLM_F_REPLACE;
    }
    if (op==cps_api_oper_DELETE) {
        nlh->nlmsg_type =RTM_DELROUTE;
    }

    rm->rtm_table = RT_TABLE_MAIN;
    rm->rtm_protocol = RTPROT_BOOT;
    rm->rtm_dst_len = prefix_len;
    rm->rtm_scope = RT_SCOPE_UNIVERSE;
    rm->rtm_type = RTN_UNICAST;

    rm->rtm_family = (unsigned char) cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_FAMILY]);

    EV_LOG(INFO,NETLINK,3,"ROUTEADD","Family is %d",rm->rtm_family);

    if (list[cps_api_if_ROUTE_A_PREFIX]!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_DST,list[cps_api_if_ROUTE_A_PREFIX]);

    if (list[cps_api_if_ROUTE_A_HOP_COUNT]==NULL) return cps_api_ret_code_ERR;
    uint32_t hc =  cps_api_object_attr_data_u32(list[cps_api_if_ROUTE_A_HOP_COUNT]);
    EV_LOG(INFO,NETLINK,3,"ROUTEADD","hopcount is %d",hc);

    if (hc==1) {
        cps_api_attr_id_t ids[3] = { cps_api_if_ROUTE_A_NH, 0, cps_api_if_ROUTE_A_NEXT_HOP_ADDR};
        const int ids_len = sizeof(ids)/sizeof(*ids);
        cps_api_object_attr_t gw = cps_api_object_e_get(obj,ids,ids_len);

        EV_LOG(INFO,NETLINK,3,"ROUTEADD","nh addr is %d",(int)(size_t)gw);
        if (gw!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_GATEWAY,gw);

        ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
        cps_api_object_attr_t gwix = cps_api_object_e_get(obj,ids,ids_len);
        EV_LOG(INFO,NETLINK,3,"ROUTEADD","nh index is %d",(int)(size_t)gwix);
        if (gwix!=NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_OIF,gwix);

        ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_WEIGHT;
        cps_api_object_attr_t weight = cps_api_object_e_get(obj,ids,ids_len);
        if (weight!=NULL) nas_nl_add_attr_int(nlh,sizeof(buff),RTA_PRIORITY,weight);

    } else {
        struct nlattr * attr_nh = nlmsg_nested_start(nlh, sizeof(buff));

        attr_nh->nla_len = 0;
        attr_nh->nla_type = RTA_MULTIPATH;
        size_t ix = 0;
        for (ix = 0; ix < hc ; ++ix) {
            struct rtnexthop * rtnh = (struct rtnexthop * )nlmsg_reserve(nlh,sizeof(buff), sizeof(struct rtnexthop));
            memset(rtnh,0,sizeof(*rtnh));

            cps_api_attr_id_t ids[3] = { cps_api_if_ROUTE_A_NH, ix, cps_api_if_ROUTE_A_NEXT_HOP_ADDR};
            const int ids_len = sizeof(ids)/sizeof(*ids);
            cps_api_object_attr_t attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) nas_nl_add_attr_ip(nlh,sizeof(buff),RTA_GATEWAY,attr);

            ids[2] = cps_api_if_ROUTE_A_NH_IFINDEX;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_ifindex = (int)cps_api_object_attr_data_u32(attr);

            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_WEIGHT;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_hops = (char)cps_api_object_attr_data_u32(attr);

            ids[2] = cps_api_if_ROUTE_A_NEXT_HOP_FLAGS;
            attr = cps_api_object_e_get(obj,ids,ids_len);
            if (attr!=NULL) rtnh->rtnh_flags = (char)cps_api_object_attr_data_u32(attr);


            rtnh->rtnh_len = (char*)nlmsg_tail(nlh) - (char*)rtnh;
        }
        nlmsg_nested_end(nlh,attr_nh);
    }
    return (cps_api_return_code_t) nl_do_set_request(nas_nl_sock_T_ROUTE,nlh,buff,sizeof(buff));
}