OZ++ Class: NetlinkMsgHeader |
/****************************************************************************** * * Copyright (c) 2014 Antillia.com TOSHIYUKI ARAI. ALL RIGHTS RESERVED. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions, and the following disclaimer. * * 2. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * NetlinkMsgHeader.h * *****************************************************************************/ #pragma once #include <oz++/CommonObject.h> #include <oz++/Exception.h> #include <oz++/StringBufferT.h> #include <oz++/Pair.h> #include <oz++/CharString.h> #include <oz++/File.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <linux/if_arp.h> #include <asm/types.h> /* struct nlmsghdr { __u32 nlmsg_len; // Length of message including header __u16 nlmsg_type; // Message content __u16 nlmsg_flags; // Additional flags __u32 nlmsg_seq; // Sequence number __u32 nlmsg_pid; // Sending process port ID }; */ namespace OZ { class NetlinkMsgHeader :public CommonObject { private: struct nlmsghdr* header; int size; public: NetlinkMsgHeader(struct nlmsghdr* hdr) :header(hdr), size(0) { if (hdr) { size = hdr->nlmsg_len; } else { throw IException("Invalid argument"); } } public: NetlinkMsgHeader(struct nlmsghdr& hdr) :header(&hdr), size(hdr.nlmsg_len) { if (size <=0) { throw IException("Invalid argument"); } } NetlinkMsgHeader(const char* buffer, int len) :header((struct nlmsghdr*)buffer), size(len) { if (buffer == NULL || len == 0) { throw IException("Invalid arguments"); } } struct nlmsghdr* getMsgHeader() { return this->header; } bool isDone() { bool rc = false; if (header -> nlmsg_type == NLMSG_DONE) { rc = true; } return rc; } bool isError() { bool rc = false; if (header -> nlmsg_type == NLMSG_ERROR) { rc = true; } return rc; } __u16 type() { return header ->nlmsg_type; } void type(__u16 type) { header ->nlmsg_type = type; } int align() { return NLMSG_ALIGN(size); } int length() { return NLMSG_LENGTH(size); } int attributeLength(size_t msgSize ) { return header ->nlmsg_len - NLMSG_LENGTH(msgSize); } void length(__u32 len) { header ->nlmsg_len =len; // Length of message including header } __u16 flags() { return header -> nlmsg_flags; } void flags(__u16 flags) { header -> nlmsg_flags = flags; // Additional flags } __u32 seq() { return header -> nlmsg_seq; } void seq(__u32 seq) { header -> nlmsg_seq = seq; // Sequence number } __u32 pid() { return header ->nlmsg_pid; } void pid(__u32 pid) { header ->nlmsg_pid = pid; // Sending process port ID } int space() { return NLMSG_SPACE(size); } void* data() { return NLMSG_DATA(header); } //2015/01/01 struct nlmsgerr* errorMsg() { struct nlmsgerr* err = NULL; if (header -> nlmsg_type == NLMSG_ERROR) { err = (struct nlmsgerr*)NLMSG_DATA(header); } return err; } bool next() { bool rc = false; struct nlmsghdr* hdr = NLMSG_NEXT(this->header, size); if (hdr != NULL && size >0) { this -> header = hdr; if (ok() && isDone() == false) { rc = true; } } return rc; } __u32 ok() { // size_t len = size; return NLMSG_OK(header, (__u32)size); } int payload() { return NLMSG_PAYLOAD(header, size); } public: //2015/01/01 static CharString getFlags(__u16 flags) { static Pair< __u16 , const char*> hdrFlags[] = { {NLM_F_REQUEST,"NLM_F_REQUEST"}, {NLM_F_MULTI,"NLM_F_MULTI"}, {NLM_F_ACK,"NLM_F_ACK"}, {NLM_F_ECHO,"NLM_F_ECHO"}, {NLM_F_DUMP_INTR,"NLM_F_DUMP_INTR"}, {NLM_F_ROOT,"NLM_F_ROOT"}, {NLM_F_MATCH,"NLM_F_MATCH"}, {NLM_F_ATOMIC,"NLM_F_ATOMIC"}, {NLM_F_DUMP,"NLM_F_DUMP"}, {NLM_F_REPLACE,"NLM_F_REPLACE"}, {NLM_F_EXCL,"NLM_F_EXCL"}, {NLM_F_CREATE,"NLM_F_CREATE"}, {NLM_F_APPEND, "NLM_F_APPEND"}, }; StringBufferT<char> buffer; for (int i = 0; i<SizeOf(hdrFlags); i++) { if (flags & hdrFlags[i].first) { if (buffer.getContentSize() > 0) { buffer.append("|"); } buffer.append(hdrFlags[i].second); } } const char* string = (const char*)buffer; return CharString(string); } public: //2014/12/26 static const char* getType(int type) { // Routing/neighbour discovery messages. static Pair<int, const char*> types[] = { {RTM_BASE, "RTM_BASE"}, {RTM_NEWLINK, "RTM_NEWLINK"}, {RTM_DELLINK, "RTM_DELLINK"}, {RTM_GETLINK, "RTM_GETLINK"}, {RTM_SETLINK, "RTM_SETLINK"}, {RTM_NEWADDR, "RTM_NEWADDR"}, {RTM_DELADDR, "RTM_DELADDR"}, {RTM_GETADDR, "RTM_GETADDR"}, {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_GETROUTE, "RTM_GETROUTE"}, {RTM_NEWNEIGH, "RTM_NEWNEIGH"}, {RTM_DELNEIGH, "RTM_DELNEIGH"}, {RTM_GETNEIGH, "RTM_GETNEIGH"}, {RTM_NEWRULE, "RTM_NEWRULE"}, {RTM_DELRULE, "RTM_DELRULE"}, {RTM_GETRULE, "RTM_GETRULE"}, {RTM_NEWQDISC, "RTM_NEWQDISC"}, {RTM_DELQDISC, "RTM_DELQDISC"}, {RTM_GETQDISC, "RTM_GETQDISC"}, {RTM_NEWTCLASS, "RTM_NEWTCLASS"}, {RTM_DELTCLASS, "RTM_DELTCLASS"}, {RTM_GETTCLASS, "RTM_GETTCLASS"}, {RTM_NEWTFILTER, "RTM_NEWTFILTER"}, {RTM_DELTFILTER, "RTM_DELTFILTER"}, {RTM_GETTFILTER, "RTM_GETTFILTER"}, {RTM_NEWACTION, "RTM_NEWACTION"}, {RTM_DELACTION, "RTM_DELACTION"}, {RTM_GETACTION, "RTM_GETACTION"}, {RTM_NEWPREFIX, "RTM_NEWPREFIX"}, {RTM_GETMULTICAST, "RTM_GETMULTICAST"}, {RTM_GETANYCAST, "RTM_GETANYCAST"}, {RTM_NEWNEIGHTBL, "RTM_NEWNEIGHTBL"}, {RTM_GETNEIGHTBL, "RTM_GETNEIGHTBL"}, {RTM_SETNEIGHTBL, "RTM_SETNEIGHTBL"}, {RTM_NEWNDUSEROPT, "RTM_NEWNDUSEROPT"}, {RTM_NEWADDRLABEL, "RTM_NEWADDRLABEL"}, {RTM_DELADDRLABEL, "RTM_DELADDRLABEL"}, {RTM_GETADDRLABEL, "RTM_GETADDRLABEL"}, {RTM_GETDCB , "RTM_GETDCB"}, {RTM_SETDCB, "RTM_SETDCB"}, }; const char* name = "???"; for (int i = 0; i<SizeOf(types); i++) { if (types[i].first == type) { name = types[i].second; break; } } return name; } public: void save(const char* filename) { File file(filename); file.create(); size_t size = length(); printf("Size %zd\n", size); unsigned char* data = (unsigned char*) this -> header; while (size > 0) { int written = file.write(data, size); data += written; //printf("Written %d\n", written); if (written <= 0) { break; } size -= written; } file.close(); } public: void display() { printf("NLMSGHDR len: %u\n", length()); printf("NLMSGHDR type: %s\n", getType(type() )); printf("NLMSGHDR flags: %s\n", (const char*)getFlags( flags() )); printf("NLMSGHDR seq: %u\n", seq()); printf("NLMSGHDR pid: %u\n", pid()); } }; }