View Full Version : The need for connect/listen on raw sockets?
BinarySpike
2006.10.15, 10:42 PM
I've been doing some raw sockets tutorials, but none of them work right...
So I was wondering, is there a need for connect/listen or bind using a raw socket? (read and write based)
I can't find *anything* that is up to date or uses other code bases...
btw, IPv4 if it makes any difference... (I don't know what I support...)
OneSadCookie
2006.10.15, 11:03 PM
How could either make sense, given that there's no protocol at this level?
BinarySpike
2006.10.15, 11:27 PM
Um...
I generated IP and UDP headers, I didn't provide a payload, and I sent using send...
I haven't found *anything* and I've been searching for two days... just a couple outdated tutorials...
My RAW sockets reader didn't accept it either... here's the code for both...
(I was just wondering cause I saw a tutorial that had bind and connect in it)
I've tried three styles, and none of them get caught... I'm not sure how to tell they are being sent either... I don't need a catcher! I need a thrower mainly...
(although I will need a catcher after a while)
Throw
#include <iostream.h>
#define P 5000
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define maxBufSize 4096
struct IPHeader {
unsigned char ip_hl:4, ip_v:4; /* this means that each member is 4 bits */
unsigned char ip_tos;
unsigned short int ip_len;
unsigned short int ip_id;
unsigned short int ip_off;
unsigned char ip_ttl;
unsigned char ip_p;
unsigned short int ip_sum;
unsigned int ip_src;
unsigned int ip_dst;
}; /* total ip header length: 20 bytes (=160 bits) */
struct UDPHeader {
unsigned short int uh_sport;
unsigned short int uh_dport;
unsigned short int uh_len;
unsigned short int uh_check;
}; /* total udp header length: 8 bytes (=64 bits) */
unsigned short csum (unsigned short *buf, int nwords)
{
unsigned long sum;
for (sum = 0; nwords > 0; nwords--)
sum += *buf++;
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
int main(int argc, char * argv[])
{
char datagram[maxBufSize];
IPHeader *iph = (IPHeader *) datagram;
UDPHeader *udph = (UDPHeader *) datagram + sizeof(IPHeader);
memset(datagram, 0, maxBufSize);
int fd = socket (PF_INET, SOCK_RAW, IPPROTO_UDP);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(P);
sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
iph->ip_hl = 5;
iph->ip_v = 4;
iph->ip_tos = 0;
iph->ip_len = sizeof (IPHeader) + sizeof (UDPHeader); /* no payload */
iph->ip_id = htonl (54321); /* the value doesn't matter here */
iph->ip_off = 0;
iph->ip_ttl = 255;
iph->ip_p = 6;
iph->ip_sum = 0; /* set it to 0 before computing the actual checksum later */
iph->ip_src = inet_addr("1.2.3.4");/* SYN's can be blindly spoofed */
iph->ip_dst = sin.sin_addr.s_addr;
udph->uh_sport = htons(1234);
udph->uh_dport = sin.sin_port;
udph->uh_len = sizeof(UDPHeader);
udph->uh_check = 0;
iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1);
int one = 1;
const int *val = &one;
int error = setsockopt(fd, IPPROTO_IP, IP_
if (setsockopt (fd, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
printf ("Warning: Cannot set HDRINCL!\n");
if (write(fd, datagram, maxBufSize) > 0)
cout << "caught packet" << endl;
cout << "quiting" << endl;
return 0;
}
Catch
#include <iostream.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char * argv[])
{
int fd = socket (PF_INET, SOCK_RAW, IPPROTO_TCP);
char buffer[8192]; /* single packets are usually not bigger than 8192 bytes */
while (true)
{
if (read (fd, buffer, 8192) > 0)
cout << "caught packet" << endl;
}
cout << "quiting" << endl;
return 0;
}
OneSadCookie
2006.10.15, 11:31 PM
you don't have nearly enough htonl and htons calls in that code, whatever other problems it might have.
BinarySpike
2006.10.16, 01:04 AM
you don't have nearly enough htonl and htons calls in that code, whatever other problems it might have.
Those shouldn't matter if I'm running localhost though...
Any tutorials would be nice if you don't have any insightful information...
akb825
2006.10.16, 02:13 AM
At the very bottom of this page (http://www.ecst.csuchico.edu/~chafey/prog/sockets/sinfo1.html) is some sample code for a server/client. If you want to connect with a specific IP address, you can just copy the address info for the server replacing INADDR_ANY with the IP address.
OneSadCookie
2006.10.16, 03:12 AM
Those shouldn't matter if I'm running localhost though...
Why shouldn't they? You think nothing tries to parse the IP header you create?
Maybe it does, maybe it doesn't. I wouldn't like to make a blanket statement without any evidence!
OneSadCookie
2006.10.16, 03:13 AM
At the very bottom of this page (http://www.ecst.csuchico.edu/~chafey/prog/sockets/sinfo1.html) is some sample code for a server/client. If you want to connect with a specific IP address, you can just copy the address info for the server replacing INADDR_ANY with the IP address.
He's trying to do raw socket stuff, not standard TCP/UDP stuff... Maybe I'm blind, but I didn't see anything on that page about raw sockets...
akb825
2006.10.16, 03:39 AM
Sorry, I thought "raw sockets" meant using sockets directly. :blush: Be careful, though: according to Wikipedia (http://en.wikipedia.org/wiki/Raw_socket), raw sockets are limited under Windows. (in case you want Windows compatibility)
unknown
2006.10.16, 07:26 AM
JOOI, is this working code on mac OS?
Steven
2006.10.16, 06:28 PM
Could you be having problems with your setting both the source and destination addresses to 1.2.3.4? That likely isn't your IP address...
BinarySpike
2006.10.16, 08:42 PM
Could you be having problems with your setting both the source and destination addresses to 1.2.3.4? That likely isn't your IP address...
sin.sin_addr.s_addr = inet_addr ("127.0.0.1");
...
iph->ip_src = inet_addr("1.2.3.4");
iph->ip_dst = sin.sin_addr.s_addr;
Source is 1.2.3.4 and destination is 127.0.0.1
I didn't notice source, thanks :)
Why shouldn't they? You think nothing tries to parse the IP header you create?
Maybe it does, maybe it doesn't. I wouldn't like to make a blanket statement without any evidence!
I didn't, you use hton functions to convert a variable's byte ordering
And should only be needed if you send packets to another architecture that has the opposite bit ordering (in this case I should be able to send it to another mac computer fine)
But, there are routers, that might run off a different bit ordering, but again when you send to 127.0.0.1 you are routed by your kernel, or on some older computer ethernet hardware.
So if you connect localhost you never leave your computer, and I haven't read anything to say that the kernel and programs use different bit ordering...
That's what I've read, and been told since I began sockets. (I wrote a socket library that handled sockets but I didn't know about byte ordering, so mac-to-windows didn't work, I am sure mac-to-mac worked fine)
OneSadCookie
2006.10.16, 09:23 PM
And should only be needed if you send packets to another architecture that has the opposite bit ordering (in this case I should be able to send it to another mac computer fine)
But, there are routers, that might run off a different bit ordering, but again when you send to 127.0.0.1 you are routed by your kernel, or on some older computer ethernet hardware.
So if you connect localhost you never leave your computer, and I haven't read anything to say that the kernel and programs use different bit ordering...
That's what I've read, and been told since I began sockets. (I wrote a socket library that handled sockets but I didn't know about byte ordering, so mac-to-windows didn't work, I am sure mac-to-mac worked fine)
No, *everything* uses network byte order for these protocol headers. Even if you're sending to yourself, you still need to make sure that you put the bytes in the right order, if there's the slightest chance that the OS might try to interpret them.
(and remember, Macs have two different byte orders these days...)
Steven
2006.10.16, 11:45 PM
BinarySpike: Have you tried using something like Ethereal (now WireShark?)
It can be invaluable to see both if the packet actually gets on the wire and then it will show you how it interprets the packet (so you can see if it is valid)
Zekaric
2006.10.17, 11:48 AM
I don't know if this will help any. In the past we've been bitten by this at work. Structures may not be as compact as you have declared them. There may be padding inside that allows the values to be aligned on byte boundaries. This may be an issue if you are sending the raw structure over the wire and the other end is expecting a certain values at certain byte locations other than byte boundaries.
Just in case, you might want to look for a #pragma pack() sort of preprocessor command that will ensure the byte ordering of the structures.
This is on top of making sure the values are in network order because everything inbetween the send and recieve (OS, Internet) is expecting network order. But then OSC has pretty much berrated you on that point. :)
unknown
2006.10.17, 12:22 PM
'SYN's can be blindly spoofed'
what the heck are you doing, and does this work on mac os x?
BinarySpike
2006.10.17, 01:42 PM
BinarySpike: Have you tried using something like Ethereal (now WireShark?)
It can be invaluable to see both if the packet actually gets on the wire and then it will show you how it interprets the packet (so you can see if it is valid)
Just tried, I put it on lo0 using MacSniffer, whenever I tried "sudo ./throw" stuff appeared, but when I did "sudo -s" and then tried nothing appeared, so simply speaking, localhost packets are being sent when I sudo, and ./throw isn't throwing anything...
I don't know if this will help any. In the past we've been bitten by this at work. Structures may not be as compact as you have declared them. There may be padding inside that allows the values to be aligned on byte boundaries. This may be an issue if you are sending the raw structure over the wire and the other end is expecting a certain values at certain byte locations other than byte boundaries.
Just in case, you might want to look for a #pragma pack() sort of preprocessor command that will ensure the byte ordering of the structures.
This is on top of making sure the values are in network order because everything inbetween the send and recieve (OS, Internet) is expecting network order. But then OSC has pretty much berrated you on that point.
I see, I revised my code to to put *all* unsigned shorts and longs in correct order, I didn't know what to do about the 4 bit variables, or the chars (cause the chars and one byte they shouldn't be ordered specially...)
'SYN's can be blindly spoofed'
what the heck are you doing, and does this work on mac os x?
Idk what a SYN is... but that was left over from some code I grabbed...
(which I based this version off of)
I'm gonna go checkout SDL
BinarySpike
2006.10.18, 02:28 AM
*edit*
PowerPC runs big endian *and* little endian... idk how exactly this all fits together but that is what the source said (aka, OSC was right)
MacSniffer running off lo0 saw the packets just fine without the DONTROUTE setting.
(Go MacSniffer!)
*/edit*
Success!
I looked up the SYN spoofing thing... kinda scary :(
So anyway, I found a great resource (old e-mail to a linux community) and finally figured out the headers required to work it all, but the major thing that both I and the old e-mail had in common, is that they didn't work till we added the bind function.
I also found the IP headers... for future reference here's a list of headers and why they are required.
#include <stdlib.h>
#include <stdio.h>
// required for sys/socket.h and sys/types.h
#include <sys/socket.h>
#include <sys/types.h>
// the main socket headers dupid silly person!
#include <netinet/in_systm.h> // defines n_long for netinet/ip.h
#include <netinet/in.h> // defines IPPROTO_IP and IP_HDRINCL IIRC
#include <netinet/ip.h> // defines struct ip (mac) for IP headers
// note some resources use iphdr, you could always typedef struct iphdr to struct ip for portability
I haven't tested the headers netinet/tcp.h or netinet/udp.h
tcp.h should have the TCP header struct and udp.h should have the UDP header struct... I have not tested to see what other headers they require...
on mac you only need include libstdc++
Please note this is as of 10.2.8, dev tools... I haven't upgraded any of my netinet so far, if I find source code to update my sockets stuff I would gladly upgrade :)
akb825
2006.10.18, 02:42 AM
Just FYI, the G4 has a little endian mode, but the G5 does not. (that's the main reason why VirtualPC took so long to port to the G5)
OneSadCookie
2006.10.18, 03:24 AM
As akb825 nearly says, little-endian mode was an optional feature of PowerPC processors, could only be switched to by a privileged process, and wasn't quite full-featured, IIRC -- some instructions weren't available in little-endian mode or something. G3s and G4s had it, G5s didn't.
IOW, you can basically ignore the idea that PowerPCs are little-endian. For all intents and purposes, they're always big-endian.
BinarySpike
2006.10.18, 03:36 AM
Ok thanks...
I tried to get my program working on different ports... it only runs on port 0, any other port fails at bind...
Btw this is with and without the UDP header (I've gotten it to work)
anybody know why it would do this?
unknown
2006.10.18, 06:40 AM
you need root to bind to ports <= 1024
Just use UDP and TCP you can bind them to any port (in my experience), dont use RAW sockets.
Unless you have a specific need for RAW sockets which I would be interested to hear if you did.
BinarySpike
2006.10.18, 01:02 PM
You need root to use RAW Sockets, so it doesn't matter I would suppose what port you used.
(At least you can't set IP_HDRINCL without being root)
My UDP header seems to be working, but bind doesn't even see the headers, only sendto does...
*edit*
I have several needs for RAW sockets, raw sockets improve on memory usage, while increase CPU usage, so theirs a gain for using raw sockets or not...
Only port 0 binds, I've tried 5555, 3333, 20000 and 1000
all while under root (sudo -s)
I'm gonna try to see if they send out without binding (or at least not exit when binding fails)
Steven
2006.10.18, 03:50 PM
Correct me if I'm wrong, but isn't the port a property of the TCP or UDP packet? (Ex: port makes no sense on an ICMP packet?)
Therefore, binding to a specific port on a raw socket makes no sense?
unknown
2006.10.18, 05:05 PM
To be honest I think you should just save yourself a huge amount of bother and use TCP/UDP instead of IP. There is really no advantage to filling in your own TCP headers in any normal situation.
OneSadCookie
2006.10.18, 05:10 PM
Raw sockets are *only* useful for implementing things like ICMP pingers and port scanners. If you're fighting with them out of some misplaced idea that you can somehow write a better UDP stack than Apple it's time to get realistic :p
Of course, if you're just messing with them because you think they're cool and want to know how they work, fine :)
BinarySpike
2006.10.19, 03:16 AM
Raw sockets are *only* useful for implementing things like ICMP pingers and port scanners. If you're fighting with them out of some misplaced idea that you can somehow write a better UDP stack than Apple it's time to get realistic :p
Of course, if you're just messing with them because you think they're cool and want to know how they work, fine :)
Exactly :)
No use using something I don't know how it works :wacko:
for example, I had no clue why connect, listen, or accept were required... it was just soooo complicated, then I learned it's part of the proccess of getting a connection and requires many behind the scenes packets.
Correct me if I'm wrong, but isn't the port a property of the TCP or UDP packet? (Ex: port makes no sense on an ICMP packet?)
Therefore, binding to a specific port on a raw socket makes no sense?
That's the problem if I didn't bind the packets, it wouldn't work :(
sendto would not register in either en0 or lo0 on tcpdump (I'm using MacSniffer)
To be honest I think you should just save yourself a huge amount of bother and use TCP/UDP instead of IP. There is really no advantage to filling in your own TCP headers in any normal situation.
I understand that, and I would rather use something like HawkNL or raknet to run my networking (or SDL_net). I'm making this a requirement of myself to run a working raw sockets program.
I re-wrote everything from scratch, this *should* work... but it doesn't...
I'm not pressing anybody to take a look, but I will say, it's super organized...
http://pastebin.ca/209566
Thanks :cool:
BinarySpike
wadesworld
2006.10.26, 10:01 PM
for example, I had no clue why connect, listen, or accept were required... it was just soooo complicated, then I learned it's part of the proccess of getting a connection and requires many behind the scenes packets.
If you don't understand the purpose of listen, connect and accept, your chances of understanding it by writing raw sockets code is slim. That's like not understanding how a C if statement works, and learning assembler to find out.
Go get a good basic network programming book. Get several. Study the code of others.
But really they're not that complex:
Listen: listens for incoming connections
Connect: attempts a connection
Accept: accepts an incoming connection
akb825
2006.10.26, 10:23 PM
I'm thinking he meant when he began with sockets, not now.
vBulletin® v3.6.8, Copyright ©2000-2008, Jelsoft Enterprises Ltd.