Trouble capturing IP packets with libpcap - endianness

First the structs:
/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN 6
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
#define ETHERTYPE_IP 0x0800 /* IP */
/* IP header */
struct sniff_ip {
u_char ip_vhl; /* version << 4 | header length >> 2 */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
#define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip) (((ip)->ip_vhl) >> 4)
I have opened the network device with pcap_open_live, the pcap_datalink is DLT_EN10MB for that device, but I am receiving lots of IP headers with 0 length, weird version number, etc.
Here's a snippet that outputs this:
eth = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(eth + 14); /* ETHERNET = 14 */
int version_ip = IP_V(ip);
int size_ip = IP_HL(ip)*4;
printf("caplen=%d len=%d eth->type=%d version_ip=%d size_ip=%d !\n", header.caplen, header.len, eth->ether_type, version_ip, size_ip);
And some sample output:
caplen=94 len=94 eth->type=8 version_ip=0 size_ip=0 !
caplen=159 len=159 eth->type=8 version_ip=9 size_ip=12 !
caplen=110 len=110 eth->type=8 version_ip=0 size_ip=12 !
caplen=200 len=336 eth->type=8 version_ip=4 size_ip=20 ! (this one is OK)
What is going on here?
Why is eth type 0x0008 and not 0x0800? Endianness?
What's up with the weird ip header versions?
How can the IP header length be below 20 bytes?

Found the problem...
eth = (struct sniff_ethernet*)(packet);
ip = (struct sniff_ip*)(eth + 14); /* should be (packet + 14) */
The 'smart' C pointer arithmetics doesn't add 14 bytes, but 14*sizeof(struct sniff_ethernet).

Related

Issue with Interfacing atmega328p with Bluetooth

I’m trying to interface atmega328p with Blutooth HC-0.
I was following the example in Atmega328P datasheet in USART section.
The code is simply trying to send a letter 'b' to Bluetooth terminal on mobile phone and receive a letter. If the received letter is 'a', an LED on PORTB0 will turn on, if the letter is 'c', the LED will turn off. But unfortunately nothing is working.
Connection between atmega328P and HC-05 is as follows:
HC-05 -> Atmega328P
RXD -> pin3
TXD -> pin2
GND -> pin8
VCC -> pin7
Bluetooth light is turning on and off, and is connected successfully to mobile phone but no data is received, and when the letters 'a' and 'c' are sent nothing happens with LED connected to PORTB0.
The code is shown here. Thank you for any help!
#define F_CPU 16000000UL // Clock Speed
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
char data;
char data2 = 'b';
void USART_Init(unsigned int ubrr)
{
/* Set baud rate */
UBRR0H = (unsigned char)(ubrr>>8);
UBRR0L = (unsigned char)(ubrr);
/* Enable receiver and transmitter */
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
/* Set frame format: 8data, 2stop bit */
UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}
char USART_Receive(void)
{
/* Wait for data to be received */
while ( !(UCSR0A & (1<<RXC0)) );
/* Get and return received data from buffer */
return UDR0;
}
void USART_Transmit(char data)
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) );
/* Put data into buffer, sends the data */
UDR0 = data;
}
int main(void)
{
DDRB = 0b00000001;
PORTB = 0b00000000;
USART_Init(MYUBRR);
while (1) {
data = USART_Receive();
USART_Transmit(data2);
if (data == 'a') {
PORTB = 0b00000001;
} else if (data == 'c') {
PORTB = 0b00000000;
}
}
}

setting an i2c register to high

