fgets segmentation fault reading from stdin - dynamic-memory-allocation

I'm currently trying to read a line from stdin using fgets() but i'm getting a segmentation fault (i'm not geting the segmentation fault anymore, please see edit)
int main(void)
{
char selection;
string firstName = NULL;
printf("[A]dd a new client \n");
printf("[D]isplay all clients \n");
printf("[I]ncome Average for all clients \n");
printf("[Q]uit \n");
selection = fgetc(stdin);
printf("\n");
switch (selection) {
case 'A':
printf("First name: ");
fgets(firstName, MAXNAMESIZE, stdin);
printf("\n");
...
}
}
This is the compiler's output:
[A]dd a new client
[D]isplay all clients
[I]ncome Average for all clients
[Q]uit
A
First name: Segmentation fault
Thank you!!
Edit:
i've changed the code like this:
int main(void)
{
char selection;
string firstName;
printf("[A]dd a new client \n");
printf("[D]isplay all clients \n");
printf("[I]ncome Average for all clients \n");
printf("[Q]uit \n");
selection = fgetc(stdin);
printf("\n");
switch (selection) {
case 'A':
if ((firstName = malloc(MAXNAMESIZE * sizeof(char))) == NULL)
return 1;
printf("First name: ");
fgets(firstName, MAXNAMESIZE, stdin);
printf("\n");
...
}
}
But now i'm not able to enter any name, the program just ends. This is the output:
~/workspace/ $ ./test
[A]dd a new client
[D]isplay all clients
[I]ncome Average for all clients
[Q]uit
A
First name:
~/workspace/ $

You need to malloc firstName before you can use it, hence make sure to #include <stdlib.h>.
Try string firstName = malloc(MAXNAMESIZE * sizeof(char));
Always check that the result of malloc is not NULL.
Moreover, at the end of your program or when you think it's more useful free(firstName) to prevent memory leaks.

Related

v4l2src simple pipeline to c-application

My pipeline is like this
gst-launch-1.0 v4l2src ! videoconvert ! xvimagesink
and my code is like this
#include <gst/gst.h>
// easier to pass them as callbacks
typedef struct _CustomData{
GstElement *pipeline;
GstElement *source;
GstElement *convert;
GstElement *sink;
}CustomData;
// callback function
// here src is the v4l2src, newpad is gstpad that has just been added to src element. This is usually the pad to which we want to lnk
// data is the pointer we provided when attaching to the signal.
static void pad_added_handler(GstElement *src, GstPad *new_pad,CustomData *data)
{
GstPad *sink_pad = gst_element_get_static_pad(data->convert, "sink");
GstPadLinkReturn ret;
GstCaps *new_pad_caps = NULL;
GstStructure *new_pad_struct = NULL;
const gchar *new_pad_type = NULL;
if(gst_pad_is_linked(sink_pad))
{
g_print("we are linked. igonring\n");
}
// check the new pad types
// we have previously created a piece of pipeline which deals with videoconvert linked with xvimagesink and we will nto be able to link it to a pad producing video.
//gst-pad_get_current_caps()- retrieves current capabilities of pad
new_pad_caps = gst_pad_get_current_caps(new_pad);
new_pad_struct = gst_caps_get_structure(new_pad_caps, 0);
new_pad_type = gst_structure_get_name(new_pad_struct);
if(!g_str_has_prefix(new_pad_type, "video/x-raw"))
{
g_print("It has new pad type");
}
// gst_pad_link tries to link two pads . the link must be specified from source to sink and both pads must be owned by elements residing in same pipeline
ret = gst_pad_link(new_pad, sink_pad);
if(GST_PAD_LINK_FAILED(ret))
{
g_print("type is new_pad_type");
}
if(new_pad_caps !=NULL)
{
gst_caps_unref(new_pad_caps);
}
gst_object_unref(sink_pad);
}
int main(int argc, char *argv[])
{
GMainLoop *loop;
CustomData data;
GstBus *bus;
GstMessage *msg;
gboolean terminate = FALSE;
gst_init(&argc, &argv);
// loop = g_main_loop_new(NULL, FALSE);
// create the elements
data.source = gst_element_factory_make("v4l2src", "source");
data.convert = gst_element_factory_make("videoconvert", "convert");
data.sink = gst_element_factory_make("xvimagesink", "sink");
data.pipeline = gst_pipeline_new("new-pipeline");
if(!data.pipeline || !data.source || !data.convert || !data.sink)
{
g_printerr("Not all elements could be created\n");
return -1;
}
//we did not link source at this point of time, we will do it later
gst_bin_add_many(GST_BIN(data.pipeline), data.source, data.convert, data.sink, NULL);
// we link convert element to sink, do not link them with source. we dont have source pads here. so we just have videoconvert->sink unlinked
// gst_element_link(data.source, data.convert);
if(!gst_element_link(data.convert,data.sink))
{
g_printerr("elements could not be linked\n");
gst_object_unref(data.pipeline);
return -1;
}
// we set the device source
//g_object_set(source, "device", "/dev/video0", NULL);
//connect to pad added signal.
// we want to attach pad added signal to source element. to do so, we are using g_signal_connect and provide callback function and datapointer.
// when source element has enough information to start producing data, it will create source pads and trigger the pad added signal. at this point, our callback is called
g_signal_connect(G_OBJECT(data.source), "pad-added", G_CALLBACK(pad_added_handler), &data );
//g_signal_connect(G_OBJECT(data.source), "pad-added", G_CALLBACK(handler), &data);
GstStateChangeReturn ret;
ret =gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (data.pipeline);
return -1;
}
// g_main_loop_run(loop);
/* Listen to the bus */
bus = gst_element_get_bus (data.pipeline);
do {
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL) {
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
terminate = TRUE;
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
terminate = TRUE;
break;
case GST_MESSAGE_STATE_CHANGED:
/* We are only interested in state-changed messages from the pipeline */
if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
GstState old_state, new_state, pending_state;
gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
g_print ("Pipeline state changed from %s to %s:\n",
gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
}
break;
default:
/* We should not reach here */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
} while (!terminate);
/* Free resources */
gst_object_unref (bus);
gst_element_set_state(data.pipeline, GST_STATE_NULL);
gst_object_unref(data.pipeline);
return 0;
}
and I am getting error like this
Pipeline state changed from NULL to READY:
Pipeline state changed from READY to PAUSED:
Error received from element source: Internal data stream error.
Debugging information: gstbasesrc.c(3055): gst_base_src_loop (): /GstPipeline:new-pipeline/GstV4l2Src:source:
streaming stopped, reason not-linked (-1)
Please let me know what changes should I make to make my pipeline work. Thanks! the above code is based on dynamic pipeline example from gstreamer tutorials. I dont understand where I am going wrong.
The following works though
#include <gst/gst.h>
int main(int argc, char *argv[])
{
GstElement *pipeline, *source,*filter, *convert, *sink;
GstBus *bus;
GstMessage *msg;
GstCaps *caps;
gst_init(&argc, &argv);
source = gst_element_factory_make("v4l2src", "source");
filter = gst_element_factory_make("capsfilter","filter");
convert = gst_element_factory_make("videoconvert", "convert");
sink = gst_element_factory_make("xvimagesink", "sink");\
pipeline = gst_pipeline_new("pipe");
gst_bin_add_many(GST_BIN(pipeline), source, convert,sink, NULL);
gst_element_link_many(source,convert,sink,NULL);
caps = gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "YUY2", NULL);
g_object_set(G_OBJECT(filter), "caps", caps, NULL);
gst_element_set_state(pipeline,GST_STATE_PLAYING);
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL) {
GError *err;
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &err, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), err->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&err);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
break;
default:
/* We should not reach here because we only asked for ERRORs and EOS */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
/* Free resources */
gst_object_unref(bus);
gst_element_set_state(pipeline,GST_STATE_NULL);
gst_object_unref(pipeline);
}
Any ideas why if I add pads, it is not working well??

