Procházet zdrojové kódy

Added features that will be required for PXE UDP support.

Introduced struct sockaddr_tcpip, to simplify code that deals with
both IPv4 and IPv6 addresses.

Reorganised parts of tcpip.c and udp.c.
tags/v0.9.3
Michael Brown před 18 roky
rodič
revize
467e9627cc

+ 18
- 24
src/include/gpxe/in.h Zobrazit soubor

@@ -2,6 +2,7 @@
2 2
 #define	_GPXE_IN_H
3 3
 
4 4
 #include <stdint.h>
5
+#include <gpxe/socket.h>
5 6
 
6 7
 /* Protocol numbers */
7 8
 
@@ -10,15 +11,6 @@
10 11
 #define IP_TCP		6
11 12
 #define IP_UDP		17
12 13
 
13
-/* Network address family numbers */
14
-
15
-#define AF_INET		1
16
-#define AF_INET6	2
17
-#define AF_802          6
18
-#define AF_IPX          11
19
-
20
-typedef uint16_t sa_family_t;
21
-
22 14
 /* IP address constants */
23 15
 
24 16
 #define INADDR_NONE 0xffffffff
@@ -50,35 +42,37 @@ struct in6_addr {
50 42
 #define s6_addr32       in6_u.u6_addr32
51 43
 };
52 44
 
53
-typedef uint16_t in_port_t;
54
-
55 45
 /**
56
- * IP socket address
46
+ * IPv4 socket address
57 47
  */
58 48
 struct sockaddr_in {
59
-	struct in_addr	sin_addr;
60
-	in_port_t	sin_port;
49
+	/** Socket address family (part of struct @c sockaddr)
50
+	 *
51
+	 * Always set to @c AF_INET for IPv4 addresses
52
+	 */
53
+	sa_family_t sin_family;
54
+	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
55
+	uint16_t sin_port;
56
+	/** IPv4 address */
57
+	struct in_addr sin_addr;
61 58
 };
62 59
 
63 60
 /**
64 61
  * IPv6 socket address
65 62
  */
66 63
 struct sockaddr_in6 {
67
-        in_port_t       sin6_port;      /* Destination port */
64
+	/** Socket address family (part of struct @c sockaddr)
65
+	 *
66
+	 * Always set to @c AF_INET6 for IPv6 addresses
67
+	 */
68
+	sa_family_t sin_family;
69
+	/** TCP/IP port (part of struct @c sockaddr_tcpip) */
70
+	uint16_t sin_port;
68 71
         uint32_t        sin6_flowinfo;  /* Flow number */
69 72
         struct in6_addr sin6_addr;      /* 128-bit destination address */
70 73
         uint32_t        sin6_scope_id;  /* Scope ID */
71 74
 };
72 75
 
73
-/**
74
- * Generalized socket address structure
75
- */
76
-struct sockaddr {
77
-        sa_family_t             sa_family;      /* Socket address family */
78
-        struct sockaddr_in      sin;            /* IP4 socket address */
79
-        struct sockaddr_in6     sin6;           /* IP6 socket address */
80
-};
81
-
82 76
 extern int inet_aton ( const char *cp, struct in_addr *inp );
83 77
 extern char * inet_ntoa ( struct in_addr in );
84 78
 

+ 0
- 4
src/include/gpxe/ip.h Zobrazit soubor

@@ -64,8 +64,4 @@ extern int add_ipv4_address ( struct net_device *netdev,
64 64
 			      struct in_addr gateway );
65 65
 extern void del_ipv4_address ( struct net_device *netdev );
66 66
 
67
-extern int ipv4_uip_tx ( struct pk_buff *pkb );
68
-extern int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
69
-		     struct sockaddr *sock );
70
-
71 67
 #endif /* _GPXE_IP_H */

+ 8
- 4
src/include/gpxe/tcp.h Zobrazit soubor

@@ -10,8 +10,8 @@
10 10
  */
11 11
 
12 12
 #include <stddef.h>
13
-#include <gpxe/in.h>
14 13
 #include <gpxe/list.h>
14
+#include <gpxe/tcpip.h>
15 15
 #include <gpxe/pkbuff.h>
16 16
 
17 17
 struct tcp_connection;
@@ -142,8 +142,11 @@ extern void tcp_close ( struct tcp_connection *conn );
142 142
  * A TCP connection
143 143
  */
144 144
 struct tcp_connection {
145
-	struct sockaddr sa;		/* Remote socket address */
146
-	struct sockaddr_in sin;		/* Internet socket address */
145
+	struct sockaddr_tcpip peer;	/* Remote socket address */
146
+
147
+	/* FIXME: this field should no longer be present */
148
+	struct sockaddr_in sin;
149
+
147 150
 	uint16_t local_port;		/* Local port, in network byte order */
148 151
 	int tcp_state;			/* TCP state */
149 152
 	int tcp_lstate;			/* Last TCP state */
@@ -200,7 +203,8 @@ extern struct tcpip_protocol tcp_protocol;
200 203
 
201 204
 extern void tcp_init_conn ( struct tcp_connection *conn );
202 205
 extern int tcp_connect ( struct tcp_connection *conn );
203
-extern int tcp_connectto ( struct tcp_connection *conn, struct sockaddr *peer );
206
+extern int tcp_connectto ( struct tcp_connection *conn,
207
+			   struct sockaddr_tcpip *peer );
204 208
 extern int tcp_listen ( struct tcp_connection *conn, uint16_t port );
205 209
 extern int tcp_senddata ( struct tcp_connection *conn );
206 210
 extern int tcp_close ( struct tcp_connection *conn );

+ 58
- 37
src/include/gpxe/tcpip.h Zobrazit soubor

@@ -8,16 +8,36 @@
8 8
  */
9 9
 
10 10
 #include <stdint.h>
11
+#include <gpxe/socket.h>
11 12
 #include <gpxe/in.h>
12 13
 #include <gpxe/tables.h>
13 14
 
14 15
 struct pk_buff;
15
-struct net_protocol;
16
-struct tcpip_protocol;
17
-struct tcpip_net_protocol;
16
+
17
+#define SA_TCPIP_LEN 32
18
+
19
+/**
20
+ * TCP/IP socket address
21
+ *
22
+ * This contains the fields common to socket addresses for all TCP/IP
23
+ * address families.
24
+ */
25
+struct sockaddr_tcpip {
26
+	/** Socket address family (part of struct @c sockaddr) */
27
+	sa_family_t st_family;
28
+	/** TCP/IP port */
29
+	uint16_t st_port;
30
+	/** Padding
31
+	 *
32
+	 * This ensures that a struct @c sockaddr_tcpip is large
33
+	 * enough to hold a socket address for any TCP/IP address
34
+	 * family.
35
+	 */
36
+	char pad[SA_TCPIP_LEN - sizeof ( sa_family_t ) - sizeof ( uint16_t )];
37
+};
18 38
 
19 39
 /** 
20
- * A transport-layer protocol of the TCPIP stack (eg. UDP, TCP, etc)
40
+ * A transport-layer protocol of the TCP/IP stack (eg. UDP, TCP, etc)
21 41
  */
22 42
 struct tcpip_protocol {
23 43
 	/** Protocol name */
@@ -25,75 +45,76 @@ struct tcpip_protocol {
25 45
        	/**
26 46
          * Process received packet
27 47
          *
28
-         * @v pkb       Packet buffer
29
-         * @v netdev    Network device
30
-         * @v ll_source Link-layer source address
48
+         * @v pkb	Packet buffer
49
+	 * @v st_src	Partially-filled source address
50
+	 * @v st_dest	Partially-filled destination address
51
+	 * @ret rc	Return status code
31 52
          *
32 53
          * This method takes ownership of the packet buffer.
33 54
          */
34
-        void ( * rx ) ( struct pk_buff *pkb, struct in_addr *src_net_addr,
35
-			struct in_addr *dest_net_addr );
36
-
55
+        int ( * rx ) ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
56
+		       struct sockaddr_tcpip *st_dest );
37 57
         /** 
38 58
 	 * Transport-layer protocol number
39 59
 	 *
40 60
 	 * This is a constant of the type IP_XXX
41 61
          */
42
-        uint8_t trans_proto;
62
+        uint8_t tcpip_proto;
43 63
 	/**
44 64
 	 * Checksum offset
45 65
 	 *
46
-	 * A negative number indicates that the protocol does not require
47
-	 * checksumming to be performed by the network layer. A positive number
48
-	 * is the offset of the checksum field in the transport-layer header.
66
+	 * A negative number indicates that the protocol does not
67
+	 * require checksumming to be performed by the network layer.
68
+	 * A positive number is the offset of the checksum field in
69
+	 * the transport-layer header.
49 70
 	 */
50 71
 	int csum_offset;
51 72
 };
52 73
 
53 74
 /**
54
- * A TCPIP supporting network-layer protocol
75
+ * A network-layer protocol of the TCP/IP stack (eg. IPV4, IPv6, etc)
55 76
  */
56 77
 struct tcpip_net_protocol {
57
-	/** Network protocol */
58
-	struct net_protocol *net_protocol;
78
+	/** Protocol name */
79
+	const char *name;
59 80
 	/** Network address family */
60 81
 	sa_family_t sa_family;
61 82
 	/**
62 83
 	 * Transmit packet
63 84
 	 *
64 85
 	 * @v pkb		Packet buffer
65
- 	 * @v tcpip		Transport-layer TCP/IP protocol
66
-	 * @v sock		Socket address
67
-	 */
68
-	int ( * tx ) ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
69
-			struct sockaddr *sock ); 
70
-	/** Complete transport-layer checksum calculation
71
-	 *
72
-	 * @v pkb		Packet buffer
73
-	 * @v tcpip		Transport-layer protocol
86
+	 * @v tcpip_protocol	Transport-layer protocol
87
+	 * @v st_dest		Destination address
88
+	 * @ret rc		Return status code
74 89
 	 *
90
+	 * This function takes ownership of the packet buffer.
75 91
 	 */
76
-	void ( * tx_csum ) ( struct pk_buff *pkb,
77
-			     struct tcpip_protocol *tcpip );
92
+	int ( * tx ) ( struct pk_buff *pkb,
93
+		       struct tcpip_protocol *tcpip_protocol,
94
+		       struct sockaddr_tcpip *st_dest );
78 95
 };
