Adding multiple ipv6 addresses to a single interface using ioctl - c

I am trying to port my application to ipv6 and my current code brings up alias IP addresses dynamically as shown:
eth0 Link encap:Ethernet HWaddr 00:16:35:68:21:5B
inet addr:192.168.1.245 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::216:35ff:fe68:215b/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:278885750 errors:0 dropped:0 overruns:0 frame:0
TX packets:68117973 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:68976932662 (64.2 GiB) TX bytes:39384521280 (36.6 GiB)
Interrupt:169
eth0:1 Link encap:Ethernet HWaddr 00:16:35:68:21:5B
inet addr:192.168.1.246 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MTU:1500 Metric:1
Interrupt:169
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:6060179 errors:0 dropped:0 overruns:0 frame:0
TX packets:6060179 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2366257047 (2.2 GiB) TX bytes:2366257047 (2.2 GiB)
eth0:1 will be added dynamically by the application. It uses ioctl to do this. I want to do the same for IPV6 address. I tried this Assign ipv6 address using ioctl. But the example code is adding IPV6 address to the existing interface eth0 instead of eth0:1 or eth0:2 even if I specify the interface name as eth0:1. Can anyone please help since I am new to IPV6.

This is normal behaviour. In IPv4 each interface could have only one address. To add more addresses you had to create 'fake' interfaces like eth0:1. IPv6 always has multiple addresses per interface so work-arounds like eth0:1 are not used for IPv6.

Related

Cannot SSH into QEMU virtual machine running dropbear sshd

I have set up a QEMU virtual machine emulating the vexpress-a9 machine. I've used buildroot to create the initrd system and I've used the codesourcery cross-compiler that buildroot downloads as part of it's setup to compile the Linux Kernel. This is how I invoke qemu
qemu-system-arm -m 512 -M vexpress-a9
-dtb linux-4.4.192/arch/arm/boot/dts/vexpress-v2p-ca9.dtb
-kernel linux-4.4.192/arch/arm/boot/zImage
-initrd buildroot/output/images/rootfs.cpio
-append "console=ttyAMA0,ip=dhcp"
-net nic,model=lan9118
-net user,hostfwd=tcp::2222-:22
-nographic
It boots just fine. Network related boot messages that tell that the network has been initialized and dropbear sshd was brought up and running:
Starting network: OK
Starting dropbear sshd: random: dropbear: uninitialized urandom read (32 bytes read, 1 bits of entropy available)
OK
however the eth0 interface has to be assigned an IP manually. I assign it an unused class C address in the same subnet as my Linux host like so:
# ifconfig eth0 192.168.160.150 up
smsc911x 4e000000.ethernet eth0: SMSC911x/921x identified at 0xa12a0000, IRQ: 31
So ifconfig now shows:
# ifconfig
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet addr:192.168.160.150 Bcast:192.168.160.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:31
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
netstat tells me that we are listening on port 22:
# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
I can even ssh into localhost like so:
# ssh root#127.0.0.1
random: ssh: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
random: dropbear: uninitialized urandom read (32 bytes read, 24 bits of entropy available)
Host '127.0.0.1' is not in the trusted hosts file.
(ecdsa-sha2-nistp256 fingerprint sha1!! de:cf:f8:b3:ac:4d:96:47:22:d7:76:a1:ea:11:3d:bc:ec:c6:71:9a)
Do you want to continue connecting? (y/n) y
root#127.0.0.1's password:
random: dropbear: uninitialized urandom read (32 bytes read, 26 bits of entropy available)
whereas from the host this is what I see when I try to SSH into this VM from the linux host:
$ ssh -vvv root#192.168.160.150
OpenSSH_7.4p1 Debian-10+deb9u7, OpenSSL 1.0.2s 28 May 2019
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug2: resolving "192.168.160.150" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to 192.168.160.150 [192.168.160.150] port 22.
debug1: connect to address 192.168.160.150 port 22: No route to host
ssh: connect to host 192.168.160.150 port 22: No route to host
I would be pleased to have some pointers about this as I cannot find what else can be tried
UPDATE 1: Included dhcpd while configuring buildroot. Now irrespective of whether I use dropbear or openssh, the log messages appear until
Starting dhcpcd...
no interfaces have a carrier <--- the problem
forked to background, child pid 746
smsc911x 4e000000.ethernet eth0: SMSC911x/921x identified at 0xa12a0000, IRQ: 31
Starting dropbear sshd: random: dropbear: uninitialized urandom read (32 bytes read, 2 bits of entropy available)
OK
random: dhcpcd: uninitialized urandom read (120 bytes read, 2 bits of entropy available)
at which point it just kind of stops and I cannot see the login prompt. Upon removing dhcpd and using either dropbear or openssh, I can see the login prompt again (meaning all the init scripts run to completion) but again no connectivity of any kind. I can't understand why in the world does dhcpd thinks we have no carrier (when it is able to enumerate and identify the emulated NIC card)
UPDATE2: I've tried invoking udhcpc manually to obtain an address via DHCP and it does get an address
# udhcpc -S -a100
udhcpc: started, v1.31.0
udhcpc: sending discover
udhcpc: sending select for 10.0.2.15
udhcpc: lease of 10.0.2.15 obtained, lease time 86400
deleting routers
adding dns 10.0.2.3
# ifconfig
eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56
inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2360 (2.3 KiB) TX bytes:1428 (1.3 KiB)
Interrupt:31
The machine is still however inaccessible from the host. Do I need to add a manual route to this VM from the host? If yes how do I do that? Does QEMU create a virtual interface on the host (like workstation does)?
If you're using QEMU's 'user' mode networking, then trying to assign the guest an IP address in your host's network is wrong. User mode network creates a little emulated network with its own DHCP server -- you can see a diagram of this at https://wiki.qemu.org/Documentation/Networking#User_Networking_.28SLIRP.29
By default the network the guest sits on is 10.0.2.x, but you can change it with command line arguments.
The simplest way to configure the guest is to have it run a DHCP client, which should be able to find the built-in DHCP server QEMU provides it and get an IP address on the emulated-network that way.
An important point about user mode networking is that it does not allow you to generally connect directly to the guest VM from the host. The only way to connect to it is if your QEMU command line specifies particular ports to forward from the host to the guest -- if you do that then you can connect to the host IP address and port that you specified in the command line forwarding option and it will be forwarded to the guest's IP address and port on the emulated network.
If this is not sufficient and you need the VM to appear on a real virtual interface that is bridged to the host's networking, then you should stop using user mode networking and look at the TAP networking option instead. TAP is however more complicated to set up.
I spent hours yesterday trying different options (i.e. -net, -netdev) with qemu-system-arm, but finally what worked was this one option: -nic user,hostfwd=::2222-:22 Which I learned from the list of removed features page (look at replacement of -redir option). I also had to add these 3 lines in my host's SSH config file: /etc/ssh/ssh_config
Host localhost
PreferredAuthentications=password
PubkeyAuthentication=no

How to send a packet to the kernel?

I have two interfaces in my Linux system - eth0 and eth1. I have opened a raw socket on eth0 and I am listening on it for incoming packets. When a packet comes from eth0, I forward it to eth1 after changing the ethernet header (specifically destination MAC to eth1's MAC address). The packet should now be accepted by the interface and sent to the kernel for further processing and eventually to the application waiting for it. But for some reason the packet reaches eth1 (as I can see from wireshark) but the application does not receive it (the application is ping and I don't see the ping reply).
How do I send the packet to eth1 such that it is accepted and sent upstream to the kernel?
There is probably a misunderstanding here:
If you send a packet through a raw socket on an interface, in your case eth1, it will not be treated as local to the kernel, regardless of its mac-address, but will leave the interface to the network (with its own mac-address as destination). This is what you observe with wireshark.
If you want the packet to be processed by your kernel, send it to the lo-interface (Loopback-interface), which is specifically for that purpose.

Request MAC address from Raspberry Pi

