summaryrefslogtreecommitdiff
path: root/src/common/flwd_sendpacket.c
blob: 701a44782bdfb44aee8d2b7228fb5d4ffd6ee2de (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138

#include "flowood.h"
#include "flowood_fun.h"
#include "flwd_net.h"
#include "MESA_handle_logger.h"
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <assert.h>

int flwd_sendpacket_build_ethernet(u_int16_t eth_type_host_order, 
	const unsigned char *src_mac, const unsigned char *dst_mac, char *buf)
{
	flwd_eth_hdr_t *snd_eth_hdr = (flwd_eth_hdr_t *)buf;

	memcpy(snd_eth_hdr->h_dest, dst_mac, ETH_ALEN);
	memcpy(snd_eth_hdr->h_source, src_mac, ETH_ALEN);

	snd_eth_hdr->h_proto = htons(eth_type_host_order);

	return 0;
}


int flwd_sendpacket_build_arp(u_short hrd_host, u_short pro_host, 
	u_char hln, u_char pln, u_short op_host, u_char *sha, u_char *spa, 
	u_char *tha, u_char *tpa, char *buf)
{
	flwd_arp_hdr_t *arp_hdr = (flwd_arp_hdr_t *)buf;

	if (!buf){
	    return (-1);
	}

	arp_hdr->ar_hrd = htons(hrd_host);       /* hardware address type */
	arp_hdr->ar_pro = htons(pro_host);       /* protocol address type */
	arp_hdr->ar_hln = hln;              /* hardware address length */
	arp_hdr->ar_pln = pln;              /* protocol address length */
	arp_hdr->ar_op  = htons(op_host);        /* opcode command */
	memcpy(arp_hdr->ar_sha, sha, hln);  /* sender hardware address */
	memcpy(arp_hdr->ar_spa, spa, pln);  /* sender protocol (IP) address */
	memcpy(arp_hdr->ar_tha, tha, hln);  /* target hardware address */
	memcpy(arp_hdr->ar_tpa, tpa, pln);  /* target protocol (IP) address */

	return (0);
}

int flwd_sendpacket_build_ipv4(u_int16_t carry_layer_len, u_int8_t tos, 
	u_int16_t id, u_int16_t frag, u_int8_t ttl, u_int8_t prot, u_int32_t src_net_order, 
	u_int32_t dst_net_order, const char *payload, int payload_s, char *buf)
{
	flwd_ipv4_hdr_t *ip_hdr;

	if (!buf){
	    return (-1);
	}

	ip_hdr = (flwd_ipv4_hdr_t *)buf;

	ip_hdr->ip_v    = 4;                             /* version 4 */
	ip_hdr->ip_hl   = 5;                             /* 20 byte header */
	ip_hdr->ip_tos  = tos;                           /* IP tos */
	ip_hdr->ip_len  = htons(sizeof(flwd_ipv4_hdr_t) + carry_layer_len);      /* total length */
	ip_hdr->ip_id   = htons(id);                     /* IP ID */
	ip_hdr->ip_off  = htons(frag);                   /* fragmentation flags */
	ip_hdr->ip_ttl  = ttl;                           /* time to live */
	ip_hdr->ip_p    = prot;                          /* transport protocol */
	ip_hdr->ip_sum  = 0;                             /* do this later */
	ip_hdr->ip_src.s_addr = src_net_order; 
	ip_hdr->ip_dst.s_addr = dst_net_order;
	if (payload && payload_s){
	    /*
	     *  Unchecked runtime error for buf + IP_H + payload to be greater than
	     *  the allocated heap memory.
	     */
		memcpy(buf + sizeof(flwd_ipv4_hdr_t), payload, payload_s);
	}
	
	return (0);
}


/* ���ڹ��������: ICMP-ECHO-REQUEST, ICMP-ECHO-REPLAY�� */
int flwd_sendpacket_build_icmpv4_echo(u_int8_t type, u_int8_t code, 
	u_int16_t sum, u_int16_t id_net_order, u_int16_t seq_net_order, char *payload, 
	u_int32_t payload_s, char *buf)
{
	flwd_simple_icmp_hdr_t *icmp_hdr = (flwd_simple_icmp_hdr_t *)buf;

	icmp_hdr->icmp_type = type;
	icmp_hdr->icmp_code = code;
	icmp_hdr->icmp_cksum = 0; /* checksum done in userland */ 
	icmp_hdr->icd_id = id_net_order;
	icmp_hdr->icd_seq = seq_net_order;

	if(payload && payload_s){
		/*
		 *  Unchecked runtime error for buf + IP_H + payload to be greater than
		 *  the allocated heap memory.
		*/
		memcpy(buf + sizeof(flwd_simple_icmp_hdr_t), payload, payload_s);
	}

	return 0;
}

int flwd_sendpacket_build_udp(u_int16_t carry_layer_len, 
	u_int16_t sport_net_order, u_int16_t dport_net_order, 
	const char *payload, int payload_s,  char *buf)
{
    flwd_udp_hdr_t udp_hdr;

    if (!buf)
    {
        return (-1);
    }

    udp_hdr.uh_sport   = sport_net_order;                /* source port */
    udp_hdr.uh_dport   = dport_net_order;                /* destination port */
    udp_hdr.uh_ulen    = htons(sizeof(flwd_udp_hdr_t) + carry_layer_len);   /* total length */
    udp_hdr.uh_sum     = 0;                        /* checksum */

    if (payload && payload_s)
    {
        /*
         *  Unchecked runtime error for buf + UDP_H + payload to be greater
         *  than the allocated heap memory.
         */
        memcpy(buf + sizeof(flwd_udp_hdr_t), payload, payload_s);
    } 
    memcpy(buf, &udp_hdr, sizeof(udp_hdr));
    return (1);
}