0% found this document useful (0 votes)
3 views151 pages

DCNL Codes

The document outlines the implementation of congestion control algorithms, specifically the Leaky Bucket and Token Bucket algorithms, detailing their processes and programming examples. It also discusses data encryption and decryption algorithms, including the Caesar Cipher, Vigenere Cipher, and RSA, along with their theoretical foundations and programming implementations. The results confirm the successful implementation of these algorithms.

Uploaded by

detachedward
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views151 pages

DCNL Codes

The document outlines the implementation of congestion control algorithms, specifically the Leaky Bucket and Token Bucket algorithms, detailing their processes and programming examples. It also discusses data encryption and decryption algorithms, including the Caesar Cipher, Vigenere Cipher, and RSA, along with their theoretical foundations and programming implementations. The results confirm the successful implementation of these algorithms.

Uploaded by

detachedward
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Ex. No.

4 Date:

CONGESTION CONTROL ALGORITHMS


AIM:
To implement the following Congestion Control Algorithms.
1. Leaky Bucket Algorithm.
2. Token Bucket Algorithm.

ALGORITHM:
LEAKY BUCKET:

1. Start
2. Set the bucket size or buffer size and equate it to counter value.
3. Set the output rate.
4. Check the size of the packet with the counter size.
5. If the packet size is less than the counter transmit else make it wait for counter to
reset.
6. Repeat the process until all the packets transmitted.
7. Reject the packets where its size is greater than bucket size.
8. Stop.

TOKEN BUCKET:

1. Start
2. A token is added at every time.
3. The bucket can hold at most b-tokens. If a token arrive when bucket is full it is
discarded.
4. When a packet of m-bytes arrived m-tokens are removed from the buckets and the
packet is sent to the network.
5. If less than n-tokens are available no tokens are removed from the buckets and the
packet is considered to be non-conformant.
6. The non-conformant packet may be enquired for subsequent transmission when
sufficient token have been accumulated in the bucket or the non-conformant packet
may be dropped.

THEORY:

LEAKY BUCKET:

The leaky bucket is an algorithm that may be used to determine whether some sequence
of discrete events conforms to defined limits on their average and peak rates or frequencies.
The leaky bucket algorithm is used in packet switched computer networks and
telecommunications networks to check that data transmissions, in the form of packets, conform
to defined limits on bandwidth and burstiness (a measure of the unevenness or variations in the
traffic flow). It can also be used as a scheduling algorithm to determine the timing of
transmissions that will comply with the limits set for the bandwidth and burstiness applied by
the network: see network scheduler.
PROGRAM:
LEAKY BUCKET:

#include<stdio.h>
#include<stdlib.h>
struct packet
{
int time;
int size;
} p[50];

int main()
{
int i,n,m,k=0;
int bsize,bfilled,outrate;
printf("enter the number of packets:");
scanf("%d",&n);
printf("enter packets in the order of their arrival time\n");
for(i=0;i<n;i++)
{
printf("enter the time and size:");
scanf("%d%d",&p[i].time,&p[i].size);
}
printf("enter the bucket size:");
scanf("%d",&bsize);
printf("enter the output rate:");
scanf("%d",&outrate);
m=p[n-1].time;
i=1;
k=0;
bfilled=0;
while(i<=m||bfilled!=0)
{
printf("\n\nAt time %d",i);
if(p[k].time==i)
{
if(bsize>=bfilled+p[k].size)
{
bfilled=bfilled+p[k].size;
printf("\n%d byte packet is inserted",p[k].size);
k=k+1;
}
else
{
printf("\n%d byte packet is discarded",p[k].size);
k=k+1;
}
}
if(bfilled==0)
{
The Leaky Bucket Algorithm is based on, and gets its name from, an analogy of a
bucket that has a hole in the bottom through which any water it contains will leak away at a
constant rate, until or unless it is empty. Water can be added intermittently, i.e. in bursts, but if
too much is added at once, or it is added at too high an average rate, the water will exceed the
capacity of the bucket, which will overflow. Hence, this leaky bucket determines whether
adding some amount of water would exceed or conform to a limit on the average rate at which
water can be added, set by the leak rate, and a limit on how much water can be added in a burst,
set by the depth of the bucket.

In network scenario we can control the output rate to be always less than a fixed rate in
a packet switched network where the size of each packet can be different by making use of a
counter and clock. At the tick of the clock, the counter is set to the amount of data that can be
output in one tick. The algorithm then checks the size of the frame at the front of the queue. If
the size is less than equal to the value of the counter, the packet is sent; if the size is greater
than or equal to the value of the counter, the packet is left in the queue and waits for the next
tick of the clock. The leaky bucket is used to implement traffic policing and traffic shaping in
Ethernet and cellular data networks. The algorithm can also be used to control metered-
bandwidth Internet connections to prevent going over the allotted bandwidth for a month,
thereby avoiding extra charges.

TOKEN BUCKET:

The token bucket is an algorithm used in packet switched computer networks and
telecommunications networks. It can be used to check that data transmissions, in the form of
packets, conform to defined limits on bandwidth and burstiness (a measure of the unevenness
or variations in the traffic flow). It can also be used as a scheduling algorithm to determine the
timing of transmissions that will comply with the limits set for the bandwidth and burstiness:
see network scheduler. +

The token bucket algorithm is based on an analogy of a fixed capacity bucket into which
tokens, normally representing a unit of bytes or a single packet of predetermined size, are added
at a fixed rate. When a packet is to be checked for conformance to the defined limits, the bucket
is inspected to see if it contains sufficient tokens at that time. If so, the appropriate number of
tokens, e.g. equivalent to the length of the packet in bytes, are removed ("cashed in"), and the
packet is passed, e.g., for transmission. The packet does not conform if there are insufficient
tokens in the bucket, and the contents of the bucket are not changed. Non-conformant packets
can be treated in various ways:

They may be dropped.

They may be enqueued for subsequent transmission when sufficient tokens have
accumulated in the bucket. They may be transmitted, but marked as being non-conformant,
possibly to be dropped subsequently if the network is overloaded.

A conforming flow can thus contain traffic with an average rate up to the rate at
which tokens are added to the bucket, and have a burstiness determined by the depth of the
bucket. This burstiness may be expressed in terms of either a jitter tolerance, i.e. how much
sooner a packet might conform (e.g. arrive or be transmitted) than would be expected from
the limit on the average rate, or a burst tolerance or maximum burst size, i.e. how much more
than the average level of traffic might conform in some finite period.
printf("\nNo packets to transmitted");
}
else if(bfilled>outrate)
{
bfilled=bfilled-outrate;
printf("\n %d bytes transferred",outrate);
}
else
{
printf("\n%d bytes transferred",bfilled);
bfilled=0;
}
printf("\n packets in the bucket %d byte",bfilled);
i++;
}
return 0;
}

OUTPUT:
PROGRAM:
TOKEN BUCKET:

#include <stdio.h>
#include <stdlib.h>
int main ()
{
int no_of_packets, storage, output_queue;
int input_pkt_size, token_bucket;
int packet_arrival = 0;
storage = 0;
//no_of_packets = 8;
//bucket_size = 10;
printf("\nEnter the intial bucket size: ");
scanf("%d", &token_bucket);
//input_pkt_size = 4;
for ( int i = 0; i < 10; i++ )
{
if (token_bucket != 30)
token_bucket += 1;
else
{
printf("Max token size reached");
token_bucket = 0;
}
printf("\nToken size = %d", token_bucket);
packet_arrival = rand () % 2;
if (packet_arrival == 1)
{
input_pkt_size = rand () % 10 + 1;
printf("\nPacket of size incoming: %d\n", input_pkt_size);
if (input_pkt_size <= token_bucket)
{
printf("\nPacket is sent");
token_bucket -= input_pkt_size;
}
else
puts("\nPacket is discarded");
}
else
continue;
}
return 0;
}
OUTPUT:
RESULT:

Thus the following Congestion Control Algorithms were implemented and outputs
were verified.
1. Leaky Bucket Algorithm.
2. Token Bucket Algorithm.
Ex. No: 5 Date:
DATA ENCRYPTION AND DECRYPTION ALGORITHMS

AIM:
To verify the following data encryption and decryption algorithms.
1. Caesar Cipher Algorithm
2. Vigenere Cipher Algorithm
3. RSA Authentication Algorithm

THEORY:

Cryptography is the science of secret writing is an ancient art; the first documented use
of cryptography in writing dates back to circa 1900 B.C. when an Egyptian scribe used non-
standard hieroglyphs in an inscription. It is no surprise, then, that new forms of cryptography
came soon after the widespread development of computer communications. In data and
telecommunications, cryptography is necessary when communicating over any untrusted
medium, which includes just about any network, particularly the Internet.

There are five primary functions of cryptography today:

1. Privacy/confidentiality: Ensuring that no one can read the message except the
intendedreceiver.

2. Authentication: The process of proving one's identity.

3. Integrity: Assuring the receiver that the received message has not been altered in
any wayfrom the original.

4. Non-repudiation: A mechanism to prove that the sender really sent this message.

5. Key exchange: The method by which crypto keys are shared between sender and
receiver.

CHARACTERISTICS OF CRYPTOGRAPHY:

1. Authentication
2. Data Privacy
3. Protection against Alteration
4. Non-repudiated Transfer of Information
5. Unobstructed Channel of Communication
PROGRAM:
CAESAR CIPHER ALGORITHM:

ENCRYPTION:

#include<stdio.h>
int main() {
char message[100], ch;
int i, key;
printf("Enter a message to encrypt: ");
gets(message);
printf("Enter key: ");
scanf("%d", &key);

for(i = 0; message[i] != '\0'; ++i){


ch = message[i];
if(ch >= 'a' && ch <= 'z')
ch = ch + key;
if(ch > 'z') {
ch = ch - 'z' + 'a' - 1;

message[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch + key;
if(ch > 'Z'){
ch = ch - 'Z' + 'A' - 1;
}
message[i] = ch;
}
}
printf("Encrypted message: %s", message);
return 0;
}

DECRYPTION:

#include<stdio.h>
int main() {
char message[100], ch;
int i, key;
printf("Enter a message to decrypt: ");
gets(message);
printf("Enter key: ");
scanf("%d", &key);
for(i = 0; message[i] != '\0'; ++i){
ch = message[i];
if(ch >= 'a' && ch <= 'z'){
ch = ch - key;
if(ch < 'a'){
CAESAR CIPHER ALGORITHM:

The Caesar cipher, also known as a shift cipher, is one of the simplest forms of
encryption. It is a cipher where each letter in the original message called the plain text is
replaced with a letter corresponding to a certain number of letters up or down in the alphabet.
For example, with a left shift of 3, D would be replaced by A, E would become B, and so on.
The method is namedafter Julius Caesar, who used it in his private correspondence.

The encryption can also be represented using modular arithmetic by first transforming
the letters into numbers, according to the scheme, A=0, B-1...Z-25. Encryption of a letter x by
a shift be described mathematically as:

E, (x (x+n) mod 26

Decryption can be described mathematically as:

D. (x) = (x-n) mod 26

ALGORITHM:

1. Start.

2. Get the message and number of shifts as input.

3. During encryption, each alphabet in the message is shifted to the respective number
ofshift and replaced by another alphabet, places down the line.

4. During decryption, each alphabet in the encrypted text is decremented to the


respectivenumber of shift and replaced by another alphabet, places up the line.

5. Stop the program.


ch = ch + 'z' - 'a' + 1;
}
message[i] = ch;
}
else if(ch >= 'A' && ch <= 'Z'){
ch = ch - key;
if(ch < 'A'){
ch = ch + 'Z' - 'A' + 1;
}
message[i] = ch;
}
}
printf("Decrypted message: %s", message);
return 0;
}

OUTPUT:
VIGNERE CIPHER ALGORITHM:

The Vignere Cipher is a method of encrypting alphabetic text by using a series of


interwoven Caesar Ciphers based on letters of a Keyword. It is a form of Polyalphabetic
Substitution.

The method was originally described by Glovan Battista Bellaso in 1553, later was
misattributed to Blaise de Vigenere and is widely known as Vigenere Cipher.

The Vigenere Cipher is a sequence with different shift values. To encrypt, a table of
alphabets can be used, termed a tabula recta, Vigenere square, or Vigenere table. It consists of
the alphabet written out 26 times in different rows, each alphabet shifted cyclically to the left
compared to the previous alphabet, corresponding to the 26 possible Caesar ciphers. At different
points in the encryption process, the cipher uses a different alphabet from one of rows.

ALGORITHM:

1. Start.

2. Get the message and key as input.

3. In encryption, the equivalent values of message and key is added.

4. Then the result gives the equivalent of a particular alphabet.

5. In decryption, the equivalent values of the alphabet encrypted get


subtracted from theequivalent values of the key.

6. Stop the program.


PROGRAM:
VIGENERE CIPHER ALGORITHM:

#include<stdio.h>
#include<string.h>

int main()
{
char msg[100],key[100];
int i, j;

printf("\nEnter the Message: ");


scanf("%s",msg);
printf("Enter the Key: ");
scanf("%s",key);

int msgLen = strlen(msg), keyLen = strlen(key);


char newKey[msgLen], encryptedMsg[msgLen], decryptedMsg[msgLen];

//generating new key


for(i = 0, j = 0; i < msgLen; ++i, ++j)
{
if(j == keyLen)
j = 0;
newKey[i] = key[j];
}
newKey[i] = '\0';

//encryption
for(i = 0; i < msgLen; ++i)
encryptedMsg[i] = ((msg[i] + newKey[i]) % 26) + 'A';
encryptedMsg[i] = '\0';

//decryption
for(i = 0; i < msgLen; ++i)
decryptedMsg[i] = (((encryptedMsg[i] - newKey[i]) + 26) % 26) + 'A';
decryptedMsg[i] = '\0';

printf("Original Message: %s", msg);


printf("\nKey: %s", key);
printf("\nNew Generated Key: %s", newKey);
printf("\nEncrypted Message: %s", encryptedMsg);
printf("\nDecrypted Message: %s", decryptedMsg);

return 0;
}
OUTPUT:
RIVEST SHAMIR ADLEMAN ALGORITHM (RSA):

RSA is one of the first practical cryptosystems and is widely used for secure data
transmission. In such a cryptosystem, the encryption key is public and differs from the
decryption key which is kept secret. In RSA, this asymmetry is based on the practical difficulty
of factoring problem. RSA is made of the initial letters of the surnames of Ron Rivest, Adi
Shamir and Leonard Adleman, who first publicly described the algorithm in 1977.

A user of RSA creates and then publishes a public key based on two large prime
numbers, along with an auxiliary value. The prime numbers must be kept secret. Anyone can
use the public key to encrypt a message. If the public key must be large enough only someone
with knowledge of the prim numbers can feasibly decode the message.

RSA is a relatively slow algorithm, and because of this it is less commonly used to
directly encrypt user data. More often, RSA passes encrypted shared keys for symmetric key
cryptography which in turn can perform bulk encryption-decryption operations a much higher
speed.

ARITHMETIC PROCESS:

RSA involves a public key and private key The public key can be known to everyone, it
is used to encrypt messages. Messages encrypted using the public key can only be decrypted
with theprivate key. The keys for the RSA algorithm are generated the following way:

1. Generate two large random primes, p and q, of equal size such that their product
npq isof the required bit length, e.g. 1024 bits.

2. Compute n = pq and (phi) - (p-1) (q-1). 3. Choose an integer e, 1 <e <phi, such that
gcd(e, phi) - 1.

3. Compute the secret exponent d, 1<d<phi, such that ed= 1 (mod phi).

4. The public key is (n, e) and the private key (d, p, q). Keep all the values d, p, q and
phi secret. [We prefer sometimes to write the private key as (n, d) because you need
the value of n when using d. Other times we might write the key pair as ((N, e), d).]

n is known as the modulus.

e is known as the public exponent or encryption exponent or just the exponent.

d is known as the secret exponent or decryption exponent.

RSA algorithm example:

Choose p=3 and q = 11

Compute n=p*q=3*11=33
PROGRAM:
RSA ALGORITHM:

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
long int p,q,n,t,flag,e[100],d[100],temp[100],en[100],j,i;
char m[100];
char msg[100];
int prime(long int);
void ce();
long int cd(long int);
void encrypt();
void decrypt();
void main() {
printf("\nENTER FIRST PRIME NUMBER\n");
scanf("%ld",&p);
flag=prime(p);
if(flag==0) {
printf("\nWRONG INPUT\n");
exit(1);
}

printf("\nENTER ANOTHER PRIME NUMBER\n");


scanf("%ld",&q);
flag=prime(q);
if(flag==0||p==q) {
printf("\nWRONG INPUT\n");

}
printf("\nENTER MESSAGE\n");
fflush(stdin);
scanf("%s",msg);

for (i=0;msg[i]!='\0';i++) {
m[i]=msg[i];
n=p*q;
t=(p-1)*(q-1);
ce();
printf("\nPOSSIBLE VALUES OF e AND d ARE\n");
for (i=0;i<j-1;i++)
printf("\n%ld\t%ld",e[i],d[i]);
encrypt();
decrypt();
}
Compute o(n)=(p-1) * (q-1)=2*10=20

Choose e such that 1 <e <p(n) and e and o (n) are co-prime. Let e = 7

Compute a value for d such that (d * e) % p(n)= 1. One solution is

d=3 [(3*7) % 20 = 1]

Public key is (e, n) => (7,33)

Private key is (d, n) => (3, 33)

ALGORITHM:

1. Start.

2. Get the message as input.

3. By taking prime numbers as encryption values, the message in encrypted. 4. In


decryption,the different values that are not known (private key) is used.

4. By this, the message can be recovered.

5. Stop the program.


int prime(long int pr) {
int i;
j=sqrt(pr);
for (i=2;i<=j;i++) {
if(pr%i==0)
return 0;
}
return 1; }
void ce() {
int k;
k=0;
for (i=2;i<t;i++) {
if(t%i==0)
continue;
flag=prime(i);
if(flag==1&&i!=p&&i!=q) {
e[k]=i;
flag=cd(e[k]);
if(flag>0) {
d[k]=flag;
k++;
}
if(k==99)
break;
}
}
}

long int cd(long int x) {


long int k=1;
while(1) {
k=k+t;
if(k%x==0)
return(k/x);
}
}

void encrypt() {
long int pt,ct,key=e[0],k,len;
i=0;
len=strlen(msg);
while(i!=len) {
pt=m[i];
pt=pt-96;
k=1;
for (j=0;j<key;j++) {
k=k*pt;
k=k%n;
}
temp[i]=k;
ct=k+96;
en[i]=ct;
i++;
}

en[i]=-1;
printf("\nTHE ENCRYPTED MESSAGE IS\n");
for (i=0;en[i]!=-1;i++)
printf("%ld",en[i]);
}

void decrypt() {
long int pt,ct,key=d[0],k;
i=0;
while(en[i]!=-1) {
ct=temp[i];
k=1;
for (j=0;j<key;j++) {
k=k*ct;
k=k%n;

OUTPUT:
RESULT:

Thus, the following data encryption and decryption has been implemented and verified.
1. Caesar Cipher Algorithm
2. Vigenere Cipher Algorithm
3. RSA Authentication Algorithm
Ex. No. 2 Date:

ERROR DETECTION AND CORRECTION CODE


AIM:
To implement the Error Detection and Correction Code such as Hamming Code.

ALGORITHM:
1. Start.
2. Get the data and the divisor as input.
3. Perform XOR division and determine the remainder.
4. Then append the remainder at the end of data bits.
5. Get the received data from the user.
6. Again, perform the XOR division, if the remainder is ‘0’, then the received data bit
is not connected.
7. Else the received data bit is corrupted.
8. Stop.

THEORY:
HAMMING CODE:
Hamming Code is a set of error correction code that can be used to detect and correct it
error that can occur when computer data is moved or stored. Hamming code is named R.W
Hamming of Bell Labs. Hamming codes makes FEC less expensive to implement through the
use of block parity mechanism.
 A minimum number of redundancy bits are needed to correct any single bit
error in the data.
 A minimum number of 4 redundancy bits is needed if the number of data bits
is 4.
 Redundancy bits in the hamming code are placed in the code word bit positions
that are raised to the power of 2.
 Each redundancy bit is the parity bit for a different combination of data bits.
 Each data bits may be included in more than one parity check.
PROGRAM:
HAMMING CODE:

#include<stdio.h>
void main()
{
int data[10];
int dataatrec[10],c,c1,c2,c3,i;

printf("Enter 4 bits of data one by one\n");


scanf("%d",&data[0]);
scanf("%d",&data[1]);
scanf("%d",&data[2]);
scanf("%d",&data[4]);

//Calculation of even parity


data[6]=data[0]^data[2]^data[4];
data[5]=data[0]^data[1]^data[4];
data[3]=data[0]^data[1]^data[2];

printf("\nEncoded data is\n");


for(i=0;i<7;i++)
printf("%d",data[i]);
printf("\n\nEnter received data bits one by one\n");

for(i=0;i<7;i++)
scanf("%d",&dataatrec[i]);

c1=dataatrec[6]^dataatrec[4]^dataatrec[2]^dataatrec[0];
c2=dataatrec[5]^dataatrec[4]^dataatrec[1]^dataatrec[0];
c3=dataatrec[3]^dataatrec[2]^dataatrec[1]^dataatrec[0];
c=c3*4+c2*2+c1;
Hamming codes detect two bit errors with more than one parity bit, each of which is
computed on different combinations of bits in the data. The number of parity bits required
depends on the number of bits in the data transmission, and is calculated by the hamming
rule. d+p+1<=2(1), where d is the no of data bits and p is the no of parity bits.

HAMMING DISTANCE CALCULATE:


Thus a code with minimum Hamming Diatance (d) between its codewords can
detect at most d-1 errors and can correct [(d-1)/2] errors.
 In this example, Hamming distance is enough for not only error detection, but also
error correction. Every allowable combination has set of not allowable.
ALLOWABLE NOT ALLOWABLE
000 001
010
100
111 011
101
110
if(c==0) {
printf("\nNo error while transmission of data\n");
}
else {
printf("\nError on position %d",c);

printf("\nData sent : ");


for(i=0;i<7;i++)
printf("%d",data[i]);
printf("\nData received : ");
for(i=0;i<7;i++)
printf("%d",dataatrec[i]);
printf("\nCorrect message is\n");

//if errorneous bit is 0 we complement it else vice versa


if(dataatrec[7-c]==0)
dataatrec[7-c]=1;
else
dataatrec[7-c]=0;
for (i=0;i<7;i++) {
printf("%d",dataatrec[i]);
}
}
}
HAMMING CODE WORKING:

ERROR CORRECTION USING XOR METHOD:


OUTPUT:
BURST ERROR CORRECTION USING HAMMING CODE:
RESULT:
Thus, the error detection and correction code such as Hamming Code has been
implemented and verified successfully.
Ex. No. 1 Date:

ERROR DETECTION CODES

AIM:

To implement Error Detection codes such as Parity Checker code and Cyclic
Redundancy Check Code in C Language.

ALGORITHM:

PARITY CHECKER:

1. Open the text editor and save a file in ‘.c’ format.


2. Get the data from the user.
3. Count the number of ones, in case of odd parity. If number of ones is odd, the parity
bit is assigned as 0. If number of ones is even, the parity bit is assigned as 1.
4. In the case of even parity, if the number of ones are odd, the parity bit is assigned as
1. If the number ones are even, the parity bit is assigned as 0.
5. Append the parity bit to data from the control word.
6. Use a parity checker to check the correctness of data.
7. Stop the program.

CYCLIC REDUNDANCY CHECK:

1. Start.
2. Get the data and the divisor as input.
3. Perform XOR division and determine the remainder.
4. Then append the remainder at the end of data bits.
5. Get the received data from the user.
6. Again, perform the XOR division, if the remainder is '0', then the received data bit is
not corrected.
7. Else the received data bit is corrupted.
8. Stop.

THEORY:

PARITY CHECKER:

Parity checking is the most basic form of error detection in communications. A parity
check is a process that ensures accurate data transmission between nodes during
communication. A parity bit is appended to the original data bits to create an even or odd
number, the number of bits to value one. The source then transmits this data via a link, and bits
are checked and verified at the destination. Data is considered accurate if the number of bits
matches the number transmitted from the source.
PROGRAM:
PARITY CHECK:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
char data[20],rdata[20]; int datlen;
int check(char data[20]);

int main()
{
int i, count=0, tflag, rflag, test;

printf("Enter the total bits of data: ");


scanf("%d",&datlen);
printf("\n Enter the data: ");
scanf("%s", data);

tflag=check(data);
puts("\n Rececived data: \n");
strcpy(rdata, data);
for(i=0; i<datlen; i++)
printf("%c",rdata[i]);

srand(time(NULL));
test=rand()%2;

printf("\nrand=%d\n", test);
rdata[0]=(test>0.5)?'1':'0';
printf("Received data after replacing with rand\n");

for(i=0;i<datlen; i++)
printf("%c",rdata[i]);
rflag=check(rdata);

if(tflag==rflag)
puts("\n Success!!!\nThe received message has no error");

else
puts("\n Failure!!!\n The received message has some error in it.");

return 0;
}
Parity checking, which was created to eliminate data communication errors, is a simple
method of network data verification and has an easy and understandable working mechanism.

As an example, if original data is 1010001, there are three 1's when even parity checking
is used, a parity bit with value 1 is added to data left side to make the number of ones even;
transmitted data becomes 11010001. However, if odd parity checking is used, then the parity
bit value is 0,01010001.

If the original data contains an even number of 1's, then parity bit of value 1 is added
to the data's left side to make the number of ones is odd, if odd parity checking is used and data
transmitted becomes 11101001. In case data is transmitted incorrectly, the parity bit value
becomes incorrect, thus indicating an error has occurred during transmission.

Parity checking is used not only in communication but also to test memory storage
devices Many PCs, for example, perform a parity check on memory every time a byte of data
is read.

CYCLIC REDUNDANCY CHECK:

In data transmission, the ability of a receiving station to correct errors in the received
data is called forward error correction (FEC) and can increase throughput on a data link when
there is a lot of mouse present. To enable this, the transmitting station must add extra data
(called error corrections bits) to the transmission. However, the correction may not always
represent a cost-saving over that of simply resending the information.

CYCLIC REDUNDANCY CHECK (CRC):

A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital


networks and storage devices to detect accidental changes to raw data. The CRC was invented
by W. Wesley Peterson in 1961, the 32-bit CRC function of Ethernet and many other standards
is the work of several researchers and was published in 1975.

CRC is based on binary division. In CRC, instead of adding bits to achieve the desired
parity, a sequence of redundant bits, called the CRC or CRC remainder, is appended to the end
of the data unit so that the resulting data unit becomes exactly divisible by a second,
predetermined binary number. At the destination, the incoming data unit is assumed to be intact
and is therefore accepted. A remainder indicates that the data unit has been damaged in transit
and therefore must be rejected.
int check(char data[20])
{
int i,evenpar, oddpar, count=0;
for(i=0; i<datlen; i++)
{
if (data[i]=='1')
count++;
}
printf("\n Count:\n%d\n",count);
if (count%2)
{
evenpar=1;
oddpar=0;
}
else
{
evenpar=0;
oddpar=1;
}

printf("Even parity=%d, Odd parity=%d",evenpar,oddpar);


return evenpar;
}

OUTPUT:
PROGRAM:
CYCLIC REDUNDANCY CHECK:
#include<stdio.h>
char data[20],div[20],temp[4],total[100];
int i,j,datalen,divlen,len,flag=1;
void check();
int main()
{
printf("Enter the total bit of data:");
scanf("%d",&datalen);
printf("\nEnter the total bit of divisor");
scanf("%d",&divlen);
len=datalen+divlen-1;
printf("\nEnter the data:");
scanf("%s",&data);
printf("\nEnter the divisor");
scanf("%s",div);

for(i=0;i<datalen;i++)
{
total[i]=data[i];
temp[i]=data[i];
}
for(i=datalen;i<len;i++)
total[i]='0';
check();
for(i=0;i<divlen;i++)
temp[i+datalen]=data[i];
printf("\ntransmitted Code Word:%s",temp);
printf("\n\nEnter the received code word:");
scanf("%s",total);
check();
for(i=0;i<divlen-1;i++)
if(data[i]=='1')
{
flag=0;
break;
}
if(flag==1)
printf("\nsuccessful!!");
else
printf("\nreceived code word contains errors...\n");
}
void check()
{
for(j=0;j<divlen;j++)
data[j]=total[j];
while(j<=len)
{
if(data[0]=='1')
for(i = 1;i <divlen ; i++)
data[i] = (( data[i] == div[i])?'0':'1');
for(i=0;i<divlen-1;i++)
data[i]=data[i+1];
data[i]=total[j++];
}
}

OUTPUT:
RESULT:

Thus, the error-detecting codes such as Parity Checker codes and Cyclic Redundancy
Check Codes has been implemented and verified successfully.
Ex. No.3 Date:
FLOW CONTROL MECHANISM USING ARQ
AIM:
To implement the flow control mechanisms such as Stop and Wait ARQ, Go Back –
N ARQ and Selective Repeat ARQ.
ALGORITHM:
STOP AND WAIT ARQ:
1. Start.
2. Enter the number of frames to be transmitted.
3. Sender transmits the first frame and waits for the acknowledgement from the receiver
for the transit time.
4. The receiver sends the acknowledgement (ACK) to the sender.
5. If the sender receives the ACK, it transmits the next frame.
6. Else the sender waits until the timer expires, and re-transmits the frame again.
7. The above step is followed until all the frames get transmitted.
8. Stop the program.
GO BACK N ARQ:
1. Start.
2. Enter the number of frames to be transmitted.
3. Enter the window size n.
4. The sender transmits the group of frames and each frame is labeled with a sequence
number.
5. If the receiver receives the frames intact then the receiver sends positive
acknowledgement.
6. Else the receiver sends the negative acknowledgement for the frame from which the
sender has to re-transmit the frame in sequence.
7. The step is followed until all the frames get transmitted.
8. Stop the program.
SELECTIVE REPEAT ARQ:
1. Start.
2. Enter the number of frames to be transmitted.
3. Enter the window size n.
4. The sender transmits the group of frames and each frame is labeled with a sequence
number.
5. If the receiver receives the frames intact then the receiver sends positive
acknowledgement.
6. Else the receiver sends the negative acknowledgement for the particular frame which
is lost or damaged.
7. Hence the sender re-transmits that particular frame and sends the next group of
frames.
8. The step is followed until all the frames get transmitted.
9. Stop the program.
PROGRAM:
STOP AND WAIT ARQ:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void main()
{
int i=1,j=1,noframes,x,x1=10,x2;
printf(“\nEnter the number of windows: “);
scanf(“%d”,&noframes);
printf("\nNumber of frames is %d",noframes);
while(noframes>0)
{
printf("\nSending Frame %d",i);
srand(x1++);
x=rand()%10;
if(x%2==0)
{
for(x2=1;x2<2;x2++)
{
printf("\nWaiting for %d seconds, No acknowledgement received so
retransmitting frame \n",x2);
sleep(x2);
}
printf("\nRetransmitting Frame %d",i);
srand(x1++);
x=rand()%10;
}
printf("\nAcknowledgement for frame %d",j);
noframes-=1;
i++;
j++;
}
printf("\nEnd of stop wait protocol");
}
THEORY:
FLOW CONTROL:
It refers to set of procedure involved in data link layer, to know the number of frames
that can be sent to the receiver without overwhelming to the receiver.
FLOW CONTROL PROTOCOL:
1. Stop and Wait ARQ
2. Sliding Window Protocol
 Go Back N ARQ
 Selective Repeat ARQ

STOP AND WAIT ARQ:


It is simplest algorithm and useful protocol in noiseless condition. The sender
transmits one frame at a time and waits for the acknowledgement from the receiver. If the
receiver sends the acknowledgement, then the sender transmits the next frame else the sender
waits until the timer get expires and re-transmit the frame. Here the sender should always
have the copy of the transmitted frames, till it receives the acknowledgement from the
receiver.

ADVANTAGES:
 It is the simplest algorithm.
 No sequence is needed.
DISADVANTAGES:
 Resource utilization is more.
 Transmission time is huge.
OUTPUT:
SLIDING WINDOW PROTOCOL:
Multiple frames are transmitted at a time. The sequence of the frame should be given.
The window size must be same at the receiver and the sender.
There are three possibilities:
1. Lost data frame
2. Damaged data frame
3. Lost ACK
For the above possibilities, the sender should always preserve the copies of transmitted
frames and activates the timers and wait for the acknowledgement. If there is no response in
the form of NAK/ACK the sender re-transmits all the frames. The receiver should send the
damage frame (NAK) or the next expected frame (ACK) and should be aware of the status of
lost/received frames. It needs to check whether the frame received is duplicate or not. If the
frame received is duplicate then discard it.

GO BACK N ARQ:
The group of frames is transmitted by the sender and it wait for the acknowledgement. If one
of the frames is erroneous in the group of frames then the remaining frames are discarded.
Thus, the sender re-transmits the frames from the erroneous frame onwards.
PROGRAM:
GO BACK N ARQ:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
int nf, N;
int no_tr = 0;
srand(time(NULL));
printf("Enter the number of frames : ");
scanf("%d", &nf);
printf("Enter the window size : ");
scanf("%d", &N);
int i = 1;
while (i <= nf)
{
int x = 0;
for (int j = i; j < i + N && j <= nf; j++)
{
printf("Sent Frame %d\n", j);
no_tr++;
}
for (int j = i; j < i + N && j <= nf; j++)
{
int flag = rand() % 2;
if (!flag)
{
printf("Acknowledgment for Frame %d\n", j);
x++;
}
else
{
printf("Frame %d", j);
printf(" Not Received\n");
printf("Retransmitting Window");
break;
}
}
printf("\n");
i += x;
}
printf("Total number of transmissions : %d\n", no_tr);
return 0;
}
ADVANTAGES:
 One ACK can acknowledge more than one frames.
 The sender can send many frames at a time.
 Efficiency is more.
DISADVANTAGE:
 Resource utilization is more.

SELECTIVE REPEAT ARQ:


The sender sends the group of frames and waits for the acknowledgement. If the
particular frame is erroneous or damaged only that particular frame is discarded while
remaining frames are not discarded. The receiver sends the negative acknowledgement for
that frame. The sender re-transmits that particular frame along with the next group of frames.
ADVANTAGE:
 Wastage of resource is reduced.
DISADVANTAGE:
 It is a complicated mechanism.
OUTPUT:
PROGRAM:
SELECTIVE REPEAT ARQ:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main()
{
int nf, N;
int no_tr = 0;
srand(time(NULL));
printf("Enter the number of frames : ");
scanf("%d", &nf);
printf("Enter the window size : ");
scanf("%d", &N);
int i = 1;
while (i <= nf)
{
int x = 0;
for (int j = i; j < i + N && j <= nf; j++)
{
printf("Sent Frame %d\n", j);
no_tr++;
}
for (int j = i; j < i + N && j <= nf; j++)
{
int flag = rand() % 2;
if (!flag)
{
printf("Acknowledgment for Frame %d\n", j);
x++;
}
else
{
printf("Frame %d Not Received\n", j);
printf("Retransmitting frame %d alone\n",j);
j--;
no_tr++;
}
}
i += x;
printf("\n");

}
printf("Total number of transmissions : %d\n", no_tr);
return 0;
}
OUTPUT:
RESULT:
Thus, the codes for implementing ARQ based flow control protocols such as Stop and
Wait ARQ, Go Back – N ARQ and Selective Repeat ARQ are verified successfully.
Ex. No: 8 Date:
DIJKSTRA’S SHORTEST PATH ALGORITHM

AIM:
Write a C program to implement Dijkstra’s algorithm to compute the shortest path
between nodes.

ALGORITHM:

1. Create cost matrix C[ ][ ] from adjacency matrix adj[ ][ ]. C[i][j] is the cost of going
from vertex i to vertex j. If there is no edge between vertices i and j then C[i][j] is
infinity.

2. Array visited[ ] is initialized to zero.


for(i=0;i<n;i++)
visited[i]=0;
3. If the vertex 0 is the source vertex then visited[0] is marked as 1.

4. Create the distance matrix, by storing the cost of vertices from vertex no. 0 to n-1 from
the source vertex 0.
for(i=1;i<n;i++)
distance[i]=cost[0][i];
Initially, distance of source vertex is taken as 0. i.e. distance[0]=0;

5. for(i=1;i<n;i++)
– Choose a vertex w, such that distance[w] is minimum and visited[w] is 0. Mark
visited[w] as 1.
– Recalculate the shortest distance of remaining vertices from the source.
– Only, the vertices not marked as 1 in array visited[ ] should be considered for
recalculation of distance. i.e. for each vertex v
if(visited[v]==0)
distance[v]=min(distance[v],
distance[w]+cost[w][v]).

THEORY:

GRAPHS:
Graphs are data structures used to represent "connections" between pairs of elements.
▪ These elements are called nodes. They represent real-life objects, persons, or entities.
▪ The connections between nodes are called edges.

.
PROGRAM:

#include<stdio.h>
#include<conio.h>
#define INFINITY 9999
#define MAX 10

void dijkstra(int G[MAX][MAX],int n,int startnode);

int main()
{
int G[MAX][MAX],i,j,n,u;
printf("Enter no. of vertices:");
scanf("%d",&n);
printf("\nEnter the adjacency matrix:\n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
scanf("%d",&G[i][j]);
printf("\nEnter the starting node:");
scanf("%d",&u);
dijkstra(G,n,u);
return 0;
}

void dijkstra(int G[MAX][MAX],int n,int startnode)


{

int cost[MAX][MAX],distance[MAX],pred[MAX];
int visited[MAX],count,mindistance,nextnode,i,j;
//pred[] stores the predecessor of each node
//count gives the number of nodes seen so far
//create the cost matrix
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(G[i][j]==0)
cost[i][j]=INFINITY;
else
cost[i][j]=G[i][j];
//initialize pred[],distance[] and visited[]
for(i=0;i<n;i++)
{
distance[i]=cost[startnode][i];
pred[i]=startnode;
visited[i]=0;
}
distance[startnode]=0;
visited[startnode]=1;
count=1;
while(count<n-1)
{
mindistance=INFINITY;
This is a graphical representation of a graph:

Types of Graphs:
Graphs can be:
• Undirected: if for every pair of connected nodes, you can go from one node to the other
in both directions.
• Directed: if for every pair of connected nodes, you can only go from one node to
another in a specific direction. We use arrows instead of simple lines to represent
directed edges.

DIJKSTRA'S ALGORITHM:

Purpose and Use Cases:


With Dijkstra's Algorithm, you can find the shortest path between nodes in a graph.
Particularly, you can find the shortest path from a node (called the "source node") to all other
nodes in the graph, producing a shortest-path tree.
This algorithm is used in GPS devices to find the shortest path between the current
location and the destination. It has broad applications in industry, specially in domains that
require modelling networks.

Basics of Dijkstra's Algorithm:


• Dijkstra's Algorithm basically starts at the node that you choose (the source node) and it
analyzes the graph to find the shortest path between that node and all the other nodes in
the graph.

• The algorithm keeps track of the currently known shortest distance from each node to
the source node and it updates these values if it finds a shorter path.

• Once the algorithm has found the shortest path between the source node and another
node, that node is marked as "visited" and added to the path.
//nextnode gives the node at minimum distance
for(i=0;i<n;i++)
if(distance[i]<mindistance&&!visited[i])
{
mindistance=distance[i];
nextnode=i;
}
//check if a better path exists through nextnode
visited[nextnode]=1;
for(i=0;i<n;i++)
if(!visited[i])
if(mindistance+cost[nextnode][i]<distance[i])
{
distance[i]=mindistance+cost[nextnode][i];
pred[i]=nextnode;
}
count++;
}

//print the path and distance of each node


for(i=0;i<n;i++)
if(i!=startnode)
{
printf("\nDistance of node%d=%d",i,distance[i]);
printf("\nPath=%d",i);
j=i;
do
{
j=pred[j];
printf("<-%d",j);
}while(j!=startnode);
}
}
• The process continues until all the nodes in the graph have been added to the path. This
way, we have a path that connects the source node to all other nodes following the
shortest path possible to reach each node.

Requirements:
Dijkstra's Algorithm can only work with graphs that have positive weights. This is
because, during the process, the weights of the edges have to be added to find the shortest path.
If there is a negative weight in the graph, then the algorithm will not work properly. Once a
node has been marked as "visited", the current path to that node is marked as the shortest path
to reach that node. And negative weights can alter this if the total weight can be decremented
after this step has occurred.

Time Complexity:
The program contains two nested loops each of which has a complexity of O(n). n is
number of vertices. So the complexity of algorithm is O(n2).

Advantages:
▪ It is used in Google Maps
▪ It is used in finding Shortest Path.
▪ It is used in geographical Maps
▪ To find locations of Map which refers to vertices of graph.
▪ Distance between the location refers to edges.
▪ It is used in IP routing to find Open shortest Path First.
▪ It is used in the telephone network.

Disadvantages:
▪ It does blind search so wastes lot of time while processing.
▪ It cannot handle negative edges.
▪ This leads to acyclic graphs and most often cannot obtain the right shortest path.
OUTPUT:
RESULT:

Thus the C program to implement Dijkstra’s Algorithm to compute shortest path


between nodes was implemented and verified successfully.
Ex. No: 11 Date:
IP ROUTE LOOKUP

AIM:
Write a C program to implement IP route lookup based on the optimized TRIE structure
and evaluate the performance.

THEORY:

IP ROUTING:

IP Routing is a process that sends packets from a host on one network to another host on
a different remote network. It helps you examine the destination IP address of a packet, determine
the next-hop address, and forward it. IP routers use routing tables to determine the next-hop
address to which the packet should be delivered.
In IP routing, data is routed from its source to its destination through routers and across
multiple networks. The IP Routing protocols allow routers to build up a forwarding table that
correlates final destinations with next-hop addresses.

ROUTING TABLE LOOKUP

Each address in IPv4 is 32 bits long.

Each routing table entry stores:

1. a Destination, which is an IP address.


2. a Gateway or Next Hop, which is also an IP address.
3. a mask, which is a 32-bit string, but not an IP address.
4. various flags, which for this assignment may be ignored
5. a metric, which for this assignment may be ignored
6. an interface, which is an arbitrary string
PROGRAM:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

int error_code; // In this variable we save the error codes that produces some methods

#define MTABLE_ENTRIES_LENGTH 16777216 // 2^24 entries


void compute_routes();
void initializeRouteTable();
void interface_lookup(uint32_t *IP_lookup,short int *ntables,unsigned short *interface);

//RIB.h
// Route related hedaers
#define MTABLE_ENTRIES_LENGTH 16777216 // 2^24 entries

typedef struct RIB {


short *main_table; // Main Table
short *aux_table; // Second Table
unsigned short extended_pools; // Number of networks using the extended table.
long ip_index;
} RIB_t ;

RIB_t rib;

uint32_t *IP_addr;
int *aux_prefixLength;
int *aux_outInterface;

struct timeval start, end;

/*** VARIABLES RELATED WITH THE PERFORMANCE INFORMATION*/


int *processedPackets;
double *totalTableAccesses;
double *totalPacketProcessingTime;

/***********************************************************************
* Static variables for the input/output files
***********************************************************************/
static FILE *routingTable;
static FILE *inputFile;
static FILE *outputFile;
ROUTING METRICS
Routing metric are the value that allows the routers to decide the best route for the data packet

Different routing metrics are:

• Hops
• Bandwidth
• Load
• Cost
• Reliability

HOW DOES IP ROUTING WORK?

• Host X has an IP address of the router T1 configured as the default gateway address.
• Here, host X is trying to communicate with host Y, which is a host on another remote
network.
• This host looks up in its routing table to check if there is an entry for the destination
network address.
• If the entry is found, the host will send all data to the router T1.
• Router T1 then receives the packets and forwards them to host Y.

.
void RIB_init(RIB_t* self);
void RIB_addRoute(RIB_t* rib, uint32_t *ipv4_addr, int *mask, int *out_iface);
void RIB_lookup(RIB_t* rib, uint32_t *IP_lookup, short int *ntables, unsigned short *iface);
void RIB_destroy(RIB_t* rib);

//IO related headers

/********************************************************************
* Constant definitions
********************************************************************/
#define OUTPUT_NAME ".out"
#define OK 0
#define ROUTING_TABLE_NOT_FOUND -3000
#define INPUT_FILE_NOT_FOUND -3001
#define BAD_ROUTING_TABLE -3002
#define REACHED_EOF -3003
#define BAD_INPUT_FILE -3004
#define PARSE_ERROR -3005
#define CANNOT_CREATE_OUTPUT -3006

int initializeIO(char *routingTableName, char *inputFileName);


void freeIO();
void printIOExplanationError(int result);
int readFIBLine(uint32_t *prefix, int *prefixLength, int *outInterface);
int readInputPacketFileLine(uint32_t *IPAddress);
void printOutputLine(uint32_t IPAddress, int outInterface, struct timeval *initialTime, struct
timeval *finalTime,
double *searchingTime, int numberOfHashtables);

void printSummary(int processedPackets, double averageTableAccesses, double


averagePacketProcessingTime);
void printMemoryTimeUsage();

int main( int argc, char *argv[] )


{
RIB_init(&rib);

processedPackets = calloc(1,sizeof(int));
totalTableAccesses = calloc(1,sizeof(double));
totalPacketProcessingTime = calloc(1,sizeof(double));
error_code = 0;

if( argc == 3 )
{
error_code = initializeIO(argv[1], argv[2]); //Initialize Input
if(error_code != 0){
printf("\nERROR: \n\t");
printIOExplanationError(error_code);
return -1; }
TYPES OF ROUTING PROTOCOLS:
The following protocols help data packets find their way across the Internet:

IP:
The Internet Protocol (IP) specifies the origin and destination for each data packet. Routers
inspect each packet’s IP header to identify where to send them.

OSPF:
Open Shortest Path First (OSPF) protocol is a link-state IGP tailor-made for IP networks using
the Shortest Path First (SPF) method.

RIP:
RIP is used in both LAN and WAN Networks. It also runs on the application layer of the OSI
model. The full form of RIP is the Routing Information Protocol. Two versions of RIP are

1. RIPv1
2. RIPv2

EIGRP:
It is a hybrid routing protocol that provides routing protocols, distance vector, and link-state
routing protocols. It will route the same protocols that IGRP routes using the same composite
metrics as IGRP, which helps the network select the best path destination.

ISIS:
ISIS routing protocol is used on the Internet to send IP routing information. It consists of a
range of components, including end systems, intermediate systems, areas, and domains.

BGP:
BGP is a routing protocol of the Internet, which is classified as a DPVP (distance path vector
protocol). The full form of BGP is the Border Gateway Protocol.

ADVANTAGES OF IP ROUTING:
The routing process ensures that appropriate packets are routed from the source to the
destination

Goals of routing include:

• It offers stability
• It provides a robust network
• Offers dynamic routing update of the network paths
• Information is safe while transmitting.
initializeRouteTable();
compute_routes();
printSummary(*processedPackets, (*totalTableAccesses / *processedPackets),
(*totalPacketProcessingTime / *processedPackets));
freeIO(); /* Freeing Resources */
RIB_destroy(&rib);
free(processedPackets);
free(totalTableAccesses);
free(totalPacketProcessingTime);

}
else
{
printf("\nUSE:\n\t./my_route_lookup <routingTable>
<inputFile>\n\nWHERE:\n\t<routingTable>\t\tThe path for the file containing the routing
table\n\t<inputFile>\t\tThe path for the input file\n\n");
return -1;
}
return 1;
}

/********************************************************************
* Initalize file descriptors
*
* routingTableName contains FIB info (argv[1] of main function)
* inputFileName contains IP addresses (argv[2] of main function)
*
***********************************************************************/
int initializeIO(char *routingTableName, char *inputFileName){

char outputFileName[100];

routingTable = fopen(routingTableName, "r");


if (routingTable == NULL) return ROUTING_TABLE_NOT_FOUND;

inputFile = fopen(inputFileName, "r");


if (inputFile == NULL) {
fclose(routingTable);
return INPUT_FILE_NOT_FOUND;
}

sprintf(outputFileName, "%s%s", inputFileName, OUTPUT_NAME);


outputFile = fopen(outputFileName, "w");
if (outputFile == NULL) {
fclose(routingTable);
fclose(inputFile);
return CANNOT_CREATE_OUTPUT;
}
return OK;

}
ROUTE LOOKUP IN A TRIE

Looking up a route in a routing table is to find the most specific prefix matching the requested
destination.

For each node, the prefix is known by its path from the root node and the prefix length is the
current depth.

A lookup in such a trie is quite simple: at each step, fetch the nth bit of the IP address, where n
is the current depth. If it is 0, continue with the first child. Otherwise, continue with the second.
If a child is missing, backtrack until a routing entry is found. For example, when looking for
[Link], we will find the result in the corresponding leaf (at depth 32). However for
[Link], we will reach [Link]/31 but there is no second child. Therefore, we backtrack
until the [Link]/25 routing entry.

Adding and removing routes is quite easy. From a performance point of view, the lookup is
done in constant time relative to the number of routes (due to maximum depth being capped to
32).
void initializeRouteTable()
{
IP_addr = calloc(1,sizeof(int));
aux_prefixLength = calloc(1,sizeof(int));
aux_outInterface = calloc(1,sizeof(int));
error_code = readFIBLine(IP_addr, aux_prefixLength, aux_outInterface);
while(error_code == 0){ //WHILE NOT EOF OR ANOTHER TYPE OF ERROR
RIB_addRoute(&rib, IP_addr,aux_prefixLength,aux_outInterface);
error_code = readFIBLine(IP_addr,aux_prefixLength,aux_outInterface);
}
free(IP_addr);
free(aux_prefixLength);
free(aux_outInterface);
}

/***********************************************************************
* Read one entry in the FIB
*
* It should be noted that prefix, prefixLength and outInterface are
* pointers since they are used as output parameters
*
***********************************************************************/
int readFIBLine(uint32_t *prefix, int *prefixLength, int *outInterface){
int n[4], result;

result = fscanf(routingTable, "%i.%i.%i.%i/%i\t%i\n", &n[0], &n[1], &n[2], &n[3],


prefixLength, outInterface);
if (result == EOF) return REACHED_EOF;
else if (result != 6) return BAD_ROUTING_TABLE;
else{
//Intel architecture is little endian
*prefix = (n[0]<<24) + (n[1]<<16) + (n[2]<<8) + n[3];
//*prefix = n[0]*pow(2,24) + n[1]*pow(2,16) + n[2]*pow(2,8) + n[3];
return OK;
}

/**
* [Perform routing process, going through the file and looking for the best Interface for each
IP]
*
* Output:
* processedPackets
* totalTableAccesses
* totalPacketProcessingTime
*/
void compute_routes()
{
uint32_t *IP_lookup = calloc(1,sizeof(uint32_t));
unsigned short *interface = calloc(1,sizeof(unsigned short));
double *searching_time = calloc(1,sizeof(double));
short int *number_of_tables = calloc(1,sizeof(short int));
error_code = readInputPacketFileLine(IP_lookup);
while(error_code == 0)
{
gettimeofday(&start, NULL);
RIB_lookup(&rib, IP_lookup, number_of_tables, interface);
gettimeofday(&end, NULL);
printOutputLine(*IP_lookup, *interface, &start, &end,searching_time,
*number_of_tables);
*processedPackets = *processedPackets + 1;
*totalTableAccesses = *totalTableAccesses + *number_of_tables;
*totalPacketProcessingTime = *totalPacketProcessingTime + *searching_time;
error_code = readInputPacketFileLine(IP_lookup);
}
free(IP_lookup);
free(interface);
free(searching_time);
free(number_of_tables);
}

/***********************************************************************
* Read one entry in the input packet file
*
* Again, it should be noted that IPAddress is a pointer since it is used
* as output parameter
*
***********************************************************************/
int readInputPacketFileLine(uint32_t *IPAddress){

int n[4], result;

result = fscanf(inputFile, "%i.%i.%i.%i\n", &n[0], &n[1], &n[2], &n[3]);


if (result == EOF) return REACHED_EOF;
else if (result != 4) return BAD_INPUT_FILE;
else{
//remember that pentium architecture is little endian
*IPAddress = (n[0]<<24) + (n[1]<<16) + (n[2]<<8) + n[3];
//*IPAddress = n[0]*pow(2,24) + n[1]*pow(2,16) + n[2]*pow(2,8) + n[3];
return OK;
}

/***********************************************************************
* Print a line to the output file
*
* gettimeofday(&initialTime, NULL) must be called right before the lookup function
*
* gettimeofday(&finalTime, NULL) must be called right after the lookup function
* The lookup function must return (either as output parameter or as return value)
* the number of hash tables that have been accessed for every IP address
*
***********************************************************************/
void printOutputLine(uint32_t IPAddress, int outInterface, struct timeval *initialTime, struct
timeval *finalTime,
double *searchingTime, int numberOfHashtables) {

unsigned long sec, usec;

usec = finalTime->tv_usec - initialTime->tv_usec;


if (usec > finalTime->tv_usec) initialTime->tv_sec += 1;
sec = finalTime->tv_sec - initialTime->tv_sec;

*searchingTime = 1000000*sec + usec;

//remember that output interface equals 0 means no matching


//remember that if no matching but default route is specified in the FIB, the default
output interface
//must be stored to avoid dropping the packet (i.e., MISS)
if (!outInterface){
fprintf(outputFile,"%i.%i.%i.%i;%s;%i;%.0lf\n",IPAddress >> 24, (IPAddress >> 16) &
0x000000ff, (IPAddress >> 8) & 0x000000ff, IPAddress & 0x000000ff ,
"MISS",numberOfHashtables, *searchingTime);
}
else{
fprintf(outputFile,"%i.%i.%i.%i;%i;%i;%.0lf\n",IPAddress >> 24, (IPAddress
>> 16) & 0x000000ff, (IPAddress >> 8) & 0x000000ff, IPAddress & 0x000000ff ,
outInterface,numberOfHashtables, *searchingTime);
}
}

/***********************************************************************
* Print execution summary to the output file
*
* It should be noted that:
*
* averageTableAccesses = totalTableAccesses/processedPackets
*
* averagePacketProcessingTime = totalPacketProcessingTime/processedPackets
*
***********************************************************************/
void printSummary(int processedPackets, double averageTableAccesses, double
averagePacketProcessingTime){
fprintf(outputFile, "\nPackets processed= %i\n", processedPackets);
fprintf(outputFile, "Average table accesses= %.2lf\n", averageTableAccesses);
fprintf(outputFile,"Average packet processing time (usecs)= %.2lf\n",
averagePacketProcessingTime);
printMemoryTimeUsage(); }
/***********************************************************************
* Print memory and CPU time
*
* For more info: man getrusage
*
***********************************************************************/
void printMemoryTimeUsage(){

float user_time, system_time;


long int memory;
struct rusage usage;

if (getrusage (RUSAGE_SELF, &usage)){


printf("Resource measurement failed.\n");
}
else{
user_time = (float)usage.ru_utime.tv_sec+(float)usage.ru_utime.tv_usec/1000000;
system_time = (float)usage.ru_stime.tv_sec+(float)usage.ru_stime.tv_usec/1000000;
memory = usage.ru_maxrss;

fprintf(outputFile, "Memory (Kbytes) = %ld\n", memory );


fprintf(outputFile, "CPU Time (secs)= %.6f\n\n", user_time+system_time);
}

/***********************************************************************
* Close the input/output files
***********************************************************************/
void freeIO() {

fclose(inputFile);
fclose(outputFile);
fclose(routingTable);

/***********************************************************************
* Write explanation for error identifier (verbose mode)
***********************************************************************/
void printIOExplanationError(int result){

switch(result) {
case ROUTING_TABLE_NOT_FOUND:
printf("Routing table not found\n");
exit(0);

case INPUT_FILE_NOT_FOUND:
printf("Input file not found\n");
exit(0);

case BAD_ROUTING_TABLE:
printf("Bad routing table structure\n");
exit(0);
case BAD_INPUT_FILE:
printf("Bad input file structure\n");
exit(0);
case PARSE_ERROR:
printf("Parse error\n");
exit(0);
case CANNOT_CREATE_OUTPUT:
printf("Cannot create output file\n");
exit(0);
case REACHED_EOF:
printf("Reached End Of File\n");
exit(0);
default:
printf("Unknown error\n");
exit(0);
}
exit(0);

// Constructor (without allocation)


void RIB_init(RIB_t* rib) {
rib->main_table = calloc(MTABLE_ENTRIES_LENGTH,sizeof(short));
rib->extended_pools = 0;
rib->ip_index = 0;
}

void RIB_addRoute(RIB_t* rib, uint32_t *ipv4_addr, int *mask, int *out_iface){


long int n_hosts = 0; // We calculate the number of hosts affected by the mask
if(*mask <= 24){
n_hosts = pow(2,24 - *mask);
for(rib->ip_index = 0; rib->ip_index < n_hosts; rib->ip_index++)
{
rib->main_table[(*ipv4_addr>>8) + rib->ip_index] = *out_iface;
}
}else{
n_hosts = pow(2,32 - *mask);
if(rib->main_table[*ipv4_addr>>8]>>15 == 0)
{
// 1. REALLOC MEMORY, we reserve 256 more chunks for the new interfaces
rib->aux_table = realloc(rib->aux_table, 256*(rib->extended_pools + 1)*2);
// 2. COPY FROM MTABLE TO STABLE
for(rib->ip_index = 0; rib->ip_index <= 255; rib->ip_index++)
{
rib->aux_table[rib->extended_pools*256 + rib->ip_index] = rib-
>main_table[*ipv4_addr>>8]; }
// 3. UPDATE MTABLE VALUE WITH THE INDEX OF STABLE
rib->main_table[*ipv4_addr>>8] = rib->extended_pools |
0b1000000000000000;
// 4. POPULATE THE STABLE CHUNK WITH THE SPECIFIED NEW
ADDRESS
for(rib->ip_index = (*ipv4_addr & 0xFF);
rib->ip_index < n_hosts + (*ipv4_addr & 0xFF);
rib->ip_index++)
{
rib->aux_table[rib->extended_pools*256 + rib->ip_index] = *out_iface;
}
rib->extended_pools++;
}
else{ // If it already exists a chunk for this Ip range inside stable
for(rib->ip_index = (*ipv4_addr & 0xFF);
rib->ip_index < n_hosts + (*ipv4_addr & 0xFF);
rib->ip_index++
){
rib->aux_table[(rib->main_table[*ipv4_addr>>8] & 0x7FFF)*256 + rib-
>ip_index] = *out_iface;
}
}
}
}

/**
* [Look for an IP address inside the main table and secundary table stored in RAM]
* Input:
* IP_lookup
* Output.
* interface
* ntables
*/
void RIB_lookup(RIB_t* rib, uint32_t *IP_lookup, short int *ntables, unsigned short *iface)
{
*iface = rib->main_table[*IP_lookup>>8];
if(*iface>>15 == 0)
{
*ntables = 1;
return;
}
else
{
*ntables = 2;
*iface = rib->aux_table[(*iface & 0x7FFF)*256 + (*IP_lookup &
0x000000FF)];
// 0x7fff = 0b0111111111111111 to adquire just the address to the 2nd table
return;
}
return;
}
void RIB_destroy(RIB_t* rib) {
if (rib) {
free(rib->main_table);
free(rib->aux_table);
}
}

OUTPUT:
RESULT:

Thus the C program to implement IP route lookup based on the optimized TRIE structure
and to evaluate its performance has been executed successfully.
Ex. No: 7 Date:
FILE TRANSFER USING CLIENT – SERVER PROGRAM

AIM:
Write a C program to make the Server send the content of the requested file to the Client
if the file is present.

ALGORITHM:

SERVER:

1. Create a UDP socket and bind it to the Server address.


2. Wait for filename from the Client.
3. When file name is received, if file is present, then read the contents, apply a simple
XOR based encryption and send a buffer filled with the encrypted file content. If the
file is not present send ‘file not present’ message.
4. Go to Step 2.

CLIENT:

1. Create a UDP socket.


2. Send a filename and wait for the server's response.
3. If the file is received, decrypt the characters and print them till End of File.
Go to Step 2.

THEORY:
UDP PROTOCOL:

In computer networking, the UDP stands for User Datagram Protocol. The David P.
Reed developed the UDP protocol in 1980. It is defined in RFC 768, and it is a part of
the TCP/IP protocol, so it is a standard protocol over the internet. The UDP protocol allows the
computer applications to send the messages in the form of datagrams from one machine to
another machine over the Internet Protocol (IP) network. The UDP is an alternative
communication protocol to the TCP protocol (transmission control protocol). Like TCP, UDP
provides a set of rules that governs how the data should be exchanged over the internet.

The UDP works by encapsulating the data into the packet and providing its own header
information to the packet. Then, this UDP packet is encapsulated to the IP packet and sent off to
its destination. Both the TCP and UDP protocols send the data over the internet protocol
network, so it is also known as TCP/IP and UDP/IP. There are many differences between these
two protocols. UDP enables the process to process communication, whereas the TCP provides
host to host communication.

Since UDP sends the messages in the form of datagrams, it is considered the best-effort
mode of communication. TCP sends the individual packets, so it is a reliable transport medium.
PROGRAM:
UDP SERVER:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024

int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from server";
struct sockaddr_in servaddr, cliaddr;

// Creating socket file descriptor


if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));
memset(&cliaddr, 0, sizeof(cliaddr));

// Filling server information


servaddr.sin_family = AF_INET; // IPv4
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(PORT);

// Bind the socket with the server address


if ( bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
int len, n;
len = sizeof(cliaddr); //len is value/result
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, ( struct sockaddr *) &cliaddr, &len);
buffer[n] = '\0';
printf("Client : %s\n", buffer);
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &cliaddr,len);
printf("Hello message sent.\n");
return 0;

}
Features of UDP protocol:

The following are the features of the UDP protocol:

o Transport layer protocol

UDP is the simplest transport layer communication protocol. It contains a minimum amount of
communication mechanisms. It is considered an unreliable protocol, and it is based on best-
effort delivery services. UDP provides no acknowledgment mechanism, which means that the
receiver does not send the acknowledgment for the received packet, and the sender also does
not wait for the acknowledgment for the packet that it has sent.

o Connectionless

The UDP is a connectionless protocol as it does not create a virtual path to transfer the data. It
does not use the virtual path, so packets are sent in different paths between the sender and the
receiver, which leads to the loss of packets or received out of order.

Ordered delivery of data is not guaranteed.

In the case of UDP, the datagrams are sent in some order will be received in the same order is
not guaranteed as the datagrams are not numbered.

o Ports

The UDP protocol uses different port numbers so that the data can be sent to the correct
destination. The port numbers are defined between 0 and 1023.

o Faster transmission

UDP enables faster transmission as it is a connectionless protocol, i.e., no virtual path is


required to transfer the data. But there is a chance that the individual packet is lost, which
affects the transmission quality. On the other hand, if the packet is lost in TCP connection, that
packet will be resent, so it guarantees the delivery of the data packets.

o Acknowledgment mechanism

The UDP does have any acknowledgment mechanism, i.e., there is no handshaking between the
UDP sender and UDP receiver. If the message is sent in TCP, then the receiver acknowledges
that I am ready, then the sender sends the data. In the case of TCP, the handshaking occurs
between the sender and the receiver, whereas in UDP, there is no handshaking between the
sender and the receiver.
UDP CLIENT:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define PORT 8080
#define MAXLINE 1024

int main() {
int sockfd;
char buffer[MAXLINE];
char *hello = "Hello from client";
struct sockaddr_in servaddr;

// Creating socket file descriptor


if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&servaddr, 0, sizeof(servaddr));

// Filling server information


servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(PORT);
servaddr.sin_addr.s_addr = INADDR_ANY;

int n, len;
sendto(sockfd, (const char *)hello, strlen(hello),
MSG_CONFIRM, (const struct sockaddr *) &servaddr, sizeof(servaddr));
printf("Hello message sent.\n");

n = recvfrom(sockfd, (char *)buffer, MAXLINE,


MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
buffer[n] = '\0';
printf("Server : %s\n", buffer);
close(sockfd);
return 0;
}
o Segments are handled independently

Each UDP segment is handled individually of others as each segment takes different path to
reach the destination. The UDP segments can be lost or delivered out of order to reach the
destination as there is no connection setup between the sender and the receiver.

Why do we require the UDP protocol?


As we know that the UDP is an unreliable protocol, but we still require a UDP protocol
in some cases. The UDP is deployed where the packets require a large amount of bandwidth
along with the actual data. For example, in video streaming, acknowledging thousands of
packets is troublesome and wastes a lot of bandwidth. In the case of video streaming, the loss of
some packets couldn't create a problem, and it can also be ignored.

Limitations:
o It provides an unreliable connection delivery service. It does not provide any services of
IP except that it provides process-to-process communication.
o The UDP message can be lost, delayed, duplicated, or can be out of order.
o It does not provide a reliable transport delivery service. It does not provide any
acknowledgment or flow control mechanism. However, it does provide error control to
some extent.

Advantages:
o It produces a minimal number of overheads.
OUTPUT:
RESULT:

Thus the connection between two computers using UDP File Transfer Client-Server was
implemented and verified successfully.
Ex. No: 10 Date:
MULTICAST COMMUNICATION

AIM:
To create a network scenario and study the multicast communications using the NS-2
simulator tool.

THEORY:

MULTICAST COMMUNICATION:

When it comes to radio and television broadcasts, it does not matter how many users are
tuned in and using the service. This is not at all the case when sending information over IP
networks. For example, if several different users were able to connect to a live stream, the
standard IP unicast communication would require the sending station to send the corresponding
packets to each recipient separately. Since this would use up the available bandwidth within a
very short period, Multicast routing (also known as IP multicast) was quickly developed and
implemented. It enables the sender to transmit IP data streams to many recipients simultaneously
in a single step.

Multicasting is similar to broadcasting, but only transmits information to specific users. It is


used to efficiently transmit streaming media and other types of data to multiple users at one
time.

.
PROGRAM:

#This example is to demonstrate the multicast routing protocol.


set ns [new Simulator -multicast on]
#Turn on Tracing
set tf [open [Link] w]
$ns trace-all $tf

# Turn on nam Tracing


set fd [open [Link] w]
$ns namtrace-all $fd

# Create nodes
set n0 [$ns node]
set n1 [$ns node]
set n2 [$ns node]
set n3 [$ns node]
set n4 [$ns node]
set n5 [$ns node]
set n6 [$ns node]
set n7 [$ns node]

# Create links with DropTail Queues


$ns duplex-link $n0 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n1 $n2 1.5Mb 10ms DropTail
$ns duplex-link $n2 $n3 1.5Mb 10ms DropTail
$ns duplex-link $n3 $n4 1.5Mb 10ms DropTail
$ns duplex-link $n3 $n7 1.5Mb 10ms DropTail
$ns duplex-link $n4 $n5 1.5Mb 10ms DropTail
$ns duplex-link $n4 $n6 1.5Mb 10ms DropTail

# Routing protocol: say distance vector


#Protocols: CtrMcast, DM, ST, BST
#Dense Mode protocol is supported in this example
set proto DM
set mrthandle [$ns mrtproto $mproto {}]

# Set two groups with group addresses


set group1 [Node allocaddr]
set group2 [Node allocaddr]

# UDP Transport agent for the traffic source for group1


set udp0 [new Agent/UDP]
$ns attach-agent $n0 $udp0
$udp0 set dst_addr_ $group1
Multicast is group communication where information is addressed to a group of destination
computers simultaneously. Multicasting can allow you to reach many end-users while utilizing
only one data stream, decreasing the amount of bandwidth and saving [Link](Carrier
Sense Multiple Access)is the protocol for carrier transmission access in Ethernet networks. On
Ethernet, each device can try to send a frame at any time.

There are three fundamental types of IPv4 addresses: unicast, broadcast, and multicast. A unicast
address is designed to transmit a packet to a single destination. A broadcast address is used to
send a datagram to an entire subnetwork. A multicast address is
designed to enable the delivery of datagrams to a set of hosts that have been configured as
members of a multicast group in various scattered subnetworks.

PROCEDURE:

• create the simulator object.

• Set up the network topology by creating node objects, and connecting the nodes with
link objects. If the output queue of a router is implemented as a part of a link, we need to
specify the queue type. In this project, the DropTail queue is used. In some cases, we
may define the layout of the network topology for a better NAM display.

• Define traffic patterns by creating agents, applications, and flows. In NS2, packets are
always sent from one agent to another agent or a group of agents. In addition, we need
to associate these agents with nodes.

• Define the trace files, and place monitors at places in the topology to collect information
about packet flows. NS2 supports two primary monitoring capabilities: traces and
monitors. The traces enable the recording of packets whenever an event such as packet
drop or arrival occurs in a queue or a link. The monitors provide a means for collecting
quantities, such as several packets dropping their several arrived packets in the queue.
The monitor can be used to collect these quantities for all packets or just for a specified
flow (a flow monitor).

• Schedule the simulation by defining the start and stop of the simulation, traffic flows,
tracing, and other events.

• Finally we need to extract useful data from the traces, as you just did use Awk
commands, and feed it to plotting software to get human-readable results. In the
individual tasks below, each task is prefaced with the name of the files you should hand
in concerning that subtask.
$udp0 set dst_port_ 0
set cbr1 [new Application/Traffic/CBR]
$cbr1 attach-agent $udp0

# Transport agent for the traffic source for group2


set udp1 [new Agent/UDP]
$ns attach-agent $n1 $udp1
$udp1 set dst_addr_ $group2
$udp1 set dst_port_ 0
set cbr2 [new Application/Traffic/CBR]
$cbr2 attach-agent $udp1

# Create receiver to accept the packets


set rcvr1 [new Agent/Null]
$ns attach-agent $n5 $rcvr1
$ns at 1.0 "$n5 join-group $rcvr1 $group1"
set rcvr2 [new Agent/Null]
$ns attach-agent $n6 $rcvr2
$ns at 1.5 "$n6 join-group $rcvr2 $group1"

set rcvr3 [new Agent/Null]


$ns attach-agent $n7 $rcvr3
$ns at 2.0 "$n7 join-group $rcvr3 $group1"

set rcvr4 [new Agent/Null]


$ns attach-agent $n5 $rcvr1
$ns at 2.5 "$n5 join-group $rcvr4 $group2"

set rcvr5 [new Agent/Null]


$ns attach-agent $n6 $rcvr2
$ns at 3.0 "$n6 join-group $rcvr5 $group2"

set rcvr6 [new Agent/Null]


$ns attach-agent $n7 $rcvr3

#The nodes are leaving the group at specified times


$ns at 3.5 "$n7 join-group $rcvr6 $group2"
$ns at 4.0 "$n5 leave-group $rcvr1 $group1"
$ns at 4.5 "$n6 leave-group $rcvr2 $group1"
$ns at 5.0 "$n7 leave-group $rcvr3 $group1"
$ns at 5.5 "$n5 leave-group $rcvr4 $group2"
$ns at 6.0 "$n6 leave-group $rcvr5 $group2"
$ns at 6.5 "$n7 leave-group $rcvr6 $group2"
APPLICATIONS OF NS2 MULTICASTING PROJECTS:

• Streaming multimedia over the internet like live TV and internet radio.
• Video conferencing and webcasts.
• Stock quotes.
• Digital copies of the software
• News.

ADVANTAGES OF NS-2 MULTI-CASTING PROJECTS:

• Reduce internet bandwidth usage.


• It will increase productivity.
• Use group address.
• Can be used across a WAN.
• Datagram received only by the interfaces that want it.
• Messages are UDP so there is no connection setup or teardown.
# Schedule events

$ns at 0.5 "$cbr1 start"


$ns at 9.5 "$cbr1 stop"
$ns at 0.5 "$cbr2 start"
$ns at 9.5 "$cbr2 stop"

#post-processing

$ns at 10.0 "finish"


proc finish {} {
global ns tf
$ns flush-trace
close $tf
exec nam [Link] &
exit 0
}

$ns set-animation-rate 3.0ms


$ns run
OUTPUT:
RESULT:

Thus the C program to create a network scenario and study the multicast
communications using the NS-2 simulator tool has been executed successfully.
Ex. No: 12 Date:
FILE TRANSFER USING TCP/IP PROTOCOL

AIM:
Write a C program to establish a connection between two computers using
TCP/IP socket and to make the Server send the content of the requested file to the Client if the
file is present.

THEORY:

FILE TRANSFER TCP ALGORITHM:

SERVER SIDE FILER TRANSFER TCP ALGORITHM:

STEP 1: Start the program.


STEP 2: Declare the variables and structure for the socket.
STEP 3: Create a socket using socket functions
STEP 4: The socket is binded at the specified port.
STEP 5: Using the object the port and address are declared.
STEP 6: After the binding is executed the file is specified.
STEP 7: Then the file is specified.
STEP 8: Execute the client program.

CLIENT FILE TRANSFER TCP PROGRAMMING ALGORITHM:

STEP 1: Start the program.


STEP 2: Declare the variables and structure.
STEP 3: Socket is created and connects function is executed.
STEP 4: If the connection is successful then server sends the message.
STEP 5: The file name that is to be transferred is specified in the client side.
STEP 6: The contents of the file is verified from the server side.
STEP 7: Stop the program
PROGRAM:

TCP SERVER:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024

void write_file(int sockfd){


int n;
FILE *fp;
char *filename = "[Link]";
char buffer[SIZE];

fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0){
break;
return;
}
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
return;
}

int main(){
char *ip = "[Link]";
int port = 8080;
int e;

int sockfd, new_sock;


struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
char buffer[SIZE];

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");

server_addr.sin_family = AF_INET;
server_addr.sin_port = port;
server_addr.sin_addr.s_addr = inet_addr(ip);
TCP (TRANSMISSION CONTROL PROTOCOL):

A TCP (transmission control protocol) is a connection-oriented communication. It is an


intermediate layer of the application layer and internet protocol layer in the OSI model. TCP is
designed to send the data packets over the network. It ensures that data is delivered to the
correct destination.

A socket is an abstraction through which an application may send and receive data, in pretty
much the same way as opening a file to read and write data.

TCP creates a connection between the source and destination node before transmitting the data
and keeps the connection alive until the communication is active.

In TCP before sending the data it breaks the large data into smaller packets and cares the
integrity of the data at the time of reassembling at the destination node. Major Internet
applications such as the World Wide Web, email, remote administration, and file transfer rely
on TCP.

TCP also offers the facility of retransmission, when a TCP client sends data to the server, it
requires an acknowledgment in return. If an acknowledgment is not received, after a certain
amount of time transmitted data will be lost and TCP automatically retransmits the data.

The communication over the network in TCP/IP model takes place in form of a client-server
architecture. ie, the client begins the communication and establishes a connection with a server.
e = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(e < 0) {
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successfull.\n");

if(listen(sockfd, 10) == 0){


printf("[+]Listening....\n");
}else{
perror("[-]Error in listening");
exit(1);
}

addr_size = sizeof(new_addr);
new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size);
write_file(new_sock);
printf("[+]Data written in the file successfully.\n");

return 0;
}

OUTPUT:
TCP CLIENT:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#define SIZE 1024

void send_file(FILE *fp, int sockfd){


int n;
char data[SIZE] = {0};

while(fgets(data, SIZE, fp) != NULL) {


if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}

int main(){
char *ip = "[Link]";
int port = 8080;
int e;

int sockfd;
struct sockaddr_in server_addr;
FILE *fp;
char *filename = "[Link]";

sockfd = socket(AF_INET, SOCK_STREAM, 0);


if(sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");

server_addr.sin_family = AF_INET;
server_addr.sin_port = port;
server_addr.sin_addr.s_addr = inet_addr(ip);

e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));


APPLICATIONS OF TCP/IP PROTOCOLS

Bootstrap Protocols

It provides the dynamic methods for identifying the servers and dispense the dynamic methods.
Such as address and initial program load, internet protocol.

Connecting to the Internet

To connect the IBM operating system are networking service provider or else configuring the
operating systems consist both the application server or else web server. For the most part, it is
the uses of internet setup data and information to affix.

Domain Name System

In reality it is distributed data type for running the hostnames and they are associating the IP
addresses.

Dynamic Hosting Configuration

The TCP/IP standard are consists the DHCP that will use the central server to manage the
internet protocol addresses in Embedded Programming. In particular dynamic and other
configuration details about the whole network.

REXEC

The remote execution server is having the transmission control protocols or else IP applications
that will allow the client users to submit their remote system. Especially it will enable the
processing of both the programs and also a command to hosting on the internet.

Virtual Private Networking

As a matter of fact it enables the stable ad to enlarge their private process over the existing
framework of a public processor. Such as the VPN companies are controlling the networking
traffics while providing the essential security types, i.e. data privacy.

BENEFITS OF TCP/IP PROTOCOLS

The standard model which it is consists the effectively established in practical problems. In the
final analysis, It allows the cross platforms which it is communicating among the heterogeneous
networking. Open protocols are a unique process using any individual or else organizations.
With attention to both the client-server and also scalable architecture allows the Latest
Networking which is adding a disrupting the latest services. It is assigning the internet protocols
are having an entire computer on the network.
if(e == -1) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Connected to Server.\n");

fp = fopen(filename, "r");
if (fp == NULL) {
perror("[-]Error in reading file.");
exit(1);
}

send_file(fp, sockfd);
printf("[+]File data sent successfully.\n");

printf("[+]Closing the connection.\n");


close(sockfd);

return 0;
}

OUTPUT:
OUTPUT:
RESULT:

Thus the connection between two computers using TCP File Transfer Client-Server was
implemented and verified successfully.
Ex. No: 6 Date:
COMMUNICATION BETWEEN PC’S

AIM:
Write a C program to establish a connection between two computers using TCP/IP
socket and share data between them.

ALGORITHM:

SERVER:
1. Create a TCP socket.
2. Bind the socket to Server address.
3. Listen to the Client.
4. Accept and make the connection.
5. Listen to the Client, read the received/buffered characters and print them.
6. Receive the characters from the console, write the message into the buffer for sending
to Client.
7. Go to Step 5.

CLIENT:
1. Create a TCP socket.
2. Connect the socket to the Server.
3. Receive the characters from the console, write the message into the buffer for sending
to Server.
4. Listen to the Server, read the buffered characters and print them.
5. Go to Step 3.

THEORY:

TCP/IP MODEL:

o The TCP/IP model was developed prior to the OSI model.


o The TCP/IP model is not exactly similar to the OSI model.
o The TCP/IP model consists of five layers: the application layer, transport layer, network
layer, data link layer and physical layer.
o The first four layers provide physical standards, network interface, internetworking, and
transport functions that correspond to the first four layers of the OSI model and these
four layers are represented in TCP/IP model by a single layer called the application
layer.
o TCP/IP is a hierarchical protocol made up of interactive modules, and each of them
provides specific functionality.
PROGRAM:
TCP SERVER:

#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr

// Function designed for chat between client and server.


void func(int connfd)
{
char buff[MAX];
int n;
// infinite loop for chat
for (;;) {
bzero(buff, MAX);

// read the message from client and copy it in buffer


read(connfd, buff, sizeof(buff));
// print buffer which contains the client contents
printf("From client: %s\t To client : ", buff);
bzero(buff, MAX);
n = 0;
// copy server message in the buffer
while ((buff[n++] = getchar()) != '\n')
;

// and send that buffer to client


write(connfd, buff, sizeof(buff));

// if msg contains "Exit" then server exit and chat ended.


if (strncmp("exit", buff, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
}

// Driver function
int main()
{
int sockfd, connfd, len;
struct sockaddr_in servaddr, cli;

// socket create and verification


FUNCTIONS OF TCP/IP LAYERS:

Network Access Layer:


o A network layer is the lowest layer of the TCP/IP model.
o A network layer is the combination of the Physical layer and Data Link layer defined in
the OSI reference model.
o It defines how the data should be sent physically through the network.
o This layer is mainly responsible for the transmission of the data between two devices on
the same network.
o The functions carried out by this layer are encapsulating the IP datagram into frames
transmitted by the network and mapping of IP addresses into physical addresses.
o The protocols used by this layer are ethernet, token ring, FDDI, X.25, frame relay.

Internet Layer:
o An internet layer is the second layer of the TCP/IP model.
o An internet layer is also known as the network layer.
o The main responsibility of the internet layer is to send the packets from any network,
and they arrive at the destination irrespective of the route they take.
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));

// assign IP, PORT


servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);

// Binding newly created socket to given IP and verification


if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...\n");
exit(0);
}
else
printf("Socket successfully binded..\n");

// Now server is ready to listen and verification


if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...\n");
exit(0);
}
else
printf("Server listening..\n");
len = sizeof(cli);

// Accept the data packet from client and verification


connfd = accept(sockfd, (SA*)&cli, &len);
if (connfd < 0) {
printf("server accept failed...\n");
exit(0);
}
else
printf("server accept the client...\n");

// Function for chatting between client and server


func(connfd);

// After chatting close the socket


close(sockfd);
IP Protocol: IP protocol is used in this layer, and it is the most significant part of the entire
TCP/IP suite.

Following are the responsibilities of this protocol:

o IP Addressing: This protocol implements logical host addresses known as IP addresses.


The IP addresses are used by the internet and higher layers to identify the device and to
provide internetwork routing.
o Host-to-host communication: It determines the path through which the data is to be
transmitted.
o Data Encapsulation and Formatting: An IP protocol accepts the data from the
transport layer protocol. An IP protocol ensures that the data is sent and received
securely, it encapsulates the data into message known as IP datagram.
o Fragmentation and Reassembly: The limit imposed on the size of the IP datagram by
data link layer protocol is known as Maximum Transmission unit (MTU). If the size of
IP datagram is greater than the MTU unit, then the IP protocol splits the datagram into
smaller units so that they can travel over the local network. Fragmentation can be done
by the sender or intermediate router. At the receiver side, all the fragments are
reassembled to form an original message.
o Routing: When IP datagram is sent over the same local network such as LAN, MAN,
WAN, it is known as direct delivery. When source and destination are on the distant
network, then the IP datagram is sent indirectly. This can be accomplished by routing
the IP datagram through various devices such as routers.

Transmission Control Protocol (TCP):

o It provides a full transport layer services to applications.


o It creates a virtual circuit between the sender and receiver, and it is active for the
duration of the transmission.
o TCP is a reliable protocol as it detects the error and retransmits the damaged frames.
Therefore, it ensures all the segments must be received and acknowledged before the
transmission is considered to be completed and a virtual circuit is discarded.
o At the sending end, TCP divides the whole message into smaller units known as
segment, and each segment contains a sequence number which is required for
reordering the frames to form an original message.
o At the receiving end, TCP collects all the segments and reorders them based on
sequence numbers.
TCP CLIENT:

#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd)
{
char buff[MAX];
int n;
for (;;) {
bzero(buff, sizeof(buff));
printf("Enter the string : ");
n = 0;
while ((buff[n++] = getchar()) != '\n')
;
write(sockfd, buff, sizeof(buff));
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server : %s", buff);
if ((strncmp(buff, "exit", 4)) == 0) {
printf("Client Exit...\n");
break;
}
}
}

int main()
{
int sockfd, connfd;
struct sockaddr_in servaddr, cli;

// socket create and verification


sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...\n");
exit(0);
}
else
printf("Socket successfully created..\n");
bzero(&servaddr, sizeof(servaddr));

// assign IP, PORT


servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("[Link]");
servaddr.sin_port = htons(PORT);
// connect the client socket to server socket
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");

// function for chat


func(sockfd);

// close the socket


close(sockfd);
}
OUTPUT:
RESULT:

Thus a connection between two computers using TCP/IP socket was implemented and
verified successfully.
Ex. No: 9 Date:
PACKET SNIFFER

AIM:
Write a C program to implement a basic packet sniffer and identify packet type by
parsing the IP packet header.

THEORY:

PACKET SNIFFING:

In IT operations, ensuring secure and reliable communications over different networks


is a crucial requirement. IT administrators have to rely on different protocols, networking best
practices, and network monitoring tools to ensure the flow of data in a network meets various
standards for security and Quality of Service (QoS). One of these common practices is known
as packet sniffing, which helps IT administrators keep track of packets (small formatted units of
data) and ensure they’re transferred smoothly. While the packet sniffing technique is often
associated with cyberattacks, it’s commonly used by internet service providers, government
agencies, advertisers, and even large organizations for network monitoring. In this article, we’ll
discuss packet sniffing in detail and also explore commonly used tools by IT practitioners.

All networks consist of several components, such as workstations, servers, networking


hardware, and more. In the networking terminology, all these components are called nodes. A
healthy network connection ensures the data between these nodes is transferred reliably and at
an acceptable speed according to the bandwidth and throughput of the network. While most of
the traditional networks maintain physical or wired connections, modern networks are a mix of
physical and wireless connections. However, the concepts of data transfer in all such networks
remain the same.

In networking, the data is transferred in the form of packets, or small chunks of data.
These packets vary in their format, depending on the network protocol (TCP/IP, UDP, etc.). In
addition to the actual information or data, all packets contain control information designed to
help in the delivery of packets from source to destination. The control information is required as
packets intended to be transferred to a specific node often pass through several nodes in a
network and can end up at the wrong node. The control information includes IP addresses of the
sender and the receiver, packet sequencing information (e.g., packet number), and more to
ensure packets reach the right destination. However, the transfer of packets in a network can get
disrupted due to several issues and network errors.

.
PROGRAM:

#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h> //For standard things
#include<stdlib.h> //malloc
#include<string.h> //strlen

#include<netinet/ip_icmp.h> //Provides declarations for icmp header


#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
#include<netinet/if_ether.h> //For ETH_P_ALL
#include<net/ethernet.h> //For ether_header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

void ProcessPacket(unsigned char* , int);

FILE *logfile;
struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,arp=0,ospf=0,total=0,i,j;

int main()
{
int saddr_size , data_size;
struct sockaddr saddr;

unsigned char *buffer = (unsigned char *) malloc(65536);

logfile=fopen("[Link]","w");
if(logfile==NULL)
{
printf("Unable to create [Link] file.");
}
printf("Starting...\n");

int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;


setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );

if(sock_raw < 0)
{
//Print the error with proper message
perror("Socket Error");
return 1;
}
In protocols like TCP/IP, there’s no inherent mechanism to recover the packets lost in
transmission. However, network architects use the protocol in only fault-tolerant networks,
where losses below certain thresholds are acceptable and don’t affect the communication.
However, in protocols like UDP, the sender continues to resend the packet until it receives the
acknowledgment of receipt from the receiver. While it adds reliability to the transmission, it
also increases resource consumption. If left unchecked, it can lead to significant delays in
overall transmission rates. This is where packet sniffers offer a solution.

With a packet sniffer, sometimes also called packet analyser, network administrators can
monitor their network traffic and gain valuable insights about their infrastructure and its
performance. It allows them to measure the traffic flow in a network and also identify which
applications are using the maximum bandwidth.

TYPES OF PACKET SNIFFERS:

Hardware Packet Sniffers:

As the name suggests, it’s a hardware component plugged into a network for packet
sniffing or network analysis purposes. Hardware packet sniffers are commonly used when
network administrators have to analyse or monitor a particular segment of a large network.
With a physical connection, these packet sniffers allow administrators to ensure all packets are
captured without any loss due to routing, filtering, or any other network issue. A hardware
packet sniffer can have the facility to store the packets, or they can be programmed to forward
all captured packers to a centralized location for further analysis.

Software Packet Sniffers:

Software Packet Sniffers are the more common type of packet sniffers used by many
organizations. Every computer or node connects to the network using a Network Interface Card
(NIC), which is generally configured to ignore the packets not addressed to it. However, a
Software Packet Sniffer changes this behavior, so one can receive every bit of network traffic
for analysis. The NIC configuration is known as promiscuous mode. The amount of information
collected depends on whether the packet sniffer is set on filtered or unfiltered mode.

BENEFITS OF PACKET SNIFFING:

• Detecting the Root Cause of a Network Issue


• Troubleshooting Network Issues
• Traffic Analysis
• Bandwidth Management
• Network Security and Compliance
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
ProcessPacket(buffer , data_size);
}
close(sock_raw);
printf("Finished");
return 0;
}

/* This function will parse the packet read and identifies the packet type (ICMP, ARP etc
* based on the IP header protocol type */

void ProcessPacket(unsigned char* buffer, int size)


{
//Get the IP Header part of this packet , excluding the ethernet header
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
++total;

switch (iph->protocol)
/* Check the Protocol type */
{
/* ICMP Protocol */
case 1:
++icmp;
break;
case 2:
++igmp;
break;
case 6:
++tcp;
break;
case 17:
/* UDP packet */
++udp;
break;
case 89:
/* OSPF packet */
++ospf;
break;
default:
++others;
break;
}
printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r",
tcp, udp, icmp, igmp, others, total);
}

OUTPUT:
RESULT:

Thus the C program to implement a basic packet sniffer and identifying packet type is
implemented and verified successfully.
Ex. No: 9 b.) Date:
PACKET SNIFFER

AIM:
Write a C program to implement a basic packet sniffer and identify packet type by parsing
the IP packet header.

THEORY:

PACKET SNIFFING:

In IT operations, ensuring secure and reliable communications over different networks is


a crucial requirement. IT administrators have to rely on different protocols, networking best
practices, and network monitoring tools to ensure the flow of data in a network meets various
standards for security and Quality of Service (QoS). One of these common practices is known as
packet sniffing, which helps IT administrators keep track of packets (small formatted units of
data) and ensure they’re transferred smoothly. While the packet sniffing technique is often
associated with cyberattacks, it’s commonly used by internet service providers, government
agencies, advertisers, and even large organizations for network monitoring. In this article, we’ll
discuss packet sniffing in detail and also explore commonly used tools by IT practitioners.

All networks consist of several components, such as workstations, servers, networking


hardware, and more. In the networking terminology, all these components are called nodes. A
healthy network connection ensures the data between these nodes is transferred reliably and at an
acceptable speed according to the bandwidth and throughput of the network. While most
traditional networks maintain physical or wired connections, modern networks are a mix of
physical and wireless connections. However, the concepts of data transfer in all such networks
remain the same.

In networking, the data is transferred in the form of packets, or small chunks of data.
These packets vary in their format, depending on the network protocol (TCP/IP, UDP, etc.). In
addition to the actual information or data, all packets contain control information designed to help
in the delivery of packets from source to destination. The control information is required as
packets intended to be transferred to a specific node often pass through several nodes in a network
and can end up at the wrong node. The control information includes IP addresses of the sender
and the receiver, packet sequencing information (e.g., packet number), and more to ensure
packets reach the right destination. However, the transfer of packets in a network can get
disrupted due to several issues and network errors.

.
PROGRAM:

#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h> //For standard things
#include<stdlib.h> //malloc
#include<string.h> //strlen

#include<netinet/ip_icmp.h> //Provides declarations for icmp header


#include<netinet/udp.h> //Provides declarations for udp header
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h> //Provides declarations for ip header
#include<netinet/if_ether.h> //For ETH_P_ALL
#include<net/ethernet.h> //For ether_header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

void ProcessPacket(unsigned char* , int);

FILE *logfile;
struct sockaddr_in source,dest;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,arp=0,ospf=0,total=0,i,j;

int main()
{
int saddr_size , data_size;
struct sockaddr saddr;

unsigned char *buffer = (unsigned char *) malloc(65536);

logfile=fopen("[Link]","w");
if(logfile==NULL)
{
printf("Unable to create [Link] file.");
}
printf("Starting...\n");

int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;


setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , "eth0" , strlen("eth0")+ 1 );

if(sock_raw < 0)
{
//Print the error with proper message
perror("Socket Error");
return 1;
}
In protocols like TCP/IP, there’s no inherent mechanism to recover the packets lost in
transmission. However, network architects use the protocol in only fault-tolerant networks, where
losses below certain thresholds are acceptable and don’t affect communication. However, in
protocols like UDP, the sender continues to resend the packet until it receives the
acknowledgment of receipt from the receiver. While it adds reliability to the transmission, it also
increases resource consumption. If left unchecked, it can lead to significant delays in overall
transmission rates. This is where packet sniffers offer a solution.

With a packet sniffer, sometimes also called a packet analyzer, network administrators
can monitor their network traffic and gain valuable insights into their infrastructure and its
performance. It allows them to measure the traffic flow in a network and also identify which
applications are using the maximum bandwidth.

Packet sniffers are programs that intercept the network traffic flowing in and out of a system
through network interfaces. So if you are browsing the internet then traffic is flowing and a
packet sniffer would be able to catch it in the form of packets and display them for whatever
reasons required. Packet sniffers are used for various needs like analyzing protocols, monitoring
networks, and assessing the security of a network. Wireshark for example is the most popular
packet sniffer out there and is available for all platforms. It GUI based and very easy to use.
In this post, we are going to talk about how to code and make our packet sniffer in C and on the
Linux platform. By Linux, it means that the code sample shown here would work only on Linux
and not windows. Packet sniffers can be coded by either using sockets API provided by the
kernel, or by using some packet capture library like libpcap. In this tutorial we shall be covering
the first method, that is by using sockets.

TYPES OF PACKET SNIFFERS:

Hardware Packet Sniffers:

As the name suggests, it’s a hardware component plugged into a network for packet
sniffing or network analysis purposes. Hardware packet sniffers are commonly used when
network administrators have to analyze or monitor a particular segment of a large network. With
a physical connection, these packet sniffers allow administrators to ensure all packets are captured
without any loss due to routing, filtering, or any other network issue. A hardware packet sniffer
can have the facility to store the packets, or they can be programmed to forward all captured
packers to a centralized location for further analysis.

Software Packet Sniffers:

Software Packet Sniffers are the more common type of packet sniffers used by many
organizations. Every computer or node connects to the network using a Network Interface Card
(NIC), which is generally configured to ignore the packets not addressed to it. However, a
Software Packet Sniffer changes this behavior, so one can receive every bit of network traffic for
analysis. The NIC configuration is known as promiscuous mode. The amount of information
collected depends on whether the packet sniffer is set in filtered or unfiltered mode.
while(1)
{
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
if(data_size <0 )
{
printf("Recvfrom error , failed to get packets\n");
return 1;
}
ProcessPacket(buffer , data_size);
}
close(sock_raw);
printf("Finished");
return 0;
}

/* This function will parse the packet read and identifies the packet type (ICMP, ARP, etc
* based on the IP header protocol type */

void ProcessPacket(unsigned char* buffer, int size)


{
//Get the IP Header part of this packet , excluding the ethernet header
struct iphdr *iph = (struct iphdr*)(buffer + sizeof(struct ethhdr));
++total;

switch (iph->protocol)
/* Check the Protocol type */
{
/* ICMP Protocol */
case 1:
++icmp;
break;
case 2:
++igmp;
break;
case 6:
++tcp;
break;
case 17:
/* UDP packet */
++udp;
break;
case 89:
/* OSPF packet */
++ospf;
break;
default:
++others;
break;
}
BENEFITS OF PACKET SNIFFING:

• Detecting the Root Cause of a Network Issue


• Troubleshooting Network Issues
• Traffic Analysis
• Bandwidth Management
• Network Security and Compliance
printf("TCP : %d UDP : %d ICMP : %d IGMP : %d Others : %d Total : %d\r",
tcp, udp, icmp, igmp, others, total);
}

void print_ip_header(unsigned char* Buffer, int Size)


{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;


iphdrlen =iph->ihl*4;

memset(&source, 0, sizeof(source));
source.sin_addr.s_addr = iph->saddr;

memset(&dest, 0, sizeof(dest));
dest.sin_addr.s_addr = iph->daddr;

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
fprintf(logfile," |-IP Version : %d\n",(unsigned int)iph->version);
fprintf(logfile," |-IP Header Length : %d DWORDS or %d Bytes\n",(unsigned int)iph-
>ihl,((unsigned int)(iph->ihl))*4);
fprintf(logfile," |-Type Of Service : %d\n",(unsigned int)iph->tos);
fprintf(logfile," |-IP Total Length : %d Bytes(Size of Packet)\n",ntohs(iph->tot_len));
fprintf(logfile," |-Identification : %d\n",ntohs(iph->id));
//fprintf(logfile," |-Reserved ZERO Field : %d\n",(unsigned int)iphdr-
>ip_reserved_zero);
//fprintf(logfile," |-Dont Fragment Field : %d\n",(unsigned int)iphdr-
>ip_dont_fragment);
//fprintf(logfile," |-More Fragment Field : %d\n",(unsigned int)iphdr-
>ip_more_fragment);
fprintf(logfile," |-TTL : %d\n",(unsigned int)iph->ttl);
fprintf(logfile," |-Protocol : %d\n",(unsigned int)iph->protocol);
fprintf(logfile," |-Checksum : %d\n",ntohs(iph->check));
fprintf(logfile," |-Source IP : %s\n",inet_ntoa(source.sin_addr));
fprintf(logfile," |-Destination IP : %s\n",inet_ntoa(dest.sin_addr));
}

