iPXE
tcpip.c
Go to the documentation of this file.
1#include <stdint.h>
2#include <stdlib.h>
3#include <string.h>
4#include <errno.h>
5#include <byteswap.h>
6#include <ipxe/iobuf.h>
7#include <ipxe/tables.h>
8#include <ipxe/ipstat.h>
9#include <ipxe/netdevice.h>
10#include <ipxe/tcpip.h>
11
12/** @file
13 *
14 * Transport-network layer interface
15 *
16 * This file contains functions and utilities for the
17 * TCP/IP transport-network layer interface
18 */
19
20FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
21FILE_SECBOOT ( PERMITTED );
22
23/**
24 * Process a received TCP/IP packet
25 *
26 * @v iobuf I/O buffer
27 * @v netdev Network device
28 * @v tcpip_proto Transport-layer protocol number
29 * @v st_src Partially-filled source address
30 * @v st_dest Partially-filled destination address
31 * @v pshdr_csum Pseudo-header checksum
32 * @v stats IP statistics
33 * @ret rc Return status code
34 *
35 * This function expects a transport-layer segment from the network
36 * layer. The network layer should fill in as much as it can of the
37 * source and destination addresses (i.e. it should fill in the
38 * address family and the network-layer addresses, but leave the ports
39 * and the rest of the structures as zero).
40 */
41int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
42 uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
43 struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
44 struct ip_statistics *stats ) {
45 struct tcpip_protocol *tcpip;
46
47 /* Hand off packet to the appropriate transport-layer protocol */
49 if ( tcpip->tcpip_proto == tcpip_proto ) {
50 DBG ( "TCP/IP received %s packet\n", tcpip->name );
51 stats->in_delivers++;
52 return tcpip->rx ( iobuf, netdev, st_src, st_dest,
53 pshdr_csum );
54 }
55 }
56
57 DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
58 stats->in_unknown_protos++;
59 free_iob ( iobuf );
60 return -EPROTONOSUPPORT;
61}
62
63/**
64 * Find TCP/IP network-layer protocol
65 *
66 * @v sa_family Address family
67 * @ret tcpip_net TCP/IP network-layer protocol, or NULL if not found
68 */
70 struct tcpip_net_protocol *tcpip_net;
71
73 if ( tcpip_net->sa_family == sa_family )
74 return tcpip_net;
75 }
76
77 DBG ( "Unrecognised TCP/IP address family %d\n", sa_family );
78 return NULL;
79}
80
81/**
82 * Transmit a TCP/IP packet
83 *
84 * @v iobuf I/O buffer
85 * @v tcpip_protocol Transport-layer protocol
86 * @v st_src Source address, or NULL to use route default
87 * @v st_dest Destination address
88 * @v netdev Network device to use if no route found, or NULL
89 * @v trans_csum Transport-layer checksum to complete, or NULL
90 * @ret rc Return status code
91 */
92int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
93 struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
94 struct net_device *netdev, uint16_t *trans_csum ) {
95 struct tcpip_net_protocol *tcpip_net;
96
97 /* Hand off packet to the appropriate network-layer protocol */
98 tcpip_net = tcpip_net_protocol ( st_dest->st_family );
99 if ( tcpip_net ) {
100 DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
101 return tcpip_net->tx ( iobuf, tcpip_protocol, st_src, st_dest,
102 netdev, trans_csum );
103 }
104
105 free_iob ( iobuf );
106 return -EAFNOSUPPORT;
107}
108
109/**
110 * Determine transmitting network device
111 *
112 * @v st_dest Destination address
113 * @ret netdev Network device, or NULL
114 */
115struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest ) {
116 struct tcpip_net_protocol *tcpip_net;
117
118 /* Hand off to the appropriate network-layer protocol */
119 tcpip_net = tcpip_net_protocol ( st_dest->st_family );
120 if ( tcpip_net )
121 return tcpip_net->netdev ( st_dest );
122
123 return NULL;
124}
125
126/**
127 * Determine maximum transmission unit
128 *
129 * @v st_dest Destination address
130 * @ret mtu Maximum transmission unit
131 */
132size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest ) {
133 struct tcpip_net_protocol *tcpip_net;
134 struct net_device *netdev;
135 size_t mtu;
136
137 /* Find appropriate network-layer protocol */
138 tcpip_net = tcpip_net_protocol ( st_dest->st_family );
139 if ( ! tcpip_net )
140 return 0;
141
142 /* Find transmitting network device */
143 netdev = tcpip_net->netdev ( st_dest );
144 if ( ! netdev )
145 return 0;
146
147 /* Calculate MTU */
148 mtu = ( netdev->mtu - tcpip_net->header_len );
149
150 return mtu;
151}
152
153/**
154 * Calculate continued TCP/IP checkum
155 *
156 * @v partial Checksum of already-summed data, in network byte order
157 * @v data Data buffer
158 * @v len Length of data buffer
159 * @ret cksum Updated checksum, in network byte order
160 *
161 * Calculates a TCP/IP-style 16-bit checksum over the data block. The
162 * checksum is returned in network byte order.
163 *
164 * This function may be used to add new data to an existing checksum.
165 * The function assumes that both the old data and the new data start
166 * on even byte offsets; if this is not the case then you will need to
167 * byte-swap either the input partial checksum, the output checksum,
168 * or both. Deciding which to swap is left as an exercise for the
169 * interested reader.
170 */
172 const void *data, size_t len ) {
173 unsigned int cksum = ( ( ~partial ) & 0xffff );
174 unsigned int value;
175 unsigned int i;
176
177 for ( i = 0 ; i < len ; i++ ) {
178 value = * ( ( uint8_t * ) data + i );
179 if ( i & 1 ) {
180 /* Odd bytes: swap on little-endian systems */
181 value = be16_to_cpu ( value );
182 } else {
183 /* Even bytes: swap on big-endian systems */
184 value = le16_to_cpu ( value );
185 }
186 cksum += value;
187 if ( cksum > 0xffff )
188 cksum -= 0xffff;
189 }
190
191 return ( ~cksum );
192}
193
194/**
195 * Calculate TCP/IP checkum
196 *
197 * @v data Data buffer
198 * @v len Length of data buffer
199 * @ret cksum Checksum, in network byte order
200 *
201 * Calculates a TCP/IP-style 16-bit checksum over the data block. The
202 * checksum is returned in network byte order.
203 */
204uint16_t tcpip_chksum ( const void *data, size_t len ) {
206}
207
208/**
209 * Bind to local TCP/IP port
210 *
211 * @v st_local Local TCP/IP socket address, or NULL
212 * @v available Function to check port availability
213 * @ret port Local port number, or negative error
214 */
215int tcpip_bind ( struct sockaddr_tcpip *st_local,
216 int ( * available ) ( int port ) ) {
217 uint16_t flags = 0;
218 uint16_t try_port = 0;
219 uint16_t min_port;
220 uint16_t max_port;
221 unsigned int offset;
222 unsigned int i;
223
224 /* Extract parameters from local socket address */
225 if ( st_local ) {
226 flags = st_local->st_flags;
227 try_port = ntohs ( st_local->st_port );
228 }
229
230 /* If an explicit port is specified, check its availability */
231 if ( try_port )
232 return available ( try_port );
233
234 /* Otherwise, find an available port in the range [1,1023] or
235 * [1025,65535] as appropriate.
236 */
237 min_port = ( ( ( ~flags ) & TCPIP_BIND_PRIVILEGED ) + 1 );
238 max_port = ( ( flags & TCPIP_BIND_PRIVILEGED ) - 1 );
239 offset = random();
240 for ( i = 0 ; i <= max_port ; i++ ) {
241 try_port = ( ( i + offset ) & max_port );
242 if ( try_port < min_port )
243 continue;
244 if ( available ( try_port ) < 0 )
245 continue;
246 return try_port;
247 }
248 return -EADDRINUSE;
249}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 port
Port number.
Definition CIB_PRM.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned short uint16_t
Definition stdint.h:11
unsigned char uint8_t
Definition stdint.h:10
uint16_t offset
Offset to command line.
Definition bzimage.h:3
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint32_t mtu
Maximum MTU.
Definition ena.h:17
uint8_t flags
Flags.
Definition ena.h:7
Error codes.
static struct net_device * netdev
Definition gdbudp.c:53
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EAFNOSUPPORT
Address family not supported.
Definition errno.h:314
#define EADDRINUSE
Address already in use.
Definition errno.h:304
#define EPROTONOSUPPORT
Protocol not supported.
Definition errno.h:630
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
#define le16_to_cpu(value)
Definition byteswap.h:113
#define ntohs(value)
Definition byteswap.h:137
#define be16_to_cpu(value)
Definition byteswap.h:116
Transport-network layer interface.
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition tcpip.h:58
@ TCPIP_BIND_PRIVILEGED
Bind to a privileged port (less than 1024)
Definition tcpip.h:67
#define TCPIP_PROTOCOLS
TCP/IP transport-layer protocol table.
Definition tcpip.h:179
#define TCPIP_NET_PROTOCOLS
TCP/IP network-layer protocol table.
Definition tcpip.h:185
String functions.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
IP statistics.
Network device management.
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
uint16_t sa_family_t
A socket address family.
Definition socket.h:86
A persistent I/O buffer.
Definition iobuf.h:38
IP system statistics.
Definition ipstat.h:45
unsigned long in_unknown_protos
ipSystemStatsInUnknownProtos
Definition ipstat.h:84
unsigned long in_delivers
ipSystemStatsInDelivers
Definition ipstat.h:117
A network device.
Definition netdevice.h:353
TCP/IP socket address.
Definition tcpip.h:76
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition tcpip.h:78
uint16_t st_flags
Flags.
Definition tcpip.h:80
uint16_t st_port
TCP/IP port.
Definition tcpip.h:82
A network-layer protocol of the TCP/IP stack (eg.
Definition tcpip.h:141
struct net_device *(* netdev)(struct sockaddr_tcpip *dest)
Determine transmitting network device.
Definition tcpip.h:175
int(* tx)(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit packet.
Definition tcpip.h:163
sa_family_t sa_family
Network address family.
Definition tcpip.h:145
size_t header_len
Fixed header length.
Definition tcpip.h:147
const char * name
Protocol name.
Definition tcpip.h:143
A transport-layer protocol of the TCP/IP stack (eg.
Definition tcpip.h:105
uint8_t tcpip_proto
Transport-layer protocol number.
Definition tcpip.h:135
const char * name
Protocol name.
Definition tcpip.h:107
int(* rx)(struct io_buffer *iobuf, struct net_device *netdev, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum)
Process received packet.
Definition tcpip.h:120
Linker tables.
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition tcpip.c:92
uint16_t generic_tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition tcpip.c:171
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition tcpip.c:204
int tcpip_rx(struct io_buffer *iobuf, struct net_device *netdev, uint8_t tcpip_proto, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum, struct ip_statistics *stats)
Process a received TCP/IP packet.
Definition tcpip.c:41
size_t tcpip_mtu(struct sockaddr_tcpip *st_dest)
Determine maximum transmission unit.
Definition tcpip.c:132
int tcpip_bind(struct sockaddr_tcpip *st_local, int(*available)(int port))
Bind to local TCP/IP port.
Definition tcpip.c:215
struct tcpip_net_protocol * tcpip_net_protocol(sa_family_t sa_family)
Find TCP/IP network-layer protocol.
Definition tcpip.c:69
struct net_device * tcpip_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition tcpip.c:115
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition x86_tcpip.c:46