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