1 / 15

Hardware-address filtering

Learn how to send packets to a single node using address filtering and configure packet routing for better privacy in a LAN setting using new 'nic.c' driver.

elmergibbs
Download Presentation

Hardware-address filtering

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Hardware-address filtering How can we send packets to just one node on our ‘anchor’ cluster?

  2. Privacy, please! • Our ‘xmit1000.c’ driver transmits all of its packets to every node on our LAN, and our ‘recv1000.c’ driver receives all of the packets transmitted by any of the nodes! • Is this what we really want to happen? anchor00 anchor01 anchor07 anchor02 anchor06 anchor03 anchor05 anchor04

  3. Receive address filtering • Nowadays any network interface controller has a “filtering” capability which allows any packet NOT to be received by nodes that the packet’s sender didn’t intend it to go to Transmit FIFO to/from LAN Receive buffer filtering engine Receive FIFO Network Interface Controller Host memory

  4. Our new ‘nic.c’ module • This device-driver combines the ‘write()’ and ‘read()’ methods from our ‘xmit1000.c’ and ‘recv1000.c’ modules, but it adds an ‘ioctl()’ method that lets applications setup any ethernet-packet’s destination-address, as is illustrated in our companion program (named ‘sendto.cpp’) which finds a node’s hardware-address in our ‘ethers’ database

  5. The ‘sendto’ algorithm • Here are the steps which our ‘sendto.cpp’ demo-program performs: Find the destination’s node-name on the command-line Search our ‘ethers’ file for a line with that node’s name Convert that node’s MAC-address from ascii to numeric Open the ‘/dev/nic’ device-file Call our driver’s ‘ioctl()’ method to setup packets’ destination Write our application’s test-message to the ‘dev/nic’ device-file Print a message confirming the destination and bytes written

  6. Notes on library functions • Use ‘fopen()’ to open the ‘ethers’ textfile, so you can use the ‘fgets()’ function to read in its contents one-line-at-a-time: #include <stdio.h> // for fopen(), fgets(), puts() #include <string.h> // for strstr() int main( int argc, char *argv[ ] ) { if ( argc == 1 ) exit(1); // missing command-line argument FILE *fd = fopen( “ethers”, “ro” ); if ( fd == NULL ) exit(1); // file not found in current directory char line[ 80 ]; while ( fgets( line, 80, fd ) ) if ( strstr( line, argv[1] ) puts( line ); /* additional processing goes here */ }

  7. ‘ascii-to-numeric’ • Use ‘strstr( string, substring )’ to find line in ‘ethers’ file with name of specified node • Use ‘strtol( string, NULL, 16 )’ to convert a hexadecimal digit-string to a numeric value unsigned char dstn[ 6 ]; // storage for 6-byte MAC-address // loop converts colon-formatted hex-string to array of numbers for (int i = 0; i < 6; i++) dstn[ i ] = strtol( line+3*i, NULL, 16 );

  8. Our ‘ioctl()’ function • Our ‘nic.c’ driver implements an ‘ioctl()’ service allowing a user-program to setup the network hardware-address that will be used in the destination-field of any packet that the driver’s ‘write()’ function transmits // open the network interface controller’s device-file int fp = open( “/dev/nic”, O_RDWR ); if ( fp < 0 ) { perror( “/dev/nic” ); exit(1); } // setup packet-destination to be used when transmittting if ( ioctl( fp, 0, dstn ) < 0 ) { perror( “ioctl” ); exit(1); }

  9. Driver’s ‘ioctl()’ function char mac[ 6 ]; // packet source-address gets filled in by ‘module_init()’ char dstn[ 6 ]; // packet destination-address gets filled in by our ‘ioctl()’ int my_ioctl( struct inode *, struct file*, unsigned int cmd, unsigned long address ) { unsigned char *from = (unsigned char *)address; switch ( cmd ) { case 0: // set the driver’s ethernet-packet destination-address if ( copy_from_user( dstn, from, 6 ) ) return –EFAULT; return 0; //SUCCESS default: break; } return –EINVAL; // requested command not implemented }

  10. Change in ‘write()’ • Our device-driver’s ‘write()’ method needs only a tiny change in order to make use of the user-supplied destination-address: ssize_t my_write( struct file *file, char *buf, size_t len, loff_t *pos ) { int tail = ioread32( io + E1000_TDT ); // next tx-ring index char *packet = phys_to_virt( txdesc[ tail ].base_addr ); // memset( packet+0, 0xFF, 6 ); // broadcast-address (NO!) memcpy( packet+0, dstn, 6 ); // user-supplied MAC-address memcpy( packet+6, mac, 6 ); // source MAC-address (ours!) /* other processing same as before */ }

  11. Change in ‘init()’ • To prevent reception of ethernet packets whose destination-address doesn’t match our device’s address, we need to alter the way we program our nic’s RCTL register: 31 26 15 4 3 2 1 0 0000 0100 0000 0000 1000 0000 00000110 RCTL (0x0100) SECRC (Strip Ethernet CRC) BAM (Broadcast Accept Mode) MPE (Multicast Promiscuous Enable) UPE (Unicast Promiscuous Enable) SBP (Store Bad Packets) EN (Enable receive engine)

  12. A change in memory-usage 4 pages of kernel memory RxBuf 0 RxBuf 1 RxBuf 2 RxBuf 3 RxBuf 4 RxBuf 5 RxBuf 6 RxBuf 7 TxBuf R X D E S C T X D E S C Eight receive-buffers (0x600 bytes each) One ‘shared’ transmit-buffer (0x600 bytes) Eight receive-descriptors (0x80 bytes) Eight transmit-descriptors (0x80 bytes) physaddr descaddr When we “merged” the code from our two previous device-drivers, we needed to make sure that receive-buffers and transmit-buffers do not overlap, and likewise that the Rx and Tx descriptor-queues occupy distinct regions within the allocated kernel-memory region

  13. Is 00:00:00:00:00:00 legal? • If you comment out all the lines of code in our ‘sendto.cpp’ application that precede the ‘open()’ statement, then our driver’s ‘dstn[ 6 ]’ array will remain all zeros, and hence packets will be sent with a ‘zero’ destinatin-address (normally not legal) • EXERCISE: Try this out and see if your test-message gets received any node

  14. Receive-filter Array quadword (64-bits) 0x5400 0x5408 0x5410 0x5418 0x5420 0x5428 0x5430 0x5438 1 Filter-address 0 0 Filter-address 1 The NIC’s own unique hardware-address gets programmed into this initial array-entry during initialization Other addresses may be added later by driver software Filter-address 2 0 0 Filter-address 3 Filter-address 4 0 0 Filter-address 5 Filter-address 6 0 Filter-address 7 0 … ‘valid’-bit (1=yes, 0=no)

  15. In-class exercise • Apply your knowledge of the Intel 82573L ‘Receive-filter Array’ to add the quadword 0x8000000000000000 at offset 0x5408 in the NIC’s i/o-memory space • Then test your modified ‘sendto.cpp’ code to see if you can ‘receive’ a packet which has ‘zero’ as its destination-address

More Related