79 96
 
80 97
 /**
81
- * Register a transport-layer protocol
98
+ * Register a TCP/IP transport-layer protocol
82 99
  *
83
- * @v protocol          Transport-layer protocol
100
+ * @v protocol		Transport-layer protocol
84 101
  */
85 102
 #define TCPIP_PROTOCOL( protocol ) \
86
-        struct tcpip_protocol protocol __table ( tcpip_protocols, 01 )
103
+	struct tcpip_protocol protocol __table ( tcpip_protocols, 01 )
87 104
 
105
+/**
106
+ * Register a TCP/IP network-layer protocol
107
+ *
108
+ * @v protocol		Network-layer protocol
109
+ */
88 110
 #define TCPIP_NET_PROTOCOL( protocol ) \
89
-        struct tcpip_net_protocol protocol __table ( tcpip_net_protocols, 01 )
90
-
91
-extern void tcpip_rx ( struct pk_buff *pkb, uint8_t trans_proto, 
92
-		       struct in_addr *src, struct in_addr *dest );
111
+	struct tcpip_net_protocol protocol __table ( tcpip_net_protocols, 01 )
93 112
 
113
+extern int tcpip_rx ( struct pk_buff *pkb, uint8_t tcpip_proto,
114
+		      struct sockaddr_tcpip *st_src,
115
+		      struct sockaddr_tcpip *st_dest );
94 116
 extern int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, 
95
-		      struct sockaddr *dest );
96
-
117
+		      struct sockaddr_tcpip *st_dest );
97 118
 extern unsigned int tcpip_continue_chksum ( unsigned int partial,
98 119
 					    const void *data, size_t len );
99 120
 extern unsigned int tcpip_chksum ( const void *data, size_t len );

+ 14
- 23
src/include/gpxe/udp.h Zobrazit soubor

@@ -10,8 +10,8 @@
10 10
  */
11 11
 
12 12
 #include <stddef.h>
13
-#include <gpxe/in.h>
14 13
 #include <gpxe/pkbuff.h>
14
+#include <gpxe/tcpip.h>
15 15
 #include <gpxe/if_ether.h>
16 16
 
17 17
 /**
@@ -65,8 +65,9 @@ struct udp_operations {
65 65
 	 * @v data	Data
66 66
 	 * @v len	Length of data
67 67
 	 */
68
-	void ( * newdata ) ( struct udp_connection *conn,
69
-			     void *data, size_t len );
68
+	int ( * newdata ) ( struct udp_connection *conn, void *data,
69
+			    size_t len, struct sockaddr_tcpip *st_src,
70
+			    struct sockaddr_tcpip *st_dest );
70 71
 };
71 72
 
72 73
 /**
@@ -75,7 +76,7 @@ struct udp_operations {
75 76
  */
