gdbudp.c File Reference

GDB over UDP transport. More...

#include <stdio.h>
#include <string.h>
#include <byteswap.h>
#include <gpxe/iobuf.h>
#include <gpxe/in.h>
#include <gpxe/if_arp.h>
#include <gpxe/if_ether.h>
#include <gpxe/ip.h>
#include <gpxe/udp.h>
#include <gpxe/netdevice.h>
#include <gpxe/nap.h>
#include <gpxe/gdbstub.h>
#include <gpxe/gdbudp.h>

Go to the source code of this file.

Enumerations

enum  { DEFAULT_PORT = 43770 }

Functions

static void gdbudp_ensure_netdev_open (struct net_device *netdev)
static size_t gdbudp_recv (char *buf, size_t len)
static void gdbudp_send (const char *buf, size_t len)
struct gdb_transportgdbudp_configure (const char *name, struct sockaddr_in *addr)
static int gdbudp_init (int argc, char **argv)

Variables

struct gdb_transport
udp_gdb_transport 
__gdb_transport
static struct net_devicenetdev
static uint8_t dest_eth [ETH_ALEN]
static struct sockaddr_in dest_addr
static struct sockaddr_in source_addr


Detailed Description

GDB over UDP transport.

Definition in file gdbudp.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
DEFAULT_PORT 

Definition at line 39 of file gdbudp.c.

00039      {
00040         DEFAULT_PORT = 43770, /* UDP listen port */
00041 };


Function Documentation

static void gdbudp_ensure_netdev_open ( struct net_device netdev  )  [static]

Definition at line 50 of file gdbudp.c.

References assert, and netdev_open().

Referenced by gdbudp_recv(), and gdbudp_send().

00050                                                                     {
00051         /* The device may have been closed between breakpoints */
00052         assert ( netdev );
00053         netdev_open ( netdev );
00054 
00055         /* Strictly speaking, we may need to close the device when leaving the interrupt handler */
00056 }

static size_t gdbudp_recv ( char *  buf,
size_t  len 
) [static]

Definition at line 58 of file gdbudp.c.

References arphdr::ar_hln, arphdr::ar_hrd, arphdr::ar_op, arphdr::ar_pln, arphdr::ar_pro, arp_sender_ha(), arp_sender_pa(), arp_target_ha(), arp_target_pa(), ARPHRD_ETHER, ARPOP_REPLY, ARPOP_REQUEST, cpu_nap(), io_buffer::data, udp_header::dest, iphdr::dest, dest_addr, dest_eth, ETH_ALEN, ETH_P_ARP, ETH_P_IP, free_iob(), gdbudp_ensure_netdev_open(), ethhdr::h_dest, ethhdr::h_protocol, ethhdr::h_source, htons, iob_len(), iob_pull, iob_push, IP_UDP, udp_header::len, net_device::ll_addr, memcpy, netdev_poll(), netdev_rx_dequeue(), netdev_tx(), ntohs, NULL, iphdr::protocol, in_addr::s_addr, sockaddr_in::sin_addr, sockaddr_in::sin_port, source_addr, udp_header::src, and iphdr::src.

