Selaa lähdekoodia

Partial migration of UDP to data-xfer interface. (Will not link at

present; DHCP is broken).
tags/v0.9.3
Michael Brown 17 vuotta sitten
vanhempi
commit
e381714c07
3 muutettua tiedostoa jossa 310 lisäystä ja 331 poistoa
  1. 12
    135
      src/include/gpxe/udp.h
  2. 7
    30
      src/interface/pxe/pxe_udp.c
  3. 291
    166
      src/net/udp.c

+ 12
- 135
src/include/gpxe/udp.h Näytä tiedosto

@@ -14,7 +14,8 @@
14 14
 #include <gpxe/tcpip.h>
15 15
 #include <gpxe/if_ether.h>
16 16
 
17
-struct net_device;
17
+struct xfer_interface;
18
+struct sockaddr;
18 19
 
19 20
 /**
20 21
  * UDP constants
@@ -24,147 +25,23 @@ struct net_device;
24 25
 #define UDP_MAX_TXIOB	ETH_MAX_MTU
25 26
 #define UDP_MIN_TXIOB	ETH_ZLEN
26 27
 
27
-typedef uint16_t port_t;
28
-
29 28
 /**
30 29
  * A UDP header
31 30
  */
32 31
 struct udp_header {
33
-	port_t source_port;
34
-	port_t dest_port;
32
+	/** Source port */
33
+	uint16_t src;
34
+	/** Destination port */
35
+	uint16_t dest;
36
+	/** Length */
35 37
 	uint16_t len;
38
+	/** Checksum */
36 39
 	uint16_t chksum;
37 40
 };
38 41
 
39
-struct udp_connection;
40
-
41
-/**
42
- * UDP operations
43
- *
44
- */
45
-struct udp_operations {
46
-	
47
-	/**
48
-	 * Transmit data
49
-	 *
50
-	 * @v conn	UDP connection
51
-	 * @v buf	Temporary data buffer
52
-	 * @v len	Length of temporary data buffer
53
-	 * @ret rc	Return status code
54
-	 *
55
-	 * The application may use the temporary data buffer to
56
-	 * construct the data to be sent.  Note that merely filling
57
-	 * the buffer will do nothing; the application must call
58
-	 * udp_send() in order to actually transmit the data.  Use of
59
-	 * the buffer is not compulsory; the application may call
60
-	 * udp_send() on any block of data.
61
-	 */
62
-	int ( * senddata ) ( struct udp_connection *conn, void *buf,
63
-			     size_t len );
64
-	/**
65
-	 * New data received
66
-	 *
67
-	 * @v conn	UDP connection
68
-	 * @v data	Data
69
-	 * @v len	Length of data
70
-	 * @v st_src	Source address
71
-	 * @v st_dest	Destination address
72
-	 * @ret rc	Return status code
73
-	 */
74
-	int ( * newdata ) ( struct udp_connection *conn, void *data,
75
-			    size_t len, struct sockaddr_tcpip *st_src,
76
-			    struct sockaddr_tcpip *st_dest );
77
-};
78
-
79
-/**
80
- * A UDP connection
81
- *
82
- */
83
-struct udp_connection {
84
-       /** Address of the remote end of the connection */
85
-	struct sockaddr_tcpip peer;
86
-	/** Local port on which the connection receives packets */
87
-	port_t local_port;
88
-	/** Transmit buffer */
89
-	struct io_buffer *tx_iob;
90
-	/** List of registered connections */
91
-	struct list_head list;
92
-	/** Operations table for this connection */
93
-	struct udp_operations *udp_op;
94
-};
95
-
96
-/*
97
- * Functions provided to the application layer
98
- */
99
-
100
-/**
101
- * Bind UDP connection to all local ports
102
- *
103
- * @v conn		UDP connection
104
- *
105
- * A promiscuous UDP connection will receive packets with any
106
- * destination UDP port.  This is required in order to support the PXE
107
- * UDP API.
108
- *
109
- * If the promiscuous connection is not the only UDP connection, the
110
- * behaviour is undefined.
111
- */
112
-static inline void udp_bind_promisc ( struct udp_connection *conn ) {
113
-	conn->local_port = 0;
114
-}
115
-
116
-/**
117
- * Connect UDP connection to remote host and port
118
- *
119
- * @v conn		UDP connection
120
- * @v peer		Destination socket address
121
- *
122
- * This function sets the default address for transmitted packets,
123
- * i.e. the address used when udp_send() is called rather than
124
- * udp_sendto().
125
- */
126
-static inline void udp_connect ( struct udp_connection *conn,
127
-				 struct sockaddr_tcpip *peer ) {
128
-	memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
129
-}
130
-
131
-/**
132
- * Connect UDP connection to remote port
133
- *
134
- * @v conn		UDP connection
135
- * @v port		Destination port
136
- *
137
- * This function sets only the port part of the default address for
138
- * transmitted packets.
139
- */
140
-static inline void udp_connect_port ( struct udp_connection *conn,
141
-				      uint16_t port ) {
142
-	conn->peer.st_port = port;
143
-}
144
-
145
-/**
146
- * Get default address for transmitted packets
147
- *
148
- * @v conn		UDP connection
149
- * @ret peer		Default destination socket address
150
- */
151
-static inline struct sockaddr_tcpip *
152
-udp_peer ( struct udp_connection *conn ) {
153
-	return &conn->peer;
154
-}
155
-
156
-extern int udp_bind ( struct udp_connection *conn, uint16_t local_port );
157
-extern int udp_open ( struct udp_connection *conn, uint16_t local_port );
158
-extern void udp_close ( struct udp_connection *conn );
159
-
160
-extern int udp_senddata ( struct udp_connection *conn );
161
-extern int udp_send ( struct udp_connection *conn,
162
-		      const void *data, size_t len );
163
-extern int udp_sendto ( struct udp_connection *conn,
164
-			struct sockaddr_tcpip *peer,
165
-			const void *data, size_t len );
166
-int udp_sendto_via ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
167
-		     struct net_device *netdev, const void *data,
168
-		     size_t len );
42
+extern int udp_open_promisc ( struct xfer_interface *xfer );
43
+extern int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
44
+		      struct sockaddr *local );
169 45
 