I have a Linux machine that is connected directly to a Raspberry Pi via an Ethernet cable. Is there a way to programmatically in C get the Raspberry Pi's MAC address based on which Ethernet port on my computer it is connected to (eth0, eth1 etc...)
For instance, say I have two Raspberry Pi's, one connected to eth0 and another to eth1. I would like to get the MAC address of only the Pi that is connected to eth0. How would I do that?
Depending on do you know the ip address of the Pi, there are two cases:
The Pi has IP address and are known to your program, you can just send any data to it, e.g. an ICMP PING packet, the networking stack will send out ARP requests for the address, and when the Pi respond with its MAC address, you can get it from the ARP table, which can be viewed by the command arp -n.
The Pi's IP is not known, then you send a broadcast packet through the connected interface, eth0 in this case, for example, ping -b -I eth0 255.255.255.255, the Pi will also respond with its MAC address, and you can get it from the local arp table.
Now for how to do this in programmatic way, you can send the packet using raw sockets, and read arp table through parsing the proc entry /proc/net/arp.

Can u-boot support more than one ethernet port?

I want to ping out of multiple ethernet ports. Is there an inherent restriction where u-boot only supports a single ethernet port?
Can u-boot support more than one ethernet port?
Yes, in recent versions of U-Boot (going back to at least 2012.10).
Salient code is eth_current_changed() and eth_set_current() in net/eth.c.
Is there an inherent restriction where u-boot only supports a single ethernet port?
No, recent versions of U-Boot can support more than one Ethernet port on the board.
When more than one Ethernet interface is available (as reported by the "Net" device list on startup, e.g. "Net: macb0, gmac0, usb_ether"), the environment variable ethact is used to define the selected Ethernet interface that is active.
Use the printenv ethact command to view the current selection.
Use the setenv ethact <port name> to change the active Ethernet port.
The U-Boot network commands, such as ping and tftpboot, will use the Ethernet port defined by the ethact variable. This preserves the command syntax with older versions of U-Boot, and the syntax is consistent regardless of the number of available ports (e.g. scripts do not change).
Each Ethernet port is assigned its own MAC address, using the following environment variables:
ethaddr: Ethernet MAC address for first/only ethernet interface (= eth0 in Linux).
This variable can be set only once (usually during manufacturing of the board). U-Boot refuses to delete or overwrite this variable once it has been set.
eth1addr: Ethernet MAC address for second ethernet interface (= eth1 in Linux).
eth2addr: Ethernet MAC address for third ethernet interface (= eth2 in Linux).
Obviously you can only (easily) access one port at a time.
There is also only one static IP address assignment, i.e. the ipaddr environment variable.
(I don't know what happens with an IP address acquired by DHCP using one port, and then the active port is changed.)
U-Boot> printenv ethact
ethact=macb0
U-Boot> setenv ethact gmac0
U-Boot> ping 192.168.1.1
gmac0: PHY present at 7
gmac0: Starting autonegotiation...
gmac0: Autonegotiation complete
gmac0: link up, 1000Mbps full-duplex (lpa: 0x2800)
Using gmac0 device
host 192.168.1.1 is alive
U-Boot>
Note that there also a rotation scheme that automatically changes the active port when the ports are down:
U-Boot> printenv ethact
ethact=gmac0
U-Boot> ping 192.168.1.1
gmac0: PHY present at 7
gmac0: Starting autonegotiation...
gmac0: Autonegotiation timed out (status=0x7949)
gmac0: link down (status: 0x7949)
ERROR: Need valid 'usbnet_devaddr' to be set
at drivers/usb/gadget/ether.c:2362/usb_eth_init()
macb0: PHY present at 0
macb0:0 is connected to macb0. Reconnecting to macb0
macb0: Starting autonegotiation...
macb0: Autonegotiation timed out (status=0x7849)
macb0: link up, 100Mbps full-duplex (lpa: 0x41e1)
Using macb0 device
ping failed; host 192.168.1.1 is not alive
U-Boot> printenv ethact
ethact=macb0
U-Boot>

How to include an IP packet in C linux sockets?

I want to include an IP packet in Socket programming. I have a readymade Ip packet which contains igmp packet. I don't want to design igmp protocol but want to use that packet to sent igmp query. By some how the Ip packet I have must be recognize as IP packet and not as TCP/UDP data.
You have to use the raw socket with sendmsg. This need root permission.
And if you want to send IGMP packets you should use the setsockopt() API to do so.

Resources