I have this project that my boss asked me to do and the first step is to figure out how to set a given I2C register to high or low using the silicon lab library, if anyone knows any good sources for this type of problem please provide them thank you. The pic that I am using is the pic16f1823, I've already looked at the documentation of the pic but into only states how to read and write to an I2c.
I use this as a header file and seems to work well for PIC16F1827 which is basically the same as the 1823. It used the peripheral of the PIC. Just include in in any c file you want to use i2c in. Make sure you #define FOSC in order to calculate the correct baud rate. Also double check the port and tris assignments are correct for your device and make adjustments.
It uses polling instead of an interrupt. Uncomment the interrupt setup code and write an interrupt service routine to catch the interrupts.
#ifndef I2C_H
#define I2C_H
#ifdef __cplusplus
extern "C" {
#endif
/*
* Hi-Tech C I2C library for 12F1822
* Master mode routines for I2C MSSP port to read and write to slave device
* Copyright (C)2011 HobbyTronics.co.uk 2011
* Freely distributable.
*/
#define I2C_WRITE 0
#define I2C_READ 1
// Initialise MSSP port. (12F1822 - other devices may differ)
void i2c_Init(void){
// Initialise I2C MSSP
// Master 100KHz
TRISB2 = 1;
TRISB5 = 1;
SSP1CON1 = 0b00101000; // I2C Master mode
SSP1CON2 = 0b00000000;
SSP1CON3 = 0b00000000;
//SSP1MSK = 0b00000000;
SSP1ADD = I2C_BRG; // clock = FOSC/(4 * (SSPxADD+1))
//SSP1IE = 1; // enable interrupt
SSP1STAT = 0b10000000;
}
// i2c_Wait - wait for I2C transfer to finish
void i2c_Wait(void){
while ( ( SSP1CON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
}
// i2c_Start - Start I2C communication
void i2c_Start(void)
{
i2c_Wait();
SSP1CON2bits.SEN=1;
}
// i2c_Restart - Re-Start I2C communication
void i2c_Restart(void){
i2c_Wait();
SSP1CON2bits.RSEN=1;
}
// i2c_Stop - Stop I2C communication
void i2c_Stop(void)
{
i2c_Wait();
SSP1CON2bits.PEN=1;
}
// i2c_Write - Sends one byte of data
void i2c_Write(unsigned char data)
{
i2c_Wait();
SSPBUF = data;
}
// i2c_Address - Sends Slave Address and Read/Write mode
// mode is either I2C_WRITE or I2C_READ
void i2c_Address(unsigned char address, unsigned char mode)
{
unsigned char l_address;
l_address=address<<1;
l_address+=mode;
i2c_Wait();
SSPBUF = l_address;
}
// i2c_Read - Reads a byte from Slave device
unsigned char i2c_Read(unsigned char ack)
{
// Read data from slave
// ack should be 1 if there is going to be more data read
// ack should be 0 if this is the last byte of data read
unsigned char i2cReadData;
i2c_Wait();
SSP1CON2bits.RCEN=1;
i2c_Wait();
i2cReadData = SSPBUF;
i2c_Wait();
if ( ack ) SSP1CON2bits.ACKDT=0; // Ack
else SSP1CON2bits.ACKDT=1; // NAck
SSP1CON2bits.ACKEN=1; // send acknowledge sequence
return( i2cReadData );
}
#ifdef __cplusplus
}
#endif
#endif /* I2C_H */
Then you can use the higher level functions defined above to control a device, which is described in the datasheet of the slave device.
For example, to read from an eeprom:
#include <xc.h>
#define FOSC 16000000
#include "i2c.h"
unsigned char i2c_read_eeprom( unsigned char slaveaddress, unsigned char memaddress )
{
unsigned char data;
data = 123;
i2c_Start();
i2c_Address( slaveaddress, I2C_WRITE);
i2c_Write(memaddress);
if( SSP1CON2bits.ACKSTAT )
txstring("ACK!\r\n");
else txstring("nACK!\r\n");
i2c_Start();
i2c_Address( slaveaddress, I2C_READ);
data = i2c_Read(0);
i2c_Stop();
return data;
}

Why is stat's st_size field offset 96 on 64bit OSX and can it be calculated?

Using the latest sources from apple's open source repo I have derived the following structure for the "stat" struct (in go syntax):
type timespec struct {
tv_sec int32
tv_nsec uint32
}
type stat64 struct {
st_dev int32 /* [XSI] ID of device containing file */
st_mode uint16 /* [XSI] Mode of file (see below) */
st_nlink uint16 /* [XSI] Number of hard links */
st_ino uint64 /* [XSI] File serial number */
st_uid uint32 /* [XSI] User ID of the file */
st_gid uint32 /* [XSI] Group ID of the file */
st_rdev int32 /* [XSI] Device ID */
st_atimespec timespec /* time of last access */
st_mtimespec timespec /* time of last data modification */
st_ctimespec timespec /* time of last status change */
st_birthtimespec timespec /* time of file creation(birth) */
st_size int64 /* [XSI] file size, in bytes */
st_blocks int64 /* [XSI] blocks allocated for file */
st_blksize int32 /* [XSI] optimal blocksize for I/O */
st_flags uint32 /* user defined flags for file */
st_gen uint32 /* file generation number */
st_lspare int32 /* RESERVED: DO NOT USE! */
st_qspare [2]int64 /* RESERVED: DO NOT USE! */
}
but in practice it turns out st_size has an offset of 96 bytes instead of the 60 shown above. What's the cause of this discrepancy and how can this be seen from the original source code?
On OS X, both fields of struct timespec are long, which is 64-bit in the usual LP64 convention. Therefore, sizeof(struct timespec) == 16 (you can check this yourself), and it is aligned on a 64-bit boundary, giving you an offset of 96 for st_size.

SCSI Inquiry Data

I am new to SCSI Programming and hence sorry for asking basic question. I sent SCSI Inquiry command to a Tape Device through 6 byte CDB
ccb = (Exec_IO_CCB *)( buffer + header_size );
ccb->ccb_length = sizeof(Exec_IO_CCB);
ccb->cam_opcode = 0x1;
ccb->connect_id = 0;
ccb->sense_buf_ptr = (long)(header_size + ccb->ccb_length);
ccb->sense_buf_length = MAX_SENSE_LEN;
ccb->time_out = CAM_TIMEOUT;
ccb->cdb_length = 6;
/* For INQUIRY sets cam_flags and cdb[0] */
ccb->cam_flags = NO_DATA;
ccb->cdb[0] = INQUIRY; /* 0x12 SCSI Opcode for Inquiry Command */
ccb->cdb[1] = 0;
ccb->cdb[2] = 0;
ccb->cdb[3] = 0;
ccb->cdb[4] = 3200;
ccb->cdb[5] = 0;
The SCSI Command is successful . How do i capture the output of INQUIRY command so that i can get
Vendor ID / Product ID ??
I have declared the Execute I/O SCSI buffer as follows
typedef struct {
long ccb_address; /* Address of this CCB */
short ccb_length; /* CAM Control Block Length */
char cam_opcode; /* CAM Operation Code */
char status; /* CAM Status */
long connect_id; /* Connect ID - no fields supported */
long cam_flags; /* CAM Flags */
long pd_pointer; /* Peripheral driver pointer */
long next_ccb_ptr; /* Next CCB Pointer */
long req_map_info; /* Request mapping information */
long call_on_comp; /* Callback on completion */
long data_buf_ptr; /* Data Buffer Pointer */
long data_xfer_length; /* Data transfer length */
long sense_buf_ptr; /* Sense information buffer pointer */
char sense_buf_length; /* Sense information buffer length */
char cdb_length; /* Command Descriptor Block (CDB) **
** length */
short num_sg_entries; /* Number of scatter/gather entries */
long vendor_unique; /* Vendor Unique field */
char scsi_status; /* SCSI status */
char auto_resid; /* Auto sense residual length */
short reserved; /* Reserved */
long resid_length; /* Residual length */
char cdb[12]; /* Command Descriptor Block (CDB) */
long time_out; /* Time-out value */
long msg_buf_ptr; /* Message buffer pointer */
short msg_buf_length; /* Message buffer length */
short vu_flags; /* Vendor-unique flags */
char tag_queue_act; /* Tagged Queue action */
char tag_id; /* Tag ID (target only) */
char init_id; /* Initiator ID (target only) */
char reserved2; /* Reserved */
} Exec_IO_CCB;
This structure will never capture SCSI Output ?
I have declared the Inquiry Structure as follows . But I am not sure how Inquire command will
populate Inquiry_Data structure data ??
typedef struct {
short data_valid; /* Flag that indicates whether or not the */
/* structure has been filled in with */
/* inquiry data from the device. */
byte periph_qual;
byte periph_dev_type;
byte rmb;
byte iso_version;
byte ecma_version;
byte ansi_version;
byte resp_data_format;
byte rel_adr;
byte sync;
byte linked;
byte cmd_que;
byte sft_rst;
char vendor_id[9];
char prod_id[17];
char prod_rev[5];
char reserved;
} Inquiry_Data;
The first thing that you have assigned a short to cdb[4], but cdb[4] is a byte. The assignment probably put a 0 there since the compiler would truncate. Since bytes 3 and 4 are the allocation length you have told the target not to send anything. Maybe you ment to assign 32 to cdb[4]; but since your Inquiry_Data structure is 44 bytes you probably want to assign 44 to cdb[4].

mac address order

I found out MAC address of my net device in ifconfig -a - HWaddr 00:1a:92:9c:9b:bb
How can I relate to this address in my code?
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));
I'm endeavouring to write to h_dest
memcpy(eth->h_dest,dest_mac,ETH_ALEN);
but I do not know in what order of bytes and bites must I pass the MAC-address value.
They should be in left-to-right order, so h_dest[0] = 0x00.

Resources