For the creation of the map, the user is left with the possibility of requesting the following four functions via a menu with one (switch):
Insertion of a zone at the end of the insert_zone function list. It creates the new zone in dynamic memory malloc, inserts it in the list by modifying the value of the next_zone pointer of the last land in the list with the result of the malloc. The type of the zone as well as the object found within the zone are randomly generated: all zones are equiprobable, no_object has a 40% probability while the other objects in the enum Object_type_zone have equal probability. Finally, the enum field Tipo_prova prova will be inserted with a certain probability every time a player arrives in a given zone see function advance .
Delete the last zone inserted in the path cancel_zone
Print the fields of all the zones created up to that moment print_map.
i leaves the possibility to the user to use a menu to perform the following four functions:
insert_zone: delete_zone: print_map;
.
I leave a copy of the file.h (works well); "you can help to find the solution for the problem"
#ifndef H_GAMELIB
#define H_GAMELIB
extern void imposta_gioco();
extern void gioca();
extern void termina_gioco();
extern void inserisci_zona();
extern void stampa_mappa();
extern void chiudi_mappa();
extern void cancella_zona();
enum Tipo_Difficolta { dilettante, intermedio, incubo };
enum Tipo_oggetto_iniziale { EMF, spirit_box, videocamera, calmanti, sale };
enum Tipo_oggetto_zona { adrenalina, cento_dollari, coltello, calmanti1, nessun_oggetto };
enum Tipo_zona { caravan, cucina, soggiorno, camera, bagno, garage, seminterrato };
enum Tipo_prova { prova_EMF, prova_spirit_box, prova_videocamera, nessuna_prova };
struct Zona_mappa {
enum Tipo_zona zona;
enum Tipo_prova prova;
enum Tipo_oggetto_zona oggetto_zona;
struct Zona_mappa* prossima_zona;
};
struct Giocatore {
char nome_giocatore[30];
unsigned char sanita_mentale;
struct Zona_mappa* posizione;
unsigned char zaino[4];
};
#endif
main.c
#include "gamelib.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
int main (void){
unsigned short numero;
int c = 0;
printf("\033[1;35m ____ ____ ____ ____ ____ ____ ____ ____ \n");
printf(" ||P |||h |||a |||l |||s |||o |||P |||h ||\n");
printf(" ||__|||__|||__|||__|||__|||__|||__|||__||\n");
printf(" |/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|/__\\|\n");
printf("\033[0m\n");
printf("||preme 'invio' per continuare||\n");
while(getchar()!= '\n');
do{
printf("\n");
printf("> \033[1;93m1\033[1m: Imposta Gioco.\n");
printf("> \033[1;96m2\033[2m: Gioca.\n");
printf("> \033[1;91m3\033[3m: Termina gioco.\n\n");
printf ("\033[92mScelta:\033[0m ");
scanf("%hu",&numero);
while ((c = getchar()) != '\n' && c != EOF); //pulizia dei buffer
switch(numero){
case 1:
printf("hai inserito il primo numero\n");
imposta_gioco();
break;
case 2:
printf("hai inserito il secondo numero\n");
gioca();break;
case 3:
printf("hai inserito il terzo numero");
termina_gioco();break;
default: printf("\033[31mAttenzione!\033[0m Opzione non valida, per favore inserisci \033[31mun numero da 1 a 3\033[0m.\n");
}
}while (numero != 3);
return 0;
}
gamelib.c
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include "gamelib.h"
#define ERROR_ARGS_NUM(_min, _max) printf("\033[31mAttenzione!\033[5m Opzione non valida, per favore inserisci \033[31mun numero da " #_min " a " #_max "\033[0m.\n")
#define CHECK_NUM_INPUT_RANGE(n, _min, _max)
struct Zona_mappa *pLast = NULL;
struct Zona_mappa *pFirst = NULL;
static struct Giocatore players[4];
static int nplayers = 0;
static int difficulty_level;
int ask_num(const char *prompt)
{
if (prompt)
printf("%s", prompt);
int n;
if (scanf("%d", &n) <= 0)
n = -1;
return n;
}
void mostra_zaino(struct Giocatore *giocatore)
{
const char *nome_oggetto_iniziale;
switch (giocatore->zaino[0])
{
case EMF:
nome_oggetto_iniziale = "EMF";
break;
case spirit_box:
nome_oggetto_iniziale = "Spirit Box";
break;
case videocamera:
nome_oggetto_iniziale = "Videocamera";
break;
case calmanti:
nome_oggetto_iniziale = "Calmanti";
break;
case sale:
nome_oggetto_iniziale = "Sale";
break;
default:
return;
}
printf("Contenuto zaino di %s:\nOggetto iniziale: %s\n", giocatore->nome_giocatore, nome_oggetto_iniziale);
for (int i = 1; i < 3; i++)
{
switch (giocatore->zaino[i])
{
case cento_dollari:
printf("100$\n");
break;
case nessun_oggetto:
printf("nessun_oggetto\n");
break;
case coltello:
printf("coltello\n");
break;
case calmanti1:
printf("calmanti1\n");
break;
case adrenalina:
printf("adrenalina\n");
break;
}
}
printf("\n");
}
void imposta_gioco()
{
srand(time(NULL));
memset(players, 0, sizeof(players));
nplayers = ask_num("Inserisci il numero di giocatori (da 1 a 4): ");
CHECK_NUM_INPUT_RANGE(nplayers, 1, 4);
printf("Scegli il livello di difficoltà:\n");
printf("> \033[1;93m1\033[0m: Dilettante\n");
printf("> \033[2;93m2\033[0m: Intermedio\n");
printf("> \033[3;93m3\033[0m: Incubo\n");
difficulty_level = ask_num("\033[32mInserisci il numero corrispondente: ");
CHECK_NUM_INPUT_RANGE(difficulty_level, 1, 3);
for (int i = 0; i < nplayers; i++)
{
printf("Inserisci il nome del giocatore %d: ", (i + 1));
if (scanf("%s", players[i].nome_giocatore) <= 0)
return;
players[i].sanita_mentale = 100;
players[i].zaino[0] = rand() % 5;
for (int j = 1; j < 4; j++)
players[i].zaino[j] = nessun_oggetto;
mostra_zaino(&players[i]);
}
}
struct Zona_mappa *genera_mappa()
{
// Crea la prima zona mappa
struct Zona_mappa *prima_zona = malloc(sizeof(struct Zona_mappa));
prima_zona->zona = cucina;
// Crea la seconda zona mappa
struct Zona_mappa *seconda_zona = malloc(sizeof(struct Zona_mappa));
seconda_zona->zona = soggiorno;
prima_zona->prossima_zona = seconda_zona;
// Crea la terza zona
struct Zona_mappa *terza_zona = malloc(sizeof(struct Zona_mappa));
terza_zona->zona = garage;
seconda_zona->prossima_zona = terza_zona;
struct Zona_mappa *quarta_zona = malloc(sizeof(struct Zona_mappa));
quarta_zona->zona = camera;
terza_zona->prossima_zona = quarta_zona;
// Crea la terza zona
struct Zona_mappa *quinta_zona = malloc(sizeof(struct Zona_mappa));
quinta_zona->zona = bagno;
quarta_zona->prossima_zona = quinta_zona;
struct Zona_mappa *ultima_zona = malloc(sizeof(struct Zona_mappa));
ultima_zona->zona = seminterrato;
quinta_zona->prossima_zona = ultima_zona;
ultima_zona->prossima_zona = prima_zona;
// Assegna i valori ai puntatori globali
pFirst = prima_zona;
pLast = ultima_zona;
printf("la lista è pronta\n");
return prima_zona; // Restituisce l'indirizzo della prima zona
}
void inserisci_zona()
{
struct Zona_mappa *nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERRORE di allocazione di memoria per la nuova zona\n");
return;
}
nuova_zona->zona = rand() % 4;
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 60)
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 90)
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
}
void cancella_zona()
{
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the last zone in the list and delete it
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = pFirst;
}
void stampa_mappa()
{
// Caso particolare: la lista è vuota
if (pFirst == NULL)
{
printf("La mappa è vuota\n");
return;
}
printf("Stampa della mappa:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zona di tipo %d, con oggetto %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != pFirst);
}
void chiudi_mappa()
{
gioco_impostato = 1;
}
// Funzione che avvia il gioco
void gioca()
{
{
}
}
// Funzione che termina il gioco
void termina_gioco()
{
}
I have problems in the following 3 blocks of code
void inserisci_zona()
{
struct Zona_mappa *nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERRORE di allocazione di memoria per la nuova zona\n");
return;
}
nuova_zona->zona = rand() % 4;
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 60)
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 90)
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = pFirst;
}
}
void cancella_zona()
{
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the last zone in the list and delete it
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = pFirst;
}
void stampa_mappa()
{
// Caso particolare: la lista è vuota
if (pFirst == NULL)
{
printf("La mappa è vuota\n");
return;
}
printf("Stampa della mappa:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zona di tipo %d, con oggetto %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != pFirst);
}
Here's the fixed code. Required modifications to fix the code are marked and explained with comments at the end of the lines starting with "// Edit:". It is a single file where I inserted the header file. At the end is a small main() to test the code.
#include <stdlib.h>
#include <stdio.h>
#ifndef H_GAMELIB
#define H_GAMELIB
void imposta_gioco (void);
void gioca (void);
void termina_gioco (void);
void inserisci_zona(void);
void stampa_mappa (void);
void chiudi_mappa (void);
void cancella_zona (void);
enum Tipo_Difficolta { dilettante, intermedio, incubo };
enum Tipo_oggetto_iniziale { EMF, spirit_box, videocamera, calmanti, sale };
enum Tipo_oggetto_zona { adrenalina, cento_dollari, coltello, calmanti1, nessun_oggetto };
enum Tipo_zona { caravan, cucina, soggiorno, camera, bagno, garage, seminterrato };
enum Tipo_prova { prova_EMF, prova_spirit_box, prova_videocamera, nessuna_prova };
struct Zona_mappa {
enum Tipo_zona zona;
enum Tipo_prova prova;
enum Tipo_oggetto_zona oggetto_zona;
struct Zona_mappa* prossima_zona;
};
struct Giocatore {
char nome_giocatore[30];
unsigned char sanita_mentale;
struct Zona_mappa* posizione;
unsigned char zaino[4];
};
#endif
static struct Zona_mappa* pFirst = NULL; // Edit: Added since pFirst was missing
static struct Zona_mappa* pLast = NULL; // Edit: Added since pLast was missing
void inserisci_zona(void) {
struct Zona_mappa* nuova_zona = malloc(sizeof(struct Zona_mappa));
if (nuova_zona == NULL)
{
fprintf(stderr, "ERROR of memory allocation for the new zone\n");
return;
}
nuova_zona->zona = rand() % 7; // Edit: enum has 7 enumerators
// Edit: Since zones are equiprobable, above line is sufficient
/*
int r = rand() % 100;
if (r < 80)
{
nuova_zona->zona = cucina;
}
else if (r < 60)
{
nuova_zona->zona = bagno;
}
else if (r < 50)
{
nuova_zona->zona = garage;
}
else if (r < 40)
{
nuova_zona->zona = seminterrato;
}
else if (r < 30)
{
nuova_zona->zona = camera;
}
else
{
nuova_zona->zona = soggiorno;
}
*/
int r = rand() % 100;
if (r < 40)
{
nuova_zona->oggetto_zona = nessun_oggetto;
}
else if (r < 55) // Edit: No object has 40% and all others 15%
{
nuova_zona->oggetto_zona = calmanti1;
}
else if (r < 70)
{
nuova_zona->oggetto_zona = coltello;
}
else if (r < 85) // Edit: No object has 40% and all others 15%
{
nuova_zona->oggetto_zona = cento_dollari;
}
else
{
nuova_zona->oggetto_zona = adrenalina;
}
// Insert the new zone at the end of the list
if (pFirst == NULL)
{
// If the list is empty, set First and Last as the new zone
pFirst = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = NULL; // Edit: Next of last one has to be NULL
}
else
{
pLast->prossima_zona = nuova_zona;
pLast = nuova_zona;
pLast->prossima_zona = NULL; // Edit: Next of last one has to be NULL
}
}
void cancella_zona(void) {
// Special case: the list is empty
if (pFirst == NULL)
{
return;
}
// Special case: the list contains a single zone
if (pFirst == pLast)
{
free(pFirst);
pFirst = NULL;
pLast = NULL;
return;
}
// Otherwise, find the second to last zone in the list
struct Zona_mappa *p = pFirst;
while (p->prossima_zona != pLast)
{
p = p->prossima_zona;
}
free(pLast);
pLast = p;
pLast->prossima_zona = NULL; // Edit: Next of last zone has to be NULL
}
void stampa_mappa(void) {
// Special case: the list is empty
if (pFirst == NULL)
{
printf("The map is empty\n");
return;
}
printf("Map printing:\n");
struct Zona_mappa *p = pFirst;
do
{
printf(" - Zone of type %d, with object %d\n", p->zona, p->oggetto_zona);
p = p->prossima_zona;
} while (p != NULL); // Edit: Iterate until there's no next Zona_mappa which is the case if next is NULL
}
int main(void) {
stampa_mappa();
inserisci_zona();
inserisci_zona();
inserisci_zona();
stampa_mappa();
cancella_zona();
stampa_mappa();
cancella_zona();
cancella_zona();
stampa_mappa();
for (;;);
return 0;
}
#include<iostream>
using namespace std;
enum Stare {DESCHIS=10, LUCRU=20, DUPLICAT=30, REZOLVAT=40, INCHIS=50};
struct Task
{
char *idTask;
char *data;
char *numeInginer;
int nivelComplexitate;
Stare stare;
};
struct List
{
Task *task;
List*next;
};
struct HashTable
{
List** vector;
int size;
};
List* creareNodLista(Task *task)
{
List*nod = (List*)malloc(sizeof(List));
nod->task = task;
nod->next = NULL;
return nod;
}
void initHashTable(HashTable &hTable, int size)
{
hTable.vector = (List**)malloc(sizeof(List*)*size);
hTable.size = size;
memset(hTable.vector, 0, sizeof(List*)*size);
}
int fhash(char c, int l)
{
return c%l;
}
void inserareNodLista(List*&list, List*nod)
{
nod->next = list;
list = nod;
}
void inserareNodHashTable(HashTable hTable, List*nod)
{ //determinarea pozitiei pe care se face inserarea
int index = fhash(nod->task->numeInginer[0],hTable.size);
//obtinerea listei in care se face inserarea
List*list = hTable.vector[index];
//inserare element nou in lista
inserareNodLista(list, nod);
//actualizare element in hashTable
hTable.vector[index] = list;
}
List* getHashTable(HashTable ht, char cheie)
{
int f = fhash(cheie, ht.size);
return ht.vector[f];
}
void printHashTable(HashTable ht)
{
for (char c = 'A'; c < 'Z'; c++)
{
List*lista = getHashTable(ht, c);
int count = 0;
while (lista)
{
count++;
printf("%d", count);
printf("%s\n", lista->task->idTask);
printf("%s\n", lista->task->data);
printf("%s\n", lista->task->numeInginer);
printf("%d\n", lista->task->nivelComplexitate);
printf("%d\n", lista->task->stare);
lista = lista->next;
}
if (count>1)
printf("\nColiziune\n\n");
}
}
int stergeNodHashTable(HashTable hTable, char*numeInginer)
{
int pozitie = 0;
pozitie = fhash(numeInginer[0], hTable.size);
if (hTable.vector[pozitie] == NULL)
return -1;
else
{
if (strcmp(hTable.vector[pozitie]->task->numeInginer, numeInginer) == 0)
{
if (hTable.vector[pozitie]->next == NULL)
{
free(hTable.vector[pozitie]->task->idTask);
free(hTable.vector[pozitie]->task->data);
free(hTable.vector[pozitie]->task->numeInginer);
free(hTable.vector[pozitie]->task);
free(hTable.vector[pozitie]);
hTable.vector[pozitie] = NULL;
}
else
{
List*lista = hTable.vector[pozitie];
hTable.vector[pozitie] = lista->next;
free(lista->task->idTask);
free(lista->task->data);
free(lista->task->numeInginer);
free(lista->task);
free(lista);
lista->next = NULL;
lista = NULL;
}
}
else
{
List*tmp = hTable.vector[pozitie];
while (tmp->next != NULL && strcmp(tmp->next->task->numeInginer, numeInginer) != 0)
tmp = tmp->next;
List*list = tmp->next;
if (list->next == NULL)
{
free(list->task->idTask);
free(list->task->numeInginer);
free(list->task->data);
free(list->task);
free(list);
tmp->next = NULL;
list = NULL;
}
else
{
List*tmp = list;
list = list->next;
free(tmp->task->idTask);
free(tmp->task->data);
free(tmp->task->numeInginer);
free(tmp->task);
free(tmp);
tmp->next = NULL;
tmp = NULL;
}
}
}
return pozitie;
}
void main()
{
FILE *pFile = fopen("Text.txt", "r");
Task *task = NULL;
HashTable ht;
initHashTable(ht, 29);
if (pFile)
{
while (!feof(pFile))
{
task = (Task*)malloc(sizeof(Task));
char id[50];
fscanf(pFile, "%s", &id);
task->idTask = (char*)malloc(strlen(id) + 1);
strcpy(task->idTask, id);
char data[50];
fscanf(pFile, "%s", data);
task->data = (char*)malloc(strlen(data) + 1);
strcpy(task->data, data);
char numeInfiner[50];
fscanf(pFile, "%s", numeInfiner);
task->numeInginer = (char*)malloc(strlen(numeInfiner) + 1);
strcpy(task->numeInginer, numeInfiner);
fscanf(pFile, "%d", &task->nivelComplexitate);
fscanf(pFile, "%d", &task->stare);
//creare element lista
List*nod = creareNodLista(task);
//inserare element in hashTable
inserareNodHashTable(ht, nod);
}
fclose(pFile);
for (char c = 'A'; c < 'Z'; c++)
{
List *lista = getHashTable(ht, c);
while (lista)
{
if (lista->task->stare == 50)
stergeNodHashTable(ht, lista->task->numeInginer);
}
}
printHashTable(ht);
}
}
I am trying to delete from hashTable all the elements with status marked as closed. The delete function is working fine but when i call it for al the hashtable, it got me error: lista->task was 0xDDDDDD. I cant understand why. Please help me!
I am trying to make a c program to create port forwarding rule using libiptc.
static int insert_forward_rule(const char *table, const char *chain, unsigned int src, unsigned int dest, const char * ports, const char *target1, char * proto) {
struct xtc_handle *h;
struct ipt_entry *en = NULL;
struct ipt_entry * e;
struct ipt_entry_match * match_proto, * match_limit;
struct ipt_entry_target * target;
unsigned int size_ipt_entry, size_ipt_entry_match, size_ipt_entry_target, total_length;
size_ipt_entry = IPT_ALIGN(sizeof (struct ipt_entry));
size_ipt_entry_match = IPT_ALIGN(sizeof (struct ipt_entry_match)) + sizeof (struct ipt_tcp) + sizeof (int);
size_ipt_entry_target = IPT_ALIGN(sizeof (struct ipt_entry_target) + sizeof (IPTC_LABEL_ACCEPT));
total_length = 216; //size_ipt_entry + size_ipt_entry_match + size_ipt_entry_target + IPT_ALIGN(sizeof (struct ipt_natinfo)); //size_ipt_entry + 48 + 40
//printf("size of ipt ebtry=%u,match=%u,target=%u,total=%u\n", size_ipt_entry, size_ipt_entry_match, size_ipt_entry_target, total_length);
//memory allocation for all structs that represent the netfilter rule we want to insert
e = calloc(1, total_length);
if (e == NULL) {
printf("malloc failure");
exit(1);
}
int size = 160;
//offsets to the other bits:
//target struct begining
e->target_offset = size; //size_ipt_entry + size_ipt_entry_match; //+ size_ipt_tcp + size_rateinfo + size_physdevinfo;
//next "e" struct, end of the current one
e->next_offset = total_length;
e->nfcache = NFC_IP_DST_PT;
if (dest) {
e->ip.dst.s_addr = dest;
e->ip.dmsk.s_addr = 0xFFFFFFFF;
}
match_limit = (struct ipt_entry_match *) (e->elems); //+ match_proto->u.match_size
match_limit->u.user.match_size = size_ipt_entry_match; //size_ipt_entry_match*3; //+ size_rateinfo;
strncpy(match_limit->u.user.name, "tcp", sizeof (match_limit->u.user.name)); //set name of the module, we will use in this match
struct ipt_tcp *info = (struct ipt_tcp *) match_limit->data;
unsigned int i = 0;
if (strchr(ports, ':') != NULL) {
char aPort[2][10];
sscanf(ports, "%[^:], %[^:]", aPort[0], aPort[1]);
info->dpts[0] = atoi(aPort[0]);
info->dpts[1] = atoi(aPort[1]);
} else {
info->dpts[0] = info->dpts[1] = atoi(ports);
}
info->spts[0] = 0;
info->spts[1] = 0xFFFF;
e->ip.proto = IPPROTO_TCP;
printf("Target offset=%d,next offset=%d\n", e->target_offset, e->next_offset);
target = (struct ipt_entry_target *) ((void*) e + e->target_offset); // + size_ipt_entry_match); //+ size_ipt_tcp + size_rateinfo + size_physdevinfo
size = 56;
target->u.user.target_size = size_ipt_entry_target + IPT_ALIGN(sizeof (struct nf_nat_range)); // size_ipt_entry_target;
target->u.user.revision = 0;
strncpy(target->u.user.name, target1, sizeof (target->u.user.name));
struct ipt_natinfo *inf = (struct ipt_natinfo*) target->data;
struct nf_nat_range range;
memset(&range, 0, sizeof (range));
range.flags |= IP_NAT_RANGE_MAP_IPS;
range.min_ip = range.max_ip = src;
inf->mr.rangesize++;
inf->mr.range[inf->mr.rangesize] = range;
inf->t.u.target_size = XT_ALIGN(sizeof (*inf) + inf->mr.rangesize * sizeof (struct nf_nat_range));
printf("after s_addr\n\n");
//All the functions, mentioned below could be found in "Querying libiptc HOWTO" manual
h = iptc_init(table);
printf("h=%d\n", h);
if (!h) {
printf("Error initializing: %s\n", iptc_strerror(errno));
return 0;
}
printf("target_size=%d,match=%d,chain=%s,table=%s,target=%s\n", target->u.user.target_size, match_limit->u.user.match_size, chain, table, target1);
int x = iptc_append_entry(chain, e, h);
if (!x) {
printf("Error append_entry: %s\n", iptc_strerror(errno));
goto ERROR;
}
printf("%d,chain=%s,target=%s\n", target->u.user.target_size, chain, table);
int y = iptc_commit(h);
if (!y) {
printf("Error no=%d,commit: %s\n", errno, iptc_strerror(errno));
goto ERROR;
}
iptc_free(h);
if (e != NULL) {
free(e);
e = NULL;
}
return 1;
ERROR:
iptc_free(h);
if (e != NULL) {
free(e);
e = NULL;
}
return 0;
}
To call this function
inet_pton(AF_INET, "20.10.10.254", &a);
inet_pton(AF_INET, "20.10.10.100", &b);
insert_forward_rule("nat", "port_forward", b, a, "1111", "DNAT", "tcp");
Every time i run this code i am getting error as invalid arguments(code 22).If i change the position of rangesize to below iptc_init() then it gave an error code 94(socket operation on non-socket)
I tried struct nf_nat_range structure directly but then its not saving the destination ip in rules instead of that its showing random.
Rule which i want to make is
iptables -t nat -A port_forward -j DNAT -d 192.168.10.202 -p udp --dport 8080:8084 --to 20.10.10.112
what it is creating with structure nf_nat_range is
Chain port_forward (0 references)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- * * 0.0.0.0/0 20.10.10.254 tcp dpt:1111 to: random
0 0 DNAT tcp -- * * 0.0.0.0/0 20.10.10.254 tcp dpt:1111 to: random
0 0 DNAT tcp -- * * 0.0.0.0/0 20.10.10.254 tcp dpt:1111 to: random
These are the functions which helped me to Add or Delete DNAT and SNAT rules using libiptc. I uploaded this to my GitHub account.
void iptc_add_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to, const int append) {
iptc_handle_t handle;
struct ipt_entry *chain_entry;
struct ipt_entry_match *entry_match = NULL;
struct ipt_entry_target *entry_target;
ipt_chainlabel labelit;
long match_size;
int result = 0;
chain_entry = (struct ipt_entry *) calloc(1, sizeof (*chain_entry));
if (src) {
chain_entry->ip.src.s_addr = inet_addr(src);
chain_entry->ip.smsk.s_addr = inet_addr("255.255.255.255");
}
if (dest) {
chain_entry->ip.dst.s_addr = inet_addr(dest);
chain_entry->ip.dmsk.s_addr = inet_addr("255.255.255.255");
}
if (iniface) strncpy(chain_entry->ip.iniface, iniface, IFNAMSIZ);
if (outiface) strncpy(chain_entry->ip.outiface, outiface, IFNAMSIZ);
if (strcmp(protocol, "TCP") == 0) {
chain_entry->ip.proto = IPPROTO_TCP;
entry_match = get_tcp_match(srcports, destports, &chain_entry->nfcache);
} else if (strcmp(protocol, "UDP") == 0) {
chain_entry->ip.proto = IPPROTO_UDP;
entry_match = get_udp_match(srcports, destports, &chain_entry->nfcache);
} else {
printf("Unsupported protocol: %s", protocol);
return;
}
if (strcmp(target, "") == 0
|| strcmp(target, IPTC_LABEL_ACCEPT) == 0
|| strcmp(target, IPTC_LABEL_DROP) == 0
|| strcmp(target, IPTC_LABEL_QUEUE) == 0
|| strcmp(target, IPTC_LABEL_RETURN) == 0) {
size_t size;
size = IPT_ALIGN(sizeof (struct ipt_entry_target)) + IPT_ALIGN(sizeof (int));
entry_target = (struct ipt_entry_target *) calloc(1, size);
entry_target->u.user.target_size = size;
strncpy(entry_target->u.user.name, target, IPT_FUNCTION_MAXNAMELEN);
} else if (strcmp(target, "DNAT") == 0) {
entry_target = get_dnat_target(dnat_to, &chain_entry->nfcache);
printf("dnat\n");
} else if (strcmp(target, "SNAT") == 0) {
entry_target = get_snat_target(dnat_to, &chain_entry->nfcache);
printf("snat\n");
}
if (entry_match)
match_size = entry_match->u.match_size;
else
match_size = 0;
struct ipt_entry *tmp_ipt = chain_entry;
chain_entry = (struct ipt_entry *) realloc(chain_entry, sizeof (*chain_entry) + match_size + entry_target->u.target_size);
if (chain_entry == NULL) {
free(tmp_ipt);
}
memcpy(chain_entry->elems + match_size, entry_target, entry_target->u.target_size);
chain_entry->target_offset = sizeof (*chain_entry) + match_size;
chain_entry->next_offset = sizeof (*chain_entry) + match_size + entry_target->u.target_size;
printf("target->offset=%d,next_offset=%d,target_size=%d\n", chain_entry->target_offset, chain_entry->next_offset, entry_target->u.user.target_size);
if (entry_match) {
memcpy(chain_entry->elems, entry_match, match_size);
printf("%d\n", __LINE__);
}
printf("%d\n", __LINE__);
handle = iptc_init(table);
if (!handle) {
printf("libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno));
free(chain_entry);
free(entry_target);
if (entry_match) free(entry_match);
return;
}
strncpy(labelit, chain, sizeof (ipt_chainlabel));
printf("%d\n", __LINE__);
result = iptc_is_chain(chain, handle);
if (!result) {
printf("libiptc error: Chain %s does not exist!", chain);
free(chain_entry);
free(entry_target);
if (entry_match) free(entry_match);
return;
}
printf("%d,labeit=%s\n", __LINE__, labelit);
if (append)
result = iptc_append_entry(labelit, chain_entry, handle);
else
result = iptc_insert_entry(labelit, chain_entry, 0, handle);
printf("%d\n", __LINE__);
if (!result) {
printf("libiptc error: Can't add, %s", iptc_strerror(errno));
free(chain_entry);
free(entry_target);
if (entry_match) free(entry_match);
return;
}
printf("%d\n", __LINE__);
result = iptc_commit(handle);
if (!result) {
printf("libiptc error: Commit error, %s", iptc_strerror(errno));
free(chain_entry);
free(entry_target);
if (entry_match) free(entry_match);
return;
} else
printf("added new rule to block successfully");
if (entry_match) free(entry_match);
free(entry_target);
free(chain_entry);
}
void iptc_delete_rule(const char *table, const char *chain, const char *protocol, const char *iniface, const char *outiface, const char *src, const char *dest, const char *srcports, const char *destports, const char *target, const char *dnat_to) {
iptc_handle_t handle;
const struct ipt_entry *e;
ipt_chainlabel labelit;
int i, result;
unsigned long int s_src, s_dest;
if (src) s_src = inet_addr(src);
if (dest) s_dest = inet_addr(dest);
handle = iptc_init(table);
if (!handle) {
printf("libiptc error: Can't initialize table %s, %s", table, iptc_strerror(errno));
return;
}
strncpy(labelit, chain, sizeof (ipt_chainlabel));
result = iptc_is_chain(chain, handle);
if (!result) {
printf("libiptc error: Chain %s does not exist!", chain);
return;
}
for (e = iptc_first_rule(chain, handle), i = 0; e; e = iptc_next_rule(e, handle), i++) {
if (src && e->ip.src.s_addr != s_src) continue;
else if (dest && e->ip.dst.s_addr != s_dest) continue;
else if (iniface && strcmp(e->ip.iniface, iniface) != 0) continue;
else if (outiface && strcmp(e->ip.outiface, outiface) != 0) continue;
else if (protocol && strcmp(protocol, "TCP") == 0 && e->ip.proto != IPPROTO_TCP) continue;
else if (protocol && strcmp(protocol, "UDP") == 0 && e->ip.proto != IPPROTO_UDP) continue;
else if ((srcports || destports) && IPT_MATCH_ITERATE_MY(e, matchcmp, srcports, destports) == 0) continue;
else if (target && strcmp(target, iptc_get_target(e, handle)) != 0) continue;
else if (dnat_to && strcmp(target, "DNAT") == 0) {
struct ipt_entry_target *t;
struct ip_nat_multi_range *mr;
struct ip_nat_range *r, range;
t = (struct ipt_entry_target *) (e + e->target_offset);
mr = (struct ip_nat_multi_range *) ((void *) &t->data);
if (mr->rangesize != 1) continue; // we have only single dnat_to target now
r = mr->range;
parse_range(dnat_to, &range);
if (r->flags == range.flags
&& r->min_ip == range.min_ip
&& r->max_ip == range.max_ip
&& r->min.all == range.min.all
&& r->max.all == range.max.all) {
break;
}
} else break;
}
if (!e) return;
result = iptc_delete_num_entry(chain, i, handle);
if (!result) {
printf("libiptc error: Delete error, %s", iptc_strerror(errno));
return;
}
result = iptc_commit(handle);
if (!result) {
printf("libiptc error: Commit error, %s", iptc_strerror(errno));
return;
} else
printf("deleted rule from block successfully");
}
int matchcmp(const struct ipt_entry_match *match, const char *srcports, const char *destports) {
u_int16_t temp[2];
if (strcmp(match->u.user.name, "tcp") == 0) {
struct ipt_tcp *tcpinfo = (struct ipt_tcp *) match->data;
if (srcports) {
parse_ports(srcports, temp);
if (temp[0] != tcpinfo->spts[0] || temp[1] != tcpinfo->spts[1]) return 0;
}
if (destports) {
parse_ports(destports, temp);
if (temp[0] != tcpinfo->dpts[0] || temp[1] != tcpinfo->dpts[1]) return 0;
}
return 1;
} else if (strcmp(match->u.user.name, "udp") == 0) {
struct ipt_udp *udpinfo = (struct ipt_udp *) match->data;
if (srcports) {
parse_ports(srcports, temp);
if (temp[0] != udpinfo->spts[0] || temp[1] != udpinfo->spts[1]) return 0;
}
if (destports) {
parse_ports(destports, temp);
if (temp[0] != udpinfo->dpts[0] || temp[1] != udpinfo->dpts[1]) return 0;
}
return 1;
} else return 0;
}
/* These functions are used to create structs */
struct ipt_entry_match *get_tcp_match(const char *sports, const char *dports, unsigned int *nfcache) {
struct ipt_entry_match *match;
struct ipt_tcp *tcpinfo;
size_t size;
size = IPT_ALIGN(sizeof (*match)) + IPT_ALIGN(sizeof (*tcpinfo));
match = (struct ipt_entry_match *) calloc(1, size);
match->u.match_size = size;
strncpy(match->u.user.name, "tcp", IPT_FUNCTION_MAXNAMELEN);
tcpinfo = (struct ipt_tcp *) match->data;
tcpinfo->spts[1] = tcpinfo->dpts[1] = 0xFFFF;
printf("sports=%s,dports=%s\n", sports, dports);
if (sports) {
*nfcache |= NFC_IP_SRC_PT;
parse_ports(sports, tcpinfo->spts);
printf("%d\n", __LINE__);
}
if (dports) {
*nfcache |= NFC_IP_DST_PT;
parse_ports(dports, tcpinfo->dpts);
printf("%d\n", __LINE__);
}
return match;
}
struct ipt_entry_match *get_udp_match(const char *sports, const char *dports, unsigned int *nfcache) {
struct ipt_entry_match *match;
struct ipt_udp *udpinfo;
size_t size;
size = IPT_ALIGN(sizeof (*match)) + IPT_ALIGN(sizeof (*udpinfo));
match = (struct ipt_entry_match *) calloc(1, size);
match->u.match_size = size;
strncpy(match->u.user.name, "udp", IPT_FUNCTION_MAXNAMELEN);
udpinfo = (struct ipt_udp *) match->data;
udpinfo->spts[1] = udpinfo->dpts[1] = 0xFFFF;
printf("sports=%s,dports=%s\n", sports, dports);
if (sports) {
*nfcache |= NFC_IP_SRC_PT;
parse_ports(sports, udpinfo->spts);
printf("%d\n", __LINE__);
}
if (dports) {
*nfcache |= NFC_IP_DST_PT;
parse_ports(dports, udpinfo->dpts);
printf("%d\n", __LINE__);
}
return match;
}
struct ipt_entry_target *get_dnat_target(const char *input, unsigned int *nfcache) {
struct ipt_entry_target *target;
struct ipt_natinfo *info;
struct ip_nat_range range;
char *buffer;
size_t size;
/* Can't cache this */
*nfcache |= NFC_UNKNOWN;
buffer = strdup(input);
size = IPT_ALIGN(sizeof (*target)) + IPT_ALIGN(sizeof (struct ip_nat_multi_range));
target = (struct ipt_entry_target *) calloc(1, size);
target->u.target_size = size;
strncpy(target->u.user.name, "DNAT", IPT_FUNCTION_MAXNAMELEN);
info = (struct ipt_natinfo *) target;
printf("buffer range=%s\n", buffer);
parse_range(buffer, &range);
target = &(append_range(info, &range)->t);
printf("range=%d\n", range.flags);
printf("%d\n", __LINE__);
free(buffer);
return target;
}
struct ipt_entry_target *get_snat_target(const char *input, unsigned int *nfcache) {
struct ipt_entry_target *target;
struct ipt_natinfo *info;
struct ip_nat_range range;
char *buffer;
size_t size;
/* Can't cache this */
*nfcache |= NFC_UNKNOWN;
buffer = strdup(input);
size = IPT_ALIGN(sizeof (*target)) + IPT_ALIGN(sizeof (struct ip_nat_multi_range));
target = (struct ipt_entry_target *) calloc(1, size);
target->u.target_size = size;
strncpy(target->u.user.name, "SNAT", IPT_FUNCTION_MAXNAMELEN);
info = (struct ipt_natinfo *) target;
printf("buffer range=%s\n", buffer);
parse_range(buffer, &range);
target = &(append_range(info, &range)->t);
printf("range=%d\n", range.flags);
printf("%d\n", __LINE__);
free(buffer);
return target;
}
/* Copied and modified from libipt_tcp.c and libipt_udp.c */
static u_int16_t parse_port(const char *port) {
unsigned int portnum;
if ((portnum = service_to_port(port)) != -1) {
return (u_int16_t) portnum;
} else {
return atoi(port);
}
}
static void parse_ports(const char *portstring, u_int16_t *ports) {
char *buffer;
char *cp;
buffer = strdup(portstring);
if ((cp = strchr(buffer, ':')) == NULL)
ports[0] = ports[1] = parse_port(buffer);
else {
*cp = '\0';
cp++;
ports[0] = buffer[0] ? parse_port(buffer) : 0;
ports[1] = cp[0] ? parse_port(cp) : 0xFFFF;
}
free(buffer);
}
static int service_to_port(const char *name) {
struct servent *service;
if ((service = getservbyname(name, "tcp")) != NULL)
return ntohs((unsigned short) service->s_port);
return -1;
}
/* Copied and modified from libipt_DNAT.c */
static void parse_range(const char *input, struct ip_nat_range *range) {
char *colon, *dash, *buffer;
in_addr_t ip;
buffer = strdup(input);
memset(range, 0, sizeof (*range));
colon = strchr(buffer, ':');
if (colon) {
int port;
range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED;
port = atoi(colon + 1);
dash = strchr(colon, '-');
if (!dash) {
range->min.all
= range->max.all
= htons(port);
} else {
int maxport;
maxport = atoi(dash + 1);
range->min.all = htons(port);
range->max.all = htons(maxport);
}
/* Starts with a colon? No IP info...*/
if (colon == buffer) {
free(buffer);
return;
}
*colon = '\0';
}
range->flags |= IP_NAT_RANGE_MAP_IPS;
dash = strchr(buffer, '-');
if (colon && dash && dash > colon)
dash = NULL;
if (dash)
*dash = '\0';
ip = inet_addr(buffer);
range->min_ip = ip;
if (dash) {
ip = inet_addr(dash + 1);
range->max_ip = ip;
} else
range->max_ip = range->min_ip;
free(buffer);
return;
}
static struct ipt_natinfo *append_range(struct ipt_natinfo *info, const struct ip_nat_range *range) {
unsigned int size;
/* One ip_nat_range already included in ip_nat_multi_range */
size = IPT_ALIGN(sizeof (*info) + info->mr.rangesize * sizeof (*range));
info = (struct ipt_natinfo *) realloc(info, size);
info->t.u.target_size = size;
info->mr.range[info->mr.rangesize] = *range;
info->mr.rangesize++;
printf("range size=%d\n", info->mr.rangesize);
return info;
}
I am a noob in c, and i have this code that doesnt work properly because some bad memory allcoation i make for a char** pointer. Could you please help? Thx a lot in advance.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node_t {
struct tuple_t *tuple; //Entrada na lista
struct node_t *next; //o node seguinte da lista
};
struct tuple_t {
long timestamp; /* instante de criacao do tuplo*/
int n_fields; /* numero de campos deste tuplo */
char **fields; /* array com campos do tuplo */
/* 4 + 4 + 4 bytes?? */
};
char ** split_str(char [], char **, const char *);
struct node_t *node_create(void *node_data){
struct node_t *node = NULL;
node = (struct node_t *)malloc(sizeof(struct node_t));
if(!node){
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = (struct tuple_t *)malloc(sizeof(struct tuple_t));
if(!node->tuple){printf("Erro ao criar o node->tuple\n"); free(node); return NULL;}
node->tuple->fields = (char ** )malloc(strlen((char *) node_data) * sizeof(char *));
if(!node->tuple->fields){ printf("Erro ao criar o node->tuple->node_fields\n"); free(node->tuple); free(node); return NULL; }
char **array;
const char *sep=" ";
char *s = (char *)node_data;
char arr[strlen(s)];
int i = 0;
while(arr[i++]=s[i]);
array = split_str(arr,array, sep);
i = 0;
while(array[i]){
node->tuple->fields[i] = (char *)malloc((strlen(array[i])) * sizeof(char));
if(!node->tuple->fields[i]){
printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
return NULL;
}
node->tuple->fields[i] = array[i];
// printf("array[i]=%s\n",array[i]);
// printf("node->tuple->fields[i]=%s\n",node->tuple->fields[i]);
i++;
}
node->tuple->n_fields = i;
node->tuple->timestamp = 0L;
node->next = NULL;
return node;
}
char** split_str(char writablestring[],char **array, const char *sep ){
array = malloc(strlen(writablestring) + 1);
if(! array){printf("Erro ao alocar memoria para o array em split\n"); return NULL;}
char *token = strtok(writablestring, sep);
int i=0;
while(token != NULL)
{
array[i] = malloc(strlen(token)+1);
if(!array[i])
return NULL;
array[i] = token;
token = strtok(NULL, " ");
i++;
}
return array;
}
int main(int argc, char** argv)
{
void * n_data = "hello 123 ploc";
struct node_t * node = node_create(n_data);
printf("node->num_fields=%d\n", node->tuple->n_fields);
int i=0;
while( node->tuple->fields[i] ){
printf("node->tuple->fields[%d]=%s\n",i,node->tuple->fields[i]);
i++;
}
return 0;
}
End code.
Your split_str() function returns pointers into writablestring, which is the array arr in node_create(). You then copy these pointers into node->tuple->fields[i] - but the arr array won't exist after the node_create() function exits - so those pointers will no longer be valid. Instead, you need to copy the returned string into the memory that you have allocated (this also shows how you can use a for() loop in place of your while(), and you also need to free the memory that was allocated in split_str()):
for (i = 0; array[i]; i++) {
node->tuple->fields[i] = malloc(strlen(array[i]) + 1);
if (!node->tuple->fields[i]){
printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
return NULL;
}
strcpy(node->tuple->fields[i], array[i]);
}
free(array);
Additionally, your code assumes that the array returned by split_str() will be terminated by a NULL, but the function does not ensure this. The function has numerous other problems (incorrect size passed to malloc(), memory leak caused by unnecessary malloc()) - so you need to fix it, too:
char **split_str(char writablestring[], const char *sep)
{
char **array = malloc(strlen(writablestring) * sizeof array[0]);
if(!array) {
printf("Erro ao alocar memoria para o array em split\n");
return NULL;
}
char *token = strtok(writablestring, sep);
int i;
for (i = 0; (array[i] = token) != NULL; i++) {
token = strtok(NULL, " ");
}
return array;
}
(Note that array does not need to be passed as a parameter - it's being immediately overwritten anyway, so I turned it into a local variable).
Once you've done this, you might notice that there's really no reason to allocate array in split_str(), only to copy its contents to node->tuple->fields and then free it. You might as well pass the array node->tuple->fields to split_str() and have it write directly into it. It could then return the number of strings allocated - that would look like:
int split_str(char [], char **, const char *);
struct node_t *node_create(void *node_data)
{
struct node_t *node = NULL;
char *s = node_data;
size_t slen = strlen(s);
node = malloc(sizeof *node);
if (!node) {
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = malloc(sizeof *node->tuple);
if (!node->tuple) {
printf("Erro ao criar o node->tuple\n");
free(node);
return NULL;
}
node->tuple->fields = malloc(slen * sizeof node->tuple->fields[0]);
if (!node->tuple->fields) {
printf("Erro ao criar o node->tuple->node_fields\n");
free(node->tuple);
free(node);
return NULL;
}
char arr[slen + 1];
strcpy(arr, s);
int i = split_str(arr, node->tuple->fields, " ");
node->tuple->n_fields = i;
node->tuple->timestamp = 0L;
node->next = NULL;
return node;
}
int split_str(char writablestring[], char **array, const char *sep)
{
char *token = strtok(writablestring, sep);
int i;
for (i = 0; token != NULL; i++) {
array[i] = malloc(strlen(token) + 1);
if (!array[i]) {
printf("Erro ao criar o array[i]\n");
break;
}
strcpy(array[i], token);
token = strtok(NULL, " ");
}
return i;
}
Try something like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct tuple_t
{
long timestamp; /* instante de criacao do tuplo*/
int n_fields; /* numero de campos deste tuplo */
char** fields; /* array com campos do tuplo */
};
struct node_t
{
struct tuple_t* tuple; //Entrada na lista
struct node_t* next; //o node seguinte da lista
};
char** split_str(const char *, const char *, int *);
void node_destroy(struct node_t*);
struct node_t* node_create(char* node_data)
{
struct node_t* node = (struct node_t *) malloc(sizeof(struct node_t));
if(!node)
{
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = (struct tuple_t *) malloc(sizeof(struct tuple_t));
if(!node->tuple)
{
printf("Erro ao criar o node->tuple\n");
node_destroy(node);
return NULL;
}
node->tuple->timestamp = 0L;
node->tuple->fields = split_str(node_data, " ", &(node->tuple->n_fields));
if(!node->tuple->fields)
{
printf("Erro ao criar o node->tuple->node_fields\n");
node_destroy(node);
return NULL;
}
node->next = NULL;
return node;
}
void node_destroy(struct node_t* node)
{
if(node)
{
if(node->tuple)
{
if(node->tuple->fields)
{
for(int i = 0; i < node->tuple->n_fields; ++i)
free(node->tuple->fields[i]);
free(node->tuple->fields);
}
free(node->tuple);
}
free(node);
}
}
char** split_str(const char* str, const char* sep, int* found)
{
if (found) *found = 0;
int len = strlen(str);
char** array = (char**) malloc(len * sizeof(char*));
if(!array)
{
printf("Erro ao alocar memoria para o array em split\n");
return NULL;
}
++len;
char* writablestring = (char*) malloc(len);
if(!array)
{
printf("Erro ao alocar memoria para writeablestring em split\n");
free(array);
return -1;
}
strncpy(writablestring, str, len);
char* token = strtok(writablestring, sep);
int i = 0;
while(token)
{
len = strlen(token) + 1;
array[i] = (char*) malloc(len);
if(!array[i])
{
printf("Erro ao alocar memoria para o array item em split\n");
free(writeablestring);
for(int j = 0; j < i; ++j)
free(array[j]);
free(array);
return NULL;
}
strncpy(array[i], token, len);
++i;
token = strtok(NULL, sep);
}
free(writeablestring);
if(found) *found = i;
return array;
}
int main(int argc, char** argv)
{
char* n_data = "hello 123 ploc";
struct node_t* node = node_create(n_data);
if(node)
{
printf("node->tuple->n_fields=%d\n", node->tuple->n_fields);
for(int i = 0; i < node->tuple->n_fields; ++i)
printf("node->tuple->fields[%d]=%s\n", i, node->tuple->fields[i]);
node_destroy(node);
}
return 0;
}