170 46
 #endif /* _GPXE_UDP_H */
47
+

+ 7
- 30
src/interface/pxe/pxe_udp.c Näytä tiedosto

@@ -34,8 +34,6 @@
34 34
 struct pxe_udp_connection {
35 35
 	/** Data transfer interface to UDP stack */
36 36
 	struct xfer_interface xfer;
37
-	/** "Connection is open" flag */
38
-	int open;
39 37
 	/** Local address */
40 38
 	struct sockaddr_in local;
41 39
 	/** Current PXENV_UDP_READ parameter block */
@@ -169,21 +167,19 @@ static struct pxe_udp_connection pxe_udp = {
169 167
  *
170 168
  */
171 169
 PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
170
+	int rc;
172 171
 
173 172
 	DBG ( "PXENV_UDP_OPEN" );
174 173
 
175
-	/* Check connection is not already open */
176
-	if ( pxe_udp.open ) {
177
-		pxenv_udp_open->Status = PXENV_STATUS_UDP_OPEN;
178
-		return PXENV_EXIT_FAILURE;
179
-	}
180
-
181 174
 	/* Record source IP address */
182 175
 	pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
183 176
 
184 177
 	/* Open promiscuous UDP connection */
185
-	udp_open_promisc ( &pxe_udp.xfer );
186
-	pxe_udp.open = 1;
178
+	xfer_close ( &pxe_udp.xfer, 0 );
179
+	if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
180
+		pxenv_udp_open->Status = PXENV_STATUS ( rc );
181
+		return PXENV_EXIT_FAILURE;
182
+	}
187 183
 
188 184
 	pxenv_udp_open->Status = PXENV_STATUS_SUCCESS;
189 185
 	return PXENV_EXIT_SUCCESS;
@@ -213,15 +209,8 @@ PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
213 209
 PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
214 210
 	DBG ( "PXENV_UDP_CLOSE" );
215 211
 
216
-	/* Check connection is open */
217
-	if ( ! pxe_udp.open ) {
218
-		pxenv_udp_close->Status = PXENV_STATUS_UDP_CLOSED;
219
-		return PXENV_EXIT_SUCCESS; /* Well, it *is* closed */
220
-	}
221
-
222 212
 	/* Close UDP connection */
223
-	udp_close_promisc ( &pxe_udp.xfer );
224
-	pxe_udp.open = 0;
213
+	xfer_close ( &pxe_udp.xfer, 0 );
225 214
 
226 215
 	pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
227 216
 	return PXENV_EXIT_SUCCESS;
@@ -281,12 +270,6 @@ PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
281 270
 
282 271
 	DBG ( "PXENV_UDP_WRITE" );
283 272
 
284
-	/* Check connection is open */
285
-	if ( ! pxe_udp.open ) {
286
-		pxenv_udp_write->Status = PXENV_STATUS_UDP_CLOSED;
287
-		return PXENV_EXIT_FAILURE;
288
-	}
289
-
290 273
 	/* Construct destination socket address */
291 274
 	memset ( &dest, 0, sizeof ( dest ) );
292 275
 	dest.sin_family = AF_INET;
@@ -383,12 +366,6 @@ PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
383 366
 
384 367
 	DBG ( "PXENV_UDP_READ" );
385 368
 
386
-	/* Check connection is open */
387
-	if ( ! pxe_udp.open ) {
388
-		pxenv_udp_read->Status = PXENV_STATUS_UDP_CLOSED;
389
-		return PXENV_EXIT_FAILURE;
390
-	}
391
-
392 369
 	/* Try receiving a packet */
393 370
 	pxe_udp.pxenv_udp_read = pxenv_udp_read;
394 371
 	step();

+ 291
- 166
src/net/udp.c Näytä tiedosto

@@ -1,11 +1,14 @@
1 1
 #include <stdint.h>
2
+#include <stdlib.h>
2 3
 #include <string.h>
3 4
 #include <assert.h>
4 5
 #include <byteswap.h>
5 6
 #include <errno.h>
6 7
 #include <gpxe/tcpip.h>
7 8
 #include <gpxe/iobuf.h>
8
-#include <gpxe/netdevice.h>
9
+#include <gpxe/xfer.h>
10
+#include <gpxe/open.h>
11
+#include <gpxe/uri.h>
9 12
 #include <gpxe/udp.h>
10 13
 
11 14
 /** @file
@@ -13,233 +16,234 @@
13 16
  * UDP protocol
14 17
  */
15 18
 
16
-struct tcpip_protocol udp_protocol;
17
-
18 19
 /**
19
- * List of registered UDP connections
20
+ * A UDP connection
21
+ *
20 22
  */
21
-static LIST_HEAD ( udp_conns );
23
+struct udp_connection {
24
+	/** Reference counter */
25
+	struct refcnt refcnt;
26
+	/** List of UDP connections */
27
+	struct list_head list;
28
+
29
+	/** Data transfer interface */
30
+	struct xfer_interface xfer;
31
+
32
+	/** Remote socket address */
33
+	struct sockaddr_tcpip peer;
34
+	/** Local port on which the connection receives packets */
35
+	unsigned int local_port;
36
+};
22 37
 
23 38
 /**
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
39
+ * List of registered UDP connections
29 40
  */
30
-int udp_bind ( struct udp_connection *conn, uint16_t local_port ) {
31
-	struct udp_connection *existing;
41
+static LIST_HEAD ( udp_conns );
32 42
 
33
-	list_for_each_entry ( existing, &udp_conns, list ) {
34
-		if ( existing->local_port == local_port )
35
-			return -EADDRINUSE;
36
-	}
37
-	conn->local_port = local_port;
38
-	return 0;
39
-}
43
+/* Forward declatations */
44
+static struct xfer_interface_operations udp_xfer_operations;
45
+struct tcpip_protocol udp_protocol;
40 46
 
41 47
 /**
42
- * Open a local port
48
+ * Bind UDP connection to local port
43 49
  *
44
- * @v conn		UDP connection
45
- * @v local_port	Local port, in network byte order, or zero
50
+ * @v udp		UDP connection
51
+ * @v port		Local port, in network byte order, or zero
46 52
  * @ret rc		Return status code
47 53
  *
48 54
  * Opens the UDP connection and binds to a local port.  If no local
49 55
  * port is specified, the first available port will be used.
50 56
  */
51
-int udp_open ( struct udp_connection *conn, uint16_t local_port ) {
57
+static int udp_bind ( struct udp_connection *udp, unsigned int port ) {
58
+	struct udp_connection *existing;
52 59
 	static uint16_t try_port = 1024;
53
-	int rc;
54 60
 
55 61
 	/* If no port specified, find the first available port */
56
-	if ( ! local_port ) {
62
+	if ( ! port ) {
57 63
 		for ( ; try_port ; try_port++ ) {
58 64
 			if ( try_port < 1024 )
59 65
 				continue;
60
-			if ( udp_open ( conn, htons ( try_port ) ) == 0 )
66
+			if ( udp_bind ( udp, htons ( try_port ) ) == 0 )
61 67
 				return 0;
62 68
 		}
63 69
 		return -EADDRINUSE;
64 70
 	}
65 71
 
66 72
 	/* Attempt bind to local port */
67
-	if ( ( rc = udp_bind ( conn, local_port ) ) != 0 ) {
68
-		DBGC ( conn, "UDP %p could not bind to local port %d: %s\n",
69
-		       conn, local_port, strerror ( rc ) );
70
-		return rc;
73
+	list_for_each_entry ( existing, &udp_conns, list ) {
74
+		if ( existing->local_port == port ) {
75
+			DBGC ( udp, "UDP %p could not bind: port %d in use\n",
76
+			       udp, ntohs ( port ) );
77
+			return -EADDRINUSE;
78
+		}
71 79
 	}
80
+	udp->local_port = port;
72 81
 
73 82
 	/* Add to UDP connection list */
74
-	list_add ( &conn->list, &udp_conns );
75
-	DBGC ( conn, "UDP %p opened on port %d\n", conn,
76
-	       ntohs ( local_port ) );
83
+	DBGC ( udp, "UDP %p bound to port %d\n", udp, ntohs ( port ) );
77 84
 
78 85
 	return 0;
79 86
 }
80 87
 
81 88
 /**
82
- * Close a UDP connection
89
+ * Open a UDP connection
83 90
  *
84
- * @v conn		UDP connection
91
+ * @v xfer		Data transfer interface
92
+ * @v peer		Peer socket address
93
+ * @v local		Local socket address, or NULL
94
+ * @v promisc		Socket is promiscuous
95
+ * @ret rc		Return status code
85 96
  */
86
-void udp_close ( struct udp_connection *conn ) {
87
-	list_del ( &conn->list );
88
-	DBGC ( conn, "UDP %p closed\n", conn );
97
+static int udp_open_common ( struct xfer_interface *xfer,
98
+			     struct sockaddr *peer, struct sockaddr *local,
99
+			     int promisc ) {
100
+	struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
101
+	struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
102
+	struct udp_connection *udp;
103
+	unsigned int bind_port;
104
+	int rc;
105
+
106
+	/* Allocate and initialise structure */
107
+	udp = malloc ( sizeof ( *udp ) );
108
+	if ( ! udp )
109
+		return -ENOMEM;
110
+	DBGC ( udp, "UDP %p allocated\n", udp );
111
+	memset ( udp, 0, sizeof ( *udp ) );
112
+	xfer_init ( &udp->xfer, &udp_xfer_operations, &udp->refcnt );
113
+	memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
114
+
115
+	/* Bind to local port */
116
+	if ( ! promisc ) {
117
+		bind_port = ( st_local ? st_local->st_port : 0 );
118
+		if ( ( rc = udp_bind ( udp, bind_port ) ) != 0 )
119
+			goto err;
120
+	}
121
+
122
+	/* Attach parent interface, transfer reference to connection
123
+	 * list and return
124
+	 */
125
+	xfer_plug_plug ( &udp->xfer, xfer );
126
+	list_add ( &udp->list, &udp_conns );
127
+	return 0;
128
+
129
+ err:
130
+	ref_put ( &udp->refcnt );
131
+	return rc;
89 132
 }
90 133
 
91 134
 /**
92
- * Allocate I/O buffer for UDP
135
+ * Open a UDP connection
93 136
  *
94
- * @v conn		UDP connection
95
- * @ret iobuf		I/O buffer, or NULL
137
+ * @v xfer		Data transfer interface
138
+ * @v peer		Peer socket address
139
+ * @v local		Local socket address, or NULL
140
+ * @ret rc		Return status code
96 141
  */
97
-static struct io_buffer * udp_alloc_iob ( struct udp_connection *conn ) {
98
-	struct io_buffer *iobuf;
99
-
100
-	iobuf = alloc_iob ( UDP_MAX_TXIOB );
101
-	if ( ! iobuf ) {
102
-		DBGC ( conn, "UDP %p cannot allocate buffer of length %d\n",
103
-		       conn, UDP_MAX_TXIOB );
104
-		return NULL;
105
-	}
106
-	iob_reserve ( iobuf, UDP_MAX_HLEN );
107
-	return iobuf;
142
+int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
143
+		      struct sockaddr *local ) {
144
+	return udp_open_common ( xfer, peer, local, 0 );
108 145
 }
109 146
 
110 147
 /**
111
- * User request to send data via a UDP connection
148
+ * Open a promiscuous UDP connection
112 149
  *
113
- * @v conn		UDP connection
150
+ * @v xfer		Data transfer interface
151
+ * @ret rc		Return status code
114 152
  *
115
- * This function allocates buffer space and invokes the function's
116
- * senddata() callback.  The callback may use the buffer space as
117
- * temporary storage space.
153
+ * Promiscuous UDP connections are required in order to support the
154
+ * PXE API.
118 155
  */
119
-int udp_senddata ( struct udp_connection *conn ) {
120
-	int rc;
156
+int udp_open_promisc ( struct xfer_interface *xfer ) {
157
+	return udp_open_common ( xfer, NULL, NULL, 1 );
158
+}
121 159
 
122
-	conn->tx_iob = udp_alloc_iob ( conn );
123
-	if ( ! conn->tx_iob )
124
-		return -ENOMEM;
160
+/**
161
+ * Close a UDP connection
162
+ *
163
+ * @v udp		UDP connection
164
+ * @v rc		Reason for close
165
+ */
166
+static void udp_close ( struct udp_connection *udp, int rc ) {
125 167
 
126
-	rc = conn->udp_op->senddata ( conn, conn->tx_iob->data, 
127
-				      iob_tailroom ( conn->tx_iob ) );
128
-	if ( rc != 0 ) {
129
-		DBGC ( conn, "UDP %p application could not send packet: %s\n",
130
-		       conn, strerror ( rc ) );
131
-	}
168
+	/* Close data transfer interface */
169
+	xfer_nullify ( &udp->xfer );
170
+	xfer_close ( &udp->xfer, rc );
132 171
 
133
-	if ( conn->tx_iob ) {
134
-		free_iob ( conn->tx_iob );
135
-		conn->tx_iob = NULL;
136
-	}
172
+	/* Remove from list of connections and drop list's reference */
173
+	list_del ( &udp->list );
174
+	ref_put ( &udp->refcnt );
137 175
 
138
-	return rc;
176
+	DBGC ( udp, "UDP %p closed\n", udp );
139 177
 }
140
-		
178
+
141 179
 /**
142 180
  * Transmit data via a UDP connection to a specified address
143 181
  *
144
- * @v conn		UDP connection
145
- * @v peer		Destination address
146
- * @v netdev		Network device to use if no route found, or NULL
147
- * @v data		Data to send
148
- * @v len		Length of data
182
+ * @v udp		UDP connection
183
+ * @v iobuf		I/O buffer
184
+ * @v src_port		Source port, or 0 to use default
185
+ * @v dest		Destination address, or NULL to use default
149 186
  * @ret rc		Return status code
150 187
  */
151
-int udp_sendto_via ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
152
-		     struct net_device *netdev, const void *data,
153
-		     size_t len ) {
188
+static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
189
+		    unsigned int src_port, struct sockaddr_tcpip *dest ) {
154 190
        	struct udp_header *udphdr;
155
-	struct io_buffer *iobuf;
191
+	struct net_device *netdev = NULL;
192
+	size_t len;
156 193
 	int rc;
157 194
 
158
-	/* Use precreated I/O buffer if one is available */
159
-	if ( conn->tx_iob ) {
160
-		iobuf = conn->tx_iob;
161
-		conn->tx_iob = NULL;
162
-	} else {
163
-		iobuf = udp_alloc_iob ( conn );
164
-		if ( ! iobuf )
165
-			return -ENOMEM;
166
-	}
195
+#warning "netdev?"
167 196
 
168
-	/* Avoid overflowing TX buffer */
169
-	if ( len > iob_tailroom ( iobuf ) )
170
-		len = iob_tailroom ( iobuf );
197
+	/* Check we can accommodate the header */
198
+	if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
199
+		free_iob ( iobuf );
200
+		return rc;
201
+	}
171 202
 
172
-	/* Copy payload */
173
-	memmove ( iob_put ( iobuf, len ), data, len );
203
+	/* Fill in default values if not explicitly provided */
204
+	if ( ! src_port )
205
+		src_port = udp->local_port;
206
+	if ( ! dest )
207
+		dest = &udp->peer;
174 208
 
175
-	/*
176
-	 * Add the UDP header
177
-	 *
178
-	 * Covert all 16- and 32- bit integers into network btye order before
179
-	 * sending it over the network
180
-	 */
209
+	/* Add the UDP header */
181 210
 	udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
182
-	udphdr->dest_port = peer->st_port;
183
-	udphdr->source_port = conn->local_port;
184
-	udphdr->len = htons ( iob_len ( iobuf ) );
211
+	len = iob_len ( iobuf );
212
+	udphdr->dest = dest->st_port;
213
+	udphdr->src = src_port;
214
+	udphdr->len = htons ( len );
185 215
 	udphdr->chksum = 0;
186
-	udphdr->chksum = tcpip_chksum ( udphdr, sizeof ( *udphdr ) + len );
216
+	udphdr->chksum = tcpip_chksum ( udphdr, len );
187 217
 
188 218
 	/* Dump debugging information */
189
-	DBGC ( conn, "UDP %p TX %d->%d len %zd\n", conn,
190
-	       ntohs ( udphdr->source_port ), ntohs ( udphdr->dest_port ),
219
+	DBGC ( udp, "UDP %p TX %d->%d len %zd\n", udp,
220
+	       ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
191 221
 	       ntohs ( udphdr->len ) );
192 222
 
193 223
 	/* Send it to the next layer for processing */
194
-	if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, peer, netdev,
224
+	if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, dest, netdev,
195 225
 			       &udphdr->chksum ) ) != 0 ) {
196
-		DBGC ( conn, "UDP %p could not transmit packet: %s\n",
197
-		       conn, strerror ( rc ) );
226
+		DBGC ( udp, "UDP %p could not transmit packet: %s\n",
227
+		       udp, strerror ( rc ) );
198 228
 		return rc;
199 229
 	}
200 230
 
201 231
 	return 0;
202 232
 }
203 233
 
204
-/**
205
- * Transmit data via a UDP connection to a specified address
206
- *
207
- * @v conn		UDP connection
208
- * @v peer		Destination address
209
- * @v data		Data to send
210
- * @v len		Length of data
211
- * @ret rc		Return status code
212
- */
213
-int udp_sendto ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
214
-		 const void *data, size_t len ) {
215
-	return udp_sendto_via ( conn, peer, NULL, data, len );
216
-}
217
-
218
-/**
219
- * Transmit data via a UDP connection
220
- *
221
- * @v conn		UDP connection
222
- * @v data		Data to send
223
- * @v len		Length of data
224
- * @ret rc		Return status code
225
- */
226
-int udp_send ( struct udp_connection *conn, const void *data, size_t len ) {
227
-	return udp_sendto ( conn, &conn->peer, data, len );
228
-}
229
-
230 234
 /**
231 235
  * Identify UDP connection by local port number
232 236
  *
233 237
  * @v local_port	Local port (in network-endian order)
234
- * @ret conn		TCP connection, or NULL
238
+ * @ret udp		UDP connection, or NULL
235 239
  */
236
-static struct udp_connection * udp_demux ( uint16_t local_port ) {
237
-	struct udp_connection *conn;
240
+static struct udp_connection * udp_demux ( unsigned int local_port ) {
241
+	struct udp_connection *udp;
238 242
 
239
-	list_for_each_entry ( conn, &udp_conns, list ) {
240
-		if ( ( conn->local_port == local_port ) ||
241
-		     ( conn->local_port == 0 ) ) {
242
-			return conn;
243
+	list_for_each_entry ( udp, &udp_conns, list ) {
244
+		if ( ( udp->local_port == local_port ) ||
245
+		     ( udp->local_port == 0 ) ) {
246
+			return udp;
243 247
 		}
244 248
 	}
245 249
 	return NULL;
@@ -257,9 +261,10 @@ static struct udp_connection * udp_demux ( uint16_t local_port ) {
257 261
 static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
258 262
 		    struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
259 263
 	struct udp_header *udphdr = iobuf->data;
260
-	struct udp_connection *conn;
264
+	struct udp_connection *udp;
265
+	struct xfer_metadata meta;
261 266
 	size_t ulen;
262
-	uint16_t csum;
267
+	unsigned int csum;
263 268
 	int rc = 0;
264 269
 
265 270
 	/* Sanity check packet */
@@ -294,37 +299,30 @@ static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
294 299
 	}
295 300
 
296 301
 	/* Parse parameters from header and strip header */
297
-	st_src->st_port = udphdr->source_port;
298
-	st_dest->st_port = udphdr->dest_port;
299
-	conn = udp_demux ( udphdr->dest_port );
302
+	st_src->st_port = udphdr->src;
303
+	st_dest->st_port = udphdr->dest;
304
+	udp = udp_demux ( udphdr->dest );
300 305
 	iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
301 306
 	iob_pull ( iobuf, sizeof ( *udphdr ) );
302 307
 
303 308
 	/* Dump debugging information */
304
-	DBGC ( conn, "UDP %p RX %d<-%d len %zd\n", conn,
305
-	       ntohs ( udphdr->dest_port ), ntohs ( udphdr->source_port ),
306
-	       ulen );
309
+	DBGC ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
310
+	       ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
307 311
 
308 312
 	/* Ignore if no matching connection found */
309
-	if ( ! conn ) {
313
+	if ( ! udp ) {
310 314
 		DBG ( "No UDP connection listening on port %d\n",
311
-		      ntohs ( udphdr->dest_port ) );
315
+		      ntohs ( udphdr->dest ) );
312 316
 		rc = -ENOTCONN;
313 317
 		goto done;
314 318
 	}
315 319
 
316 320
 	/* Pass data to application */
317
-	if ( conn->udp_op->newdata ) {
318
-		rc = conn->udp_op->newdata ( conn, iobuf->data, iob_len ( iobuf ),
319
-				     st_src, st_dest );
320
-		if ( rc != 0 ) {
321
-			DBGC ( conn, "UDP %p application rejected packet: %s\n",
322
-			       conn, strerror ( rc ) );
323
-		}
324
-	} else {
325
-		DBGC ( conn, "UDP %p application has no newdata handler for " \
326
-			"incoming packet\n", conn );
327
-	}
321
+	memset ( &meta, 0, sizeof ( meta ) );
322
+	meta.src = ( struct sockaddr * ) st_src;
323
+	meta.dest = ( struct sockaddr * ) st_dest;
324
+	rc = xfer_deliver_iob_meta ( &udp->xfer, iobuf, &meta );
325
+	iobuf = NULL;
328 326
 
329 327
  done:
330 328
 	free_iob ( iobuf );
@@ -336,3 +334,130 @@ struct tcpip_protocol udp_protocol __tcpip_protocol = {
336 334
 	.rx = udp_rx,
337 335
 	.tcpip_proto = IP_UDP,
338 336
 };
337
+
338
+/***************************************************************************
339
+ *
340
+ * Data transfer interface
341
+ *
342
+ ***************************************************************************
343
+ */
344
+
345
+/**
346
+ * Close interface
347
+ *
348
+ * @v xfer		Data transfer interface
349
+ * @v rc		Reason for close
350
+ */
351
+static void udp_xfer_close ( struct xfer_interface *xfer, int rc ) {
352
+	struct udp_connection *udp =
353
+		container_of ( xfer, struct udp_connection, xfer );
354
+
355
+	/* Close connection */
356
+	udp_close ( udp, rc );
357
+}
358
+
359
+/**
360
+ * Allocate I/O buffer for UDP
361
+ *
362
+ * @v xfer		Data transfer interface
363
+ * @v len		Payload size
364
+ * @ret iobuf		I/O buffer, or NULL
365
+ */
366
+static struct io_buffer * udp_alloc_iob ( struct xfer_interface *xfer,
367
+					  size_t len ) {
368
+	struct udp_connection *udp =
369
+		container_of ( xfer, struct udp_connection, xfer );	
370
+	struct io_buffer *iobuf;
371
+
372
+	iobuf = alloc_iob ( UDP_MAX_HLEN + len );
373
+	if ( ! iobuf ) {
374
+		DBGC ( udp, "UDP %p cannot allocate buffer of length %d\n",
375
+		       udp, len );
376
+		return NULL;
377
+	}
378
+	iob_reserve ( iobuf, UDP_MAX_HLEN );
379
+	return iobuf;
380
+}
381
+
382
+/**
383
+ * Deliver datagram as I/O buffer
384
+ *
385
+ * @v xfer		Data transfer interface
386
+ * @v iobuf		Datagram I/O buffer
387
+ * @v meta		Data transfer metadata, or NULL
388
+ * @ret rc		Return status code
389
+ */
390
+static int udp_xfer_deliver_iob ( struct xfer_interface *xfer,
391
+				  struct io_buffer *iobuf,
392
+				  struct xfer_metadata *meta ) {
393
+	struct udp_connection *udp =
394
+		container_of ( xfer, struct udp_connection, xfer );
395
+	struct sockaddr_tcpip *src;
396
+	struct sockaddr_tcpip *dest = NULL;
397
+	unsigned int src_port = 0;
398
+
399
+	/* Apply xfer metadata */
400
+	if ( meta ) {
401
+		src = ( struct sockaddr_tcpip * ) meta->src;
402
+		if ( src )
403
+			src_port = src->st_port;
404
+		dest = ( struct sockaddr_tcpip * ) meta->dest;
405
+	}
406
+
407
+	/* Transmit data, if possible */
408
+	udp_tx ( udp, iobuf, src_port, dest );
409
+
410
+	return 0;
411
+}
412
+
413
+/** UDP data transfer interface operations */
414
+static struct xfer_interface_operations udp_xfer_operations = {
415
+	.close		= udp_xfer_close,
416
+	.vredirect	= ignore_xfer_vredirect,
417
+	.request	= ignore_xfer_request,
418
+	.seek		= ignore_xfer_seek,
419
+	.alloc_iob	= udp_alloc_iob,
420
+	.deliver_iob	= udp_xfer_deliver_iob,
421
+	.deliver_raw	= xfer_deliver_as_iob,
422
+};
423
+
424
+/***************************************************************************
425
+ *
426
+ * Openers
427
+ *
428
+ ***************************************************************************
429
+ */
430
+
431
+/** UDP socket opener */
432
+struct socket_opener udp_socket_opener __socket_opener = {
433
+	.semantics	= SOCK_DGRAM,
434
+	.family		= AF_INET,
435
+	.open		= udp_open,
436
+};
437
+
438
+/**
439
+ * Open UDP URI
440
+ *
441
+ * @v xfer		Data transfer interface
442
+ * @v uri		URI
443
+ * @ret rc		Return status code
444
+ */
445
+static int udp_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
446
+	struct sockaddr_tcpip peer;
447
+
448
+	/* Sanity check */
449
+	if ( ! uri->host )
450
+		return -EINVAL;
451
+
452
+	memset ( &peer, 0, sizeof ( peer ) );
453
+	peer.st_port = htons ( uri_port ( uri, 0 ) );
454
+	return xfer_open_named_socket ( xfer, SOCK_DGRAM,
455
+					( struct sockaddr * ) &peer,
456
+					uri->host, NULL );
457
+}
458
+
459
+/** UDP URI opener */
460
+struct uri_opener udp_uri_opener __uri_opener = {
461
+	.scheme		= "udp",
462
+	.open		= udp_open_uri,
463
+};

Loading…
Peruuta
Tallenna