00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <netlink-local.h>
00021 #include <netlink/netlink.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/msg.h>
00024 #include <netlink/handlers.h>
00025
00026 static void print_header_content(FILE *ofd, struct nlmsghdr *n)
00027 {
00028 char flags[128];
00029 char type[32];
00030
00031 fprintf(ofd, "type=%s length=%u flags=<%s> sequence-nr=%u pid=%u",
00032 nl_nlmsgtype2str(n->nlmsg_type, type, sizeof(type)),
00033 n->nlmsg_len, nl_nlmsg_flags2str(n->nlmsg_flags, flags,
00034 sizeof(flags)), n->nlmsg_seq, n->nlmsg_pid);
00035 }
00036
00037 static inline void dump_hex(FILE *ofd, char *start, int len)
00038 {
00039 int i, a, c, limit;
00040 char ascii[21] = {0};
00041
00042 limit = 18;
00043 fprintf(ofd, " ");
00044
00045 for (i = 0, a = 0, c = 0; i < len; i++) {
00046 int v = *(uint8_t *) (start + i);
00047
00048 fprintf(ofd, "%02x ", v);
00049 ascii[a++] = isprint(v) ? v : '.';
00050
00051 if (c == limit-1) {
00052 fprintf(ofd, "%s\n", ascii);
00053 if (i < (len - 1))
00054 fprintf(ofd, " ");
00055 a = c = 0;
00056 memset(ascii, 0, sizeof(ascii));
00057 } else
00058 c++;
00059 }
00060
00061 if (c != 0) {
00062 for (i = 0; i < (limit - c); i++)
00063 fprintf(ofd, " ");
00064 fprintf(ofd, "%s\n", ascii);
00065 }
00066 }
00067
00068 static void print_hdr(FILE *ofd, struct nl_msg *msg)
00069 {
00070 struct nlmsghdr *nlh = nlmsg_hdr(msg);
00071 struct nl_cache_ops *ops;
00072 char buf[128];
00073
00074 fprintf(ofd, " .nlmsg_len = %d\n", nlh->nlmsg_len);
00075
00076 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg), nlh->nlmsg_type);
00077
00078 fprintf(ofd, " .nlmsg_type = %d <%s>\n", nlh->nlmsg_type,
00079 ops ? nl_cache_mngt_type2name(ops, nlh->nlmsg_type,
00080 buf, sizeof(buf))
00081 : nl_nlmsgtype2str(nlh->nlmsg_type, buf, sizeof(buf)));
00082 fprintf(ofd, " .nlmsg_flags = %d <%s>\n", nlh->nlmsg_flags,
00083 nl_nlmsg_flags2str(nlh->nlmsg_flags, buf, sizeof(buf)));
00084 fprintf(ofd, " .nlmsg_seq = %d\n", nlh->nlmsg_seq);
00085 fprintf(ofd, " .nlmsg_pid = %d\n", nlh->nlmsg_pid);
00086
00087 }
00088
00089 static void raw_dump_msg(FILE *ofd, struct nl_msg *msg)
00090 {
00091 struct nlmsghdr *hdr = nlmsg_hdr(msg);
00092
00093 fprintf(ofd,
00094 "-------------------------- BEGIN NETLINK MESSAGE "
00095 "---------------------------\n");
00096
00097 fprintf(ofd, " [HEADER] %Zu octets\n", sizeof(struct nlmsghdr));
00098 print_hdr(ofd, msg);
00099
00100 if (hdr->nlmsg_type == NLMSG_ERROR &&
00101 hdr->nlmsg_len >= nlmsg_msg_size(sizeof(struct nlmsgerr))) {
00102 struct nl_msg *errmsg;
00103 struct nlmsgerr *err = nlmsg_data(hdr);
00104
00105 fprintf(ofd, " [ERRORMSG] %Zu octets\n", sizeof(*err));
00106 fprintf(ofd, " .error = %d \"%s\"\n", err->error,
00107 strerror(-err->error));
00108 fprintf(ofd, " [ORIGINAL MESSAGE] %Zu octets\n", sizeof(*hdr));
00109
00110 errmsg = nlmsg_build(&err->msg);
00111 print_hdr(ofd, errmsg);
00112 nlmsg_free(msg);
00113 } else if (nlmsg_len(hdr) > 0) {
00114 struct nl_cache_ops *ops;
00115 int payloadlen = nlmsg_len(hdr);
00116 int attrlen = 0;
00117
00118 ops = nl_cache_mngt_associate(nlmsg_get_proto(msg),
00119 hdr->nlmsg_type);
00120 if (ops) {
00121 attrlen = nlmsg_attrlen(hdr, ops->co_hdrsize);
00122 payloadlen -= attrlen;
00123 }
00124
00125 fprintf(ofd, " [PAYLOAD] %d octets\n", payloadlen);
00126 dump_hex(ofd, nlmsg_data(hdr), payloadlen);
00127
00128 if (attrlen) {
00129 int rem, padlen;
00130 struct nlattr *nla;
00131
00132 nlmsg_for_each_attr(nla, hdr, ops->co_hdrsize, rem) {
00133 int alen = nla_len(nla);
00134
00135 fprintf(ofd, " [ATTR %02d] %d octets\n",
00136 nla->nla_type, alen);
00137 dump_hex(ofd, nla_data(nla), alen);
00138
00139 padlen = nla_padlen(alen);
00140 if (padlen > 0) {
00141 fprintf(ofd, " [PADDING] %d octets\n",
00142 padlen);
00143 dump_hex(ofd, nla_data(nla) + alen,
00144 padlen);
00145 }
00146 }
00147 }
00148 }
00149
00150 fprintf(ofd,
00151 "--------------------------- END NETLINK MESSAGE "
00152 "---------------------------\n");
00153 }
00154
00155 static int nl_valid_handler_default(struct nl_msg *msg, void *arg)
00156 {
00157 return NL_PROCEED;
00158 }
00159
00160 static int nl_finish_handler_default(struct nl_msg *msg, void *arg)
00161 {
00162 return NL_EXIT;
00163 }
00164
00165 static int nl_invalid_handler_default(struct nl_msg *msg, void *arg)
00166 {
00167 return NL_EXIT;
00168 }
00169
00170 static int nl_msg_in_handler_default(struct nl_msg *msg, void *arg)
00171 {
00172 return NL_PROCEED;
00173 }
00174
00175 static int nl_msg_out_handler_default(struct nl_msg *msg, void *arg)
00176 {
00177 return NL_PROCEED;
00178 }
00179
00180 static int nl_overrun_handler_default(struct nl_msg *msg, void *arg)
00181 {
00182 return NL_EXIT;
00183 }
00184
00185 static int nl_skipped_handler_default(struct nl_msg *msg, void *arg)
00186 {
00187 return NL_SKIP;
00188 }
00189
00190 static int nl_ack_handler_default(struct nl_msg *msg, void *arg)
00191 {
00192 return NL_EXIT;
00193 }
00194
00195 static int nl_error_handler_default(struct sockaddr_nl *who,
00196 struct nlmsgerr *e, void *arg)
00197 {
00198 return NL_EXIT;
00199 }
00200
00201 static int nl_valid_handler_verbose(struct nl_msg *msg, void *arg)
00202 {
00203 FILE *ofd = arg ? arg : stdout;
00204
00205 fprintf(ofd, "-- Warning: unhandled valid message: ");
00206 print_header_content(ofd, nlmsg_hdr(msg));
00207 fprintf(ofd, "\n");
00208
00209 return NL_PROCEED;
00210 }
00211
00212 static int nl_finish_handler_verbose(struct nl_msg *msg, void *arg)
00213 {
00214 return NL_EXIT;
00215 }
00216
00217 static int nl_msg_in_handler_verbose(struct nl_msg *msg, void *arg)
00218 {
00219 return NL_PROCEED;
00220 }
00221
00222 static int nl_invalid_handler_verbose(struct nl_msg *msg, void *arg)
00223 {
00224 FILE *ofd = arg ? arg : stderr;
00225
00226 fprintf(ofd, "-- Error: Invalid message: ");
00227 print_header_content(ofd, nlmsg_hdr(msg));
00228 fprintf(ofd, "\n");
00229
00230 return NL_EXIT;
00231 }
00232
00233 static int nl_msg_out_handler_verbose(struct nl_msg *msg, void *arg)
00234 {
00235 return NL_PROCEED;
00236 }
00237
00238 static int nl_overrun_handler_verbose(struct nl_msg *msg, void *arg)
00239 {
00240 FILE *ofd = arg ? arg : stderr;
00241
00242 fprintf(ofd, "-- Error: Netlink Overrun: ");
00243 print_header_content(ofd, nlmsg_hdr(msg));
00244 fprintf(ofd, "\n");
00245
00246 return NL_EXIT;
00247 }
00248
00249 static int nl_ack_handler_verbose(struct nl_msg *msg, void *arg)
00250 {
00251 return NL_EXIT;
00252 }
00253
00254 static int nl_skipped_handler_verbose(struct nl_msg *msg, void *arg)
00255 {
00256 return NL_SKIP;
00257 }
00258
00259 static int nl_error_handler_verbose(struct sockaddr_nl *who,
00260 struct nlmsgerr *e, void *arg)
00261 {
00262 FILE *ofd = arg ? arg : stderr;
00263
00264 fprintf(ofd, "-- Error received: %s\n-- Original message: ",
00265 strerror(-e->error));
00266 print_header_content(ofd, &e->msg);
00267 fprintf(ofd, "\n");
00268
00269 return NL_EXIT;
00270 }
00271
00272 static int nl_valid_handler_debug(struct nl_msg *msg, void *arg)
00273 {
00274 FILE *ofd = arg ? arg : stderr;
00275
00276 fprintf(ofd, "-- Debug: Valid message: ");
00277 print_header_content(ofd, nlmsg_hdr(msg));
00278 fprintf(ofd, "\n");
00279
00280 return NL_PROCEED;
00281 }
00282
00283 static int nl_finish_handler_debug(struct nl_msg *msg, void *arg)
00284 {
00285 FILE *ofd = arg ? arg : stderr;
00286
00287 fprintf(ofd, "-- Debug: End of multipart message block: ");
00288 print_header_content(ofd, nlmsg_hdr(msg));
00289 fprintf(ofd, "\n");
00290
00291 return NL_EXIT;
00292 }
00293
00294 static int nl_invalid_handler_debug(struct nl_msg *msg, void *arg)
00295 {
00296 return nl_invalid_handler_verbose(msg, arg);
00297 }
00298
00299 static int nl_msg_in_handler_debug(struct nl_msg *msg, void *arg)
00300 {
00301 FILE *ofd = arg ? arg : stderr;
00302
00303 fprintf(ofd, "-- Debug: Received Message:\n");
00304 raw_dump_msg(ofd, msg);
00305
00306 return NL_PROCEED;
00307 }
00308
00309 static int nl_msg_out_handler_debug(struct nl_msg *msg, void *arg)
00310 {
00311 FILE *ofd = arg ? arg : stderr;
00312
00313 fprintf(ofd, "-- Debug: Sent Message:\n");
00314 raw_dump_msg(ofd, msg);
00315
00316 return NL_PROCEED;
00317 }
00318
00319 static int nl_overrun_handler_debug(struct nl_msg *msg, void *arg)
00320 {
00321 return nl_overrun_handler_verbose(msg, arg);
00322 }
00323
00324 static int nl_skipped_handler_debug(struct nl_msg *msg, void *arg)
00325 {
00326 FILE *ofd = arg ? arg : stderr;
00327
00328 fprintf(ofd, "-- Debug: Skipped message: ");
00329 print_header_content(ofd, nlmsg_hdr(msg));
00330 fprintf(ofd, "\n");
00331
00332 return NL_SKIP;
00333 }
00334
00335 static int nl_ack_handler_debug(struct nl_msg *msg, void *arg)
00336 {
00337 FILE *ofd = arg ? arg : stderr;
00338
00339 fprintf(ofd, "-- Debug: ACK: ");
00340 print_header_content(ofd, nlmsg_hdr(msg));
00341 fprintf(ofd, "\n");
00342
00343 return NL_EXIT;
00344 }
00345
00346 static int nl_error_handler_debug(struct sockaddr_nl *who,
00347 struct nlmsgerr *e, void *arg)
00348 {
00349 return nl_error_handler_verbose(who, e, arg);
00350 }
00351
00352 static nl_recvmsg_msg_cb_t cb_def[NL_CB_TYPE_MAX+1][NL_CB_KIND_MAX+1] = {
00353 [NL_CB_VALID] = {
00354 [NL_CB_DEFAULT] = nl_valid_handler_default,
00355 [NL_CB_VERBOSE] = nl_valid_handler_verbose,
00356 [NL_CB_DEBUG] = nl_valid_handler_debug,
00357 },
00358 [NL_CB_FINISH] = {
00359 [NL_CB_DEFAULT] = nl_finish_handler_default,
00360 [NL_CB_VERBOSE] = nl_finish_handler_verbose,
00361 [NL_CB_DEBUG] = nl_finish_handler_debug,
00362 },
00363 [NL_CB_INVALID] = {
00364 [NL_CB_DEFAULT] = nl_invalid_handler_default,
00365 [NL_CB_VERBOSE] = nl_invalid_handler_verbose,
00366 [NL_CB_DEBUG] = nl_invalid_handler_debug,
00367 },
00368 [NL_CB_MSG_IN] = {
00369 [NL_CB_DEFAULT] = nl_msg_in_handler_default,
00370 [NL_CB_VERBOSE] = nl_msg_in_handler_verbose,
00371 [NL_CB_DEBUG] = nl_msg_in_handler_debug,
00372 },
00373 [NL_CB_MSG_OUT] = {
00374 [NL_CB_DEFAULT] = nl_msg_out_handler_default,
00375 [NL_CB_VERBOSE] = nl_msg_out_handler_verbose,
00376 [NL_CB_DEBUG] = nl_msg_out_handler_debug,
00377 },
00378 [NL_CB_OVERRUN] = {
00379 [NL_CB_DEFAULT] = nl_overrun_handler_default,
00380 [NL_CB_VERBOSE] = nl_overrun_handler_verbose,
00381 [NL_CB_DEBUG] = nl_overrun_handler_debug,
00382 },
00383 [NL_CB_SKIPPED] = {
00384 [NL_CB_DEFAULT] = nl_skipped_handler_default,
00385 [NL_CB_VERBOSE] = nl_skipped_handler_verbose,
00386 [NL_CB_DEBUG] = nl_skipped_handler_debug,
00387 },
00388 [NL_CB_ACK] = {
00389 [NL_CB_DEFAULT] = nl_ack_handler_default,
00390 [NL_CB_VERBOSE] = nl_ack_handler_verbose,
00391 [NL_CB_DEBUG] = nl_ack_handler_debug,
00392 },
00393 };
00394
00395 static nl_recvmsg_err_cb_t cb_err_def[NL_CB_KIND_MAX+1] = {
00396 [NL_CB_DEFAULT] = nl_error_handler_default,
00397 [NL_CB_VERBOSE] = nl_error_handler_verbose,
00398 [NL_CB_DEBUG] = nl_error_handler_debug,
00399 };
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 struct nl_cb *nl_cb_new(enum nl_cb_kind kind)
00412 {
00413 int i;
00414 struct nl_cb *cb;
00415
00416 if (kind < 0 || kind > NL_CB_KIND_MAX)
00417 return NULL;
00418
00419 cb = calloc(1, sizeof(*cb));
00420 if (!cb) {
00421 nl_errno(ENOMEM);
00422 return NULL;
00423 }
00424
00425 for (i = 0; i <= NL_CB_TYPE_MAX; i++)
00426 nl_cb_set(cb, i, kind, NULL, NULL);
00427
00428 nl_cb_err(cb, kind, NULL, NULL);
00429
00430 return cb;
00431 }
00432
00433
00434
00435
00436
00437 void nl_cb_destroy(struct nl_cb *cb)
00438 {
00439 free(cb);
00440 }
00441
00442
00443
00444
00445
00446
00447
00448 struct nl_cb *nl_cb_clone(struct nl_cb *orig)
00449 {
00450 struct nl_cb *cb;
00451
00452 cb = nl_cb_new(NL_CB_DEFAULT);
00453 if (!cb)
00454 return NULL;
00455
00456 memcpy(cb, orig, sizeof(*orig));
00457
00458 return cb;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 int nl_cb_set(struct nl_cb *cb, enum nl_cb_type type, enum nl_cb_kind kind,
00479 nl_recvmsg_msg_cb_t func, void *arg)
00480 {
00481 if (type < 0 || type > NL_CB_TYPE_MAX)
00482 return nl_error(ERANGE, "Callback type out of range");
00483
00484 if (kind < 0 || kind > NL_CB_KIND_MAX)
00485 return nl_error(ERANGE, "Callback kind out of range");
00486
00487 if (kind == NL_CB_CUSTOM) {
00488 cb->cb_set[type] = func;
00489 cb->cb_args[type] = arg;
00490 } else {
00491 cb->cb_set[type] = cb_def[type][kind];
00492 cb->cb_args[type] = arg;
00493 }
00494
00495 return 0;
00496 }
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 int nl_cb_set_all(struct nl_cb *cb, enum nl_cb_kind kind,
00508 nl_recvmsg_msg_cb_t func, void *arg)
00509 {
00510 int i, err;
00511
00512 for (i = 0; i <= NL_CB_TYPE_MAX; i++) {
00513 err = nl_cb_set(cb, i, kind, func, arg);
00514 if (err < 0)
00515 return err;
00516 }
00517
00518 return 0;
00519 }
00520
00521
00522
00523
00524
00525
00526
00527
00528 int nl_cb_err(struct nl_cb *cb, enum nl_cb_kind kind,
00529 nl_recvmsg_err_cb_t func, void *arg)
00530 {
00531 if (kind < 0 || kind > NL_CB_KIND_MAX)
00532 return nl_error(ERANGE, "Callback kind out of range");
00533
00534 if (kind == NL_CB_CUSTOM) {
00535 cb->cb_err = func;
00536 cb->cb_err_arg = arg;
00537 } else {
00538 cb->cb_err = cb_err_def[kind];
00539 cb->cb_err_arg = arg;
00540 }
00541
00542 return 0;
00543 }
00544
00545
00546
00547
00548
00549
00550 void nl_cb_overwrite_recvmsgs(struct nl_cb *cb,
00551 int (*func)(struct nl_handle *, struct nl_cb *))
00552 {
00553 cb->cb_recvmsgs_ow = func;
00554 }
00555
00556
00557
00558
00559
00560
00561 void nl_cb_overwrite_recv(struct nl_cb *cb,
00562 int (*func)(struct nl_handle *, struct sockaddr_nl *,
00563 unsigned char **, struct ucred **))
00564 {
00565 cb->cb_recv_ow = func;
00566 }
00567
00568
00569
00570
00571
00572
00573 void nl_cb_overwrite_send(struct nl_cb *cb,
00574 int (*func)(struct nl_handle *, struct nl_msg *))
00575 {
00576 cb->cb_send_ow = func;
00577 }
00578
00579
00580
00581