LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-21-2009, 07:32 PM   #1
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165
Blog Entries: 1

Rep: Reputation: 22
Byte array conversion


Hello,

I am trying to convert a variable array of bytes to an unsigned long int. The number of bytes is passed into the function as tcpoptlen. Manually converting the first type bytes in the array works fine, but trying to convert n bytes crashes.

This worked to convert the first two bytes into a unsigned long integer.
Code:
tcpoptdata = (opt[i+2] << 8) | opt[i+3];

Code:
u_int64_t tcpoptdata;
u_int8_t bytefield;
u_int8_t count;

 /* if the option exists, but data length is 2  */
     if (tcpoptlen == 2)
          return 1;        
     else
                                         
     tcpoptdata = 0;
     count = tcpoptlen - 2;
     bytefield = 2;
                                         
     while (count > 0) {
                                                 
          tcpoptdata |= opt[i + bytefield];
          if (((tcpoptlen - bytefield) - 1) != 0)
               tcpoptdata <<= (8 * ((tcpoptlen - bytefield) - 1));
                                                 
          count =- 1;
          bytefield =+ 1;
   
} 
                                         
return tcpoptdata;
 
Old 09-21-2009, 09:35 PM   #2
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
how big is a unsigned long?
if its 64 bits:
Code:
tcpoptdata = 
(opt[i+2]<<56) + (opt[i+3]<<48) + (opt[i+4]<<40) + (opt[i+5]<<32)+
(opt[i+6]<<24) + (opt[i+7]<<16) + (opt[i+8]<<8) | (opt[i+9]&0xFE);
that should do it
i just reread your post
replace j with the number you want to convert
Code:
tcpoptdata = ((j > 0)*
(opt[i+2]<<56)) + ((j > 1)*(opt[i+3]<<48)) + ((j > 2)*(opt[i+4]<<40)) + ((j>3)*(opt[i+5]<<32))+
((j>4)*(opt[i+6]<<24)) + ((j>5)*(opt[i+7]<<16)) + ((j>6)*(opt[i+8]<<8)) | ((j>7)*(opt[i+9]&0xFE));

Last edited by smeezekitty; 09-21-2009 at 09:41 PM. Reason: bbcode mistake
 
Old 09-22-2009, 08:41 AM   #3
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Mint
Posts: 17,809

Rep: Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743Reputation: 743
Moved: This thread is more suitable in <Programming> and has been moved accordingly to help your thread/question get the exposure it deserves.
 
Old 09-22-2009, 09:31 AM   #4
carbonfiber
Member
 
Registered: Sep 2009
Location: Sparta
Posts: 237

Rep: Reputation: 46
Hello. What exactly does each byte represent? What is the type of opt? Why are you not using uint64_t, uint8_t (stdint.h)?
 
Old 09-22-2009, 11:57 AM   #5
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165

Original Poster
Blog Entries: 1

Rep: Reputation: 22
opt is an unsigned char(edit actually it looks like an array of chars). tcpopelen defines how many bytes are storing bitwise data. I need to take each byte as a field, and contantonate them together so the bits remain the same in integer form.

tcpoptlen = 2 so its two bytes or 16-bit the value is 65000 or byte[1] = 11111101, byte[2] = 11101000. I need to convert them back into an integer = 1111110111101000

At least I think thats how it work. I thought it would be easier to start with reading the into before I started trying to write to opt[].

Last edited by yaplej; 09-22-2009 at 12:51 PM.
 
Old 09-22-2009, 12:39 PM   #6
carbonfiber
Member
 
Registered: Sep 2009
Location: Sparta
Posts: 237

Rep: Reputation: 46
I'm (still) guessing you're looking for something along these lines:

Code:
/* warning: the following convert function makes many gross assumptions. */

#include <stdio.h>

unsigned long convert(const unsigned char *s, size_t sz)
{       
        unsigned long data = s[0];
        for (size_t i = 1; i < sz; ++i)
                data = (data << 8) | s[i];

        return data;
}

int main()
{       
        unsigned char s[] = { 0x07, 0xF8, 0x94, 0x09 };
        printf("%lu\n", convert(s, sizeof(s)));
        return 0;
}

