#reading a firewall rule not working

393 messages · Page 1 of 1 (latest)

steady whale
#

i want rules of the form ./client localhost 2201 A 110.101.111.123 34 to be added but right now only rules of this form are being added ./client localhost 2201 "110.101.111.123 34". ive tried changing my code but its not working please help

keen cargoBOT
#

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

Screenshots!

Your message appears to contain screenshots but no code. Please send code and error messages in text instead of screenshots if applicable!

steady whale
#

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

north spear
#

Can you post what one might reasonably expect parameter line to read?
Maybe you have an example.

steady whale
north spear
#

So where does your 'A' come into play?

steady whale
#

sorry i should've specified

#

so is there something wrong in my client code?

#

that isnt accounting for this A

north spear
#

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.

steady whale
#

can you try help me with this today @north spear

#

i’m not too sure what to do

north spear
#

What does your main() function look like right now?

steady whale
north spear
#

Client side

steady whale
#
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

north spear
#

This is homework, right?
We are bound by the wording of the assignment.

steady whale
#

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

north spear
#

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)

steady whale
#

mhm yeah

north spear
#

You are combining arg4 and arg5 into one string.
Is that so you can pass just that one string to readRule()?

steady whale
#

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;
}
north spear
#

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?

steady whale
#

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

limber frigate
#

Any type of error or just it's not giving results you want

north spear
#

I am quite happy to help.
But looking at the code, I honestly think you are capable yourself.

steady whale
#

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

limber frigate
#

So the main problem is protocol

#

Just copy the code put that in chat gpt and ask why it isn't working

steady whale
#

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

north spear
#

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.

steady whale
#

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

north spear
#

Can you show the declaration of firewallRule_t ?

limber frigate
#

But bro where did you end that very first yellow 🟡 bracket

steady whale
north spear
#

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

limber frigate
#

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

steady whale
#

this was my friends one

#

ive cleaned up errors

#

now i can start

limber frigate
#

What's ur age am I messing with someone above 22 or you are teen

steady whale
#

nah im 19

#

so for this do i need to change the processrequest function to read the rule and add it if its valid?

limber frigate
#

Well I am 16(1/2) and know the basics started a month ago.try me gpt I'm good at that

steady whale
#

fair enough

#

@north spear is this a good outline

limber frigate
#

#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;

}

steady whale
#

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);
}

limber frigate
#

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.

steady whale
#

are those the two problems?

limber frigate
#

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

}

steady whale
#

gpt isnt doing the job 😭

#

still invalid rule

limber frigate
#

its the file location right?

steady whale
#

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);
}
limber frigate
#

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.

steady whale
#

bro ive got gpt 😭 its not working

#

i need someone to acc look over it

limber frigate
#

details about the readRule function,

steady whale
#
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

limber frigate
#

lets mentioned everyone in the chat room help me to get more (actually i m helping you)

#

@brazen cargo need hel here

steady whale
#

ur friend?

limber frigate
#

@brazen cargo@pulsar pewter@red tiger@woven narwhal need hel here guys

limber frigate
#

@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

north spear
#
#

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.

limber frigate
#

screen shot is free i think

north spear
#

ss == no C&P 😢

limber frigate
#

in what lvl you got problem like this

north spear
# steady whale this?

I think this is possibly wrong, btw:
It's probably either uint8_t ipaddr1[4].
Or more likely uint32_t ipaddr1.

limber frigate
#

well its not jojn sina bcz u cant see that

steady whale
north spear
#

Your readRule() function?

#

That was the problem you couldn't solve, IIRC.
Or had you moved on to the next problem?

steady whale
#

just that it’s giving invalid rule

#

is that the fixed version or does it show what’s going wrong

north spear
#

@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.

steady whale
north spear
#

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.

steady whale
#

yeah i understand that its splitting it up into the different sections u were talking about earlier

steady whale
#

now do i need the server to read these and check if they are acceptable?

north spear
#

https://godbolt.org/z/8ETvqbq7M

Further revisions:

  • printing to stderr
  • checks if addr1 < addr2
  • checks if port1 < port2
  • checks if address range == port range
steady whale
#

tysm

#

so i need to get the server to verify this now?

north spear
#

Sure.
Does it build with the rest of your code?

steady whale
#

im getting this rather than invalid rule now

limber frigate
#

The flathead

north spear
#

You are passing arguments arg[4] and argv[5] to this function, right?

#

See the main() in the CE code I provided.

limber frigate
steady whale
#

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

limber frigate
#

So you get memory location now

north spear
limber frigate
#

Yeah.its the memory location

#

Is there something more beneath that

north spear
#

No, it's not.

6e = 110
65 = 101
6f = 111
7b = 123
limber frigate
#

After 34

#

How to change that to numbers

steady whale
#

do i need to actually send this to the server now

limber frigate
#

Try

steady whale
#

and receive the response

north spear
limber frigate
#

Well makes sense

north spear
#

Integer representations of an IP address are not very readable, though.

limber frigate
#

Well then memory location is also represent in this format isn't it?

steady whale
#

omg it says rule added

#

but i need to get rid of this extra info

limber frigate
#

Yeah

#

U got it

north spear
#

Just don't call printRule().
I guess you must have copied that too?

steady whale
#

yeah i did

north spear
#

The other bits are printed from my main().
So I guess you copied that too.

steady whale
#

theres some references to print tho

#

should i get rid of them asw\

limber frigate
#

Well does it also work on html

#

The problem is it possible to get that done on it

keen cargoBOT
#

@steady whale Has your question been resolved? If so, type !solved :)

steady whale
#

@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

north spear
#
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.

steady whale
#

i thought it would be fine if its the same

#

is it not the same output?

north spear
#

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"?

steady whale
#

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

north spear
#

