|
@@ -93,6 +93,8 @@ void udp_close ( struct udp_connection *conn ) {
|
93
|
93
|
* callback. The callback may use the buffer space
|
94
|
94
|
*/
|
95
|
95
|
int udp_senddata ( struct udp_connection *conn ) {
|
|
96
|
+ int rc;
|
|
97
|
+
|
96
|
98
|
conn->tx_pkb = alloc_pkb ( UDP_MAX_TXPKB );
|
97
|
99
|
if ( conn->tx_pkb == NULL ) {
|
98
|
100
|
DBG ( "UDP %p cannot allocate packet buffer of length %d\n",
|
|
@@ -100,8 +102,11 @@ int udp_senddata ( struct udp_connection *conn ) {
|
100
|
102
|
return -ENOMEM;
|
101
|
103
|
}
|
102
|
104
|
pkb_reserve ( conn->tx_pkb, UDP_MAX_HLEN );
|
103
|
|
- return conn->udp_op->senddata ( conn, conn->tx_pkb->data,
|
104
|
|
- pkb_available ( conn->tx_pkb ) );
|
|
105
|
+ rc = conn->udp_op->senddata ( conn, conn->tx_pkb->data,
|
|
106
|
+ pkb_available ( conn->tx_pkb ) );
|
|
107
|
+ if ( conn->tx_pkb )
|
|
108
|
+ free_pkb ( conn->tx_pkb );
|
|
109
|
+ return rc;
|
105
|
110
|
}
|
106
|
111
|
|
107
|
112
|
/**
|
|
@@ -122,13 +127,20 @@ int udp_senddata ( struct udp_connection *conn ) {
|
122
|
127
|
int udp_sendto ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
|
123
|
128
|
const void *data, size_t len ) {
|
124
|
129
|
struct udp_header *udphdr;
|
|
130
|
+ struct pk_buff *pkb;
|
|
131
|
+
|
|
132
|
+ /* Take ownership of packet buffer back from the
|
|
133
|
+ * udp_connection structure.
|
|
134
|
+ */
|
|
135
|
+ pkb = conn->tx_pkb;
|
|
136
|
+ conn->tx_pkb = NULL;
|
125
|
137
|
|
126
|
138
|
/* Avoid overflowing TX buffer */
|
127
|
|
- if ( len > pkb_available ( conn->tx_pkb ) )
|
128
|
|
- len = pkb_available ( conn->tx_pkb );
|
|
139
|
+ if ( len > pkb_available ( pkb ) )
|
|
140
|
+ len = pkb_available ( pkb );
|
129
|
141
|
|
130
|
142
|
/* Copy payload */
|
131
|
|
- memmove ( pkb_put ( conn->tx_pkb, len ), data, len );
|
|
143
|
+ memmove ( pkb_put ( pkb, len ), data, len );
|
132
|
144
|
|
133
|
145
|
/*
|
134
|
146
|
* Add the UDP header
|
|
@@ -136,22 +148,22 @@ int udp_sendto ( struct udp_connection *conn, struct sockaddr_tcpip *peer,
|
136
|
148
|
* Covert all 16- and 32- bit integers into network btye order before
|
137
|
149
|
* sending it over the network
|
138
|
150
|
*/
|
139
|
|
- udphdr = pkb_push ( conn->tx_pkb, sizeof ( *udphdr ) );
|
|
151
|
+ udphdr = pkb_push ( pkb, sizeof ( *udphdr ) );
|
140
|
152
|
udphdr->dest_port = peer->st_port;
|
141
|
153
|
udphdr->source_port = conn->local_port;
|
142
|
|
- udphdr->len = htons ( pkb_len ( conn->tx_pkb ) );
|
|
154
|
+ udphdr->len = htons ( pkb_len ( pkb ) );
|
143
|
155
|
udphdr->chksum = 0;
|
144
|
156
|
udphdr->chksum = tcpip_chksum ( udphdr, sizeof ( *udphdr ) + len );
|
145
|
157
|
|
146
|
158
|
/* Dump debugging information */
|
147
|
159
|
DBG ( "UDP %p transmitting %p+%#zx len %#x src %d dest %d "
|
148
|
|
- "chksum %#04x\n", conn, conn->tx_pkb->data,
|
149
|
|
- pkb_len ( conn->tx_pkb ), ntohs ( udphdr->len ),
|
|
160
|
+ "chksum %#04x\n", conn, pkb->data,
|
|
161
|
+ pkb_len ( pkb ), ntohs ( udphdr->len ),
|
150
|
162
|
ntohs ( udphdr->source_port ), ntohs ( udphdr->dest_port ),
|
151
|
163
|
ntohs ( udphdr->chksum ) );
|
152
|
164
|
|
153
|
165
|
/* Send it to the next layer for processing */
|
154
|
|
- return tcpip_tx ( conn->tx_pkb, &udp_protocol, peer );
|
|
166
|
+ return tcpip_tx ( pkb, &udp_protocol, peer );
|
155
|
167
|
}
|
156
|
168
|
|
157
|
169
|
/**
|
|
@@ -186,12 +198,14 @@ static int udp_rx ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
|
186
|
198
|
struct udp_connection *conn;
|
187
|
199
|
unsigned int ulen;
|
188
|
200
|
uint16_t chksum;
|
|
201
|
+ int rc;
|
189
|
202
|
|
190
|
203
|
/* Sanity check */
|
191
|
204
|
if ( pkb_len ( pkb ) < sizeof ( *udphdr ) ) {
|
192
|
205
|
DBG ( "UDP received underlength packet %p+%#zx\n",
|
193
|
206
|
pkb->data, pkb_len ( pkb ) );
|
194
|
|
- return -EINVAL;
|
|
207
|
+ rc = -EINVAL;
|
|
208
|
+ goto done;
|
195
|
209
|
}
|
196
|
210
|
|
197
|
211
|
/* Dump debugging information */
|
|
@@ -205,7 +219,8 @@ static int udp_rx ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
|
205
|
219
|
if ( ulen > pkb_len ( pkb ) ) {
|
206
|
220
|
DBG ( "UDP received truncated packet %p+%#zx\n",
|
207
|
221
|
pkb->data, pkb_len ( pkb ) );
|
208
|
|
- return -EINVAL;
|
|
222
|
+ rc = -EINVAL;
|
|
223
|
+ goto done;
|
209
|
224
|
}
|
210
|
225
|
pkb_unput ( pkb, ( pkb_len ( pkb ) - ulen ) );
|
211
|
226
|
|
|
@@ -215,7 +230,8 @@ static int udp_rx ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
|
215
|
230
|
chksum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
|
216
|
231
|
if ( chksum != 0xffff ) {
|
217
|
232
|
DBG ( "Bad checksum %#x\n", chksum );
|
218
|
|
- return -EINVAL;
|
|
233
|
+ rc = -EINVAL;
|
|
234
|
+ goto done;
|
219
|
235
|
}
|
220
|
236
|
#endif
|
221
|
237
|
|
|
@@ -237,13 +253,18 @@ static int udp_rx ( struct pk_buff *pkb, struct sockaddr_tcpip *st_src,
|
237
|
253
|
DBG ( "UDP delivering to %p\n", conn );
|
238
|
254
|
|
239
|
255
|
/* Call the application's callback */
|
240
|
|
- return conn->udp_op->newdata ( conn, pkb->data, pkb_len( pkb ),
|
241
|
|
- st_src, st_dest );
|
|
256
|
+ rc = conn->udp_op->newdata ( conn, pkb->data, pkb_len( pkb ),
|
|
257
|
+ st_src, st_dest );
|
|
258
|
+ goto done;
|
242
|
259
|
}
|
243
|
260
|
|
244
|
261
|
DBG ( "No UDP connection listening on port %d\n",
|
245
|
262
|
ntohs ( udphdr->dest_port ) );
|
246
|
|
- return 0;
|
|
263
|
+ rc = 0;
|
|
264
|
+
|
|
265
|
+ done:
|
|
266
|
+ free_pkb ( pkb );
|
|
267
|
+ return rc;
|
247
|
268
|
}
|
248
|
269
|
|
249
|
270
|
struct tcpip_protocol udp_protocol = {
|