The base64 encode formatted output from Arduino HMAC-SHA1 does not match with JAVA/python/online tool

I am working on an Arduino project which is required an authorized authentication based on OAuth 1.0 to connects to the cloud. This is alike [Authorizing a request to Twitter API][1], and I am stuck in the step of [Creating a signature][2]. The whole process of creating a signature requires algorithms like encodeURL, base64encode, and hmac-sha1. On my Arduino project, I use Cryptosuite(link 3) library for hmac-sha1 and arduino-base64(link 4) library for base64encode. Both of them are working fine separately. However, I need to get a base64-formatted output of hmac-sha1. So I have tried this:
#include <avr/pgmspace.h>
#include <sha1.h>
#include <Base64.h>
uint8_t *in, out, i;
char b64[29];
static const char PROGMEM b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char key[] = "testKey";
char basestring[] = "testing";
void printHash(uint8_t* hash) {
int i;
for (i=0; i<20; i++) {
Serial.print("0123456789abcdef"[hash[i]>>4]);
Serial.print("0123456789abcdef"[hash[i]&0xf]);
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.print("Result:");
Sha1.initHmac((uint8_t*)key, strlen(key));
Sha1.print(basestring);
printHash(Sha1.resultHmac());
Serial.println();
// encoding
char* input;
input = (char*)(Sha1.resultHmac());
int inputLen = strlen(input);
int encodedLen = base64_enc_len(inputLen);
char encoded[encodedLen];
// note input is consumed in this step: it will be empty afterwards
base64_encode(encoded, input, inputLen);
Serial.print("base64 result: ");
Serial.println(encoded);
}
void loop() {
}
The output of printHash that I got is 60d41271d43b875b791e2d54c34bf3f018a29763, which is exactly same with the online verification tool(link 5).
However, I supposed to get YNQScdQ7h1t5Hi1Uw0vz8Biil2M= for the base64 result. But I got L18B0HicKRhuxmB6SIFpZP+DpHxU which seems wrong. I have also tried to write a JAVA program and a python program, which also said that the output of the base64 result should be YNQScdQ7h1t5Hi1Uw0vz8Biil2M=
I also found this post: Issues talking between Arduino SHA1-HMAC and base64 encoding and Python(link 6). I have also tried the tidy function it mentioned from Adafruit-Tweet-Receipt(link 7).
// base64-encode SHA-1 hash output. This is NOT a general-purpose base64
// encoder! It's stripped down for the fixed-length hash -- always 20
// bytes input, always 27 chars output + '='.
for(in = Sha1.resultHmac(), out=0; ; in += 3) { // octets to sextets
b64[out++] = in[0] >> 2;
b64[out++] = ((in[0] & 0x03) << 4) | (in[1] >> 4);
if(out >= 26) break;
b64[out++] = ((in[1] & 0x0f) << 2) | (in[2] >> 6);
b64[out++] = in[2] & 0x3f;
}
b64[out] = (in[1] & 0x0f) << 2;
// Remap sextets to base64 ASCII chars
for(i=0; i<=out; i++) b64[i] = pgm_read_byte(&b64chars[b64[i]]);
b64[i++] = '=';
b64[i++] = 0;
Is there any mistake I've made in here?
Thanks!
So full example will be:
#include <avr/pgmspace.h>
#include <sha1.h>
#include <Base64.h>
char key[] = "testKey";
char basestring[] = "testing";
void printHash(uint8_t* hash) {
for (int i=0; i<20; i++) {
Serial.print("0123456789abcdef"[hash[i]>>4]);
Serial.print("0123456789abcdef"[hash[i]&0xf]);
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.print("Input: ");
Serial.println(basestring);
Serial.print("Key: ");
Serial.println(key);
Serial.print("Hmac-sha1 (hex): ");
Sha1.initHmac((uint8_t*)key, strlen(key));
Sha1.print(basestring);
uint8_t *hash;
hash = Sha1.resultHmac();
printHash(hash);
// base64 encoding
char* input = (char*) hash;
int inputLen = strlen(input) - 1; // skip null termination
int encodedLen = base64_enc_len(inputLen);
char encoded[encodedLen];
// note input is consumed in this step: it will be empty afterwards
base64_encode(encoded, input, inputLen);
Serial.print("Hmac-sha1 (base64): ");
Serial.println(encoded);
}
void loop() { }
which outputs:
Input: testing
Key: testKey
Hmac-sha1 (hex): 60d41271d43b875b791e2d54c34bf3f018a29763
Hmac-sha1 (base64): YNQScdQ7h1t5Hi1Uw0vz8Biil2M=

Using fgets and strtok to read in data and create linked list

Need some help with reading in lines of data from a text file using the fgets and string tokenization commands, which will then be used to create a linked list. I've followed some examples I've found on Stack Overflow and other tutorial websites, but still cannot get the read function below to work properly in my program, it just causes it to crash. The data file has lines like this:
Zucchini, Squash, pound, 2.19, 45
Yellow, Squash, pound, 1.79, 15
Based on everything I've read, I believe I have the necessary code, but obviously I'm missing something. Also, I commented out one of the fields (the one for float price) as I'm not sure what to use to copy the float value from the data, as I cannot treat it as a string (the integer value right below it seems to let me get away with it in my compiler).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struct for linked list node
struct produceItem
{
char produce[20];
char type[20];
char soldBy[20];
float price;
int quantityInStock;
struct produceItem *next;
};
// Function to read in data from file to
void read(struct produceItem **head)
{
struct produceItem *temp = NULL;
struct produceItem *right = NULL;
//char ch[3];
char line[50];
char *value;
FILE *data = fopen("RecitationFiveInput.txt", "r");
printf("Trying to open file RecitationFiveInput.txt\n");
if (data == NULL)
{
printf("Could not open file RecitationFiveInput.txt\n");
}
else
{
while(fgets(line, sizeof(line), data))
{
value = strtok(line, ", ");
strcpy(temp->produce, strdup(value));
value = strtok(NULL, ", ");
strcpy(temp->type, strdup(value));
value = strtok(NULL, ", ");
strcpy(temp->soldBy, strdup(value));
//value = strtok(NULL, ", ");
//strcpy(temp->price, strdup(value));
value = strtok(NULL, " \n");
strcpy(temp->quantityInStock, strdup(value));
temp->next = NULL;
if (*head == NULL)
{
*head = temp;
}
else
{
right = *head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
}
}
printf("Successfully opened file RecitationFiveInput.txt\n");
}
fclose(data);
return;
}
// Function to display the nodes of the linked list that contains the data from the data file
void display(struct produceItem *head)
{
int value = 1;
struct produceItem *temp = NULL;
temp = head;
printf("=============================================================================\n");
printf(" Item # Produce Type Sold By Price In Stock\n");
printf("=============================================================================\n");
if(temp == NULL)
{
return;
}
else
{
while(temp != NULL)
{
printf(" %d %s %s %s %lf %d\n", value, temp->produce, temp->type, temp->soldBy, temp->price, temp->quantityInStock);
value++;
temp = temp->next;
if(temp == NULL)
{
break;
}
}
}
return;
}
//Main function
int main()
{
int input = 0;
struct produceItem *head = NULL;
while(1)
{
printf("\nList Operations\n");
printf("=================\n");
printf("1. Stock Produce Department\n");
printf("2. Display Produce Inventory\n");
printf("3. Reverse Order of Produce Inventory\n");
printf("4. Export Produce Inventory\n");
printf("5. Exit Program\n");
printf("Enter your choice: ");
if(scanf("%d", &input) <= 0)
{
printf("Enter only an integer.\n");
exit(0);
}
else
{
switch(input)
{
case 1:
read(&head);
break;
case 2:
display(head);
break;
case 3:
//function
break;
case 4:
//function
break;
case 5:
printf("You have exited the program, Goodbye!\n");
return 0;
break;
default:
printf("Invalid option.\n");
}
}
}
return 0;
}
Never mind everyone, found the issue. The crashes were due to me not allocating memory for the temp pointer in the read me function.

Print the "showname" field attribute in tshark

Context
I've got a pcap file containing a bunch of beacon frames (in other words, I put my Wi-Fi adapter in monitor mode, started capturing while filtering on "wlan.fc.type_subtype == 0x08", and saved that).
Now, I want to, somehow, display specific fields of these packets. Among others:
SSID (wlan_mgt.ssid)
MAC (wlan.ta)
Current channel (wlan_mgt.ds.current_channel)
Group Cipher (wlan_mgt.rsn.gcs.type)
PairWise Ciphers (wlan_mgt.rsn.pcs.type)
Authentication Suite (wlan_mgt.rsn.akms.type)
I don't really care about the representation: plain text, xml, json, csv, X. I'm fine with it. I just don't want more data than I really need and the output needs to be meaningful to the human (wireshark newb) eye.
Eventually, I also want to filter the pcap to get a unique set and count the occurrences (some "|sort|uniq -c" will do), but let's not go there for now.
My solution so far
The first step could be, for example:
$ tshark -r capture.pcap -c 1 -T fields -e wlan_mgt.ssid -e wlan.ta -e wlan_mgt.ds.current_channel -e wlan_mgt.rsn.gcs.type -e wlan_mgt.rsn.pcs.type -e wlan_mgt.rsn.akms.type
MySSID XX:XX:XX:XX:XX:XX 2 4 4 2
After (manually) matching the numbers to their textual meaning, you get this:
SSID = MySSID
MAC (wlan.ta) = XX:XX:XX:XX:XX:XX
Current channel = 2
Group Cipher = Group Cipher Suite type: AES (CCM) (4)
PairWise Ciphers = Pairwise Cipher Suite type: AES (CCM) (4)
Authentication Suite = Auth Key Management (AKM) type: PSK (2)
This is what I'm looking for. But, as stated, I have to do it manually, which is not an option.
Question
Above you can see my current approach to the said goal. By doing
tshark -r capture.pcap -c 1 -T pdml
I get, for example (cutout):
<field name="wlan_mgt.rsn.pcs.list" showname="Pairwise Cipher Suite List 00-0f-ac (Ieee8021) AES (CCM)" size="4" pos="112" show="" value="">
<field name="wlan_mgt.rsn.pcs" showname="Pairwise Cipher Suite: 00-0f-ac (Ieee8021) AES (CCM)" size="4" pos="112" show="1027076" value="000fac04">
<field name="wlan_mgt.rsn.pcs.oui" showname="Pairwise Cipher Suite OUI: 00-0f-ac (Ieee8021)" size="3" pos="112" show="4012" value="000fac"/>
<field name="wlan_mgt.rsn.pcs.type" showname="Pairwise Cipher Suite type: AES (CCM) (4)" size="1" pos="115" show="4" value="04"/>
</field>
</field>
..., which tells me that tshark does have the information I need (in the form of the "showname" attribute).
Apparently, when working with "-T fields -e X", tshark outputs the value that's in the "show" attribute". I feel like I want what's behind the "showname" attribute. Unfortunately, after annoying google for a while I still don't know how or if this is even possible.
I'm also open to radically different ideas, but the main takeaway is that I can't part from the pcap file (which rules out iwlist, kismet, etc). I also preferably don't start writing search and replace rules to replace the meaningless numbers with their textual representation. I hope to solve it in cleaner way.
I kept messing with tshark for a while, until I decided that it couldn't be done. A little bit of programming using the amazing C++ library libtins got me where I needed to be.
The source is down below. Enjoy :)
#include <tins/tins.h>
#include <algorithm>
#include <iostream>
#include <map>
#include <string>
using namespace Tins;
using namespace std;
/*
* Container class for the data that is retrieved from the beacon.
*/
class Unit {
public:
/*
* Constructor. Parses the Dot11Beacon object and takes all the necessary
* data from it.
*/
Unit(Dot11Beacon& beacon);
Unit() = default;
unsigned getCount();
void incrementCount();
/*
* Prints this object onto the command line, in CSV format
*/
void print();
private:
string ssid;
string bssid;
unsigned channel;
unsigned count;
string gcs; // Group Cipher Suite
string pcs; // Pairwise Cipher Suite
string akm; // Authentication suite
/*
* Returns a string representation of a RSNInformation::CypherSuites enum value
*/
string type_to_string(const RSNInformation::CypherSuites& type);
/*
* Returns a string representation of a RSNInformation::AKMSuites enum value
*/
string type_to_string(const RSNInformation::AKMSuites& type);
};
Unit::Unit(Dot11Beacon& beacon) :
count {1} /* When this unit is created, it has been seen exactly once */ {
ssid = beacon.ssid();
bssid = beacon.addr3().to_string();
channel = unsigned(beacon.ds_parameter_set());
RSNInformation rsn;
for(const auto &opt : beacon.options()) {
if (opt.option() == Dot11::RSN) {
rsn = beacon.rsn_information();
// Put all authentication suite types in a string
const RSNInformation::akm_type& akmTypeList = rsn.akm_cyphers();
for (const auto& akmIt : akmTypeList) {
if (akm.size() == 0)
akm += type_to_string(akmIt);
else
akm += ";" + type_to_string(akmIt);
}
// Put all group cipher types in a string
const RSNInformation::CypherSuites& gcsType = rsn.group_suite();
gcs = type_to_string(gcsType);
// Put all pairwise ciphers in a string
const RSNInformation::cyphers_type& pcsTypeList = rsn.pairwise_cyphers();
for (const auto& pcsIt : pcsTypeList) {
if (pcs.size() == 0)
pcs += type_to_string(pcsIt);
else
pcs += ";" + type_to_string(pcsIt);
}
}
}
}
unsigned Unit::getCount() {
return count;
}
void Unit::incrementCount() {
count += 1;
}
void Unit::print() {
string ssid_to_print;
if (ssid.length() == 0) {
ssid_to_print = "<ZERO_LENGTH>";
} else if (!isprint(ssid[0])) {
ssid_to_print = to_string(static_cast<int>(ssid[0]));
} else {
ssid_to_print = ssid;
}
if (find(ssid_to_print.begin(), ssid_to_print.end(), ',') != ssid_to_print.end()) {
ssid_to_print = "\"" + ssid_to_print + "\"";
}
cout << ssid_to_print << ","
<< bssid << ","
<< to_string(channel) << ","
<< to_string(count) << ","
<< gcs << ","
<< pcs << ","
<< akm << endl;
}
string Unit::type_to_string(const RSNInformation::CypherSuites& type) {
switch (type) {
case RSNInformation::CypherSuites::CCMP:
return "CCMP";
break;
case RSNInformation::CypherSuites::TKIP:
return "TKIP";
break;
case RSNInformation::CypherSuites::WEP_104:
return "WEP_104";
break;
case RSNInformation::CypherSuites::WEP_40:
return "WEP_40";
break;
}
}
string Unit::type_to_string(const RSNInformation::AKMSuites& type) {
switch (type) {
case RSNInformation::AKMSuites::PMKSA:
return "PMKSA";
break;
case RSNInformation::AKMSuites::PSK:
return "PSK";
break;
}
}
/*
* Class that reads the pcap, keeps track of the units and writes out one
* beacon frame in pcap format for each unique AP it finds. This file is called
* "unique_beacons.pcap"
*/
class PCAPParser {
public:
/*
* Constructor. It takes the exact parameters that it will pas on to its
* FileSniffer object (a FileSniffer is actually just a file reader).
*/
PCAPParser(const string& pcapFilename, const string& filter);
/*
* Start reading the file.
*/
bool run();
/*
* Print CSV header and ask all of our collected Unit objects to print themselves
*/
void print();
private:
FileSniffer sniffer;
PacketWriter writer;
map<string, Unit> apMap; // stands for Access Point Map
bool handler(PDU&);
};
PCAPParser::PCAPParser(const string& pcapFilename, const string& filter) :
sniffer {pcapFilename, filter},
writer {"unique_beacons.pcap", PacketWriter::RADIOTAP} {
for (auto it = apMap.begin(); it != apMap.end(); it++) {
it->second.print();
}
}
bool PCAPParser::run() {
sniffer.sniff_loop( [this] (PDU& pdu) { return (bool) this->handler (pdu); } );
return true;
}
bool PCAPParser::handler(PDU& pdu) {
Dot11Beacon& beacon = pdu.rfind_pdu<Dot11Beacon>();
// An ESSID may span multiple BSSID's. Also, it's nice to keep track of what
// channels an AP has been on. Therefore, the combination of SSID, BSSID and
// channel is considered key.
const string& ssid = beacon.ssid();
const string& mac = beacon.addr3().to_string();
const unsigned channel = unsigned(beacon.ds_parameter_set());
const string key = ssid + mac + to_string(channel);
if (apMap.find(key) == apMap.end()) { // we've got a new one
Unit unit(beacon);
apMap[key] = unit;
writer.write(pdu);
} else {
apMap[key].incrementCount();
}
return true;
}
void PCAPParser::print() {
// Print the headers for the CSV output
cout << "SSID,BSSID,Current_channel,Count,Group_Cipher,Pairwise_Ciphers,Authentication_Suite" << endl;
// Ask each of the units to print themselves for the CSV output
for (auto it = apMap.begin(); it != apMap.end(); it++) {
it->second.print();
}
}
int main(int argc, char *argv[]) {
if(argc != 2) {
std::cout << "Usage: " << *argv << " <PCAP_FILE>\n";
return 1;
}
PCAPParser pcapParser(argv[1], "wlan type mgt subtype beacon");
pcapParser.run();
pcapParser.print();
}
Compile with:
g++ pcapreader.cpp -o pcapreader -O3 -std=c++11 -lpthread -ltins
The output is:
$ ./pcapreader capture.pcap
SSID,BSSID,Current_channel,Count,Group_Cipher, Pairwise_Ciphers,Authentication_Suite
MyWiFi,XX:XX:XX:XX:XX:XX,13,2,TKIP,TKIP;CCMP,PSK
...
...
Final note: if you open unique_beacons.pcap, you may find a lot of [Malformed Packet]. Apparently, a frame can still be successfully parsed if some of the tagged parameters are received wrongly. You could try to modify the code so that it only writes out frames to the pcap file that are completely intact.
tshark will print the "showname" attribute for text output only. You can control the output with a custom formatted by setting the gui.column.format preference. To print just SSID columns:
$ tshark -r capture.pcap -c 1 -T text -o 'gui.column.format:"SSID","%Cus:wlan.ssid"'

pointers and linked list with shared memory

I want to get 2 programs to communicate, one (server) would store datas, and the other (client) would just access it.
I'll have to use a linked list to store datas because it won't stop storing, and then I was wondering if I could access to the whole linked list if only the first node is shared in memory.
What I mean is… are we allowed to access from the client program to the memory pointed by a shared pointer?
Sorry it seems obvious that we can not, so should I store my linked list into the shared memory, or do you think that would be awkward?
Because if I do so, I'll have to declare a shared memory for every node right?
So, to add shared memory to both programs I need the same keys, but I don't know how many keys there will be, and I can't just store it for both programs, unless I would have had already a linked list…
so I used a very very VERY awkward method that I don't even know if it works right, but I wish you can tell, which is to use ftok that is supposed to take an (url,pid) and return a key. So I assumed it would send the exact same key if I used the same url and pid, using a fake pid starting from 0 that I would increment for every element I add to the linked list… what do you think about it? Any other way to do it which would seem less… crap?
typedef struct s_shared_elem
{
char c;
struct s_shared_elem* next;
struct s_shared_elem* previous;
}shared_elem;
typedef struct s_shared_list
{
s_shared_elem* first;
s_shared_elem* last;
}shared_list;
int forthekey = 0;
char* url="/home/toor/Projet_cgi/";
shared_elem* shared_malloc(int pid, const char* url)
{
shared_elem* shm;
int shmid;
int key=ftok(url,pid);
if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
if ((shm = shmat(shmid,NULL,0)) == (shared_elem*)-1)
{
perror("shmat");
exit(1);
}
return shm;
}
void Init_shared_list(shared_list* liste)
{
liste->first = NULL;
liste->last = NULL;
}
void Add_elem(shared_list* liste)
{
shared_elem* new = shared_malloc(pid,url);
new->next = NULL;
new->previous = liste->last;
if(liste->first == NULL)
{
liste->first = new;
liste->last = new;
}
else
{
liste->last->next = new;
liste->last = new;
}
forthekey++;
}
void shared_free(shared_elem* todelete,int pid, const char* url)
{
shared_elem* shm;
int shmid;
int key=ftok(url,pid);
if((shmid=shmget(key,1,IPC_CREAT | 0666)) < 0)
{
perror("shmget");
exit(1);
}
shmdt(todelete);
shmctl(shmid,IPC_RMID,NULL);
forthekey--;
}
void Delete_list(shared_list* liste)
{
while(liste->last != liste->first)
{
shared_elem* tmp=liste->last;
liste->last=liste->last->previous;
Shared_free(tmp,pid,url);
}
Shared_free(liste->first,pid,url);
}
In share memory you can insert a whole linked list. It is useful in many cases. You do not need to create a linked list of share memory (e.g. using previous key, next key ). All you need to copy each node of linked list to the shared memory.
for example .....
process2.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main(int argc, char *argv[])
{
int shmid,i;
node *data;
if ((shmid = shmget(10, SHM_SIZE, 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
data = (node *)shmat(shmid, (void *)0, 0); // node is linked list
for(i=0;i<2;i++)
printf("%d\n",(data++)->item_code);
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
return 0;
}
process1.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
int main(int argc, char *argv[])
{
node *SELL=NULL; // node is linked list (structure) SELL is header
insert(&SELL,"Soap",1,12.5,10);
insert(&SELL,"Pen",2,20.75,8);
display(SELL);
int shmid,i;
node *data;
if ((shmid = shmget(10, 2*sizeof(node), 0644 | IPC_CREAT)) == -1) {
perror("shmget");
exit(1);
}
data = (node *) shmat(shmid, (void *)0, 0);
for(i=0;i<2;i++)
{
*(data++)=*SELL;
SELL=SELL->next;
}
getchar();
if (shmdt(data) == -1) {
perror("shmdt");
exit(1);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
Run process1.c 1st then run process2.c

Resources