libmnl
1.0.3
|
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 size_t mnl_nlmsg_size(size_t len) 00055 { 00056 return len + MNL_NLMSG_HDRLEN; 00057 } 00058 EXPORT_SYMBOL(mnl_nlmsg_size); 00059 00067 size_t mnl_nlmsg_get_payload_len(const struct nlmsghdr *nlh) 00068 { 00069 return nlh->nlmsg_len - MNL_NLMSG_HDRLEN; 00070 } 00071 EXPORT_SYMBOL(mnl_nlmsg_get_payload_len); 00072 00082 struct nlmsghdr *mnl_nlmsg_put_header(void *buf) 00083 { 00084 int len = MNL_ALIGN(sizeof(struct nlmsghdr)); 00085 struct nlmsghdr *nlh = buf; 00086 00087 memset(buf, 0, len); 00088 nlh->nlmsg_len = len; 00089 return nlh; 00090 } 00091 EXPORT_SYMBOL(mnl_nlmsg_put_header); 00092 00104 void * 00105 mnl_nlmsg_put_extra_header(struct nlmsghdr *nlh, size_t size) 00106 { 00107 char *ptr = (char *)nlh + nlh->nlmsg_len; 00108 size_t len = MNL_ALIGN(size); 00109 nlh->nlmsg_len += len; 00110 memset(ptr, 0, len); 00111 return ptr; 00112 } 00113 EXPORT_SYMBOL(mnl_nlmsg_put_extra_header); 00114 00121 void *mnl_nlmsg_get_payload(const struct nlmsghdr *nlh) 00122 { 00123 return (void *)nlh + MNL_NLMSG_HDRLEN; 00124 } 00125 EXPORT_SYMBOL(mnl_nlmsg_get_payload); 00126 00135 void * 00136 mnl_nlmsg_get_payload_offset(const struct nlmsghdr *nlh, size_t offset) 00137 { 00138 return (void *)nlh + MNL_NLMSG_HDRLEN + MNL_ALIGN(offset); 00139 } 00140 EXPORT_SYMBOL(mnl_nlmsg_get_payload_offset); 00141 00158 bool mnl_nlmsg_ok(const struct nlmsghdr *nlh, int len) 00159 { 00160 return len >= (int)sizeof(struct nlmsghdr) && 00161 nlh->nlmsg_len >= sizeof(struct nlmsghdr) && 00162 (int)nlh->nlmsg_len <= len; 00163 } 00164 EXPORT_SYMBOL(mnl_nlmsg_ok); 00165 00179 struct nlmsghdr * 00180 mnl_nlmsg_next(const struct nlmsghdr *nlh, int *len) 00181 { 00182 *len -= MNL_ALIGN(nlh->nlmsg_len); 00183 return (struct nlmsghdr *)((void *)nlh + MNL_ALIGN(nlh->nlmsg_len)); 00184 } 00185 EXPORT_SYMBOL(mnl_nlmsg_next); 00186 00195 void *mnl_nlmsg_get_payload_tail(const struct nlmsghdr *nlh) 00196 { 00197 return (void *)nlh + MNL_ALIGN(nlh->nlmsg_len); 00198 } 00199 EXPORT_SYMBOL(mnl_nlmsg_get_payload_tail); 00200 00215 bool 00216 mnl_nlmsg_seq_ok(const struct nlmsghdr *nlh, unsigned int seq) 00217 { 00218 return nlh->nlmsg_seq && seq ? nlh->nlmsg_seq == seq : true; 00219 } 00220 EXPORT_SYMBOL(mnl_nlmsg_seq_ok); 00221 00236 bool 00237 mnl_nlmsg_portid_ok(const struct nlmsghdr *nlh, unsigned int portid) 00238 { 00239 return nlh->nlmsg_pid && portid ? nlh->nlmsg_pid == portid : true; 00240 } 00241 EXPORT_SYMBOL(mnl_nlmsg_portid_ok); 00242 00243 static void mnl_nlmsg_fprintf_header(FILE *fd, const struct nlmsghdr *nlh) 00244 { 00245 fprintf(fd, "----------------\t------------------\n"); 00246 fprintf(fd, "| %.010u |\t| message length |\n", nlh->nlmsg_len); 00247 fprintf(fd, "| %.05u | %c%c%c%c |\t| type | flags |\n", 00248 nlh->nlmsg_type, 00249 nlh->nlmsg_flags & NLM_F_REQUEST ? 'R' : '-', 00250 nlh->nlmsg_flags & NLM_F_MULTI ? 'M' : '-', 00251 nlh->nlmsg_flags & NLM_F_ACK ? 'A' : '-', 00252 nlh->nlmsg_flags & NLM_F_ECHO ? 'E' : '-'); 00253 fprintf(fd, "| %.010u |\t| sequence number|\n", nlh->nlmsg_seq); 00254 fprintf(fd, "| %.010u |\t| port ID |\n", nlh->nlmsg_pid); 00255 fprintf(fd, "----------------\t------------------\n"); 00256 } 00257 00258 static void 00259 mnl_nlmsg_fprintf_payload(FILE *fd, const struct nlmsghdr *nlh, 00260 size_t extra_header_size) 00261 { 00262 int rem = 0; 00263 unsigned int i; 00264 00265 for (i=sizeof(struct nlmsghdr); i<nlh->nlmsg_len; i+=4) { 00266 char *b = (char *) nlh; 00267 struct nlattr *attr = (struct nlattr *) (b+i); 00268 00269 /* netlink control message. */ 00270 if (nlh->nlmsg_type < NLMSG_MIN_TYPE) { 00271 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", 00272 0xff & b[i], 0xff & b[i+1], 00273 0xff & b[i+2], 0xff & b[i+3]); 00274 fprintf(fd, "| |\n"); 00275 /* special handling for the extra header. */ 00276 } else if (extra_header_size > 0) { 00277 extra_header_size -= 4; 00278 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", 00279 0xff & b[i], 0xff & b[i+1], 00280 0xff & b[i+2], 0xff & b[i+3]); 00281 fprintf(fd, "| extra header |\n"); 00282 /* this seems like an attribute header. */ 00283 } else if (rem == 0 && (attr->nla_type & NLA_TYPE_MASK) != 0) { 00284 fprintf(fd, "|%c[%d;%dm" 00285 "%.5u" 00286 "%c[%dm" 00287 "|" 00288 "%c[%d;%dm" 00289 "%c%c" 00290 "%c[%dm" 00291 "|" 00292 "%c[%d;%dm" 00293 "%.5u" 00294 "%c[%dm|\t", 00295 27, 1, 31, 00296 attr->nla_len, 00297 27, 0, 00298 27, 1, 32, 00299 attr->nla_type & NLA_F_NESTED ? 'N' : '-', 00300 attr->nla_type & 00301 NLA_F_NET_BYTEORDER ? 'B' : '-', 00302 27, 0, 00303 27, 1, 34, 00304 attr->nla_type & NLA_TYPE_MASK, 00305 27, 0); 00306 fprintf(fd, "|len |flags| type|\n"); 00307 00308 if (!(attr->nla_type & NLA_F_NESTED)) { 00309 rem = NLA_ALIGN(attr->nla_len) - 00310 sizeof(struct nlattr); 00311 } 00312 /* this is the attribute payload. */ 00313 } else if (rem > 0) { 00314 rem -= 4; 00315 fprintf(fd, "| %.2x %.2x %.2x %.2x |\t", 00316 0xff & b[i], 0xff & b[i+1], 00317 0xff & b[i+2], 0xff & b[i+3]); 00318 fprintf(fd, "| data |"); 00319 fprintf(fd, "\t %c %c %c %c\n", 00320 isalnum(b[i]) ? b[i] : 0, 00321 isalnum(b[i+1]) ? b[i+1] : 0, 00322 isalnum(b[i+2]) ? b[i+2] : 0, 00323 isalnum(b[i+3]) ? b[i+3] : 0); 00324 } 00325 } 00326 fprintf(fd, "----------------\t------------------\n"); 00327 } 00328 00372 void 00373 mnl_nlmsg_fprintf(FILE *fd, const void *data, size_t datalen, 00374 size_t extra_header_size) 00375 { 00376 const struct nlmsghdr *nlh = data; 00377 int len = datalen; 00378 00379 while (mnl_nlmsg_ok(nlh, len)) { 00380 mnl_nlmsg_fprintf_header(fd, nlh); 00381 mnl_nlmsg_fprintf_payload(fd, nlh, extra_header_size); 00382 nlh = mnl_nlmsg_next(nlh, &len); 00383 } 00384 } 00385 EXPORT_SYMBOL(mnl_nlmsg_fprintf); 00386 00420 struct mnl_nlmsg_batch { 00421 /* the buffer that is used to store the batch. */ 00422 void *buf; 00423 size_t limit; 00424 size_t buflen; 00425 /* the current netlink message in the batch. */ 00426 void *cur; 00427 bool overflow; 00428 }; 00429 00443 struct mnl_nlmsg_batch *mnl_nlmsg_batch_start(void *buf, size_t limit) 00444 { 00445 struct mnl_nlmsg_batch *b; 00446 00447 b = malloc(sizeof(struct mnl_nlmsg_batch)); 00448 if (b == NULL) 00449 return NULL; 00450 00451 b->buf = buf; 00452 b->limit = limit; 00453 b->buflen = 0; 00454 b->cur = buf; 00455 b->overflow = false; 00456 00457 return b; 00458 } 00459 EXPORT_SYMBOL(mnl_nlmsg_batch_start); 00460 00467 void mnl_nlmsg_batch_stop(struct mnl_nlmsg_batch *b) 00468 { 00469 free(b); 00470 } 00471 EXPORT_SYMBOL(mnl_nlmsg_batch_stop); 00472 00484 bool mnl_nlmsg_batch_next(struct mnl_nlmsg_batch *b) 00485 { 00486 struct nlmsghdr *nlh = b->cur; 00487 00488 if (b->buflen + nlh->nlmsg_len > b->limit) { 00489 b->overflow = true; 00490 return false; 00491 } 00492 b->cur = b->buf + b->buflen + nlh->nlmsg_len; 00493 b->buflen += nlh->nlmsg_len; 00494 return true; 00495 } 00496 EXPORT_SYMBOL(mnl_nlmsg_batch_next); 00497 00506 void mnl_nlmsg_batch_reset(struct mnl_nlmsg_batch *b) 00507 { 00508 if (b->overflow) { 00509 struct nlmsghdr *nlh = b->cur; 00510 memcpy(b->buf, b->cur, nlh->nlmsg_len); 00511 b->buflen = nlh->nlmsg_len; 00512 b->cur = b->buf + b->buflen; 00513 b->overflow = false; 00514 } else { 00515 b->buflen = 0; 00516 b->cur = b->buf; 00517 } 00518 } 00519 EXPORT_SYMBOL(mnl_nlmsg_batch_reset); 00520 00527 size_t mnl_nlmsg_batch_size(struct mnl_nlmsg_batch *b) 00528 { 00529 return b->buflen; 00530 } 00531 EXPORT_SYMBOL(mnl_nlmsg_batch_size); 00532 00540 void *mnl_nlmsg_batch_head(struct mnl_nlmsg_batch *b) 00541 { 00542 return b->buf; 00543 } 00544 EXPORT_SYMBOL(mnl_nlmsg_batch_head); 00545 00553 void *mnl_nlmsg_batch_current(struct mnl_nlmsg_batch *b) 00554 { 00555 return b->cur; 00556 } 00557 EXPORT_SYMBOL(mnl_nlmsg_batch_current); 00558 00565 bool mnl_nlmsg_batch_is_empty(struct mnl_nlmsg_batch *b) 00566 { 00567 return b->buflen == 0; 00568 } 00569 EXPORT_SYMBOL(mnl_nlmsg_batch_is_empty); 00570