Browse Source

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 18 years ago
parent
commit
467e9627cc
13 changed files with 394 additions and 481 deletions
  1. 18
    24
      src/include/gpxe/in.h
  2. 0
    4
      src/include/gpxe/ip.h
  3. 8
    4
      src/include/gpxe/tcp.h
  4. 58
    37
      src/include/gpxe/tcpip.h
  5. 14
    23
      src/include/gpxe/udp.h
  6. 1
    1
      src/include/proto.h
  7. 1
    1
      src/include/tftp.h
  8. 41
    143
      src/net/ipv4.c
  9. 8
    11
      src/net/ipv6.c
  10. 22
    30
      src/net/tcp.c
  11. 47
    55
      src/net/tcpip.c
  12. 161
    140
      src/net/udp.c
  13. 15
    8
      src/net/udp/dhcp.c

+ 18
- 24
src/include/gpxe/in.h View File

2
 #define	_GPXE_IN_H
2
 #define	_GPXE_IN_H
3
 
3
 
4
 #include <stdint.h>
4
 #include <stdint.h>
5
+#include <gpxe/socket.h>
5
 
6
 
6
 /* Protocol numbers */
7
 /* Protocol numbers */
7
 
8
 
10
 #define IP_TCP		6
11
 #define IP_TCP		6
11
 #define IP_UDP		17
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
 /* IP address constants */
14
 /* IP address constants */
23
 
15
 
24
 #define INADDR_NONE 0xffffffff
16
 #define INADDR_NONE 0xffffffff
50
 #define s6_addr32       in6_u.u6_addr32
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
 struct sockaddr_in {
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
  * IPv6 socket address
61
  * IPv6 socket address
65
  */
62
  */
66
 struct sockaddr_in6 {
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
         uint32_t        sin6_flowinfo;  /* Flow number */
71
         uint32_t        sin6_flowinfo;  /* Flow number */
69
         struct in6_addr sin6_addr;      /* 128-bit destination address */
72
         struct in6_addr sin6_addr;      /* 128-bit destination address */
70
         uint32_t        sin6_scope_id;  /* Scope ID */
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
 extern int inet_aton ( const char *cp, struct in_addr *inp );
76
 extern int inet_aton ( const char *cp, struct in_addr *inp );
83
 extern char * inet_ntoa ( struct in_addr in );
77
 extern char * inet_ntoa ( struct in_addr in );
84
 
78
 

+ 0
- 4
src/include/gpxe/ip.h View File

64
 			      struct in_addr gateway );
64
 			      struct in_addr gateway );
65
 extern void del_ipv4_address ( struct net_device *netdev );
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
 #endif /* _GPXE_IP_H */
67
 #endif /* _GPXE_IP_H */

+ 8
- 4
src/include/gpxe/tcp.h View File

10
  */
10
  */
11
 
11
 
12
 #include <stddef.h>
12
 #include <stddef.h>
13
-#include <gpxe/in.h>
14
 #include <gpxe/list.h>
13
 #include <gpxe/list.h>
14
+#include <gpxe/tcpip.h>
15
 #include <gpxe/pkbuff.h>
15
 #include <gpxe/pkbuff.h>
16
 
16
 
17
 struct tcp_connection;
17
 struct tcp_connection;
142
  * A TCP connection
142
  * A TCP connection
143
  */
143
  */
