00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdbool.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <ctype.h>
00013 #include <errno.h>
00014 #include <string.h>
00015 #include <libmnl/libmnl.h>
00016 #include "internal.h"
00017
00054 EXPORT_SYMBOL size_t mnl_nlmsg_size(size_t len)
00055 {
00056 return len + MNL_NLMSG_HDRLEN;
00057 }
00058
00066 EXPORT_SYMBOL size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
00067 {
00068 return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
00069 }
00070
00080 EXPORT_SYMBOL struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
00081 {
00082 int len = MNL_ALIGN(sizeof(struct nlmsghdr));
00083 struct nlmsghdr *nlh = buf;
00084
00085 memset(buf, 0, len);
00086 nlh->nlmsg_len = len;
00087 return nlh;
00088 }
00089
00101 EXPORT_SYMBOL void *
00102 mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
00103 {
00104 char *ptr = (char *)nlh + nlh->nlmsg_len;
00105 nlh->nlmsg_len += MNL_ALIGN(size);
00106 memset(ptr, 0, size);
00107 return ptr;
00108 }
00109
00116 EXPORT_SYMBOL void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
00117 {
00118 return (void *)nlh + MNL_NLMSG_HDRLEN;
00119 }
00120
00129 EXPORT_SYMBOL void *
00130 mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
00131 {
00132 return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
00133 }
00134
00151 EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
00152 {
00153 return len >= (int)sizeof(struct nlmsghdr) &&
00154 nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
00155 (int)nlh->nlmsg_len <= len;
00156 }
00157
00171 EXPORT_SYMBOL struct nlmsghdr *
00172 mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
00173 {
00174 *len -= MNL_ALIGN(nlh->nlmsg_len);
00175 return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
00176 }
00177
00186 EXPORT_SYMBOL void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
00187 {
00188 return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
00189 }
00190
00205 EXPORT_SYMBOL bool
00206 mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
00207 {
00208 return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
00209 }
00210
00225 EXPORT_SYMBOL bool
00226 mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
00227 {
00228 return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
00229 }
00230
00231 static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh)
00232 {
00233 fprintf(fd, "----------------\t------------------\n");
00234 fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len);
00235 fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n",
00236 nlh->nlmsg_type,
00237 nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-',
00238 nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-',
00239 nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-',
00240 nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-');
00241 fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq);
00242 fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid);
00243 fprintf(fd, "----------------\t------------------\n");
00244 }
00245
00246 static void
00247 mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
00248 size_t extra_header_size)
00249 {
00250 int rem = 0;
00251 unsigned int i;
00252
00253 for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
00254 char *b = (char *) nlh;
00255 struct nlattr *attr = (struct nlattr *) (b+i);
00256
00257
00258 if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
00259 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
00260 0xff & b[i], 0xff & b[i+1],
00261 0xff & b[i+2], 0xff & b[i+3]);
00262 fprintf(fd, "| |\n");
00263
00264 } else if (extra_header_size > 0) {
00265 extra_header_size -= 4;
00266 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
00267 0xff & b[i], 0xff & b[i+1],
00268 0xff & b[i+2], 0xff & b[i+3]);
00269 fprintf(fd, "| extra header |\n");
00270
00271 } else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
00272 fprintf(fd, "|%c[%d;%dm"
00273 "%.5u"
00274 "%c[%dm"
00275 "|"
00276 "%c[%d;%dm"
00277 "%c%c"
00278 "%c[%dm"
00279 "|"
00280 "%c[%d;%dm"
00281 "%.5u"
00282 "%c[%dm|\t",
00283 27, 1, 31,
00284 attr->nla_len,
00285 27, 0,
00286 27, 1, 32,
00287 attr->nla_type & NLA_F_NESTED ? 'N' : '-',
00288 attr->nla_type &
00289 NLA_F_NET_BYTEORDER ? 'B' : '-',
00290 27, 0,
00291 27, 1, 34,
00292 attr->nla_type & NLA_TYPE_MASK,
00293 27, 0);
00294 fprintf(fd, "|len |flags| type|\n");
00295
00296 if (!(attr->nla_type & NLA_F_NESTED)) {
00297 rem = NLA_ALIGN(attr->nla_len) -
00298 sizeof(struct nlattr);
00299 }
00300
00301 } else if (rem > 0) {
00302 rem -= 4;
00303 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
00304 0xff & b[i], 0xff & b[i+1],
00305 0xff & b[i+2], 0xff & b[i+3]);
00306 fprintf(fd, "| data |");
00307 fprintf(fd, "\t %c %c %c %c\n",
00308 isalnum(b[i]) ? b[i] : 0,
00309 isalnum(b[i+1]) ? b[i+1] : 0,
00310 isalnum(b[i+2]) ? b[i+2] : 0,
00311 isalnum(b[i+3]) ? b[i+3] : 0);
00312 }
00313 }
00314 fprintf(fd, "----------------\t------------------\n");
00315 }
00316
00360 EXPORT_SYMBOL void
00361 mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
00362 size_t extra_header_size)
00363 {
00364 const struct nlmsghdr *nlh = data;
00365 int len = datalen;
00366
00367 while (mnl_nlmsg_ok(nlh, len)) {
00368 mnl_nlmsg_fprintf_header(fd, nlh);
00369 mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
00370 nlh = mnl_nlmsg_next(nlh, &len);
00371 }
00372 }
00373
00407 struct mnl_nlmsg_batch {
00408
00409 void *buf;
00410 size_t limit;
00411 size_t buflen;
00412
00413 void *cur;
00414 bool overflow;
00415 };
00416
00430 EXPORT_SYMBOL struct mnl_nlmsg_batch *
00431 mnl_nlmsg_batch_start(void *buf, size_t limit)
00432 {
00433 struct mnl_nlmsg_batch *b;
00434
00435 b = malloc(sizeof(struct mnl_nlmsg_batch));
00436 if (b == NULL)
00437 return NULL;
00438
00439 b->buf = buf;
00440 b->limit = limit;
00441 b->buflen = 0;
00442 b->cur = buf;
00443 b->overflow = false;
00444
00445 return b;
00446 }
00447
00454 EXPORT_SYMBOL void
00455 mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
00456 {
00457 free(b);
00458 }
00459
00471 EXPORT_SYMBOL bool
00472 mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
00473 {
00474 struct nlmsghdr *nlh = b->cur;
00475
00476 if (b->buflen + nlh->nlmsg_len > b->limit) {
00477 b->overflow = true;
00478 return false;
00479 }
00480 b->cur = b->buf + b->buflen + nlh->nlmsg_len;
00481 b->buflen += nlh->nlmsg_len;
00482 return true;
00483 }
00484
00493 EXPORT_SYMBOL void
00494 mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
00495 {
00496 if (b->overflow) {
00497 struct nlmsghdr *nlh = b->cur;
00498 memcpy(b->buf, b->cur, nlh->nlmsg_len);
00499 b->buflen = nlh->nlmsg_len;
00500 b->cur = b->buf + b->buflen;
00501 b->overflow = false;
00502 } else {
00503 b->buflen = 0;
00504 b->cur = b->buf;
00505 }
00506 }
00507
00514 EXPORT_SYMBOL size_t
00515 mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
00516 {
00517 return b->buflen;
00518 }
00519
00527 EXPORT_SYMBOL void *
00528 mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
00529 {
00530 return b->buf;
00531 }
00532
00540 EXPORT_SYMBOL void *
00541 mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
00542 {
00543 return b->cur;
00544 }
00545
00552 EXPORT_SYMBOL bool
00553 mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
00554 {
00555 return b->buflen == 0;
00556 }
00557