How does one calculate ones link-local ipv6 address? - network-programming

So there are several sites that will calculate your link-local ipv6 address for you, like this one right here.
Nevertheless, it does not give any useful into as to how this address is calculated nor what the input parameters are. So what is the procedure(or algorithm)to compute a link local ipv6 address if one knows ones ipv4 address, subnet mask, and gateway address? I'm doing a project with SCTP sockets that uses ISATAP network tunneling and the LL ipv6 address is used in constructing the ISATAP address.

Appendix A of RFC 4291 describes the method for computing a modified EUI-64 from a MAC address. Once you have the modified EUI-64, you just put it in the lower 64 bits of the address and put fe80:: in the top 64 bits.
Basically you flip the 7th bit of the MAC address, and pack its first 24 bits (including the flipped bit), then fffe, then the lower 24 bits of the MAC address, resulting in 64 bits total.
That being said, your question is how to derive the link local address from the IPv4 address and subnet mask. That, you can't do. The IPv4 address and subnet mask (if indeed there is one – IPv6 does not require that IPv4 be running at all on the same interface) has nothing to do with the IPv6 address and the two aren't related in any way. The IPv4 gateway address (again, if there is one) is even less relevant.

The link-local address can be based on the MAC address per RFC 4862 or randomly generated as per RFC 4941.
Normally this should be limited to global scope, but some systems extend this privacy extension implementation to link-local scope. Follow this question on serverfault for discussion of the topic.

The previous answers failed to note that there is a defined procedure for generating a link local IPv6 address from an IPv4 address when using ISATAP, and there is a different process for generating a link local IPv6 address from a MAC address. The two things are unrelated.
For ISATAP, the 32-bit IPv4 address is prepended wit the 96 bits of either fe80::200:5efe or fe80::200:5efe to get the 128-bit IPv6 link-local address.
For MAC to IPv6, the 48-bit MAC address is split in half, 16 bits are inserted in the middle, those bits being ff:fe, then it is prepended by the 64-bit link-local prefix fe80::, and finally the 7th bit in the 5th IPv6 segment is flipped, to get the 128-bit IPv6 link-local address.
The following code provides examples showing how to use the The IPAddress library to do the conversions in either Java or Go. Disclaimer: I am the project manager of those libraries.
These examples also help to visualize the conversions described above.
Go:
func convertToIsatap(ipv4Str string, isGlobal bool) string {
ipv4Address := ipaddr.NewIPAddressString(ipv4Str).GetAddress().ToIPv4()
zero := &ipaddr.IPv6AddressSegment{}
segments := make([]*ipaddr.IPv6AddressSegment, ipaddr.IPv6SegmentCount)
segments[1], segments[2], segments[3], segments[4] = zero, zero, zero, zero
segments[0] = ipaddr.NewIPv6Segment(0xfe80)
segments[5] = ipaddr.NewIPv6Segment(0x5efe)
if isGlobal {
segments[4] = ipaddr.NewIPv6Segment(0x200)
}
ipv6Address, _ := ipv4Address.GetIPv6Address(ipaddr.NewIPv6Section(segments))
return ipv6Address.String()
}
func convertToLinkLocalIPv6(macAddr string) string {
macAddress := ipaddr.NewMACAddressString(macAddr).GetAddress()
ipv6LinkLocal, _ := macAddress.ToLinkLocalIPv6()
return ipv6LinkLocal.String()
}
fmt.Println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true))
fmt.Println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"))
Java:
static String convertToIsatap(String ipv4Str, boolean isGlobal) {
IPv4Address ipv4Address = new IPAddressString(ipv4Str).getAddress().toIPv4();
IPv6AddressSegment zeroSeg = new IPv6AddressSegment(0);
IPv6AddressSegment segments[] =
new IPv6AddressSegment[IPv6Address.SEGMENT_COUNT - 2];
segments[1] = segments[2] = segments[3] = segments[4] = zeroSeg;
segments[0] = new IPv6AddressSegment(0xfe80);
segments[5] = new IPv6AddressSegment(0x5efe);
if(isGlobal) {
segments[4] = new IPv6AddressSegment(0x200);
}
return ipv4Address.getIPv6Address(
new IPv6AddressSection(segments)).toString();
}
static String convertToLinkLocalIPv6(String macStr) {
MACAddress macAddress = new MACAddressString(macStr).getAddress();
return macAddress.toLinkLocalIPv6().toString();
}
System.out.println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true));
System.out.println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"));
The output is the same for both examples:
1.2.3.4 becomes ISATAP fe80::200:5efe:102:304
aa:bb:cc:11:22:33 becomes fe80::a8bb:ccff:fe11:2233