00058                                                     {
00059         struct io_buffer *iob;
00060         struct ethhdr *ethhdr;
00061         struct arphdr *arphdr;
00062         struct iphdr *iphdr;
00063         struct udp_header *udphdr;
00064         size_t payload_len;
00065 
00066         gdbudp_ensure_netdev_open ( netdev );
00067 
00068         for ( ; ; ) {
00069                 netdev_poll ( netdev );
00070                 while ( ( iob = netdev_rx_dequeue ( netdev ) ) != NULL ) {
00071                         /* Ethernet header */
00072                         if ( iob_len ( iob ) < sizeof ( *ethhdr ) ) {
00073                                 goto bad_packet;
00074                         }
00075                         ethhdr = iob->data;
00076                         iob_pull ( iob, sizeof ( *ethhdr ) );
00077 
00078                         /* Handle ARP requests so the client can find our MAC */
00079                         if ( ethhdr->h_protocol == htons ( ETH_P_ARP ) ) {
00080                                 arphdr = iob->data;
00081                                 if ( iob_len ( iob ) < sizeof ( *arphdr ) + 2 * ( ETH_ALEN + sizeof ( struct in_addr ) ) ||
00082                                                 arphdr->ar_hrd != htons ( ARPHRD_ETHER ) ||
00083                                                 arphdr->ar_pro != htons ( ETH_P_IP ) ||
00084                                                 arphdr->ar_hln != ETH_ALEN ||
00085                                                 arphdr->ar_pln != sizeof ( struct in_addr ) ||
00086                                                 arphdr->ar_op != htons ( ARPOP_REQUEST ) ||
00087                                                 * ( uint32_t * ) arp_target_pa ( arphdr ) != source_addr.sin_addr.s_addr ) {
00088                                         goto bad_packet;
00089                                 }
00090 
00091                                 /* Generate an ARP reply */
00092                                 arphdr->ar_op = htons ( ARPOP_REPLY );
00093                                 memswap ( arp_sender_pa ( arphdr ), arp_target_pa ( arphdr ), sizeof ( struct in_addr ) );
00094                                 memcpy ( arp_target_ha ( arphdr ), arp_sender_ha ( arphdr ), ETH_ALEN );
00095                                 memcpy ( arp_sender_ha ( arphdr ), netdev->ll_addr, ETH_ALEN );
00096 
00097                                 /* Fix up ethernet header */
00098                                 ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
00099                                 memcpy ( ethhdr->h_dest, ethhdr->h_source, ETH_ALEN );
00100                                 memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
00101 
00102                                 netdev_tx ( netdev, iob );
00103                                 continue; /* no need to free iob */
00104                         }
00105 
00106                         if ( ethhdr->h_protocol != htons ( ETH_P_IP ) ) {
00107                                 goto bad_packet;
00108                         }
00109 
00110                         /* IP header */
00111                         if ( iob_len ( iob ) < sizeof ( *iphdr ) ) {
00112                                 goto bad_packet;
00113                         }
00114                         iphdr = iob->data;
00115                         iob_pull ( iob, sizeof ( *iphdr ) );
00116                         if ( iphdr->protocol != IP_UDP || iphdr->dest.s_addr != source_addr.sin_addr.s_addr ) {
00117                                 goto bad_packet;
00118                         }
00119 
00120                         /* UDP header */
00121                         if ( iob_len ( iob ) < sizeof ( *udphdr ) ) {
00122                                 goto bad_packet;
00123                         }
00124                         udphdr = iob->data;
00125                         if ( udphdr->dest != source_addr.sin_port ) {
00126                                 goto bad_packet;
00127                         }
00128 
00129                         /* Learn the remote connection details */
00130                         memcpy ( dest_eth, ethhdr->h_source, ETH_ALEN );
00131                         dest_addr.sin_addr.s_addr = iphdr->src.s_addr;
00132                         dest_addr.sin_port = udphdr->src;
00133 
00134                         /* Payload */
00135                         payload_len = ntohs ( udphdr->len );
00136                         if ( payload_len < sizeof ( *udphdr ) || payload_len > iob_len ( iob ) ) {
00137                                 goto bad_packet;
00138                         }
00139                         payload_len -= sizeof ( *udphdr );
00140                         iob_pull ( iob, sizeof ( *udphdr ) );
00141                         if ( payload_len > len ) {
00142                                 goto bad_packet;
00143                         }
00144                         memcpy ( buf, iob->data, payload_len );
00145 
00146                         free_iob ( iob );
00147                         return payload_len;
00148 
00149 bad_packet:
00150                         free_iob ( iob );
00151                 }
00152                 cpu_nap();
00153         }
00154 }

static void gdbudp_send ( const char *  buf,
size_t  len 
) [static]

Definition at line 156 of file gdbudp.c.

References alloc_iob(), iphdr::chksum, udp_header::chksum, iphdr::dest, udp_header::dest, dest_addr, dest_eth, ETH_ALEN, ETH_P_IP, gdbudp_ensure_netdev_open(), ethhdr::h_dest, ethhdr::h_protocol, ethhdr::h_source, htons, iob_len(), iob_push, iob_put, iob_reserve, IP_TOS, IP_TTL, IP_UDP, IP_VER, iphdr::len, udp_header::len, net_device::ll_addr, memcpy, memset(), netdev_tx(), iphdr::protocol, in_addr::s_addr, iphdr::service, sockaddr_in::sin_addr, sockaddr_in::sin_port, source_addr, iphdr::src, udp_header::src, tcpip_chksum(), iphdr::ttl, and iphdr::verhdrlen.

