ãããããã®å®è£ ãžã®ã¢ãããŒãã¯ã第äžã«ãããã ãã§ã¯ãªãã第äºã«ãç¶æ³ã«ãã£ãŠã¯åãå ¥ããããªãå ŽåããããŸãïŒããšãã°ãnetdev_rx_handler_registerïŒïŒããŸã åŒã³åºãããŠããªã2.6.36ãããè¥ãã«ãŒãã«ãåããçµã¿èŸŒã¿ã·ã¹ãã ïŒã 以äžã§ã¯ãåãæ©èœãåãã代æ¿æ¡ãæ€èšããŸãããTCP / IPãããã¯ãŒã¯ã¹ã¿ãã¯ã®ãŸã£ããç°ãªãå±€ã«å®è£ ããŸãã
ãããã¯ãŒã¯å±€ãããã³ã«
ç¹°ãè¿ããªãããã«ãTCP / IPãããã¯ãŒã¯ã¹ã¿ãã¯ã®ã¬ãã«ïŒã¬ã€ã€ãŒïŒã¯OSI / ISOãªãŒãã³ãœãŒã¹ã·ã¹ãã çžäºäœçšã¢ãã«ã®7ã€ã®ã¬ãã«ïŒãŸãã¯ãããæ£çŽã«èšããšãåŠçã®äžå¿ã«è¿ãOSIã¢ãã«ïŒã«æ確ã«å¯Ÿå¿ããŠããªããšæžãããŠããŸãäžé©åã«é²åããŠããTCP / IPãããã¯ãŒã¯ïŒã åè¿°ã®å®è£ ã®ä»®æ³ã€ã³ã¿ãŒãã§ã€ã¹ã®äœæã¯ã ã€ã³ã¿ãŒãã§ã€ã¹ã¬ãã«ïŒL2ãã¬ãã«2-OSIãã£ãã«ã¬ãã«ã«ã»ãŒå¯Ÿå¿ïŒã§å®è¡ãããŸããã çŸåšã®å®è£ ã§ã¯ã ãããã¯ãŒã¯å±€ïŒL3ïŒã®æ©èœã䜿çšããŠããŸãã
ãããã¯ãŒã¯ã¬ãã«ã®ããŒã«ã«é¢ããŠãçŸåšã®ã¿ã¹ã¯ã«å¿ èŠãªãã®ããããããã«åºãããªã¥ãŒã ã§ããããªãæ¡åŒµã®å¯èœæ§ã®ããã«ãäžå®ã®æå°å€ãèæ ®ããããšãé©åãšæãããŸãã ãããã¯ãŒã¯ã¬ãã«ã§ã¯ããããã¯ãŒã¯ãããã³ã«ã®ã¹ã¿ãã¯ïŒTCP / IPã ãã§ãªããä»ã®ãã¹ãŠã®ãããã³ã«ãã¡ããªãããã§ãµããŒããããŠããŸãããä»æ¥ã§ã¯ã»ãšãã©é¢ä¿ããªãããã§ãïŒãIP / IPv4 / IPv6ãIPXãIGMPãRIPãªã©ã®ãããã³ã«ã®åŠç ã OSPFãARPããŸãã¯å ã®ãŠãŒã¶ãŒãããã³ã«ã®è¿œå ã ãããã¯ãŒã¯ã¬ãã«ã®ãã³ãã©ãŒãã€ã³ã¹ããŒã«ããã«ã¯ããããã¯ãŒã¯ã¬ãã«ã®APIïŒ<linux / netdevice.h>ïŒãæäŸãããŸãã
struct packet_type { __be16 type; /* This is really htons(ether_type). */ struct net_device *dev; /* NULL is wildcarded here */ int (*func) (struct sk_buff*, struct net_device*, struct packet_type*, struct net_device*); ... struct list_head list; }; extern void dev_add_pack( struct packet_type *pt ); extern void dev_remove_pack( struct packet_type *pt );
å®éãã«ãŒãã«ã®ãããã³ã«ã¢ãžã¥ãŒã«ã§ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®å ¥åã¹ããªãŒã ãããœã±ãããããã¡ãŒãééãããã£ã«ã¿ãŒãè¿œå ããå¿ èŠããããŸãïŒåã®å®è£ ã§ç€ºããããã«ãåºåã¹ããªãŒã ã¯ããç°¡åã«å®è£ ãããŸãïŒã dev_add_packïŒïŒé¢æ°ã¯ãfuncïŒïŒé¢æ°ã«ãã£ãŠå®è£ ããããæå®ãããã¿ã€ãã®ããã±ãŒãžã«å¥ã®æ°ãããã³ãã©ãŒãè¿œå ããŸãã ãã®é¢æ°ã¯ãæ¢åã®ãã³ãã©ãŒïŒLinuxãããã¯ãŒã¯ã·ã¹ãã ã®ããã©ã«ããã³ãã©ãŒãå«ãïŒãè¿œå ããŸããã眮ãæããŸãã ã åŠçã®ããã«ããã®é¢æ°ã¯ãstruct packet_typeæ§é äœã«èŠå®ãããåºæºãæºãããœã±ãããããã¡ãŒãéžæïŒååŸïŒããŸãïŒãããã³ã«ã¿ã€ãããã³ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹devã®ã¿ã€ãã«å¿ããŠïŒã
泚ïŒåãæ¹æ³ïŒãã£ã«ã¿ãŒæ©èœã®èšå®ïŒã§ããããã¯ãŒã¯ã¹ã¿ãã¯ã®ããé«ããã©ã³ã¹ããŒãã¬ãã«ã§æ°ãããããã³ã«ãè¿œå ãããŸãïŒããšãã°ãUDPãTCPãSCTPãããã³ã«ãåŠçãããŸãïŒã ãã¹ãŠã®ããé«ãã¬ãã«ïŒOSIã¢ãã«ã®ã¬ãã«ãšã»ãŒåãïŒã¯ãã«ãŒãã«ã§ã¯è¡šçŸããããBSDãœã±ããããã°ã©ãã³ã°æè¡ã«ãã£ãŠãŠãŒã¶ãŒç©ºéã§æäŸãããŸãã ãããããããã®é«ã¬ãã«ã®è©³çŽ°ã¯ãã¹ãŠæ¬æã§ã¯èæ ®ãããªããªããŸãã
æ°ãããããã³ã«ïŒç¬èªä»æ§ïŒãè¿œå ããå Žåã¯ããã®ã¿ã€ããåå®çŸ©ããå¿ èŠããããŸãã
#define PROTO_ID 0x1234 static struct packet_type test_proto = { __constant_htons( PROT_ID ), ... }
åé¡ã¯ãæšæºã®IPã¹ã¿ãã¯ããã®ãããªãããã³ã«ãèªèããŠããªãããšã§ããããã¹ãŠã®åŠçãåŠçããå¿ èŠããããŸãã ããããç§ãã¡ã®ç®æšã¯ãäžéšã®ãã±ããã®åŠçãåå®çŸ©ããããšã ãã§ãããã®ãããå®æ°ETH_P_ALLã䜿çšãããã¹ãŠã®ãããã³ã«ããã£ã«ã¿ãŒãééããããšã瀺ããŸãïŒdevãã£ãŒã«ããNULLã®å Žåããã¹ãŠã®ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ãééããå¿ èŠããããŸãïŒã
æ¯èŒãšå ·äœåã®ããã«ãå€æ°ã®ãããã³ã«èå¥åïŒã€ãŒãµããããããã³ã«IDïŒã<linux / if_ether.h>ã«ãããŸãã以äžã«äŸã瀺ããŸãã
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ ...
ãã®å Žåãã¿ã€ããã£ãŒã«ãã¯ããã°ã©ã ã³ãŒãã®æœè±¡çãªæ°å€ã§ã¯ãããŸããããã€ããªåœ¢åŒã®ãã®å€ã¯ãé ä¿¡ç°å¢ã«ç©ççã«éä¿¡ããããã¬ãŒã ã®ã€ãŒãµãããããããŒã«å ¥åãããŸãã
struct ethhdr { unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ unsigned char h_source[ETH_ALEN]; /* source ether addr */ __be16 h_proto; /* packet type ID field */ } __attribute__((packed));
ïŒã¢ãžã¥ãŒã«ã®struct packet_typeæ§é äœã«å ¥åãããšããã³ãŒãã«åã説æãå¿ èŠã§ãïŒã
ãã£ã«ã¿ãŒé¢æ°èªäœïŒfuncãã£ãŒã«ãïŒã¯ãããããæãç°¡åãªåœ¢åŒã§ã¯ãŸã èšè¿°ããŠããŸãããã次ã®ãããªãã®ã§ãã
int test_pack_rcv( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *odev ) { LOG( "packet received with length: %u\n", skb->len ); kfree_skb( skb ); return skb->len; };
ããã§ã¯ãäž»ã«kfree_skbïŒïŒã®åŒã³åºããå¿ é ã§ãããããé¢æ°ã瀺ãããŠããŸãã éä¿¡ãã£ãã«ã®dev_kfree_skbïŒïŒã®æå³ã§äžèŠè¿ããšã¯ç°ãªãããœã±ãããããã¡ãç Žå£ãã ããã®äœ¿çšã«ãŠã³ã¿ïŒusersãã£ãŒã«ãïŒãæžå°ãããã ãã§ãã è¿œå ã®åãããã³ã«ãã£ã«ã¿ãŒãdev_add_packïŒïŒãåŒã³åºããŠèšå®ããããšããã®ãœã±ãããããã¡ãŒãã£ãŒã«ããã€ã³ã¯ãªã¡ã³ããããŸãã è€æ°ã®ãããã¯ãŒã¯ã¬ãã«ã®ãã£ã«ã¿ãŒãïŒåããã®ããŸãã¯è€æ°ã®ããŒãå¯èœãªã¢ãžã¥ãŒã«ã«ïŒã€ã³ã¹ããŒã«ã§ããã€ã³ã¹ããŒã«ã®éã®é åºã§æ©èœããŸããããããããkfree_skbïŒïŒãå®è¡ããå¿ èŠããããŸãã ããããªããšããããã¯ãŒã¯ã¹ã¿ãã¯ã§ãã£ããã§ããå®å®ããã¡ã¢ãªãªãŒã¯ãçºçãããããã·ã¹ãã ã¯ã©ãã·ã¥ã®ãããªçµæã¯ãæ°æéã®é£ç¶æäœåŸã«ã®ã¿æ€åºãããŸãã
ããã¯éåžžã«èå³æ·±ãå Žæã§ãããæããã§ã¯ãããŸããããã®ãããkfree_skbïŒïŒïŒfile net / core / skbuff.cïŒã®å®è£ ã®ãœãŒã¹ã³ãŒãã泚ææ£æŒ«ã«ããŠèŠãã®ãçã«ããªã£ãŠããŸãã
void kfree_skb(struct sk_buff *skb) { if (unlikely(!skb)) return; if (likely(atomic_read(&skb->users) == 1)) smp_rmb(); else if (likely(!atomic_dec_and_test(&skb->users))) return; trace_kfree_skb(skb, __builtin_return_address(0)); __kfree_skb(skb); }
kfree_skbïŒïŒãåŒã³åºããšãskb-> users == 1ã®å Žåã«ã®ã¿å®éã«ãœã±ãããããã¡ãŒã解æŸãããä»ã®ãã¹ãŠã®å€ã§ã¯ãskb-> usersïŒäœ¿çšéã«ãŠã³ã¿ãŒïŒã ããæžå°ããŸãã
ããã§ãä»®æ³ã€ã³ã¿ãŒãã§ã€ã¹ã®æäœãæŽçããã®ã«ååãªè©³çŽ°ãåŸãããŸããããä»åã¯IPã¹ã¿ãã¯ã®ãããã¯ãŒã¯å±€ã䜿çšããŠããŸãã
ä»®æ³ã€ã³ã¿ãŒãã§ãŒã¹ã¢ãžã¥ãŒã«
以åã®ããã«é²ã¿ãŸãïŒã¢ãžã¥ãŒã«ã®2ã€ã®ããŒãžã§ã³ãäœæããŸã-ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ãŒã¹ïŒvirt0ïŒ ã芪ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ãŒã¹ã«çœ®ãæãã virtl.koã®ç°¡æããŒãžã§ã³ãšããããã¯ãŒã¯ãããã³ã«ãã¬ãŒã ïŒARPããã³IP4ïŒãåæãããã®ãã©ãã£ãã¯ã®ã¿ã«åœ±é¿ããvirt.koã®ãã«ããŒãžã§ã³ããã¯ãã®ã€ã³ã¿ãŒãã§ãŒã¹ã«é¢é£ããŠããŸãã éãã¯ãç°¡ç¥åãããã¢ãžã¥ãŒã«ã®ããŒãäžã芪ã€ã³ã¿ãŒãã§ãŒã¹ãäžæçã«åäœãåæ¢ããããšã§ãïŒvirtl.koã¢ãžã¥ãŒã«ãã¢ã³ããŒãããããŸã§ïŒããã«ããŒãžã§ã³ãããŒãããå Žåãäž¡æ¹ã®ã€ã³ã¿ãŒãã§ãŒã¹ã䞊è¡ããŠç¬ç«ããŠåäœã§ããŸãã å®å šãªã¢ãžã¥ãŒã«ã®ã³ãŒãã¯æããã«é¢åã§ãããååãç解ããããã«äœãè¿œå ããŸããã 次ã«ãååã瀺ãç°¡ç¥çã詳现ã«æ€èšããŸãããåŸã«ãªã£ãŠããå®å šçã«æäœé觊ããŸãïŒãã®ã³ãŒããšãã¹ãã¬ããŒãã¯ãµã³ãã«ã¢ãŒã«ã€ãã«èšèŒãããŠããŸãïŒã
ããã¯ããªãé·ãã³ãŒãã§ã
#include <linux/module.h> #include <linux/version.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/inetdevice.h> #include <linux/moduleparam.h> #include <net/arp.h> #include <linux/ip.h> #define ERR(...) printk( KERN_ERR "! "__VA_ARGS__ ) #define LOG(...) printk( KERN_INFO "! "__VA_ARGS__ ) #define DBG(...) if( debug != 0 ) printk( KERN_INFO "! "__VA_ARGS__ ) static char* link = "eth0"; module_param( link, charp, 0 ); static char* ifname = "virt"; module_param( ifname, charp, 0 ); static int debug = 0; module_param( debug, int, 0 ); static struct net_device *child = NULL; static struct net_device_stats stats; // static u32 child_ip; struct priv { struct net_device *parent; }; static char* strIP( u32 addr ) { // IP static char saddr[ MAX_ADDR_LEN ]; sprintf( saddr, "%d.%d.%d.%d", ( addr ) & 0xFF, ( addr >> 8 ) & 0xFF, ( addr >> 16 ) & 0xFF, ( addr >> 24 ) & 0xFF ); return saddr; } static int open( struct net_device *dev ) { struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa = in_dev->ifa_list; /* IP ifaddr chain */ LOG( "%s: device opened", dev->name ); child_ip = ifa->ifa_address; netif_start_queue( dev ); if( debug != 0 ) { char sdebg[ 40 ] = ""; sprintf( sdebg, "%s:", strIP( ifa->ifa_address ) ); strcat( sdebg, strIP( ifa->ifa_mask ) ); DBG( "%s: %s", dev->name, sdebg ); } return 0; } static int stop( struct net_device *dev ) { LOG( "%s: device closed", dev->name ); netif_stop_queue( dev ); return 0; } static struct net_device_stats *get_stats( struct net_device *dev ) { return &stats; } // static netdev_tx_t start_xmit( struct sk_buff *skb, struct net_device *dev ) { struct priv *priv = netdev_priv( dev ); stats.tx_packets++; stats.tx_bytes += skb->len; skb->dev = priv->parent; // () skb->priority = 1; dev_queue_xmit( skb ); DBG( "tx: injecting frame from %s to %s with length: %u", dev->name, skb->dev->name, skb->len ); return 0; return NETDEV_TX_OK; } static struct net_device_ops net_device_ops = { .ndo_open = open, .ndo_stop = stop, .ndo_get_stats = get_stats, .ndo_start_xmit = start_xmit, }; // int pack_parent( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *odev ) { skb->dev = child; // stats.rx_packets++; stats.rx_bytes += skb->len; DBG( "tx: injecting frame from %s to %s with length: %u", dev->name, skb->dev->name, skb->len ); kfree_skb( skb ); return skb->len; }; static struct packet_type proto_parent = { __constant_htons( ETH_P_ALL ), // : ETH_P_ARP & ETH_P_IP NULL, pack_parent, (void*)1, NULL }; int __init init( void ) { void setup( struct net_device *dev ) { // ( GCC) int j; ether_setup( dev ); memset( netdev_priv( dev ), 0, sizeof( struct priv ) ); dev->netdev_ops = &net_device_ops; for( j = 0; j < ETH_ALEN; ++j ) // MAC dev->dev_addr[ j ] = (char)j; } int err = 0; struct priv *priv; char ifstr[ 40 ]; sprintf( ifstr, "%s%s", ifname, "%d" ); #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)) child = alloc_netdev( sizeof( struct priv ), ifstr, setup ); #else child = alloc_netdev( sizeof( struct priv ), ifstr, NET_NAME_UNKNOWN, setup ); #endif if( child == NULL ) { ERR( "%s: allocate error", THIS_MODULE->name ); return -ENOMEM; } priv = netdev_priv( child ); priv->parent = dev_get_by_name( &init_net, link ); // if( !priv->parent ) { ERR( "%s: no such net: %s", THIS_MODULE->name, link ); err = -ENODEV; goto err; } if( priv->parent->type != ARPHRD_ETHER && priv->parent->type != ARPHRD_LOOPBACK ) { ERR( "%s: illegal net type", THIS_MODULE->name ); err = -EINVAL; goto err; } memcpy( child->dev_addr, priv->parent->dev_addr, ETH_ALEN ); memcpy( child->broadcast, priv->parent->broadcast, ETH_ALEN ); if( ( err = dev_alloc_name( child, child->name ) ) ) { ERR( "%s: allocate name, error %i", THIS_MODULE->name, err ); err = -EIO; goto err; } register_netdev( child ); // proto_parent.dev = priv->parent; dev_add_pack( &proto_parent ); // LOG( "module %s loaded", THIS_MODULE->name ); LOG( "%s: create link %s", THIS_MODULE->name, child->name ); return 0; err: free_netdev( child ); return err; } void __exit virt_exit( void ) { struct priv *priv= netdev_priv( child ); dev_remove_pack( &proto_parent ); // unregister_netdev( child ); dev_put( priv->parent ); free_netdev( child ); LOG( "module %s unloaded", THIS_MODULE->name ); LOG( "=============================================" ); } module_init( init ); module_exit( virt_exit ); MODULE_AUTHOR( "Oleg Tsiliuric" ); MODULE_LICENSE( "GPL v2" ); MODULE_VERSION( "3.7" );
ãã¹ãŠãéåžžã«éæã§ãïŒ
- æ°ãããããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ïŒvirt0ïŒãç»é²ããåŸãdev_add_packïŒïŒãåŒã³åºããŸããããã«ããã芪ã€ã³ã¿ãŒãã§ã€ã¹ã®ãã±ãããã£ã«ã¿ãŒãèšå®ãããŸãã
- devãã£ãŒã«ãã¯packet_typeæ§é äœã§èŠªã€ã³ã¿ãŒãã§ãŒã¹ãã€ã³ã¿ãŒã«äºåèšå®ãããŠããŸãããã®ã€ã³ã¿ãŒãã§ãŒã¹ããã®ã¿ãæ§é äœã§å®çŸ©ãããpack_parentïŒïŒé¢æ°ã«ãã£ãŠçä¿¡ãã©ãã£ãã¯ãã€ã³ã¿ãŒã»ãããããŸãã
- ãã®é¢æ°ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®çµ±èšæ å ±ããã£ããã£ããæãéèŠãªããšãšããŠã芪ã€ã³ã¿ãŒãã§ã€ã¹ãã€ã³ã¿ããœã±ãããããã¡å ã®ä»®æ³ã€ã³ã¿ãŒãã§ã€ã¹ãã€ã³ã¿ã«çœ®ãæããŸãã
- ïŒä»®æ³ããç©çãžã®ïŒé眮æã¯ããã¬ãŒã éä¿¡é¢æ°start_xmitïŒïŒã§çºçããŸãã
ä»çµã¿ã¯æ¬¡ã®ãšããã§ãã
- ãã¹ãããã³ã³ãã¥ãŒã¿ãŒã§ãã¢ãžã¥ãŒã«ãããŒãããå¥ã®æ°ãããµããããã§æ§æããŸãã
$ ip address ... 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:52:b9:e0 brd ff:ff:ff:ff:ff:ff inet 192.168.1.21/24 brd 192.168.1.255 scope global eth0 inet6 fe80::a00:27ff:fe52:b9e0/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:0f:13:6d brd ff:ff:ff:ff:ff:ff inet 192.168.56.102/24 brd 192.168.56.255 scope global eth1 inet6 fe80::a00:27ff:fe0f:136d/64 scope link valid_lft forever preferred_lft forever $ sudo insmod virt.ko link=eth1 debug=1 $ sudo ifconfig virt0 192.168.50.19 $ sudo ifconfig virt0 virt0 Link encap:Ethernet HWaddr 08:00:27:0f:13:6d inet addr:192.168.50.19 Bcast:192.168.50.255 Mask:255.255.255.0 inet6 addr: fe80::a00:27ff:fe0f:136d/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:46 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:8373 (8.1 KiB)
ïŒããã¯ãã€ã³ã¿ãŒãã§ãŒã¹ã§åä¿¡ãããŒããã€ãã®çµ±èšã瀺ããŠããŸãïŒã - ãã¹ã察象ã®ã³ã³ãã¥ãŒã¿ãŒã§ãæ°ãããµããããïŒ192.168.50.0/24ïŒã®ãšã€ãªã¢ã¹IPãäœæããäœæããã€ã³ã¿ãŒãã§ã€ã¹ãžã®ãã©ãã£ãã¯ãå®è¡ã§ããŸãã
$ sudo ifconfig vboxnet0:1 192.168.50.1 $ ping 192.168.50.19 PING 192.168.50.19 (192.168.50.19) 56(84) bytes of data. 64 bytes from 192.168.50.19: icmp_req=1 ttl=64 time=0.627 ms 64 bytes from 192.168.50.19: icmp_req=2 ttl=64 time=0.305 ms 64 bytes from 192.168.50.19: icmp_req=3 ttl=64 time=0.326 ms ^C --- 192.168.50.19 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.305/0.419/0.627/0.148 ms
- åãïŒãã¹ãïŒã³ã³ãã¥ãŒã¿ãŒïŒæ»ãåŽïŒã§ãtcpdumpã«ãã£ãŠä¿®æ£ããããã©ãã£ãã¯ãïŒå¥ã®ç«¯æ«ã§ïŒèŠ³å¯ããããšã¯éåžžã«æçã§ãã
$ sudo tcpdump -i vboxnet0 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on vboxnet0, link-type EN10MB (Ethernet), capture size 65535 bytes ... 18:41:01.740607 ARP, Request who-has 192.168.50.19 tell 192.168.50.1, length 28 18:41:01.741104 ARP, Reply 192.168.50.19 is-at 08:00:27:0f:13:6d (oui Unknown), length 28 18:41:01.741116 IP 192.168.50.1 > 192.168.50.19: ICMP echo request, id 8402, seq 1, length 64 18:41:01.741211 IP 192.168.50.19 > 192.168.50.1: ICMP echo reply, id 8402, seq 1, length 64 18:41:02.741164 IP 192.168.50.1 > 192.168.50.19: ICMP echo request, id 8402, seq 2, length 64 18:41:02.741451 IP 192.168.50.19 > 192.168.50.1: ICMP echo reply, id 8402, seq 2, length 64 18:41:03.741163 IP 192.168.50.1 > 192.168.50.19: ICMP echo request, id 8402, seq 3, length 64 18:41:03.741471 IP 192.168.50.19 > 192.168.50.1: ICMP echo reply, id 8402, seq 3, length 64 18:41:06.747701 ARP, Request who-has 192.168.50.1 tell 192.168.50.19, length 28 18:41:06.747715 ARP, Reply 192.168.50.1 is-at 0a:00:27:00:00:00 (oui Unknown), length 28
æ©äŒã®æ¡å€§
ç°¡æœã«ãç°¡åã«èšãã°ãç¬èªã®ãã©ãã£ãã¯ã§ã®ã¿åäœãã芪ã€ã³ã¿ãŒãã§ã€ã¹ã®åäœãäžæããªãæ¬æ Œçãªä»®æ³ã€ã³ã¿ãŒãã§ã€ã¹ãäœæããæ¹æ³ã«ã€ããŠïŒã¢ãžã¥ãŒã«ã®ãã«ããŒãžã§ã³ãã¢ãŒã«ã€ãã§è¡ãããšïŒã ãããè¡ãã«ã¯ã以äžãè¡ãå¿ èŠããããŸãã
- 2ã€ã®å¥åã®ãããã³ã«ãã³ãã©ãŒã宣èšããŸãïŒARPåå解決ãããã³ã«ãšIPãããã³ã«èªäœçšïŒïŒ
// ETH_P_ARP int arp_pack_rcv( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *odev ) { ... return skb->len; }; static struct packet_type arp_proto = { __constant_htons( ETH_P_ARP ), NULL, arp_pack_rcv, // ETH_P_ARP (void*)1, NULL }; // ETH_P_IP int ip4_pack_rcv( struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *odev ) { ... return skb->len; }; static struct packet_type ip4_proto = { __constant_htons( ETH_P_IP ), NULL, ip4_pack_rcv, // ETH_P_IP (void*)1, NULL };
- ã©ã¡ããã¢ãžã¥ãŒã«åæåé¢æ°ã«é çªã«ç»é²ãããŸãïŒ
arp_proto.dev = ip4_proto.dev = priv->parent; // dev_add_pack( &arp_proto ); dev_add_pack( &ip4_proto );
- ã€ã³ã¹ããŒã«ãããåãã£ã«ã¿ãŒã¯ãåä¿¡è IPãã€ã³ã¿ãŒãã§ã€ã¹ã®IPãšäžèŽãããã¬ãŒã ã«å¯ŸããŠã®ã¿ã€ã³ã¿ãŒãã§ã€ã¹ã¹ããŒãã£ã³ã°ãå®è¡ããå¿ èŠããããŸã...
- 2ã€ã®å¥åã®ãã³ãã©ãŒã¯ãARPãã¬ãŒã ãšIPãã¬ãŒã ã®ããããŒã®åœ¢åŒããŸã£ããç°ãªããããå®å IPãç°ãªãæ¹æ³ã§å²ãåœãŠãå¿ èŠããããšããç¹ã§äŸ¿å©ã§ãïŒãã¹ãŠã®ã³ãŒãã¯ã¢ãŒã«ã€ãã®äŸã«ç€ºãããŠããŸãïŒã
ãã®ãããªãã«ãŠã§ã€ãã¢ãžã¥ãŒã«ã䜿çšãããšãããšãã°ãç°ãªãã€ã³ã¿ãŒãã§ã€ã¹äžã§ïŒç°ãªãIPã䜿çšããŠïŒ2ã€ã®äžŠåSSHã»ãã·ã§ã³ãéãããšãã§ããå®éã«ã¯åäžã®å ±éç©çã€ã³ã¿ãŒãã§ã€ã¹ã䞊åã«äœ¿çšããŸãã
$ ssh olej@192.168.50.17 olej@192.168.50.17's password: Last login: Mon Jul 16 15:52:16 2012 from 192.168.1.9 ... $ ssh olej@192.168.56.101 olej@192.168.56.101's password: Last login: Mon Jul 16 17:29:57 2012 from 192.168.50.1 ... $ who olej tty1 2012-07-16 09:29 (:0) olej pts/0 2012-07-16 09:33 (:0.0) ... olej pts/6 2012-07-16 17:29 (192.168.50.1) olej pts/7 2012-07-16 17:31 (192.168.56.1)
瀺ãããŠããæåŸã®ã³ãã³ãïŒèª°ïŒã¯ãSSHã»ãã·ã§ã³ã§ãã€ãŸã2ã€ã®ç°ãªããµããããããã®2 ã€ã®ç¬ç«ããæ¥ç¶ãåºå®ãããŠããïŒåºåã®æåŸã®2è¡ïŒãå®éã«ã¯1ã€ã®ãã¹ããè¡šããŠããŸããããã®èŠ³ç¹ããã¯ãSSHã»ãã·ã§ã³ã§æ¢ã«å®è¡ãããŠããŸãããŸããŸãªãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ã
ãããªãæŽç·Ž
ãµã³ãã«ã¢ãžã¥ãŒã«ã®æºåãšãããã°ã§ã¯ã詳现ãæ確ã«ããããã«ããã®ïŒããªãæè¿ã®ïŒæ¬ãç©æ¥µçã«äœ¿çšãããŸãããRamiRosenïŒãLinux Kernel NetworkingïŒImplementation and TheoryããApressã650ããŒãžã2014幎ãISBN-13ïŒ978-1-4302 -6196-4ã

èè ã¯ãæ¬ãçºå£²ãããåã«ç¡æã§ããŠã³ããŒãã§ããããã«èŠªåã«æäŸããŸããïŒ2013-12-22ïŒã ãã®ããŒãžããããŠã³ããŒãã§ããŸã ã
ãã®èšäºã§èª¬æãããããªåé¡ã«èå³ããã人ã¯ãèªåã®ãããã¯ãŒã¯ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããæè¡ãããã«çºå±ãããããã«ããã®åºçç©ã§å€ãã®ã¢ã€ãã¢ãèŠã€ããããšãã§ããŸãã
ãããããã§å®éšãšãããªãéçºã®ããã«ããã¹ãã§èšåãããã³ãŒãã®ã¢ãŒã«ã€ããåãããšãã§ããŸã ã