#reading a firewall rule not working
393 messages · Page 1 of 1 (latest)
When your question is answered use !solved to mark the question as resolved.
Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.
@steady whale
Your message appears to contain screenshots but no code. Please send code and error messages in text instead of screenshots if applicable!
i tried skipping the A
but its still not working
this is my code for reading a rule
struct firewallRule_t *readRule (char * line) {
struct firewallRule_t *newRule;
char *pos;
// Skip the initial 'A' and any following spaces
pos = line;
if (*pos == 'A' || *pos == 'a') {
pos++;
}
while (*pos == ' ') {
pos++;
}
// parse IP addresses
newRule = malloc(sizeof(struct firewallRule_t));
pos = parseIPaddress(newRule->ipaddr1, pos, true);
if ((pos == NULL) || (newRule->ipaddr1[0] == -1)) {
free(newRule);
return NULL;
}
newRule->ipaddr2[0] = -1; // Assuming single IP address (not a range)
// Skip spaces before port number
while (*pos == ' ') pos++;
// parse ports
pos = parsePort(&(newRule->port1), pos);
if ((pos == NULL) || (newRule->port1 == -1)) {
free(newRule);
return NULL;
}
newRule->port2 = newRule->port1; // Assuming single port (not a range)
return newRule;
}
please help
Can you post what one might reasonably expect parameter line to read?
Maybe you have an example.
i think this is what ur asking?
So where does your 'A' come into play?
sorry i should've specified
so is there something wrong in my client code?
that isnt accounting for this A
Those parameters should be caught using argc and argv in your main function.
But if parameter rule can assume values like
aaa.bbb.ccc.ddd ppp
(note the space)
Then this will be very difficult to capture.
Either way, 'A' would not be part of the rule.
What does your main() function look like right now?
on my server side or client side?
Client side
int main(int argc, char *argv[]) {
int sockfd, n;
struct addrinfo hints;
struct addrinfo *result, *rp;
int res;
char buffer[BUFFERLENGTH];
// Check if enough arguments are provided
if (argc < 5) {
fprintf(stderr, "Usage: %s hostname port A rule\n", argv[0]);
exit(1);
}
/* Prepare the rule to be sent */
snprintf(buffer, BUFFERLENGTH, "A %s %s\n", argv[4], argv[5]); // Concatenating "A", IP, and Port
/* Obtain address(es) matching host/port */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0; /* Any protocol */
res = getaddrinfo(argv[1], argv[2], &hints, &result);
if (res != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(res));
exit(EXIT_FAILURE);
}
/* Try each address until we successfully connect */
for (rp = result; rp != NULL; rp = rp->ai_next) {
sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (sockfd == -1)
continue;
if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
break; /* Success */
close(sockfd);
}
if (rp == NULL) { /* No address succeeded */
fprintf(stderr, "Could not connect\n");
exit(EXIT_FAILURE);
}
freeaddrinfo(result); /* No longer needed */
/* Send the rule directly */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer, BUFFERLENGTH);
/* Wait for the server's response */
n = read(sockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n", buffer);
close(sockfd);
return 0;
}
i havent changed anything on my client side apart from the base code ive been given and tried to do this change:
i got told i need to try join the ip and the port
/* Prepare the rule to be sent */
snprintf(buffer, BUFFERLENGTH, "A %s %s\n", argv[4], argv[5]); // Concatenating "A", IP, and Port
This is homework, right?
We are bound by the wording of the assignment.
yeah do you want me to send it? its due tomorrow asw
its quite long but im currently trying to do the first add rule question
so i can at least get something to work
this is what im trying to do rn
These are the arguments as a C program understands them.
build/client localhost 2201 A 110.101.111.123 34
0: build/client
1: localhost
2: 2201
3: A
4: 110.101.111.123
5: 34
build/client localhost 2201 A 110.101.111.123-110.101.111.254 34
0: build/client
1: localhost
2: 2201
3: A
4: 110.101.111.123-110.101.111.254
5: 34
build/client localhost 2201 A 110.101.111.123-110.101.111.254 34-45
0: build/client
1: localhost
2: 2201
3: A
4: 110.101.111.123-110.101.111.254
5: 34-45
So it's always 5 arguments.
Would you concur?
(arg0 being the app, ofc)
mhm yeah
You are combining arg4 and arg5 into one string.
Is that so you can pass just that one string to readRule()?
yeah thats what i was trying to do
struct firewallRule_t *readRule (char * line) {
struct firewallRule_t *newRule;
char *pos;
// Skip the initial 'A' and any following spaces
pos = line;
if (*pos == 'A' || *pos == 'a') {
pos++;
}
while (*pos == ' ') {
pos++;
}
// parse IP addresses
newRule = malloc(sizeof(struct firewallRule_t));
pos = parseIPaddress(newRule->ipaddr1, pos, true);
if ((pos == NULL) || (newRule->ipaddr1[0] == -1)) {
free(newRule);
return NULL;
}
if (*pos == '-') {
// read second IP address
pos = parseIPaddress (newRule->ipaddr2, pos+1, true);
if ((pos == NULL) || (newRule->ipaddr2[0] == -1)) {
free (newRule);
return NULL;
}
if (compareIPAddresses (newRule->ipaddr1, newRule->ipaddr2) != -1) {
free(newRule);
return NULL;
}
}
else {
newRule->ipaddr2[0] = -1;
}
if (*pos != ' ') {
free(newRule);
return NULL;
}
else pos++;
// parse ports
pos = parsePort (&(newRule->port1), pos);
if ((pos == NULL) || (newRule->port1 == -1)) {
free(newRule);
return NULL;
}
if ((*pos == '\n') || (*pos == '\0')) {
newRule->port2 = -1;
return newRule;
}
if (*pos != '-') {
free(newRule);
return NULL;
}
pos++;
pos = parsePort (&(newRule->port2), pos);
if ((pos == NULL) || (newRule->port2 == -1)) {
free(newRule);
return NULL;
}
if (newRule->port2 <= newRule->port1) {
free(newRule);
return NULL;
}
if ((*pos == '\n') || (*pos == '\0')) {
return newRule;
}
free(newRule);
return NULL;
}
Is there a reason why this function takes just that one argument?
I ask, because for all intents and purposes, it would appear that you have code in main() that puts two strings together.
And then code in readRule() to pick them apart again.
Is the function signature forced upon you?
no nothing is forced, we got given the skeleton code to make the server and then we can edit it as we wish
i might start again from the code we were given and do it logically because its a mess right now
Any type of error or just it's not giving results you want
I am quite happy to help.
But looking at the code, I honestly think you are capable yourself.
before it was just not giving the results i wanted but now im getting could not connect for some reason, i think ill start again
i havent done anything 😭
So the main problem is protocol
Just copy the code put that in chat gpt and ask why it isn't working
bro chatgpt is what messed up my code in the first place
its overcomplicating it
alright ive started again
servers running
im gonna copy over all the helper functions from my prev assignment that i need
Here's one small suggestion to clear up the code.
Rather than doing a malloc at the start of readRule() and then having to free it every time you an early return, create a stack variable instead.
Then do the malloc at the end of the function and "move" the data from the stack variable to the heap variable.
i see
ive got these two files from solns from the last assignment
but i dont know what the difference between them is
as in
they both have a readrule function
nvm they are the same
i just copied one of them
Can you show the declaration of firewallRule_t ?
But bro where did you end that very first yellow 🟡 bracket
this?
its just not included in the ss
How about this as the function sig?
/*
* function readRule(addr, port)
*
* examples:
* addr = "110.101.111.123" port="34"
* addr = "110.101.111.123-110.101.111.254" port="34"
* addr = "110.101.111.123-110.101.111.254" port="34-45"
*/
struct firewallRule_t* readRule(const char* addr, const char* port)
{
}
Anything wrong with this?
You understand the requirements better than I do.
I wonder for instance if the second example is valid.
If you specify an IP range, should the ports also be a range?
And should the range of both be identical?
x addresses == x ports
Well what is he up to an application or something
If it's from the host side then
No.. sorry that's not gonna work
i think so yes
this was my friends one
ive cleaned up errors
now i can start
What's ur age am I messing with someone above 22 or you are teen
nah im 19
so for this do i need to change the processrequest function to read the rule and add it if its valid?
Well I am 16(1/2) and know the basics started a month ago.try me gpt I'm good at that
#include <stdio.h>
#include <string.h>
// Assuming you have a data structure to store firewall rules
// For example, an array of strings
#define MAX_RULES 100
char firewallRules[MAX_RULES][100]; // Assuming rules are strings of maximum length 100
int ruleCount = 0;
// Function to check if a rule is valid
int isValidRule(const char *rule) {
// Implement your logic to check if 'rule' is a valid firewall rule
// Return 1 if valid, 0 otherwise
// You might want to check the syntax, keywords, etc.
// Example: Check if the rule contains keywords like "allow" or "deny"
// For simplicity, let's assume any non-empty string is valid
return (strlen(rule) > 0);
}
// Function to add a rule to the set of firewall rules
void addRule(const char *rule) {
if (isValidRule(rule) && ruleCount < MAX_RULES) {
strcpy(firewallRules[ruleCount], rule);
ruleCount++;
printf("Rule added\n");
} else {
printf("Invalid rule\n");
}
}
int main() {
// Example usage
addRule("allow tcp from any to any");
addRule("deny udp from 192.168.1.1 to any");
// You can add more rules or use this in your program
return 0;
}
just reeed as an example
or
If you want to implement a client-server application where both the client and server communicate online, you'll need to set up a network connection between them. One common approach is to use sockets for communication. Here's a simple example that combines server and client functionality using sockets in C.
Firstly, let's create a simple server:
// server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define PORT 12345
#define MAX_RULES 100
char firewallRules[MAX_RULES][100]; // Assuming rules are strings of maximum length 100
int ruleCount = 0;
int isValidRule(const char *rule) {
// Implement your rule validation logic here
return (strlen(rule) > 0);
}
void addRule(const char *rule) {
if (isValidRule(rule) && ruleCount < MAX_RULES) {
strcpy(firewallRules[ruleCount], rule);
ruleCount++;
printf("Rule added\n");
} else {
printf("Invalid rule\n");
}
}
int main() {
int serverSocket, clientSocket;
struct sockaddr_in serverAddr, clientAddr;
socklen_t addrLen = sizeof(clientAddr);
// Create socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
perror("Error creating socket");
exit(EXIT_FAILURE);
}
// Bind to a specific port
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = INADDR_ANY;
serverAddr.sin_port = htons(PORT);
if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {
perror("Error binding");
exit(EXIT_FAILURE);
}
// Listen for incoming connections
if (listen(serverSocket, 5) == -1) {
perror("Error listening");
exit(EXIT_FAILURE);
}
printf("Server listening on port %d\n", PORT);
// Accept incoming connections
clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &addrLen);
if (clientSocket == -1) {
perror("Error accepting connection");
exit(EXIT_FAILURE);
}
// Receive data from the client
char buffer[1024];
recv(clientSocket, buffer, sizeof(buffer), 0);
// Process the received data (assuming it's a rule to add)
addRule(buffer);
// Close sockets
close(clientSocket);
close(serverSocket);
return 0;
}
i think i did most of it
but
now ive got a logic error
void *processRequest(void *args) {
struct threadArgs_t *threadArgs = (struct threadArgs_t *) args;
char buffer[BUFFERLENGTH];
int n;
bzero(buffer, BUFFERLENGTH);
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
// Assuming the rule starts after 'A '
struct firewallRule_t *newRule = readRule(buffer + 2);
if (newRule != NULL) {
addFirewallRule(newRule); // Add the new rule to the linked list
n = write(threadArgs->newsockfd, "Rule added\n", strlen("Rule added\n"));
} else {
n = write(threadArgs->newsockfd, "Invalid rule\n", strlen("Invalid rule\n"));
}
if (n < 0)
error("ERROR writing to socket");
// Proper thread termination and cleanup
serverThreads[threadArgs->threadIndex].status = THREAD_FINISHED;
pthread_cond_signal(&threadCond);
close(threadArgs->newsockfd); // Avoid memory leak
free(threadArgs);
pthread_exit(&returnValue);
}
The pthread_exit function should be passed the address of the variable holding the thread's return value, not the address of the variable holding the return value itself. You should replace pthread_exit(&returnValue); with pthread_exit(NULL); because it seems like you are not using returnValue in your code.
Make sure the readRule function returns a valid struct firewallRule_t*. If readRule returns NULL even when the rule is valid, it could lead to the "Invalid rule" branch being taken incorrectly.
are those the two problems?
likely
try this side way
void *processRequest(void *args) {
struct threadArgs_t *threadArgs = (struct threadArgs_t *)args;
char buffer[BUFFERLENGTH];
int n;
bzero(buffer, BUFFERLENGTH);
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
// Assuming the rule starts after 'A '
struct firewallRule_t *newRule = readRule(buffer + 2);
if (newRule != NULL) {
addFirewallRule(newRule); // Add the new rule to the linked list
n = write(threadArgs->newsockfd, "Rule added\n", strlen("Rule added\n"));
} else {
n = write(threadArgs->newsockfd, "Invalid rule\n", strlen("Invalid rule\n"));
}
if (n < 0)
error("ERROR writing to socket");
// Proper thread termination and cleanup
serverThreads[threadArgs->threadIndex].status = THREAD_FINISHED;
pthread_cond_signal(&threadCond);
close(threadArgs->newsockfd); // Avoid memory leak
free(threadArgs);
pthread_exit(NULL); // Corrected line
}
its the file location right?
yh thats fine
something wrong with this
void *processRequest(void *args) {
struct threadArgs_t *threadArgs = (struct threadArgs_t *) args;
char buffer[BUFFERLENGTH];
int n;
bzero(buffer, BUFFERLENGTH);
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
// Find the start of the actual rule after 'A '
char *ruleStart = strchr(buffer, ' ');
if (ruleStart != NULL) {
ruleStart++; // Move past the space to the start of the rule
} else {
ruleStart = buffer; // Fallback if no space found
}
struct firewallRule_t *newRule = readRule(ruleStart);
if (newRule != NULL) {
addFirewallRule(newRule); // Add the new rule to the linked list
n = write(threadArgs->newsockfd, "Rule added\n", strlen("Rule added\n"));
} else {
n = write(threadArgs->newsockfd, "Invalid rule\n", strlen("Invalid rule\n"));
}
if (n < 0)
error("ERROR writing to socket");
// Proper thread termination and cleanup
serverThreads[threadArgs->threadIndex].status = THREAD_FINISHED;
pthread_cond_signal(&threadCond);
close(threadArgs->newsockfd); // Avoid memory leak
free(threadArgs);
pthread_exit(&returnValue);
}
there might be an issue with the readRule function or the way the rule is constructed
In this part of your code:
struct firewallRule_t *newRule = readRule(ruleStart);
Make sure that the readRule function is correctly implemented to parse the rule from the provided string (ruleStart). If the readRule function is returning NULL, it means that it couldn't successfully parse a valid rule from the input string.
provide more details about the readRule function, the expected format of the rule, and any error messages you receive.
details about the readRule function,
struct firewallRule_t *readRule (char * line) {
struct firewallRule_t *newRule;
char *pos;
// parse IP addresses
newRule = malloc (sizeof(struct firewallRule_t));
pos = parseIPaddress (newRule->ipaddr1, line, true);
if ((pos == NULL) || (newRule->ipaddr1[0] == -1)) {
free (newRule);
return NULL;
}
if (*pos == '-') {
// read second IP address
pos = parseIPaddress (newRule->ipaddr2, pos+1, true);
if ((pos == NULL) || (newRule->ipaddr2[0] == -1)) {
free (newRule);
return NULL;
}
if (compareIPAddresses (newRule->ipaddr1, newRule->ipaddr2) != -1) {
free(newRule);
return NULL;
}
}
else {
newRule->ipaddr2[0] = -1;
}
if (*pos != ' ') {
free(newRule);
return NULL;
}
else pos++;
// parse ports
pos = parsePort (&(newRule->port1), pos);
if ((pos == NULL) || (newRule->port1 == -1)) {
free(newRule);
return NULL;
}
if ((*pos == '\n') || (*pos == '\0')) {
newRule->port2 = -1;
return newRule;
}
if (*pos != '-') {
free(newRule);
return NULL;
}
pos++;
pos = parsePort (&(newRule->port2), pos);
if ((pos == NULL) || (newRule->port2 == -1)) {
free(newRule);
return NULL;
}
if (newRule->port2 <= newRule->port1) {
free(newRule);
return NULL;
}
if ((*pos == '\n') || (*pos == '\0')) {
return newRule;
}
free(newRule);
return NULL;
}
might be something wrong with this asw
lets mentioned everyone in the chat room help me to get more (actually i m helping you)
@brazen cargo need hel here
ur friend?
@brazen cargo@pulsar pewter@red tiger@woven narwhal need hel here guys
nah just some random pro
@indigo holly@hollow fox@autumn bridge need help if you can plz .someone got real trouble here
@nocturne coyote here if you
@nocturne coyote Adding a rule to the stored rules. This request expects a string which contains a firewall rule as specified in exercise 1. If the rule is valid, the rule is added the set of firewall rules. The server returns the string Rule added if the rule has been added, and Invalid rule if the string is not a valid rule. thats the problem
struct firewallRule_t
{
uint32_t ipaddr1;
uint32_t ipaddr2;
uint16_t port1;
uint16_t port2;
};
struct firewallRule_t* readRule(const char* addr, const char* port);
void printRule(const struct firewallRule_t* rule);
int main(int argc, char** argv)
{
if (argc < 6) {
fprintf(stderr, "Usage: %s hostname port A rule\n", ...
It's using a union and a bit-field for IPv4 encoding, though.
Are you familiar with those?
Code was too large for Discord and I am not paying for Nitro.
screen shot is free i think
ss == no C&P 😢
well what you think the networking is also added in this program is this the level .intermediate or expert
in what lvl you got problem like this
I think this is possibly wrong, btw:
It's probably either uint8_t ipaddr1[4].
Or more likely uint32_t ipaddr1.
well its not jojn sina bcz u cant see that
whats this?
Your readRule() function?
That was the problem you couldn't solve, IIRC.
Or had you moved on to the next problem?
yeah i mean i’m not sure what’s not working
just that it’s giving invalid rule
is that the fixed version or does it show what’s going wrong
No.
@steady whale Improved version
https://godbolt.org/z/1c1jTb6ej
It now detects "cruft" at the end of the string.
E.g. "110.101.111.123-110.101.111.254abc"
Where it would previously just happily stop scanning the string at the last '4' and ignore whatever was left in the buffer.
struct firewallRule_t
{
uint32_t ipaddr1;
uint32_t ipaddr2;
uint16_t port1;
uint16_t port2;
};
struct firewallRule_t* readRule(const char* addr, const char* port);
void printRule(const struct firewallRule_t* rule);
int main(int argc, char** argv)
{
if (argc < 5) {
fprintf(stderr, "Usage: %s hostname port A rule\n", ...
shd i copy paste this into my client code and see if it works then
I think you should try to understand what it does.
Are you able to follow the logic?
You only need to look at the readRule() function.
Happy to answer questions and talk you through it.
yeah i understand that its splitting it up into the different sections u were talking about earlier
.
now do i need the server to read these and check if they are acceptable?
https://godbolt.org/z/8ETvqbq7M
Further revisions:
- printing to stderr
- checks if addr1 < addr2
- checks if port1 < port2
- checks if address range == port range
struct firewallRule_t
{
uint32_t ipaddr1;
uint32_t ipaddr2;
uint16_t port1;
uint16_t port2;
};
struct firewallRule_t* readRule(const char* addr, const char* port);
void printRule(const struct firewallRule_t* rule);
int main(int argc, char** argv)
{
if (argc < 5) {
fprintf(stderr, "Usage: %s hostname port A rule\n", ...
As per the requirements here: #1173011782588170350 message
Sure.
Does it build with the rest of your code?
im getting this rather than invalid rule now
You are passing arguments arg[4] and argv[5] to this function, right?
See the main() in the CE code I provided.

wait i only provided 4 arguments there
nice i dont get an error now
i just need it to say rule added rather than outputting this info right
So you get memory location now
No, that's the hex representation of the IP address
No, it's not.
6e = 110
65 = 101
6f = 111
7b = 123
do i need to actually send this to the server now
Try
and receive the response
// turn
printf("0x%x, %u\n", rule->ipaddr1, rule->port1);
//into
printf("%d, %u\n", rule->ipaddr1, rule->port1);
Well makes sense
Integer representations of an IP address are not very readable, though.
Well then memory location is also represent in this format isn't it?
Just don't call printRule().
I guess you must have copied that too?
yeah i did
The other bits are printed from my main().
So I guess you copied that too.
Well does it also work on html
The problem is it possible to get that done on it
@steady whale Has your question been resolved? If so, type !solved :)
@north spear i think the adding rule is working now tysm
dyu have any idea why the server result says error
thats after i run the test file ive been given
thats where the msg is coming from
ive tried asking ppl doing the hwk, u dont have much info about it
so its hard to say
res=`diff $clientOut $successFile 2>&1`
So the output of your client program does not match the expected output.
So you happen to know what is inside successFile ?
This is nothing to do with readRule().
There is something else not right with your code.
From the assignment:
The server returns the string "Rule added" is the rule has been added, and "Invalid rule" if the string is not a valid rule.
Could it be that your client is asked to add an invalid rule, but you're not printing "Invalid rule"?
i tried spamming some numbers in and it did say invalid rule
but im not sure if its working EXACTLY right cause i dont have any testcases
when i "make" in the terminal does it automatically update these output files?
if not, they could be old
I can only guess.
I honestly don't know what you are dealing with here.
Did you write both server and client?
Or is the server provided?
Well try to put else statement because you got two cases
I'm still stuck on the basics

After return 0(;)
Couldn't help but notice. From the assignment:
147.188.193.0-147.188.194.255 21-22
The address range is MUCH larger than the port range.
Maybe you should take out this check from readRule()
uint32_t addr_diff = addr2.raw - addr1.raw;
uint32_t port_diff = port2 - port1;
if (addr_diff != port_diff) {
fprintf(stderr, "Address range not the same as port range\n");
return NULL;
}
Because it would appear that these two strings should be considered valid?
Return null is same as 0?
i just made a testcase file
and ran it and it worked on them
so i should be good?

Yes, but NULL is nicer because we are supposed to return a pointer and not an int.

If this were C++ we would return nullptr.
OMG IT WORKED
I HAD "rule added\n"
not just rule added
omg
on god ur a goat bro @north spear
God no.
No payment of any kind, please.
Just a "thanks" will do. And I got that alr.
hahaha
thats 1 of 4 tasks completed 😭 but im just glad ive got something to work
ive spent wayy too many hours on this
to submit nothing
What other skill you got except flathead and c
The question remains; do you understand the code?
Because you will need to defend that code when probed.
can u give me a brief overview of what u did
Type solved
Not yet
union ipv4addr
{
uint32_t raw;
struct {
uint32_t oct4 : 8;
uint32_t oct3 : 8;
uint32_t oct2 : 8;
uint32_t oct1 : 8;
} p;
};
Do you know what this union does?
Oct 1 the date?
oct = octet
u can store stuff in the same memory location?
Yes, all members of the union occupy the same (stack-) memory location.
This union has two members.
- a 32 bit unsigned integer.
- a bit-field of a 32 bit unsigned integer
Do you understand bit-fields?
is it to do with memory management, command line arguments, file handling or concurrency
thats all ive learnt
struct {
uint32_t oct4 : 8;
uint32_t oct3 : 8;
uint32_t oct2 : 8;
uint32_t oct1 : 8;
};
The type of this struct is a 32 bit unsigned integer.
But it's been "partitioned" off into 4 parts of 8 bits each.
One for each octet in an IPv4 address.
It's no coincidence that 4 * 8 = 32 bits.
How long ago u started learning C
So when you write
addr1.p.oct1 = 101;
You are effectively writing just to highest byte of an unsigned int.
hm yes
U in computer engineering
and this helps us compare to the rule easier?
maths and cs at uni
Software?
nah just computer science
this is the first assignment ive struggled on this bad lmao
@steady whale Do you understand sscanf()?
It's my second year in clg
Yey I know scanf for getting inputs from user
Well I'm the third guy
no not really
For taking the value from the user
that's scanf() you are thinking about.
sscanf() allows you to decode a string.
In this case the strings passed to readRule().
So the 🥇 s reference to string
Bro recommend the book or source of C
Where to learn
Let's look at the address string first.
This string can be an address, or it can be an address range.
We need to be greedy and try scanning a range first.
If the string is not a range, then we try just reading a single address.
i have to go to the shops for a bit but if u explain ill definitely read when im back
Age and field
Grocery time
sscanf() (like scanf()) will return the number of parameters that it succesfully managed to get from the string.
So in in the case of the address range, we expect there to be 8 integers extracted. One for each octet for two addresses.
Hence the if (sscanf(....) == 8)
If we don't get 8 values from the string, then we will try decoding just a single address.
But even then we still need 4 octets.
So we try else if (sscanf(...) == 4)
And if that does not work, then sorry to say, but argument addr that we passed to readRule() is just not valid at all.
sscanf() is great, but there is a drawback.
Imagine parameter addr reading something silly like "147.188.192.41abc".
If you just did
char* addr = "147.188.192.41abc";
if (sscanf(addr, "%u.%u.%u.%u", &a11, &a12, &a13, &a14) == 4) {
puts("success");
}
Then you will find that this prints "success".
That is because it was able to extract 4 octets from that string. It totally ignores the "abc" that appears behind those octets.
We don't want that.
\n
[FIXED - copy and paste error]
One way to detect silly trailing nonsense is to use the "%n" field
From https://cplusplus.com/reference/cstdio/scanf/
As a last field to our sscanf() we are going to get sscanf() to tell us how many characters it processed.
So for a string like "147.188.192.41", the number of characters processed would be 14 chars.
But if the string read "147.188.192.41abc", the numbers of characters processed would also be 14, because it would stop at processing just the IP address. It needs to scan 4 integers separated with full stops and it manages to do exactly that from this string.
So if we instead did:
char* addr = "147.188.192.41abc";
if (sscanf(addr, "%u.%u.%u.%u%n", &a11, &a12, &a13, &a14, &len) == 4) {
if ((size_t)len != strlen(addr)) {
fprintf(stderr, "There are more characters in the buffer than expected\n");
return NULL;
}
}
We would detect that there are characters still in our buffer ("abc") that we did not process.
Because strlen("147.188.192.41abc") > 14).
And therefore the string does not conform to the expected format.
I honestly think that understanding these building blocks that I just explained, the rest of the function should start to make sense.
Just follow the breadcrumbs.
Sorry, are you asking me?
What are you asking?
What did I use to learn these skills?
I learned C a looong time ago. In university. A very old version of C in fact.
I never used it much.
As soon as I left uni, I became quite proficient in C++ over the next 25 years.
But recently, I have started getting interested in C again.
I had to re-learn a few things. But most of the time I just pick it up (-again) from other people here.
And from articles on the internet, incl. Stack Overflow questions.
I'm 16(1/2) 2nd year CLG student you 22 work in anonymous group? Or gill Bates
Never worked for Microsoft. I consider them evil.
I wouldn't work for certain companies.
Microsoft, Google, Apple, Facebook, X. 👎
I wouldn't work for "defence" companies either.
I don't want to write software that kills people.
It means..All the time I disturbing David bomal age man.sorry sir.
Well I'm interested in AI to defend what these sharks are upto
As you mentioned a long time and 25 year stuff u might be 35+
If you want to make a career out of writing software, the best advice I can give you is:
Watch what other, more experienced people do and learn from them.
It could mean learning bad habbits, maybe.
But someone down the line at some point will put you right.
Make mistakes, learn from them.
Don't be afraid to form your own opinion either.
Well I also know what are they upto bcz it doesn't make sense as it's been a long time for humans are on 🌎 and in just last 200 years they find what technology is .no no no they are up to something big.
Well I don't want to put religion in that but they are working for the one man they believe him to be good .recently I watch another video where a person is describing how
1 •/• are controlling earth .might you know about ∆ the sign .or freemassions
Or stuff like that
@north spear and 666 sign
@steady whale I am going to be out walking the dog for the next couple of hours.
If there are any further questions, just leave them here.
I will check back later.
what dyu want me to do broski, its my homework 🤣 dont look at it if its boring
void *processRequest(void *args) {
struct threadArgs_t *threadArgs = (struct threadArgs_t *) args;
char buffer[BUFFERLENGTH];
int n;
bzero(buffer, BUFFERLENGTH);
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
char commandType;
sscanf(buffer, "%c ", &commandType);
// Find the start of the actual rule after the command character
char *ruleStart = strchr(buffer, ' ');
if (ruleStart != NULL) {
ruleStart++; // Move past the space to the start of the rule
} else {
ruleStart = buffer; // Fallback if no space found
}
if (commandType == 'A') {
struct firewallRule_t *newRule = readRule(ruleStart);
if (newRule != NULL) {
addFirewallRule(newRule); // Add the new rule to the linked list
n = write(threadArgs->newsockfd, "Rule added\n", strlen("Rule added\n"));
} else {
n = write(threadArgs->newsockfd, "Invalid rule\n", strlen("Invalid rule\n"));
}
} else if (commandType == 'D') {
struct firewallRule_t *ruleToDelete = readRule(ruleStart);
if (ruleToDelete != NULL) {
if (deleteRule(ruleToDelete)) {
n = write(threadArgs->newsockfd, "Rule deleted\n", strlen("Rule deleted\n"));
} else {
n = write(threadArgs->newsockfd, "Rule not found\n", strlen("Rule not found\n"));
}
free(ruleToDelete);
} else {
n = write(threadArgs->newsockfd, "Invalid rule\n", strlen("Invalid rule\n"));
}
}
if (n < 0)
error("ERROR writing to socket");
// Proper thread termination and cleanup
serverThreads[threadArgs->threadIndex].status = THREAD_FINISHED;
pthread_cond_signal(&threadCond);
close(threadArgs->newsockfd); // Avoid memory leak
free(threadArgs);
pthread_exit(&returnValue);
}
@north spear im trying to do as much of this assignment before tmrw as possible so ill read ur stuff later
but now im trying to do the delete one
but whenever i try call it using D it keeps saying rule added rather than recognising that its a delete function
i thought ive written it fine above, with the two ifs
is there something wrong with it
do i need to change anything on the client side? i didnt think id need to as its just checking if the rules are the same and then deleting them
Looking...
ty
Incidentally, complete aside.
Does bzero() initialise the buffer to all zeroes?
yh it does
Well, just for information, so does
char buffer[BUFFERLENGTH] = {0};
So unless bzero() is used elsewhere, that function may be redundant.
(but it's not wrong either)
Yeah. We may need to instrument the code to find out where we are zagging instead of zigging.
Hang on...
let me know if u want to see my deleterule/compare rule(prewritten for me) functions but i dont think thats the problem rn
Can you add this function to your code?
void printBytes(const char* buffer, int size)
{
for (const char *i = buffer, *iend = i + size; i < iend; ++i) {
printf("%02x ", *i);
}
printf("\n");
}
Then after reading the bytes, call it
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
printBytes(buffer, n); // Add just this line to your code
I'd like to see what this prints, please.
Later on, when we're done you may want to remove this function again.
If you want.
so ill add the function and then call it after the char commandType: bit
after its scanned?
oh u want me to replace the bit
replace the bzero bit?
No replacement.
We're just adding something.
Temporarily.
This is unrelated to bzero().
Ah, you misunderstood.
i didnt get what u mean by after reading the bytes call it
I have added a comment to my previous snippet.
Read it again.
Mention your 📍
oh im dumb hahaha
I could have been clearer.
This is on the server side though, isn't it? (the code we're looking at)
Where do you run the server?
Does that terminal not show what we're printing then?
Obv you must rebuild the server.
You did (re-)build the server, right?
Stop server.
Run make (or whatever)
Start server.
but how do i stop it 😭
I think you did. Using CTRL-C.
It appears you run the server interactively.
hmm theres nothing in my server output file or in the terminal
i stopped it and ran it again
yeah, but did you build (compiled) the code in between?
Making changes to source code requires re-making the binary.
Hmmmm 🤔
do you think i should do the checking question before the delete one
my friend said he used the checking one for the delete one
so maybe i should do it in order
this looks harder than the delete rule though
void *processRequest(void *args) {
struct threadArgs_t *threadArgs = (struct threadArgs_t *) args;
char buffer[BUFFERLENGTH];
int n;
bzero(buffer, BUFFERLENGTH);
n = read(threadArgs->newsockfd, buffer, BUFFERLENGTH - 1);
if (n < 0)
error("ERROR reading from socket");
// Find the start of the actual rule after 'A '
char *ruleStart = strchr(buffer, ' ');
if (ruleStart != NULL) {
ruleStart++; // Move past the space to the start of the rule
} else {
ruleStart = buffer; // Fallback if no space found
}
struct firewallRule_t *newRule = readRule(ruleStart);
if (newRule != NULL) {
addFirewallRule(newRule); // Add the new rule to the linked list
n = write(threadArgs->newsockfd, "Rule added", strlen("Rule added"));
} else {
n = write(threadArgs->newsockfd, "Invalid rule", strlen("Invalid rule"));
}
if (n < 0)
error("ERROR writing to socket");
// Proper thread termination and cleanup
serverThreads[threadArgs->threadIndex].status = THREAD_FINISHED;
pthread_cond_signal(&threadCond);
close(threadArgs->newsockfd); // Avoid memory leak
free(threadArgs);
pthread_exit(&returnValue);
}
``` This is my original code for adding rule, is there an easier way to implement the delete than what i did
@steady whale Has your question been resolved? If so, type !solved :)
Sorry, was AFK.
There is no deletion happening here.
The earlier code was more comprehensive.
I don't think we're getting to the bottom of this unless we get this server to print to the terminal.
I don't understand why it wouldn't.
Can you print anything from its main() function?
Just to check that printing to the terminal should work.
yeah i was just wondering if i should start again with the deletion cause i don’t know what’s going wrong w it

