| 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());
}
};
}