Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
master-embedded-systems
c-exercise-solutions public
Commits
d94a228b
Commit
d94a228b
authored
Aug 30, 2017
by
Dominik Widhalm
Browse files
Added example solutions for task 6.13
parent
8bf59fa1
Changes
2
Hide whitespace changes
Inline
Side-by-side
ch_6/task_13/main.c
0 → 100644
View file @
d94a228b
/******************************************************************************
* C PROGRAMMING *
* BASIC EXERCISES - EXAMPLE SOLUTIONS *
* *
* Task_6.13: TCP/IP Parser *
* Author: Dominik Widhalm *
* Email: dominik.widhalm@technikum-wien.at *
* Date: 2017-08-30 *
* *
******************************************************************************/
/***** INCLUDES ***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/***** MACROS *****************************************************************/
/*** ETH Protocol ***/
// Internet Protocol Version 4
#define ETHERTYPE_IP4 0x0800
// Address Resolution Protocol
#define ETHERTYPE_ARP 0x0806
// Internet Protocol Version 6
#define ETHERTYPE_IP6 0x86DD
// Precision Time Protocol
#define ETHERTYPE_PTP 0x88F7
/*** IP Protocol ***/
// Internet Control Message Protocol
#define IPTYPE_ICMP 0x01
// Internet Group Management Protocol
#define IPTYPE_IGMP 0x02
// Transmission Control Protocol
#define IPTYPE_TCP 0x06
// User Datagram Protocol
#define IPTYPE_UDP 0x11
/*** TCP Flag Offsets & Masks ***/
// Urgent Flag
#define TCP_OSET_URG 5
#define TCP_MASK_URG (1<<TCP_OSET_URG)
// Acknowledgement Flag
#define TCP_OSET_ACK 4
#define TCP_MASK_ACK (1<<TCP_OSET_ACK)
// Push Flag
#define TCP_OSET_PSH 3
#define TCP_MASK_PSH (1<<TCP_OSET_PSH)
// Reset Flag
#define TCP_OSET_RST 2
#define TCP_MASK_RST (1<<TCP_OSET_RST)
// Synchronise Flag
#define TCP_OSET_SYN 1
#define TCP_MASK_SYN (1<<TCP_OSET_SYN)
// Finish Flag
#define TCP_OSET_FIN 0
#define TCP_MASK_FIN (1<<TCP_OSET_FIN)
/*** Macro Functions ***/
// Macro to convert between little and big endian
#define LITTLE2BIG16(x) ((uint16_t)((x>>8) | (x<<8)))
/***** TYPEDEFS ***************************************************************/
/*** Unions ***/
/* Union to access MAC addresses either byte- or wordwise */
typedef
union
mac_a
{
uint8_t
b
[
6
];
uint16_t
w
[
3
];
}
MAC_A
;
/* Union to access IP addresses either byte- or wordwise */
typedef
union
ip_a
{
uint8_t
b
[
4
];
uint16_t
w
[
2
];
uint32_t
d
;
}
IP_A
;
/*** Structures ***/
/* Structure for an Ethernet header */
typedef
struct
eth
{
MAC_A
destination
;
// 6 Byte destination address
MAC_A
source
;
// 6 Byte source address
uint16_t
protocol
;
// 2 Byte ethernet type
uint8_t
data
[
1
];
// data origin (pseudo-pointer)
}
ETH_t
;
/* Structure for an IP header */
typedef
struct
ip
{
uint8_t
version
;
// 1 Byte version (bit 0-3) and IHL (bit 4-7)
uint8_t
service_type
;
// 1 Byte type of service
uint16_t
length
;
// 2 Bytes total length
uint16_t
identification
;
// 2 Bytes identification
uint16_t
flags
;
// 2 Bytes flags (bit 0-2) and fragment offset (bit 3- 15)
uint8_t
ttl
;
// 1 Byte Time-To-Live
uint8_t
protocol
;
// 1 Byte protocol
uint16_t
header_checksum
;
// 2 Bytes header checksum
IP_A
source
;
// 4 Bytes source IP address
IP_A
destination
;
// 4 Bytes destination IP address
uint8_t
data
[
1
];
// data origin (pseudo-pointer)
}
IP_t
;
/* Structure for a TCP header */
typedef
struct
tcp
{
uint16_t
source_port
;
// 2 Byte source port
uint16_t
destination_port
;
// 2 Byte destination port
uint32_t
sequence
;
// 4 Byte sequence number
uint32_t
ack_number
;
// 4 Byte acknowledgement number
uint16_t
data_flags
;
// 2 Byte data offset (bit 0-3) and flags (bit 7-15)
uint16_t
window_size
;
// 2 Byte window size
uint16_t
checksum
;
// 2 Byte checksum
uint16_t
urgent
;
// 2 Byte urgent pointer
uint8_t
data
[
1
];
// data origin (pseudo-pointer)
}
TCP_t
;
/***** GLOBAL VARIABLES *******************************************************/
uint8_t
sample
[]
=
{
0xFE
,
0xFF
,
0x20
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
\
0x00
,
0x00
,
0x08
,
0x00
,
0x45
,
0x00
,
0x00
,
0x28
,
0x0F
,
0x4E
,
\
0x40
,
0x00
,
0x80
,
0x06
,
0x91
,
0xE6
,
0x91
,
0xFE
,
0xA0
,
0xED
,
\
0x41
,
0xD0
,
0xE4
,
0xDF
,
0x0D
,
0x2C
,
0x00
,
0x50
,
0x38
,
0xAF
,
\
0xFF
,
0xF3
,
0x11
,
0x4C
,
0x81
,
0xE4
,
0x50
,
0x10
,
0x25
,
0xBC
,
\
0x57
,
0x2D
,
0x00
,
0x00
};
/***** FUNCTION PROTOTYPES ****************************************************/
void
print_binary
(
uint8_t
data
,
uint8_t
count
);
void
address_print_mac
(
MAC_A
*
mac
);
void
address_print_ip
(
IP_A
*
ip
);
uint16_t
eth_get_header_length
(
void
);
uint16_t
eth_get_total_length
(
ETH_t
*
frame
);
void
eth_print_protocol
(
uint16_t
type
);
void
ip_print_protocol
(
uint8_t
type
);
void
eth_print
(
ETH_t
*
frame
);
void
ip_print
(
IP_t
*
frame
);
void
tcp_print
(
TCP_t
*
frame
);
/***** LOCAL FUNCTIONS ********************************************************/
/******************************************************************************
* print_binary *
* @brief Function to print a given 8-bit value in binary form. *
* *
* This function prints the given 8-bit value in binary form. *
* *
* @param data 8-bit value *
* @param count Number of bits to be printed *
******************************************************************************/
void
print_binary
(
uint8_t
data
,
uint8_t
count
)
{
/* Iterate over all 8 bits */
for
(
int
i
=
(
count
-
1
);
i
>=
0
;
i
--
)
{
/* Print current bit */
if
(
data
&
(
1
<<
i
))
{
/* Bit is 1 */
printf
(
"1"
);
}
else
{
/* Bit is 0 */
printf
(
"0"
);
}
/* If not the last (LSB) bit ... */
if
(
i
>
0
)
{
/* Print separator */
printf
(
" "
);
}
}
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* address_print_mac *
* @brief Function to print a given MAC address in a formatted way. *
* *
* This function prints the given MAC in the form XX:XX:XX:XX:XX:XX. *
* *
* @param mac Pointer to the MAC address *
******************************************************************************/
void
address_print_mac
(
MAC_A
*
mac
)
{
/* Iterate over all 6 bytes of the MAC address */
for
(
unsigned
int
i
=
0
;
i
<
sizeof
(
MAC_A
);
i
++
)
{
/* Print current byte */
printf
(
"%02X"
,
mac
->
b
[
i
]);
/* If not the last byte ... */
if
(
i
<
(
sizeof
(
MAC_A
)
-
1
))
{
/* ... additionally print a '-' */
printf
(
"-"
);
}
}
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* address_print_ip *
* @brief Function to print a given IP address in a formatted way. *
* *
* This function prints the given IP in the form x.x.x.x. *
* *
* @param ip Pointer to the IP address *
******************************************************************************/
void
address_print_ip
(
IP_A
*
ip
)
{
/* Iterate over all 4 bytes of the IP address */
for
(
unsigned
int
i
=
0
;
i
<
sizeof
(
IP_A
);
i
++
)
{
/* Print current byte */
printf
(
"%u"
,
ip
->
b
[
i
]);
/* If not the last byte ... */
if
(
i
<
(
sizeof
(
IP_A
)
-
1
))
{
/* ... additionally print a ':' */
printf
(
"."
);
}
}
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* eth_get_header_length *
* @brief Function to calculate the ETH header size in bytes. *
* *
* This function returns the size of the ETH header in bytes. *
* *
* @return Size of the ETH header in bytes *
******************************************************************************/
uint16_t
eth_get_header_length
(
void
)
{
/* Return the length of the ETH header */
return
(
uint16_t
)(
2
*
sizeof
(
MAC_A
)
+
sizeof
(
uint16_t
));
}
/******************************************************************************
* eth_get_total_length *
* @brief Function to calculate the frame total size in bytes. *
* *
* This function calculates the total size of the frame according to the *
* derived (fixed) header sizes and the information from the IP frame. *
* *
* @param frame Pointer to the data frame *
* @return Size of the frame in bytes *
******************************************************************************/
uint16_t
eth_get_total_length
(
ETH_t
*
frame
)
{
/* Temporary variable for the number of bytes */
uint16_t
length
=
0
;
/* Temporary pointer to access the IP frame */
IP_t
*
ip_frame
=
(
IP_t
*
)
frame
->
data
;
/* Add the length of the ETH header */
length
+=
eth_get_header_length
();
/* Add the total length of the IP frame */
length
+=
LITTLE2BIG16
(
ip_frame
->
length
);
/* Return the calculated length */
return
length
;
}
/******************************************************************************
* eth_print_protocol *
* @brief Function to print the ETH protocol type. *
* *
* This function prints the name of the given protocol (if known). *
* *
* @param type 16-bit protocol number *
******************************************************************************/
void
eth_print_protocol
(
uint16_t
type
)
{
/* Check if protocol is known */
switch
(
type
)
{
case
ETHERTYPE_IP4
:
printf
(
"IPv4"
);
break
;
case
ETHERTYPE_ARP
:
printf
(
"ARP"
);
break
;
case
ETHERTYPE_IP6
:
printf
(
"IPv6"
);
break
;
case
ETHERTYPE_PTP
:
printf
(
"PTP"
);
break
;
default:
printf
(
"UNKNOWN"
);
break
;
}
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* ip_print_protocol *
* @brief Function to print the IP protocol type. *
* *
* This function prints the name of the given protocol (if known). *
* *
* @param type 8-bit protocol number *
******************************************************************************/
void
ip_print_protocol
(
uint8_t
type
)
{
/* Check if protocol is known */
switch
(
type
)
{
case
IPTYPE_ICMP
:
printf
(
"ICMP"
);
break
;
case
IPTYPE_IGMP
:
printf
(
"IGMP"
);
break
;
case
IPTYPE_TCP
:
printf
(
"TCP"
);
break
;
case
IPTYPE_UDP
:
printf
(
"UDP"
);
break
;
default:
printf
(
"UNKNOWN"
);
break
;
}
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* eth_print *
* @brief Function to print information from ETH frame. *
* *
* This function prints the information contained in a given ETH frame. *
* *
* @param frame Pointer to the data frame *
******************************************************************************/
void
eth_print
(
ETH_t
*
frame
)
{
/* Print output-header */
printf
(
"Ethernet Header:
\n
"
);
/* Print the destination address */
printf
(
" |-Destination Address : "
);
address_print_mac
(
&
(
*
frame
).
destination
);
printf
(
"
\n
"
);
/* Print the source address */
printf
(
" |-Source Address : "
);
address_print_mac
(
&
(
*
frame
).
source
);
printf
(
"
\n
"
);
/* Print the ETH header length */
printf
(
" |-ETH Header Length : %u Bytes
\n
"
,
eth_get_header_length
());
/* Print the ETH total length */
printf
(
" |-ETH Total Length : %u Bytes
\n
"
,
eth_get_total_length
(
frame
));
/* Print the contained protocol */
printf
(
" |-Protocol : 0x%04X ("
,
LITTLE2BIG16
(
frame
->
protocol
));
eth_print_protocol
(
LITTLE2BIG16
(
frame
->
protocol
));
printf
(
")
\n
"
);
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* ip_print *
* @brief Function to print information from IP frame. *
* *
* This function prints the information contained in a given IP frame. *
* *
* @param frame Pointer to the data frame *
******************************************************************************/
void
ip_print
(
IP_t
*
frame
)
{
/* Print output-header */
printf
(
"IP Header:
\n
"
);
/* Print the destination IP */
printf
(
" |-Destination IP : "
);
address_print_ip
(
&
(
*
frame
).
destination
);
printf
(
"
\n
"
);
/* Print the source address */
printf
(
" |-Source IP : "
);
address_print_ip
(
&
(
*
frame
).
source
);
printf
(
"
\n
"
);
/* Print the IP version */
printf
(
" |-IP Version : IPv%u
\n
"
,(
frame
->
version
&
0xF0
)
>>
4
);
/* Print the IP header length */
printf
(
" |-IP Header Length : %u Bytes
\n
"
,(
frame
->
version
&
0x0F
)
*
4
);
/* Print the IP total length */
printf
(
" |-IP Total Length : %u Bytes
\n
"
,
LITTLE2BIG16
(
frame
->
length
));
/* Print the time to live (TTL) */
printf
(
" |-TTL : %u
\n
"
,
frame
->
ttl
);
/* Print the contained protocol */
printf
(
" |-Protocol : 0x%02X ("
,
frame
->
protocol
);
ip_print_protocol
(
frame
->
protocol
);
printf
(
")
\n
"
);
/* Print the transmitted checksum */
printf
(
" |-Checksum : 0x%04X
\n
"
,
LITTLE2BIG16
(
frame
->
header_checksum
));
/* A void function has nothing to return */
return
;
}
/******************************************************************************
* tcp_print *
* @brief Function to print information from TCP frame. *
* *
* This function prints the information contained in a given TCP frame. *
* *
* @param frame Pointer to the data frame *
******************************************************************************/
void
tcp_print
(
TCP_t
*
frame
)
{
/* Print output-header */
printf
(
"TCP Header:
\n
"
);
/* Print the destination Port */
printf
(
" |-Destination Port : %u
\n
"
,
LITTLE2BIG16
(
frame
->
destination_port
));
/* Print the source Port */
printf
(
" |-Source Port : %u
\n
"
,
LITTLE2BIG16
(
frame
->
source_port
));
/* Print the TCP header length */
printf
(
" |-TCP Header Length : %u Bytes
\n
"
,((
frame
->
data_flags
&
0xF000
)
>>
12
)
*
4
+
16
);
/* Print the contained flags */
printf
(
" |-Flags : "
);
print_binary
(
frame
->
data_flags
&
0x003F
,
6
);
printf
(
"
\n
"
);
printf
(
" |-Urgent Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_URG
)
>>
TCP_OSET_URG
));
printf
(
" |-ACK Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_ACK
)
>>
TCP_OSET_ACK
));
printf
(
" |-Push Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_PSH
)
>>
TCP_OSET_PSH
));
printf
(
" |-Reset Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_RST
)
>>
TCP_OSET_RST
));
printf
(
" |-Synchronise Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_SYN
)
>>
TCP_OSET_SYN
));
printf
(
" |-Finish Flag : %d
\n
"
,((
frame
->
data_flags
&
TCP_MASK_FIN
)
>>
TCP_OSET_FIN
));
/* Print the window size */
printf
(
" |-Window Size : %u
\n
"
,
LITTLE2BIG16
(
frame
->
window_size
));
/* Print the transmitted checksum */
printf
(
" |-Checksum : 0x%04X
\n
"
,
LITTLE2BIG16
(
frame
->
checksum
));
/* A void function has nothing to return */
return
;
}
/***** MAIN ROUTINE ***********************************************************/
int
main
(
void
)
{
/*** Local Variables ***/
ETH_t
*
eth_frame
;
IP_t
*
ip_frame
;
TCP_t
*
tcp_frame
;
/* Typecast the sample record on the ETH frame */
eth_frame
=
(
ETH_t
*
)
sample
;
/* Extract the IP part from the ETH frame */
ip_frame
=
(
IP_t
*
)
eth_frame
->
data
;
/* Extract the TCP part from the IP frame */
tcp_frame
=
(
TCP_t
*
)
ip_frame
->
data
;
/* Print the information of all three frames */
eth_print
(
eth_frame
);
ip_print
(
ip_frame
);
tcp_print
(
tcp_frame
);
/* Notify the user about the termination of the program */
printf
(
"
\n
The program will now be terminated...
\n
"
);
return
0
;
/* Return with Success (0) */
}
/******************************************************************************/
ch_6/task_13/makefile
0 → 100644
View file @
d94a228b
# Get the current path(s) (relevant directory on last position)
TASKPATH
:=
$(
dir
$(
abspath
$(
lastword
$(MAKEFILE_LIST)
)))
CHPATH
:=
$(
dir
$
(
TASKPATH:%/
=
%
))
# Variables for text substitution
empty
:=
slash
:=
/
space
:=
$(empty)
$(empty)
task
:=
task_
ch
:=
ch_
# Get TASK number
TASK
:=
$(
subst
$(slash)
,
$(space)
,
$(TASKPATH)
)
TASK
:=
$(
lastword
$(TASK)
)
TASK
:=
$(
subst
$(task)
,
$(empty)
,
$(TASK)
)
# Get CH number
CH
:=
$(
subst
$(slash)
,
$(space)
,
$(CHPATH)
)
CH
:=
$(
lastword
$(CH)
)
CH
:=
$(
subst
$(ch)
,
$(empty)
,
$(CH)
)
# Specify SRD directory
SRCDIR
=
.
# Call superior makefile
include
../../makefile
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment