aboutsummaryrefslogtreecommitdiff
path: root/lib/libnet/udp.c
blob: d6982eac10a699fdf1da6eca777917bf6890ddef (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
/******************************************************************************
 * Copyright (c) 2004, 2008 IBM Corporation
 * All rights reserved.
 * This program and the accompanying materials
 * are made available under the terms of the BSD License
 * which accompanies this distribution, and is available at
 * http://www.opensource.org/licenses/bsd-license.php
 *
 * Contributors:
 *     IBM Corporation - initial implementation
 *****************************************************************************/

/************************ DEFINITIONS & DECLARATIONS *********************/

#include <udp.h>
#include <sys/socket.h>
#include <dhcp.h>
#include <dhcpv6.h>
#include <dns.h>
#include <tftp.h>


/****************************** IMPLEMENTATION ***************************/


/**
 * NET: Handles UDP-packets according to Receive-handle diagram.
 *
 * @param  udp_packet UDP-packet to be handled
 * @param  packetsize Length of the packet
 * @return            ZERO - packet handled successfully;
 *                    NON ZERO - packet was not handled (e.g. bad format)
 * @see               receive_ether
 * @see               udphdr
 */
int8_t handle_udp(int fd, uint8_t * udp_packet, uint32_t packetsize)
{
	struct udphdr * udph = (struct udphdr *) udp_packet;

	if (packetsize < sizeof(struct udphdr))
		return -1; // packet is too small

	switch (htons(udph -> uh_dport)) {
	case UDPPORT_BOOTPC:
		if (udph -> uh_sport == htons(UDPPORT_BOOTPS))
			return handle_dhcp(fd, udp_packet + sizeof(struct udphdr),
			                    packetsize - sizeof(struct udphdr));
		else
			return -1;
	case UDPPORT_DNSC:
		if (udph -> uh_sport == htons(UDPPORT_DNSS))
			return handle_dns(udp_packet + sizeof(struct udphdr),
			                  packetsize - sizeof(struct udphdr));
		else
			return -1;
	case UDPPORT_DHCPV6C:
		return handle_dhcpv6(udp_packet+sizeof(struct udphdr),
		                     packetsize - sizeof(struct udphdr));
	case UDPPORT_TFTPC:
		return handle_tftp(fd, udp_packet, packetsize);
	default:
		return -1;
	}
}

/**
 * NET: This function handles situation when "Destination unreachable"
 *      ICMP-error occurs during sending UDP-packet.
 *
 * @param  err_code   Error Code (e.g. "Host unreachable")
 * @param  packet     original UDP-packet
 * @param  packetsize length of the packet
 * @see               handle_icmp
 */
void handle_udp_dun(uint8_t * udp_packet, uint32_t packetsize, uint8_t err_code)
{
	struct udphdr * udph = (struct udphdr *) udp_packet;

	if (packetsize < sizeof(struct udphdr))
		return; // packet is too small

	switch (htons(udph -> uh_sport)) {
	case UDPPORT_TFTPC:
		handle_tftp_dun(err_code);
		break;
	}
}

/**
 * NET: Creates UDP-packet. Places UDP-header in a packet and fills it
 *      with corresponding information.
 *      <p>
 *      Use this function with similar functions for other network layers
 *      (fill_ethhdr, fill_iphdr, fill_dnshdr, fill_btphdr).
 *
 * @param  packet      Points to the place where UDP-header must be placed.
 * @param  packetsize  Size of the packet in bytes incl. this hdr and data.
 * @param  src_port    UDP source port
 * @param  dest_port   UDP destination port
 * @see                udphdr
 * @see                fill_ethhdr
 * @see                fill_iphdr
 * @see                fill_dnshdr
 * @see                fill_btphdr
 */
void fill_udphdr(uint8_t * packet, uint16_t packetsize,
		 uint16_t src_port, uint16_t dest_port)
{
	struct udphdr * udph = (struct udphdr *) packet;

	udph -> uh_sport = htons(src_port);
	udph -> uh_dport = htons(dest_port);
	udph -> uh_ulen = htons(packetsize);
	udph -> uh_sum = htons(0);
}