void print_tcp_packet(unsigned char* Buffer, int Size)


{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;


iphdrlen = iph->ihl*4;

struct tcphdr *tcph=(struct tcphdr*)(Buffer + iphdrlen);

fprintf(logfile,"\n\n********************TCP Packet********************\n");
print_ip_header(Buffer,Size);

fprintf(logfile,"\n");
fprintf(logfile,"TCP Header\n");
fprintf(logfile," |-Source Port : %u\n",ntohs(tcph->source));
fprintf(logfile," |-Destination Port : %u\n",ntohs(tcph->dest));
fprintf(logfile," |-Sequence Number : %u\n",ntohl(tcph->seq));
fprintf(logfile," |-Acknowledge Number : %u\n",ntohl(tcph->ack_seq));
fprintf(logfile," |-Header Length : %d DWORDS or %d BYTES\n" ,(unsigned
int)tcph->doff,(unsigned int)tcph->doff*4);
//fprintf(logfile," |-CWR Flag : %d\n",(unsigned int)tcph->cwr);
//fprintf(logfile," |-ECN Flag : %d\n",(unsigned int)tcph->ece);
fprintf(logfile," |-Urgent Flag : %d\n",(unsigned int)tcph->urg);
fprintf(logfile," |-Acknowledgement Flag : %d\n",(unsigned int)tcph->ack);
fprintf(logfile," |-Push Flag : %d\n",(unsigned int)tcph->psh);
fprintf(logfile," |-Reset Flag : %d\n",(unsigned int)tcph->rst);
fprintf(logfile," |-Synchronise Flag : %d\n",(unsigned int)tcph->syn);
fprintf(logfile," |-Finish Flag : %d\n",(unsigned int)tcph->fin);
fprintf(logfile," |-Window : %d\n",ntohs(tcph->window));
fprintf(logfile," |-Checksum : %d\n",ntohs(tcph->check));
fprintf(logfile," |-Urgent Pointer : %d\n",tcph->urg_ptr);
fprintf(logfile,"\n");
fprintf(logfile," DATA Dump ");
fprintf(logfile,"\n");

fprintf(logfile,"IP Header\n");
PrintData(Buffer,iphdrlen);

fprintf(logfile,"TCP Header\n");
PrintData(Buffer+iphdrlen,tcph->doff*4);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + tcph->doff*4 , (Size - tcph->doff*4-iph->ihl*4) );

fprintf(logfile,"\n#######################################################");
}

void print_udp_packet(unsigned char *Buffer , int Size)


{

unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;


iphdrlen = iph->ihl*4;

struct udphdr *udph = (struct udphdr*)(Buffer + iphdrlen);

fprintf(logfile,"\n\n********************UDP Packet**********************\n");

print_ip_header(Buffer,Size);
fprintf(logfile,"\nUDP Header\n");
fprintf(logfile," |-Source Port : %d\n" , ntohs(udph->source));
fprintf(logfile," |-Destination Port : %d\n" , ntohs(udph->dest));
fprintf(logfile," |-UDP Length : %d\n" , ntohs(udph->len));
fprintf(logfile," |-UDP Checksum : %d\n" , ntohs(udph->check));

fprintf(logfile,"\n");
fprintf(logfile,"IP Header\n");
PrintData(Buffer , iphdrlen);

fprintf(logfile,"UDP Header\n");
PrintData(Buffer+iphdrlen , sizeof udph);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + sizeof udph ,( Size - sizeof udph - iph->ihl * 4 ));

fprintf(logfile,"\n#######################################################");
}

void print_icmp_packet(unsigned char* Buffer , int Size)


{
unsigned short iphdrlen;

struct iphdr *iph = (struct iphdr *)Buffer;


iphdrlen = iph->ihl*4;

struct icmphdr *icmph = (struct icmphdr *)(Buffer + iphdrlen);

fprintf(logfile,"\n\n*******************ICMP Packet**********************\n");

print_ip_header(Buffer , Size);

fprintf(logfile,"\n");

fprintf(logfile,"ICMP Header\n");
fprintf(logfile," |-Type : %d",(unsigned int)(icmph->type));

if((unsigned int)(icmph->type) == 11)


fprintf(logfile," (TTL Expired)\n");
else if((unsigned int)(icmph->type) == ICMP_ECHOREPLY)
fprintf(logfile," (ICMP Echo Reply)\n");
fprintf(logfile," |-Code : %d\n",(unsigned int)(icmph->code));
fprintf(logfile," |-Checksum : %d\n",ntohs(icmph->checksum));
//fprintf(logfile," |-ID : %d\n",ntohs(icmph->id));
//fprintf(logfile," |-Sequence : %d\n",ntohs(icmph->sequence));
fprintf(logfile,"\n");

fprintf(logfile,"IP Header\n");
PrintData(Buffer,iphdrlen);
fprintf(logfile,"UDP Header\n");
PrintData(Buffer + iphdrlen , sizeof icmph);

fprintf(logfile,"Data Payload\n");
PrintData(Buffer + iphdrlen + sizeof icmph , (Size - sizeof icmph - iph->ihl * 4));

fprintf(logfile,"\n#######################################################");
}

void PrintData (unsigned char* data , int Size)


{

for(i=0 ; i < Size ; i++)


{
if( i!=0 && i%16==0) //if one line of hex printing is complete...
{
fprintf(logfile," ");
for(j=i-16 ; j<i ; j++)
{
if(data[j]>=32 && data[j]<=128)
fprintf(logfile,"%c",(unsigned char)data[j]); //if its a
number or alphabet

else fprintf(logfile,"."); //otherwise print a dot


}
fprintf(logfile,"\n");
}

if(i%16==0) fprintf(logfile," ");


fprintf(logfile," %02X",(unsigned int)data[i]);

if( i==Size-1) //print the last spaces


{
for(j=0;j<15-i%16;j++) fprintf(logfile," "); //extra spaces

fprintf(logfile," ");

for(j=i-i%16 ; j<=i ; j++)


{
if(data[j]>=32 && data[j]<=128) fprintf(logfile,"%c",(unsigned
char)data[j]);
else fprintf(logfile,".");
}
fprintf(logfile,"\n");
}
}
}
OUTPUT:
RESULT:

Thus the C program to implement a basic packet sniffer and identifying packet type is
implemented and verified successfully.

You might also like