Last edited by carbonfiber; 09-22-2009 at 12:40 PM.
 
Old 09-22-2009, 04:50 PM   #7
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165

Original Poster
Blog Entries: 1

Rep: Reputation: 22
Well I am finally getting there. My test data is tcpoplen = 4, and opt[i+2] + opt[i+3] = the 16-bit binary value of 1460.

It works(meaning not crashing the system), but the data I get is 1461 not 1460 like it should be. So the problem is with my routine that converts the bytes into a single integer value.


Code:
    
u_int64_t tcpoptdata;
u_int8_t bytefield;
u_int8_t count;

/* if the option exists, but data length is 2  */
     if (tcpoptlen == 2)
          return 1;        
     else
                                         
     count = opt[i+1] - 2; // get option length from header, 
                           // and ignore header fields.
     bytefield = 2;  // the first data byte is always at i+2.
     tcpoptdata = 0; // initialize tcpoptdata.
                                         
                                         
                         
     while (count > 0) {
          count--;
          if ((count) != 0) {
               tcpoptdata += (opt[i+bytefield] << 8 * count);
          }
          else {
               tcpoptdata += opt[i+bytefield];
          }        
                                         
          bytefield++;
     } 
                                         
     tcpoptdata |= opt[i+bytefield];        
                                         

return tcpoptdata;
 
Old 09-22-2009, 05:42 PM   #8
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165

Original Poster
Blog Entries: 1

Rep: Reputation: 22
Fixed it! Had to add "& 0xFE" to this line. Not sure what that does, but it is now returning the correct result for any byte length tcp option.

Code:
tcpoptdata |= opt[i+bytefield];
Code:

u_int64_t tcpoptdata;
u_int8_t bytefield;
u_int8_t count;

/* if the option exists, but data length is 2  */
     if (tcpoptlen == 2)
          return 1;        
     else
                                         
     count = opt[i+1] - 2; // get option length from header, 
                           // and ignore header fields.
     bytefield = 2;  // the first data byte is always at i+2.
     tcpoptdata = 0; // initialize tcpoptdata.
                                         
                                         
                         
     while (count > 0) {
          count--;
          if ((count) != 0) {
               tcpoptdata += (opt[i+bytefield] << 8 * count);
          }
          else {
               tcpoptdata += opt[i+bytefield];
          }        
                                         
          bytefield++;
     } 
                                         
     tcpoptdata |= opt[i+bytefield] & 0xFE;        
                                         

return tcpoptdata;
 
Old 09-23-2009, 01:38 PM   #9
yaplej
Member
 
Registered: Apr 2009
Distribution: CentOS, Ubuntu, openSuSE
Posts: 165

Original Poster
Blog Entries: 1

Rep: Reputation: 22
Quote:
Originally Posted by carbonfiber View Post
Hello. What exactly does each byte represent? What is the type of opt? Why are you not using uint64_t, uint8_t (stdint.h)?
This is done in kernel space so using <stdint.h> is not allowed from what I understand.
 
Old 09-23-2009, 01:44 PM   #10
smeezekitty
Senior Member
 
Registered: Sep 2009
Location: Washington U.S.
Distribution: M$ Windows / Debian / Ubuntu / DSL / many others
Posts: 2,339

Rep: Reputation: 231Reputation: 231Reputation: 231
Quote:
Originally Posted by yaplej View Post
This is done in kernel space so using <stdint.h> is not allowed from what I understand.
stdint sholuld be just a seires of typedefs or #defines
so there is no reason it would not work
but my sugjestion is if it works to fool with it
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
byte order conversion from network to host... adnap Programming 1 04-15-2007 04:36 AM
Converting Image to Byte Array (Java) megabot Programming 2 03-17-2007 09:49 AM
C: a float from 2 bytes of a 4-byte array carcassonne Programming 8 01-17-2007 06:23 PM
[Perl] basic byte conversion script noir911 Programming 1 11-21-2006 01:01 AM
Java byte array problem Mohsen Programming 2 03-11-2004 01:37 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration