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
54EXPORT_SYMBOL size_t mnl_nlmsg_size(size_t len)
55{
56 return len + MNL_NLMSG_HDRLEN;
57}
58
66EXPORT_SYMBOL size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
67{
68 return nlh->nlmsg_len - MNL_NLMSG_HDRLEN;
69}
70
80EXPORT_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
101EXPORT_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
117EXPORT_SYMBOL void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
118{
119 return (void *)nlh + MNL_NLMSG_HDRLEN;
120}
121
130EXPORT_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
152EXPORT_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
172EXPORT_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
187EXPORT_SYMBOL void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
188{
189 return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len);
190}
191
206EXPORT_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
226EXPORT_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
232static 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
247static 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
360EXPORT_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
411struct mnl_nlmsg_batch {
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
434EXPORT_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
458EXPORT_SYMBOL void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
459{
460 free(b);
461}
462
474EXPORT_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
495EXPORT_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
515EXPORT_SYMBOL size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
516{
517 return b->buflen;
518}
519
527EXPORT_SYMBOL void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
528{
529 return b->buf;
530}
531
539EXPORT_SYMBOL void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
540{
541 return b->cur;
542}
543
550EXPORT_SYMBOL bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
551{
552 return b->buflen == 0;
553}
554
void * mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:539
bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:474
size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:515
void * mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:527
void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:495
struct mnl_nlmsg_batch * mnl_nlmsg_batch_start(void *buf, size_t limit)
Definition: nlmsg.c:434
bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:550
void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b)
Definition: nlmsg.c:458
void * mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset)
Definition: nlmsg.c:130
size_t mnl_nlmsg_size(size_t len)
Definition: nlmsg.c:54
bool mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq)
Definition: nlmsg.c:206
void * mnl_nlmsg_get_payload(const struct nlmsghdr *nlh)
Definition: nlmsg.c:117
struct nlmsghdr * mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len)
Definition: nlmsg.c:172
struct nlmsghdr * mnl_nlmsg_put_header(void *buf)
Definition: nlmsg.c:80
void mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, size_t extra_header_size)
Definition: nlmsg.c:360
bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len)
Definition: nlmsg.c:152
void * mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size)
Definition: nlmsg.c:101
size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh)
Definition: nlmsg.c:66
bool mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid)
Definition: nlmsg.c:226
void * mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh)
Definition: nlmsg.c:187