Home | History | Annotate | Download | only in idiag
      1 /*
      2  * lib/idiag/idiagnl_req_obj.c Inet Diag Request Object
      3  *
      4  *	This library is free software; you can redistribute it and/or
      5  *	modify it under the terms of the GNU Lesser General Public
      6  *	License as published by the Free Software Foundation version 2.1
      7  *	of the License.
      8  *
      9  * Copyright (c) 2013 Sassano Systems LLC <joe (at) sassanosystems.com>
     10  */
     11 
     12 #include <netlink-private/netlink.h>
     13 #include <netlink/idiag/req.h>
     14 #include <linux/inet_diag.h>
     15 
     16 /**
     17  * @ingroup idiag
     18  * @defgroup idiagnl_req Inet Diag Requests
     19  *
     20  * @details
     21  * @idiagnl_doc{idiagnl_req, Inet Diag Request Documentation}
     22  * @{
     23  */
     24 struct idiagnl_req *idiagnl_req_alloc(void)
     25 {
     26 	return (struct idiagnl_req *) nl_object_alloc(&idiagnl_req_obj_ops);
     27 }
     28 
     29 void idiagnl_req_get(struct idiagnl_req *req)
     30 {
     31 	nl_object_get((struct nl_object *) req);
     32 }
     33 
     34 void idiagnl_req_put(struct idiagnl_req *req)
     35 {
     36 	nl_object_put((struct nl_object *) req);
     37 }
     38 
     39 /**
     40  * @name Attributes
     41  * @{
     42  */
     43 
     44 uint8_t idiagnl_req_get_family(const struct idiagnl_req *req)
     45 {
     46 	return req->idiag_family;
     47 }
     48 
     49 void idiagnl_req_set_family(struct idiagnl_req *req, uint8_t family)
     50 {
     51 	req->idiag_family = family;
     52 }
     53 
     54 uint8_t idiagnl_req_get_ext(const struct idiagnl_req *req)
     55 {
     56 	return req->idiag_ext;
     57 }
     58 
     59 void idiagnl_req_set_ext(struct idiagnl_req *req, uint8_t ext)
     60 {
     61 	req->idiag_ext = ext;
     62 }
     63 
     64 uint32_t idiagnl_req_get_ifindex(const struct idiagnl_req *req)
     65 {
     66 	return req->idiag_ifindex;
     67 }
     68 
     69 void idiagnl_req_set_ifindex(struct idiagnl_req *req, uint32_t ifindex)
     70 {
     71 	req->idiag_states = ifindex;
     72 }
     73 
     74 uint32_t idiagnl_req_get_states(const struct idiagnl_req *req)
     75 {
     76 	return req->idiag_states;
     77 }
     78 
     79 void idiagnl_req_set_states(struct idiagnl_req *req, uint32_t states)
     80 {
     81 	req->idiag_states = states;
     82 }
     83 
     84 uint32_t idiagnl_req_get_dbs(const struct idiagnl_req *req)
     85 {
     86 	return req->idiag_dbs;
     87 }
     88 
     89 void idiagnl_req_set_dbs(struct idiagnl_req *req, uint32_t dbs)
     90 {
     91 	req->idiag_dbs = dbs;
     92 }
     93 
     94 struct nl_addr *idiagnl_req_get_src(const struct idiagnl_req *req)
     95 {
     96 	return req->idiag_src;
     97 }
     98 
     99 int idiagnl_req_set_src(struct idiagnl_req *req, struct nl_addr *addr)
    100 {
    101 	if (req->idiag_src)
    102 		nl_addr_put(req->idiag_src);
    103 
    104 	nl_addr_get(addr);
    105 	req->idiag_src = addr;
    106 
    107 	return 0;
    108 }
    109 
    110 struct nl_addr *idiagnl_req_get_dst(const struct idiagnl_req *req)
    111 {
    112 	return req->idiag_dst;
    113 }
    114 
    115 int idiagnl_req_set_dst(struct idiagnl_req *req, struct nl_addr *addr)
    116 {
    117 	if (req->idiag_dst)
    118 		nl_addr_put(req->idiag_dst);
    119 
    120 	nl_addr_get(addr);
    121 	req->idiag_dst = addr;
    122 
    123 	return 0;
    124 }
    125 
    126 /** @} */
    127 
    128 static void idiag_req_dump_line(struct nl_object *a, struct nl_dump_params *p)
    129 {
    130 	struct idiagnl_req *req = (struct idiagnl_req *) a;
    131 	char buf[64] = { 0 };
    132 
    133 	nl_dump_line(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf)));
    134 	nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf)));
    135 	nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf)));
    136 	nl_dump(p, "iif %d ", req->idiag_ifindex);
    137 	nl_dump(p, "\n");
    138 }
    139 
    140 static void idiag_req_dump_details(struct nl_object *a, struct nl_dump_params *p)
    141 {
    142 	struct idiagnl_req *req = (struct idiagnl_req *) a;
    143 	char buf[64];
    144 
    145 	nl_dump_line(p, "    ");
    146 	nl_dump(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf)));
    147 	nl_dump(p, "exts %s ",
    148 			idiagnl_exts2str(req->idiag_ext, buf, sizeof(buf)));
    149 	nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf)));
    150 	nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf)));
    151 	nl_dump(p, "iif %d ", req->idiag_ifindex);
    152 	nl_dump(p, "states %s ", idiagnl_state2str(req->idiag_states, buf,
    153 				sizeof(buf)));
    154 	nl_dump(p, "dbs %d", req->idiag_dbs);
    155 	nl_dump(p, "\n");
    156 }
    157 
    158 static void idiag_req_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
    159 {
    160 	idiag_req_dump_details(obj, p);
    161 }
    162 
    163 static void idiagnl_req_free(struct nl_object *a)
    164 {
    165 	struct idiagnl_req *req = (struct idiagnl_req *) a;
    166 	if (a == NULL)
    167 		return;
    168 
    169 	nl_addr_put(req->idiag_src);
    170 	nl_addr_put(req->idiag_dst);
    171 }
    172 
    173 static int idiagnl_req_clone(struct nl_object *_dst, struct nl_object *_src)
    174 {
    175 	struct idiagnl_req *dst = (struct idiagnl_req *) _dst;
    176 	struct idiagnl_req *src = (struct idiagnl_req *) _src;
    177 
    178 	if (src->idiag_src)
    179 		if (!(dst->idiag_src = nl_addr_clone(src->idiag_src)))
    180 			return -NLE_NOMEM;
    181 
    182 	if (src->idiag_dst)
    183 		if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst)))
    184 			return -NLE_NOMEM;
    185 
    186 	return 0;
    187 }
    188 
    189 int idiagnl_req_parse(struct nlmsghdr *nlh, struct idiagnl_req **result)
    190 {
    191 	struct idiagnl_req *req = NULL;
    192 	struct inet_diag_req *raw_req = NULL;
    193 	struct nl_addr *src = NULL, *dst = NULL;
    194 	int err = 0;
    195 
    196 	req = idiagnl_req_alloc();
    197 	if (!req)
    198 		goto errout_nomem;
    199 
    200 	raw_req = nlmsg_data(nlh);
    201 	req->idiag_family = raw_req->idiag_family;
    202 	req->idiag_ext = raw_req->idiag_ext;
    203 	req->idiag_states = raw_req->idiag_states;
    204 	req->idiag_dbs = raw_req->idiag_dbs;
    205 	req->idiag_ifindex = raw_req->id.idiag_if;
    206 
    207 	dst = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_dst,
    208 			sizeof(raw_req->id.idiag_dst));
    209 	if (!dst)
    210 		goto errout_nomem;
    211 
    212 	err = idiagnl_req_set_dst(req, dst);
    213 	if (err < 0)
    214 		goto errout;
    215 
    216 	nl_addr_put(dst);
    217 
    218 	src = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_src,
    219 			sizeof(raw_req->id.idiag_src));
    220 	if (!src)
    221 		goto errout_nomem;
    222 
    223 	err = idiagnl_req_set_src(req, src);
    224 	if (err < 0)
    225 		goto errout;
    226 
    227 	nl_addr_put(src);
    228 
    229 	*result = req;
    230 	return 0;
    231 
    232 errout:
    233 	idiagnl_req_put(req);
    234 	return err;
    235 
    236 errout_nomem:
    237 	err = -NLE_NOMEM;
    238 	goto errout;
    239 }
    240 
    241 /** @cond SKIP */
    242 struct nl_object_ops idiagnl_req_obj_ops = {
    243 	.oo_name		  = "idiag/idiag_req",
    244 	.oo_size		  = sizeof(struct idiagnl_req),
    245 	.oo_free_data		  = idiagnl_req_free,
    246 	.oo_clone		  = idiagnl_req_clone,
    247 	.oo_dump		  = {
    248 		[NL_DUMP_LINE]	  = idiag_req_dump_line,
    249 		[NL_DUMP_DETAILS] = idiag_req_dump_details,
    250 		[NL_DUMP_STATS]	  = idiag_req_dump_stats,
    251 	},
    252 };
    253 /** @endcond */
    254 
    255 /** @} */
    256