通过C代码配置can接口


struct set_req {
    struct nlmsghdr hdr;
    struct ifinfomsg ifi;
    char payload[1024];
};

#define NLMSG_TAIL(nmsg) ((struct rtattr*)(((char *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))

int addattr_l(struct nlmsghdr* n, unsigned int maxlen, int type, const void* data, int alen) {
    unsigned int len = RTA_LENGTH(alen);
    struct rtattr* rta;

    if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
        fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n", maxlen);
        return -1;
    }
    rta = NLMSG_TAIL(n);
    rta->rta_type = type;
    rta->rta_len = len;
    if (alen) memcpy(RTA_DATA(rta), data, alen);
    n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
    return 0;
}

struct rtattr* addattr_nest(struct nlmsghdr* n, int maxlen, int type) {
    struct rtattr* nest = NLMSG_TAIL(n);

    addattr_l(n, maxlen, type, nullptr, 0);
    return nest;
}

int addattr_nest_end(struct nlmsghdr* n, struct rtattr* nest) {
    nest->rta_len = (char*)NLMSG_TAIL(n) - (char*)nest;
    return n->nlmsg_len;
}

int addattr32(struct nlmsghdr* n, int maxlen, int type, __u32 data) {
    return addattr_l(n, maxlen, type, &data, sizeof(__u32));
}

bool setBitRate(const std::string& ifname, uint32_t bitrate) {
	int ret;
	can_bittiming bt{};
    rtattr *linkinfo = nullptr, *data = nullptr;
    const char* type = "can";
    set_seq req{};
    int ifindex = -1;
	int sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	
    req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(ifinfomsg));
    req.hdr.nlmsg_flags = NLM_F_REQUEST;
    req.hdr.nlmsg_type = RTM_NEWLINK;
    req.ifi.ifi_family = AF_UNSPEC;	
    
    ifindex = if_nametoindex(ifname.c_str());
    if (ifindex == 0) {
        fprintf(stderr, "no dev %s\n", ifname.c_str());
        return false;
    }
	addattr32(&req.hdr, sizeof(req), IFLA_LINK, ifindex);
	req.ifi.ifi_index = ifindex;
	linkinfo = addattr_nest(&req.hdr, sizeof(req), IFLA_LINKINFO);
    addattr_l(&req.hdr, sizeof(req), IFLA_INFO_KIND, (void*)type, strlen(type));
    data = addattr_nest(&req.hdr, sizeof(req), IFLA_INFO_DATA);
    addattr_l(&req.hdr, 1024, IFLA_CAN_BITTIMING, &bt, sizeof(bt));
    addattr_nest_end(&req.hdr, data);
    addattr_nest_end(&req.hdr, linkinfo);
    iovec iov = {
            .iov_base = &req.hdr,
            .iov_len = req.hdr.nlmsg_len,
    };

    sockaddr_nl nladdr = {
            .nl_family = AF_NETLINK,
    };

    msghdr msg = {
            .msg_name = &nladdr,
            .msg_namelen = sizeof(nladdr),
            .msg_iov = &iov,
            .msg_iovlen = 1,
    };

    req.hdr.nlmsg_flags |= NLM_F_ACK;
    req.hdr.nlmsg_seq = 1;
    
    ret = sendmsg(sock, &msg, 0);

    if (ret < 0) {
        // fprintf(stderr, "sendmsg FAIL:%s\n", strerror(errno));
        PLOG(ERROR) << "sendmsg FAIL:" << strerror(errno);
        return false;
    }

    return ret > 0;
}

struct netlink_req {
    struct nlmsghdr hdr;
    struct ifinfomsg ifi;
};

static void fill_message(struct netlink_req *req, const std::string &ifname) {
    req->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(req->ifi));
    req->hdr.nlmsg_type = RTM_NEWLINK;
    req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req->ifi.ifi_family = AF_UNSPEC;
    req->ifi.ifi_index = if_nametoindex(ifname.c_str());
}

bool ifup(const std::string &ifname) {
    struct netlink_req req{};
    struct sockaddr_nl kernel_sa{};
    int ret;

    int sock = socket_create();

    if (sock < 0)
        return -1;
    
    fill_message(&req, ifname);

    req.ifi.ifi_change = IFF_UP;
    req.ifi.ifi_flags |= IFF_UP;

    kernel_sa.nl_family = AF_NETLINK;
    struct iovec iov = {
        &req.hdr, 
        req.hdr.nlmsg_len,
    };

    struct msghdr msg = {
        &kernel_sa,
        sizeof(kernel_sa),
        &iov,
        1,
        nullptr,
        0,
        0,
    };

    ret = sendmsg(sock, &msg, 0);

    close(sock);

    return ret > 0;
}

bool ifdown(const std::string &ifname) {
    struct netlink_req req{};
    struct sockaddr_nl kernel_sa{};
    int ret;

    int sock = socket_create();
    if (sock < 0)
        return -1;

    fill_message(&req, ifname);

    req.ifi.ifi_change = IFF_UP;
    req.ifi.ifi_flags &= ~IFF_UP;

    kernel_sa.nl_family = AF_NETLINK;
    struct iovec iov = {
        &req.hdr, 
        req.hdr.nlmsg_len,
    };

    struct msghdr msg = {
        &kernel_sa,
        sizeof(kernel_sa),
        &iov,
        1,
        nullptr,
        0,
        0,
    };

    ret = sendmsg(sock, &msg, 0);

    close(sock);

    return ret > 0;
}

以上代码摘抄自iprout2

你可能感兴趣的:(常用小技巧,c语言,开发语言)