/* * debug string attribute */ void debug_rta_str(int lev, struct rtattr *rta, const char *name, char *str, unsigned len) { if(RTA_PAYLOAD(rta) > len) { rec_dbg(lev, "%s(%hu): -- payload too long --", name, RTA_ALIGN(rta->rta_len)); return; } char *p = (char *)malloc(len); if(p == NULL) return; memset(p, 0, len); /* always p[len] == NULL */ strncpy(p, (char *)RTA_DATA(rta), len - 1); rec_dbg(lev, "%s(%hu): %s", name, RTA_ALIGN(rta->rta_len), p); if(str) strncpy(str, p, len); free(p); return; }
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; }
/* * debug prio options */ void debug_tca_options_prio(int lev, struct rtattr *tca, const char *name) { struct tc_prio_qopt *qopt; char prio[MAX_STR_SIZE] = ""; char *p = prio; int i, len = sizeof(prio); if(debug_rta_len_chk(lev, tca, name, sizeof(*qopt))) return; qopt = (struct tc_prio_qopt *)RTA_DATA(tca); for(i = 0; i < TC_PRIO_MAX + 1; i++) { if(i == TC_PRIO_MAX) APPEND_SNPRINTF(rc, p, len, "%d ", qopt->priomap[i]); else APPEND_SNPRINTF(rc, p, len, "%d-", qopt->priomap[i]); } if (p - prio == sizeof(prio)) { rec_dbg(lev, "%s(%hu): -- priomap too long --", name, RTA_ALIGN(tca->rta_len)); return; } rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); rec_dbg(lev, " [ tc_prio_qopt(%d) ]", sizeof(*qopt)); rec_dbg(lev, " bands(%d): %d", sizeof(qopt->bands), qopt->bands); rec_dbg(lev, " priomap(%d): %s", sizeof(qopt->priomap), prio); }
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); memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); }
int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) { int len = RTA_LENGTH(4); struct rtattr *subrta; 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, 4); rta->rta_len = NLMSG_ALIGN(rta->rta_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; }
int FAST_FUNC rta_addattr32(struct rtattr *rta, int maxlen, int type, uint32_t data) { int len = RTA_LENGTH(4); struct rtattr *subrta; 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; move_to_unaligned32(RTA_DATA(subrta), data); rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; return 0; }
/* * debug attribute */ void debug_rta_tc_addr(int lev, struct tcmsg *tcm, struct rtattr *rta, const char *name) { char addr[INET6_ADDRSTRLEN+1] = ""; int res; res = inet_ntop_tc_addr(tcm, rta, addr, sizeof(addr)); if(res) { rec_dbg(lev, "%s(%hu): -- %s --", name, RTA_ALIGN(rta->rta_len), (res == 1) ? strerror(errno) : "payload too short"); return; } rec_dbg(lev, "%s(%hu): %s", name, RTA_ALIGN(rta->rta_len), addr); }
/* * Respond to a single RTM_NEWLINK event from the rtnetlink socket. */ static int LinkCatcher(struct nlmsghdr *nlh) { struct ifinfomsg* ifi; #if 0 fprintf(stderr, "nlmsg_type = %d.\n", nlh->nlmsg_type); #endif ifi = NLMSG_DATA(nlh); /* Code is ugly, but sort of works - Jean II */ /* If interface is getting destoyed */ if(nlh->nlmsg_type == RTM_DELLINK) { /* Remove from cache (if in cache) */ iw_del_interface_data(ifi->ifi_index); return 0; } /* Only keep add/change events */ if(nlh->nlmsg_type != RTM_NEWLINK) return 0; /* Check for attributes */ if (nlh->nlmsg_len > NLMSG_ALIGN(sizeof(struct ifinfomsg))) { int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(sizeof(struct ifinfomsg)); struct rtattr *attr = (void *) ((char *) ifi + NLMSG_ALIGN(sizeof(struct ifinfomsg))); while (RTA_OK(attr, attrlen)) { /* Check if the Wireless kind */ if(attr->rta_type == IFLA_WIRELESS) { /* Go to display it */ print_event_stream(ifi->ifi_index, (char *) attr + RTA_ALIGN(sizeof(struct rtattr)), attr->rta_len - RTA_ALIGN(sizeof(struct rtattr))); } attr = RTA_NEXT(attr, attrlen); } } return 0; }
int rta_addattr32(struct rtattr *rta, int maxlen, int type, __u32 data) { int len = RTA_LENGTH(4); struct rtattr *subrta; if (RTA_ALIGN(rta->rta_len) + len > maxlen) { fprintf(stderr,"rta_addattr32: Error! max allowed bound %d exceeded\n",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, 4); rta->rta_len = NLMSG_ALIGN(rta->rta_len) + len; return 0; }
/* * debug attribute RTA_CACHEINFO */ void debug_rta_cacheinfo(int lev, struct rtattr *rta, const char *name) { struct rta_cacheinfo *rtac; if(debug_rta_len_chk(lev, rta, name, sizeof(*rtac))) return; rtac = (struct rta_cacheinfo *)RTA_DATA(rta); rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(rta->rta_len)); rec_dbg(lev, " [ rta_cacheinfo(%d) ]", sizeof(*rtac)); rec_dbg(lev, " rta_clntref(%d): %u", sizeof(rtac->rta_clntref), rtac->rta_clntref); rec_dbg(lev, " rta_lastuse(%d): %u", sizeof(rtac->rta_lastuse), rtac->rta_lastuse); rec_dbg(lev, " rta_expires(%d): %d", sizeof(rtac->rta_expires), rtac->rta_expires); rec_dbg(lev, " rta_error(%d): %u", sizeof(rtac->rta_error), rtac->rta_error); rec_dbg(lev, " rta_used(%d): %u", sizeof(rtac->rta_used), rtac->rta_used); rec_dbg(lev, " rta_id(%d): %u", sizeof(rtac->rta_id), rtac->rta_id); rec_dbg(lev, " rta_ts(%d): %u", sizeof(rtac->rta_ts), rtac->rta_ts); rec_dbg(lev, " rta_tsage(%d): %u", sizeof(rtac->rta_tsage), rtac->rta_tsage); }
static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv, struct nlmsghdr *h, int len) { struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < (int) sizeof(*ifi)) return; ifi = NLMSG_DATA(h); /* TODO: use ifi->ifi_index to filter out wireless events from other * interfaces */ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_WIRELESS) { hostapd_wireless_event_wireless( drv, ((char *) attr) + rta_len, attr->rta_len - rta_len); } attr = RTA_NEXT(attr, attrlen); } }
/* * debug hfsc options */ void debug_tca_options_hfsc(int lev, struct rtattr *tca, const char *name) { struct tc_hfsc_qopt *qopt; struct rtattr *hfsc[__TCA_HFSC_MAX]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); if(RTA_PAYLOAD(tca) == sizeof(*qopt)) { qopt = (struct tc_hfsc_qopt *)RTA_DATA(tca); rec_dbg(lev, " [ tc_hfsc_qopt(%d) ]", sizeof(*qopt)); rec_dbg(lev, " defcls(%d): 0x%x", sizeof(qopt->defcls), qopt->defcls); return; } parse_nested_rtattr(hfsc, TCA_HFSC_MAX, tca); if(hfsc[TCA_HFSC_RSC]) debug_tca_hfsc_sc(lev+1, hfsc[TCA_HFSC_RSC], "TCA_HFSC_RSC"); if(hfsc[TCA_HFSC_FSC]) debug_tca_hfsc_sc(lev+1, hfsc[TCA_HFSC_FSC], "TCA_HFSC_FSC"); if(hfsc[TCA_HFSC_USC]) debug_tca_hfsc_sc(lev+1, hfsc[TCA_HFSC_USC], "TCA_HFSC_USC"); }
/* * debug attribute RTA_MULTIPATH */ void debug_rta_multipath(int lev, struct rtmsg *rtm, struct rtattr *rta, const char *name) { struct rtnexthop *rtnh; int rtnh_len = RTA_PAYLOAD(rta); struct rtattr *rtnha[__RTA_MAX]; char ifname[IFNAMSIZ] = ""; char flags_list[MAX_STR_SIZE] = ""; if(debug_rta_len_chk(lev, rta, name, sizeof(*rtnh))) return; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(rta->rta_len)); for(rtnh = RTA_DATA(rta); RTNH_OK(rtnh, rtnh_len); rtnh = RTNH_NEXT(rtnh), rtnh_len -= RTNH_ALIGN(rtnh->rtnh_len)) { conv_rtnh_flags(rtnh->rtnh_flags, flags_list, sizeof(flags_list)); if_indextoname_from_lists(rtnh->rtnh_ifindex, ifname); rec_dbg(lev, " [ rtnexthop(%d) ]", sizeof(*rtnh)); rec_dbg(lev, " rtnh_len(%d): %hu", sizeof(rtnh->rtnh_len), rtnh->rtnh_len); rec_dbg(lev, " rtnh_flags(%d): %d(%s)", sizeof(rtnh->rtnh_flags), rtnh->rtnh_flags, flags_list); rec_dbg(lev, " rtnh_hops(%d): %d", sizeof(rtnh->rtnh_hops), rtnh->rtnh_hops); rec_dbg(lev, " rtnh_ifindex(%d): %d(%s)", sizeof(rtnh->rtnh_ifindex), rtnh->rtnh_ifindex, ifname); parse_rtattr(rtnha, RTA_MAX, RTNH_DATA(rtnh), rtnh->rtnh_len - sizeof(*rtnh)); if(rtnha[RTA_GATEWAY]) debug_rta_af(lev+3, rtnha[RTA_GATEWAY], "RTA_GATEWAY", rtm->rtm_family); } }
static void wpa_driver_wext_event_rtm_dellink(struct wpa_driver_wext_data *drv, void *ctx, struct nlmsghdr *h, int len) { struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < sizeof(*ifi)) return; ifi = NLMSG_DATA(h); nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_IFNAME) { wpa_driver_wext_event_link(drv, ctx, ((char *) attr) + rta_len, attr->rta_len - rta_len, 1); } attr = RTA_NEXT(attr, attrlen); } }
/* * debug attribute TCA_RSVP_PINFO */ void debug_tca_rsvp_pinfo(int lev, struct rtattr *rsvp, const char *name) { struct tc_rsvp_pinfo *pinfo; struct tc_rsvp_gpi *dpi, *spi; if(debug_rta_len_chk(lev, rsvp, name, sizeof(*pinfo))) return; pinfo = (struct tc_rsvp_pinfo *)RTA_DATA(rsvp); dpi = &(pinfo->dpi); spi = &(pinfo->spi); rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(rsvp->rta_len)); rec_dbg(lev, " [ tc_rsvp_pinfo(%d) ]", sizeof(*pinfo)); rec_dbg(lev, " [ tc_rsvp_gpi dpi(%d) ]", sizeof(*dpi)); rec_dbg(lev, " key(%d): 0x%08x", sizeof(dpi->key), dpi->key); rec_dbg(lev, " mask(%d): 0x%08x", sizeof(dpi->mask), dpi->mask); rec_dbg(lev, " offset(%d): %d", sizeof(dpi->offset), dpi->offset); rec_dbg(lev, " [ tc_rsvp_gpi spi(%d) ]", sizeof(*spi)); rec_dbg(lev, " key(%d): 0x%08x", sizeof(spi->key), spi->key); rec_dbg(lev, " mask(%d): 0x%08x", sizeof(spi->mask), spi->mask); rec_dbg(lev, " offset(%d): %d", sizeof(spi->offset), spi->offset); rec_dbg(lev, " protocol(%d): %d", sizeof(pinfo->protocol), pinfo->protocol); rec_dbg(lev, " tunnelid(%d): %d", sizeof(pinfo->tunnelid), pinfo->tunnelid); rec_dbg(lev, " tunnelhdr(%d): %d", sizeof(pinfo->tunnelhdr), pinfo->tunnelhdr); rec_dbg(lev, " pad(%d): %d", sizeof(pinfo->pad), pinfo->pad); }
/* * debug attribute TCA_ACT_OPTIONS */ void debug_tca_act_options(int lev, struct rtattr *act, const char *name, char *kind, int len) { rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(act->rta_len)); if(!strncmp(kind, "police", len)) debug_tca_act_options_police(lev, act, NULL); else if(!strncmp(kind, "gact", len)) debug_tca_act_options_gact(lev, act); else if(!strncmp(kind, "pedit", len)) debug_tca_act_options_pedit(lev, act); else if(!strncmp(kind, "mirred", len)) debug_tca_act_options_mirred(lev, act); #ifdef HAVE_LINUX_TC_ACT_TC_NAT_H else if(!strncmp(kind, "nat", len)) debug_tca_act_options_nat(lev, act); #endif #ifdef HAVE_LINUX_TC_ACT_TC_SKBEDIT_H else if(!strncmp(kind, "skbedit", len)) debug_tca_act_options_skbedit(lev, act); #endif #ifdef HAVE_LINUX_TC_ACT_TC_CSUM_H else if(!strncmp(kind, "csum", len)) debug_tca_act_options_csum(lev, act); #endif else rec_dbg(lev, " -- unknown action %s --", kind); }
/* * debug attribute TCA_SFB_PARMS */ void debug_tca_sfb_parms(int lev, struct rtattr *sfb, const char *name) { struct tc_sfb_qopt *qopt; if(debug_rta_len_chk(lev, sfb, name, sizeof(*qopt))) return; qopt = (struct tc_sfb_qopt *)RTA_DATA(sfb); rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(sfb->rta_len)); rec_dbg(lev, " [ tc_stats(%d) ]", sizeof(*qopt)); rec_dbg(lev, " rehash_interval(%d): %u", sizeof(qopt->rehash_interval), qopt->rehash_interval); rec_dbg(lev, " warmup_time(%d): %u", sizeof(qopt->warmup_time), qopt->warmup_time); rec_dbg(lev, " max(%d): %u", sizeof(qopt->max), qopt->max); rec_dbg(lev, " bin_size(%d): %u", sizeof(qopt->bin_size), qopt->bin_size); rec_dbg(lev, " increment(%d): %u", sizeof(qopt->increment), qopt->increment); rec_dbg(lev, " decrement(%d): %u", sizeof(qopt->decrement), qopt->decrement); rec_dbg(lev, " limit(%d): %u", sizeof(qopt->limit), qopt->limit); rec_dbg(lev, " penalty_rate(%d): %u", sizeof(qopt->penalty_rate), qopt->penalty_rate); rec_dbg(lev, " penalty_burst(%d): %u", sizeof(qopt->penalty_burst), qopt->penalty_burst); }
static int netlink_add_rtattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { int len = RTA_LENGTH(alen); struct rtattr *rta; if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) return FALSE; rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = len; memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return TRUE; }
/* * debug unsigned short attribute */ void debug_rta_u16(int lev, struct rtattr *rta, const char *name, const char *(*conv)(unsigned short num, unsigned char debug)) { if(debug_rta_len_chk(lev, rta, name, sizeof(unsigned short))) return; unsigned short data = *(unsigned short *)RTA_DATA(rta); if(conv) rec_dbg(lev, "%s(%hu): %hu(%s)", name, RTA_ALIGN(rta->rta_len), data, conv(data, 1)); else rec_dbg(lev, "%s(%hu): %hu", name, RTA_ALIGN(rta->rta_len), data); return; }
/* * debug rsvp options */ void debug_tca_options_rsvp(int lev, struct tcmsg *tcm, struct rtattr *tca, const char *name) { struct rtattr *rsvp[__TCA_RSVP_MAX]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(tca->rta_len)); parse_nested_rtattr(rsvp, TCA_RSVP_MAX, tca); if(rsvp[TCA_RSVP_CLASSID]) debug_tca_classid(lev+1, rsvp[TCA_RSVP_CLASSID], "TCA_RSVP_CLASSID"); if(rsvp[TCA_RSVP_DST]) debug_rta_tc_addr(lev+1, tcm, rsvp[TCA_RSVP_DST], "TCA_RSVP_DST"); if(rsvp[TCA_RSVP_SRC]) debug_rta_tc_addr(lev+1, tcm, rsvp[TCA_RSVP_SRC], "TCA_RSVP_SRC"); if(rsvp[TCA_RSVP_PINFO]) debug_tca_rsvp_pinfo(lev+1, rsvp[TCA_RSVP_PINFO], "TCA_RSVP_PINFO"); if(rsvp[TCA_RSVP_POLICE]) debug_tca_act_options_police(lev+1, rsvp[TCA_RSVP_POLICE], "TCA_RSVP_POLICE"); if(rsvp[TCA_RSVP_ACT]) debug_tca_acts(lev+1, rsvp[TCA_RSVP_ACT], "TCA_RSVP_ACT"); }
/* * debug int attribute */ void debug_rta_s32x(int lev, struct rtattr *rta, const char *name, const char *(*conv)(int num, unsigned char debug)) { if(debug_rta_len_chk(lev, rta, name, sizeof(int))) return; int data = *(int *)RTA_DATA(rta); if(conv) rec_dbg(lev, "%s(%hu): 0x%08x(%s)", name, RTA_ALIGN(rta->rta_len), data, conv(data, 1)); else rec_dbg(lev, "%s(%hu): 0x%08x", name, RTA_ALIGN(rta->rta_len), data); return; }
/* * debug attribute RTA_METRICS */ void debug_rta_metrics(int lev, struct rtattr *rta, const char *name) { struct rtattr *rtax[RTAX_MAX+1]; rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(rta->rta_len)); parse_rtattr(rtax, RTAX_MAX, RTA_DATA(rta), RTA_PAYLOAD(rta)); if(rtax[RTAX_LOCK]) debug_rta_u32(lev+1, rtax[RTAX_LOCK], "RTAX_LOCK", NULL); if(rtax[RTAX_MTU]) debug_rta_u32(lev+1, rtax[RTAX_MTU], "RTAX_MTU", NULL); if(rtax[RTAX_ADVMSS]) debug_rta_u32(lev+1, rtax[RTAX_ADVMSS], "RTAX_ADVMSS", NULL); if(rtax[RTAX_HOPLIMIT]) debug_rta_s32(lev+1, rtax[RTAX_HOPLIMIT], "RTAX_HOPLIMIT", NULL); if(rtax[RTAX_WINDOW]) debug_rta_u32(lev+1, rtax[RTAX_WINDOW], "RTAX_WINDOW", NULL); }
static void madwifi_wireless_event_rtm_newlink(struct madwifi_driver_data *drv, struct nlmsghdr *h, int len) { struct ifinfomsg *ifi; int attrlen, nlmsg_len, rta_len; struct rtattr * attr; if (len < (int) sizeof(*ifi)) return; ifi = NLMSG_DATA(h); if (ifi->ifi_index != drv->ifindex) return; nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); attrlen = h->nlmsg_len - nlmsg_len; if (attrlen < 0) return; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); while (RTA_OK(attr, attrlen)) { if (attr->rta_type == IFLA_WIRELESS) { madwifi_wireless_event_wireless( drv, ((char *) attr) + rta_len, attr->rta_len - rta_len); } attr = RTA_NEXT(attr, attrlen); } }
/* 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; }
/* * debug attribute TCA_EM_META_HDR */ struct tcf_meta_hdr *debug_tca_em_meta_hdr(int lev, struct rtattr *meta, const char *name) { struct tcf_meta_hdr *hdr; struct tcf_meta_val *left, *right; if(debug_rta_len_chk(lev, meta, name, sizeof(*hdr))) return(NULL); hdr = (struct tcf_meta_hdr *)RTA_DATA(meta); left = &(hdr->left); right = &(hdr->right); rec_dbg(lev, "%s(%hu):", name, RTA_ALIGN(meta->rta_len)); rec_dbg(lev, " [ tcf_meta_hdr(%d) ]", sizeof(*hdr)); rec_dbg(lev, " [ tcf_meta_val left(%d) ]", sizeof(*left)); rec_dbg(lev, " kind(%d): 0x%04x(%s,%s)", sizeof(left->kind), left->kind, conv_tcf_meta_type(TCF_META_TYPE(left->kind), 1), conv_tcf_meta_id(TCF_META_ID(left->kind), 1)); rec_dbg(lev, " shift(%d): %d", sizeof(left->shift), left->shift); rec_dbg(lev, " op(%d): %d(%s)", sizeof(left->op), left->op, conv_tcf_em_opnd(left->op, 1)); rec_dbg(lev, " [ tcf_meta_val right(%d) ]", sizeof(*right)); rec_dbg(lev, " kind(%d): 0x%04x(%s,%s)", sizeof(right->kind), right->kind, conv_tcf_meta_type(TCF_META_TYPE(right->kind), 1), conv_tcf_meta_id(TCF_META_ID(right->kind), 1)); rec_dbg(lev, " shift(%d): %d", sizeof(right->shift), right->shift); rec_dbg(lev, " op(%d): %d(%s)", sizeof(right->op), right->op, conv_tcf_em_opnd(right->op, 1)); return(hdr); }
static int add_rtattr(struct nlmsghdr *n, size_t max_length, int type, const void *data, size_t data_length) { size_t length; struct rtattr *rta; length = RTA_LENGTH(data_length); if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length) > max_length) return -E2BIG; rta = NLMSG_TAIL(n); rta->rta_type = type; rta->rta_len = length; memcpy(RTA_DATA(rta), data, data_length); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(length); return 0; }
/* * debug ARPHRD_* address attribute */ void debug_rta_arphrd(int lev, struct rtattr *rta, const char *name, unsigned short type) { char addr[INET6_ADDRSTRLEN+1] = ""; int res; res = arphrd_ntop(type, rta, addr, sizeof(addr)); if(res) { rec_dbg(lev, "%s(%hu): -- %s --", name, RTA_ALIGN(rta->rta_len), (res == 1) ? strerror(errno) : "payload too short"); return; } rec_dbg(lev, "%s(%hu): %s", name, RTA_ALIGN(rta->rta_len), addr); return; }
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { 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; memcpy(RTA_DATA(rta), data, alen); n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); return 0; }
int rta_addattr_l(struct rtattr *rta, int maxlen, int type, const void *data, int alen) { struct rtattr *subrta; int len = RTA_LENGTH(alen); if (RTA_ALIGN(rta->rta_len) + RTA_ALIGN(len) > maxlen) { fprintf(stderr,"rta_addattr_l: Error! max allowed bound %d exceeded\n",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) + RTA_ALIGN(len); return 0; }