I can only guess.
I honestly don't know what you are dealing with here.

#1173011782588170350 message

Did you write both server and client?
Or is the server provided?

limber frigate
#

Well try to put else statement because you got two cases

#

I'm still stuck on the basics

limber frigate
north spear
#

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?

limber frigate
#

Return null is same as 0?

steady whale
#

i just made a testcase file

#

and ran it and it worked on them

#

so i should be good?

limber frigate
north spear
limber frigate
north spear
#

If this were C++ we would return nullptr.

steady whale
#

OMG IT WORKED

limber frigate
#

What

#

How

steady whale
#

I HAD "rule added\n"

#

not just rule added

#

omg

#

on god ur a goat bro @north spear

limber frigate
#

Well give him Treet or nitro lol

#

U r executing it on?

north spear
#

God no.
No payment of any kind, please.
Just a "thanks" will do. And I got that alr.

steady whale
#

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

limber frigate
#

What other skill you got except flathead and c

north spear
#

The question remains; do you understand the code?
Because you will need to defend that code when probed.

limber frigate
steady whale
limber frigate
#

Type solved

north spear
#

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?

north spear
#

oct = octet

steady whale
#

u can store stuff in the same memory location?

north spear
#

Yes, all members of the union occupy the same (stack-) memory location.

#

This union has two members.

  1. a 32 bit unsigned integer.
  2. a bit-field of a 32 bit unsigned integer
#

Do you understand bit-fields?

limber frigate
#

Can you share the source of c

#

I have the basics

limber frigate
#

The size

#

Occupied by the

steady whale
#

thats all ive learnt

north spear
#
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.

limber frigate
steady whale
#

3 weeks

#

and its not even a C module

north spear
#

So when you write

addr1.p.oct1 = 101;

You are effectively writing just to highest byte of an unsigned int.

steady whale
#

its an operating systems module

#

but we use C to help understand the concepts

limber frigate
#

U in computer engineering

steady whale
#

and this helps us compare to the rule easier?

steady whale
limber frigate
#

Software?

steady whale
#

nah just computer science

#

this is the first assignment ive struggled on this bad lmao

north spear
#

@steady whale Do you understand sscanf()?

limber frigate
#

It's my second year in clg

#

Yey I know scanf for getting inputs from user

#

Well I'm the third guy

steady whale
limber frigate
north spear
#

sscanf() allows you to decode a string.
In this case the strings passed to readRule().

limber frigate
#

So the 🥇 s reference to string

#

Bro recommend the book or source of C

#

Where to learn

north spear
#

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.

steady whale
#

i have to go to the shops for a bit but if u explain ill definitely read when im back

limber frigate
#

Age and field

north spear
#

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.

limber frigate
#

Forget something for me

#

Yeah the book of C

#

C for dummies?

north spear
#

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.

limber frigate
#

\n

north spear
#

[FIXED - copy and paste error]

limber frigate
#

Lowlight curvedtail

#

Well I got deathnote

#

Still typing

north spear
#

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.

limber frigate
north spear
#

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.

limber frigate
#

Well sorry

#

Just the source you used to build c skils

north spear
limber frigate
#

Yeah

#

Don't tell you got training from Snowden

north spear
#

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.

limber frigate
#

I'm 16(1/2) 2nd year CLG student you 22 work in anonymous group? Or gill Bates

north spear
#

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.

limber frigate
#

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+

north spear
#

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.

limber frigate
#

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

north spear
#

@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.

hollow fox
#

beginner C programmers parsing data manually

#

this thread is so boring

steady whale
#
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

north spear
#

Looking...

steady whale
#

ty

north spear
#

Incidentally, complete aside.
Does bzero() initialise the buffer to all zeroes?

steady whale
#

yh it does

north spear
#

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)

steady whale
#

oh okay i see

#

still not sure why my program wont recognise A or D

north spear
#

Yeah. We may need to instrument the code to find out where we are zagging instead of zigging.
Hang on...

steady whale
#

let me know if u want to see my deleterule/compare rule(prewritten for me) functions but i dont think thats the problem rn

north spear
#

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.

steady whale
#

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?

north spear
#

No replacement.
We're just adding something.
Temporarily.

This is unrelated to bzero().

steady whale
#

okok

#

how do i call it in the terminal?

#

ive added it

north spear
#

Ah, you misunderstood.

steady whale
#

i didnt get what u mean by after reading the bytes call it

north spear
#

I have added a comment to my previous snippet.
Read it again.

limber frigate
#

Mention your 📍

steady whale
#

oh im dumb hahaha

north spear
#

I could have been clearer.

steady whale
#

it doesnt print it

#

when i try delete

#

it just says rule added

north spear
#

This is on the server side though, isn't it? (the code we're looking at)
Where do you run the server?

steady whale
#

in a separate terminal

#

ive just got it running the entire time

north spear
#

Does that terminal not show what we're printing then?

#

Obv you must rebuild the server.

steady whale
#

should i stop the server and rerun it then

#

its not outputting anything

north spear
#

You did (re-)build the server, right?

steady whale
#

yeah im pretty sure ctrl c kills it

#

is there any other command i can try

north spear
#

Stop server.
Run make (or whatever)
Start server.

steady whale
#

but how do i stop it 😭

north spear
#

I think you did. Using CTRL-C.
It appears you run the server interactively.

steady whale
#

hmm theres nothing in my server output file or in the terminal

#

i stopped it and ran it again

north spear
#

yeah, but did you build (compiled) the code in between?

#

Making changes to source code requires re-making the binary.

steady whale
#

yeah the codes updated

north spear
#

Hmmmm 🤔

steady whale
#

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
keen cargoBOT
#

@steady whale Has your question been resolved? If so, type !solved :)

north spear
#

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.

steady whale