• Main Page
  • Modules
  • Data Structures
  • Files
  • File List

nlmsg.c

00001 /*
00002  * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU Lesser General Public License as published
00006  * by the Free Software Foundation; either version 2.1 of the License, or
00007  * (at your option) any later version.
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                 /* netlink control message. */
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                 /* special handling for the extra header. */
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                 /* this seems like an attribute header. */
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                 /* this is the attribute payload. */
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         /* the buffer that is used to store the batch. */
00409         void *buf;
00410         size_t limit;
00411         size_t buflen;
00412         /* the current netlink message in the batch. */
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 

Generated on Sun Dec 26 2010 22:23:55 for libmnl by  doxygen 1.7.1