Related

How can I capture Gre or Vxlan inner network traffic?

I want to capture some network traffic with the filter like "src x.x.x.x and dst x.x.x.x".
Ususally it works, but it doesn't work when the network traffic is encapsulated by protocls like Gre or Vxlan.
For example, the Gre encapsulate a message like this:
Ethernet II, Src: VMware_91:f6:ad (00:0c:29:91:f6:ad), Dst: VMware_dc:c7:71 (00:0c:29:dc:c7:71)
Internet Protocol Version 4, Src: 10.75.2.161, Dst: 10.75.2.140
Generic Routing Encapsulation (Transparent Ethernet bridging)
Ethernet II, Src: Micro-St_e3:51:57 (4c:cc:6a:e3:51:57), Dst: VMware_91:f6:ad (00:0c:29:91:f6:ad)
Internet Protocol Version 4, Src: 10.75.2.11, Dst: 10.75.2.160
So what should I do to capture those inner traffic?
I use "src 10.75.2.160" to capture but it tcpdump captured nothing.
tcpdump -i eth0 "src 10.75.2.11"
It doesn't work.
I use "ip[54:4]" to capture, it works, but my leader tell me it's not accurate.
So what else can I try?
I don't know how accurate your leader wants the filter, but if we can make a few assumptions about the outer IP and GRE headers, then the filter isn't too complicated. So here are the 2 assumptions:
The outer IP header is a standard 20 bytes. If this isn't the case or can't be relied upon, then everywhere I use 20 in the filter will need to be replaced with the IP header length calculation, which is (ip[0] & 0x0f) * 4.
The GRE header is a standard size of 4 bytes. If options are present and you can guarantee that all GRE headers are exactly the same size, then you can substitute 4 for the actual GRE header length, but if GRE options could vary, then it should still be possible to specify a capture filter that works with any size GRE header, but it will be much more complicated and hard to follow. I leave that as an exercise for the reader.
With those assumptions out of the way, here's a filter that would be the equivalent of "src 10.75.2.11" but for the inner source IP address of a IP/GRE/IP packet:
(ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b0x0b)
Explanation:
ip proto 47: This captures only IP/GRE packets as GRE is assigned protocol number 47.
ip[20 + 2:2] = 0x0800: Since 0x0800 is the assigned Ethertype for IPv4, this captures only GRE packets where the Protocol Type field is IP, so only IP/GRE/IP packets. (NOTE: RFC 1701 states, "The Protocol Type field contains the protocol type of the payload packet. In general, the value will be the Ethernet protocol type field for the packet.")
ip[20 + 4 + 12:4] = 0x0a4b020b: This captures only the IP/GRE/IP packets where the source IP address field of the inner IP header is 10.75.2.11. (NOTE: To get 0x0a4b020b from 10.75.2.11, you just need to convert each decimal octet to hexadecimal and combine them into a single 4 byte value.)
To verify the resulting BPF code, you can run tcpdump with the -d option to check that the filter meets your expectations, for example:
tcpdump -i eth0 "(ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b020b)"
You should see output of the following form:
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 9
(002) ldb [23]
(003) jeq #0x2f jt 4 jf 9
(004) ldh [36]
(005) jeq #0x800 jt 6 jf 9
(006) ld [50]
(007) jeq #0xa4b020b jt 8 jf 9
(008) ret #262144
(009) ret #0
If you're not familiar with BPF code, then I would suggest further reading elsewhere, as providing a BPF tutorial here is beyond the scope of this answer.
Finally, if you need to filter for the source IP address whether it's in the outer IP header or the inner IP header, then you can basically just combine the 2 filters, i.e.:
"(ip src 10.75.2.11) || ((ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b020b))"

What port byte order is used in URL?

