Send net-snmp INFORM calling send_v2trap() in C - c

This tutorial explains how to send a SNMP TRAP calling send_v2trap() in C.
How do I send a SNMP INFORM instead?
The manpage says I can send INFORMs, but it doesn't say how.

Figured out by myself :-)
send_v2trap(3) says:
send_v2trap() uses the supplied list of variable bindings to form an SNMPv2 trap,
which is sent to SNMPv2-capable sinks on the configured list.
An equivalent INFORM is sent to the configuredq list of inform sinks.
but doesn't say what is this configured list;
Instead, snmpd.conf(5) explains that I should edit /etc/snmp/snmpd.conf and add lines telling which hosts will receive the INFORMs. For example, the following makes send_v2trap() send INFORM to host1 and host2:
informsink host1 public 162
informsink host2 public 162

Actually, you can register the sinks inside C by using the net-snmp, agent_trap.h function:
void snmpd_parse_config_informsink(const char *, char *);
where I suppose that the first argument is not used and the second argument you can write as the following example in C++:
//sink declarations
String serverAddress = "127.0.0.1";
int serverPort = 162;
String community = "public";
//mount sink string
string cptrS = serverAddress + ":" + to_string(serverPort) + " \t\n" + community;
//transform string to char*
char * cptr = &cptrS[0];
//register the sink
snmpd_parse_config_informsink(NULL,cptr);
now, you can call send_v2trap() and send by inform the variables set using snmp_varlist_add_variable().
Reference: http://www.net-snmp.org/dev/agent/agent__trap_8c-source.html

Related

GLIB D-BUS Bluetooth - How to get the file descriptor?

