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