When you want to bind to port in C you have to use htons(port) to convert the port from host byte order to network byte order. This happens because the port number is copied directly to the TCP packets, so they have to match on little-endian and big-endian machines.
Consider the following example in C:
int port = 5000;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
Notice the use of htons. Now, if you run netstat -anp --tcp (on Linux) you'll see that 0.0.0.0:5000 is being listened. It looks like the port number uses host endianness.
Now, a question arises: if port number is host-endian in URL, does this mean that a big-endian client can't use http://a.b.c.d:5000 URL to connect to a little-endian server listening on 0.0.0.0:5000?
No, you're almost certainly misapplying the rules at the wrong abstraction level.
The local browser, in all likelihood, will grab the :5000 string off the end of the URL and use that to create the integer 5000 in host format. It will then pass that to htons as part of constructing the session, in exactly the same way your code snippet does.
And, voila, the structures contain the correct network order.

Wireshark filters: Difference between !(ip.addr == 192.0.2.1) and (ip.addr != 192.0.2.1)

Regarding the filters in Wireshark, what is the differencebetween !(ip.addr == 192.0.2.1) and (ip.addr != 192.0.2.1)? When check the result, it's not giving the same result and I don't know why...
Plus, when I apply the filter (ip.addr != 192.0.2.1) appears a different color as background in filters (Yellow).
image
Does anyone can help me? Thanks in advance.
In Boolean Logic, A not equals B and not A equals B are the same test.
But, the relevant part of the WireShark documentation linked by Jürgen Thelen explains that in WireShark, ip.addr covers both the source and destination field, so the test is more like:
not ((A or B) equals C)
which filters packets where source or destination match, and then hides them (correctly).
Compared to:
(A or B) not equals C
which filters packets where either the source OR the destination is not C, and that's every packet, so it shows every packet.
6.4.6. A Common Mistake
Using the != operator on combined expressions like eth.addr, ip.addr, tcp.port, and udp.port will probably not work as expected.
Often people use a filter string to display something like ip.addr == 1.2.3.4 which will display all packets containing the IP address 1.2.3.4.
Then they use ip.addr != 1.2.3.4 to see all packets not containing the IP address 1.2.3.4 in it. Unfortunately, this does not do the expected.
Instead, that expression will even be true for packets where either source or destination IP address equals 1.2.3.4. The reason for this, is that the expression ip.addr != 1.2.3.4 must be read as “the packet contains a field named ip.addr with a value different from 1.2.3.4”. As an IP datagram contains both a source and a destination address, the expression will evaluate to true whenever at least one of the two addresses differs from 1.2.3.4.
The reason it takes a yellow background is because of this potentially surprising behaviour, and there is a matching warning at the bottom of the screen, in the status bar, suggesting checking the user guide for more details:
Suppose we want to filter out any traffic to or from 10.43.54.65. We might try the following:
ip.addr != 10.43.54.65.
This translates to "pass all traffic except for traffic with a source IPv4 address of 10.43.54.65 and a destination IPv4 address of 10.43.54.65".
! ( ip.addr == 10.43.54.65 ).
This translates to "pass any traffic except with a source IPv4 address of 10.43.54.65 or a destination IPv4 address of 10.43.54.65".
You can see more on this at Wireshark: DisplayFilters.

Does all subnets have a broadcast/network address?

I am setting up a peer 2 peer network and i cant find if my 2 subnets will both have a network and broadcast?
x.x.x.0 and x.x.x.127 will be my first subnet's broadcast/network.
x.x.x.128 and x.x.x.255 will be the second subnet broadcast/network addresses.
or is it just x.x.x.0 and x.x.x.255 that are the broadcast/network addresses?
This is defined by the subnetmask, which is why you normally write IP addresses as:
192.168.1.24/24
This means the network address is 192.168.1.0 and the broadcast address 192.168.1.255. The network part of the is /24 bits, and host id is 8 bits. For the broadcast address you always set all the host id bits to 1 (8 bits set to one = 255), and for the network address you set it to 0.
Both subnet's will have the broadcast/network ip's so there will be -4 ip in the total amount of valip ip addresses in the entire subnet.

How calculate RAM address form 23bit normal adress to row,col and bank address?

I'm making some stuff in VHDL. I got 23bit address from CPU and I need to convert it to address in RAM. But! Interface from RAM side is: 12bit row addres, 9bit col address and 2bit bank address.
I try to get something like this: Bank1 = {0,4,8,12,...}, Bank2 { 1,5,9,13,...}, Bank3 {2,6,10,14,...} and Bank4 = {3,7,11,15,...}.
I have no idea how to convert 23bit address to 12bit + 9bit + 2bit combination.

Resources