summaryrefslogtreecommitdiff
path: root/proto/ospf/packet.c
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2014-02-06 17:46:01 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2014-02-06 17:46:01 +0100
commit48e5f32db676645640f84ab3d630cce975aa6b20 (patch)
treeb940fc8156b3e0c18aab6c339a066bdb7a9ec1e0 /proto/ospf/packet.c
parentf48fa14214301382b2e6b134788a7506b61b664f (diff)
Many changes in I/O and OSPF sockets and packet handling.
I/O: - BSD: specify src addr on IP sockets by IP_HDRINCL - BSD: specify src addr on UDP sockets by IP_SENDSRCADDR - Linux: specify src addr on IP/UDP sockets by IP_PKTINFO - IPv6: specify src addr on IP/UDP sockets by IPV6_PKTINFO - Alternative SKF_BIND flag for binding to IP address - Allows IP/UDP sockets without tx_hook, on these sockets a packet is discarded when TX queue is full - Use consistently SOL_ for socket layer values. OSPF: - Packet src addr is always explicitly set - Support for secondary addresses in BSD - Dynamic RX/TX buffers - Fixes some minor buffer overruns - Interface option 'tx length' - Names for vlink pseudoifaces (vlinkX) - Vlinks use separate socket for TX - Vlinks do not use fixed associated iface - Fixes TTL for direct unicast packets - Fixes DONTROUTE for OSPF sockets - Use ifa->ifname instead of ifa->iface->name
Diffstat (limited to 'proto/ospf/packet.c')
-rw-r--r--proto/ospf/packet.c54
1 files changed, 36 insertions, 18 deletions
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index 4338bc1a..cd4b8a97 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -39,7 +39,6 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
unsigned
ospf_pkt_maxsize(struct ospf_iface *ifa)
{
- unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
unsigned headers = SIZE_OF_IP_HEADER;
#ifdef OSPFv2
@@ -47,7 +46,7 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)
headers += OSPF_AUTH_CRYPT_SIZE;
#endif
- return mtu - headers;
+ return ifa->tx_length - headers;
}
#ifdef OSPFv2
@@ -263,7 +262,7 @@ ospf_rx_hook(sock *sk, int size)
return 1;
DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
- sk->iface->name, sk->faddr, sk->laddr);
+ sk->ifname, sk->faddr, sk->laddr);
/* Initially, the packet is associated with the 'master' iface */
struct ospf_iface *ifa = sk->data;
@@ -321,22 +320,31 @@ ospf_rx_hook(sock *sk, int size)
return 1;
}
- int osize = ntohs(ps->length);
- if ((unsigned) osize < sizeof(struct ospf_packet))
+ uint plen = ntohs(ps->length);
+ if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
{
- log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, osize);
+ log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
return 1;
}
- if ((osize > size) || ((osize % 4) != 0))
+ if (sk->flags & SKF_TRUNCATED)
{
- log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size);
+ log(L_WARN "%s%I - too large (%d/%d)", mesg, sk->faddr, plen, size);
+
+ /* If we have dynamic buffers and received truncated message, we expand RX buffer */
+
+ uint bs = plen + 256;
+ bs = BIRD_ALIGN(bs, 1024);
+
+ if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
+ sk_set_rbsize(sk, bs);
+
return 1;
}
- if ((unsigned) size > sk->rbsize)
+ if (plen > size)
{
- log(L_ERR "%s%I - too large (%d vs %d)", mesg, sk->faddr, size, sk->rbsize);
+ log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
return 1;
}
@@ -349,7 +357,7 @@ ospf_rx_hook(sock *sk, int size)
#ifdef OSPFv2
if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
(!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
- osize - sizeof(struct ospf_packet), NULL)))
+ plen - sizeof(struct ospf_packet), NULL)))
{
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
return 1;
@@ -448,7 +456,7 @@ ospf_rx_hook(sock *sk, int size)
if(!n && (ps->type != HELLO_P))
{
log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
- sk->faddr, ifa->iface->name);
+ sk->faddr, ifa->ifname);
return 1;
}
@@ -495,20 +503,30 @@ ospf_rx_hook(sock *sk, int size)
return 1;
}
+/*
void
ospf_tx_hook(sock * sk)
{
struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
// struct proto *p = (struct proto *) (ifa->oa->po);
- log(L_ERR "OSPF: TX hook called on %s", ifa->iface->name);
+ log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
}
+*/
void
ospf_err_hook(sock * sk, int err)
{
struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
-// struct proto *p = (struct proto *) (ifa->oa->po);
- log(L_ERR "OSPF: Socket error on %s: %M", ifa->iface->name, err);
+ struct proto *p = &(ifa->oa->po->proto);
+ log(L_ERR "%s: Socket error on %s: %M", p->name, ifa->ifname, err);
+}
+
+void
+ospf_verr_hook(sock *sk, int err)
+{
+ struct proto_ospf *po = (struct proto_ospf *) (sk->data);
+ struct proto *p = &po->proto;
+ log(L_ERR "%s: Vlink socket error: %M", p->name, err);
}
void
@@ -543,9 +561,9 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
#endif
ospf_pkt_finalize(ifa, pkt);
- if (sk->tbuf != sk->tpos)
- log(L_ERR "Aiee, old packet was overwritten in TX buffer");
- sk_send_to(sk, len, dst, 0);
+ int done = sk_send_to(sk, len, dst, 0);
+ if (!done)
+ log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
}