Multiple outgoing ipv6 addresses - c

I need to implement the following scheme (in C, however the language is not the case here):
client(192.168.1.2) <-> proxy(addr4: 192.168.1.1:1000, addr6: FE80:0000:0000:0000:0202:B3FF:FE1E:8329) <-> some_remote_host(remote_addr6)
The thing is addr6 on proxy side must be dynamically changed according to incoming ipv4 port. For example:
client connects to 192.168.1.1:1000, outgoing connection is made via addr6_0
client connects to 192.168.1.1:1001, outgoing connection is made via addr6_1
etc ...
The most straight-forward implementation would be: assign multiple static ipv6 addrs to ethernet interface and use bind() on socket before outgoing connection. The problem is that the number of incoming ports/outgoing addrs can be ~10000 (and as far as I understood recommended value for net.ipv6.conf.all.max_addresses is 32 or 64, default is 16).
The questions are:
What possible problems can I expect if I assign 10000 ipv6 addrs to one interface, I assume performance issues?
Is there a better way to achieve the goal?

Related

Packet forwarding event in Contiki

I am doing some work on worm-attack detection in RPL. In RPL, the communication between the clients might be multiple hops, with the packets going through many nodes.
However, only the receiver gets a tcpip_event on reception of the packet. The nodes that the route passes through do not get this event. Is there any way to detect the packet on the intermediate nodes?
You cannot get a notification or callback when a packet is forwarded. However, you can get a callback when a packet is received or sent by the lower layers.
In Contiki, use the function rime_sniffer_add for that. Check apps/powertrace/powertrace.c for an example.
In Contiki-NG the function has been renamed to netstack_sniffer_add.
Usage example:
Declare the sniffer like this, in the global scope:
RIME_SNIFFER(packet_sniffer, input_packet, output_packet);
Then add the sniffer from your code, once, at the start of the application execution:
rime_sniffer_add(&packet_sniffer);
The functions input_packet and output_packets are callbacks defined by you and can be used to examine the packets; for example, like this:
static void
input_packet(void)
{
int rssi = (int)packetbuf_attr(PACKETBUF_ATTR_RSSI);
printf("received a packet with RSSI=%d\n", rssi);
}

How can I update sofia when the current Ip address changes?

I have developed a small voip client application in C using sofia library and based on the sofia-sip client example.
Evertyhing works fine but one thing, if my Ip address changes once the application is running sofia doesn't update itself. I'll explain myself:
When I execute my voip application (running in Linux) sofia takes the current Ip address and the application will accept all the incoming calls to that address.
If the IP of the device where the application is running is changed (updating network config of Linux) i'm not able to update sofia in order to work with the new ip, therefore any incoming call is not received.
I've tried with ssc_set_public_address, which updates ssc_address and set the new value in nua using nua_set_params:
/**
* Sets the public address used for invites, messages,
* registrations, etc method.
*/
void ssc_set_public_address(ssc_t *ssc, const char *address)
{
if (address) {
su_free(ssc->ssc_home, ssc->ssc_address);
ssc->ssc_address = su_strdup(ssc->ssc_home, address);
nua_set_params(ssc->ssc_nua,
SIPTAG_FROM_STR(ssc->ssc_address),
TAG_NULL());
}
}
After doing it, it looks like the internal ip address has changed (if I read it using get_params I get the new one), however something is missed because no incoming call will be received.
In order to work with the new IP I need to reboot the whole application.
Does anybody know how to really update the sofia IP without rebooting the application?
Thank you.

Receiving different multicast with same source address on different interfaces

On a system with several network interfaces, I can have the same multicast address and port combination used on different networks, with different data on them. I want to be able to connect to them with several network cards and receive different data on each interface.
To do so, I bind to the interface I want to receive on using the IP_MULTICAST_IF option:
ip_mreqn mreqn;
memset(&mreqn, 0, sizeof (ip_mreqn));
mreqn.imr_multiaddr.s_addr = inet_addr(mc);
mreqn.imr_address.s_addr = INADDR_ANY;
mreqn.imr_ifindex = if_nametoindex(device);
if (setsockopt(mct->fd, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn)) < 0) {
perror("setsockopt multicast if");
return 1;
}
and make sure the join request is only sent on that interface by setting IP_ADD_MEMBERSHIP with the same structure:
if (setsockopt(mct->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn, sizeof(mreqn)) < 0) {
perror("setsockopt add membership");
return 1;
}
While the IP_ADD_MEMBERSHIP code works (the join request is only sent on the interface specified), the IP_MULTICAST_IF does not. Instead once it is able to join the multicast on any of the interfaces, I receive the same data through all sockets, even if they have different imr_ifindex set.
The IP_MULTICAST_IF ioctl does not control incoming selection, it is setting the socket's default interface for its outgoing multicast packets.
IP_ADD_MEMBERSHIP is the only mechanism for configuring incoming multicast and the memberships it creates are for the entire host, the host does not tailor delivery to individual sockets based on their requested memberships. (You can observe the hosts memberships with netstat -gn and the reference count is being used to determine when the host can stop observing, but not which sockets are receiving fan-out. If you have a matching membership from any socket, all sockets that made an applicable bind(2) will start receiving that multicast, even if they have never used IP_ADD_MEMBERSHIP.)
The usual method to differentiate these packets with out changing the system setup, is to receive them all on a socket using ancillary data to identify their interface. On Linux, this ancillary data setup is done with IP_PKTINFO as described in ip(7).

