Age | Commit message (Collapse) | Author |
|
The ipifc->local generator is the big exception,
dumping the whole link structure of the interface.
|
|
when reading the status files from a conversation, ipread()
allocates a temporary buffer and calls the protocols
generator to fill the buffer and the calls
readstr() to handle the read request.
if the generator or readstr() erors, we must free the
temporary buffer.
also, allocate a more reasonable size for the "local"
and "remote" strings. allocating and zeroing 32K big
buffers for them is excessive.
|
|
|
|
relax the maclen check as v6 neighbour disicovery might
give bigger buffers as the medium uses for the mac
address size, as the packet does not contain exact byte
count but rounds all the options to multiples of 8.
drop neighbour discovery packets coming from interfaces
with zero-length maclen.
when dialing icmpv6 protocol with link-local address
for the local ip address, filter any packets to it that
come from a different interface. otherwise ipconfig
would see router advertisements from other interfaces.
fix the locking for ipifc ctl messages: properly
acquire the wlock and check that the interface is still
bound for every ctl messages touching the interface.
make add6 ipifc ctl message work for media with
zero-length maclen by using the interface identier
from pre-existing link-local address when available.
|
|
|
|
Generalize the arp proxy code, so one can create
specific routes for ip ranges that we want to arp
proxy for, not just for point-to-point interface
routes.
as we have source specific routes, this also
gives some control over which requester we will
reply to.
one example for this is a vps where we booked
another ip address on the ethernet, that we want
to route into a vpn tunnel. the new ip is in
subnet of the public ethernet interface, so all
we now need todo is add a route for that ip into
the vpn tunnel and set the proxy flag "y", and
we will respond to arp for that ip on the public
ethernet interface.
|
|
> It gets applied to any protocol type that is not pptp
> but should only process encapsulated ip4 packets.
|
|
|
|
AddrMaskRequest
|
|
icmpdontfrag() was not working properly, need to pass the
gating source interface. in fact, we now always pass the source
interface to all icmp*() functions, which is used to
determine source ip address of the icmp reply.
also dont generate a icmp response for packets going to
non-unicast addresses (such as broadcast).
increase the amount of icmp response payload, but keep
icmp responses below the minimum ipv4 mtu (68 bytes).
regularize icmpv6 function names.
move icmp unreachable codes to icmpv6.c.
provide the mtu value for icmppkttoobig6().
dont advise announced udp connections.
avoid code duplication in icmp.c and icmpv6.c,
by having single send function with type, code and arg
parameters.
maintain statistics for sent ipv4 icmp types.
avoid route lookup in ipout*() by passing Routehint* to
icmpnohost*().
iladvise()... more like ill advice.
|
|
We used to only clamp to the MTU of the destination interface,
but this is wrong. We have to clamp to the minimum of both
source and destination.
For this, we change the gating argument type of ipoput4()
and ipoput6() from int to Ipifc* to pass the source interface.
|
|
We falsely confused locally listening connections
as existing translation entires. Fix it.
|
|
If the interface does not support multicast, ignore it.
|
|
Allow accepting udp "connections" using a multicast local address.
Before, it was only possible to receive multicast using the headers
option. Having a connection orirented stream can be very usefull
when receiving multicast audio data. One gets a "connection" for
every source.
Implement (optional) support for IGMPv2 and MLDv1.
This can be usefull if bridges on the network have IGMP/MLD snooping
enabled, and wont forward multicast traffic unless we report what
we excpect. This is experimental for now, so the igmp protocol
must be manually added to the kernel configuration.
|
|
|
|
|
|
|
|
All the mediums we have implemented know their minimum
transmit unit. The minimum transfer unit is not adjustable
so there is no point in caching it in the ip interface.
|
|
Add arphit() function, handling validation and checking
for maximum life-time of the enty as well as copying
out the mac address.
|
|
|
|
Due to locking changes, it is possible for arpresolve()
to return multiple packets in the multicast case,
resulting in etherbwrite() to fail assert(bp->list == nil).
Ensure that arpresolve() always returns the first packet
from the hold chain and frees the rest if any.
For arpenter(), we want to transmit the whole chain of
packets, so we detach them from the arp entry before
calling arpresolve() and ignoring its result.
|
|
|
|
The len variable refers to the total length of a Block list
in ipoputX(), but we need to pass the size of the buffer
we pass instead, which can be less if there are multiple
blocks.
|
|
|
|
|
|
when forwarding packets (gating), unconditionally
check tcp-syn packets for the mss-size option and
reduce it to fit the mtu of the outgoing interface.
this is done by exporting a new tcpmssclamp() function
from ip/tcp.c that takes an ip packet and its buffer size
and the effective mtu of the interface and adjusts
the mss value of tcp syn options.
this function is now also used by devbridge, enforcing
a tcp mss below the tunnel mtu.
|
|
|
|
Superceding interface routes is handled specially,
only incrementing reference count, but need to take
the new Rtrans flag into account.
|
|
This avoids ipconfig having to explicitely specify the tag
when we want to set route type, as the tag can be provided
implicitely thru the "tag" command.
|
|
This makes the interface route have the "t"-flag,
which causes packets routed to the interface to get
source translated.
|
|
This adds a new route "t"-flag that enables network address translation,
replacing the source address (and local port) of a forwarded packet to
one of the outgoing interface.
The state for a translation is kept in a new Translation structure,
which contains two Iphash entries, so it can be inserted into the
per protocol 4-tuple hash table, requiering no extra lookups.
Translations have a low overhead (~200 bytes on amd64),
so we can have many of them. They get reused after 5 minutes
of inactivity or when the per protocol limit of 1000 entries
is reached (then the one with longest inactivity is reused).
The protocol needs to export a "forward" function that is responsible
for modifying the forwarded packet, and then handle translations in
its input function for iphash hits with Iphash.trans != 0.
This patch also fixes a few minor things found during development:
- Include the Iphash in the Conv structure, avoiding estra malloc
- Fix ttl exceeded check (ttl < 1 -> ttl <= 1)
- Router should not reply with ttl exceeded for multicast flows
- Extra checks for icmp advice to avoid protocol confusions.
|
|
Wlock()'ing the ifc causes a deadlock with Medium
bind/unbind as the routine can walk /net, while
ndb/dns or ndb/cs are currently blocked enumerating
/net/ipifc/*.
The fix is to have a fake medium, called "unbound",
that is set temporarily during the call of Medium
bind and unbind.
That way, the interface rwlock can be released while
bind/unbind is in progress.
The ipifcunbind() routine will refuse to unbind a
ifc that is currently assigned to the "unbound"
medium, preventing any accidents.
|
|
The ipoput4() and ipoput6() functions can raise an error(),
which means before calling sndrst() or limbo() (from tcpiput()),
we have to get rid of our blist by calling freeblist(bp).
Makse sure to set the Block pointer to nil after freeing in
ipiput() to avoid accidents.
Fix wrong panic string in sndsynack, and make any sending
functions like sndrst(), sndsynack() and tcpsendka()
return the value of ipoput*(), so we can distinguish
"no route" error.
Add a Enoroute[] string constant.
Both htontcp4() and htontcp6() can never return nil,
as they will allocate new or resize the existing block.
Remove the misleading error handling code that assumes
that it can fail.
Unlock proto on error in limborexmit() which can
be raised from sndsynack() -> ipoput*() -> error().
Make sndsynack() pass a Routehint pointer to ipoput*()
as it already did the route lookup, so we dont have todo
it twice.
|
|
|
|
i'm not confident about mutating the route tree
pointers and have concurrent readers walking the
pointer chains.
given that most route lookups are bypassed now
for non-routing case and we are not building a
high performance router here, lets play it safe.
|
|
theres no structure in the lower 32 bits of an ipv6 address.
use the top bit to distinguish special stuff like multicast
and link-local addresses, and use the 16-bit subnet-id bits
for the rest.
|
|
Instead of having to do an arp hash table lookup for each
outgoing ip packet, forward the Routehint pointer to the
medium's bwrite() function and let it cache the arp entry
pointer.
This avoids route and arp hash table lookups for tcp, il
and connection oriented udp.
It also allows us to avoid multiple route and arp table
lookups for the retransmits once an arp/neighbour solicitation
response arrives.
|
|
|
|
The IPv4 ARP cache used to indefinitely buffer packets in the Arpent hold list.
This is bad in case of a router, because it opens a 1 second
(retransmit time) window to leak all the to be forwarded packets.
This change makes the ipv4 arp code path similar to the IPv6 neighbour
solicitation path, using the retransmit process to time out old entries
(after 3 arp retransmits => 3 seconds).
A new function arpcontinue() has been added that unifies the point when
we schedule the (ipv6 sol retransmit) / (ipv4 arp timeout) and reduce
the hold queue to the last packet and unlock the cache.
As a bonus, we also now send a icmp host unreachable notification
for the dropped packets.
|
|
Added a ver= field to the filter to distinguish the ip version.
By default, a filter is parsed as ipv6, and after parsing
proto, src and dst fields are converted to ipv4. When no
ver= field is specified, a ip version filter is implicitely
added and both protocols are parsed.
This change also gets rid of the fast compare types as the
filed might not be aligned correctly in the packet.
This also fixes the ifc= filter, as we have to check any
local address.
|
|
|
|
We used to just return the first address of the incoming
interface regardless of if the address matches the source
ip type and scope.
This change tries to find the best interface address that
will match the source ip so it can be used as a source
address when replying to the packet.
|
|
ipiput4() and ipiput6() are called with the incoming interface rlocked
while ipoput4() and ipoput6() also rlock() the outgoing interface once
a route has been found. it is common that the incoming and outgoing
interfaces are the same recusive rlocking().
the deadlock happens when a reader holds the rlock for the incoming interface,
then ip/ipconfig tries to add a new address, trying to wlock the interface.
as there are still active readers on the ifc, ip/ipconfig process gets queued
on the inteface RWlock.
now the reader finds the outgoing route which has the same interface as the
incoming packet and tries to rlock the ifc again. but now theres a writer
queued, so we also go to sleep waiting four outselfs to release the lock.
the solution is to never wait for the outgoing interface rlock, but instead
use non-queueing canrlock() and if it cannot be acquired, discard the packet.
|
|
to prevent deadlock on media unbind (which is called with
the interface wlock()'ed), the medias reader processes
that unbind was waiting for used to discard packets when
the interface could not be rlocked.
this has the unfortunate side effect that when we change
addresses on a interface that packets are getting lost.
this is problematic for the processing of ipv6 router
advertisements when multiple RA's are getting received
in quick succession.
this change removes that packet dropping behaviour and
instead changes the unbind process to avoid the deadlock
by wunlock()ing the interface temporarily while waiting
for the reader processes to finish. the interface media
is also changed to the mullmedium before unlocking (see
the comment).
|
|
when making outgoing connections, the source ip was selected
by just iterating from the first to the last interface and
trying each local address until a route was found. the result
was kind of hard to predict as it depends on the interface
order.
this change replaces the algorithm with the route lookup algorithm
that we already have which takes more specific desination and
source prefixes into account. so the order of interfaces does
not matter anymore.
|
|
permission checking had the "other" and "owner" bits swapped plus incoming
connections where always owned by "network" instead of the owner of
the listening connection. also, ipwstat() was not effective as the uid
strings where not parsed.
this fixes the permission checks for data/ctl/err file and makes incoming
connections inherit the owner from the listening connection.
we also allow ipwstat() to change ownership to the commonuser() or anyone
if we are eve.
we might have to add additional restrictions for none at a later point...
|
|
(thanks joe9)
if the server responds without a window scale option in
its syn-ack, disable window scaling alltogether as both
sides need to understand the option.
|
|
the Ipselftab is designed to not require locking on read
operation. locking the selftab in ipselftabread() risks
deadlock when accessing the user buffer creates a fault.
remove unused fields from the Ipself struct.
|
|
check, consistent error strings
initialize the rate limits when the device gets
bound, not when it is created. so that the
rate limtis get reset to default when the ifc
is reused.
adjust the burst delay when the mtu is changed.
this is to make sure that we allow at least one
full sized packet burst.
make a local copy of ifc->m before doing nil
check as it can change under us when we do
not have the ifc locked.
specify Ebound[] and Eunbound[] error strings
and use them consistently.
|
|
|