6

I wish to write a bootable program in assembler that would be capable of sending and receiving network packets. I do not wish to use any libraries, I'd like to create it all by myself (and also learn while doing so). Unfortunately, I was unable to find any information regarding communication with the network card on the lowest level (sending raw sockets). I believe it's necessary to use OUT and IN instructions, although I couldn't find any information about the port that is assigned to the network card (or how to find it, if it's not always the same). Could anybody point me in the right direction? ;-)

starblue
  • 55,348
  • 14
  • 97
  • 151
Neo_b
  • 231
  • 5
  • 9
  • If you're writing your own OS, see https://wiki.osdev.org/Network_Stack. Otherwise make system calls on an existing OS, like raw sockets on Linux. – Peter Cordes Apr 01 '21 at 21:55

3 Answers3

7

This is quite a large problem to solve. Even getting to the point of "raw sockets" is going to be quite a bit of work.

First, with a modern BIOS, your network card won't normally be configured by default, so you'll need to deal with PCI configuration to configure it to have some ports that are visible to the processor. This will give you the basic capability of getting the CPU to actually talk to the network card.

Second, you'll have to find some documentation on the particular chipset it happens to use so you'll know how to read and write network data. With some older cards this was pretty easy, but most newer ones act as bus masters with scatter/gather hardware. Programming them to do even a simple transfer can be non-trivial. This depends completely on the hardware though.

Third, you'll need to develop a substantial part of an IP stack to be able to use even raw sockets. At the hardware level, you basically have two capabilities: receive whatever packets happen to arrive, and send packets to specified MAC addresses -- or other hardware addresses, if your card isn't (and doesn't look/act like) Ethernet.

The next couple of layers on top of that would be an ARP resolver (to let you use IP addresses instead of MAC addresses) and a DNS client (so you can use normal address names instead of something like dotted quads. Along with that, you'll probably want to build software that knows how to create/understand IP datagrams.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

Different network cards have different hardware interfaces (which is why they have different device drivers).

You might get information about the hardware from the device manufacturer (or you might not: they might regard that as proprietary information, and write their own device drivers).

You might also get that information by looking at the source code of open source network cards: for example, I'd guess, for Linux; or, perhaps, the Crynwr packet drivers.

ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • So are you saying that all operating systems that do not require drivers installed for a network card already have all drivers of all existing network cards? – Neo_b Sep 01 '10 at 21:22
  • There are a lot of these drivers; e.g. 20 pages of Intel drivers at http://drivers.softpedia.com/get/NETWORK-CARD/INTEL/ – ChrisW Sep 01 '10 at 21:29
  • I bought my copy of Windows preinstalled when I bought this computer. The computer manufacturer ("OEM"), who installed the O/S, knew what kind of network card they had put in this machine, and was therefore able to install the right driver. – ChrisW Sep 01 '10 at 21:31
  • Otherwise, if you buy a network card as an aftermarket add-on, then I think you'll find included in its box the card-specific device drivers for various O/Ses. – ChrisW Sep 01 '10 at 21:32
  • There are some "generic" APIs, more or less old (and possibly obsolete now), which may or may not be supported by any given card: e.g. [NE2000](http://en.wikipedia.org/wiki/NE2000). – ChrisW Sep 01 '10 at 21:34
-1

In x86-64 Linux, you can make system calls to use raw sockets.

global _start

section .text:
_start:
    ;sys_socket: rax, 41
    mov rax,41 

    ;sys_socket inputs:
    ;%rdi    %rsi  %rdx
    ;family  type  protocol

    mov rdi,2  ;AF_INET 
    mov rsi,2  ;DGRAM Socket
    mov rdx,0  ;protocol
    syscall

    ;sys_sendto: rax, 44
    ; I will do this later because rax holds the file desc 

    ;sys_sendto inputs:
    ;%rdi       %rsi  %rdx    %r10   %r8   %r9
    ;file desc  buff  lenght  flags  addr  addr-lenght
    mov rdi,rax  ;file desc
    mov rax,44   ;sys_sendto
    mov rsi,msg  ;buff
    mov rdx,msgl ;length
    mov r8,addr  ;addr
    mov r9,16    ;remember htons()??? that's why 16
    syscall


section .data:
    msg: db "hello"
    msgl: equ $-msg
    ;addr
    addr: dw 2
      db 10h,00h  ;htons()
      db 7fh,0h,0h,01h
      db 0,0,0,0,0,0,0,0

From a tutorial video: https://youtu.be/vOJoisKtR-A

Sushant
  • 71
  • 1
  • 3
  • 3
    This looks exactly like spam, since you didn't even mention a title or author for the video. But regardless, even if this video is some kind of guide or tutorial, link-only answers are off-topic for Stack Overflow. If you wrote an answer that describes what you have to do and/or includes some code, it would be ok to link something else as a "see more", but a link can't be the only thing in your answer. If you want to just post a relevant link, like https://wiki.osdev.org/Network_Stack, use a comment. (Which requires some rep, for obviously spam-filtering reasons.) – Peter Cordes Apr 01 '21 at 21:57
  • It's not a good idea to use `int 0x80` in 64-bit code, especially for system calls with pointer args: [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730) – Peter Cordes Apr 01 '21 at 23:06
  • @PeterCordes Sorry But The Question Mentions `x86` – Sushant Apr 01 '21 at 23:10
  • 1
    Yeah, and this code is for x86's 64-bit long mode: you can tell from the `r` register names, and use of `r8` and `r9`. Looks like you used the code from the video, and broke it by replacing `syscall` with `int 0x80` without changing to the 32-bit call numbers or porting to the 32-bit ABI's different calling convention (EBX, ECX, EDX, ... in that order, instead of RDI, RSI, RDX, ... in that order). In short, you should just change it back to `syscall`, for use on 64-bit x86 systems. You should try assembling + running this with `strace ./a.out` to see what system calls it makes. – Peter Cordes Apr 02 '21 at 02:46
  • UPDATED THE CODE :-) – Sushant Apr 02 '21 at 05:18