static struct Qdisc *tbf_create_dflt_qdisc(struct Qdisc *sch, u32 limit) { struct Qdisc *q; struct rtattr *rta; int ret; q = qdisc_create_dflt(sch->dev, &bfifo_qdisc_ops, TC_H_MAKE(sch->handle, 1)); if (q) { rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; ret = q->ops->change(q, rta); kfree(rta); if (ret == 0) return q; } qdisc_destroy(q); } return NULL; }
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 void prep_diag_args( struct nogvl_args *args, struct sockaddr_nl *nladdr, struct rtattr *rta, struct diag_req *req, struct msghdr *msg) { memset(req, 0, sizeof(struct diag_req)); memset(nladdr, 0, sizeof(struct sockaddr_nl)); nladdr->nl_family = AF_NETLINK; req->nlh.nlmsg_len = sizeof(struct diag_req) + RTA_LENGTH(args->iov[2].iov_len); req->nlh.nlmsg_type = TCPDIAG_GETSOCK; req->nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req->nlh.nlmsg_pid = getpid(); req->r.idiag_states = (1<<TCP_ESTABLISHED) | (1<<TCP_LISTEN); rta->rta_type = INET_DIAG_REQ_BYTECODE; rta->rta_len = RTA_LENGTH(args->iov[2].iov_len); args->iov[0].iov_base = req; args->iov[0].iov_len = sizeof(struct diag_req); args->iov[1].iov_base = rta; args->iov[1].iov_len = sizeof(struct rtattr); prep_msghdr(msg, args, nladdr, 3); }
int parse_nexthops(struct nlmsghdr *n, struct rtmsg *r, int argc, char *argv) { char buf[1024]; struct rtattr *rta = (void*)buf; struct rtnexthop *rtnh; rta->rta_type = RTA_MULTIPATH; rta->rta_len = RTA_LENGTH(0); rtnh = RTA_DATA(rta); while (argc > 0) { if(strcmp(argv, "nexthop") != 0) { fprintf(stderr, "Error: \"nexthop\" or end of line is expected instead of \"%s\"\n", argv); exit(-1); } if(argc <= 1) { fprintf(stderr, "Error: unexpected end of line after \"nexthop\"\n"); exit(-1); } memset(rtnh, 0, sizeof(*rtnh)); rtnh->rtnh_len = sizeof(*rtnh); rta->rta_len += rtnh->rtnh_len; parse_one_nh(rta, rtnh, &argc, argv); rtnh = RTNH_NEXT(rtnh); } if(rta->rta_len > RTA_LENGTH(0)) addattr_l(n, 1024, RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); return 0; }
static void add_nexthops(ip_route_t *route, struct nlmsghdr *nlh, struct rtmsg *rtm) { char buf[ENCAP_RTA_SIZE]; struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; nexthop_t *nh; element e; rta->rta_type = RTA_MULTIPATH; rta->rta_len = RTA_LENGTH(0); rtnh = RTA_DATA(rta); for (e = LIST_HEAD(route->nhs); e; ELEMENT_NEXT(e)) { nh = ELEMENT_DATA(e); memset(rtnh, 0, sizeof(*rtnh)); rtnh->rtnh_len = sizeof(*rtnh); rta->rta_len += rtnh->rtnh_len; add_nexthop(nh, nlh, rtm, rta, sizeof(buf), rtnh); rtnh = RTNH_NEXT(rtnh); } if (rta->rta_len > RTA_LENGTH(0)) addattr_l(nlh, sizeof(buf), RTA_MULTIPATH, RTA_DATA(rta), RTA_PAYLOAD(rta)); }
/* Add remote address */ static int netlink_addroute(uint32_t ifa_index, uint8_t remote) { struct rtmsg *rtm; struct rtattr *rta; uint32_t reqlen = NLMSG_LENGTH(NLMSG_ALIGN(sizeof(*rtm)) + RTA_SPACE(1) + RTA_SPACE(sizeof(ifa_index))); struct req { struct nlmsghdr nlh; char buf[512]; } req = { .nlh = { .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | NLM_F_APPEND, .nlmsg_type = RTM_NEWROUTE, .nlmsg_pid = getpid(), .nlmsg_len = reqlen, }, }; size_t buflen = sizeof(req.buf) - sizeof(*rtm); int fd; int error; struct sockaddr_nl addr = { .nl_family = AF_NETLINK, }; rtm = NLMSG_DATA(&req.nlh); rtm->rtm_family = AF_PHONET; rtm->rtm_dst_len = 6; rtm->rtm_src_len = 0; rtm->rtm_tos = 0; rtm->rtm_table = RT_TABLE_MAIN; rtm->rtm_protocol = RTPROT_STATIC; rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_type = RTN_UNICAST; rtm->rtm_flags = 0; rta = IFA_RTA(rtm); rta->rta_type = RTA_DST; rta->rta_len = RTA_LENGTH(1); *(uint8_t *)RTA_DATA(rta) = remote; rta = RTA_NEXT(rta, buflen); rta->rta_type = RTA_OIF; rta->rta_len = RTA_LENGTH(sizeof(ifa_index)); *(uint32_t *)RTA_DATA(rta) = ifa_index; fd = netlink_socket(); if (fd == -1) return -errno; if (sendto(fd, &req, reqlen, 0, (void *)&addr, sizeof(addr)) == -1) error = -errno; else error = netlink_getack(fd); close(fd); return error; }
void Secondary_Ipaddr_Handler::fill_rtnetlink_request ( nlmsghdr &hdr, int type, void *data, int data_length) { // points to the end of the aligned header struct rtattr *rta = reinterpret_cast <struct rtattr*> (((reinterpret_cast <char*>(&hdr)) + NLMSG_ALIGN (hdr.nlmsg_len))); rta->rta_type = type; rta->rta_len = RTA_LENGTH (data_length); ACE_OS::memcpy (RTA_DATA(rta), data, data_length); hdr.nlmsg_len = NLMSG_ALIGN (hdr.nlmsg_len) + RTA_LENGTH (data_length); }
int nl_set_ifaddr(struct in_addr ifaddr, struct in_addr bcaddr, int ifindex) { struct { struct ifaddrmsg ifa; struct { struct rtattr rta; struct in_addr addr; } data[3]; } m; memset(&m, 0, sizeof(m)); m.ifa.ifa_family = AF_INET; if (IN_CLASSA(ifaddr.s_addr)) m.ifa.ifa_prefixlen = IN_CLASSA_NSHIFT; else if (IN_CLASSB(ifaddr.s_addr)) m.ifa.ifa_prefixlen = IN_CLASSB_NSHIFT; else if (IN_CLASSC(ifaddr.s_addr)) m.ifa.ifa_prefixlen = IN_CLASSC_NSHIFT; else if (IN_CLASSD(ifaddr.s_addr)) m.ifa.ifa_prefixlen = 0; m.ifa.ifa_prefixlen = 24; m.ifa.ifa_flags = 0; //IFA_F_PERMANENT; m.ifa.ifa_scope = RT_SCOPE_UNIVERSE; m.ifa.ifa_index = ifindex; m.data[0].rta.rta_len = RTA_LENGTH(sizeof(ifaddr)); m.data[0].rta.rta_type = IFA_LOCAL; m.data[0].addr.s_addr = ifaddr.s_addr; m.data[1].rta.rta_len = RTA_LENGTH(sizeof(ifaddr)); m.data[1].rta.rta_type = IFA_ADDRESS; m.data[1].addr.s_addr = ifaddr.s_addr; m.data[2].rta.rta_len = RTA_LENGTH(sizeof(ifaddr)); m.data[2].rta.rta_type = IFA_BROADCAST; m.data[2].addr.s_addr = bcaddr.s_addr; DEBUG(LOG_DEBUG, 0, "Sending new ifaddr %s %s netlink message index=%d", ip_to_str(ifaddr), ip_to_str(bcaddr), ifindex); return nl_create_and_send_msg(rtnlsock, RTM_NEWADDR, &m, sizeof(m)); }
/* * ./ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID> */ int main(int argc, char **argv) { struct rtattr *rta; int intf_index, pid, rtnetlink_socket; if (argc != 3) { tst_resm(TINFO, "%s <INTERFACE_NAME> <NAMESPACE_PID>\n", argv[0]); return 1; } intf_index = get_intf_index_from_name(argv[1]); if (intf_index == -1) { tst_resm(TINFO , "unable to get interface index"); return 1; } pid = atoi(argv[2]); rtnetlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (rtnetlink_socket == -1) { tst_resm(TINFO | TERRNO, "socket"); return 1; } memset(&req, 0, sizeof(req)); req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)); req.nh.nlmsg_flags = NLM_F_REQUEST; req.nh.nlmsg_type = RTM_NEWLINK; req.ifi.ifi_family = AF_UNSPEC; req.ifi.ifi_index = intf_index; req.ifi.ifi_change = 0xffffffff; rta = (struct rtattr *)(((char *) &req) + NLMSG_ALIGN(req.nh.nlmsg_len)); rta->rta_type = IFLA_NET_NS_PID; rta->rta_len = RTA_LENGTH(sizeof(int)); req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) + RTA_LENGTH(sizeof(pid)); memcpy(RTA_DATA(rta), &pid, sizeof(pid)); if (send(rtnetlink_socket, &req, req.nh.nlmsg_len, 0) == -1) { tst_resm(TINFO | TERRNO, "send"); return 1; } close(rtnetlink_socket); return 0; }
int get_translation_table_info (int sd, int *status, char *buff, size_t size) { struct { struct nlmsghdr n; struct ndmsg r; char buf[1024]; } req; struct rtattr *rta; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH (sizeof(struct ndmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT; req.n.nlmsg_type = RTM_GETNEIGH; req.r.ndm_family = AF_INET6; rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len)); rta->rta_len = RTA_LENGTH(16); if(send(sd, &req, req.n.nlmsg_len, 0) < 0) { snmp_log(LOG_ERR,"Sending request failed\n"); return -1; } if((*status = recv(sd, buff, size, 0)) < 0) { snmp_log(LOG_ERR,"Recieving request failed\n"); return -1; } if(*status == 0) { snmp_log(LOG_ERR,"End of file\n"); return -1; } return 0; }
int route_del(struct sockaddr_storage *destination, struct sockaddr_storage *gateway,int prefix,unsigned int metric){ struct rtnl_handle rth; // structure of the netlink packet. struct{ struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; char mxbuf[256]; struct rtattr * mxrta = (void*)mxbuf; //unsigned mxlock = 0; memset(&req, 0, sizeof(req)); // Initialisation of a few parameters req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE; req.n.nlmsg_type = RTM_DELROUTE; req.r.rtm_family = destination->ss_family; req.r.rtm_table = get_eigrp_routing_table_number(); req.r.rtm_dst_len = prefix; req.r.rtm_protocol = get_eigrp_routing_protocol_number(); req.r.rtm_scope = RT_SCOPE_UNIVERSE; req.r.rtm_type = RTN_UNICAST; mxrta->rta_type = RTA_METRICS; mxrta->rta_len = RTA_LENGTH(0); // RTA_DST and RTA_GW are the two esential parameters for adding a route // for ipv4, the length of the address is 4 bytes. if(destination->ss_family == AF_INET){ struct sockaddr_in *dest = (struct sockaddr_in *)destination; struct sockaddr_in *gate = (struct sockaddr_in *)gateway; addattr_l(&req.n, sizeof(req), RTA_DST, &dest->sin_addr.s_addr, 4); addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &gate->sin_addr.s_addr, 4); }else{ struct sockaddr_in6 *dest = (struct sockaddr_in6 *)destination; struct sockaddr_in6 *gate = (struct sockaddr_in6 *)gateway; addattr_l(&req.n, sizeof(req), RTA_DST, &dest->sin6_addr.s6_addr, sizeof(dest->sin6_addr.s6_addr)); addattr_l(&req.n, sizeof(req), RTA_GATEWAY, &gate->sin6_addr.s6_addr, sizeof(dest->sin6_addr.s6_addr)); } addattr_l(&req.n, sizeof(req), RTA_PRIORITY, &metric, sizeof(metric)); int status = 0; // opening the netlink socket to communicate with the kernel if (rtnl_open(&rth, 0) < 0){ printf("cannot open rtnetlink\n"); return -1; } // sending the packet to the kernel. status = rtnl_talk(&rth, &req.n, 0, 0, NULL); if (status < 0) return status; rtnl_close(&rth); return 0; }
static int set_fifo_limit(struct Qdisc *q, int limit) { struct rtattr *rta; int ret = -ENOMEM; rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; ret = q->ops->change(q, rta); kfree(rta); } return ret; }
/* If successful the updated message will be correctly aligned, if unsuccessful the old message is untouched. */ static int add_rtattr(sd_netlink_message *m, unsigned short type, const void *data, size_t data_length) { uint32_t rta_length; size_t message_length, padding_length; struct nlmsghdr *new_hdr; struct rtattr *rta; char *padding; unsigned i; int offset; assert(m); assert(m->hdr); assert(!m->sealed); assert(NLMSG_ALIGN(m->hdr->nlmsg_len) == m->hdr->nlmsg_len); assert(!data || data_length); /* get offset of the new attribute */ offset = m->hdr->nlmsg_len; /* get the size of the new rta attribute (with padding at the end) */ rta_length = RTA_LENGTH(data_length); /* get the new message size (with padding at the end) */ message_length = offset + RTA_ALIGN(rta_length); /* realloc to fit the new attribute */ new_hdr = realloc(m->hdr, message_length); if (!new_hdr) return -ENOMEM; m->hdr = new_hdr; /* get pointer to the attribute we are about to add */ rta = (struct rtattr *) ((uint8_t *) m->hdr + offset); /* if we are inside containers, extend them */ for (i = 0; i < m->n_containers; i++) GET_CONTAINER(m, i)->rta_len += message_length - offset; /* fill in the attribute */ rta->rta_type = type; rta->rta_len = rta_length; if (data) /* we don't deal with the case where the user lies about the type * and gives us too little data (so don't do that) */ padding = mempcpy(RTA_DATA(rta), data, data_length); else { /* if no data was passed, make sure we still initialize the padding note that we can have data_length > 0 (used by some containers) */ padding = RTA_DATA(rta); } /* make sure also the padding at the end of the message is initialized */ padding_length = (uint8_t*)m->hdr + message_length - (uint8_t*)padding; memzero(padding, padding_length); /* update message size */ m->hdr->nlmsg_len = message_length; return offset; }
int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int family, int type, __u32 filt_mask) { struct { struct nlmsghdr nlh; struct ifinfomsg ifm; /* attribute has to be NLMSG aligned */ struct rtattr ext_req __attribute__ ((aligned(NLMSG_ALIGNTO))); __u32 ext_filter_mask; } req; memset(&req, 0, sizeof(req)); req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_DUMP|NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = rth->dump = ++rth->seq; req.ifm.ifi_family = family; req.ext_req.rta_type = IFLA_EXT_MASK; req.ext_req.rta_len = RTA_LENGTH(sizeof(__u32)); req.ext_filter_mask = filt_mask; return send(rth->fd, (void*)&req, sizeof(req), 0); }
static int sfq_change(struct Qdisc *sch, struct rtattr *opt) { struct sfq_sched_data *q = qdisc_priv(sch); struct tc_sfq_qopt *ctl = RTA_DATA(opt); unsigned int qlen; if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) return -EINVAL; sch_tree_lock(sch); q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1); qlen = sch->q.qlen; while (sch->q.qlen > q->limit) sfq_drop(sch); qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen); del_timer(&q->perturb_timer); if (q->perturb_period) { mod_timer(&q->perturb_timer, jiffies + q->perturb_period); get_random_bytes(&q->perturbation, 4); } sch_tree_unlock(sch); return 0; }
static int sfq_change(struct Qdisc *sch, struct rtattr *opt) { struct sfq_sched_data *q = (struct sfq_sched_data *)sch->data; struct tc_sfq_qopt *ctl = RTA_DATA(opt); if (opt->rta_len < RTA_LENGTH(sizeof(*ctl))) return -EINVAL; sch_tree_lock(sch); q->quantum = ctl->quantum ? : psched_mtu(sch->dev); q->perturb_period = ctl->perturb_period*HZ; if (ctl->limit) q->limit = min_t(u32, ctl->limit, SFQ_DEPTH); while (sch->q.qlen >= q->limit-1) sfq_drop(sch); del_timer(&q->perturb_timer); if (q->perturb_period) { q->perturb_timer.expires = jiffies + q->perturb_period; add_timer(&q->perturb_timer); } sch_tree_unlock(sch); return 0; }
static int nl_add_attr(struct nlmsghdr *nlm, int buflen, char *data, int type, int datalen) { struct rtattr *rta; if (NLMSG_ALIGN(nlm->nlmsg_len) + RTA_LENGTH(datalen) > buflen) return -1; rta = (struct rtattr *)(((char *)nlm) + NLMSG_ALIGN(nlm->nlmsg_len)); rta->rta_type = type; rta->rta_len = RTA_LENGTH(datalen); memcpy(RTA_DATA(rta), data, datalen); nlm->nlmsg_len = NLMSG_ALIGN(nlm->nlmsg_len) + RTA_LENGTH(datalen); return 0; }
void addattr(uint32_t attr, const void *data, int len) { int rlen = RTA_LENGTH(len); rtattr *rta = (rtattr *)(((uint8_t *)&n) + NLMSG_ALIGN(n.nlmsg_len)); rta->rta_type = attr; rta->rta_len = rlen; memcpy(RTA_DATA(rta), data, len); n.nlmsg_len = NLMSG_ALIGN(n.nlmsg_len) + rlen; }
void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) { struct rtattr *rta; int size = RTA_LENGTH(attrlen); rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); rta->rta_type = attrtype; rta->rta_len = size; memcpy(RTA_DATA(rta), data, attrlen); }
hidden void *rta_put(struct nlmsghdr *m, int type, int len) { struct rtattr *rta = (void *)m + NLMSG_ALIGN(m->nlmsg_len); int rtalen = RTA_LENGTH(len); rta->rta_type = type; rta->rta_len = rtalen; m->nlmsg_len = NLMSG_ALIGN(m->nlmsg_len) + RTA_ALIGN(rtalen); return RTA_DATA(rta); }
void addrta(struct nlmsghdr *n, int type, const void *data,int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; rta = NL_MSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NL_MSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); }
/* Pass size change message down to embedded FIFO */ static int set_fifo_limit(struct Qdisc *q, int limit) { struct rtattr *rta; int ret = -ENOMEM; /* Hack to avoid sending change message to non-FIFO */ if (strncmp(q->ops->id + 1, "fifo", 4) != 0) return 0; rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; ret = q->ops->change(q, rta); kfree(rta); } return ret; }
struct rtattr * rt_addAttr_hdr(struct nlmsghdr *n, int type) { struct rtattr *rta; int rlen = RTA_LENGTH(0); rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); rta->rta_type = type; rta->rta_len = rlen; n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + rlen; return rta; }
int FAST_FUNC addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) { int len = RTA_LENGTH(4); struct rtattr *rta; if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) return -1; rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); rta->rta_type = type; rta->rta_len = len; move_to_unaligned32(RTA_DATA(rta), data); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; return 0; }
int addattr32(struct nlmsghdr *n, int maxlen, int type, uint32_t data) { int len = RTA_LENGTH(4); struct rtattr *rta; if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) return -1; rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); rta->rta_type = type; rta->rta_len = len; memcpy(RTA_DATA(rta), &data, 4); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; return 0; }
/* Utility function comes from iproute2. Authors: Alexey Kuznetsov, <*****@*****.**> */ int addattr(struct nlmsghdr *n, int type, void *data, int alen) { struct rtattr *attr; int len = RTA_LENGTH(alen); attr = (struct rtattr *) (((char *) n) + NLMSG_ALIGN(n->nlmsg_len)); attr->rta_type = type; attr->rta_len = len; memcpy(RTA_DATA(attr), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; return 0; }
int tun_nlattr(struct nlmsghdr *n, int nsize, int type, void *d, int dlen) { int len = RTA_LENGTH(dlen); int alen = NLMSG_ALIGN(n->nlmsg_len); struct rtattr *rta = (struct rtattr*) (((void*)n) + alen); if (alen + len > nsize) return -1; rta->rta_len = len; rta->rta_type = type; memcpy(RTA_DATA(rta), d, dlen); n->nlmsg_len = alen + len; 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; }
int FAST_FUNC addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; if ((int)(NLMSG_ALIGN(n->nlmsg_len) + len) > maxlen) return -1; rta = (struct rtattr*)(((char*)n) + NLMSG_ALIGN(n->nlmsg_len)); rta->rta_type = type; rta->rta_len = len; memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len; return 0; }
int rta_addattr_l(struct rtattr *rta, int maxlen, int type, void *data, int alen) { struct rtattr *subrta; int len = RTA_LENGTH(alen); if (RTA_ALIGN(rta->rta_len) + len > maxlen) return -1; subrta = (struct rtattr*)(((char*)rta) + RTA_ALIGN(rta->rta_len)); subrta->rta_type = type; subrta->rta_len = len; memcpy(RTA_DATA(subrta), data, alen); rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; return 0; }