static int idiagnl_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, struct nlmsghdr *nlh, struct nl_parser_param *pp) { struct idiagnl_msg *msg = NULL; int err = 0; if ((err = idiagnl_msg_parse(nlh, &msg)) < 0) return err; err = pp->pp_cb((struct nl_object *) msg, pp); idiagnl_msg_put(msg); return err; }
inline void cleanup(struct idiagnl_msg* msg) { idiagnl_msg_put(msg); }
int idiagnl_msg_parse(struct nlmsghdr *nlh, struct idiagnl_msg **result) { struct idiagnl_msg *msg = NULL; struct inet_diag_msg *raw_msg = NULL; struct nl_addr *src = NULL, *dst = NULL; struct nlattr *tb[IDIAG_ATTR_MAX]; int err = 0; msg = idiagnl_msg_alloc(); if (!msg) goto errout_nomem; err = nlmsg_parse(nlh, sizeof(struct inet_diag_msg), tb, IDIAG_ATTR_MAX, ext_policy); if (err < 0) goto errout; raw_msg = nlmsg_data(nlh); msg->idiag_family = raw_msg->idiag_family; msg->idiag_state = raw_msg->idiag_state; msg->idiag_timer = raw_msg->idiag_timer; msg->idiag_retrans = raw_msg->idiag_retrans; msg->idiag_expires = raw_msg->idiag_expires; msg->idiag_rqueue = raw_msg->idiag_rqueue; msg->idiag_wqueue = raw_msg->idiag_wqueue; msg->idiag_uid = raw_msg->idiag_uid; msg->idiag_inode = raw_msg->idiag_inode; msg->idiag_sport = raw_msg->id.idiag_sport; msg->idiag_dport = raw_msg->id.idiag_dport; msg->idiag_ifindex = raw_msg->id.idiag_if; dst = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_dst, sizeof(raw_msg->id.idiag_dst)); if (!dst) goto errout_nomem; err = idiagnl_msg_set_dst(msg, dst); if (err < 0) goto errout; nl_addr_put(dst); src = nl_addr_build(raw_msg->idiag_family, raw_msg->id.idiag_src, sizeof(raw_msg->id.idiag_src)); if (!src) goto errout_nomem; err = idiagnl_msg_set_src(msg, src); if (err < 0) goto errout; nl_addr_put(src); if (tb[IDIAG_ATTR_TOS]) msg->idiag_tos = nla_get_u8(tb[IDIAG_ATTR_TOS]); if (tb[IDIAG_ATTR_TCLASS]) msg->idiag_tclass = nla_get_u8(tb[IDIAG_ATTR_TCLASS]); if (tb[IDIAG_ATTR_SHUTDOWN]) msg->idiag_shutdown = nla_get_u8(tb[IDIAG_ATTR_SHUTDOWN]); if (tb[IDIAG_ATTR_CONG]) msg->idiag_cong = nla_strdup(tb[IDIAG_ATTR_CONG]); if (tb[IDIAG_ATTR_INFO]) nla_memcpy(&msg->idiag_tcpinfo, tb[IDIAG_ATTR_INFO], sizeof(msg->idiag_tcpinfo)); if (tb[IDIAG_ATTR_MEMINFO]) { struct idiagnl_meminfo *minfo = idiagnl_meminfo_alloc(); struct inet_diag_meminfo *raw_minfo = NULL; if (!minfo) goto errout_nomem; raw_minfo = (struct inet_diag_meminfo *) nla_data(tb[IDIAG_ATTR_MEMINFO]); idiagnl_meminfo_set_rmem(minfo, raw_minfo->idiag_rmem); idiagnl_meminfo_set_wmem(minfo, raw_minfo->idiag_wmem); idiagnl_meminfo_set_fmem(minfo, raw_minfo->idiag_fmem); idiagnl_meminfo_set_tmem(minfo, raw_minfo->idiag_tmem); msg->idiag_meminfo = minfo; } if (tb[IDIAG_ATTR_VEGASINFO]) { struct idiagnl_vegasinfo *vinfo = idiagnl_vegasinfo_alloc(); struct tcpvegas_info *raw_vinfo = NULL; if (!vinfo) goto errout_nomem; raw_vinfo = (struct tcpvegas_info *) nla_data(tb[IDIAG_ATTR_VEGASINFO]); idiagnl_vegasinfo_set_enabled(vinfo, raw_vinfo->tcpv_enabled); idiagnl_vegasinfo_set_rttcnt(vinfo, raw_vinfo->tcpv_rttcnt); idiagnl_vegasinfo_set_rtt(vinfo, raw_vinfo->tcpv_rtt); idiagnl_vegasinfo_set_minrtt(vinfo, raw_vinfo->tcpv_minrtt); msg->idiag_vegasinfo = vinfo; } if (tb[IDIAG_ATTR_SKMEMINFO]) nla_memcpy(&msg->idiag_skmeminfo, tb[IDIAG_ATTR_SKMEMINFO], sizeof(msg->idiag_skmeminfo)); *result = msg; return 0; errout: idiagnl_msg_put(msg); return err; errout_nomem: err = -NLE_NOMEM; goto errout; }