I am using BLUEZ and GLIB/D-BUS to connect 2 Raspberry Pi (also a laptop and a Raspberry Pi).
So far I could make fair progress.
EDIT: on good advises from #ukBaz I am using a python client from my laptop, and my C code server on the Raspberry Pi.
On the "server", I can register the device with a custom service UUID and a Serial RFCOMM profile UUID, and wait for connection. Connecting with the python client works and I can see that there is a handler available (see after code below for debug output)
I'm using this code (within a dbus loop, code simplified for readability):
static void new_connection(GDBusMethodInvocation *inv)
{
g_log(LOG_SERVER, G_LOG_LEVEL_MESSAGE, "New connection.");
GDBusMessage *msg = g_dbus_method_invocation_get_message(inv);
// This prints the output below this code snippet
gchar *content = g_dbus_message_print(msg, 2);
g_log(LOG_SERVER, G_LOG_LEVEL_INFO, "Message is:\n%s", content);
g_free(content);
GVariant *params = g_dbus_method_invocation_get_parameters(inv);
const char *object;
GVariant *properties;
gint32 *handle;
g_variant_get(params, "(oha{sv})", &object, &handle, &properties);
// Problem here, 'handle' is NULL
g_log(LOG_SERVER, G_LOG_LEVEL_INFO, "Object is [%s]\nHandle is [%ls]", object, handle);
GVariantIter iter;
g_variant_iter_init(&iter, properties);
display_properties(&iter);
}
Here is the output:
New connection.
Message is:
Type: method-call
Flags: none
Version: 0
Serial: 32
Headers:
path -> objectpath '/org/bluez/jscturret'
interface -> 'org.bluez.Profile1'
member -> 'NewConnection'
destination -> ':1.18'
sender -> ':1.11'
signature -> signature 'oha{sv}'
num-unix-fds -> uint32 1
Body: (objectpath '/org/bluez/hci0/dev_00_AA_AA_AA_AA_AA', handle 0, #a{sv} {})
UNIX File Descriptors:
fd 7: dev=0:8,mode=0140777,ino=41101,uid=0,gid=0,rdev=0:0,size=0,atime=0,mtime=0,ctime=0
Object is [/org/bluez/hci0/dev_00_AA_AA_AA_AA_AA]
Handle is [(null)]
It shows that there is a file descriptor fd 7 but when I read the GVariant parameter I get NULL.
How can I access the file descriptor? My understanding is I need that to be able to read/write from/to the client.
I used https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/device-api.txt and https://git.kernel.org/pub/scm/bluetooth/bluez.git/tree/doc/adapter-api.txt for reference and a few other posts here on SO.
Also got a lot of info in https://www.linumiz.com/.
Current full code is available here: btservice
Oh! I am pretty sure you are supposed to send a pointer to an integer (not a pointer to a pointer to it).
You can do
gint32 handle; // instead of gint32 *handle;
and it should work.
This API has a very poor design (relying on variadic, with format specifiers... the reason why people dislike C).

Getting Host field from TCP packet payload

I'm writing a kernel module in C, and trying to get the Host field from a TCP packet's payload, carrying http request headers.
I've managed to do something similar with FTP (scan the payload and look for FTP commands), but I can't seem to be able to do the same and find the field.
My module is connected to the POST_ROUTING hook.
each packet that goes to that hook, if it has a dst port of 80, is being recognized as an HTTP packet, and so my module starts to parse it.
for some reason, I can't seem to be able to get the HOST line (matter of fact, I only see the server HTTP 200 ok)
are these headers always go on the packets that use port 80?
if so, what is the best way to parse those packt's payload? seems like going char by char is a lot of work. is there any better way?
Thanks
EDIT:
Got some progress.
every packet I get from the server, I can read the payload with no problem. but every packet I send - it's like the payload is empty.
I thought it's a problem of skb pointer, but i'm getting the TCP ports fine. just can't seem to read this damn payload.
this is how i parse it:
unsigned char* user_data = (unsigned char *)((int)tcphd + (int)(tcphd->doff * 4));
unsigned char *it;
for (it = user_data; it != tail; ++it) {
unsigned char c = *(unsigned char *)it;
http_command[http_command_index] = c;
http_command_index++;
}
where tail:
tail = skb_tail_pointer(skb);
The pointer doesn't advance at all on the loop. it's like it's empty from the start or something, and I can't figure out why.
help, please.
I've managed to solve this.
using this
, I've figured out how to parse all of the packet's payload.
I hope this code explains it
int http_command_offset = iphd->ihl*4 + tcphd->doff*4;
int http_command_length = skb->len - http_command_offset;
http_command = kmalloc(http_command_length + 1, GFP_ATOMIC);
skb_copy_bits(skb, http_command_offset , (void*)http_command, http_command_length);
skb_cop_bits, just copies the payload entirely into the buffer i've created. parsing it now is pretty simple.

Calling a C library method from swift using pointers

Given the following ODBC C API information and associated type definitions, how does one call the SQLSetEnvAttr function from swift?
From swift, my code successfully invokes the prerequisite SQLAllocHandle function which provides the handle to the environment (henv) utilized in the subsequent SQLSetEnvAttr function call.
I have tried a variety of approaches including UnsafeMutablePointer, attempting to follow instructions referenced on the following sites, but I couldn't figure out how to get the compiler to allow me to convert from a Void * to a SQLPOINTER (even though it is defined to be the same thing). Additionally, I was stymied on how to make the UnsafeMutablePointer point to the value of the CUnsignedLong variable (SQL_OV_ODBC3 typedef) I used (set to 3)
http://www.sitepoint.com/using-legacy-c-apis-swift/
http://chris.eidhof.nl/posts/swift-c-interop.html
ODBC API
typedef signed short int SQLSMALLINT;
typedef SQLSMALLINT SQLRETURN;
typedef void * SQLPOINTER;
#define SQL_ATTR_ODBC_VERSION 200
#define SQL_OV_ODBC3 3UL
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION,
(SQLPOINTER) SQL_OV_ODBC3, 0);
The working swift code that gets me the handle to the environment is:
var sqlHenvPtr : UnsafeMutablePointer<SQLHENV> = UnsafeMutablePointer<SQLHENV>.alloc(1)
var retcode : CShort = SQLAllocHandle(Int16(SQL_HANDLE_ENV), nil, sqlHenvPtr)
Looking for help with how to define and pass the third parameter:
let SQL_ATTR_ODBC_VERSION : Int32 = 200
retcode = SQLSetEnvAttr(sqlHenvPtr.memory, SQL_ATTR_ODBC_VERSION, ???, 0)
Any assistance would be much appreciated.
Updated per Chris's feedback
let value = UnsafeMutablePointer<Void>(bitPattern: 3)
SQLSetEnvAttr(0, 0, value, 0)
The expected value by SQLSetEnvAttr() is 0x3 (in your case it was 0x10025a478). I verified that my own prototype C function which accepts SQLPOINTER receives 0x3 in case of preparing 3rd parameter in proposed way. Hope it helps now.

Send complete string array at once

