Browse Source

[GDB] UDP clean up and add netdev refcnt

tags/v0.9.4
Stefan Hajnoczi 16 years ago
parent
commit
578b056730
1 changed files with 47 additions and 19 deletions
  1. 47
    19
      src/core/gdbudp.c

+ 47
- 19
src/core/gdbudp.c View File

@@ -27,6 +27,17 @@
27 27
 #include <gpxe/udp.h>
28 28
 #include <gpxe/netdevice.h>
29 29
 #include <gpxe/gdbstub.h>
30
+#include <bios.h>
31
+
32
+/** @file
33
+ *
34
+ * GDB over UDP transport
35
+ *
36
+ */
37
+
38
+enum {
39
+	DEFAULT_PORT = 43770, /* UDP listen port */
40
+};
30 41
 
31 42
 struct gdb_transport udp_gdb_transport __gdb_transport;
32 43
 
@@ -37,13 +48,11 @@ static struct sockaddr_in dest_addr;
37 48
 static struct sockaddr_in source_addr;
38 49
 
39 50
 static void gdbudp_ensure_netdev_open ( struct net_device *netdev ) {
40
-	if ( ( netdev->state & NETDEV_OPEN) == 0 ) {
41
-		netdev_open ( netdev );
42
-	}
43
-	/* TODO forcing the netdev to be open is useful when
44
-	 * gPXE closes the netdev between breakpoints.  Should
45
-	 * we restore the state of the netdev, i.e. closed,
46
-	 * before leaving the interrupt handler? */
51
+	/* The device may have been closed between breakpoints */
52
+	assert ( netdev );
53
+	netdev_open ( netdev );
54
+
55
+	/* Strictly speaking, we may need to close the device when leaving the interrupt handler */
47 56
 }
48 57
 
49 58
 static size_t gdbudp_recv ( char *buf, size_t len ) {
@@ -54,27 +63,28 @@ static size_t gdbudp_recv ( char *buf, size_t len ) {
54 63
 	struct udp_header *udphdr;
55 64
 	size_t payload_len;
56 65
 
57
-	assert ( netdev );
58 66
 	gdbudp_ensure_netdev_open ( netdev );
59 67
 
60 68
 	for ( ; ; ) {
69
+		netdev_poll ( netdev );
61 70
 		while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
62
-			if ( iob_len ( iob ) > sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len ) {
71
+			/* Ethernet header */
72
+			if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
63 73
 				goto bad_packet;
64 74
 			}
65
-
66
-			/* Ethernet header */
67 75
 			ethhdr = iob->data;
68 76
 			iob_pull ( iob, sizeof ( *ethhdr ) );
77
+
78
+			/* Handle ARP requests so the client can find our MAC */
69 79
 			if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
70
-				/* Handle ARP requests so the client can connect to us */
71 80
 				arphdr = iob->data;
72
-				if ( arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
81
+				if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
82
+						arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
73 83
 						arphdr->ar_pro != htons ( ETH_P_IP ) ||
74 84
 						arphdr->ar_hln != ETH_ALEN ||
75 85
 						arphdr->ar_pln != sizeof ( struct in_addr ) ||
76 86
 						arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
77
-						memcmp ( arp_target_pa ( arphdr ), &source_addr.sin_addr.s_addr, sizeof ( struct in_addr ) ) ) {
87
+						* ( uint32_t * ) arp_target_pa ( arphdr ) != source_addr.sin_addr.s_addr ) {
78 88
 					goto bad_packet;
79 89
 				}
80 90
 
@@ -91,11 +101,15 @@ static size_t gdbudp_recv ( char *buf, size_t len ) {
91 101
 				netdev_tx ( netdev, iob );
92 102
 				continue; /* no need to free iob */
93 103
 			}
104
+
94 105
 			if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
95 106
 				goto bad_packet;
96 107
 			}
97 108
 
98 109
 			/* IP header */
110
+			if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
111
+				goto bad_packet;
112
+			}
99 113
 			iphdr = iob->data;
100 114
 			iob_pull ( iob, sizeof ( *iphdr ) );
101 115
 			if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
@@ -103,6 +117,9 @@ static size_t gdbudp_recv ( char *buf, size_t len ) {
103 117
 			}
104 118
 
105 119
 			/* UDP header */
120
+			if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
121
+				goto bad_packet;
122
+			}
106 123
 			udphdr = iob->data;
107 124
 			if ( udphdr->dest != source_addr.sin_port ) {
108 125
 				goto bad_packet;
@@ -115,12 +132,14 @@ static size_t gdbudp_recv ( char *buf, size_t len ) {
115 132
 
116 133
 			/* Payload */
117 134
 			payload_len = ntohs ( udphdr->len );
118
-			if ( payload_len < sizeof ( *udphdr ) ||
119
-					payload_len > iob_len ( iob ) ) {
135
+			if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
120 136
 				goto bad_packet;
121 137
 			}
122 138
 			payload_len -= sizeof ( *udphdr );
123 139
 			iob_pull ( iob, sizeof ( *udphdr ) );
140
+			if ( payload_len > len ) {
141
+				goto bad_packet;
142
+			}
124 143
 			memcpy ( buf, iob->data, payload_len );
125 144
 
126 145
 			free_iob ( iob );
@@ -129,7 +148,7 @@ static size_t gdbudp_recv ( char *buf, size_t len ) {
129 148
 bad_packet:
130 149
 			free_iob ( iob );
131 150
 		}
132
-		netdev_poll ( netdev );
151
+		cpu_nap();
133 152
 	}
134 153
 }
135 154
 
@@ -144,7 +163,6 @@ static void gdbudp_send ( const char *buf, size_t len ) {
144 163
 		return;
145 164
 	}
146 165
 
147
-	assert ( netdev );
148 166
 	gdbudp_ensure_netdev_open ( netdev );
149 167
 
150 168
 	iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
@@ -192,14 +210,22 @@ static int gdbudp_init ( int argc, char **argv ) {
192 210
 		return 1;
193 211
 	}
194 212
 
213
+	/* Release old network device */
214
+	netdev_put ( netdev );
215
+
195 216
 	netdev = find_netdev ( argv[0] );
196 217
 	if ( !netdev ) {
197 218
 		printf ( "%s: no such interface\n", argv[0] );
198 219
 		return 1;
199 220
 	}
200 221
 
222
+	/* Hold network device */
223
+	netdev_get ( netdev );
224
+
201 225
 	if ( !netdev_link_ok ( netdev ) ) {
202 226
 		printf ( "%s: link not up\n", argv[0] );
227
+		netdev_put ( netdev );
228
+		netdev = NULL;
203 229
 		return 1;
204 230
 	}
205 231
 
@@ -209,11 +235,13 @@ static int gdbudp_init ( int argc, char **argv ) {
209 235
 	 * Storing a separate copy makes it possible to use different
210 236
 	 * MAC/IP settings than the network stack. */
211 237
 	memcpy ( source_eth, netdev->ll_addr, ETH_ALEN );
212
-	source_addr.sin_port = htons ( 43770 ); /* TODO default port */
238
+	source_addr.sin_port = htons ( DEFAULT_PORT );
213 239
 	settings = netdev_settings ( netdev );
214 240
 	fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
215 241
 	if ( source_addr.sin_addr.s_addr == 0 ) {
216 242
 		printf ( "%s: no IP address configured\n", argv[0] );
243
+		netdev_put ( netdev );
244
+		netdev = NULL;
217 245
 		return 1;
218 246
 	}
219 247
 

Loading…
Cancel
Save