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 
20 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
21 FILE_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  */
41 int 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  */
92 int 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  */
115 struct 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  */
132 size_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  */
204 uint16_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  */
215 int 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 }
TCP/IP socket address.
Definition: tcpip.h:76
unsigned short uint16_t
Definition: stdint.h:11
uint16_t generic_tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition: tcpip.c:171
struct net_device * tcpip_netdev(struct sockaddr_tcpip *st_dest)
Determine transmitting network device.
Definition: tcpip.c:115
size_t tcpip_mtu(struct sockaddr_tcpip *st_dest)
Determine maximum transmission unit.
Definition: tcpip.c:132
#define TCPIP_EMPTY_CSUM
Empty checksum value.
Definition: tcpip.h:58
Error codes.
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
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
uint8_t tcpip_proto
Transport-layer protocol number.
Definition: tcpip.h:135
size_t mtu
Maximum transmission unit length.
Definition: netdevice.h:416
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition: tcpip.h:78
#define EADDRINUSE
Address already in use.
Definition: errno.h:304
FILE_SECBOOT(PERMITTED)
unsigned long in_unknown_protos
ipSystemStatsInUnknownProtos
Definition: ipstat.h:84
#define ntohs(value)
Definition: byteswap.h:137
Bind to a privileged port (less than 1024)
Definition: tcpip.h:67
int tcpip_bind(struct sockaddr_tcpip *st_local, int(*available)(int port))
Bind to local TCP/IP port.
Definition: tcpip.c:215
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define EAFNOSUPPORT
Address family not supported.
Definition: errno.h:314
u8 port
Port number.
Definition: CIB_PRM.h:31
IP statistics.
pseudo_bit_t value[0x00020]
Definition: arbel.h:13
struct net_device *(* netdev)(struct sockaddr_tcpip *dest)
Determine transmitting network device.
Definition: tcpip.h:175
struct tcpip_net_protocol * tcpip_net_protocol(sa_family_t sa_family)
Find TCP/IP network-layer protocol.
Definition: tcpip.c:69
#define TCPIP_PROTOCOLS
TCP/IP transport-layer protocol table.
Definition: tcpip.h:179
ring len
Length.
Definition: dwmac.h:231
static struct net_device * netdev
Definition: gdbudp.c:52
uint16_t sa_family_t
A socket address family.
Definition: socket.h:86
#define be16_to_cpu(value)
Definition: byteswap.h:116
Transport-network layer interface.
IP system statistics.
Definition: ipstat.h:45
uint16_t st_port
TCP/IP port.
Definition: tcpip.h:82
const char * name
Protocol name.
Definition: tcpip.h:107
uint8_t flags
Flags.
Definition: ena.h:18
sa_family_t sa_family
Network address family.
Definition: tcpip.h:145
unsigned long in_delivers
ipSystemStatsInDelivers
Definition: ipstat.h:117
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
A network device.
Definition: netdevice.h:353
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition: random.c:32
size_t header_len
Fixed header length.
Definition: tcpip.h:147
unsigned char uint8_t
Definition: stdint.h:10
#define le16_to_cpu(value)
Definition: byteswap.h:113
A transport-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:105
Network device management.
#define EPROTONOSUPPORT
Protocol not supported.
Definition: errno.h:630
uint32_t mtu
Maximum MTU.
Definition: ena.h:28
uint8_t data[48]
Additional event data.
Definition: ena.h:22
Linker tables.
uint16_t st_flags
Flags.
Definition: tcpip.h:80
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
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
A network-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:141
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
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 tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:204
const char * name
Protocol name.
Definition: tcpip.h:143
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition: x86_tcpip.c:46
#define TCPIP_NET_PROTOCOLS
TCP/IP network-layer protocol table.
Definition: tcpip.h:185
A persistent I/O buffer.
Definition: iobuf.h:38