I'm trying to send some Hayes commands (AT commands) to my modem through a serial line.
The function I call is post_request::open(). Within this method there is a static commands string array holding the commands to configure the connection profile.
My first question is: Should I use a more "flexible" approach on creating the commands list?
I always need to send these eight commands to my modem. Of course the url, content_type and content_length vary.
Maybe somebody can show me a better way to do it.
int post_request::open(const char *url, unsigned content_length, const char *content_type)
{
static const char *commands[] =
{
// Connection profile
"AT^SISS=0,conId,0;",
// HTTP
"AT^SISS=0,srvType,Http;",
// User Agent
"AT^SISS=0,hcUsrAgent," USER_AGENT_STRING ";",
// HTTP method
"AT^SISS=0,hcMethod,1;",
// Placeholder for modem type bdx80
"AT;",
// Placeholder for address
"AT;",
// Placeholder for number of bytes sent
"AT;",
// Placeholder for content type
"AT;",
// Open internet session with configured profile
"AT^SISO=0\r",
NULL
};
// Some code...
if (modem->modem_type == bdx80)
commands[4] = "AT^SISS=0,secOpt,-1;";
// Some more code...
commands[6] = "AT^SISS=0,hcContLen,",content_length,";";
// Code for content_type settings...
int error = send_commands(modem, timeout, commands);
if (error)
return error;
}
After I finished the connection profile setup, I call send_commands().
I have a third party library which does the uart transmit & receive stuff.
The function I call within send_commands() is uart_tx().
Question: What do I need to do, to call uart_tx() correctly? I want the complete commands list to be sent at once.
Thx
static int
send_commands(modem_t *modem, unsigned timeout, const char *commands[])
{
// determine size of commands pointer array
unsigned len = ???;
// Send commands through serial line
if (uart_tx(modem->port, ???, &len, timeout))
return TIMEOUT;
}
/**
* Sends count bytes.
* #param port The serial port.
* #param buf[in] Pointer to the buffer containing the bytes to be sent.
* #param count[in,out] Pointer to the value containing the number of bytes to send
* (in) and the number of bytes actually sent (out).
* #param time_to_wait The maximum amount of time the task should block waiting
* for count bytes to be sent should the transmit queue be full at some time.
* #return 0 on successful transmission, 1 on timeout
*/
unsigned uart_tx(SerialPort port, const void *buf, unsigned *count, unsigned time_to_wait)
It seems like you want to just concatenate (memcpy or strcat or whatever) all the commands into a single buffer before sending them out.

libnl 'invalid argument (-22) while trying using nl80211

I tried to extend the 'iw' utility to allow it to set the maximum and minimum size of the 802.11 contention window. But I'm always getting a 'invalid argument (-22)' returned.
I edited phy.c of the iw-3.15 source and appended
static int handle_txq(struct nl80211_state *state,
struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv,
enum id_input id)
{
unsigned int cw_min, cw_max;
printf("HANDLE TXQ");
if (argc != 2)
return 1;
cw_min = atoi(argv[0]);
cw_max = atoi(argv[1]);
printf("setting contention window to: %d - %d\n",cw_min,cw_max);
//create nested txq array
struct nlattr *nested;
nested = nla_nest_start(msg,NL80211_ATTR_WIPHY_TXQ_PARAMS);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMIN,cw_min);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMAX,cw_max);
nla_nest_end(msg,nested);
return 0;
nla_put_failure:
return -ENOBUFS;
}
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
I couldn't find any good documentation of nl80211 or it's usage through netlink except the header file itself. I am not
sure if I contruct the nested message according to specification and using U16 for the attributes are an educated guess (they are uint_16 in the matching cfg80211).
From my understanding of netlink my message assembly should be correct, but since I get an error I'm probably wrong...
Does anyone have a good documentation for nl80211 and its usage? Can anyone spot my problem?
From the kernel code on the other end of the netlink socket (in linux/net/wireless/nl80211.c - I am using 3.13.0-30), it seems there are a few reasons you can get an "invalid argument" (-EINVAL) response.
Firstly, you need to give it a valid interface and the device needs to be in AP or P2P_GO mode. You also need to provide all the TXQ params, not just contention window values. See the nl80211_set_wiphy() and parse_txq_params() functions in nl80211.c if you want to see exactly how your message is being handled.
You do appear to be using the correct types for the parameters though: NL80211_TXQ_ATTR_QUEUE/NL80211_TXQ_ATTR_AC (depending on version) and NL80211_TXQ_ATTR_AIFS are u8, and the other three (NL80211_TXQ_ATTR_TXOP, NL80211_TXQ_ATTR_CWMIN and NL80211_TXQ_ATTR_CWMAX) are u16.

Resources