浏览代码

[GDB] UDP clean up and add netdev refcnt

tags/v0.9.4
Stefan Hajnoczi 16 年前
父节点
当前提交
578b056730
共有 1 个文件被更改,包括 47 次插入19 次删除
  1. 47
    19
      src/core/gdbudp.c

+ 47
- 19
src/core/gdbudp.c 查看文件

27
 #include <gpxe/udp.h>
27
 #include <gpxe/udp.h>
28
 #include <gpxe/netdevice.h>
28
 #include <gpxe/netdevice.h>
29
 #include <gpxe/gdbstub.h>
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
 struct gdb_transport udp_gdb_transport __gdb_transport;
42
 struct gdb_transport udp_gdb_transport __gdb_transport;
32
 
43
 
37
 static struct sockaddr_in source_addr;
48
 static struct sockaddr_in source_addr;
38
 
49
 
39
 static void gdbudp_ensure_netdev_open ( struct net_device *netdev ) {
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
 static size_t gdbudp_recv ( char *buf, size_t len ) {
58
 static size_t gdbudp_recv ( char *buf, size_t len ) {
54
 	struct udp_header *udphdr;
63
 	struct udp_header *udphdr;
55
 	size_t payload_len;
64
 	size_t payload_len;
56
 
65
 
57
-	assert ( netdev );
58
 	gdbudp_ensure_netdev_open ( netdev );
66
 	gdbudp_ensure_netdev_open ( netdev );
59
 
67
 
60
 	for ( ; ; ) {
68
 	for ( ; ; ) {
69
+		netdev_poll ( netdev );
61
 		while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
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
 				goto bad_packet;
73
 				goto bad_packet;
64
 			}
74
 			}
65
-
66
-			/* Ethernet header */
67
 			ethhdr = iob->data;
75
 			ethhdr = iob->data;
68
 			iob_pull ( iob, sizeof ( *ethhdr ) );
76
 			iob_pull ( iob, sizeof ( *ethhdr ) );
77
+
78
+			/* Handle ARP requests so the client can find our MAC */
69
 			if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
79
 			if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
70
-				/* Handle ARP requests so the client can connect to us */
71
 				arphdr = iob->data;
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
 						arphdr->ar_pro != htons ( ETH_P_IP ) ||
83
 						arphdr->ar_pro != htons ( ETH_P_IP ) ||
74
 						arphdr->ar_hln != ETH_ALEN ||
84
 						arphdr->ar_hln != ETH_ALEN ||
75
 						arphdr->ar_pln != sizeof ( struct in_addr ) ||
85
 						arphdr->ar_pln != sizeof ( struct in_addr ) ||
76
 						arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
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
 					goto bad_packet;
88
 					goto bad_packet;
79
 				}
89
 				}
80
 
90
 
91
 				netdev_tx ( netdev, iob );
101
 				netdev_tx ( netdev, iob );
92
 				continue; /* no need to free iob */
102
 				continue; /* no need to free iob */
93
 			}
103
 			}
104
+
94
 			if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
105
 			if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
95
 				goto bad_packet;
106
 				goto bad_packet;
96
 			}
107
 			}
97
 
108
 
98
 			/* IP header */
109
 			/* IP header */
110
+			if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
111
+				goto bad_packet;
112
+			}
99
 			iphdr = iob->data;
113
 			iphdr = iob->data;
100
 			iob_pull ( iob, sizeof ( *iphdr ) );
114
 			iob_pull ( iob, sizeof ( *iphdr ) );
101
 			if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
115
 			if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
103
 			}
117
 			}
104
 
118
 
105
 			/* UDP header */
119
 			/* UDP header */
120
+			if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
121
+				goto bad_packet;
122
+			}
106
 			udphdr = iob->data;
123
 			udphdr = iob->data;
107
 			if ( udphdr->dest != source_addr.sin_port ) {
124
 			if ( udphdr->dest != source_addr.sin_port ) {
108
 				goto bad_packet;
125
 				goto bad_packet;
115
 
132
 
116
 			/* Payload */
133
 			/* Payload */
117
 			payload_len = ntohs ( udphdr->len );
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
 				goto bad_packet;
136
 				goto bad_packet;
121
 			}
137
 			}
122
 			payload_len -= sizeof ( *udphdr );
138
 			payload_len -= sizeof ( *udphdr );
123
 			iob_pull ( iob, sizeof ( *udphdr ) );
139
 			iob_pull ( iob, sizeof ( *udphdr ) );
140
+			if ( payload_len > len ) {
141
+				goto bad_packet;
142
+			}
124
 			memcpy ( buf, iob->data, payload_len );
143
 			memcpy ( buf, iob->data, payload_len );
125
 
144
 
126
 			free_iob ( iob );
145
 			free_iob ( iob );
129
 bad_packet:
148
 bad_packet:
130
 			free_iob ( iob );
149
 			free_iob ( iob );
131
 		}
150
 		}
132
-		netdev_poll ( netdev );
151
+		cpu_nap();
133
 	}
152
 	}
134
 }
153
 }
135
 
154
 
144
 		return;
163
 		return;
145
 	}
164
 	}
146
 
165
 
147
-	assert ( netdev );
148
 	gdbudp_ensure_netdev_open ( netdev );
166
 	gdbudp_ensure_netdev_open ( netdev );
149
 
167
 
150
 	iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
168
 	iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
192
 		return 1;
210
 		return 1;
193
 	}
211
 	}
194
 
212
 
213
+	/* Release old network device */
214
+	netdev_put ( netdev );
215
+
195
 	netdev = find_netdev ( argv[0] );
216
 	netdev = find_netdev ( argv[0] );
196
 	if ( !netdev ) {
217
 	if ( !netdev ) {
197
 		printf ( "%s: no such interface\n", argv[0] );
218
 		printf ( "%s: no such interface\n", argv[0] );
198
 		return 1;
219
 		return 1;
199
 	}
220
 	}
200
 
221
 
222
+	/* Hold network device */
223
+	netdev_get ( netdev );
224
+
201
 	if ( !netdev_link_ok ( netdev ) ) {
225
 	if ( !netdev_link_ok ( netdev ) ) {
202
 		printf ( "%s: link not up\n", argv[0] );
226
 		printf ( "%s: link not up\n", argv[0] );
227
+		netdev_put ( netdev );
228
+		netdev = NULL;
203
 		return 1;
229
 		return 1;
204
 	}
230
 	}
205
 
231
 
209
 	 * Storing a separate copy makes it possible to use different
235
 	 * Storing a separate copy makes it possible to use different
210
 	 * MAC/IP settings than the network stack. */
236
 	 * MAC/IP settings than the network stack. */
211
 	memcpy ( source_eth, netdev->ll_addr, ETH_ALEN );
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
 	settings = netdev_settings ( netdev );
239
 	settings = netdev_settings ( netdev );
214
 	fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
240
 	fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
215
 	if ( source_addr.sin_addr.s_addr == 0 ) {
241
 	if ( source_addr.sin_addr.s_addr == 0 ) {
216
 		printf ( "%s: no IP address configured\n", argv[0] );
242
 		printf ( "%s: no IP address configured\n", argv[0] );
243
+		netdev_put ( netdev );
244
+		netdev = NULL;
217
 		return 1;
245
 		return 1;
218
 	}
246
 	}
219
 
247
 

正在加载...
取消
保存