libmnl  1.0.5
nlmsg.c
1 /*
2  * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  */
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <ctype.h>
13 #include <errno.h>
14 #include <string.h>
15 #include <libmnl/libmnl.h>
16 #include "internal.h"
17 
54 EXPORT_SYMBOL size_t mnl_nlmsg_size(size_t len)
55 {
56  return len + MNL_NLMSG_HDRLEN;
57 }
58 
66 EXPORT_SYMBOL size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
67 {
68  return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
69 }
70 
80 EXPORT_SYMBOL struct nlmsghdr *mnl_nlmsg_put_header(void *buf)
81 {
82  int len = MNL_ALIGN(sizeof(struct nlmsghdr));
83  struct nlmsghdr *nlh = buf;
84 
85  memset(buf, 0, len);
86  nlh->nlmsg_len = len;
87  return nlh;
88 }
89 
101 EXPORT_SYMBOL void *mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh,
102  size_t size)
103 {
104  char *ptr = (char *)nlh + nlh->nlmsg_len;
105  size_t len = MNL_ALIGN(size);
106  nlh->nlmsg_len += len;
107  memset(ptr, 0, len);
108  return ptr;
109 }
110 
117 EXPORT_SYMBOL void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
118 {
119  return (void *)nlh + MNL_NLMSG_HDRLEN;
120 }
121 
130 EXPORT_SYMBOL void *mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh,
131  size_t offset)
132 {
133  return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset);
134 }
135 
152 EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
153 {
154  return len >= (int)sizeof(struct nlmsghdr) &&
155  nlh->nlmsg_len >= sizeof(struct nlmsghdr) &&
156  (int)nlh->nlmsg_len <= len;
157 }
158 
172 EXPORT_SYMBOL struct nlmsghdr *mnl_nlmsg_next(const struct nlmsghdr *nlh,
173  int *len)
174 {
175  *len -= MNL_ALIGN(nlh->nlmsg_len);
176  return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len));
177 }
178 
187 EXPORT_SYMBOL void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
188 {
189  return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
190 }
191 
206 EXPORT_SYMBOL bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh,
207  unsigned int seq)
208 {
209  return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true;
210 }
211 
226 EXPORT_SYMBOL bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh,
227  unsigned int portid)
228 {
229  return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true;
230 }
231 
232 static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh)
233 {
234  fprintf(fd, "----------------\t------------------\n");
235  fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len);
236  fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n",
237  nlh->nlmsg_type,
238  nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-',
239  nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-',
240  nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-',
241  nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-');
242  fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq);
243  fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid);
244  fprintf(fd, "----------------\t------------------\n");
245 }
246 
247 static void mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh,
248  size_t extra_header_size)
249 {
250  int rem = 0;
251  unsigned int i;
252 
253  for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) {
254  char *b = (char *) nlh;
255  struct nlattr *attr = (struct nlattr *) (b+i);
256 
257  /* netlink control message. */
258  if (nlh->nlmsg_type < NLMSG_MIN_TYPE) {
259  fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
260  0xff & b[i], 0xff & b[i+1],
261  0xff & b[i+2], 0xff & b[i+3]);
262  fprintf(fd, "| |\n");
263  /* special handling for the extra header. */
264  } else if (extra_header_size > 0) {
265  extra_header_size -= 4;
266  fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
267  0xff & b[i], 0xff & b[i+1],
268  0xff & b[i+2], 0xff & b[i+3]);
269  fprintf(fd, "| extra header |\n");
270  /* this seems like an attribute header. */
271  } else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) {
272  fprintf(fd, "|%c[%d;%dm"
273  "%.5u"
274  "%c[%dm"
275  "|"
276  "%c[%d;%dm"
277  "%c%c"
278  "%c[%dm"
279  "|"
280  "%c[%d;%dm"
281  "%.5u"
282  "%c[%dm|\t",
283  27, 1, 31,
284  attr->nla_len,
285  27, 0,
286  27, 1, 32,
287  attr->nla_type & NLA_F_NESTED ? 'N' : '-',
288  attr->nla_type &
289  NLA_F_NET_BYTEORDER ? 'B' : '-',
290  27, 0,
291  27, 1, 34,
292  attr->nla_type & NLA_TYPE_MASK,
293  27, 0);
294  fprintf(fd, "|len |flags| type|\n");
295 
296  if (!(attr->nla_type & NLA_F_NESTED)) {
297  rem = NLA_ALIGN(attr->nla_len) -
298  sizeof(struct nlattr);
299  }
300  /* this is the attribute payload. */
301  } else if (rem > 0) {
302  rem -= 4;
303  fprintf(fd, "| %.2x %.2x %.2x %.2x |\t",
304  0xff & b[i], 0xff & b[i+1],
305  0xff & b[i+2], 0xff & b[i+3]);
306  fprintf(fd, "| data |");
307  fprintf(fd, "\t %c %c %c %c\n",
308  isprint(b[i]) ? b[i] : ' ',
309  isprint(b[i+1]) ? b[i+1] : ' ',
310  isprint(b[i+2]) ? b[i+2] : ' ',
311  isprint(b[i+3]) ? b[i+3] : ' ');
312  }
313  }
314  fprintf(fd, "----------------\t------------------\n");
315 }
316 
360 EXPORT_SYMBOL void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen,
361  size_t extra_header_size)
362 {
363  const struct nlmsghdr *nlh = data;
364  int len = datalen;
365 
366  while (mnl_nlmsg_ok(nlh, len)) {
367  mnl_nlmsg_fprintf_header(fd, nlh);
368  mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size);
369  nlh = mnl_nlmsg_next(nlh, &len);
370  }
371 }
372 
412  /* the buffer that is used to store the batch. */
413  void *buf;
414  size_t limit;
415  size_t buflen;
416  /* the current netlink message in the batch. */
417  void *cur;
418  bool overflow;
419 };
420 
434 EXPORT_SYMBOL struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf,
435  size_t limit)
436 {
437  struct mnl_nlmsg_batch *b;
438 
439  b = malloc(sizeof(struct mnl_nlmsg_batch));
440  if (b == NULL)
441  return NULL;
442 
443  b->buf = buf;
444  b->limit = limit;
445  b->buflen = 0;
446  b->cur = buf;
447  b->overflow = false;
448 
449  return b;
450 }
451 
458 EXPORT_SYMBOL void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
459 {
460  free(b);
461 }
462 
474 EXPORT_SYMBOL bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
475 {
476  struct nlmsghdr *nlh = b->cur;
477 
478  if (b->buflen + nlh->nlmsg_len > b->limit) {
479  b->overflow = true;
480  return false;
481  }
482  b->cur = b->buf + b->buflen + nlh->nlmsg_len;
483  b->buflen += nlh->nlmsg_len;
484  return true;
485 }
486 
495 EXPORT_SYMBOL void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
496 {
497  if (b->overflow) {
498  struct nlmsghdr *nlh = b->cur;
499  memcpy(b->buf, b->cur, nlh->nlmsg_len);
500  b->buflen = nlh->nlmsg_len;
501  b->cur = b->buf + b->buflen;
502  b->overflow = false;
503  } else {
504  b->buflen = 0;
505  b->cur = b->buf;
506  }
507 }
508 
515 EXPORT_SYMBOL size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
516 {
517  return b->buflen;
518 }
519 
527 EXPORT_SYMBOL void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
528 {
529  return b->buf;
530 }
531 
539 EXPORT_SYMBOL void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
540 {
541  return b->cur;
542 }
543 
550 EXPORT_SYMBOL bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
551 {
552  return b->buflen == 0;
553 }
554 
EXPORT_SYMBOL void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:495
EXPORT_SYMBOL bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:474
EXPORT_SYMBOL struct mnl_nlmsg_batch * mnl_nlmsg_batch_start(void *buf, size_t limit)
Definition: nlmsg.c:434
EXPORT_SYMBOL void * mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:527
EXPORT_SYMBOL void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:458
EXPORT_SYMBOL size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:515
EXPORT_SYMBOL void * mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:539
EXPORT_SYMBOL bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:550
EXPORT_SYMBOL void * mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
Definition: nlmsg.c:101
EXPORT_SYMBOL bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
Definition: nlmsg.c:226
EXPORT_SYMBOL bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
Definition: nlmsg.c:206
EXPORT_SYMBOL void * mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
Definition: nlmsg.c:117
EXPORT_SYMBOL void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size)
Definition: nlmsg.c:360
EXPORT_SYMBOL void * mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
Definition: nlmsg.c:130
EXPORT_SYMBOL size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
Definition: nlmsg.c:66
EXPORT_SYMBOL bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
Definition: nlmsg.c:152
EXPORT_SYMBOL size_t mnl_nlmsg_size(size_t len)
Definition: nlmsg.c:54
EXPORT_SYMBOL struct nlmsghdr * mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
Definition: nlmsg.c:172
EXPORT_SYMBOL void * mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
Definition: nlmsg.c:187
EXPORT_SYMBOL struct nlmsghdr * mnl_nlmsg_put_header(void *buf)
Definition: nlmsg.c:80