static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n, int attrtype) { int argc = *argcp; char **argv = *argvp; struct ifla_vlan_qos_mapping m; struct rtattr *tail; tail = NLMSG_TAIL(n); addattr_l(n, 1024, attrtype, NULL, 0); while (argc > 0) { char *colon = strchr(*argv, ':'); if (!colon) break; *colon = '\0'; if (get_u32(&m.from, *argv, 0)) return 1; if (get_u32(&m.to, colon + 1, 0)) return 1; argc--, argv++; addattr_l(n, 1024, IFLA_VLAN_QOS_MAPPING, &m, sizeof(m)); } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *)tail; *argcp = argc; *argvp = argv; return 0; }
static int qdisc_tbf(struct qdisc_opt *qopt, struct nlmsghdr *n) { struct tc_tbf_qopt opt; __u32 rtab[256]; int Rcell_log = -1; unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */ struct rtattr *tail; memset(&opt, 0, sizeof(opt)); opt.rate.rate = qopt->rate; opt.limit = (double)qopt->rate * qopt->latency + qopt->buffer; opt.rate.mpu = conf_mpu; if (tc_calc_rtable(&opt.rate, rtab, Rcell_log, conf_mtu, linklayer) < 0) { log_ppp_error("shaper: failed to calculate rate table.\n"); return -1; } opt.buffer = tc_calc_xmittime(opt.rate.rate, qopt->buffer); tail = NLMSG_TAIL(n); addattr_l(n, TCA_BUF_MAX, TCA_OPTIONS, NULL, 0); addattr_l(n, TCA_BUF_MAX, TCA_TBF_PARMS, &opt, sizeof(opt)); addattr_l(n, TCA_BUF_MAX, TCA_TBF_RTAB, rtab, 1024); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
int form_request_add() { int ifcn = 1; //interface number bzero(&req, sizeof(req)); req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); rtap = NLMSG_TAIL(&req.nl); rtap->rta_type = RTA_DST; rtap->rta_len = RTA_LENGTH(4); inet_pton(AF_INET, dsts, ((char *)rtap) + sizeof(struct rtattr)); req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rtap->rta_len); rtap = NLMSG_TAIL(&req.nl);; rtap->rta_type = RTA_OIF;//Output interface index rtap->rta_len = RTA_LENGTH(sizeof(int)); memcpy(((char *)rtap) + sizeof(struct rtattr), &ifcn, sizeof(int)); req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rtap->rta_len); req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK; req.nl.nlmsg_type = RTM_NEWROUTE; req.rt.rtm_family = AF_INET; req.rt.rtm_table = RT_TABLE_MAIN; req.rt.rtm_protocol = RTPROT_STATIC; req.rt.rtm_scope = RT_SCOPE_UNIVERSE; req.rt.rtm_type = RTN_UNICAST; req.rt.rtm_dst_len = pn; return 0; }
static int drr_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u32 tmp; tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); while (argc > 0) { if (strcmp(*argv, "quantum") == 0) { NEXT_ARG(); if (get_size(&tmp, *argv)) { fprintf(stderr, "Illegal \"quantum\"\n"); return -1; } addattr_l(n, 1024, TCA_DRR_QUANTUM, &tmp, sizeof(tmp)); } else if (strcmp(*argv, "help") == 0) { explain2(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain2(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *)tail; return 0; }
static int veth_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *hdr) { char *name = NULL; char *type = NULL; char *link = NULL; char *dev = NULL; int err, len; struct rtattr * data; if (strcmp(argv[0], "peer") != 0) { usage(); return -1; } data = NLMSG_TAIL(hdr); addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0); hdr->nlmsg_len += sizeof(struct ifinfomsg); err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, &name, &type, &link, &dev); if (err < 0) return err; if (name) { len = strlen(name) + 1; if (len > IFNAMSIZ) invarg("\"name\" too long\n", *argv); addattr_l(hdr, 1024, IFLA_IFNAME, name, len); } data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; return argc - 1 - err; }
int netlink_link_add_vmac(vrrp_rt *vrrp) { struct rtattr *linkinfo; interface *ifp; char ifname[IFNAMSIZ]; struct { struct nlmsghdr n; struct ifinfomsg ifi; char buf[256]; } req; if (!vrrp->ifp) return -1; memset(&req, 0, sizeof (req)); memset(ifname, 0, IFNAMSIZ); strncpy(ifname, vrrp->vmac_ifname, IFNAMSIZ - 1); req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; req.n.nlmsg_type = RTM_NEWLINK; req.ifi.ifi_family = AF_INET; /* macvlan settings */ linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind)); linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; addattr_l(&req.n, sizeof(req), IFLA_LINK, &IF_INDEX(vrrp->ifp), sizeof(uint32_t)); addattr_l(&req.n, sizeof(req), IFLA_IFNAME, ifname, strlen(ifname)); if (netlink_talk(&nl_cmd, &req.n) < 0) return -1; /* * Update interface queue and vrrp instance interface binding. * bring it UP ! */ netlink_interface_lookup(); ifp = if_get_by_ifname(ifname); if (!ifp) return -1; vrrp->ifp = ifp; vrrp->vmac |= 2; netlink_link_setlladdr(vrrp); netlink_link_up(vrrp); /* * By default MACVLAN interface are in VEPA mode which filters * out received packets whose MAC source address matches that * of the MACVLAN interface. Setting MACVLAN interface in private * mode will not filter based on source MAC address. */ netlink_link_setmode(vrrp); return 1; }
static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { unsigned limit = 0; unsigned target = 0; unsigned interval = 0; int ecn = -1; struct rtattr *tail; while (argc > 0) { if (strcmp(*argv, "limit") == 0) { NEXT_ARG(); if (get_unsigned(&limit, *argv, 0)) { fprintf(stderr, "Illegal \"limit\"\n"); return -1; } } else if (strcmp(*argv, "target") == 0) { NEXT_ARG(); if (get_time(&target, *argv)) { fprintf(stderr, "Illegal \"target\"\n"); return -1; } } else if (strcmp(*argv, "interval") == 0) { NEXT_ARG(); if (get_time(&interval, *argv)) { fprintf(stderr, "Illegal \"interval\"\n"); return -1; } } else if (strcmp(*argv, "ecn") == 0) { ecn = 1; } else if (strcmp(*argv, "noecn") == 0) { ecn = 0; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); if (limit) addattr_l(n, 1024, TCA_CODEL_LIMIT, &limit, sizeof(limit)); if (interval) addattr_l(n, 1024, TCA_CODEL_INTERVAL, &interval, sizeof(interval)); if (target) addattr_l(n, 1024, TCA_CODEL_TARGET, &target, sizeof(target)); if (ecn != -1) addattr_l(n, 1024, TCA_CODEL_ECN, &ecn, sizeof(ecn)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int veth_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *hdr) { char *dev = NULL; char *name = NULL; char *link = NULL; char *type = NULL; int index = 0; int err, len; struct rtattr * data; int group; struct ifinfomsg *ifm, *peer_ifm; unsigned int ifi_flags, ifi_change; if (strcmp(argv[0], "peer") != 0) { usage(); return -1; } ifm = NLMSG_DATA(hdr); ifi_flags = ifm->ifi_flags; ifi_change = ifm->ifi_change; ifm->ifi_flags = 0; ifm->ifi_change = 0; data = NLMSG_TAIL(hdr); addattr_l(hdr, 1024, VETH_INFO_PEER, NULL, 0); hdr->nlmsg_len += sizeof(struct ifinfomsg); err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, &name, &type, &link, &dev, &group, &index); if (err < 0) return err; if (name) { len = strlen(name) + 1; if (len > IFNAMSIZ) invarg("\"name\" too long\n", *argv); addattr_l(hdr, 1024, IFLA_IFNAME, name, len); } peer_ifm = RTA_DATA(data); peer_ifm->ifi_index = index; peer_ifm->ifi_flags = ifm->ifi_flags; peer_ifm->ifi_change = ifm->ifi_change; ifm->ifi_flags = ifi_flags; ifm->ifi_change = ifi_change; if (group != -1) addattr32(hdr, 1024, IFLA_GROUP, group); data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; return argc - 1 - err; }
static int dsmark_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u16 ind; char *end; int dflt,set_tc_index; ind = set_tc_index = 0; dflt = -1; while (argc > 0) { if (!strcmp(*argv,"indices")) { NEXT_ARG(); ind = strtoul(*argv,&end,0); if (*end) { explain(); return -1; } } else if (!strcmp(*argv,"default_index") || !strcmp(*argv, "default")) { NEXT_ARG(); dflt = strtoul(*argv,&end,0); if (*end) { explain(); return -1; } } else if (!strcmp(*argv,"set_tc_index")) { set_tc_index = 1; } else { explain(); return -1; } argc--; argv++; } if (!ind) { explain(); return -1; } tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); addattr_l(n,1024,TCA_DSMARK_INDICES,&ind,sizeof(ind)); if (dflt != -1) { __u16 tmp = dflt; addattr_l(n,1024,TCA_DSMARK_DEFAULT_INDEX,&tmp,sizeof(tmp)); } if (set_tc_index) addattr_l(n,1024,TCA_DSMARK_SET_TC_INDEX,NULL,0); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
int addraw_l(struct nlmsghdr *n, int maxlen, const void *data, int len) { if (NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len) > maxlen) { fprintf(stderr, "addraw_l ERROR: message exceeded bound of %d\n",maxlen); return -1; } memcpy(NLMSG_TAIL(n), data, len); memset((void *) NLMSG_TAIL(n) + len, 0, NLMSG_ALIGN(len) - len); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + NLMSG_ALIGN(len); return 0; }
int addraw_l(struct nlmsghdr *n, size_t maxlen, const void *data, size_t len) { size_t align_len = NLMSG_ALIGN(len); if (n->nlmsg_len + align_len > maxlen) return -1; memcpy(NLMSG_TAIL(n), data, len); memset((void *) NLMSG_TAIL(n) + len, 0, align_len - len); n->nlmsg_len += (uint32_t)align_len; return 0; }
static int psp_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct tc_psp_copt copt; struct rtattr *tail; memset(&copt, 0, sizeof(copt)); copt.mode = TC_PSP_MODE_STATIC; /* default mode */ while (argc > 0) { if (matches(*argv, "rate") == 0) { NEXT_ARG(); if (GET_RATE(&copt.rate, *argv)) { explain1("rate"); return -1; } } else if (matches(*argv, "mode") == 0) { NEXT_ARG(); if (get_u32(&copt.mode, *argv, 16)) { explain1("mode"); return -1; } } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } if (copt.mode == TC_PSP_MODE_NORMAL && copt.rate != 0) { fprintf(stderr, "You can not set to \"rate\" parameter " "in normal mode\n"); explain1("rate"); return -1; } else if (copt.mode == TC_PSP_MODE_STATIC && copt.rate == 0) { fprintf(stderr, "You need set to \"rate\" parameter " "in static target rate mode.\n"); explain1("rate"); return -1; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 1024, TCA_PSP_COPT, &copt, sizeof(copt)); tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail; return 0; }
struct rtattr *addattr_nest(struct nlmsghdr *n, int type) { struct rtattr *nest = NLMSG_TAIL(n); addattr_l(n, type, NULL, 0); return nest; }
static int psp_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct tc_psp_qopt qopt; struct rtattr *tail; memset(&qopt, 0, sizeof(qopt)); qopt.ifg = 12; while (argc > 0) { if (matches(*argv, "rate") == 0) { NEXT_ARG(); if (GET_RATE(&qopt.rate, *argv)) { explain1("rate"); return -1; } } else if (matches(*argv, "default") == 0) { NEXT_ARG(); if (get_u32(&qopt.defcls, *argv, 16)) { explain1("default"); return -1; } } else if (matches(*argv, "ifg") == 0) { NEXT_ARG(); if (get_u32(&qopt.ifg, *argv, 10)) { explain1("ifg"); return -1; } } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 1024, TCA_PSP_QOPT, &qopt, sizeof(qopt)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
std::string KernelNetlinkProtocol::build_vlan(uint16_t vlan_id, uint16_t link, const std::string& name) { struct { nlmsghdr nl_hdr; ifinfomsg if_msg; char buf[1024]; } req; memset(&req, 0, sizeof(req)); req.nl_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(req.if_msg)); req.nl_hdr.nlmsg_type = RTM_NEWLINK; req.nl_hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; req.nl_hdr.nlmsg_pid = cmd_local_addr_.nl_pid; req.nl_hdr.nlmsg_seq = ++seq_num; // physical device id, required addattr_32(&req.nl_hdr, sizeof(req), IFLA_LINK, link); if (!name.empty()) { addattr_l(&req.nl_hdr, sizeof(req), IFLA_IFNAME, name.c_str(), name.size() + 1); } // if (!address.empty()) // optional vlan MAC address setting // { // addattr_l(&req.nl_hdr, sizeof(req), IFLA_ADDRESS, address.data(), address.size()); // } rtattr* linkinfo = NLMSG_TAIL(&req.nl_hdr); addattr_l(&req.nl_hdr, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.nl_hdr, sizeof(req), IFLA_INFO_KIND, "vlan", strlen("vlan")); rtattr* data = NLMSG_TAIL(&req.nl_hdr); addattr_l(&req.nl_hdr, sizeof(req), IFLA_INFO_DATA, NULL, 0); addattr_l(&req.nl_hdr, sizeof(req), IFLA_VLAN_ID, &vlan_id, 2); // not adding vlan flags data->rta_len = (char *) NLMSG_TAIL(&req.nl_hdr) - (char *) data; linkinfo->rta_len = (char *) NLMSG_TAIL(&req.nl_hdr) - (char *) linkinfo; assert(req.nl_hdr.nlmsg_len > 0); return std::string(reinterpret_cast<char*>(&req), req.nl_hdr.nlmsg_len); }
static int netlink_link_setmode(vrrp_rt *vrrp) { int status = 1; struct { struct nlmsghdr n; struct ifinfomsg ifi; char buf[256]; } req; struct rtattr *linkinfo; struct rtattr *data; memset(&req, 0, sizeof (req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_NEWLINK; req.ifi.ifi_family = AF_INET; req.ifi.ifi_index = IF_INDEX(vrrp->xmit_ifp); linkinfo = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, (void *)ll_kind, strlen(ll_kind)); data = NLMSG_TAIL(&req.n); addattr_l(&req.n, sizeof(req), IFLA_INFO_DATA, NULL, 0); /* * In private mode, macvlan will receive frames with same MAC addr * as configured on the interface. */ #ifndef MACVLAN_MODE_VRRP #define MACVLAN_MODE_VRRP 16 #endif addattr32(&req.n, sizeof(req), IFLA_MACVLAN_MODE, MACVLAN_MODE_VRRP); data->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)data; linkinfo->rta_len = (void *)NLMSG_TAIL(&req.n) - (void *)linkinfo; if (netlink_talk(&nl_cmd, &req.n) < 0) status = -1; return status; }
static int wrr_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int ok=0; struct wrr_class_opt copt; struct rtattr *tail; copt.handle = 0; copt.quantum = 0; //printf("wrr_parse_class_opt.\n"); while (argc > 0) { if (strcmp(*argv, "quantum") == 0) { NEXT_ARG(); if (get_size(&copt.quantum, *argv)) { fprintf(stderr, "Illegal \"quantum\"\n"); return -1; } ok++; }else if (strcmp(*argv, "nfmark") == 0) { NEXT_ARG(); if (get_size(&copt.handle, *argv)) { fprintf(stderr, "Illegal \"nfmark\"\n"); return -1; } } else if (strcmp(*argv, "help") == 0) { explain2(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain2(); return -1; } argc--; argv++; } //printf("wrr_parse_class_opt ok %d q=%d h:%x.\n",ok,copt.quantum,copt.handle); if (ok) { tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 2024, TCA_WRR_PARAMS, &copt, sizeof(copt)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; } return 0; }
static int qdisc_htb_root(struct qdisc_opt *qopt, struct nlmsghdr *n) { struct tc_htb_glob opt; struct rtattr *tail; memset(&opt,0,sizeof(opt)); opt.rate2quantum = qopt->quantum; opt.version = 3; opt.defcls = qopt->defcls; tail = NLMSG_TAIL(n); addattr_l(n, TCA_BUF_MAX, TCA_OPTIONS, NULL, 0); addattr_l(n, TCA_BUF_MAX, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt))); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
struct rtattr *rta_begin_nested(struct link_req *req, int attr) { struct rtattr *rtattr = NLMSG_TAIL(&req->nh); if (rta_put(req, attr, NULL, 0)) return NULL; return rtattr; }
struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr) { struct rtattr *rtattr = NLMSG_TAIL(&nlmsg->nlmsghdr); if (nla_put_attr(nlmsg, attr)) return NULL; return rtattr; }
static int qdisc_htb_class(struct qdisc_opt *qopt, struct nlmsghdr *n) { struct tc_htb_opt opt; __u32 rtab[256],ctab[256]; int cell_log=-1,ccell_log = -1; unsigned mtu = conf_mtu ? conf_mtu : 1600; unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */ struct rtattr *tail; memset(&opt, 0, sizeof(opt)); opt.rate.rate = qopt->rate; opt.rate.mpu = conf_mpu; opt.ceil.rate = qopt->rate; opt.ceil.mpu = conf_mpu; if (tc_calc_rtable(&opt.rate, rtab, cell_log, mtu, linklayer) < 0) { log_ppp_error("shaper: failed to calculate rate table.\n"); return -1; } opt.buffer = tc_calc_xmittime(opt.rate.rate, qopt->buffer); if (tc_calc_rtable(&opt.ceil, ctab, ccell_log, mtu, linklayer) < 0) { log_ppp_error("shaper: failed to calculate ceil rate table.\n"); return -1; } opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, conf_cburst ? conf_cburst : qopt->buffer); if (qopt->quantum) opt.quantum = qopt->quantum; else if (conf_moderate_quantum) { unsigned int q = qopt->rate / conf_r2q; if (q < 1500 || q > 200000) opt.quantum = q < 1500 ? 1500 : 200000; } tail = NLMSG_TAIL(n); addattr_l(n, TCA_BUF_MAX, TCA_OPTIONS, NULL, 0); addattr_l(n, TCA_BUF_MAX, TCA_HTB_PARMS, &opt, sizeof(opt)); addattr_l(n, TCA_BUF_MAX, TCA_HTB_RTAB, rtab, 1024); addattr_l(n, TCA_BUF_MAX, TCA_HTB_CTAB, ctab, 1024); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
std::string KernelNetlinkProtocol::build_add_link(const std::string& kind, const std::string& name, const std::string& mac, const std::string& mtu) { struct { nlmsghdr nl_hdr; ifinfomsg if_msg; char buf[128]; } req; memset(&req, 0, sizeof(req)); req.nl_hdr.nlmsg_len = NLMSG_LENGTH(sizeof(req.if_msg)); req.nl_hdr.nlmsg_type = RTM_NEWLINK; req.nl_hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_EXCL; req.nl_hdr.nlmsg_pid = cmd_local_addr_.nl_pid; req.nl_hdr.nlmsg_seq = ++seq_num; if (!name.empty()) { addattr_l(&req.nl_hdr, sizeof(req), IFLA_IFNAME, name.c_str(), name.size() + 1); } if (!mac.empty()) { addattr_l(&req.nl_hdr, sizeof(req), IFLA_ADDRESS, tnt::MacAddress(mac).raw().data(), 6); } if (!mtu.empty()) { int m = std::stoi(mtu); addattr_l(&req.nl_hdr, sizeof(req), IFLA_MTU, &m, 4); } rtattr* linkinfo = NLMSG_TAIL(&req.nl_hdr); addattr_l(&req.nl_hdr, sizeof(req), IFLA_LINKINFO, NULL, 0); addattr_l(&req.nl_hdr, sizeof(req), IFLA_INFO_KIND, kind.data(), kind.size()); linkinfo->rta_len = reinterpret_cast<char*>(NLMSG_TAIL(&req.nl_hdr)) - reinterpret_cast<char*>(linkinfo); assert(req.nl_hdr.nlmsg_len > 0); return std::string(reinterpret_cast<char*>(&req), req.nl_hdr.nlmsg_len); }
struct nlattr * nest_start(struct nlmsghdr *nlh, unsigned short type) { struct nlattr *nest = NLMSG_TAIL(nlh); nest->nla_type = type; nlh->nlmsg_len += sizeof(struct nlattr); return nest; }
int tc_action_modify(int cmd, unsigned flags, int *argc_p, char ***argv_p) { int argc = *argc_p; char **argv = *argv_p; int ret = 0; struct rtattr *tail; struct { struct nlmsghdr n; struct tcamsg t; char buf[MAX_MSG]; } req; req.t.tca_family = AF_UNSPEC; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcamsg)); req.n.nlmsg_flags = NLM_F_REQUEST|flags; req.n.nlmsg_type = cmd; tail = NLMSG_TAIL(&req.n); argc -=1; argv +=1; if (parse_action(&argc, &argv, TCA_ACT_TAB, &req.n)) { fprintf(stderr, "Illegal \"action\"\n"); return -1; } tail->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail; if (rtnl_talk(&rth, &req.n, 0, 0, NULL) < 0) { fprintf(stderr, "We have an error talking to the kernel\n"); ret = -1; } *argc_p = argc; *argv_p = argv; return ret; }
static int wrr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { int ok=0; struct wrr_gopt gopt; struct rtattr *tail; //printf("wrr_parse_opt. \n"); while (argc > 0) { if (strcmp(*argv, "queues") == 0) { NEXT_ARG(); if (get_size(&gopt.total_queues, *argv)) { fprintf(stderr, "Illegal \"limit\"\n"); return -1; } ok++; } else if (strcmp(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } argc--; argv++; } //printf("wrr_parse_opt ok %d q=%d.\n",ok,gopt.total_queues); if (ok) { tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 2024, TCA_WRR_INIT, &gopt, sizeof(gopt)); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; } return 0; }
static inline int netlink_set_interface_flags(int ifindex, const sysctl_opts_t *sys_opts) { int status = 0; struct { struct nlmsghdr n; struct ifinfomsg ifi; char buf[64]; } req; struct nlattr *start; struct nlattr *inet_start; struct nlattr *conf_start; const sysctl_opts_t *so; memset(&req, 0, sizeof (req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct ifinfomsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_NEWLINK; req.ifi.ifi_family = AF_UNSPEC; req.ifi.ifi_index = ifindex; start = nest_start(&req.n, IFLA_AF_SPEC); inet_start = nest_start(&req.n, AF_INET); conf_start = nest_start(&req.n, IFLA_INET_CONF); for (so = sys_opts; so->param; so++) addattr32(&req.n, sizeof req, so->param, so->value); nest_end(NLMSG_TAIL(&req.n), conf_start); nest_end(NLMSG_TAIL(&req.n), inet_start); nest_end(NLMSG_TAIL(&req.n), start); if (netlink_talk(&nl_cmd, &req.n) < 0) status = 1; return status; }
static int dsmark_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct rtattr *tail; __u8 tmp; char *end; tail = NLMSG_TAIL(n); addattr_l(n,1024,TCA_OPTIONS,NULL,0); while (argc > 0) { if (!strcmp(*argv,"mask")) { NEXT_ARG(); tmp = strtoul(*argv,&end,0); if (*end) { explain_class(); return -1; } addattr_l(n,1024,TCA_DSMARK_MASK,&tmp,1); } else if (!strcmp(*argv,"value")) { NEXT_ARG(); tmp = strtoul(*argv,&end,0); if (*end) { explain_class(); return -1; } addattr_l(n,1024,TCA_DSMARK_VALUE,&tmp,1); } else { explain_class(); return -1; } argc--; argv++; } tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) { struct tc_htb_glob opt; struct rtattr *tail; unsigned i; char *p; memset(&opt,0,sizeof(opt)); opt.rate2quantum = 10; opt.version = 3; while (argc > 0) { if (matches(*argv, "r2q") == 0) { NEXT_ARG(); if (get_u32(&opt.rate2quantum, *argv, 10)) { explain1("r2q"); return -1; } } else if (matches(*argv, "default") == 0) { NEXT_ARG(); if (get_u32(&opt.defcls, *argv, 16)) { explain1("default"); return -1; } } else if (matches(*argv, "debug") == 0) { NEXT_ARG(); p = *argv; for (i=0; i<16; i++,p++) { if (*p<'0' || *p>'3') break; opt.debug |= (*p-'0')<<(2*i); } } else { printk(KERN_DEBUG "[MTC] [Q_HTB] What is \"%s\"?\n", *argv); return -1; } argc--; argv++; } tail = NLMSG_TAIL(n); addattr_l(n, 1024, TCA_OPTIONS, NULL, 0); addattr_l(n, 2024, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt))); tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; return 0; }
static int nla_put(struct nlmsg *nlmsg, int attr, const void *data, size_t len) { struct rtattr *rta; size_t rtalen = RTA_LENGTH(len); rta = NLMSG_TAIL(&nlmsg->nlmsghdr); rta->rta_type = attr; rta->rta_len = rtalen; memcpy(RTA_DATA(rta), data, len); nlmsg->nlmsghdr.nlmsg_len = NLMSG_ALIGN(nlmsg->nlmsghdr.nlmsg_len) + RTA_ALIGN(rtalen); return 0; }
static int rta_put(struct link_req *req, int attr, const void *data, size_t len) { struct rtattr *rta; size_t rtalen = RTA_LENGTH(len); rta = NLMSG_TAIL(&req->nh); rta->rta_type = attr; rta->rta_len = rtalen; memcpy(RTA_DATA(rta), data, len); req->nh.nlmsg_len = NLMSG_ALIGN(req->nh.nlmsg_len) + RTA_ALIGN(rtalen); return 0; }