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 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <stdio.h>
27 #include <string.h>
28 #include <byteswap.h>
29 #include <ipxe/iobuf.h>
30 #include <ipxe/in.h>
31 #include <ipxe/if_arp.h>
32 #include <ipxe/if_ether.h>
33 #include <ipxe/ip.h>
34 #include <ipxe/udp.h>
35 #include <ipxe/netdevice.h>
36 #include <ipxe/nap.h>
37 #include <ipxe/gdbstub.h>
38 #include <ipxe/gdbudp.h>
39 
40 /** @file
41  *
42  * GDB over UDP transport
43  *
44  */
45 
46 enum {
47  DEFAULT_PORT = 43770, /* UDP listen port */
48 };
49 
50 struct gdb_transport udp_gdb_transport __gdb_transport;
51 
52 static struct net_device *netdev;
54 static struct sockaddr_in dest_addr;
55 static struct sockaddr_in source_addr;
56 
57 static void gdbudp_ensure_netdev_open ( struct net_device *netdev ) {
58  /* The device may have been closed between breakpoints */
59  assert ( netdev );
60  netdev_open ( netdev );
61 
62  /* Strictly speaking, we may need to close the device when leaving the interrupt handler */
63 }
64 
65 static size_t gdbudp_recv ( char *buf, size_t len ) {
66  struct io_buffer *iob;
67  struct ethhdr *ethhdr;
68  struct arphdr *arphdr;
69  struct iphdr *iphdr;
70  struct udp_header *udphdr;
71  size_t payload_len;
72 
74 
75  for ( ; ; ) {
76  netdev_poll ( netdev );
77  while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
78  /* Ethernet header */
79  if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
80  goto bad_packet;
81  }
82  ethhdr = iob->data;
83  iob_pull ( iob, sizeof ( *ethhdr ) );
84 
85  /* Handle ARP requests so the client can find our MAC */
86  if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
87  arphdr = iob->data;
88  if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
89  arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
90  arphdr->ar_pro != htons ( ETH_P_IP ) ||
91  arphdr->ar_hln != ETH_ALEN ||
92  arphdr->ar_pln != sizeof ( struct in_addr ) ||
93  arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
95  goto bad_packet;
96  }
97 
98  /* Generate an ARP reply */
100  memswap ( arp_sender_pa ( arphdr ), arp_target_pa ( arphdr ), sizeof ( struct in_addr ) );
103 
104  /* Fix up ethernet header */
105  ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
108 
109  netdev_tx ( netdev, iob );
110  continue; /* no need to free iob */
111  }
112 
113  if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
114  goto bad_packet;
115  }
116 
117  /* IP header */
118  if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
119  goto bad_packet;
120  }
121  iphdr = iob->data;
122  iob_pull ( iob, sizeof ( *iphdr ) );
124  goto bad_packet;
125  }
126 
127  /* UDP header */
128  if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
129  goto bad_packet;
130  }
131  udphdr = iob->data;
132  if ( udphdr->dest != source_addr.sin_port ) {
133  goto bad_packet;
134  }
135 
136  /* Learn the remote connection details */
139  dest_addr.sin_port = udphdr->src;
140 
141  /* Payload */
142  payload_len = ntohs ( udphdr->len );
143  if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
144  goto bad_packet;
145  }
146  payload_len -= sizeof ( *udphdr );
147  iob_pull ( iob, sizeof ( *udphdr ) );
148  if ( payload_len > len ) {
149  goto bad_packet;
150  }
151  memcpy ( buf, iob->data, payload_len );
152 
153  free_iob ( iob );
154  return payload_len;
155 
156 bad_packet:
157  free_iob ( iob );
158  }
159  cpu_nap();
160  }
161 }
162 
163 static void gdbudp_send ( const char *buf, size_t len ) {
164  struct io_buffer *iob;
165  struct ethhdr *ethhdr;
166  struct iphdr *iphdr;
167  struct udp_header *udphdr;
168 
169  /* Check that we are connected */
170  if ( dest_addr.sin_port == 0 ) {
171  return;
172  }
173 
175 
176  iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
177  if ( !iob ) {
178  return;
179  }
180 
181  /* Payload */
182  iob_reserve ( iob, sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) );
183  memcpy ( iob_put ( iob, len ), buf, len );
184 
185  /* UDP header */
186  udphdr = iob_push ( iob, sizeof ( *udphdr ) );
187  udphdr->src = source_addr.sin_port;
188  udphdr->dest = dest_addr.sin_port;
189  udphdr->len = htons ( iob_len ( iob ) );
190  udphdr->chksum = 0; /* optional and we are not using it */
191 
192  /* IP header */
193  iphdr = iob_push ( iob, sizeof ( *iphdr ) );
194  memset ( iphdr, 0, sizeof ( *iphdr ) );
195  iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
196  iphdr->service = IP_TOS;
197  iphdr->len = htons ( iob_len ( iob ) );
198  iphdr->ttl = IP_TTL;
199  iphdr->protocol = IP_UDP;
202  iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
203 
204  /* Ethernet header */
205  ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
209 
210  netdev_tx ( netdev, iob );
211 }
212 
213 struct gdb_transport *gdbudp_configure ( const char *name, struct sockaddr_in *addr ) {
214  struct settings *settings;
215 
216  /* Release old network device */
217  netdev_put ( netdev );
218 
219  netdev = find_netdev ( name );
220  if ( !netdev ) {
221  return NULL;
222  }
223 
224  /* Hold network device */
225  netdev_get ( netdev );
226 
227  /* Source UDP port */
228  source_addr.sin_port = ( addr && addr->sin_port ) ? addr->sin_port : htons ( DEFAULT_PORT );
229 
230  /* Source IP address */
231  if ( addr && addr->sin_addr.s_addr ) {
232  source_addr.sin_addr.s_addr = addr->sin_addr.s_addr;
233  } else {
235  fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
236  if ( source_addr.sin_addr.s_addr == 0 ) {
237  netdev_put ( netdev );
238  netdev = NULL;
239  return NULL;
240  }
241  }
242 
243  return &udp_gdb_transport;
244 }
245 
246 static int gdbudp_init ( int argc, char **argv ) {
247  if ( argc != 1 ) {
248  printf ( "udp: missing <interface> argument\n" );
249  return 1;
250  }
251 
252  if ( !gdbudp_configure ( argv[0], NULL ) ) {
253  printf ( "%s: device does not exist or has no IP address\n", argv[0] );
254  return 1;
255  }
256  return 0;
257 }
258 
259 struct gdb_transport udp_gdb_transport __gdb_transport = {
260  .name = "udp",
261  .init = gdbudp_init,
262  .send = gdbudp_send,
263  .recv = gdbudp_recv,
264 };
void * memswap(void *first, void *second, size_t len)
Swap memory regions.
Definition: string.c:153
static void gdbudp_send(const char *buf, size_t len)
Definition: gdbudp.c:163
uint16_t h_protocol
Protocol ID.
Definition: if_ether.h:37
static void * arp_sender_pa(struct arphdr *arphdr)
ARP packet sender protocol address.
Definition: if_arp.h:80
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
CPU sleeping.
const char * name
Definition: ath9k_hw.c:1984
#define iob_put(iobuf, len)
Definition: iobuf.h:120
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
uint16_t chksum
Checksum.
Definition: udp.h:37
#define IP_UDP
Definition: in.h:14
static void * arp_target_ha(struct arphdr *arphdr)
ARP packet target hardware address.
Definition: if_arp.h:89
static void * arp_target_pa(struct arphdr *arphdr)
ARP packet target protocol address.
Definition: if_arp.h:98
#define IP_VER
Definition: ip.h:22
struct in_addr src
Definition: ip.h:44
#define iob_push(iobuf, len)
Definition: iobuf.h:84
int fetch_ipv4_setting(struct settings *settings, const struct setting *setting, struct in_addr *inp)
Fetch value of IPv4 address setting.
Definition: settings.c:912
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
const char * name
Transport name.
Definition: gdbstub.h:22
#define ETH_P_IP
Definition: if_ether.h:18
static uint8_t dest_eth[ETH_ALEN]
Definition: gdbudp.c:53
uint16_t chksum
Definition: ip.h:43
IP protocol.
IPv4 socket address.
Definition: in.h:84
#define ntohs(value)
Definition: byteswap.h:136
uint8_t ar_hln
Link-layer address length.
Definition: if_arp.h:59
An IPv4 packet header.
Definition: ip.h:35
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:129
static struct settings * netdev_settings(struct net_device *netdev)
Get per-netdevice configuration settings block.
Definition: netdevice.h:583
uint16_t src
Source port.
Definition: udp.h:31
Address Resolution Protocol constants and types.
uint16_t ar_hrd
Link-layer protocol.
Definition: if_arp.h:52
#define IP_TTL
Definition: ip.h:32
uint16_t len
Length.
Definition: udp.h:35
uint8_t h_dest[ETH_ALEN]
Destination MAC address.
Definition: if_ether.h:33
void * memcpy(void *dest, const void *src, size_t len) __nonnull
static void gdbudp_ensure_netdev_open(struct net_device *netdev)
Definition: gdbudp.c:57
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition: netdevice.h:572
struct gdb_transport udp_gdb_transport __gdb_transport
Definition: gdbudp.c:50
uint16_t len
Definition: ip.h:38
#define ARPOP_REQUEST
ARP request.
Definition: if_arp.h:32
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
static struct net_device * netdev
Definition: gdbudp.c:52
uint8_t verhdrlen
Definition: ip.h:36
An ARP header.
Definition: if_arp.h:47
void netdev_poll(struct net_device *netdev)
Poll for completed and received packets on network device.
Definition: netdevice.c:612
IP address structure.
Definition: in.h:41
uint16_t sin_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition: in.h:93
uint16_t ar_op
ARP opcode.
Definition: if_arp.h:63
static int gdbudp_init(int argc, char **argv)
Definition: gdbudp.c:246
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
A network device.
Definition: netdevice.h:352
#define ARPOP_REPLY
ARP reply.
Definition: if_arp.h:33
int netdev_tx(struct net_device *netdev, struct io_buffer *iobuf)
Transmit raw packet via network device.
Definition: netdevice.c:334
A settings block.
Definition: settings.h:132
unsigned char uint8_t
Definition: stdint.h:10
static struct net_device * netdev_get(struct net_device *netdev)
Get reference to network device.
Definition: netdevice.h:561
uint8_t h_source[ETH_ALEN]
Source MAC address.
Definition: if_ether.h:35
struct in_addr dest
Definition: ip.h:45
#define ETH_ALEN
Definition: if_ether.h:8
static void * arp_sender_ha(struct arphdr *arphdr)
ARP packet sender hardware address.
Definition: if_arp.h:71
unsigned int uint32_t
Definition: stdint.h:12
uint16_t dest
Destination port.
Definition: udp.h:33
struct gdb_transport * gdbudp_configure(const char *name, struct sockaddr_in *addr)
Definition: gdbudp.c:213
static struct sockaddr_in source_addr
Definition: gdbudp.c:55
GDB remote debugging.
uint32_t s_addr
Definition: in.h:42
Network device management.
struct in_addr sin_addr
IPv4 address.
Definition: in.h:100
uint8_t protocol
Definition: ip.h:42
#define iob_reserve(iobuf, len)
Definition: iobuf.h:67
#define IP_TOS
Definition: ip.h:31
void cpu_nap(void)
Sleep with interrupts enabled until next CPU interrupt.
struct net_device * find_netdev(const char *name)
Get network device by name.
Definition: netdevice.c:988
void * data
Start of data.
Definition: iobuf.h:48
u32 addr
Definition: sky2.h:8
uint16_t ar_pro
Network-layer protocol.
Definition: if_arp.h:57
uint8_t ar_pln
Network-layer address length.
Definition: if_arp.h:61
static size_t gdbudp_recv(char *buf, size_t len)
Definition: gdbudp.c:65
GDB remote debugging over UDP.
#define ETH_P_ARP
Definition: if_ether.h:19
uint8_t ll_addr[MAX_LL_ADDR_LEN]
Link-layer address.
Definition: netdevice.h:387
UDP constants.
Definition: udp.h:29
uint8_t ttl
Definition: ip.h:41
#define ARPHRD_ETHER
Ethernet 10Mbps.
Definition: if_arp.h:16
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:203
uint8_t service
Definition: ip.h:37
An Ethernet link-layer header.
Definition: if_ether.h:31
uint32_t len
Length.
Definition: ena.h:14
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
String functions.
A transport mechanism for the GDB protocol.
Definition: gdbstub.h:20
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
#define htons(value)
Definition: byteswap.h:135
UDP protocol.
void * memset(void *dest, int character, size_t len) __nonnull
struct io_buffer * netdev_rx_dequeue(struct net_device *netdev)
Remove packet from device's receive queue.
Definition: netdevice.c:637
A persistent I/O buffer.
Definition: iobuf.h:33
static struct sockaddr_in dest_addr
Definition: gdbudp.c:54