144
 struct tcp_connection {
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
 	uint16_t local_port;		/* Local port, in network byte order */
150
 	uint16_t local_port;		/* Local port, in network byte order */
148
 	int tcp_state;			/* TCP state */
151
 	int tcp_state;			/* TCP state */
149
 	int tcp_lstate;			/* Last TCP state */
152
 	int tcp_lstate;			/* Last TCP state */
200
 
203
 
201
 extern void tcp_init_conn ( struct tcp_connection *conn );
204
 extern void tcp_init_conn ( struct tcp_connection *conn );
202
 extern int tcp_connect ( struct tcp_connection *conn );
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
 extern int tcp_listen ( struct tcp_connection *conn, uint16_t port );
208
 extern int tcp_listen ( struct tcp_connection *conn, uint16_t port );
205
 extern int tcp_senddata ( struct tcp_connection *conn );
209
 extern int tcp_senddata ( struct tcp_connection *conn );
206
 extern int tcp_close ( struct tcp_connection *conn );
210
 extern int tcp_close ( struct tcp_connection *conn );

+ 58
- 37
src/include/gpxe/tcpip.h View File

8
  */
8
  */
9
 
9
 
10
 #include <stdint.h>
10
 #include <stdint.h>
11
+#include <gpxe/socket.h>
11
 #include <gpxe/in.h>
12
 #include <gpxe/in.h>
12
 #include <gpxe/tables.h>
13
 #include <gpxe/tables.h>
13
 
14
 
14
 struct pk_buff;
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
 struct tcpip_protocol {
42
 struct tcpip_protocol {
23
 	/** Protocol name */
43
 	/** Protocol name */
25
        	/**
45
        	/**
26
          * Process received packet
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
          * This method takes ownership of the packet buffer.
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
 	 * Transport-layer protocol number
58
 	 * Transport-layer protocol number
39
 	 *
59
 	 *
40
 	 * This is a constant of the type IP_XXX
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
 	 * Checksum offset
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
 	int csum_offset;
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
 struct tcpip_net_protocol {
77
 struct tcpip_net_protocol {
57
-	/** Network protocol */
58
-	struct net_protocol *net_protocol;
78
+	/** Protocol name */
79
+	const char *name;
59
 	/** Network address family */
80
 	/** Network address family */
60
 	sa_family_t sa_family;
81
 	sa_family_t sa_family;
61
 	/**
82
 	/**
62
 	 * Transmit packet
83
 	 * Transmit packet
63
 	 *
84
 	 *
64
 	 * @v pkb		Packet buffer
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
 #define TCPIP_PROTOCOL( protocol ) \
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
 #define TCPIP_NET_PROTOCOL( protocol ) \
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
 extern int tcpip_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip, 
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
 extern unsigned int tcpip_continue_chksum ( unsigned int partial,
118
 extern unsigned int tcpip_continue_chksum ( unsigned int partial,
98
 					    const void *data, size_t len );
119
 					    const void *data, size_t len );
99
 extern unsigned int tcpip_chksum ( const void *data, size_t len );
120
 extern unsigned int tcpip_chksum ( const void *data, size_t len );

+ 14
- 23
src/include/gpxe/udp.h View File

10
  */
10
  */
11
 
11
 
12
 #include <stddef.h>
12
 #include <stddef.h>
13
-#include <gpxe/in.h>
14
 #include <gpxe/pkbuff.h>
13
 #include <gpxe/pkbuff.h>
14
+#include <gpxe/tcpip.h>
15
 #include <gpxe/if_ether.h>
15
 #include <gpxe/if_ether.h>
16
 
16
 
17
 /**
17
 /**
65
 	 * @v data	Data
65
 	 * @v data	Data
66
 	 * @v len	Length of data
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
  */
76
  */
76
 struct udp_connection {
77
 struct udp_connection {
77
        /** Address of the remote end of the connection */
78
        /** Address of the remote end of the connection */
78
-	struct sockaddr sa;
79
+	struct sockaddr_tcpip peer;
79
 	/** Local port on which the connection receives packets */
80
 	/** Local port on which the connection receives packets */
80
 	port_t local_port;
81
 	port_t local_port;
81
 	/** Transmit buffer */
82
 	/** Transmit buffer */
86
 	struct udp_operations *udp_op;
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
  * Functions provided to the application layer
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
 extern int udp_open ( struct udp_connection *conn, uint16_t local_port );
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
 extern void udp_close ( struct udp_connection *conn );
98
 extern void udp_close ( struct udp_connection *conn );
103
 
99
 
104
 extern int udp_senddata ( struct udp_connection *conn );
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
 #endif /* _GPXE_UDP_H */
107
 #endif /* _GPXE_UDP_H */

+ 1
- 1
src/include/proto.h View File

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

+ 1
- 1
src/include/tftp.h View File

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

+ 41
- 143
src/net/ipv4.c View File

128
  * @v timer	Retry timer
128
  * @v timer	Retry timer
129
  * @v over	If asserted, the timer is greater than @c MAX_TIMEOUT 
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
 	if ( over ) {
133
 	if ( over ) {
133
 		DBG ( "Fragment reassembly timeout" );
134
 		DBG ( "Fragment reassembly timeout" );
134
 		/* Free the fragment buffer */
135
 		/* Free the fragment buffer */
140
  *
141
  *
141
  * @v fragbug	Fragment buffer
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
 	if ( fragbuf ) {
145
 	if ( fragbuf ) {
145
 		free_dma ( fragbuf, sizeof ( *fragbuf ) );
146
 		free_dma ( fragbuf, sizeof ( *fragbuf ) );
146
 	}
147
 	}
152
  * @v pkb		Packet buffer, fragment of the datagram
153
  * @v pkb		Packet buffer, fragment of the datagram
153
  * @ret frag_pkb	Reassembled packet, or NULL
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
 	struct iphdr *iphdr = pkb->data;
157
 	struct iphdr *iphdr = pkb->data;
157
 	struct frag_buffer *fragbuf;
158
 	struct frag_buffer *fragbuf;
158
 	
159
 	
234
  *
235
  *
235
  * This function calculates the tcpip 
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
 	struct iphdr *iphdr = pkb->data;
240
 	struct iphdr *iphdr = pkb->data;
240
 	struct ipv4_pseudo_header pshdr;
241
 	struct ipv4_pseudo_header pshdr;
241
 	uint16_t *csum = ( ( ( void * ) iphdr ) + sizeof ( *iphdr )
242
 	uint16_t *csum = ( ( ( void * ) iphdr ) + sizeof ( *iphdr )
255
 /**
256
 /**
256
  * Calculate the transport-layer checksum while processing packets
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
 	 * This function needs to be implemented. Until then, it will return
262
 	 * This function needs to be implemented. Until then, it will return
262
 	 * 0xffffffff every time
263
 	 * 0xffffffff every time
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
  * @v pkb		Packet buffer
271
  * @v pkb		Packet buffer
343
  * @v tcpip		Transport-layer protocol
272
  * @v tcpip		Transport-layer protocol
344
- * @v dest		Destination network-layer address
273
+ * @v st_dest		Destination network-layer address
345
  * @ret rc		Status
274
  * @ret rc		Status
346
  *
275
  *
347
  * This function expects a transport-layer segment and prepends the IP header
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
 	struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
281
 	struct iphdr *iphdr = pkb_push ( pkb, sizeof ( *iphdr ) );
282
+	struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
353
 	struct ipv4_miniroute *miniroute;
283
 	struct ipv4_miniroute *miniroute;
354
 	struct net_device *netdev = NULL;
284
 	struct net_device *netdev = NULL;
355
 	struct in_addr next_hop;
285
 	struct in_addr next_hop;
364
 	iphdr->ident = htons ( next_ident++ );
294
 	iphdr->ident = htons ( next_ident++ );
365
 	iphdr->frags = 0;
295
 	iphdr->frags = 0;
366
 	iphdr->ttl = IP_TTL;
296
 	iphdr->ttl = IP_TTL;
367
-	iphdr->protocol = tcpip->trans_proto;
297
+	iphdr->protocol = tcpip_protocol->tcpip_proto;
368
 
298
 
369
 	/* Copy destination address */
299
 	/* Copy destination address */
370
-	iphdr->dest = *dest;
300
+	iphdr->dest = sin_dest->sin_addr;
371
 
301
 
372
 	/**
302
 	/**
373
 	 * All fields in the IP header filled in except the source network
303
 	 * All fields in the IP header filled in except the source network
375
 	 * requires the source network address). As the pseudo header requires
305
 	 * requires the source network address). As the pseudo header requires
376
 	 * the source address as well and the transport-layer checksum is
306
 	 * the source address as well and the transport-layer checksum is
377
 	 * updated after routing.
307
 	 * updated after routing.
378
-	 *
379
-	 * Continue processing as in ipv4_uip_tx()
380
 	 */
308
 	 */
381
 
309
 
382
 	/* Use routing table to identify next hop and transmitting netdev */
310
 	/* Use routing table to identify next hop and transmitting netdev */
400
 	}
328
 	}
401
 
329
 
402
 	/* Calculate the transport layer checksum */
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
 	/* Calculate header checksum, in network byte order */
335
 	/* Calculate header checksum, in network byte order */
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
  * @v pkb	Packet buffer
379
  * @v pkb	Packet buffer
487
  * @v netdev	Network device
380
  * @v netdev	Network device
490
  * This function expects an IP4 network datagram. It processes the headers 
383
  * This function expects an IP4 network datagram. It processes the headers 
491
  * and sends it to the transport layer.
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
 	struct iphdr *iphdr = pkb->data;
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
 	uint16_t chksum;
393
 	uint16_t chksum;
499
 
394
 
500
 	/* Sanity check */
395
 	/* Sanity check */
501
 	if ( pkb_len ( pkb ) < sizeof ( *iphdr ) ) {
396
 	if ( pkb_len ( pkb ) < sizeof ( *iphdr ) ) {
502
 		DBG ( "IP datagram too short (%d bytes)\n",
397
 		DBG ( "IP datagram too short (%d bytes)\n",
503
 			pkb_len ( pkb ) );
398
 			pkb_len ( pkb ) );
504
-		return;
399
+		return -EINVAL;
505
 	}
400
 	}
506
 
401
 
507
 	/* Print IP4 header for debugging */
402
 	/* Print IP4 header for debugging */
510
 	/* Validate version and header length */
405
 	/* Validate version and header length */
511
 	if ( iphdr->verhdrlen != 0x45 ) {
406
 	if ( iphdr->verhdrlen != 0x45 ) {
512
 		DBG ( "Bad version and header length %x\n", iphdr->verhdrlen );
407
 		DBG ( "Bad version and header length %x\n", iphdr->verhdrlen );
513
-		return;
408
+		return -EINVAL;
514
 	}
409
 	}
515
 
410
 
516
 	/* Validate length of IP packet */
411
 	/* Validate length of IP packet */
517
-	if ( ntohs ( iphdr->len ) != pkb_len ( pkb ) ) {
412
+	if ( ntohs ( iphdr->len ) > pkb_len ( pkb ) ) {
518
 		DBG ( "Inconsistent packet length %d\n",
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
 	/* Verify the checksum */
418
 	/* Verify the checksum */
533
 		 */
428
 		 */
534
 		pkb = ipv4_reassemble ( pkb );
429
 		pkb = ipv4_reassemble ( pkb );
535
 		if ( !pkb ) {
430
 		if ( !pkb ) {
536
-			return;
431
+			return 0;
537
 		}
432
 		}
538
 	}
433
 	}
539
 
434
 
543
 	 * 3. Check the service field
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
 	/* Strip header */
449
 	/* Strip header */
547
 	pkb_pull ( pkb, sizeof ( *iphdr ) );
450
 	pkb_pull ( pkb, sizeof ( *iphdr ) );
548
 
451
 
549
 	/* Send it to the transport layer */
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
 	.name = "IP",
504
 	.name = "IP",
602
 	.net_proto = htons ( ETH_P_IP ),
505
 	.net_proto = htons ( ETH_P_IP ),
603
 	.net_addr_len = sizeof ( struct in_addr ),
506
 	.net_addr_len = sizeof ( struct in_addr ),
604
-#if USE_UIP
605
-	.rx = ipv4_uip_rx,
606
-#else
607
 	.rx = ipv4_rx,
507
 	.rx = ipv4_rx,
608
-#endif
609
 	.ntoa = ipv4_ntoa,
508
 	.ntoa = ipv4_ntoa,
610
 };
509
 };
611
 
510
 
613
 
512
 
614
 /** IPv4 TCPIP net protocol */
513
 /** IPv4 TCPIP net protocol */
615
 struct tcpip_net_protocol ipv4_tcpip_protocol = {
514
 struct tcpip_net_protocol ipv4_tcpip_protocol = {
616
-	.net_protocol = &ipv4_protocol,
515
+	.name = "IPv4",
617
 	.sa_family = AF_INET,
516
 	.sa_family = AF_INET,
618
 	.tx = ipv4_tx,
517
 	.tx = ipv4_tx,
619
-	.tx_csum = ipv4_tx_csum,
620
 };
518
 };
621
 
519
 
622
 TCPIP_NET_PROTOCOL ( ipv4_tcpip_protocol );
520
 TCPIP_NET_PROTOCOL ( ipv4_tcpip_protocol );

+ 8
- 11
src/net/ipv6.c View File

12
 /**
12
 /**
13
  * Transmit IP6 packets
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
 	return -ENOSYS;
18
 	return -ENOSYS;
18
 }
19
 }
19
 
20
 
22
  *
23
  *
23
  * Placeholder function. Should rewrite in net/ipv6.c
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
 static const char * ipv6_ntoa ( const void *net_addr ) {
32
 static const char * ipv6_ntoa ( const void *net_addr ) {
49
 
47
 
50
 /** IPv6 TCPIP net protocol */
48
 /** IPv6 TCPIP net protocol */
51
 struct tcpip_net_protocol ipv6_tcpip_protocol = {
49
 struct tcpip_net_protocol ipv6_tcpip_protocol = {
52
-	.net_protocol = &ipv6_protocol,
50
+	.name = "IPv6",
53
 	.sa_family = AF_INET6,
51
 	.sa_family = AF_INET6,
54
 	.tx = ipv6_tx,
52
 	.tx = ipv6_tx,
55
-	.tx_csum = ipv6_tx_csum,
56
 };
53
 };
57
 
54
 
58
 TCPIP_NET_PROTOCOL ( ipv6_tcpip_protocol );
55
 TCPIP_NET_PROTOCOL ( ipv6_tcpip_protocol );

+ 22
- 30
src/net/tcp.c View File

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

+ 47
- 55
src/net/tcpip.c View File

1
 #include <stdint.h>
1
 #include <stdint.h>
2
 #include <string.h>
2
 #include <string.h>
3
 #include <errno.h>
3
 #include <errno.h>
4
-#include <malloc.h>
5
 #include <byteswap.h>
4
 #include <byteswap.h>
6
-#include <gpxe/in.h>
7
-#include <gpxe/ip.h>
8
-#include <gpxe/ip6.h>
9
 #include <gpxe/pkbuff.h>
5
 #include <gpxe/pkbuff.h>
10
 #include <gpxe/tables.h>
6
 #include <gpxe/tables.h>
11
-#include <gpxe/netdevice.h>
12
 #include <gpxe/tcpip.h>
7
 #include <gpxe/tcpip.h>
13
 
8
 
14
 /** @file
9
 /** @file
15
  *
10
  *
16
  * Transport-network layer interface
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
  * @v pkb		Packet buffer
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
 	struct tcpip_protocol *tcpip;
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
  * @v pkb		Packet buffer
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
 	struct tcpip_net_protocol *tcpip_net;
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
 	return -EAFNOSUPPORT;
81
 	return -EAFNOSUPPORT;
88
 }
82
 }
89
 
83
 
90
-#endif
91
-
92
 /**
84
 /**
93
  * Calculate continued TCP/IP checkum
85
  * Calculate continued TCP/IP checkum
94
  *
86
  *

+ 161
- 140
src/net/udp.c View File

2
 #include <string.h>
2
 #include <string.h>
3
 #include <assert.h>
3
 #include <assert.h>
4
 #include <byteswap.h>
4
 #include <byteswap.h>
5
-#include <latch.h>
6
 #include <errno.h>
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
 #include <gpxe/pkbuff.h>
7
 #include <gpxe/pkbuff.h>
13
 #include <gpxe/netdevice.h>
8
 #include <gpxe/netdevice.h>
14
-#include <gpxe/tcpip.h>
9
+#include <gpxe/udp.h>
15
 
10
 
16
 /** @file
11
 /** @file
17
  *
12
  *
18
  * UDP protocol
13
  * UDP protocol
19
  */
14
  */
20
 
15
 
16
+struct tcpip_protocol udp_protocol;
17
+
21
 /**
18
 /**
22
  * List of registered UDP connections
19
  * List of registered UDP connections
23
  */
20
  */
24
 static LIST_HEAD ( udp_conns );
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
  * This function stores the socket address within the connection
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
  * User request to send data via a UDP connection
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
  * This function allocates buffer space and invokes the function's senddata()
120
  * This function allocates buffer space and invokes the function's senddata()
96
  * callback. The callback may use the buffer space
121
  * callback. The callback may use the buffer space
98
 int udp_senddata ( struct udp_connection *conn ) {
123
 int udp_senddata ( struct udp_connection *conn ) {
99
 	conn->tx_pkb = alloc_pkb ( UDP_MAX_TXPKB );
124
 	conn->tx_pkb = alloc_pkb ( UDP_MAX_TXPKB );
100
 	if ( conn->tx_pkb == NULL ) {
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
 		return -ENOMEM;
128
 		return -ENOMEM;
104
 	}
129
 	}
105
 	pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
130
 	pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
111
 /**
136
 /**
112
  * Transmit data via a UDP connection to a specified address
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
 		 const void *data, size_t len ) {
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
 	/* Copy payload */
159
 	/* Copy payload */
129
 	memmove ( pkb_put ( conn->tx_pkb, len ), data, len );
160
 	memmove ( pkb_put ( conn->tx_pkb, len ), data, len );
135
 	 * sending it over the network
166
 	 * sending it over the network
136
 	 */
167
 	 */
137
 	udphdr = pkb_push ( conn->tx_pkb, sizeof ( *udphdr ) );
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
 	udphdr->source_port = conn->local_port;
170
 	udphdr->source_port = conn->local_port;
144
 	udphdr->len = htons ( pkb_len ( conn->tx_pkb ) );
171
 	udphdr->len = htons ( pkb_len ( conn->tx_pkb ) );
145
 	udphdr->chksum = 0;
172
 	udphdr->chksum = 0;
146
 	udphdr->chksum = tcpip_chksum ( udphdr, sizeof ( *udphdr ) + len );
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
 	/* Send it to the next layer for processing */
182
 	/* Send it to the next layer for processing */
154
 	return tcpip_tx ( conn->tx_pkb, &udp_protocol, peer );
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
  * @v conn		UDP connection
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
  * Process a received packet
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
 	struct udp_header *udphdr = pkb->data;
214
 	struct udp_header *udphdr = pkb->data;
217
 	struct udp_connection *conn;
215
 	struct udp_connection *conn;
218
-	uint16_t ulen;
216
+	unsigned int ulen;
219
 	uint16_t chksum;
217
 	uint16_t chksum;
220
 
218
 
221
-	udp_dump ( udphdr );
222
-
223
-	/* Validate the packet and the UDP length */
219
+	/* Sanity check */
224
 	if ( pkb_len ( pkb ) < sizeof ( *udphdr ) ) {
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
 	ulen = ntohs ( udphdr->len );
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
 	/* Verify the checksum */
241
 	/* Verify the checksum */
238
 #warning "Don't we need to take the pseudo-header into account here?"
242
 #warning "Don't we need to take the pseudo-header into account here?"
240
 	chksum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
244
 	chksum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
241
 	if ( chksum != 0xffff ) {
245
 	if ( chksum != 0xffff ) {
242
 		DBG ( "Bad checksum %#x\n", chksum );
246
 		DBG ( "Bad checksum %#x\n", chksum );
243
-		return;
247
+		return -EINVAL;
244
 	}
248
 	}
245
 #endif
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
 	/* Demux the connection */
255
 	/* Demux the connection */
250
 	list_for_each_entry ( conn, &udp_conns, list ) {
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
 struct tcpip_protocol udp_protocol  = {
286
 struct tcpip_protocol udp_protocol  = {
266
 	.name = "UDP",
287
 	.name = "UDP",
267
 	.rx = udp_rx,
288
 	.rx = udp_rx,
268
-	.trans_proto = IP_UDP,
289
+	.tcpip_proto = IP_UDP,
269
 	.csum_offset = 6,
290
 	.csum_offset = 6,
270
 };
291
 };
271
 
292
 

+ 15
- 8
src/net/udp/dhcp.c View File

491
 }
491
 }
492
 
492
 
493
 /** Address for transmitting DHCP requests */
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
 	.sin = {
498
 	.sin = {
499
+		.sin_family = AF_INET,
497
 		.sin_addr.s_addr = INADDR_BROADCAST,
500
 		.sin_addr.s_addr = INADDR_BROADCAST,
498
 		.sin_port = htons ( BOOTPS_PORT ),
501
 		.sin_port = htons ( BOOTPS_PORT ),
499
 	},
502
 	},
548
 	}
551
 	}
549
 
552
 
550
 	/* Transmit the packet */
553
 	/* Transmit the packet */
551
-	if ( ( rc = udp_sendto ( conn, &sa_dhcp_server,
554
+	if ( ( rc = udp_sendto ( conn, &sa_dhcp_server.st,
552
 				 dhcppkt.dhcphdr, dhcppkt.len ) ) != 0 ) {
555
 				 dhcppkt.dhcphdr, dhcppkt.len ) ) != 0 ) {
553
 		DBG ( "Could not transmit UDP packet\n" );
556
 		DBG ( "Could not transmit UDP packet\n" );
554
 		return;
557
 		return;
588
  * @v udp		UDP connection
591
  * @v udp		UDP connection
589
  * @v data		Received data
592
  * @v data		Received data
590
  * @v len		Length of received data
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
 	struct dhcp_session *dhcp = udp_to_dhcp ( conn );
600
 	struct dhcp_session *dhcp = udp_to_dhcp ( conn );
595
 	struct dhcphdr *dhcphdr = data;
601
 	struct dhcphdr *dhcphdr = data;
596
 	struct dhcp_option_block *options;
602
 	struct dhcp_option_block *options;
600
 	if ( dhcphdr->xid != dhcp->xid ) {
606
 	if ( dhcphdr->xid != dhcp->xid ) {
601
 		DBG ( "DHCP wrong transaction ID (wanted %08lx, got %08lx)\n",
607
 		DBG ( "DHCP wrong transaction ID (wanted %08lx, got %08lx)\n",
602
 		      ntohl ( dhcphdr->xid ), ntohl ( dhcp->xid ) );
608
 		      ntohl ( dhcphdr->xid ), ntohl ( dhcp->xid ) );
603
-		return;
609
+		return 0;
604
 	};
610
 	};
605
 
611
 
606
 	/* Parse packet and create options structure */
612
 	/* Parse packet and create options structure */
607
 	options = dhcp_parse ( dhcphdr, len );
613
 	options = dhcp_parse ( dhcphdr, len );
608
 	if ( ! options ) {
614
 	if ( ! options ) {
609
 		DBG ( "Could not parse DHCP packet\n" );
615
 		DBG ( "Could not parse DHCP packet\n" );
610
-		return;
616
+		return -EINVAL;
611
 	}
617
 	}
612
 
618
 
613
 	/* Determine message type */
619
 	/* Determine message type */
643
 	} else {
649
 	} else {
644
 		dhcp_done ( dhcp, 0 );
650
 		dhcp_done ( dhcp, 0 );
645
 	}
651
 	}
646
-	return;
652
+	return 0;
647
 
653
 
648
  out_discard:
654
  out_discard:
649
 	free_dhcp_options ( options );
655
 	free_dhcp_options ( options );
656
+	return 0;
650
 }
657
 }
651
 
658
 
652
 /** DHCP UDP operations */
659
 /** DHCP UDP operations */

Loading…
Cancel
Save