76 77
 struct udp_connection {
77 78
        /** Address of the remote end of the connection */
78
-	struct sockaddr sa;
79
+	struct sockaddr_tcpip peer;
79 80
 	/** Local port on which the connection receives packets */
80 81
 	port_t local_port;
81 82
 	/** Transmit buffer */
@@ -86,31 +87,21 @@ struct udp_connection {
86 87
 	struct udp_operations *udp_op;
87 88
 };
88 89
 
89
-/**
90
- * UDP protocol
91
- */
92
-extern struct tcpip_protocol udp_protocol;
93
-
94
-/**
90
+/*
95 91
  * Functions provided to the application layer
96 92
  */
97 93
 
98
-extern void udp_init ( struct udp_connection *conn, struct udp_operations *udp_op );
94
+extern int udp_bind ( struct udp_connection *conn, uint16_t local_port );
95
+extern void udp_connect ( struct udp_connection *conn,
96
+			  struct sockaddr_tcpip *peer );
99 97
 extern int udp_open ( struct udp_connection *conn, uint16_t local_port );
100
-
101
-extern void udp_connect ( struct udp_connection *conn, struct sockaddr *peer );
102 98
 extern void udp_close ( struct udp_connection *conn );
103 99
 
104 100
 extern int udp_senddata ( struct udp_connection *conn );
105
-extern int udp_send ( struct udp_connection *conn, const void *data, size_t len );
106
-extern int udp_sendto ( struct udp_connection *conn, struct sockaddr *peer, const void *data, size_t len );
107
-
108
-static inline void * udp_buffer ( struct udp_connection *conn ) {
109
-	return conn->tx_pkb->data;
110
-}
111
-
112
-static inline int udp_buflen ( struct udp_connection *conn ) {
113
-	return pkb_len ( conn->tx_pkb );
114
-}
101
+extern int udp_send ( struct udp_connection *conn,
102
+		      const void *data, size_t len );
103
+extern int udp_sendto ( struct udp_connection *conn,
104
+			struct sockaddr_tcpip *peer,
105
+			const void *data, size_t len );
115 106
 
116 107
 #endif /* _GPXE_UDP_H */

+ 1
- 1
src/include/proto.h Zobrazit soubor

@@ -7,7 +7,7 @@
7 7
 
8 8
 struct protocol {
9 9
 	char *name;
10
-	in_port_t default_port;
10
+	uint16_t default_port;
11 11
 	int ( * load ) ( char *url, struct sockaddr_in *server, char *file,
12 12
 			 struct buffer *buffer );
13 13
 };

+ 1
- 1
src/include/tftp.h Zobrazit soubor

@@ -105,7 +105,7 @@ struct tftp_state {
105 105
 	 * This is the UDP port from which the open request will be
106 106
 	 * sent, and to which any unicast data packets will be sent.
107 107
 	 */
108
-	in_port_t lport;
108
+	uint16_t lport;
109 109
 	/** TFTP multicast address
110 110
 	 *
111 111
 	 * This is the IP address and UDP port to which multicast data

+ 41
- 143
src/net/ipv4.c Zobrazit soubor

@@ -128,7 +128,8 @@ static void ipv4_dump ( struct iphdr *iphdr __unused ) {
128 128
  * @v timer	Retry timer
129 129
  * @v over	If asserted, the timer is greater than @c MAX_TIMEOUT 
130 130
  */
131
-void ipv4_frag_expired ( struct retry_timer *timer __unused , int over ) {
131
+static void ipv4_frag_expired ( struct retry_timer *timer __unused,
132
+				int over ) {
132 133
 	if ( over ) {
133 134
 		DBG ( "Fragment reassembly timeout" );
134 135
 		/* Free the fragment buffer */
@@ -140,7 +141,7 @@ void ipv4_frag_expired ( struct retry_timer *timer __unused , int over ) {
140 141
  *
141 142
  * @v fragbug	Fragment buffer
142 143
  */
143
-void free_fragbuf ( struct frag_buffer *fragbuf ) {
144
+static void free_fragbuf ( struct frag_buffer *fragbuf ) {
144 145
 	if ( fragbuf ) {
145 146
 		free_dma ( fragbuf, sizeof ( *fragbuf ) );
146 147
 	}
@@ -152,7 +153,7 @@ void free_fragbuf ( struct frag_buffer *fragbuf ) {
152 153
  * @v pkb		Packet buffer, fragment of the datagram
153 154
  * @ret frag_pkb	Reassembled packet, or NULL
154 155
  */
155
-struct pk_buff * ipv4_reassemble ( struct pk_buff * pkb ) {
156
+static struct pk_buff * ipv4_reassemble ( struct pk_buff * pkb ) {
156 157
 	struct iphdr *iphdr = pkb->data;
157 158
 	struct frag_buffer *fragbuf;
158 159
 	
@@ -234,8 +235,8 @@ struct pk_buff * ipv4_reassemble ( struct pk_buff * pkb ) {
234 235
  *
235 236
  * This function calculates the tcpip 
236 237
  */
237
-void ipv4_tx_csum ( struct pk_buff *pkb, struct tcpip_protocol *tcpip ) {
238
-
238
+static void ipv4_tx_csum ( struct pk_buff *pkb,
239
+			   struct tcpip_protocol *tcpip ) {
239 240
 	struct iphdr *iphdr = pkb->data;
240 241
 	struct ipv4_pseudo_header pshdr;
241 242
 	uint16_t *csum = ( ( ( void * ) iphdr ) + sizeof ( *iphdr )
@@ -255,8 +256,8 @@ void ipv4_tx_csum ( struct pk_buff *pkb, struct tcpip_protocol *tcpip ) {
255 256
 /**
256 257
  * Calculate the transport-layer checksum while processing packets
257 258
  */
258
-uint16_t ipv4_rx_csum ( struct pk_buff *pkb __unused,
259
-			uint8_t trans_proto __unused ) {
259
+static uint16_t ipv4_rx_csum ( struct pk_buff *pkb __unused,
260
+			       uint8_t trans_proto __unused ) {
260 261
 	/** 
261 262
 	 * This function needs to be implemented. Until then, it will return
262 263
 	 * 0xffffffff every time
@@ -265,91 +266,20 @@ uint16_t ipv4_rx_csum ( struct pk_buff *pkb __unused,
265 266
 }
266 267
 
267 268
 /**
268
- * Transmit packet constructed by uIP
269
- *
270
- * @v pkb		Packet buffer
271
- * @ret rc		Return status code
272
- *
273
- */
274
-int ipv4_uip_tx ( struct pk_buff *pkb ) {
275
-	struct iphdr *iphdr = pkb->data;
276
-	struct ipv4_miniroute *miniroute;
277
-	struct net_device *netdev = NULL;
278
-	struct in_addr next_hop;
279
-	struct in_addr source;
280
-	uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
281
-	const uint8_t *ll_dest = ll_dest_buf;
282
-	int rc;
283
-
284
-	/* Use routing table to identify next hop and transmitting netdev */
285
-	next_hop = iphdr->dest;
286
-	list_for_each_entry ( miniroute, &miniroutes, list ) {
287
-		if ( ( ( ( iphdr->dest.s_addr ^ miniroute->address.s_addr ) &
288
-			 miniroute->netmask.s_addr ) == 0 ) ||
289
-		     ( miniroute->gateway.s_addr != INADDR_NONE ) ) {
290
-			netdev = miniroute->netdev;
291
-			source = miniroute->address;
292
-			if ( miniroute->gateway.s_addr != INADDR_NONE )
293
-				next_hop = miniroute->gateway;
294
-			break;
295
-		}
296
-	}
297
-
298
-	/* Abort if no network device identified */
299
-	if ( ! netdev ) {
300
-		DBG ( "No route to %s\n", inet_ntoa ( iphdr->dest ) );
301
-		rc = -EHOSTUNREACH;
302
-		goto err;
303
-	}
304
-
305
-	/* Determine link-layer destination address */
306
-	if ( next_hop.s_addr == INADDR_BROADCAST ) {
307
-		/* Broadcast address */
308
-		ll_dest = netdev->ll_protocol->ll_broadcast;
309
-	} else if ( IN_MULTICAST ( next_hop.s_addr ) ) {
310
-		/* Special case: IPv4 multicast over Ethernet.	This
311
-		 * code may need to be generalised once we find out
312
-		 * what happens for other link layers.
313
-		 */
314
-		uint8_t *next_hop_bytes = ( uint8_t * ) &next_hop;
315
-		ll_dest_buf[0] = 0x01;
316
-		ll_dest_buf[0] = 0x00;
317
-		ll_dest_buf[0] = 0x5e;
318
-		ll_dest_buf[3] = next_hop_bytes[1] & 0x7f;
319
-		ll_dest_buf[4] = next_hop_bytes[2];
320
-		ll_dest_buf[5] = next_hop_bytes[3];
321
-	} else {
322
-		/* Unicast address: resolve via ARP */
323
-		if ( ( rc = arp_resolve ( netdev, &ipv4_protocol, &next_hop,
324
-					  &source, ll_dest_buf ) ) != 0 ) {
325
-			DBG ( "No ARP entry for %s\n",
326
-			      inet_ntoa ( iphdr->dest ) );
327
-			goto err;
328
-		}
329
-	}
330
-	
331
-	/* Hand off to link layer */
332
-	return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest );
333
-
334
- err:
335
-	free_pkb ( pkb );
336
-	return rc;
337
-}
338
-
339
-/**
340
- * Transmit IP packet (without uIP)
269
+ * Transmit IP packet
341 270
  *
342 271
  * @v pkb		Packet buffer
343 272
  * @v tcpip		Transport-layer protocol
344
- * @v dest		Destination network-layer address
273
+ * @v st_dest		Destination network-layer address
345 274
  * @ret rc		Status
346 275
  *
347 276
  * This function expects a transport-layer segment and prepends the IP header
348 277
  */
349
-int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
350
-	      struct sockaddr* sock ) {
351
-	struct in_addr *dest = &sock->sin.sin_addr;
278
+static int ipv4_tx ( struct pk_buff *pkb,
279
+		     struct tcpip_protocol *tcpip_protocol,
280
+		     struct sockaddr_tcpip *st_dest ) {
352 281
 	struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
282
+	struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
353 283
 	struct ipv4_miniroute *miniroute;
354 284
 	struct net_device *netdev = NULL;
355 285
 	struct in_addr next_hop;
@@ -364,10 +294,10 @@ int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
364 294
 	iphdr->ident = htons ( next_ident++ );
365 295
 	iphdr->frags = 0;
366 296
 	iphdr->ttl = IP_TTL;
367
-	iphdr->protocol = tcpip->trans_proto;
297
+	iphdr->protocol = tcpip_protocol->tcpip_proto;
368 298
 
369 299
 	/* Copy destination address */
370
-	iphdr->dest = *dest;
300
+	iphdr->dest = sin_dest->sin_addr;
371 301
 
372 302
 	/**
373 303
 	 * All fields in the IP header filled in except the source network
@@ -375,8 +305,6 @@ int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
375 305
 	 * requires the source network address). As the pseudo header requires
376 306
 	 * the source address as well and the transport-layer checksum is
377 307
 	 * updated after routing.
378
-	 *
379
-	 * Continue processing as in ipv4_uip_tx()
380 308
 	 */
381 309
 
382 310
 	/* Use routing table to identify next hop and transmitting netdev */
@@ -400,8 +328,8 @@ int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
400 328
 	}
401 329
 
402 330
 	/* Calculate the transport layer checksum */
403
-	if ( tcpip->csum_offset > 0 ) {
404
-		ipv4_tx_csum ( pkb, tcpip );
331
+	if ( tcpip_protocol->csum_offset > 0 ) {
332
+		ipv4_tx_csum ( pkb, tcpip_protocol );
405 333
 	}
406 334
 
407 335
 	/* Calculate header checksum, in network byte order */
@@ -446,42 +374,7 @@ int ipv4_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
446 374
 }
447 375
 
448 376
 /**
449
- * Process incoming IP packets
450
- *
451
- * @v pkb		Packet buffer
452
- * @v netdev		Network device
453
- * @v ll_source		Link-layer source address
454
- * @ret rc		Return status code
455
- *
456
- * This handles IP packets by handing them off to the uIP protocol
457
- * stack.
458
- */
459
-static int ipv4_uip_rx ( struct pk_buff *pkb,
460
-			 struct net_device *netdev __unused,
461
-			 const void *ll_source __unused ) {
462
-
463
-	/* Transfer to uIP buffer.  Horrendously space-inefficient,
464
-	 * but will do as a proof-of-concept for now.
465
-	 */
466
-	uip_len = pkb_len ( pkb );
467
-	memcpy ( uip_buf, pkb->data, uip_len );
468
-	free_pkb ( pkb );
469
-
470
-	/* Hand to uIP for processing */
471
-	uip_input ();
472
-	if ( uip_len > 0 ) {
473
-		pkb = alloc_pkb ( MAX_LL_HEADER_LEN + uip_len );
474
-		if ( ! pkb )
475
-			return -ENOMEM;
476
-		pkb_reserve ( pkb, MAX_LL_HEADER_LEN );
477
-		memcpy ( pkb_put ( pkb, uip_len ), uip_buf, uip_len );
478
-		ipv4_uip_tx ( pkb );
479
-	}
480
-	return 0;
481
-}
482
-
483
-/**
484
- * Process incoming packets (without uIP)
377
+ * Process incoming packets
485 378
  *
486 379
  * @v pkb	Packet buffer
487 380
  * @v netdev	Network device
@@ -490,18 +383,20 @@ static int ipv4_uip_rx ( struct pk_buff *pkb,
490 383
  * This function expects an IP4 network datagram. It processes the headers 
491 384
  * and sends it to the transport layer.
492 385
  */
493
-void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
494
-			const void *ll_source __unused ) {
386
+static int ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
387
+		     const void *ll_source __unused ) {
495 388
 	struct iphdr *iphdr = pkb->data;
496
-	struct in_addr *src = &iphdr->src;
497
-	struct in_addr *dest = &iphdr->dest;
389
+	union {
390
+		struct sockaddr_in sin;
391
+		struct sockaddr_tcpip st;
392
+	} src, dest;
498 393
 	uint16_t chksum;
499 394
 
500 395
 	/* Sanity check */
501 396
 	if ( pkb_len ( pkb ) < sizeof ( *iphdr ) ) {
502 397
 		DBG ( "IP datagram too short (%d bytes)\n",
503 398
 			pkb_len ( pkb ) );
504
-		return;
399
+		return -EINVAL;
505 400
 	}
506 401
 
507 402
 	/* Print IP4 header for debugging */
@@ -510,14 +405,14 @@ void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
510 405
 	/* Validate version and header length */
511 406
 	if ( iphdr->verhdrlen != 0x45 ) {
512 407
 		DBG ( "Bad version and header length %x\n", iphdr->verhdrlen );
513
-		return;
408
+		return -EINVAL;
514 409
 	}
515 410
 
516 411
 	/* Validate length of IP packet */
517
-	if ( ntohs ( iphdr->len ) != pkb_len ( pkb ) ) {
412
+	if ( ntohs ( iphdr->len ) > pkb_len ( pkb ) ) {
518 413
 		DBG ( "Inconsistent packet length %d\n",
519
-					ntohs ( iphdr->len ) );
520
-		return;
414
+		      ntohs ( iphdr->len ) );
415
+		return -EINVAL;
521 416
 	}
522 417
 
523 418
 	/* Verify the checksum */
@@ -533,7 +428,7 @@ void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
533 428
 		 */
534 429
 		pkb = ipv4_reassemble ( pkb );
535 430
 		if ( !pkb ) {
536
-			return;
431
+			return 0;
537 432
 		}
538 433
 	}
539 434
 
@@ -543,11 +438,19 @@ void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
543 438
 	 * 3. Check the service field
544 439
 	 */
545 440
 
441
+	/* Construct socket addresses */
442
+	memset ( &src, 0, sizeof ( src ) );
443
+	src.sin.sin_family = AF_INET;
444
+	src.sin.sin_addr = iphdr->src;
445
+	memset ( &dest, 0, sizeof ( dest ) );
446
+	dest.sin.sin_family = AF_INET;
447
+	dest.sin.sin_addr = iphdr->dest;
448
+
546 449
 	/* Strip header */
547 450
 	pkb_pull ( pkb, sizeof ( *iphdr ) );
548 451
 
549 452
 	/* Send it to the transport layer */
550
-	tcpip_rx ( pkb, iphdr->protocol, src, dest );
453
+	return tcpip_rx ( pkb, iphdr->protocol, &src.st, &dest.st );
551 454
 }
552 455
 
553 456
 /** 
@@ -601,11 +504,7 @@ struct net_protocol ipv4_protocol = {
601 504
 	.name = "IP",
602 505
 	.net_proto = htons ( ETH_P_IP ),
603 506
 	.net_addr_len = sizeof ( struct in_addr ),
604
-#if USE_UIP
605
-	.rx = ipv4_uip_rx,
606
-#else
607 507
 	.rx = ipv4_rx,
608
-#endif
609 508
 	.ntoa = ipv4_ntoa,
610 509
 };
611 510
 
@@ -613,10 +512,9 @@ NET_PROTOCOL ( ipv4_protocol );
613 512
 
614 513
 /** IPv4 TCPIP net protocol */
615 514
 struct tcpip_net_protocol ipv4_tcpip_protocol = {
616
-	.net_protocol = &ipv4_protocol,
515
+	.name = "IPv4",
617 516
 	.sa_family = AF_INET,
618 517
 	.tx = ipv4_tx,
619
-	.tx_csum = ipv4_tx_csum,
620 518
 };
621 519
 
622 520
 TCPIP_NET_PROTOCOL ( ipv4_tcpip_protocol );

+ 8
- 11
src/net/ipv6.c Zobrazit soubor

@@ -12,8 +12,9 @@
12 12
 /**
13 13
  * Transmit IP6 packets
14 14
  */
15
-int ipv6_tx ( struct pk_buff *pkb __unused, uint16_t trans_proto __unused,
16
-	      struct in6_addr *dest __unused) {
15
+static int ipv6_tx ( struct pk_buff *pkb,
16
+		     struct tcpip_protocol *tcpip_protocol,
17
+		     struct sockaddr_tcpip *st_dest ) {
17 18
 	return -ENOSYS;
18 19
 }
19 20
 
@@ -22,13 +23,10 @@ int ipv6_tx ( struct pk_buff *pkb __unused, uint16_t trans_proto __unused,
22 23
  *
23 24
  * Placeholder function. Should rewrite in net/ipv6.c
24 25
  */
25
-void ipv6_rx ( struct pk_buff *pkb __unused,
26
-	       struct net_device *netdev __unused,
27
-	       const void *ll_source __unused ) {
28
-}
29
-
30
-void ipv6_tx_csum ( struct pk_buff *pkb, struct tcpip_protocol *tcpip ) {
31
-	return;
26
+static int ipv6_rx ( struct pk_buff *pkb __unused,
27
+		     struct net_device *netdev __unused,
28
+		     const void *ll_source __unused ) {
29
+	return -ENOSYS;
32 30
 }
33 31
 
34 32
 static const char * ipv6_ntoa ( const void *net_addr ) {
@@ -49,10 +47,9 @@ NET_PROTOCOL ( ipv6_protocol );
49 47
 
50 48
 /** IPv6 TCPIP net protocol */
51 49
 struct tcpip_net_protocol ipv6_tcpip_protocol = {
52
-	.net_protocol = &ipv6_protocol,
50
+	.name = "IPv6",
53 51
 	.sa_family = AF_INET6,
54 52
 	.tx = ipv6_tx,
55
-	.tx_csum = ipv6_tx_csum,
56 53
 };
57 54
 
58 55
 TCPIP_NET_PROTOCOL ( ipv6_tcpip_protocol );

+ 22
- 30
src/net/tcp.c Zobrazit soubor

@@ -379,7 +379,8 @@ void tcp_init_conn ( struct tcp_connection *conn ) {
379 379
  * peer. It sends a SYN packet to peer. When the connection is established, the
380 380
  * TCP stack calls the connected() callback function.
381 381
  */
382
-int tcp_connectto ( struct tcp_connection *conn, struct sockaddr *peer ) {
382
+int tcp_connectto ( struct tcp_connection *conn,
383
+		    struct sockaddr_tcpip *peer ) {
383 384
 	int rc;
384 385
 
385 386
 	/* A connection can only be established from the CLOSED state */
@@ -393,7 +394,7 @@ int tcp_connectto ( struct tcp_connection *conn, struct sockaddr *peer ) {
393 394
 	if ( ( rc = tcp_listen ( conn, conn->local_port ) ) != 0 ) {
394 395
 		return rc;
395 396
 	}
396
-	memcpy ( &conn->sa, peer, sizeof ( *peer ) );
397
+	memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
397 398
 
398 399
 	/* Send a SYN packet and transition to TCP_SYN_SENT */
399 400
 	conn->snd_una = ( ( ( uint32_t ) random() ) << 16 ) & random();
@@ -407,7 +408,7 @@ int tcp_connectto ( struct tcp_connection *conn, struct sockaddr *peer ) {
407 408
 }
408 409
 
409 410
 int tcp_connect ( struct tcp_connection *conn ) {
410
-	return tcp_connectto ( conn, &conn->sa );
411
+	return tcp_connectto ( conn, &conn->peer );
411 412
 }
412 413
 
413 414
 /**
@@ -542,7 +543,7 @@ int tcp_senddata ( struct tcp_connection *conn ) {
542 543
  * This function sends data to the peer socket address
543 544
  */
544 545
 int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
545
-	struct sockaddr *peer = &conn->sa;
546
+	struct sockaddr_tcpip *peer = &conn->peer;
546 547
 	struct pk_buff *pkb = conn->tx_pkb;
547 548
 	int slen;
548 549
 
@@ -557,18 +558,7 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
557 558
 	/* Source port, assumed to be in network byte order in conn */
558 559
 	tcphdr->src = conn->local_port;
559 560
 	/* Destination port, assumed to be in network byte order in peer */
560
-	switch ( peer->sa_family ) {
561
-	case AF_INET:
562
-		tcphdr->dest = peer->sin.sin_port;
563
-		break;
564
-	case AF_INET6:
565
-		tcphdr->dest = peer->sin6.sin6_port;
566
-		break;
567
-	default:
568
-		DBG ( "Family type %d not supported\n", 
569
-					peer->sa_family );
570
-		return -EAFNOSUPPORT;
571
-	}
561
+	tcphdr->dest = peer->st_port;
572 562
 	tcphdr->seq = htonl ( conn->snd_una );
573 563
 	tcphdr->ack = htonl ( conn->rcv_nxt );
574 564
 	/* Header length, = 0x50 (without TCP options) */
@@ -597,7 +587,9 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
597 587
  * @v pkb	Packet buffer
598 588
  * @v partial	Partial checksum
599 589
  */
600
-void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
590
+static int tcp_rx ( struct pk_buff *pkb,
591
+		    struct sockaddr_tcpip *st_src __unused,
592
+		    struct sockaddr_tcpip *st_dest __unused ) {
601 593
 	struct tcp_connection *conn;
602 594
 	struct tcp_header *tcphdr;
603 595
 	uint32_t acked, toack;
@@ -606,7 +598,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
606 598
 	/* Sanity check */
607 599
 	if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
608 600
 		DBG ( "Packet too short (%d bytes)\n", pkb_len ( pkb ) );
609
-		return;
601
+		return -EINVAL;
610 602
 	}
611 603
 
612 604
 	/* Process TCP header */
@@ -616,7 +608,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
616 608
 	hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
617 609
 	if ( hlen != sizeof ( *tcphdr ) ) {
618 610
 		DBG ( "Bad header length (%d bytes)\n", hlen );
619
-		return;
611
+		return -EINVAL;
620 612
 	}
621 613
 	
622 614
 	/* TODO: Verify checksum */
@@ -629,7 +621,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
629 621
 	}
630 622
 	
631 623
 	DBG ( "No connection found on port %d\n", ntohs ( tcphdr->dest ) );
632
-	return;
624
+	return 0;
633 625
 
634 626
   found_conn:
635 627
 	/* Set the advertised window */
@@ -642,7 +634,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
642 634
 	case TCP_CLOSED:
643 635
 		DBG ( "tcp_rx(): Invalid state %s\n",
644 636
 				tcp_states[conn->tcp_state] );
645
-		return;
637
+		return -EINVAL;
646 638
 	case TCP_LISTEN:
647 639
 		if ( tcphdr->flags & TCP_SYN ) {
648 640
 			tcp_trans ( conn, TCP_SYN_RCVD );
@@ -687,7 +679,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
687 679
 		if ( tcphdr->flags & TCP_RST ) {
688 680
 			tcp_trans ( conn, TCP_LISTEN );
689 681
 			conn->tcp_op->closed ( conn, CONN_RESTART );
690
-			return;
682
+			return 0;
691 683
 		}
692 684
 		if ( tcphdr->flags & TCP_ACK ) {
693 685
 			tcp_trans ( conn, TCP_ESTABLISHED );
@@ -697,7 +689,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
697 689
 			 */
698 690
 			conn->snd_una = tcphdr->ack - 1;
699 691
 			conn->tcp_op->connected ( conn );
700
-			return;
692
+			return 0;
701 693
 		}
702 694
 		/* Unexpected packet */
703 695
 		goto unexpected;
@@ -744,7 +736,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
744 736
 	case TCP_CLOSING:
745 737
 		if ( tcphdr->flags & TCP_ACK ) {
746 738
 			tcp_trans ( conn, TCP_TIME_WAIT );
747
-			return;
739
+			return 0;
748 740
 		}
749 741
 		/* Unexpected packet */
750 742
 		goto unexpected;
@@ -757,7 +749,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
757 749
 	case TCP_LAST_ACK:
758 750
 		if ( tcphdr->flags & TCP_ACK ) {
759 751
 			tcp_trans ( conn, TCP_CLOSED );
760
-			return;
752
+			return 0;
761 753
 		}
762 754
 		/* Unexpected packet */
763 755
 		goto unexpected;
@@ -791,7 +783,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
791 783
 		acked = ntohl ( tcphdr->ack ) - conn->snd_una;
792 784
 		if ( acked < 0 ) { /* TODO: Replace all uint32_t arith */
793 785
 			DBG ( "Previously ACKed (%d)\n", tcphdr->ack );
794
-			return;
786
+			return 0;
795 787
 		}
796 788
 		/* Advance snd stream */
797 789
 		conn->snd_una += acked;
@@ -802,7 +794,7 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
802 794
 		/* Invoke the senddata() callback function */
803 795
 		tcp_senddata ( conn );
804 796
 	}
805
-	return;
797
+	return 0;
806 798
 
807 799
   send_tcp_nomsg:
808 800
 	free_pkb ( conn->tx_pkb );
@@ -812,20 +804,20 @@ void tcp_rx ( struct pk_buff *pkb, uint16_t partial ) {
812 804
 	if ( ( rc = tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN ) ) != 0 ) {
813 805
 		DBG ( "Error sending TCP message (rc = %d)\n", rc );
814 806
 	}
815
-	return;
807
+	return 0;
816 808
 
817 809
   unexpected:
818 810
 	DBG ( "Unexpected packet received in %d state with flags = %hd\n",
819 811
 			conn->tcp_state, tcphdr->flags & TCP_MASK_FLAGS );
820 812
 	free_pkb ( conn->tx_pkb );
821
-	return;
813
+	return -EINVAL;
822 814
 }
823 815
 
824 816
 /** TCP protocol */
825 817
 struct tcpip_protocol tcp_protocol = {
826 818
 	.name = "TCP",
827 819
 	.rx = tcp_rx,
828
-	.trans_proto = IP_TCP,
820
+	.tcpip_proto = IP_TCP,
829 821
 	.csum_offset = 16,
830 822
 };
831 823
 

+ 47
- 55
src/net/tcpip.c Zobrazit soubor

@@ -1,94 +1,86 @@
1 1
 #include <stdint.h>
2 2
 #include <string.h>
3 3
 #include <errno.h>
4
-#include <malloc.h>
5 4
 #include <byteswap.h>
6
-#include <gpxe/in.h>
7
-#include <gpxe/ip.h>
8
-#include <gpxe/ip6.h>
9 5
 #include <gpxe/pkbuff.h>
10 6
 #include <gpxe/tables.h>
11
-#include <gpxe/netdevice.h>
12 7
 #include <gpxe/tcpip.h>
13 8
 
14 9
 /** @file
15 10
  *
16 11
  * Transport-network layer interface
17 12
  *
18
- * This file contains functions and utilities for the transport-network layer interface
13
+ * This file contains functions and utilities for the
14
+ * TCP/IP transport-network layer interface
19 15
  */
20 16
 
21
-/** Registered network-layer protocols that support TCPIP */
22
-static struct tcpip_net_protocol tcpip_net_protocols[0] __table_start ( tcpip_net_protocols );
23
-static struct tcpip_net_protocol tcpip_net_protocols_end[0] __table_end ( tcpip_net_protocols );
17
+/** Registered network-layer protocols that support TCP/IP */
18
+static struct tcpip_net_protocol
19
+tcpip_net_protocols[0] __table_start ( tcpip_net_protocols );
20
+static struct tcpip_net_protocol
21
+tcpip_net_protocols_end[0] __table_end ( tcpip_net_protocols );
24 22
 
25
-/** Registered transport-layer protocols that support TCPIP */
26
-static struct tcpip_protocol tcpip_protocols[0] __table_start ( tcpip_protocols );
27
-static struct tcpip_protocol tcpip_protocols_end[0] __table_end ( tcpip_protocols );
23
+/** Registered transport-layer protocols that support TCP/IP */
24
+static struct tcpip_protocol
25
+tcpip_protocols[0]__table_start ( tcpip_protocols );
26
+static struct tcpip_protocol
27
+tcpip_protocols_end[0] __table_end ( tcpip_protocols );
28 28
 
29
-/** Process a received packet
29
+/** Process a received TCP/IP packet
30 30
  *
31 31
  * @v pkb		Packet buffer
32
- * @v trans_proto	Transport-layer protocol number
33
- * @v src		Source network-layer address
34
- * @v dest		Destination network-layer address
32
+ * @v tcpip_proto	Transport-layer protocol number
33
+ * @v st_src		Partially-filled source address
34
+ * @v st_dest		Partially-filled destination address
35
+ * @ret rc		Return status code
35 36
  *
36
- * This function expects a transport-layer segment from the network-layer
37
+ * This function expects a transport-layer segment from the network
38
+ * layer.  The network layer should fill in as much as it can of the
39
+ * source and destination addresses (i.e. it should fill in the
40
+ * address family and the network-layer addresses, but leave the ports
41
+ * and the rest of the structures as zero).
37 42
  */
38
-void tcpip_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src,
39
-		struct in_addr *dest ) {
43
+int tcpip_rx ( struct pk_buff *pkb, uint8_t tcpip_proto, 
44
+	       struct sockaddr_tcpip *st_src,
45
+	       struct sockaddr_tcpip *st_dest ) {
40 46
 	struct tcpip_protocol *tcpip;
41 47
 
42
-	/* Identify the transport layer protocol */
43
-	for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; ++tcpip ) {
44
-		if ( tcpip->trans_proto == trans_proto ) {
45
-			tcpip->rx ( pkb, src, dest );
48
+	/* Hand off packet to the appropriate transport-layer protocol */
49
+	for ( tcpip = tcpip_protocols; tcpip < tcpip_protocols_end; tcpip++ ) {
50
+		if ( tcpip->tcpip_proto == tcpip_proto ) {
51
+			DBG ( "TCP/IP received %s packet\n", tcpip->name );
52
+			return tcpip->rx ( pkb, st_src, st_dest );
46 53
 		}
47 54
 	}
55
+
56
+	DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
57
+	return -EPROTONOSUPPORT;
48 58
 }
49 59
 
50
-/** Transmit a transport-layer segment
60
+/** Transmit a TCP/IP packet
51 61
  *
52 62
  * @v pkb		Packet buffer
53
- * @v trans_proto	Transport-layer protocol
54
- * @v sock		Destination socket address
55
- * @ret			Status
63
+ * @v tcpip_protocol	Transport-layer protocol
64
+ * @v st_dest		Destination address
65
+ * @ret rc		Return status code
56 66
  */
57
-int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
58
-	       struct sockaddr *sock ) {
59
-
60
-#if 0 /* This is the right thing to do */
61
-
67
+int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip_protocol,
68
+	       struct sockaddr_tcpip *st_dest ) {
62 69
 	struct tcpip_net_protocol *tcpip_net;
63 70
 
64
-	/* Identify the network layer protocol */
65
-	for ( tcpip_net = tcpip_net_protocols; 
66
-			tcpip_net <= tcpip_net_protocols_end; ++tcpip_net ) {
67
-		if ( tcpip_net->sa_family == sock->sa_family ) {
68
-			DBG ( "Packet sent to %s module\n", tcpip_net->net_protocol->name );
69
-			return tcpip_net->tx ( pkb, tcpip, sock );
71
+	/* Hand off packet to the appropriate network-layer protocol */
72
+	for ( tcpip_net = tcpip_net_protocols ;
73
+	      tcpip_net < tcpip_net_protocols_end ; tcpip_net++ ) {
74
+		if ( tcpip_net->sa_family == st_dest->st_family ) {
75
+			DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
76
+			return tcpip_net->tx ( pkb, tcpip_protocol, st_dest );
70 77
 		}
71 78
 	}
72
-	DBG ( "No suitable network layer protocol found for sa_family %s\n",
73
-						( sock->sa_family );
74
-	return -EAFNOSUPPORT;
75
-}
76
-
77
-#else
78
-
79
-	/* Identify the network layer protocol and send it using xxx_tx() */
80
-	switch ( sock->sa_family ) {
81
-	case AF_INET: /* IPv4 network family */
82
-		return ipv4_tx ( pkb, tcpip, sock );
83
-	case AF_INET6: /* IPv6 network family */
84
-		return ipv6_tx ( pkb, tcpip, sock );
85
-	}
86
-	DBG ( "Network family %d not supported", sock->sa_family );
79
+	
80
+	DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
87 81
 	return -EAFNOSUPPORT;
88 82
 }
89 83
 
90
-#endif
91
-
92 84
 /**
93 85
  * Calculate continued TCP/IP checkum
94 86
  *

+ 161
- 140
src/net/udp.c Zobrazit soubor

@@ -2,95 +2,120 @@
2 2
 #include <string.h>
3 3
 #include <assert.h>
4 4
 #include <byteswap.h>
5
-#include <latch.h>
6 5
 #include <errno.h>
7
-#include <gpxe/in.h>
8
-#include <gpxe/ip.h>
9
-#include <gpxe/ip6.h>
10
-#include <gpxe/udp.h>
11
-#include <gpxe/init.h>
6
+#include <gpxe/tcpip.h>
12 7
 #include <gpxe/pkbuff.h>
13 8
 #include <gpxe/netdevice.h>
14
-#include <gpxe/tcpip.h>
9
+#include <gpxe/udp.h>
15 10
 
16 11
 /** @file
17 12
  *
18 13
  * UDP protocol
19 14
  */
20 15
 
16
+struct tcpip_protocol udp_protocol;
17
+
21 18
 /**
22 19
  * List of registered UDP connections
23 20
  */
24 21
 static LIST_HEAD ( udp_conns );
25 22
 
26 23
 /**
27
- * Some utility functions
24
+ * Bind UDP connection to local port
25
+ *
26
+ * @v conn		UDP connection
27
+ * @v local_port	Local port, in network byte order
28
+ * @ret rc		Return status code
28 29
  */
29
-static inline void copy_sockaddr ( struct sockaddr *source, struct sockaddr *dest ) {
30
-	memcpy ( dest, source, sizeof ( *dest ) );
31
-}
30
+int udp_bind ( struct udp_connection *conn, uint16_t local_port ) {
31
+	struct udp_connection *existing;
32 32
 
33
-static inline uint16_t * dest_port ( struct sockaddr *sock ) {
34
-	switch ( sock->sa_family ) {
35
-	case AF_INET:
36
-		return &sock->sin.sin_port;
37
-	case AF_INET6:
38
-		return &sock->sin6.sin6_port;
33
+	list_for_each_entry ( existing, &udp_conns, list ) {
34
+		if ( existing->local_port == local_port )
35
+			return -EADDRINUSE;
39 36
 	}
40
-	return NULL;
37
+	conn->local_port = local_port;
38
+	return 0;
41 39
 }
42 40
 
43 41
 /**
44
- * Dump the UDP header
42
+ * Bind UDP connection to all local ports
45 43
  *
46
- * @v udphdr	UDP header
44
+ * @v conn		UDP connection
45
+ *
46
+ * A promiscuous UDP connection will receive packets with any
47
+ * destination UDP port.  This is required in order to support the PXE
48
+ * UDP API.
49
+ *
50
+ * If the promiscuous connection is not the only UDP connection, the
51
+ * behaviour is undefined.
47 52
  */
48
-void udp_dump ( struct udp_header *udphdr ) {
49
-
50
-	/* Print UDP header for debugging */
51
-	DBG ( "UDP header at %p + %#zx\n", udphdr, sizeof ( *udphdr ) );
52
-	DBG ( "\tSource Port = %d\n", ntohs ( udphdr->source_port ) );
53
-	DBG ( "\tDestination Port = %d\n", ntohs ( udphdr->dest_port ) );
54
-	DBG ( "\tLength = %d\n", ntohs ( udphdr->len ) );
55
-	DBG ( "\tChecksum = %x\n", ntohs ( udphdr->chksum ) );
56
-	DBG ( "\tChecksum located at %p\n", &udphdr->chksum );
53
+void udp_bind_promisc ( struct udp_connection *conn ) {
54
+	conn->local_port = 0;
57 55
 }
58 56
 
59 57
 /**
60
- * Open a UDP connection
58
+ * Connect UDP connection to remote host and port
61 59
  *
62
- * @v conn      UDP connection
63
- * @v peer      Destination socket address
60
+ * @v conn		UDP connection
61
+ * @v peer		Destination socket address
64 62
  *
65 63
  * This function stores the socket address within the connection
66 64
  */
67
-void udp_connect ( struct udp_connection *conn, struct sockaddr *peer ) {
68
-	copy_sockaddr ( peer, &conn->sa );
69
-
70
-	/* Not sure if this should add the connection to udp_conns; If it does,
71
-	 * uncomment the following code
72
-	 */
73
-//	list_add ( &conn->list, &udp_conns );
65
+void udp_connect ( struct udp_connection *conn, struct sockaddr_tcpip *peer ) {
66
+	memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
74 67
 }
75 68
 
76 69
 /**
77
- * Initialize a UDP connection
70
+ * Open a local port
71
+ *
72
+ * @v conn		UDP connection
73
+ * @v local_port	Local port, in network byte order, or zero
74
+ * @ret rc		Return status code
78 75
  *
79
- * @v conn      UDP connection
80
- * @v udp_op	UDP operations
76
+ * Opens the UDP connection and binds to a local port.  If no local
77
+ * port is specified, the first available port will be used.
81 78
  */
82
-void udp_init ( struct udp_connection *conn, struct udp_operations *udp_op ) {
83
-	conn->local_port = 0;
84
-	conn->tx_pkb = NULL;
85
-	if ( udp_op != NULL ) {
86
-		conn->udp_op = udp_op;
79
+int udp_open ( struct udp_connection *conn, uint16_t local_port ) {
80
+	static uint16_t try_port = 1024;
81
+	int rc;
82
+
83
+	/* If no port specified, find the first available port */
84
+	if ( ! local_port ) {
85
+		for ( ; try_port ; try_port++ ) {
86
+			if ( try_port < 1024 )
87
+				continue;
88
+			if ( udp_open ( conn, htons ( try_port ) ) == 0 )
89
+				return 0;
90
+		}
91
+		return -EADDRINUSE;
87 92
 	}
93
+
94
+	/* Attempt bind to local port */
95
+	if ( ( rc = udp_bind ( conn, local_port ) ) != 0 )
96
+		return rc;
97
+
98
+	/* Add to UDP connection list */
99
+	list_add ( &conn->list, &udp_conns );
100
+	DBG ( "UDP opened %p on port %d\n", conn, ntohs ( local_port ) );
101
+
102
+	return 0;
103
+}
104
+
105
+/**
106
+ * Close a UDP connection
107
+ *
108
+ * @v conn		UDP connection
109
+ */
110
+void udp_close ( struct udp_connection *conn ) {
111
+	list_del ( &conn->list );
112
+	DBG ( "UDP closed %p\n", conn );
88 113
 }
89 114
 
90 115
 /**
91 116
  * User request to send data via a UDP connection
92 117
  *
93
- * @v conn	UDP connection
118
+ * @v conn		UDP connection
94 119
  *
95 120
  * This function allocates buffer space and invokes the function's senddata()
96 121
  * callback. The callback may use the buffer space
@@ -98,8 +123,8 @@ void udp_init ( struct udp_connection *conn, struct udp_operations *udp_op ) {
98 123
 int udp_senddata ( struct udp_connection *conn ) {
99 124
 	conn->tx_pkb = alloc_pkb ( UDP_MAX_TXPKB );
100 125
 	if ( conn->tx_pkb == NULL ) {
101
-		DBG ( "Error allocating packet buffer of length %d\n",
102
-							UDP_MAX_TXPKB );
126
+		DBG ( "UDP %p cannot allocate packet buffer of length %d\n",
127
+		      conn, UDP_MAX_TXPKB );
103 128
 		return -ENOMEM;
104 129
 	}
105 130
 	pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
@@ -111,19 +136,25 @@ int udp_senddata ( struct udp_connection *conn ) {
111 136
 /**
112 137
  * Transmit data via a UDP connection to a specified address
113 138
  *
114
- * @v conn      UDP connection
115
- * @v peer	Destination address
116
- * @v data      Data to send
117
- * @v len       Length of data
139
+ * @v conn		UDP connection
140
+ * @v peer		Destination address
141
+ * @v data		Data to send
142
+ * @v len		Length of data
143
+ * @ret rc		Return status code
118 144
  *
119
- * This function fills up the UDP headers and sends the data. Discover the
120
- * network protocol through the sa_family field in the destination socket
121
- * address.
145
+ * This function fills up the UDP headers and sends the data.  It may
146
+ * be called only from within the context of an application's
147
+ * senddata() method; if the application wishes to send data it must
148
+ * call udp_senddata() and wait for its senddata() method to be
149
+ * called.
122 150
  */
123
-int udp_sendto ( struct udp_connection *conn, struct sockaddr *peer,
151
+int udp_sendto ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
124 152
 		 const void *data, size_t len ) {
125
-       	struct udp_header *udphdr;		/* UDP header */
126
-	uint16_t *dest;
153
+       	struct udp_header *udphdr;
154
+
155
+	/* Avoid overflowing TX buffer */
156
+	if ( len > pkb_available ( conn->tx_pkb ) )
157
+		len = pkb_available ( conn->tx_pkb );
127 158
 
128 159
 	/* Copy payload */
129 160
 	memmove ( pkb_put ( conn->tx_pkb, len ), data, len );
@@ -135,104 +166,77 @@ int udp_sendto ( struct udp_connection *conn, struct sockaddr *peer,
135 166
 	 * sending it over the network
136 167
 	 */
137 168
 	udphdr = pkb_push ( conn->tx_pkb, sizeof ( *udphdr ) );
138
-	if ( (dest = dest_port ( peer ) ) == NULL ) {
139
-		DBG ( "Network family %d not supported\n", peer->sa_family );
140
-		return -EAFNOSUPPORT;
141
-	}
142
-	udphdr->dest_port = *dest;
169
+	udphdr->dest_port = peer->st_port;
143 170
 	udphdr->source_port = conn->local_port;
144 171
 	udphdr->len = htons ( pkb_len ( conn->tx_pkb ) );
145 172
 	udphdr->chksum = 0;
146 173
 	udphdr->chksum = tcpip_chksum ( udphdr, sizeof ( *udphdr ) + len );
147 174
 
148
-	/**
149
-	 * Dump the contents of the UDP header
150
-	 */
151
-	udp_dump ( udphdr );
175
+	/* Dump debugging information */
176
+	DBG ( "UDP %p transmitting %p+%#zx len %#x src %d dest %d "
177
+	      "chksum %#04x\n", conn, conn->tx_pkb->data,
178
+	      pkb_len ( conn->tx_pkb ), ntohs ( udphdr->len ),
179
+	      ntohs ( udphdr->source_port ), ntohs ( udphdr->dest_port ),
180
+	      ntohs ( udphdr->chksum ) );
152 181
 
153 182
 	/* Send it to the next layer for processing */
154 183
 	return tcpip_tx ( conn->tx_pkb, &udp_protocol, peer );
155 184
 }
156 185
 
157 186
 /**
158
- * Transmit data via a UDP connection to a specified address
159
- *
160
- * @v conn      UDP connection
161
- * @v data      Data to send
162
- * @v len       Length of data
163
- */
164
-int udp_send ( struct udp_connection *conn, const void *data, size_t len ) {
165
-	return udp_sendto ( conn, &conn->sa, data, len );
166
-}
167
-
168
-/**
169
- * Close a UDP connection
170
- *
171
- * @v conn      UDP connection
172
- */
173
-void udp_close ( struct udp_connection *conn ) {
174
-	list_del ( &conn->list );
175
-}
176
-
177
-/**
178
- * Open a local port
187
+ * Transmit data via a UDP connection
179 188
  *
180 189
  * @v conn		UDP connection
181
- * @v local_port	Local port on which to open connection
190
+ * @v data		Data to send
191
+ * @v len		Length of data
192
+ * @ret rc		Return status code
182 193
  *
183
- * This does not support the 0 port option correctly yet
194
+ * This function fills up the UDP headers and sends the data.  It may
195
+ * be called only from within the context of an application's
196
+ * senddata() method; if the application wishes to send data it must
197
+ * call udp_senddata() and wait for its senddata() method to be
198
+ * called.
184 199
  */
185
-int udp_open ( struct udp_connection *conn, uint16_t local_port ) {
186
-	struct udp_connection *connr;
187
-	uint16_t min_port = 0xffff;
188
-
189
-	/* Iterate through udp_conns to see if local_port is available */
190
-	list_for_each_entry ( connr, &udp_conns, list ) {
191
-		if ( connr->local_port == local_port ) {
192
-			return -EISCONN;
193
-		}
194
-		if ( min_port > connr->local_port ) {
195
-			min_port = connr->local_port;
196
-		}
197
-	}
198
-	/* This code is buggy. I will update it soon :) */
199
-	conn->local_port = local_port == 0 ? min_port > 1024 ? 1024 :
200
-						min_port + 1 : local_port;
201
-
202
-	/* Add the connection to the list of listening connections */
203
-	list_add ( &conn->list, &udp_conns );
204
-	return 0;
200
+int udp_send ( struct udp_connection *conn, const void *data, size_t len ) {
201
+	return udp_sendto ( conn, &conn->peer, data, len );
205 202
 }
206 203
 
207 204
 /**
208 205
  * Process a received packet
209 206
  *
210
- * @v pkb	       Packet buffer
211
- * @v src_net_addr      Source network address
212
- * @v dest_net_addr     Destination network address
207
+ * @v pkb		Packet buffer
208
+ * @v st_src		Partially-filled source address
209
+ * @v st_dest		Partially-filled destination address
210
+ * @ret rc		Return status code
213 211
  */
214
-void udp_rx ( struct pk_buff *pkb, struct in_addr *src_net_addr __unused,
215
-			struct in_addr *dest_net_addr __unused ) {
212
+static int udp_rx ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
213
+		    struct sockaddr_tcpip *st_dest ) {
216 214
 	struct udp_header *udphdr = pkb->data;
217 215
 	struct udp_connection *conn;
218
-	uint16_t ulen;
216
+	unsigned int ulen;
219 217
 	uint16_t chksum;
220 218
 
221
-	udp_dump ( udphdr );
222
-
223
-	/* Validate the packet and the UDP length */
219
+	/* Sanity check */
224 220
 	if ( pkb_len ( pkb ) < sizeof ( *udphdr ) ) {
225
-		DBG ( "UDP packet too short (%d bytes)\n",
226
-		      pkb_len ( pkb ) );
227
-		return;
221
+		DBG ( "UDP received underlength packet %p+%#zx\n",
222
+		      pkb->data, pkb_len ( pkb ) );
223
+		return -EINVAL;
228 224
 	}
229 225
 
226
+	/* Dump debugging information */
227
+	DBG ( "UDP received %p+%#zx len %#x src %d dest %d chksum %#04x\n",
228
+	      pkb->data, pkb_len ( pkb ), ntohs ( udphdr->len ),
229
+	      ntohs ( udphdr->source_port ), ntohs ( udphdr->dest_port ),
230
+	      ntohs ( udphdr->chksum ) );
231
+
232
+	/* Check length and trim any excess */
230 233
 	ulen = ntohs ( udphdr->len );
231
-	if ( ulen != pkb_len ( pkb ) ) {
232
-		DBG ( "Inconsistent UDP packet length (%d bytes)\n",
233
-		      pkb_len ( pkb ) );
234
-		return;
234
+	if ( ulen > pkb_len ( pkb ) ) {
235
+		DBG ( "UDP received truncated packet %p+%#zx\n",
236
+		      pkb->data, pkb_len ( pkb ) );
237
+		return -EINVAL;
235 238
 	}
239
+	pkb_unput ( pkb, ( pkb_len ( pkb ) - ulen ) );
236 240
 
237 241
 	/* Verify the checksum */
238 242
 #warning "Don't we need to take the pseudo-header into account here?"
@@ -240,32 +244,49 @@ void udp_rx ( struct pk_buff *pkb, struct in_addr *src_net_addr __unused,
240 244
 	chksum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
241 245
 	if ( chksum != 0xffff ) {
242 246
 		DBG ( "Bad checksum %#x\n", chksum );
243
-		return;
247
+		return -EINVAL;
244 248
 	}
245 249
 #endif
246 250
 
247
-	/* Todo: Check if it is a broadcast or multicast address */
251
+	/* Complete the socket addresses */
252
+	st_src->st_port = udphdr->source_port;
253
+	st_dest->st_port = udphdr->dest_port;
248 254
 
249 255
 	/* Demux the connection */
250 256
 	list_for_each_entry ( conn, &udp_conns, list ) {
251
-		if ( conn->local_port == udphdr->dest_port ) {
252
-			goto conn;
257
+		if ( conn->local_port &&
258
+		     ( conn->local_port != udphdr->dest_port ) ) {
259
+			/* Bound to local port and local port doesn't match */
260
+			continue;
253 261
 		}
254
-	}
255
-	return;
262
+		if ( conn->peer.st_family &&
263
+		     ( memcmp ( &conn->peer, st_src,
264
+				sizeof ( conn->peer ) ) != 0 ) ) {
265
+			/* Connected to remote port and remote port
266
+			 * doesn't match
267
+			 */
268
+			continue;
269
+		}
270
+		
271
+		/* Strip off the UDP header */
272
+		pkb_pull ( pkb, sizeof ( *udphdr ) );
256 273
 
257
-	conn:
258
-	/** Strip off the UDP header */
259
-	pkb_pull ( pkb, sizeof ( *udphdr ) );
274
+		DBG ( "UDP delivering to %p\n", conn );
275
+		
276
+		/* Call the application's callback */
277
+		return conn->udp_op->newdata ( conn, pkb->data, pkb_len( pkb ),
278
+					       st_src, st_dest );
279
+	}
260 280
 
261
-	/** Call the application's callback */
262
-	conn->udp_op->newdata ( conn, pkb->data, ulen - sizeof ( *udphdr ) );
281
+	DBG ( "No UDP connection listening on port %d\n",
282
+	      ntohs ( udphdr->dest_port ) );
283
+	return 0;
263 284
 }
264 285
 
265 286
 struct tcpip_protocol udp_protocol  = {
266 287
 	.name = "UDP",
267 288
 	.rx = udp_rx,
268
-	.trans_proto = IP_UDP,
289
+	.tcpip_proto = IP_UDP,
269 290
 	.csum_offset = 6,
270 291
 };
271 292
 

+ 15
- 8
src/net/udp/dhcp.c Zobrazit soubor

@@ -491,9 +491,12 @@ static void dhcp_done ( struct dhcp_session *dhcp, int rc ) {
491 491
 }
492 492
 
493 493
 /** Address for transmitting DHCP requests */
494
-static struct sockaddr sa_dhcp_server = {
495
-	.sa_family = AF_INET,
494
+static union {
495
+	struct sockaddr_tcpip st;
496
+	struct sockaddr_in sin;
497
+} sa_dhcp_server = {
496 498
 	.sin = {
499
+		.sin_family = AF_INET,
497 500
 		.sin_addr.s_addr = INADDR_BROADCAST,
498 501
 		.sin_port = htons ( BOOTPS_PORT ),
499 502
 	},
@@ -548,7 +551,7 @@ static void dhcp_senddata ( struct udp_connection *conn,
548 551
 	}
549 552
 
550 553
 	/* Transmit the packet */
551
-	if ( ( rc = udp_sendto ( conn, &sa_dhcp_server,
554
+	if ( ( rc = udp_sendto ( conn, &sa_dhcp_server.st,
552 555
 				 dhcppkt.dhcphdr, dhcppkt.len ) ) != 0 ) {
553 556
 		DBG ( "Could not transmit UDP packet\n" );
554 557
 		return;
@@ -588,9 +591,12 @@ static void dhcp_timer_expired ( struct retry_timer *timer, int fail ) {
588 591
  * @v udp		UDP connection
589 592
  * @v data		Received data
590 593
  * @v len		Length of received data
594
+ * @v st_src		Partially-filled source address
595
+ * @v st_dest		Partially-filled destination address
591 596
  */
592
-static void dhcp_newdata ( struct udp_connection *conn,
593
-			   void *data, size_t len ) {
597
+static int dhcp_newdata ( struct udp_connection *conn, void *data, size_t len,
598
+			  struct sockaddr_tcpip *st_src __unused,
599
+			  struct sockaddr_tcpip *st_dest __unused ) {
594 600
 	struct dhcp_session *dhcp = udp_to_dhcp ( conn );
595 601
 	struct dhcphdr *dhcphdr = data;
596 602
 	struct dhcp_option_block *options;
@@ -600,14 +606,14 @@ static void dhcp_newdata ( struct udp_connection *conn,
600 606
 	if ( dhcphdr->xid != dhcp->xid ) {
601 607
 		DBG ( "DHCP wrong transaction ID (wanted %08lx, got %08lx)\n",
602 608
 		      ntohl ( dhcphdr->xid ), ntohl ( dhcp->xid ) );
603
-		return;
609
+		return 0;
604 610
 	};
605 611
 
606 612
 	/* Parse packet and create options structure */
607 613
 	options = dhcp_parse ( dhcphdr, len );
608 614
 	if ( ! options ) {
609 615
 		DBG ( "Could not parse DHCP packet\n" );
610
-		return;
616
+		return -EINVAL;
611 617
 	}
612 618
 
613 619
 	/* Determine message type */
@@ -643,10 +649,11 @@ static void dhcp_newdata ( struct udp_connection *conn,
643 649
 	} else {
644 650
 		dhcp_done ( dhcp, 0 );
645 651
 	}
646
-	return;
652
+	return 0;
647 653
 
648 654
  out_discard:
649 655
 	free_dhcp_options ( options );
656
+	return 0;
650 657
 }
651 658
 
652 659
 /** DHCP UDP operations */

Načítá se…
Zrušit
Uložit