diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2014-02-06 17:46:01 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2014-02-06 17:46:01 +0100 |
commit | 48e5f32db676645640f84ab3d630cce975aa6b20 (patch) | |
tree | b940fc8156b3e0c18aab6c339a066bdb7a9ec1e0 /proto/ospf/packet.c | |
parent | f48fa14214301382b2e6b134788a7506b61b664f (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.c | 54 |
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); } |