00156                                                         {
00157         struct io_buffer *iob;
00158         struct ethhdr *ethhdr;
00159         struct iphdr *iphdr;
00160         struct udp_header *udphdr;
00161 
00162         /* Check that we are connected */
00163         if ( dest_addr.sin_port == 0 ) {
00164                 return;
00165         }
00166 
00167         gdbudp_ensure_netdev_open ( netdev );
00168 
00169         iob = alloc_iob ( sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) + len );
00170         if ( !iob ) {
00171                 return;
00172         }
00173 
00174         /* Payload */
00175         iob_reserve ( iob, sizeof ( *ethhdr ) + sizeof ( *iphdr ) + sizeof ( *udphdr ) );
00176         memcpy ( iob_put ( iob, len ), buf, len );
00177 
00178         /* UDP header */
00179         udphdr = iob_push ( iob, sizeof ( *udphdr ) );
00180         udphdr->src = source_addr.sin_port;
00181         udphdr->dest = dest_addr.sin_port;
00182         udphdr->len = htons ( iob_len ( iob ) );
00183         udphdr->chksum = 0; /* optional and we are not using it */
00184 
00185         /* IP header */
00186         iphdr = iob_push ( iob, sizeof ( *iphdr ) );
00187         memset ( iphdr, 0, sizeof ( *iphdr ) );
00188         iphdr->verhdrlen = ( IP_VER | ( sizeof ( *iphdr ) / 4 ) );
00189         iphdr->service = IP_TOS;
00190         iphdr->len = htons ( iob_len ( iob ) ); 
00191         iphdr->ttl = IP_TTL;
00192         iphdr->protocol = IP_UDP;
00193         iphdr->dest.s_addr = dest_addr.sin_addr.s_addr;
00194         iphdr->src.s_addr = source_addr.sin_addr.s_addr;
00195         iphdr->chksum = tcpip_chksum ( iphdr, sizeof ( *iphdr ) );
00196 
00197         /* Ethernet header */
00198         ethhdr = iob_push ( iob, sizeof ( *ethhdr ) );
00199         memcpy ( ethhdr->h_dest, dest_eth, ETH_ALEN );
00200         memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
00201         ethhdr->h_protocol = htons ( ETH_P_IP );
00202 
00203         netdev_tx ( netdev, iob );
00204 }

struct gdb_transport* gdbudp_configure ( const char *  name,
struct sockaddr_in addr 
) [read]

Definition at line 206 of file gdbudp.c.

References DEFAULT_PORT, fetch_ipv4_setting(), find_netdev(), htons, netdev_get(), netdev_put(), netdev_settings(), NULL, in_addr::s_addr, sockaddr_in::sin_addr, sockaddr_in::sin_port, and source_addr.

Referenced by gdbudp_init().

00206                                                                                       {
00207         struct settings *settings;
00208 
00209         /* Release old network device */
00210         netdev_put ( netdev );
00211 
00212         netdev = find_netdev ( name );
00213         if ( !netdev ) {
00214                 return NULL;
00215         }
00216 
00217         /* Hold network device */
00218         netdev_get ( netdev );
00219 
00220         /* Source UDP port */
00221         source_addr.sin_port = ( addr && addr->sin_port ) ? addr->sin_port : htons ( DEFAULT_PORT );
00222 
00223         /* Source IP address */
00224         if ( addr && addr->sin_addr.s_addr ) {
00225                 source_addr.sin_addr.s_addr = addr->sin_addr.s_addr;
00226         } else {
00227                 settings = netdev_settings ( netdev );
00228                 fetch_ipv4_setting ( settings, &ip_setting, &source_addr.sin_addr );
00229                 if ( source_addr.sin_addr.s_addr == 0 ) {
00230                         netdev_put ( netdev );
00231                         netdev = NULL;
00232                         return NULL;
00233                 }
00234         }
00235 
00236         return &udp_gdb_transport;
00237 }

static int gdbudp_init ( int  argc,
char **  argv 
) [static]

Definition at line 239 of file gdbudp.c.

References gdbudp_configure(), NULL, and printf().

00239                                                  {
00240         if ( argc != 1 ) {
00241                 printf ( "udp: missing <interface> argument\n" );
00242                 return 1;
00243         }
00244 
00245         if ( !gdbudp_configure ( argv[0], NULL ) ) {
00246                 printf ( "%s: device does not exist or has no IP address\n", argv[0] );
00247                 return 1;
00248         }
00249         return 0;
00250 }


Variable Documentation

struct gdb_transport udp_gdb_transport __gdb_transport [read]

Initial value:

 {
        .name = "udp",
        .init = gdbudp_init,
        .send = gdbudp_send,
        .recv = gdbudp_recv,
}

Definition at line 43 of file gdbudp.c.

struct net_device* netdev [static]

uint8_t dest_eth[ETH_ALEN] [static]

Definition at line 46 of file gdbudp.c.

Referenced by gdbudp_recv(), and gdbudp_send().

struct sockaddr_in dest_addr [static]

Definition at line 47 of file gdbudp.c.

Referenced by gdbudp_recv(), and gdbudp_send().

struct sockaddr_in source_addr [static]

Definition at line 48 of file gdbudp.c.

Referenced by gdbudp_configure(), gdbudp_recv(), and gdbudp_send().


Generated on Tue Apr 6 20:01:14 2010 for gPXE by  doxygen 1.5.7.1