Refresh multicast group membership

I have several embedded machines listening and streaming rtp audio data to a multicast group. They are connected to a smart managed switch (Netgear GS108Ev2) which does basic igmp snooping and multicast filtering on its ports, so that the rest of my (W)LAN doesn't get flooded.
At start everything works fine for about 500-520 seconds. After that, they don't receive any more data until they leave and join the group again. I guess the switch is "forgetting" about the join after a timeout.
Is there any way to refresh the group membership, i.e. letting the switch know, that there ist still someone listening, without losing packets?
System info:
Arch: blackfin
# cat /proc/version
Linux version 2.6.28.10-ADI-2009R1-uCBF54x-EMM
(gcc version 4.3.3 (ADI) ) #158 PREEMPT Tue Jun 5 20:05:42 CEST 2012
This is the way multicast / the IGMP protocol works. A client has to join the group periodically by sending a Membership Report or it will be assumed that he has left the group after some short timeout. However, those reports are usually sent only when receiving a Membership Query from the local multicast router. Either your clients don't receive the query or don't respond with a report.
Try to use a tool like wireshark in order to see which IGMP packets are sent through your network.
You need an IGMP querier to send the Membership Queries, as was already explained by scai.
If you can't configure your router to do that, you can use one of your computers. Seeing how running a full multicast routing daemon would be overkill (and I've never done that), I suggest you try to abuse igmpproxy.
First create a dummy upstream interface (this is not persistent!):
ip tap add dev tap6 mode tap
Write igmpproxy.conf:
# Dummy upstream interface.
phyint tap6 upstream ratelimit 0 threshold 1
# Local interface.
phyint eth0 downstream ratelimit 0 threshold 1
# Explicitly disable any other interfaces (yes, it sucks).
phyint NAME disabled
...
Finally start igmpproxy (as root):
igmpproxy -v /path/to/igmpproxy.conf
If your embedded devices are running linux, you need to turn off the reverse packet filter on them or they won't respond to group membership queries. In that case the upstream switch will assume there is no-one listening to that multicast and switch it off.
I had same problem, multicast on wifi was lost after 260 seconds, I solved it with my application by adding AddSourceMembership on socket.
private void StartListner(IPAddress sourceIp, IPAddress multicastGroupIp, IPAddress localIp, int port)
{
try
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint localEndpoint = new IPEndPoint(localIp, port);
socket.Bind(localEndpoint);
byte[] membershipAddresses = new byte[12]; // 3 IPs * 4 bytes (IPv4)
Buffer.BlockCopy(multicastGroupIp.GetAddressBytes(), 0, membershipAddresses, 0, 4);
Buffer.BlockCopy(sourceIp.GetAddressBytes(), 0, membershipAddresses, 4, 4);
Buffer.BlockCopy(localIp.GetAddressBytes(), 0, membershipAddresses, 8, 4);
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddSourceMembership, membershipAddresses);
try
{
byte[] b = new byte[1024 * 2];
int length = socket.Receive(b);
}
catch { }
}
catch (Exception ex)
{
logger.Error("Exception: " + ex);
}
}

How do I receive a message after enabling loopback?

I have my multicast (udp) sender/receiver program up and running. If I use setsockopt to enable loopback with the sender like so:
if(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0)
error("loopback failed.");
and later on I send out the message to every subscriber, how does my sender get the message that's sent out? The sender doesn't store its own IP address and Port number and sent itself a message (basically subscribing to itself) does it?
So it should be something like:
receiver1 (subscription) -> sender
receiver2 (subscription) -> sender
when it's time to send:
sender (info) -> receiver1
sender (info) -> receiver2
sender (info) -> sender? //how does this step work?
Thanks for the help :)
In your code, loop must be of type u_char, not int. Of course, this will also change the final setsockopt() parameter to have the value 1. I have no personal experience of this, but W. Richard Stevens says so in UNIX Network Programming (3rd edition), Vol. 1, Section 21.6, so it must be so.
He also says that using type int here is a common programming error.
In addition to enabling loopback (which actually may be enabled by default, according to http://tldp.org/HOWTO/Multicast-HOWTO-6.html#ss6.1), you also need to subscribe to the multicast group.
It isn't necessary to send a separate copy of the packet to each receiver. If the multicast subscriptions are correct and you're on a network that supports multicast, then a single transmission is sufficient.

Resources