iPXE
gdbudp.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Stefan Hajnoczi <stefanha@gmail.com>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( FORBIDDEN );
26
27#include <stdio.h>
28#include <string.h>
29#include <byteswap.h>
30#include <ipxe/iobuf.h>
31#include <ipxe/in.h>
32#include <ipxe/if_arp.h>
33#include <ipxe/if_ether.h>
34#include <ipxe/ip.h>
35#include <ipxe/udp.h>
36#include <ipxe/netdevice.h>
37#include <ipxe/nap.h>
38#include <ipxe/gdbstub.h>
39#include <ipxe/gdbudp.h>
40
41/** @file
42 *
43 * GDB over UDP transport
44 *
45 */
46
47enum {
48 DEFAULT_PORT = 43770, /* UDP listen port */
49};
50
51struct gdb_transport udp_gdb_transport __gdb_transport;
52
53static struct net_device *netdev;
55static struct sockaddr_in dest_addr;
57
59 /* The device may have been closed between breakpoints */
60 assert ( netdev );
62
63 /* Strictly speaking, we may need to close the device when leaving the interrupt handler */
64}
65
66static size_t gdbudp_recv ( char *buf, size_t len ) {
67 struct io_buffer *iob;
68 struct ethhdr *ethhdr;
69 struct arphdr *arphdr;
70 struct iphdr *iphdr;
71 struct udp_header *udphdr;
72 size_t payload_len;
73
75
76 for ( ; ; ) {
78 while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
79 /* Ethernet header */
80 if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
81 goto bad_packet;
82 }
83 ethhdr = iob->data;
84 iob_pull ( iob, sizeof ( *ethhdr ) );
85
86 /* Handle ARP requests so the client can find our MAC */
87 if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
88 arphdr = iob->data;
89 if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
91 arphdr->ar_pro != htons ( ETH_P_IP ) ||
93 arphdr->ar_pln != sizeof ( struct in_addr ) ||
95 * ( uint32_t * ) arp_target_pa ( arphdr ) != source_addr.sin_addr.s_addr ) {
96 goto bad_packet;
97 }
98
99 /* Generate an ARP reply */
101 memswap ( arp_sender_pa ( arphdr ), arp_target_pa ( arphdr ), sizeof ( struct in_addr ) );
103 memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, ETH_ALEN );
104
105 /* Fix up ethernet header */
106 ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
108 memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
109
110 netdev_tx ( netdev, iob );
111 continue; /* no need to free iob */
112 }
113
114 if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
115 goto bad_packet;
116 }
117
118 /* IP header */
119 if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
120 goto bad_packet;
121 }
122 iphdr = iob->data;
123 iob_pull ( iob, sizeof ( *iphdr ) );
124 if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
125 goto bad_packet;
126 }
127
128 /* UDP header */
129 if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
130 goto bad_packet;
131 }
132 udphdr = iob->data;
133 if ( udphdr->dest != source_addr.sin_port ) {
134 goto bad_packet;
135 }
136
137 /* Learn the remote connection details */
139 dest_addr.sin_addr.s_addr = iphdr->src.s_addr;
140 dest_addr.sin_port = udphdr->src;
141
142 /* Payload */
143 payload_len = ntohs ( udphdr->len );
144 if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
145 goto bad_packet;
146 }
147 payload_len -= sizeof ( *udphdr );
148 iob_pull ( iob, sizeof ( *udphdr ) );
149 if ( payload_len > len ) {
150 goto bad_packet;
151 }
152 memcpy ( buf, iob->data, payload_len );
153
154 free_iob ( iob );
155 return payload_len;
156
157bad_packet:
158 free_iob ( iob );
159 }
160 cpu_nap();
161 }
162}
163
164static void gdbudp_send ( const char *buf, size_t len ) {
165 struct io_buffer *iob;
166 struct ethhdr *ethhdr;
167 struct iphdr *iphdr;
168 struct udp_header *udphdr;
169
170 /* Check that we are connected */
171 if ( dest_addr.sin_port == 0 ) {
172 return;
173 }
174
176
177 iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
178 if ( !iob ) {
179 return;
180 }
181
182 /* Payload */
183 iob_reserve ( iob, sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) );
184 memcpy ( iob_put ( iob, len ), buf, len );
185
186 /* UDP header */
187 udphdr = iob_push ( iob, sizeof ( *udphdr ) );
188 udphdr->src = source_addr.sin_port;
189 udphdr->dest = dest_addr.sin_port;
190 udphdr->len = htons ( iob_len ( iob ) );
191 udphdr->chksum = 0; /* optional and we are not using it */
192
193 /* IP header */
194 iphdr = iob_push ( iob, sizeof ( *iphdr ) );
195 memset ( iphdr, 0, sizeof ( *iphdr ) );
196 iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
198 iphdr->len = htons ( iob_len ( iob ) );
199 iphdr->ttl = IP_TTL;
201 iphdr->dest.s_addr = dest_addr.sin_addr.s_addr;
202 iphdr->src.s_addr = source_addr.sin_addr.s_addr;
203 iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
204
205 /* Ethernet header */
206 ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
208 memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
210
211 netdev_tx ( netdev, iob );
212}
213
214struct gdb_transport *gdbudp_configure ( const char *name, struct sockaddr_in *addr ) {
215 struct settings *settings;
216
217 /* Release old network device */
218 netdev_put ( netdev );
219
220 netdev = find_netdev ( name );
221 if ( !netdev ) {
222 return NULL;
223 }
224
225 /* Hold network device */
226 netdev_get ( netdev );
227
228 /* Source UDP port */
229 source_addr.sin_port = ( addr && addr->sin_port ) ? addr->sin_port : htons ( DEFAULT_PORT );
230
231 /* Source IP address */
232 if ( addr && addr->sin_addr.s_addr ) {
233 source_addr.sin_addr.s_addr = addr->sin_addr.s_addr;
234 } else {
237 if ( source_addr.sin_addr.s_addr == 0 ) {
238 netdev_put ( netdev );
239 netdev = NULL;
240 return NULL;
241 }
242 }
243
244 return &udp_gdb_transport;
245}
246
247static int gdbudp_init ( int argc, char **argv ) {
248 if ( argc != 1 ) {
249 printf ( "udp: missing <interface> argument\n" );
250 return 1;
251 }
252
253 if ( !gdbudp_configure ( argv[0], NULL ) ) {
254 printf ( "%s: device does not exist or has no IP address\n", argv[0] );
255 return 1;
256 }
257 return 0;
258}
259
260struct gdb_transport udp_gdb_transport __gdb_transport = {
261 .name = "udp",
262 .init = gdbudp_init,
263 .send = gdbudp_send,
264 .recv = gdbudp_recv,
265};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
const char * name
Definition ath9k_hw.c:1986
ring len
Length.
Definition dwmac.h:226
uint32_t addr
Buffer address.
Definition dwmac.h:9
const struct setting ip_setting
GDB remote debugging.
#define __gdb_transport
Definition gdbstub.h:53
static uint8_t dest_eth[ETH_ALEN]
Definition gdbudp.c:54
static struct sockaddr_in dest_addr
Definition gdbudp.c:55
struct gdb_transport * gdbudp_configure(const char *name, struct sockaddr_in *addr)
Definition gdbudp.c:214
static size_t gdbudp_recv(char *buf, size_t len)
Definition gdbudp.c:66
static void gdbudp_ensure_netdev_open(struct net_device *netdev)
Definition gdbudp.c:58
static struct sockaddr_in source_addr
Definition gdbudp.c:56
static struct net_device * netdev
Definition gdbudp.c:53
static void gdbudp_send(const char *buf, size_t len)
Definition gdbudp.c:164
@ DEFAULT_PORT
Definition gdbudp.c:48
static int gdbudp_init(int argc, char **argv)
Definition gdbudp.c:247
GDB remote debugging over UDP.
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
Address Resolution Protocol constants and types.
static void * arp_sender_pa(struct arphdr *arphdr)
ARP packet sender protocol address.
Definition if_arp.h:81
static void * arp_target_ha(struct arphdr *arphdr)
ARP packet target hardware address.
Definition if_arp.h:90
#define ARPOP_REQUEST
ARP request.
Definition if_arp.h:33
static void * arp_target_pa(struct arphdr *arphdr)
ARP packet target protocol address.
Definition if_arp.h:99
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition if_arp.h:17
#define ARPOP_REPLY
ARP reply.
Definition if_arp.h:34
static void * arp_sender_ha(struct arphdr *arphdr)
ARP packet sender hardware address.
Definition if_arp.h:72
#define ETH_ALEN
Definition if_ether.h:9
#define ETH_P_IP
Definition if_ether.h:19
#define ETH_P_ARP
Definition if_ether.h:20
#define IP_UDP
Definition in.h:15
#define htons(value)
Definition byteswap.h:136
#define ntohs(value)
Definition byteswap.h:137
CPU sleeping.
void cpu_nap(void)
Sleep with interrupts enabled until next CPU interrupt.
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
#define iob_push(iobuf, len)
Definition iobuf.h:89
#define iob_put(iobuf, len)
Definition iobuf.h:125
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
#define iob_pull(iobuf, len)
Definition iobuf.h:107
IP protocol.
#define IP_TTL
Definition ip.h:33
#define IP_TOS
Definition ip.h:32
#define IP_VER
Definition ip.h:23
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition netdevice.c:638
int netdev_open(struct net_device *netdev)
Open network device.
Definition netdevice.c:862
struct net_device * find_netdev(const char *name)
Get network device by name.
Definition netdevice.c:989
void netdev_poll(struct net_device *netdev)
Poll for completed and received packets on network device.
Definition netdevice.c:613
int netdev_tx(struct net_device *netdev, struct io_buffer *iobuf)
Transmit raw packet via network device.
Definition netdevice.c:335
Network device management.
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition netdevice.h:565
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:576
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition netdevice.h:587
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition settings.c:913
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition string.c:154
An ARP header.
Definition if_arp.h:48
uint8_t ar_hln
Link-layer address length.
Definition if_arp.h:60
uint16_t ar_op
ARP opcode.
Definition if_arp.h:64
uint16_t ar_pro
Network-layer protocol.
Definition if_arp.h:58
uint8_t ar_pln
Network-layer address length.
Definition if_arp.h:62
uint16_t ar_hrd
Link-layer protocol.
Definition if_arp.h:53
An Ethernet link-layer header.
Definition if_ether.h:32
uint16_t h_protocol
Protocol ID.
Definition if_ether.h:38
uint8_t h_dest[ETH_ALEN]
Destination MAC address.
Definition if_ether.h:34
uint8_t h_source[ETH_ALEN]
Source MAC address.
Definition if_ether.h:36
A transport mechanism for the GDB protocol.
Definition gdbstub.h:21
IP address structure.
Definition in.h:42
uint32_t s_addr
Definition in.h:43
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
An IPv4 packet header.
Definition ip.h:36
uint8_t service
Definition ip.h:38
uint8_t protocol
Definition ip.h:43
struct in_addr dest
Definition ip.h:46
uint16_t len
Definition ip.h:39
struct in_addr src
Definition ip.h:45
uint8_t ttl
Definition ip.h:42
uint8_t verhdrlen
Definition ip.h:37
uint16_t chksum
Definition ip.h:44
A network device.
Definition netdevice.h:353
A settings block.
Definition settings.h:133
IPv4 socket address.
Definition in.h:85
UDP constants.
Definition udp.h:30
uint16_t dest
Destination port.
Definition udp.h:34
uint16_t src
Source port.
Definition udp.h:32
uint16_t len
Length.
Definition udp.h:36
uint16_t chksum
Checksum.
Definition udp.h:38
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition tcpip.c:204
UDP protocol.
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition vsprintf.c:465