is it possible to create an snmpbulkwalk in C with netsnmp?
A snmpget is quite easy - but I cannot find an example to send an snmpbulkwalk...
Here is a little example for an snmpget:
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
int snmp_get(struct snmp_session *sess_handle){
struct snmp_pdu *pdu;
struct snmp_pdu *response;
struct variable_list *vars;
oid id_oid[MAX_OID_LEN];
oid serial_oid[MAX_OID_LEN];
size_t id_len = MAX_OID_LEN;
size_t serial_len = MAX_OID_LEN;
int status;
pdu = snmp_pdu_create(SNMP_MSG_GET);
read_objid("SNMPv2-MIB::sysName.0", id_oid, &id_len);
snmp_add_null_var(pdu, id_oid, id_len);
read_objid(".1.3.6.1.2.1.1.3.0", serial_oid, &serial_len);
snmp_add_null_var(pdu, serial_oid, serial_len);
status = snmp_synch_response(sess_handle, pdu, &response);
for(vars = response->variables; vars; vars = vars->next_variable)
print_value(vars->name, vars->name_length, vars);
snmp_free_pdu(response);
return status;
}
struct snmp_session *setup_snmp_session(int version, char* community, char* host){
struct snmp_session session;
struct snmp_session *sess_handle;
init_snmp("poller");
snmp_sess_init( &session );
session.version = version;
session.community = community;
session.community_len = strlen(session.community);
session.peername = host;
sess_handle = snmp_open(&session);
return sess_handle;
}
int main(int argc, char ** argv)
{
if(argv[1] == NULL){
printf("Please supply a hostname\n");
exit(1);
}
struct snmp_session *sess_handle=setup_snmp_session(SNMP_VERSION_2c,"asdf",argv[1]);
snmp_get(sess_handle);
snmp_close(sess_handle);
return (0);
}
I am looking for something equal - just doing an snmpbulkwalk!
Thx for your help!
br,
roegi
Are you aware that there is already a snmpbulkwalk command line implementation within Net-SNMP that would be a good example to look at? It does what you want already. If you want a single instance of a GETBULK, then you could look at the simpler snmpbulkget example instead.
Related
I am working on a project where I have to use multi-threading to generate multiple pwms. I am working on raspberry and I use WiringPI to generate softPWMs.
The problems is my raspberry does not want to generate 5 PWMs. Each time a run the code, the PWMs are generated randomly on 3 of the five pins I have setted. I do not know if it is the OS putting some threads on sleep or not.
I have no idea where the problem might be from. In fact, I tries using the same code to send periodically send many variable and it did work. But when I try using the same code with PWM it does not work. The code I am using is right below. If any of you has any idea please help
#include <wiringPi.h>
#include <stdio.h>
#include <softPwm.h>
#include <stdlib.h>
#include <pthread.h>
#define THREAD_NUM 1
struct thArg{
int PWM_pin1;
int rapportCyclique1;
int PWM_pin2;
int rapportCyclique2;
int PWM_pin3;
int rapportCyclique3;
int PWM_pin4;
int rapportCyclique4;
};
struct thArg data = {
22,20,
23,40,
24,80,
25,60
};
void* routine(void* args){
//int PWM_pin = *(int*)args->PWM_pin;
//int intensity = *(int*)args->rapportCyclique;
//pthread_mutex_lock(&mutexBuffer);
struct thArg *arrgs = (struct thArg *) args;
int PWM_pin1 = arrgs->PWM_pin1;
int rapportCyclique1 = arrgs->rapportCyclique1;
int PWM_pin2 = arrgs->PWM_pin2;
int rapportCyclique2 = arrgs->rapportCyclique2;
int PWM_pin3 = arrgs->PWM_pin3;
int rapportCyclique3 = arrgs->rapportCyclique3;
int PWM_pin4 = arrgs->PWM_pin4;
int rapportCyclique4 = arrgs->rapportCyclique4;
pinMode(PWM_pin1, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin2, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin3, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
pinMode(PWM_pin4, OUTPUT);
softPwmCreate(PWM_pin1, 1, 100);
softPwmWrite(PWM_pin1, rapportCyclique1);
softPwmWrite(PWM_pin2, rapportCyclique2);
softPwmWrite(PWM_pin3, rapportCyclique3);
softPwmWrite(PWM_pin4, rapportCyclique4);
//pthread_mutex_unlock(&mutexBuffer);
}
void* routine(void*);
int main(int argc, char** argv)
{
wiringPiSetup();
pthread_t th[THREAD_NUM];
for(int i=0; i<THREAD_NUM; i++)
{
struct thArg *a = malloc(sizeof(struct thArg));
*a = data;
if(pthread_create(&th[i], NULL, &routine, a) != 0)
{
perror("failed to create thread\n");
exit( EXIT_FAILURE );
}
}
for(int i = 0; i<THREAD_NUM; i++){
if(pthread_join(th[i], NULL)!= 0)
{
perror("Failed to join thread\n");
exit( EXIT_FAILURE );
}
}
//pthread_mutex_destroy(&mutexBuffer);
return EXIT_SUCCESS;
}
Using UCI we can retrieve entire lists with the following command:
$ uci get system.ntp.server
This would read the kind of configuration below:
config system
option hostname 'OpenWrt'
option timezone 'UTC'
config timeserver 'ntp'
list server '0.openwrt.pool.ntp.org'
list server '1.openwrt.pool.ntp.org'
list server '2.openwrt.pool.ntp.org'
list server '3.openwrt.pool.ntp.org'
option enabled '1'
option enable_server '0'
That returns all the ntp servers in one long string fine.
0.openwrt.pool.ntp.org 1.openwrt.pool.ntp.org 2.openwrt.pool.ntp.org 3.openwrt.pool.ntp.org
I wish to achieve the same (or equivalent) using the C api.
I put together the following code:
#include <uci.h>
#include <string.h>
void main()
{
//char path[] = "system.ntp.enabled";
char path[] = "system.ntp.server";
char buffer[80];
get_config_entry(path, &buffer);
printf("%s\n", buffer);
}
int get_config_entry (char *path, char *buffer)
{
struct uci_context *c;
struct uci_ptr ptr;
c = uci_alloc_context ();
if (uci_lookup_ptr (c, &ptr, path, true) != UCI_OK)
{
uci_perror (c, "XXX");
return 1;
}
strcpy(buffer, ptr.o->v.string);
uci_free_context (c);
return 0;
}
Running this just returns garbage in the output string.
How should I deal with list content using UCI C API?
If a list element is requested it is stored in v.list not v.string.
I found the uci_show_value function in the uci cli code which helped a lot. I have managed to get the following code to work well with list options.
#include <uci.h>
#include <string.h>
static const char *delimiter = " ";
static void uci_show_value(struct uci_option *o)
{
struct uci_element *e;
bool sep = false;
switch(o->type) {
case UCI_TYPE_STRING:
printf("%s\n", o->v.string);
break;
case UCI_TYPE_LIST:
uci_foreach_element(&o->v.list, e) {
printf("%s%s", (sep ? delimiter : ""), e->name);
sep = true;
}
printf("\n");
break;
default:
printf("<unknown>\n");
break;
}
}
int show_config_entry (char *path)
{
struct uci_context *c;
struct uci_ptr ptr;
c = uci_alloc_context ();
if (uci_lookup_ptr (c, &ptr, path, true) != UCI_OK)
{
uci_perror (c, "get_config_entry Error");
return 1;
}
uci_show_value(ptr.o);
uci_free_context (c);
return 0;
}
void main()
{
char path[] = "system.ntp.server";
show_config_entry(path);
}
Using libfuse in my c-project, I 'm trying to add custom command-line arguments and handle them.
Here is an example on which I rely
https://github.com/libfuse/libfuse/wiki/Option-Parsing
First, I tried to do the argument for the mount point configuration -с <pathtoconfig>
I tried many ways to describe an option like -c --config conf= -o conf=, but ineffectually
Please, help me find the right path to solve the problem :(
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fuse.h>
#include "fuu_walk.h"
#include "jsmnload.h"
#define _JSMN_TOKEN_SIZE_ 256
#define _JSMN_BUFFER_SIZE_ 4096
#define MYFS_OPT(t, p, v) { t, offsetof(struct myfs_config, p), v }
struct myfs_config {
char *mystring;
} conf;
static struct fuse_opt myfs_opts[] = {
MYFS_OPT("-c %s", mystring, 1),
FUSE_OPT_END
};
jsmntok_t t[_JSMN_TOKEN_SIZE_];
char buf[_JSMN_BUFFER_SIZE_];
#if 0
= ""
"{\"root\": ["
"{\"path\":\"/\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ01\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ02\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE78\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE89\", \"mode\":\"drw-------\"}"
"]}";
#endif
static int myfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
struct myfs_config *ptr = (struct myfs_config *)data;
FILE *conf;
int rc = 0;
//I wanna check the argument on the each iteration of fuse_opt_parse. It's just the debug printf
printf("arg = %s\t string %s\t key = %i\n", arg, ptr->mystring, key);
switch (key) {
case 1:
conf = fopen(ptr->mystring, "r");
rc = read(fileno(conf), buf, _JSMN_BUFFER_SIZE_);
if ( jsmnload(buf, t, _JSMN_TOKEN_SIZE_, fuu_mkfstree) < 0 ) {
printf("Error load configuration\n");
exit(-1);
}
}
return 1;
}
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
memset(&conf, 0, sizeof(conf));
fuse_opt_parse(&args, &conf, myfs_opts, myfs_opt_proc);
return fuu_main(args.argc, args.argv);
}
Launch example
./appendix/fuu /mnt/cdrom/ -c /mnt/fs.json
As a result, printf in myfs_opt_proc function works only once and outputs
arg = /mnt/cdrom/ string (null) key = -2
Why myfs_opt_proc does not work for option -c?
I cannot comment so as an answer... looking at the reference you provided it seems to me that there is no option starting with -c. So result seems correct because fuse cannot parse this. Look at this snippet from your link:
fuse_opt_add_arg(&args, "-omodules=subdir,subdir=/foo");
You may try to announce options to fuse using -o.
Edit: Youre example differs from the linked one, try to add to following line to the defined struct:
FUSE_OPT_KEY("-c", "KEY_CONFIG");
and some line before
emum {
KEY_CONFIG
};
and parse it like this in youre myfs_opt_proc function
switch (key) {
case KEY_CONFIG:
/* ... */
. Summed up you missed declaring the -c key.
I have been playing around with scsi command and I can send some basic commands like different inquirys and such.
I have been using this example to to generate my inquiry. I am working on making this example work with different scsi commands.
http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/pexample.html
I have changed to function to accept different scsi commands through a struct and it also returns a struct based on the output. This works with an inquiry flawlessly. However if I send a READ CAPACITY(16) command the function triggers on the if statement:
(io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK)
I am new to scsi programming so I might be doing something totally wrong...
my READ CAPACITY(16) command is just this:
scsi_read_capacity.cmdblk[0]=0x9e;
scsi_read_capacity.cmdblk[13]=32;
the rest of the CDB are 0!
here is the code:
#include <stdio.h>
#include <sys/ioctl.h>
#include <scsi/sg.h>
/* global struct to store return data from a scsi cmd*/
typedef struct SCSI_data {
unsigned char data[1024];
unsigned char raw_sens[252];
unsigned char sense_key;
unsigned char additional_sense_code;
unsigned char additional_sense_qualifier;
unsigned char additional_sense_length;
unsigned char sense_data_descriptors[10][244];
int result;
} SCSI_data;
/* global struct to store return data from a scsi cmd*/
typedef struct SCSI_cmd {
int sg_fd;
unsigned char cmdblk[32];
int cmdblklength;
int allocation_length;
int xfer;
int timeout;
} SCSI_cmd;
SCSI_data send_scsicmd(SCSI_cmd cmdobject) {
int k;;
unsigned char inqBuff[cmdobject.allocation_length];
unsigned char sense_buffer[252];
SCSI_data output_data;
sg_io_hdr_t io_hdr;
/* Prepare INQUIRY command */
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
io_hdr.interface_id = 'S';
io_hdr.cmd_len = cmdobject.cmdblklength;
io_hdr.mx_sb_len = sizeof(sense_buffer);
io_hdr.dxfer_direction = cmdobject.xfer;
io_hdr.dxfer_len = cmdobject.allocation_length;
io_hdr.dxferp = inqBuff;
io_hdr.cmdp = cmdobject.cmdblk;
io_hdr.sbp = sense_buffer;
io_hdr.timeout = cmdobject.timeout;
if (ioctl(cmdobject.sg_fd, SG_IO, &io_hdr) < 0) {
output_data.result=2;
return output_data;
}
/* now for the error processing */
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
output_data.result=1;
if (io_hdr.sb_len_wr > 0) {
printf("INQUIRY sense data: ");
for (k = 0; k < io_hdr.sb_len_wr; ++k) {
if ((k > 0) && (0 == (k % 10)))
printf("\n ");
printf("0x%02x ", sense_buffer[k]);
}
printf("\n");
}
if (io_hdr.masked_status)
printf("INQUIRY SCSI status=0x%x\n", io_hdr.status);
if (io_hdr.host_status)
printf("INQUIRY host_status=0x%x\n", io_hdr.host_status);
if (io_hdr.driver_status)
printf("INQUIRY driver_status=0x%x\n", io_hdr.driver_status);
}
else { /* assume INQUIRY response is present */
output_data.result=0;
for (k=0;k<cmdobject.allocation_length;k++) {
output_data.data[k]=inqBuff[k];
}
}
return output_data;
}
int main(int argc, char * argv[]) {
FILE *driveptr=fopen(argv[1], "r");
int i;
SCSI_data scsi_data_read_capacity;
SCSI_cmd scsi_read_capacity;
scsi_read_capacity.sg_fd=fileno(driveptr);
scsi_read_capacity.cmdblk[0]=0x9e;
scsi_read_capacity.cmdblk[13]=32;
scsi_read_capacity.cmdblklength=16;
scsi_read_capacity.xfer=SG_DXFER_FROM_DEV;
scsi_read_capacity.allocation_length=32;
scsi_read_capacity.timeout=1000;
scsi_data_read_capacity=send_scsicmd(scsi_read_capacity);
if (scsi_data_read_capacity.result==0) {
printf(" capacity in blocks: %02x%02x%02x%02x%02x%02x%02x%02x\n",
scsi_data_read_capacity.data[0],
scsi_data_read_capacity.data[1],
scsi_data_read_capacity.data[2],
scsi_data_read_capacity.data[3],
scsi_data_read_capacity.data[4],
scsi_data_read_capacity.data[5],
scsi_data_read_capacity.data[6],
scsi_data_read_capacity.data[7]);
printf(" blocksize: %02x%02x%02x%02x\n",
scsi_data_read_capacity.data[8],
scsi_data_read_capacity.data[9],
scsi_data_read_capacity.data[10],
scsi_data_read_capacity.data[11]);
}
fclose(driveptr);
return 0;
}
I had just a small problem. My CDB was wrong!
I had to use this:
scsi_read_capacity.cmdblk[0]=0x9E;
scsi_read_capacity.cmdblk[1]=0x10;
scsi_read_capacity.cmdblk[13]=32;
the second byte had to be equal to 0x10, this is because the scsi cmd 0x9E is a service action command which accepts an argument in the second byte which defines its behavior!
How do I set the modification time of a file programmatically in Windows?
From: http://rosettacode.org/wiki/File/Modification_Time#C
#include <time.h>
#include <utime.h>
#include <sys/stat.h>
const char *filename = "input.txt";
int main() {
struct stat foo;
time_t mtime;
struct utimbuf new_times;
stat(filename, &foo);
mtime = foo.st_mtime; /* seconds since the epoch */
new_times.actime = foo.st_atime; /* keep atime unchanged */
new_times.modtime = time(NULL); /* set mtime to current time */
utime(filename, &new_times);
return 0;
}
Windows (or the standard CRT, anyhow) has the same utimes family of functions that UNIX has.
struct _utimebuf t;
t.tma = 1265140799; // party like it's 1999
t.tmm = 1265140799;
_utime(fn, &t);
Using Win32 functions, FILE_BASIC_INFO can be set using SetFileInformationByHandle.
FILE_BASIC_INFO b;
b.CreationTime.QuadPart = 1265140799;
b.LastAccessTime.QuadPart = 1265140799;
b.LastWriteTime.QuadPart = 1265140799;
b.ChangeTime.QuadPart = 1265140799;
b.FileAttributes = GetFileAttributes(fn);
SetFileInformationByHandle(h, FileBasicInfo, &b, sizeof(b));
Use SetFileInformationByHandle with FileInformationType as FILE_BASIC_INFO
I found this to be useful on windows SetFileTime()
See http://msdn.microsoft.com/en-us/library/aa365539%28VS.85%29.aspx
Here is the solution for Darwin.
All security removed.
#include <sys/stat.h>
#include <sys/time.h>
// params
char *path = "a path to a dir, a file or a symlink";
long int modDate = 1199149200;
bool followLink = false;
// body
struct stat currentTimes;
struct timeval newTimes[2];
stat(path, ¤tTimes);
newTimes[0].tv_sec = currentTimes.st_atimespec.tv_sec;
newTimes[0].tv_usec = (__darwin_suseconds_t)0;
newTimes[1].tv_sec = modDate;
newTimes[1].tv_usec = (__darwin_suseconds_t)0;
if (followLnk) {
utimes(path, (const struct timeval *)&newTimes);
} else {
lutimes(path, (const struct timeval *)&newTimes);
}