|
@@ -104,22 +104,22 @@ void del_ipv4_address ( struct net_device *netdev ) {
|
104
|
104
|
*/
|
105
|
105
|
void ipv4_tx_csum ( struct pk_buff *pkb, uint8_t trans_proto ) {
|
106
|
106
|
|
107
|
|
- struct iphdr *iphdr = pkb->data;
|
108
|
|
- void *pshdr = malloc ( IP_PSHLEN );
|
109
|
|
- void *csum_offset = iphdr + IP_HLEN + ( trans_proto == IP_UDP ? 6 : 16 );
|
110
|
|
- int offset = 0;
|
111
|
|
-
|
112
|
|
- /* Calculate pseudo header */
|
113
|
|
- memcpy ( pshdr, &iphdr->src, sizeof ( in_addr ) );
|
114
|
|
- offset += sizeof ( in_addr );
|
115
|
|
- memcpy ( pshdr + offset, &iphdr->dest, sizeof ( in_addr ) );
|
116
|
|
- offset += sizeof ( in_addr );
|
117
|
|
- *( ( uint8_t* ) ( pshdr + offset++ ) ) = 0x00;
|
118
|
|
- *( ( uint8_t* ) ( pshdr + offset++ ) ) = iphdr->protocol;
|
119
|
|
- *( ( uint16_t* ) ( pshdr + offset ) ) = pkb_len ( pkb ) - IP_HLEN;
|
|
107
|
+ struct iphdr *iphdr = pkb->data;
|
|
108
|
+ void *pshdr = malloc ( IP_PSHLEN );
|
|
109
|
+ void *csum_offset = iphdr + IP_HLEN + ( trans_proto == IP_UDP ? 6 : 16 );
|
|
110
|
+ int offset = 0;
|
|
111
|
+
|
|
112
|
+ /* Calculate pseudo header */
|
|
113
|
+ memcpy ( pshdr, &iphdr->src, sizeof ( in_addr ) );
|
|
114
|
+ offset += sizeof ( in_addr );
|
|
115
|
+ memcpy ( pshdr + offset, &iphdr->dest, sizeof ( in_addr ) );
|
|
116
|
+ offset += sizeof ( in_addr );
|
|
117
|
+ *( ( uint8_t* ) ( pshdr + offset++ ) ) = 0x00;
|
|
118
|
+ *( ( uint8_t* ) ( pshdr + offset++ ) ) = iphdr->protocol;
|
|
119
|
+ *( ( uint16_t* ) ( pshdr + offset ) ) = pkb_len ( pkb ) - IP_HLEN;
|
120
|
120
|
|
121
|
121
|
/* Update the checksum value */
|
122
|
|
- *( ( uint16_t* ) csum_offset ) = *( ( uint16_t* ) csum_offset ) + calc_chksum ( pshdr, IP_PSHLEN );
|
|
122
|
+ *( ( uint16_t* ) csum_offset ) = *( ( uint16_t* ) csum_offset ) + calc_chksum ( pshdr, IP_PSHLEN );
|
123
|
123
|
}
|
124
|
124
|
|
125
|
125
|
/**
|
|
@@ -173,7 +173,7 @@ int ipv4_uip_tx ( struct pk_buff *pkb ) {
|
173
|
173
|
/* Broadcast address */
|
174
|
174
|
ll_dest = netdev->ll_protocol->ll_broadcast;
|
175
|
175
|
} else if ( IN_MULTICAST ( next_hop.s_addr ) ) {
|
176
|
|
- /* Special case: IPv4 multicast over Ethernet. This
|
|
176
|
+ /* Special case: IPv4 multicast over Ethernet. This
|
177
|
177
|
* code may need to be generalised once we find out
|
178
|
178
|
* what happens for other link layers.
|
179
|
179
|
*/
|
|
@@ -214,28 +214,28 @@ int ipv4_uip_tx ( struct pk_buff *pkb ) {
|
214
|
214
|
*/
|
215
|
215
|
int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest ) {
|
216
|
216
|
struct iphdr *iphdr = pkb_push ( pkb, IP_HLEN );
|
217
|
|
- struct ipv4_miniroute *miniroute;
|
218
|
|
- struct net_device *netdev = NULL;
|
219
|
|
- struct in_addr next_hop;
|
220
|
|
- struct in_addr source;
|
221
|
|
- uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
|
222
|
|
- const uint8_t *ll_dest = ll_dest_buf;
|
223
|
|
- int rc;
|
224
|
|
-
|
225
|
|
- /* Fill up the IP header, except source address */
|
226
|
|
- iphdr->verhdrlen = ( IP_VER << 4 ) | ( IP_HLEN / 4 ); /* Version = 4, Header length = 5 */
|
227
|
|
- iphdr->service = IP_TOS; /* Service = 0, is not implemented */
|
228
|
|
- iphdr->len = htons ( pkb_len ( pkb ) ); /* Total packet length, in network byte order */
|
229
|
|
- iphdr->ident = next_ident++; /* Identification number */
|
230
|
|
- iphdr->frags = 0; /* Fragmentation is not implemented at the host */
|
231
|
|
- iphdr->ttl = IP_TTL; /* Time to live */
|
232
|
|
- iphdr->protocol = trans_proto; /* Transport-layer protocol - IP_XXX */
|
|
217
|
+ struct ipv4_miniroute *miniroute;
|
|
218
|
+ struct net_device *netdev = NULL;
|
|
219
|
+ struct in_addr next_hop;
|
|
220
|
+ struct in_addr source;
|
|
221
|
+ uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
|
|
222
|
+ const uint8_t *ll_dest = ll_dest_buf;
|
|
223
|
+ int rc;
|
|
224
|
+
|
|
225
|
+ /* Fill up the IP header, except source address */
|
|
226
|
+ iphdr->verhdrlen = ( IP_VER << 4 ) | ( IP_HLEN / 4 ); /* Version = 4, Header length = 5 */
|
|
227
|
+ iphdr->service = IP_TOS; /* Service = 0, is not implemented */
|
|
228
|
+ iphdr->len = htons ( pkb_len ( pkb ) ); /* Total packet length, in network byte order */
|
|
229
|
+ iphdr->ident = next_ident++; /* Identification number */
|
|
230
|
+ iphdr->frags = 0; /* Fragmentation is not implemented at the host */
|
|
231
|
+ iphdr->ttl = IP_TTL; /* Time to live */
|
|
232
|
+ iphdr->protocol = trans_proto; /* Transport-layer protocol - IP_XXX */
|
233
|
233
|
|
234
|
234
|
/* Calculate header checksum, in network byte order */
|
235
|
|
- iphdr->chksum = 0;
|
236
|
|
- iphdr->chksum = htons ( calc_chksum ( iphdr, IP_HLEN ) );
|
|
235
|
+ iphdr->chksum = 0;
|
|
236
|
+ iphdr->chksum = htons ( calc_chksum ( iphdr, IP_HLEN ) );
|
237
|
237
|
/* Copy destination address */
|
238
|
|
- memcpy ( &iphdr->dest, dest, sizeof ( struct in_addr ) );
|
|
238
|
+ memcpy ( &iphdr->dest, dest, sizeof ( struct in_addr ) );
|
239
|
239
|
|
240
|
240
|
/**
|
241
|
241
|
* All fields in the IP header filled in except the source network address (which requires routing). As
|
|
@@ -245,77 +245,77 @@ int ipv4_tx ( struct pk_buff *pkb, uint16_t trans_proto, struct in_addr *dest )
|
245
|
245
|
* Continue processing as in ipv4_uip_tx()
|
246
|
246
|
*/
|
247
|
247
|
|
248
|
|
- /* Use routing table to identify next hop and transmitting netdev */
|
249
|
|
- next_hop = iphdr->dest;
|
250
|
|
- list_for_each_entry ( miniroute, &miniroutes, list ) {
|
251
|
|
- if ( ( ( ( iphdr->dest.s_addr ^ miniroute->address.s_addr ) &
|
252
|
|
- miniroute->netmask.s_addr ) == 0 ) ||
|
253
|
|
- ( miniroute->gateway.s_addr != INADDR_NONE ) ) {
|
254
|
|
- netdev = miniroute->netdev;
|
255
|
|
- source = miniroute->address;
|
256
|
|
- if ( miniroute->gateway.s_addr != INADDR_NONE )
|
257
|
|
- next_hop = miniroute->gateway;
|
258
|
|
- break;
|
259
|
|
- }
|
|
248
|
+ /* Use routing table to identify next hop and transmitting netdev */
|
|
249
|
+ next_hop = iphdr->dest;
|
|
250
|
+ list_for_each_entry ( miniroute, &miniroutes, list ) {
|
|
251
|
+ if ( ( ( ( iphdr->dest.s_addr ^ miniroute->address.s_addr ) &
|
|
252
|
+ miniroute->netmask.s_addr ) == 0 ) ||
|
|
253
|
+ ( miniroute->gateway.s_addr != INADDR_NONE ) ) {
|
|
254
|
+ netdev = miniroute->netdev;
|
|
255
|
+ source = miniroute->address;
|
|
256
|
+ if ( miniroute->gateway.s_addr != INADDR_NONE )
|
|
257
|
+ next_hop = miniroute->gateway;
|
|
258
|
+ break;
|
|
259
|
+ }
|
|
260
|
+ }
|
|
261
|
+ /* Abort if no network device identified */
|
|
262
|
+ if ( ! netdev ) {
|
|
263
|
+ DBG ( "No route to %s\n", inet_ntoa ( iphdr->dest ) );
|
|
264
|
+ rc = -EHOSTUNREACH;
|
|
265
|
+ goto err;
|
|
266
|
+ }
|
|
267
|
+
|
|
268
|
+ /* Copy the source address, after this the IP header is complete */
|
|
269
|
+ memcpy ( &iphdr->src, &source, sizeof ( struct in_addr ) );
|
|
270
|
+ /* Calculate the transport layer checksum */
|
|
271
|
+ ipv4_tx_csum ( pkb, trans_proto );
|
|
272
|
+
|
|
273
|
+ /* Print IP4 header for debugging */
|
|
274
|
+ DBG ( "IP4 header at %#x + %d\n", iphdr, IP_HLEN );
|
|
275
|
+ DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 );
|
|
276
|
+ DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN );
|
|
277
|
+ DBG ( "\tService = %d\n", iphdr->service );
|
|
278
|
+ DBG ( "\tTotal length = %d\n", iphdr->len );
|
|
279
|
+ DBG ( "\tIdent = %d\n", iphdr->ident );
|
|
280
|
+ DBG ( "\tFrags/Offset = %d\n", iphdr->frags );
|
|
281
|
+ DBG ( "\tIP TTL = %d\n", iphdr->ttl );
|
|
282
|
+ DBG ( "\tProtocol = %d\n", iphdr->protocol );
|
|
283
|
+ DBG ( "\tHeader Checksum (at %#x) = %x\n", &iphdr->chksum, iphdr->chksum );
|
|
284
|
+ DBG ( "\tSource = %s\n", inet_ntoa ( iphdr->src) );
|
|
285
|
+ DBG ( "\tDestination = %s\n", inet_ntoa ( iphdr->dest ) );
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+ /* Determine link-layer destination address */
|
|
289
|
+ if ( next_hop.s_addr == INADDR_BROADCAST ) {
|
|
290
|
+ /* Broadcast address */
|
|
291
|
+ ll_dest = netdev->ll_protocol->ll_broadcast;
|
|
292
|
+ } else if ( IN_MULTICAST ( next_hop.s_addr ) ) {
|
|
293
|
+ /* Special case: IPv4 multicast over Ethernet. This
|
|
294
|
+ * code may need to be generalised once we find out
|
|
295
|
+ * what happens for other link layers.
|
|
296
|
+ */
|
|
297
|
+ uint8_t *next_hop_bytes = ( uint8_t * ) &next_hop;
|
|
298
|
+ ll_dest_buf[0] = 0x01;
|
|
299
|
+ ll_dest_buf[0] = 0x00;
|
|
300
|
+ ll_dest_buf[0] = 0x5e;
|
|
301
|
+ ll_dest_buf[3] = next_hop_bytes[1] & 0x7f;
|
|
302
|
+ ll_dest_buf[4] = next_hop_bytes[2];
|
|
303
|
+ ll_dest_buf[5] = next_hop_bytes[3];
|
|
304
|
+ } else {
|
|
305
|
+ /* Unicast address: resolve via ARP */
|
|
306
|
+ if ( ( rc = arp_resolve ( netdev, &ipv4_protocol, &next_hop, &source, ll_dest_buf ) ) != 0 ) {
|
|
307
|
+ DBG ( "No ARP entry for %s\n", inet_ntoa ( iphdr->dest ) );
|
|
308
|
+ goto err;
|
|
309
|
+ }
|
260
|
310
|
}
|
261
|
|
- /* Abort if no network device identified */
|
262
|
|
- if ( ! netdev ) {
|
263
|
|
- DBG ( "No route to %s\n", inet_ntoa ( iphdr->dest ) );
|
264
|
|
- rc = -EHOSTUNREACH;
|
265
|
|
- goto err;
|
266
|
|
- }
|
267
|
|
-
|
268
|
|
- /* Copy the source address, after this the IP header is complete */
|
269
|
|
- memcpy ( &iphdr->src, &source, sizeof ( struct in_addr ) );
|
270
|
|
- /* Calculate the transport layer checksum */
|
271
|
|
- ipv4_tx_csum ( pkb, trans_proto );
|
272
|
|
-
|
273
|
|
- /* Print IP4 header for debugging */
|
274
|
|
- DBG ( "IP4 header at %#x + %d\n", iphdr, IP_HLEN );
|
275
|
|
- DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 );
|
276
|
|
- DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN );
|
277
|
|
- DBG ( "\tService = %d\n", iphdr->service );
|
278
|
|
- DBG ( "\tTotal length = %d\n", iphdr->len );
|
279
|
|
- DBG ( "\tIdent = %d\n", iphdr->ident );
|
280
|
|
- DBG ( "\tFrags/Offset = %d\n", iphdr->frags );
|
281
|
|
- DBG ( "\tIP TTL = %d\n", iphdr->ttl );
|
282
|
|
- DBG ( "\tProtocol = %d\n", iphdr->protocol );
|
283
|
|
- DBG ( "\tHeader Checksum (at %#x) = %x\n", &iphdr->chksum, iphdr->chksum );
|
284
|
|
- DBG ( "\tSource = %s\n", inet_ntoa ( iphdr->src) );
|
285
|
|
- DBG ( "\tDestination = %s\n", inet_ntoa ( iphdr->dest ) );
|
286
|
|
-
|
287
|
|
-
|
288
|
|
- /* Determine link-layer destination address */
|
289
|
|
- if ( next_hop.s_addr == INADDR_BROADCAST ) {
|
290
|
|
- /* Broadcast address */
|
291
|
|
- ll_dest = netdev->ll_protocol->ll_broadcast;
|
292
|
|
- } else if ( IN_MULTICAST ( next_hop.s_addr ) ) {
|
293
|
|
- /* Special case: IPv4 multicast over Ethernet. This
|
294
|
|
- * code may need to be generalised once we find out
|
295
|
|
- * what happens for other link layers.
|
296
|
|
- */
|
297
|
|
- uint8_t *next_hop_bytes = ( uint8_t * ) &next_hop;
|
298
|
|
- ll_dest_buf[0] = 0x01;
|
299
|
|
- ll_dest_buf[0] = 0x00;
|
300
|
|
- ll_dest_buf[0] = 0x5e;
|
301
|
|
- ll_dest_buf[3] = next_hop_bytes[1] & 0x7f;
|
302
|
|
- ll_dest_buf[4] = next_hop_bytes[2];
|
303
|
|
- ll_dest_buf[5] = next_hop_bytes[3];
|
304
|
|
- } else {
|
305
|
|
- /* Unicast address: resolve via ARP */
|
306
|
|
- if ( ( rc = arp_resolve ( netdev, &ipv4_protocol, &next_hop, &source, ll_dest_buf ) ) != 0 ) {
|
307
|
|
- DBG ( "No ARP entry for %s\n", inet_ntoa ( iphdr->dest ) );
|
308
|
|
- goto err;
|
309
|
|
- }
|
310
|
|
- }
|
311
|
|
-
|
312
|
|
- /* Hand off to link layer */
|
313
|
|
- return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest );
|
|
311
|
+
|
|
312
|
+ /* Hand off to link layer */
|
|
313
|
+ return net_tx ( pkb, netdev, &ipv4_protocol, ll_dest );
|
314
|
314
|
|
315
|
315
|
err:
|
316
|
|
- /* Warning: Allowing this function to execute causes bochs to go into an infinite loop */
|
317
|
|
- free_pkb ( pkb );
|
318
|
|
- return rc;
|
|
316
|
+ /* Warning: Allowing this function to execute causes bochs to go into an infinite loop */
|
|
317
|
+ free_pkb ( pkb );
|
|
318
|
+ return rc;
|
319
|
319
|
}
|
320
|
320
|
|
321
|
321
|
/**
|
|
@@ -381,27 +381,27 @@ void ipv6_rx ( struct pk_buff *pkb __unused, struct net_device *netdev __unused,
|
381
|
381
|
* This function expects an IP4 network datagram. It will process the headers and send it to the transport layer
|
382
|
382
|
*/
|
383
|
383
|
void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
|
384
|
|
- const void *ll_source __unused ) {
|
385
|
|
- struct iphdr *iphdr = pkb->data;
|
386
|
|
- struct in_addr *src = &iphdr->src;
|
387
|
|
- struct in_addr *dest = &iphdr->dest;
|
|
384
|
+ const void *ll_source __unused ) {
|
|
385
|
+ struct iphdr *iphdr = pkb->data;
|
|
386
|
+ struct in_addr *src = &iphdr->src;
|
|
387
|
+ struct in_addr *dest = &iphdr->dest;
|
388
|
388
|
uint16_t chksum;
|
389
|
389
|
|
390
|
|
- /* Print IP4 header for debugging */
|
391
|
|
- DBG ( "IP4 header at %#x + %d\n", iphdr, IP_HLEN );
|
392
|
|
- DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 );
|
393
|
|
- DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN );
|
394
|
|
- DBG ( "\tService = %d\n", iphdr->service );
|
395
|
|
- DBG ( "\tTotal length = %d\n", iphdr->len );
|
396
|
|
- DBG ( "\tIdent = %d\n", iphdr->ident );
|
397
|
|
- DBG ( "\tFrags/Offset = %d\n", iphdr->frags );
|
398
|
|
- DBG ( "\tIP TTL = %d\n", iphdr->ttl );
|
399
|
|
- DBG ( "\tProtocol = %d\n", iphdr->protocol );
|
400
|
|
- DBG ( "\tHeader Checksum (at %#x) = %x\n", &iphdr->chksum, iphdr->chksum );
|
401
|
|
- DBG ( "\tSource = %s\n", inet_ntoa ( iphdr->src) );
|
402
|
|
- DBG ( "\tDestination = %s\n", inet_ntoa ( iphdr->dest ) );
|
403
|
|
-
|
404
|
|
- /* Process headers */
|
|
390
|
+ /* Print IP4 header for debugging */
|
|
391
|
+ DBG ( "IP4 header at %#x + %d\n", iphdr, IP_HLEN );
|
|
392
|
+ DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 );
|
|
393
|
+ DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN );
|
|
394
|
+ DBG ( "\tService = %d\n", iphdr->service );
|
|
395
|
+ DBG ( "\tTotal length = %d\n", iphdr->len );
|
|
396
|
+ DBG ( "\tIdent = %d\n", iphdr->ident );
|
|
397
|
+ DBG ( "\tFrags/Offset = %d\n", iphdr->frags );
|
|
398
|
+ DBG ( "\tIP TTL = %d\n", iphdr->ttl );
|
|
399
|
+ DBG ( "\tProtocol = %d\n", iphdr->protocol );
|
|
400
|
+ DBG ( "\tHeader Checksum (at %#x) = %x\n", &iphdr->chksum, iphdr->chksum );
|
|
401
|
+ DBG ( "\tSource = %s\n", inet_ntoa ( iphdr->src) );
|
|
402
|
+ DBG ( "\tDestination = %s\n", inet_ntoa ( iphdr->dest ) );
|
|
403
|
+
|
|
404
|
+ /* Process headers */
|
405
|
405
|
if ( iphdr->verhdrlen != 0x45 ) {
|
406
|
406
|
DBG ( "Bad version and header length %x\n", iphdr->verhdrlen );
|
407
|
407
|
return;
|
|
@@ -424,11 +424,11 @@ void ipv4_rx ( struct pk_buff *pkb, struct net_device *netdev __unused,
|
424
|
424
|
* 3. Check the service field
|
425
|
425
|
*/
|
426
|
426
|
|
427
|
|
- /* Strip header */
|
428
|
|
- pkb_pull ( pkb, IP_HLEN );
|
|
427
|
+ /* Strip header */
|
|
428
|
+ pkb_pull ( pkb, IP_HLEN );
|
429
|
429
|
|
430
|
|
- /* Send it to the transport layer */
|
431
|
|
- trans_rx ( pkb, iphdr->protocol, src, dest );
|
|
430
|
+ /* Send it to the transport layer */
|
|
431
|
+ trans_rx ( pkb, iphdr->protocol, src, dest );
|
432
|
432
|
}
|
433
|
433
|
|
434
|
434
|
/**
|