mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Merge commit '48e5f32db676645640f84ab3d630cce975aa6b20' into integrated
This commit is contained in:
commit
c93f50635c
@ -2212,7 +2212,9 @@ protocol ospf <name> {
|
||||
wait <num>;
|
||||
dead count <num>;
|
||||
dead <num>;
|
||||
secondary <switch>;
|
||||
rx buffer [normal|large|<num>];
|
||||
tx length <num>;
|
||||
type [broadcast|bcast|pointopoint|ptp|
|
||||
nonbroadcast|nbma|pointomultipoint|ptmp];
|
||||
strict nonbroadcast <switch>;
|
||||
@ -2419,12 +2421,32 @@ protocol ospf <name> {
|
||||
<tag>dead <M>num</M></tag>
|
||||
When the router does not receive any messages from a neighbor in
|
||||
<m/dead/ seconds, it will consider the neighbor down. If both directives
|
||||
<m/dead count/ and <m/dead/ are used, <m/dead/ has precendence.
|
||||
<cf/dead count/ and <cf/dead/ are used, <cf/dead/ has precendence.
|
||||
|
||||
<tag>secondary <M>switch</M></tag>
|
||||
On BSD systems, older versions of BIRD supported OSPFv2 only for the
|
||||
primary IP address of an interface, other IP ranges on the interface
|
||||
were handled as stub networks. Since v1.4.1, regular operation on
|
||||
secondary IP addresses is supported, but disabled by default for
|
||||
compatibility. This option allows to enable it. The option is a
|
||||
transitional measure, will be removed in the next major release as the
|
||||
behavior will be changed. On Linux systems, the option is irrelevant, as
|
||||
operation on non-primary addresses is already the regular behavior.
|
||||
|
||||
<tag>rx buffer <M>num</M></tag>
|
||||
This sets the size of buffer used for receiving packets. The buffer should
|
||||
be bigger than maximal size of any packets. Value NORMAL (default)
|
||||
means 2*MTU, value LARGE means maximal allowed packet - 65535.
|
||||
This option allows to specify the size of buffers used for packet
|
||||
processing. The buffer size should be bigger than maximal size of any
|
||||
packets. By default, buffers are dynamically resized as needed, but a
|
||||
fixed value could be specified. Value <cf/large/ means maximal allowed
|
||||
packet size - 65535.
|
||||
|
||||
<tag>tx length <M>num</M></tag>
|
||||
Transmitted OSPF messages that contain large amount of information are
|
||||
segmented to separate OSPF packets to avoid IP fragmentation. This
|
||||
option specifies the soft ceiling for the length of generated OSPF
|
||||
packets. Default value is the MTU of the network interface. Note that
|
||||
larger OSPF packets may still be generated if underlying OSPF messages
|
||||
cannot be splitted (e.g. when one large LSA is propagated).
|
||||
|
||||
<tag>type broadcast|bcast</tag>
|
||||
BIRD detects a type of a connected network automatically, but
|
||||
|
@ -157,13 +157,13 @@ rfree(void *res)
|
||||
{
|
||||
resource *r = res;
|
||||
|
||||
if (r)
|
||||
{
|
||||
if (r->n.next)
|
||||
rem_node(&r->n);
|
||||
r->class->free(r);
|
||||
xfree(r);
|
||||
}
|
||||
if (!r)
|
||||
return;
|
||||
|
||||
if (r->n.next)
|
||||
rem_node(&r->n);
|
||||
r->class->free(r);
|
||||
xfree(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -408,6 +408,9 @@ mb_realloc(void *m, unsigned size)
|
||||
void
|
||||
mb_free(void *m)
|
||||
{
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
struct mblock *b = SKIP_BACK(struct mblock, data, m);
|
||||
rfree(b);
|
||||
}
|
||||
|
19
lib/socket.h
19
lib/socket.h
@ -59,6 +59,9 @@ int sk_open(sock *); /* Open socket */
|
||||
int sk_send(sock *, unsigned len); /* Send data, <0=err, >0=ok, 0=sleep */
|
||||
int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to given destination */
|
||||
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
|
||||
void sk_set_rbsize(sock *s, uint val); /* Resize RX buffer */
|
||||
void sk_set_tbsize(sock *s, uint val); /* Resize TX buffer, keeping content */
|
||||
void sk_set_tbuf(sock *s, void *tbuf); /* Switch TX buffer, NULL-> return to internal */
|
||||
void sk_dump_all(void);
|
||||
int sk_set_ttl(sock *s, int ttl); /* Set transmit TTL for given socket */
|
||||
int sk_set_min_ttl(sock *s, int ttl); /* Set minimal accepted TTL for given socket */
|
||||
@ -85,7 +88,6 @@ static inline int sk_is_ipv4(sock *sk)
|
||||
static inline int sk_is_ipv6(sock *sk)
|
||||
{ return sk->af == AF_INET6; }
|
||||
|
||||
|
||||
extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */
|
||||
|
||||
/* Socket flags */
|
||||
@ -93,10 +95,13 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
|
||||
#define SKF_V4ONLY 0x01 /* Use IPv4 for IP sockets */
|
||||
#define SKF_V6ONLY 0x02 /* Use IPV6_V6ONLY socket option */
|
||||
#define SKF_LADDR_RX 0x04 /* Report local address for RX packets */
|
||||
#define SKF_LADDR_TX 0x08 /* Allow to specify local address for TX packets */
|
||||
#define SKF_TTL_RX 0x10 /* Report TTL / Hop Limit for RX packets */
|
||||
#define SKF_TTL_RX 0x08 /* Report TTL / Hop Limit for RX packets */
|
||||
#define SKF_BIND 0x10 /* Bind datagram socket to given source address */
|
||||
|
||||
#define SKF_THREAD 0x100 /* Socked used in thread, Do not add to main loop */
|
||||
#define SKF_TRUNCATED 0x200 /* Received packet was truncated, set by IO layer */
|
||||
#define SKF_HDRINCL 0x400 /* Used internally */
|
||||
#define SKF_PKTINFO 0x800 /* Used internally */
|
||||
|
||||
/*
|
||||
* Socket types SA SP DA DP IF TTL SendTo (?=may, -=must not, *=must)
|
||||
@ -122,6 +127,14 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shoul
|
||||
* call sk_setup_multicast() to enable multicast on that socket,
|
||||
* and then use sk_join_group() and sk_leave_group() to manage
|
||||
* a set of received multicast groups.
|
||||
*
|
||||
* For datagram (SK_UDP, SK_IP) sockets, there are two ways to handle
|
||||
* source address. The socket could be bound to it using bind()
|
||||
* syscall, but that also forbids the reception of multicast packets,
|
||||
* or the address could be set on per-packet basis using platform
|
||||
* dependent options (but these are not available in some corner
|
||||
* cases). The first way is used when SKF_BIND is specified, the
|
||||
* second way is used otherwise.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
@ -230,7 +230,7 @@ bfd_open_tx_sk(struct bfd_proto *p, ip_addr local, struct iface *ifa)
|
||||
sk->tos = IP_PREC_INTERNET_CONTROL;
|
||||
sk->priority = sk_priority_control;
|
||||
sk->ttl = ifa ? 255 : -1;
|
||||
sk->flags = SKF_THREAD;
|
||||
sk->flags = SKF_THREAD | SKF_BIND;
|
||||
|
||||
#ifdef IPV6
|
||||
sk->flags |= SKF_V6ONLY;
|
||||
|
@ -116,7 +116,8 @@ CF_KEYWORDS(NONE, SIMPLE, AUTHENTICATION, STRICT, CRYPTOGRAPHIC, TTL, SECURITY)
|
||||
CF_KEYWORDS(ELIGIBLE, POLL, NETWORKS, HIDDEN, VIRTUAL, CHECK, LINK, ONLY, BFD)
|
||||
CF_KEYWORDS(RX, BUFFER, LARGE, NORMAL, STUBNET, HIDDEN, SUMMARY, TAG, EXTERNAL)
|
||||
CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY)
|
||||
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY)
|
||||
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
|
||||
CF_KEYWORDS(SECONDARY)
|
||||
|
||||
%type <t> opttext
|
||||
%type <ld> lsadb_args
|
||||
@ -292,14 +293,16 @@ ospf_iface_item:
|
||||
| AUTHENTICATION NONE { OSPF_PATT->autype = OSPF_AUTH_NONE; }
|
||||
| AUTHENTICATION SIMPLE { OSPF_PATT->autype = OSPF_AUTH_SIMPLE; ospf_check_auth(); }
|
||||
| AUTHENTICATION CRYPTOGRAPHIC { OSPF_PATT->autype = OSPF_AUTH_CRYPT; ospf_check_auth(); }
|
||||
| RX BUFFER LARGE { OSPF_PATT->rxbuf = OSPF_RXBUF_LARGE ; }
|
||||
| RX BUFFER NORMAL { OSPF_PATT->rxbuf = OSPF_RXBUF_NORMAL ; }
|
||||
| RX BUFFER expr { OSPF_PATT->rxbuf = $3 ; if (($3 < OSPF_RXBUF_MINSIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
|
||||
| RX BUFFER NORMAL { OSPF_PATT->rx_buffer = 0; }
|
||||
| RX BUFFER LARGE { OSPF_PATT->rx_buffer = OSPF_MAX_PKT_SIZE; }
|
||||
| RX BUFFER expr { OSPF_PATT->rx_buffer = $3; if (($3 < OSPF_MIN_PKT_SIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("Buffer size must be in range 256-65535"); }
|
||||
| TX tos { OSPF_PATT->tx_tos = $2; }
|
||||
| TX PRIORITY expr { OSPF_PATT->tx_priority = $3; }
|
||||
| TX LENGTH expr { OSPF_PATT->tx_length = $3; if (($3 < OSPF_MIN_PKT_SIZE) || ($3 > OSPF_MAX_PKT_SIZE)) cf_error("TX length must be in range 256-65535"); }
|
||||
| TTL SECURITY bool { OSPF_PATT->ttl_security = $3; }
|
||||
| TTL SECURITY TX ONLY { OSPF_PATT->ttl_security = 2; }
|
||||
| BFD bool { OSPF_PATT->bfd = $2; cf_check_bfd($2); }
|
||||
| SECONDARY bool { OSPF_PATT->bsd_secondary = $2; }
|
||||
| password_list { ospf_check_auth(); }
|
||||
;
|
||||
|
||||
|
@ -93,18 +93,26 @@ static void ospf_dbdes_dump(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
|
||||
|
||||
static void
|
||||
ospf_dbdes_prepare(struct ospf_neighbor *n, struct ospf_packet *pkt, int lsdb)
|
||||
ospf_dbdes_prepare(struct ospf_neighbor *n, int lsdb)
|
||||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
int i = 0;
|
||||
struct ospf_packet *pkt;
|
||||
|
||||
if (n->ldd_bsize != ifa->tx_length)
|
||||
{
|
||||
mb_free(n->ldd_buffer);
|
||||
n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
|
||||
n->ldd_bsize = ifa->tx_length;
|
||||
}
|
||||
|
||||
pkt = n->ldd_buffer;
|
||||
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
||||
|
||||
if (lsdb && (n->myimms & DBDES_M))
|
||||
{
|
||||
struct ospf_lsa_header *lsas;
|
||||
unsigned lsa_max;
|
||||
unsigned i = 0, lsa_max;
|
||||
snode *sn;
|
||||
|
||||
ospf_dbdes_body(po, pkt, ospf_pkt_maxsize(ifa), &lsas, &lsa_max);
|
||||
@ -179,7 +187,6 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct ospf_area *oa = ifa->oa;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_packet *pkt;
|
||||
unsigned length;
|
||||
|
||||
/* FIXME ??? */
|
||||
@ -192,22 +199,25 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
n->myimms |= DBDES_I;
|
||||
|
||||
/* Send empty packets */
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
ospf_dbdes_prepare(n, pkt, 0);
|
||||
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
ospf_dbdes_prepare(n, 0);
|
||||
OSPF_PACKET(ospf_dbdes_dump, n->ldd_buffer,
|
||||
"DBDES packet sent to %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
sk_set_tbuf(ifa->sk, n->ldd_buffer);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
sk_set_tbuf(ifa->sk, NULL);
|
||||
break;
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
n->myimms &= ~DBDES_I;
|
||||
|
||||
if (next)
|
||||
ospf_dbdes_prepare(n, n->ldbdes, 1);
|
||||
ospf_dbdes_prepare(n, 1);
|
||||
|
||||
case NEIGHBOR_LOADING:
|
||||
case NEIGHBOR_FULL:
|
||||
|
||||
length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
|
||||
length = n->ldd_buffer ? ntohs(((struct ospf_packet *) n->ldd_buffer)->length) : 0;
|
||||
if (!length)
|
||||
{
|
||||
OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating");
|
||||
@ -215,12 +225,14 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy last sent packet again */
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
memcpy(pkt, n->ldbdes, length);
|
||||
/* Send last packet from ldd buffer */
|
||||
|
||||
OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
|
||||
"DBDES packet sent to %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
sk_set_tbuf(ifa->sk, n->ldd_buffer);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
sk_set_tbuf(ifa->sk, NULL);
|
||||
|
||||
/* XXXX remove this? */
|
||||
if (n->myimms & DBDES_MS)
|
||||
@ -290,7 +302,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
return;
|
||||
}
|
||||
|
||||
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
|
||||
@ -324,12 +336,12 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
return;
|
||||
|
||||
case NEIGHBOR_EXSTART:
|
||||
if ((rcv_iface_mtu != ifa->iface->mtu) &&
|
||||
if ((ifa->type != OSPF_IT_VLINK) &&
|
||||
(rcv_iface_mtu != ifa->iface->mtu) &&
|
||||
(rcv_iface_mtu != 0) &&
|
||||
(ifa->iface->mtu != 0) &&
|
||||
(ifa->type != OSPF_IT_VLINK))
|
||||
(ifa->iface->mtu != 0))
|
||||
log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)",
|
||||
n->ip, ifa->iface->name, rcv_iface_mtu, ifa->iface->mtu);
|
||||
n->ip, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
|
||||
|
||||
if ((rcv_imms == DBDES_IMMS) &&
|
||||
(n->rid > po->router_id) &&
|
||||
|
@ -36,29 +36,46 @@ wait_timer_hook(timer * timer)
|
||||
struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s.", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s", ifa->ifname);
|
||||
ospf_iface_sm(ifa, ISM_WAITF);
|
||||
}
|
||||
|
||||
static void ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa);
|
||||
|
||||
u32
|
||||
rxbufsize(struct ospf_iface *ifa)
|
||||
static inline uint
|
||||
ifa_tx_length(struct ospf_iface *ifa)
|
||||
{
|
||||
switch(ifa->rxbuf)
|
||||
{
|
||||
case OSPF_RXBUF_NORMAL:
|
||||
return (ifa->iface->mtu * 2);
|
||||
break;
|
||||
case OSPF_RXBUF_LARGE:
|
||||
return OSPF_MAX_PKT_SIZE;
|
||||
break;
|
||||
default:
|
||||
return ifa->rxbuf;
|
||||
break;
|
||||
}
|
||||
return ifa->cf->tx_length ?: ifa->iface->mtu;
|
||||
}
|
||||
|
||||
static inline uint
|
||||
ifa_bufsize(struct ospf_iface *ifa)
|
||||
{
|
||||
uint bsize = ifa->cf->rx_buffer ?: ifa->iface->mtu;
|
||||
return MAX(bsize, ifa->tx_length);
|
||||
}
|
||||
|
||||
int
|
||||
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
|
||||
{
|
||||
plen += SIZE_OF_IP_HEADER;
|
||||
|
||||
#ifdef OSPFv2
|
||||
if (ifa->autype == OSPF_AUTH_CRYPT)
|
||||
plen += OSPF_AUTH_CRYPT_SIZE;
|
||||
#endif
|
||||
|
||||
if (plen <= ifa->sk->tbsize)
|
||||
return 0;
|
||||
|
||||
if (ifa->cf->rx_buffer || (plen > 0xffff))
|
||||
return -1;
|
||||
|
||||
plen = BIRD_ALIGN(plen, 1024);
|
||||
plen = MIN(plen, 0xffff);
|
||||
sk_set_tbsize(ifa->sk, plen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct nbma_node *
|
||||
find_nbma_node_in(list *nnl, ip_addr ip)
|
||||
{
|
||||
@ -69,6 +86,7 @@ find_nbma_node_in(list *nnl, ip_addr ip)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ospf_sk_open(struct ospf_iface *ifa)
|
||||
{
|
||||
@ -77,21 +95,20 @@ ospf_sk_open(struct ospf_iface *ifa)
|
||||
sock *sk = sk_new(ifa->pool);
|
||||
sk->type = SK_IP;
|
||||
sk->dport = OSPF_PROTO;
|
||||
sk->saddr = IPA_NONE;
|
||||
sk->saddr = ifa->addr->ip;
|
||||
sk->iface = ifa->iface;
|
||||
|
||||
sk->tos = ifa->cf->tx_tos;
|
||||
sk->priority = ifa->cf->tx_priority;
|
||||
sk->rx_hook = ospf_rx_hook;
|
||||
sk->tx_hook = ospf_tx_hook;
|
||||
// sk->tx_hook = ospf_tx_hook;
|
||||
sk->err_hook = ospf_err_hook;
|
||||
sk->iface = ifa->iface;
|
||||
sk->rbsize = rxbufsize(ifa);
|
||||
sk->tbsize = rxbufsize(ifa);
|
||||
sk->rbsize = sk->tbsize = ifa_bufsize(ifa);
|
||||
sk->data = (void *) ifa;
|
||||
sk->flags = SKF_LADDR_RX | (ifa->check_ttl ? SKF_TTL_RX : 0);
|
||||
sk->ttl = ifa->cf->ttl_security ? 255 : -1;
|
||||
sk->ttl = ifa->cf->ttl_security ? 255 : 1;
|
||||
|
||||
if (sk_open(sk) != 0)
|
||||
if (sk_open(sk) < 0)
|
||||
goto err;
|
||||
|
||||
/* 12 is an offset of the checksum in an OSPFv3 packet */
|
||||
@ -99,28 +116,6 @@ ospf_sk_open(struct ospf_iface *ifa)
|
||||
if (sk_set_ipv6_checksum(sk, 12) < 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* For OSPFv2: When sending a packet, it is important to have a
|
||||
* proper source address. We expect that when we send one-hop
|
||||
* unicast packets, OS chooses a source address according to the
|
||||
* destination address (to be in the same prefix). We also expect
|
||||
* that when we send multicast packets, OS uses the source address
|
||||
* from sk->saddr registered to OS by sk_setup_multicast(). This
|
||||
* behavior is needed to implement multiple virtual ifaces (struct
|
||||
* ospf_iface) on one physical iface and is signalized by
|
||||
* CONFIG_MC_PROPER_SRC.
|
||||
*
|
||||
* If this behavior is not available (for example on BSD), we create
|
||||
* non-stub iface just for the primary IP address (see
|
||||
* ospf_iface_stubby()) and we expect OS to use primary IP address
|
||||
* as a source address for both unicast and multicast packets.
|
||||
*
|
||||
* FIXME: the primary IP address is currently just the
|
||||
* lexicographically smallest address on an interface, it should be
|
||||
* signalized by sysdep code which one is really the primary.
|
||||
*/
|
||||
|
||||
sk->saddr = ifa->addr->ip;
|
||||
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_PTP))
|
||||
{
|
||||
if (ifa->cf->real_bcast)
|
||||
@ -135,7 +130,6 @@ ospf_sk_open(struct ospf_iface *ifa)
|
||||
{
|
||||
ifa->all_routers = ospf_is_v2(po) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
|
||||
ifa->des_routers = ospf_is_v2(po) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
|
||||
sk->ttl = ifa->cf->ttl_security ? 255 : 1;
|
||||
|
||||
if (sk_setup_multicast(sk) < 0)
|
||||
goto err;
|
||||
@ -174,6 +168,40 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
|
||||
ifa->sk_dr = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ospf_open_vlink_sk(struct proto_ospf *po)
|
||||
{
|
||||
sock *sk = sk_new(po->proto.pool);
|
||||
sk->type = SK_IP;
|
||||
sk->dport = OSPF_PROTO;
|
||||
|
||||
/* FIXME: configurable tos/priority ? */
|
||||
sk->tos = IP_PREC_INTERNET_CONTROL;
|
||||
sk->priority = sk_priority_control;
|
||||
sk->err_hook = ospf_verr_hook;
|
||||
|
||||
sk->rbsize = 0;
|
||||
sk->tbsize = OSPF_VLINK_MTU;
|
||||
sk->data = (void *) po;
|
||||
sk->flags = 0;
|
||||
|
||||
if (sk_open(sk) < 0)
|
||||
goto err;
|
||||
|
||||
#ifdef OSPFv3
|
||||
/* 12 is an offset of the checksum in an OSPF packet */
|
||||
if (sk_set_ipv6_checksum(sk, 12) < 0)
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
po->vlink_sk = sk;
|
||||
return;
|
||||
|
||||
err:
|
||||
rfree(sk);
|
||||
log(L_ERR "%s: Cannot open virtual link socket", po->proto.name);
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_iface_down(struct ospf_iface *ifa)
|
||||
{
|
||||
@ -185,13 +213,13 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||
{
|
||||
if (ospf_is_v3(ifa->oa->po))
|
||||
OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
|
||||
ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
|
||||
ifa->ifname, ifa->instance_id, ifa->oa->areaid);
|
||||
else if (ifa->addr->flags & IA_PEER)
|
||||
OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
|
||||
ifa->iface->name, ifa->addr->opposite, ifa->oa->areaid);
|
||||
ifa->ifname, ifa->addr->opposite, ifa->oa->areaid);
|
||||
else
|
||||
OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
|
||||
ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
|
||||
ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
|
||||
|
||||
/* First of all kill all the related vlinks */
|
||||
WALK_LIST(iff, po->iface_list)
|
||||
@ -219,9 +247,7 @@ ospf_iface_down(struct ospf_iface *ifa)
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
ifa->vifa = NULL;
|
||||
ifa->iface = NULL;
|
||||
ifa->addr = NULL;
|
||||
ifa->sk = NULL;
|
||||
ifa->cost = 0;
|
||||
ifa->vip = IPA_NONE;
|
||||
}
|
||||
@ -273,12 +299,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||
|
||||
ifa->state = state;
|
||||
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
OSPF_TRACE(D_EVENTS, "Changing state of virtual link %R from %s to %s",
|
||||
ifa->vid, ospf_is[oldstate], ospf_is[state]);
|
||||
else
|
||||
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
|
||||
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
|
||||
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
|
||||
ifa->ifname, ospf_is[oldstate], ospf_is[state]);
|
||||
|
||||
if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
|
||||
{
|
||||
@ -320,8 +342,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
||||
void
|
||||
ospf_iface_sm(struct ospf_iface *ifa, int event)
|
||||
{
|
||||
DBG("SM on %s %s. Event is '%s'\n", (ifa->type == OSPF_IT_VLINK) ? "vlink" : "iface",
|
||||
ifa->iface ? ifa->iface->name : "(none)" , ospf_ism[event]);
|
||||
DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism[event]);
|
||||
|
||||
switch (event)
|
||||
{
|
||||
@ -438,7 +459,7 @@ ospf_iface_add(struct object_lock *lock)
|
||||
/* Open socket if interface is not stub */
|
||||
if (! ifa->stub && ! ospf_sk_open(ifa))
|
||||
{
|
||||
log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->iface->name);
|
||||
log(L_ERR "%s: Socket open failed on interface %s, declaring as stub", p->name, ifa->ifname);
|
||||
ifa->ioprob = OSPF_I_SK;
|
||||
ifa->stub = 1;
|
||||
}
|
||||
@ -471,9 +492,6 @@ add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
|
||||
static int
|
||||
ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
|
||||
{
|
||||
if (! addr)
|
||||
return 0;
|
||||
|
||||
/* a host address */
|
||||
if (addr->flags & IA_HOST)
|
||||
return 1;
|
||||
@ -483,12 +501,11 @@ ospf_iface_stubby(struct ospf_iface_patt *ip, struct ifa *addr)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* We cannot properly support multiple OSPF ifaces on real iface
|
||||
* with multiple prefixes, therefore we force OSPF ifaces with
|
||||
* non-primary IP prefixes to be stub.
|
||||
* For compatibility reasons on BSD systems, we force OSPF
|
||||
* interfaces with non-primary IP prefixes to be stub.
|
||||
*/
|
||||
#if defined(OSPFv2) && !defined(CONFIG_MC_PROPER_SRC)
|
||||
if (! (addr->flags & IA_PRIMARY))
|
||||
if (!ip->bsd_secondary && !(addr->flags & IA_PRIMARY))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
@ -499,16 +516,11 @@ void
|
||||
ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct iface *iface = addr ? addr->iface : NULL;
|
||||
struct iface *iface = addr->iface;
|
||||
struct ospf_iface *ifa;
|
||||
struct pool *pool;
|
||||
|
||||
struct ospf_iface *ifa;
|
||||
struct nbma_node *nb;
|
||||
struct object_lock *lock;
|
||||
|
||||
if (ip->type == OSPF_IT_VLINK)
|
||||
OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
|
||||
else if (ospf_is_v3(po))
|
||||
if (ospf_is_v3(po))
|
||||
OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
|
||||
iface->name, ip->instance_id, oa->areaid);
|
||||
else if (addr->flags & IA_PEER)
|
||||
@ -526,6 +538,9 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
ifa->cf = ip;
|
||||
ifa->pool = pool;
|
||||
|
||||
ifa->iface_id = iface->index;
|
||||
ifa->ifname = iface->name;
|
||||
|
||||
ifa->cost = ip->cost;
|
||||
ifa->rxmtint = ip->rxmtint;
|
||||
ifa->inftransdelay = ip->inftransdelay;
|
||||
@ -537,7 +552,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
ifa->deadint = ip->deadint;
|
||||
ifa->stub = ospf_iface_stubby(ip, addr);
|
||||
ifa->ioprob = OSPF_I_OK;
|
||||
ifa->rxbuf = ip->rxbuf;
|
||||
ifa->tx_length = ifa_tx_length(ifa);
|
||||
ifa->check_link = ip->check_link;
|
||||
ifa->ecmp_weight = ip->ecmp_weight;
|
||||
ifa->check_ttl = (ip->ttl_security == 1);
|
||||
@ -546,10 +561,11 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
ifa->passwords = ip->passwords;
|
||||
ifa->instance_id = ip->instance_id;
|
||||
|
||||
ifa->ptp_netmask = addr ? !(addr->flags & IA_PEER) : 0;
|
||||
ifa->ptp_netmask = !(addr->flags & IA_PEER);
|
||||
if (ip->ptp_netmask < 2)
|
||||
ifa->ptp_netmask = ip->ptp_netmask;
|
||||
|
||||
|
||||
ifa->type = ospf_iface_classify(ip->type, addr);
|
||||
|
||||
/* Check validity of interface type */
|
||||
@ -572,12 +588,12 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
|
||||
po->proto.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
|
||||
|
||||
/* Assign iface ID, for vlinks, this is ugly hack */
|
||||
ifa->iface_id = (ifa->type != OSPF_IT_VLINK) ? iface->index : oa->po->last_vlink_id++;
|
||||
|
||||
ifa->state = OSPF_IS_DOWN;
|
||||
init_list(&ifa->neigh_list);
|
||||
init_list(&ifa->nbma_list);
|
||||
|
||||
struct nbma_node *nb;
|
||||
WALK_LIST(nb, ip->nbma_list)
|
||||
{
|
||||
/* In OSPFv3, addr is link-local while configured neighbors could
|
||||
@ -594,19 +610,8 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
add_nbma_node(ifa, nb, 0);
|
||||
}
|
||||
|
||||
ifa->state = OSPF_IS_DOWN;
|
||||
add_tail(&oa->po->iface_list, NODE ifa);
|
||||
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
ifa->voa = ospf_find_area(oa->po, ip->voa);
|
||||
ifa->vid = ip->vid;
|
||||
|
||||
ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
|
||||
|
||||
return; /* Don't lock, don't add sockets */
|
||||
}
|
||||
|
||||
/*
|
||||
* In some cases we allow more ospf_ifaces on one physical iface.
|
||||
* In OSPFv2, if they use different IP address prefix.
|
||||
@ -614,7 +619,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
* Therefore, we store such info to lock->addr field.
|
||||
*/
|
||||
|
||||
lock = olock_new(pool);
|
||||
struct object_lock *lock = olock_new(pool);
|
||||
lock->addr = ospf_is_v2(po) ? ifa->addr->prefix : _MI6(0,0,0,ifa->instance_id);
|
||||
lock->type = OBJLOCK_IP;
|
||||
lock->port = OSPF_PROTO;
|
||||
@ -625,6 +630,63 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
|
||||
olock_acquire(lock);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_iface_new_vlink(struct proto_ospf *po, struct ospf_iface_patt *ip)
|
||||
{
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_iface *ifa;
|
||||
struct pool *pool;
|
||||
|
||||
if (!po->vlink_sk)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
|
||||
|
||||
/* Vlink ifname is stored just after the ospf_iface structure */
|
||||
|
||||
pool = rp_new(p->pool, "OSPF Vlink");
|
||||
ifa = mb_allocz(pool, sizeof(struct ospf_iface) + 16);
|
||||
ifa->oa = po->backbone;
|
||||
ifa->cf = ip;
|
||||
ifa->pool = pool;
|
||||
|
||||
/* Assign iface ID, for vlinks, this is ugly hack */
|
||||
u32 vlink_id = po->last_vlink_id++;
|
||||
ifa->iface_id = vlink_id + OSPF_VLINK_ID_OFFSET;
|
||||
ifa->ifname = (void *) (ifa + 1);
|
||||
bsprintf(ifa->ifname, "vlink%d", vlink_id);
|
||||
|
||||
ifa->voa = ospf_find_area(po, ip->voa);
|
||||
ifa->vid = ip->vid;
|
||||
ifa->sk = po->vlink_sk;
|
||||
|
||||
ifa->helloint = ip->helloint;
|
||||
ifa->rxmtint = ip->rxmtint;
|
||||
ifa->waitint = ip->waitint;
|
||||
ifa->deadint = ip->deadint;
|
||||
ifa->inftransdelay = ip->inftransdelay;
|
||||
ifa->tx_length = OSPF_VLINK_MTU;
|
||||
|
||||
#ifdef OSPFv2
|
||||
ifa->autype = ip->autype;
|
||||
ifa->passwords = ip->passwords;
|
||||
#endif
|
||||
|
||||
#ifdef OSPFv3
|
||||
ifa->instance_id = ip->instance_id;
|
||||
#endif
|
||||
|
||||
ifa->type = OSPF_IT_VLINK;
|
||||
|
||||
ifa->state = OSPF_IS_DOWN;
|
||||
init_list(&ifa->neigh_list);
|
||||
init_list(&ifa->nbma_list);
|
||||
|
||||
add_tail(&po->iface_list, NODE ifa);
|
||||
|
||||
ifa->hello_timer = tm_new_set(ifa->pool, hello_timer_hook, ifa, 0, ifa->helloint);
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_iface_change_timer(timer *tm, unsigned val)
|
||||
{
|
||||
@ -641,12 +703,12 @@ int
|
||||
ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct nbma_node *nb, *nbx;
|
||||
char *ifname = (ifa->type != OSPF_IT_VLINK) ? ifa->iface->name : "vlink";
|
||||
struct ospf_iface_patt *old = ifa->cf;
|
||||
char *ifname = ifa->ifname;
|
||||
|
||||
/* Type could be changed in ospf_iface_new(),
|
||||
but if config values are same then also results are same */
|
||||
int old_type = ospf_iface_classify(ifa->cf->type, ifa->addr);
|
||||
int old_type = ospf_iface_classify(old->type, ifa->addr);
|
||||
int new_type = ospf_iface_classify(new->type, ifa->addr);
|
||||
if (old_type != new_type)
|
||||
return 0;
|
||||
@ -656,10 +718,10 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
return 0;
|
||||
|
||||
/* Change of these options would require to reset the iface socket */
|
||||
if ((new->real_bcast != ifa->cf->real_bcast) ||
|
||||
(new->tx_tos != ifa->cf->tx_tos) ||
|
||||
(new->tx_priority != ifa->cf->tx_priority) ||
|
||||
(new->ttl_security != ifa->cf->ttl_security))
|
||||
if ((new->real_bcast != old->real_bcast) ||
|
||||
(new->tx_tos != old->tx_tos) ||
|
||||
(new->tx_priority != old->tx_priority) ||
|
||||
(new->ttl_security != old->ttl_security))
|
||||
return 0;
|
||||
|
||||
ifa->cf = new;
|
||||
@ -761,6 +823,8 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
ifa->strictnbma = new->strictnbma;
|
||||
}
|
||||
|
||||
struct nbma_node *nb, *nbx;
|
||||
|
||||
/* NBMA LIST - remove or update old */
|
||||
WALK_LIST_DELSAFE(nb, nbx, ifa->nbma_list)
|
||||
{
|
||||
@ -801,13 +865,35 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
}
|
||||
}
|
||||
|
||||
/* RX BUFF */
|
||||
if (ifa->rxbuf != new->rxbuf)
|
||||
int update_buffers = 0;
|
||||
|
||||
/* TX LENGTH */
|
||||
if (old->tx_length != new->tx_length)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Changing rxbuf interface %s from %d to %d",
|
||||
ifname, ifa->rxbuf, new->rxbuf);
|
||||
ifa->rxbuf = new->rxbuf;
|
||||
ospf_iface_change_mtu(ifa->oa->po, ifa);
|
||||
OSPF_TRACE(D_EVENTS, "Changing TX length on interface %s from %d to %d",
|
||||
ifname, old->tx_length, new->tx_length);
|
||||
|
||||
/* ifa cannot be vlink */
|
||||
ifa->tx_length = ifa_tx_length(ifa);
|
||||
update_buffers = 1;
|
||||
}
|
||||
|
||||
/* RX BUFFER */
|
||||
if (old->rx_buffer != new->rx_buffer)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Changing buffer size on interface %s from %d to %d",
|
||||
ifname, old->rx_buffer, new->rx_buffer);
|
||||
|
||||
/* ifa cannot be vlink */
|
||||
update_buffers = 1;
|
||||
}
|
||||
|
||||
/* Buffer size depends on both tx_length and rx_buffer options */
|
||||
if (update_buffers && ifa->sk)
|
||||
{
|
||||
uint bsize = ifa_bufsize(ifa);
|
||||
sk_set_rbsize(ifa->sk, bsize);
|
||||
sk_set_tbsize(ifa->sk, bsize);
|
||||
}
|
||||
|
||||
/* LINK */
|
||||
@ -817,6 +903,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
|
||||
new->check_link ? "Enabling" : "Disabling", ifname);
|
||||
ifa->check_link = new->check_link;
|
||||
|
||||
/* ifa cannot be vlink */
|
||||
if (!(ifa->iface->flags & IF_LINK_UP))
|
||||
ospf_iface_sm(ifa, ifa->check_link ? ISM_LOOP : ISM_UNLOOP);
|
||||
}
|
||||
@ -1013,6 +1100,7 @@ ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a)
|
||||
static void
|
||||
ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface_patt *ip;
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
@ -1040,6 +1128,8 @@ ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
continue;
|
||||
|
||||
/* Hard restart */
|
||||
log(L_INFO "%s: Restarting interface %s (%I/%d) in area %R",
|
||||
po->proto.name, ifa->ifname, a->prefix, a->pxlen, oa->areaid);
|
||||
ospf_iface_shutdown(ifa);
|
||||
ospf_iface_remove(ifa);
|
||||
}
|
||||
@ -1053,6 +1143,7 @@ ospf_ifaces_reconfigure2(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
static void
|
||||
ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
{
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct ospf_iface_patt *ip;
|
||||
struct iface *iface;
|
||||
struct ifa *a;
|
||||
@ -1083,6 +1174,8 @@ ospf_ifaces_reconfigure3(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
continue;
|
||||
|
||||
/* Hard restart */
|
||||
log(L_INFO "%s: Restarting interface %s (IID %d) in area %R",
|
||||
po->proto.name, ifa->ifname, ifa->instance_id, oa->areaid);
|
||||
ospf_iface_shutdown(ifa);
|
||||
ospf_iface_remove(ifa);
|
||||
}
|
||||
@ -1106,32 +1199,28 @@ ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
|
||||
static void
|
||||
ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa)
|
||||
{
|
||||
struct ospf_packet *op;
|
||||
struct ospf_neighbor *n;
|
||||
OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->iface->name);
|
||||
/* ifa is not vlink */
|
||||
|
||||
if (ifa->sk)
|
||||
{
|
||||
ifa->sk->rbsize = rxbufsize(ifa);
|
||||
ifa->sk->tbsize = rxbufsize(ifa);
|
||||
sk_reallocate(ifa->sk);
|
||||
}
|
||||
OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->ifname);
|
||||
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
{
|
||||
op = (struct ospf_packet *) n->ldbdes;
|
||||
n->ldbdes = mb_allocz(n->pool, ifa->iface->mtu);
|
||||
ifa->tx_length = ifa_tx_length(ifa);
|
||||
|
||||
if (ntohs(op->length) <= ifa->iface->mtu) /* If the packet in old buffer is bigger, let it filled by zeros */
|
||||
memcpy(n->ldbdes, op, ifa->iface->mtu); /* If the packet is old is same or smaller, copy it */
|
||||
if (!ifa->sk)
|
||||
return;
|
||||
|
||||
mb_free(op);
|
||||
}
|
||||
/* We do not shrink dynamic buffers */
|
||||
uint bsize = ifa_bufsize(ifa);
|
||||
if (bsize > ifa->sk->rbsize)
|
||||
sk_set_rbsize(ifa->sk, bsize);
|
||||
if (bsize > ifa->sk->tbsize)
|
||||
sk_set_tbsize(ifa->sk, bsize);
|
||||
}
|
||||
|
||||
static void
|
||||
ospf_iface_notify(struct proto_ospf *po, unsigned flags, struct ospf_iface *ifa)
|
||||
{
|
||||
/* ifa is not vlink */
|
||||
|
||||
if (flags & IF_CHANGE_DOWN)
|
||||
{
|
||||
ospf_iface_remove(ifa);
|
||||
@ -1161,7 +1250,7 @@ ospf_if_notify(struct proto *p, unsigned flags, struct iface *iface)
|
||||
|
||||
struct ospf_iface *ifa, *ifx;
|
||||
WALK_LIST_DELSAFE(ifa, ifx, po->iface_list)
|
||||
if ((ifa->type != OSPF_IT_VLINK) && (ifa->iface == iface))
|
||||
if (ifa->iface == iface)
|
||||
ospf_iface_notify(po, flags, ifa);
|
||||
|
||||
/* We use here that even shutting down iface also shuts down
|
||||
@ -1184,21 +1273,18 @@ ospf_iface_info(struct ospf_iface *ifa)
|
||||
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
cli_msg(-1015, "Virtual link to %R:", ifa->vid);
|
||||
cli_msg(-1015, "Virtual link %s to %R:", ifa->ifname, ifa->vid);
|
||||
cli_msg(-1015, "\tPeer IP: %I", ifa->vip);
|
||||
cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid,
|
||||
ifa->voa->areaid);
|
||||
cli_msg(-1015, "\tInterface: \"%s\"",
|
||||
(ifa->iface ? ifa->iface->name : "(none)"));
|
||||
cli_msg(-1015, "\tTransit area: %R (%u)", ifa->voa->areaid, ifa->voa->areaid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ospf_is_v3(ifa->oa->po))
|
||||
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
|
||||
cli_msg(-1015, "Interface %s (IID %d)", ifa->ifname, ifa->instance_id);
|
||||
else if (ifa->addr->flags & IA_PEER)
|
||||
cli_msg(-1015, "Interface %s (peer %I)", ifa->iface->name, ifa->addr->opposite);
|
||||
cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite);
|
||||
else
|
||||
cli_msg(-1015, "Interface %s (%I/%d)", ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen);
|
||||
cli_msg(-1015, "Interface %s (%I/%d)", ifa->ifname, ifa->addr->prefix, ifa->addr->pxlen);
|
||||
|
||||
cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
|
||||
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
|
||||
|
@ -18,11 +18,16 @@ void ospf_ifa_notify2(struct proto *p, unsigned flags, struct ifa *a);
|
||||
void ospf_ifa_notify3(struct proto *p, unsigned flags, struct ifa *a);
|
||||
void ospf_iface_info(struct ospf_iface *ifa);
|
||||
void ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *ip);
|
||||
void ospf_iface_new_vlink(struct proto_ospf *po, struct ospf_iface_patt *ip);
|
||||
void ospf_iface_remove(struct ospf_iface *ifa);
|
||||
void ospf_iface_shutdown(struct ospf_iface *ifa);
|
||||
int ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new);
|
||||
void ospf_ifaces_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac);
|
||||
|
||||
int ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen);
|
||||
|
||||
void ospf_open_vlink_sk(struct proto_ospf *po);
|
||||
|
||||
struct nbma_node *find_nbma_node_in(list *nnl, ip_addr ip);
|
||||
|
||||
static inline struct nbma_node *
|
||||
|
@ -89,7 +89,7 @@ ospf_lsack_send_one(struct ospf_neighbor *n, int queue)
|
||||
length = ospf_pkt_hdrlen(po) + i * sizeof(struct ospf_lsa_header);
|
||||
pkt->length = htons(length);
|
||||
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet sent via %s", ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet sent via %s", ifa->ifname);
|
||||
|
||||
/* XXXX this is very strange */
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
@ -130,8 +130,7 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
|
||||
/* No need to check length, lsack has only basic header */
|
||||
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet received from %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsack_dump, pkt, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
return;
|
||||
|
@ -86,8 +86,7 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
||||
length = ospf_pkt_hdrlen(po) + i * sizeof(struct ospf_lsreq_header);
|
||||
pkt->length = htons(length);
|
||||
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet sent to %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet sent to %I via %s", n->ip, ifa->ifname);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
}
|
||||
|
||||
@ -102,8 +101,7 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
|
||||
/* No need to check length, lsreq has only basic header */
|
||||
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet received from %I via %s",
|
||||
n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsreq_dump, pkt, "LSREQ packet received from %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
return;
|
||||
|
@ -41,21 +41,21 @@ void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
log(L_TRACE "%s: router %R", p->name, ntohl(pkt->routerid));
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
static inline uint
|
||||
ospf_lsupd_hdrlen(struct proto_ospf *po)
|
||||
{
|
||||
return ospf_pkt_hdrlen(po) + 4; /* + u32 lsa count field */
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, unsigned hdrlen)
|
||||
ospf_lsupd_get_lsa_count(struct ospf_packet *pkt, uint hdrlen)
|
||||
{
|
||||
u32 *c = ((void *) pkt) + hdrlen - 4;
|
||||
return ntohl(*c);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, unsigned hdrlen, u32 val)
|
||||
ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, uint hdrlen, u32 val)
|
||||
{
|
||||
u32 *c = ((void *) pkt) + hdrlen - 4;
|
||||
*c = htonl(val);
|
||||
@ -63,9 +63,9 @@ ospf_lsupd_set_lsa_count(struct ospf_packet *pkt, unsigned hdrlen, u32 val)
|
||||
|
||||
static inline void
|
||||
ospf_lsupd_body(struct proto_ospf *po, struct ospf_packet *pkt,
|
||||
unsigned *offset, unsigned *bound, unsigned *lsa_count)
|
||||
uint *offset, uint *bound, uint *lsa_count)
|
||||
{
|
||||
unsigned hlen = ospf_lsupd_hdrlen(po);
|
||||
uint hlen = ospf_lsupd_hdrlen(po);
|
||||
*offset = hlen;
|
||||
*bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
|
||||
*lsa_count = ospf_lsupd_get_lsa_count(pkt, hlen);
|
||||
@ -79,7 +79,7 @@ static void ospf_lsupd_dump(struct proto_ospf *po, struct ospf_packet *pkt)
|
||||
ospf_dump_common(po, pkt);
|
||||
|
||||
/* We know that ntohs(pkt->length) >= sizeof(struct ospf_lsa_header) */
|
||||
unsigned offset, bound, i, lsa_count, lsalen;
|
||||
uint offset, bound, i, lsa_count, lsalen;
|
||||
ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
|
||||
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
@ -195,16 +195,16 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
unsigned sendreq = 1; /* XXXX ?? */
|
||||
uint sendreq = 1; /* XXXX ?? */
|
||||
|
||||
unsigned plen = ntohs(pkt->length);
|
||||
uint plen = ntohs(pkt->length);
|
||||
if (plen < (ospf_lsupd_hdrlen(po) + sizeof(struct ospf_lsa_header)))
|
||||
{
|
||||
log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen);
|
||||
return;
|
||||
}
|
||||
|
||||
OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
{
|
||||
@ -214,7 +214,7 @@ ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
||||
|
||||
unsigned offset, bound, i, lsa_count;
|
||||
uint offset, bound, i, lsa_count;
|
||||
ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
|
||||
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
@ -504,10 +504,10 @@ ospf_lsupd_flood(struct proto_ospf *po, struct top_hash_entry *en, struct ospf_n
|
||||
|
||||
static int
|
||||
ospf_lsupd_prepare(struct proto_ospf *po, struct ospf_iface *ifa,
|
||||
struct top_hash_entry **lsa_list, unsigned lsa_count)
|
||||
struct top_hash_entry **lsa_list, uint lsa_count)
|
||||
{
|
||||
struct ospf_packet *pkt;
|
||||
unsigned hlen, pos, i, maxsize;
|
||||
uint hlen, pos, i, maxsize;
|
||||
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
hlen = ospf_lsupd_hdrlen(po);
|
||||
@ -519,7 +519,7 @@ ospf_lsupd_prepare(struct proto_ospf *po, struct ospf_iface *ifa,
|
||||
for (i = 0; i < lsa_count; i++)
|
||||
{
|
||||
struct top_hash_entry *en = lsa_list[i];
|
||||
unsigned len = en->lsa.length;
|
||||
uint len = en->lsa.length;
|
||||
|
||||
if ((pos + len) > maxsize)
|
||||
{
|
||||
@ -528,14 +528,17 @@ ospf_lsupd_prepare(struct proto_ospf *po, struct ospf_iface *ifa,
|
||||
break;
|
||||
|
||||
/* LSA is larger than MTU, check buffer size */
|
||||
if ((pos + len) > ospf_pkt_bufsize(ifa))
|
||||
if (ospf_iface_assure_bufsize(ifa, pos + len) < 0)
|
||||
{
|
||||
/* Cannot fit in a tx buffer, skip that */
|
||||
log(L_ERR "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)",
|
||||
en->lsa_type, en->lsa.id, en->lsa.rt);
|
||||
XXXX();
|
||||
log(L_ERR "OSPF: LSA too large to send on %s (Type: %04x, Id: %R, Rt: %R)",
|
||||
ifa->ifname, en->lsa_type, en->lsa.id, en->lsa.rt);
|
||||
XXXX(); /* XXXX: handle packets with no LSA */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* TX buffer could be reallocated */
|
||||
pkt = ospf_tx_buffer(ifa);
|
||||
}
|
||||
|
||||
struct ospf_lsa_header *buf = ((void *) pkt) + pos;
|
||||
@ -560,7 +563,7 @@ ospf_lsupd_flood_ifa(struct proto_ospf *po, struct ospf_iface *ifa, struct top_h
|
||||
ospf_lsupd_prepare(po, ifa, &en, 1);
|
||||
|
||||
OSPF_PACKET(ospf_lsupd_dump, ospf_tx_buffer(ifa),
|
||||
"LSUPD packet flooded via %s", ifa->iface->name);
|
||||
"LSUPD packet flooded via %s", ifa->ifname);
|
||||
|
||||
switch (ifa->type)
|
||||
{
|
||||
@ -596,18 +599,18 @@ ospf_lsupd_flood_ifa(struct proto_ospf *po, struct ospf_iface *ifa, struct top_h
|
||||
}
|
||||
|
||||
int
|
||||
ospf_lsupd_send(struct ospf_neighbor *n, struct top_hash_entry **lsa_list, unsigned lsa_count)
|
||||
ospf_lsupd_send(struct ospf_neighbor *n, struct top_hash_entry **lsa_list, uint lsa_count)
|
||||
{
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
unsigned i, c;
|
||||
uint i, c;
|
||||
|
||||
for (i = 0; i < lsa_count; i += c)
|
||||
{
|
||||
c = ospf_lsupd_prepare(po, ifa, lsa_list + i, lsa_count - i);
|
||||
|
||||
OSPF_PACKET(ospf_lsupd_dump, ospf_tx_buffer(ifa),
|
||||
"LSUPD packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
"LSUPD packet sent to %I via %s", n->ip, ifa->ifname);
|
||||
|
||||
ospf_send_to(ifa, n->ip);
|
||||
}
|
||||
@ -620,10 +623,10 @@ ospf_lsupd_rxmt(struct ospf_neighbor *n)
|
||||
{
|
||||
struct proto_ospf *po = n->ifa->oa->po;
|
||||
|
||||
const unsigned max = 128;
|
||||
const uint max = 128;
|
||||
struct top_hash_entry *entries[max];
|
||||
struct top_hash_entry *ret, *en;
|
||||
unsigned i = 0;
|
||||
uint i = 0;
|
||||
|
||||
WALK_SLIST(ret, n->lsrtl)
|
||||
{
|
||||
|
@ -67,7 +67,6 @@ ospf_neighbor_new(struct ospf_iface *ifa)
|
||||
add_tail(&ifa->neigh_list, NODE n);
|
||||
n->adj = 0;
|
||||
n->csn = 0;
|
||||
n->ldbdes = mb_allocz(pool, ifa->iface->mtu);
|
||||
n->state = NEIGHBOR_DOWN;
|
||||
|
||||
init_lists(n);
|
||||
@ -275,10 +274,10 @@ can_do_adj(struct ospf_neighbor *n)
|
||||
{
|
||||
case OSPF_IS_DOWN:
|
||||
case OSPF_IS_LOOP:
|
||||
bug("%s: Iface %s in down state?", p->name, ifa->iface->name);
|
||||
bug("%s: Iface %s in down state?", p->name, ifa->ifname);
|
||||
break;
|
||||
case OSPF_IS_WAITING:
|
||||
DBG("%s: Neighbor? on iface %s\n", p->name, ifa->iface->name);
|
||||
DBG("%s: Neighbor? on iface %s\n", p->name, ifa->ifname);
|
||||
break;
|
||||
case OSPF_IS_DROTHER:
|
||||
if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
|
||||
@ -292,15 +291,15 @@ can_do_adj(struct ospf_neighbor *n)
|
||||
i = 1;
|
||||
break;
|
||||
default:
|
||||
bug("%s: Iface %s in unknown state?", p->name, ifa->iface->name);
|
||||
bug("%s: Iface %s in unknown state?", p->name, ifa->ifname);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bug("%s: Iface %s is unknown type?", p->name, ifa->iface->name);
|
||||
bug("%s: Iface %s is unknown type?", p->name, ifa->ifname);
|
||||
break;
|
||||
}
|
||||
DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->iface->name, i);
|
||||
DBG("%s: Iface %s can_do_adj=%d\n", p->name, ifa->ifname, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
@ -533,9 +532,8 @@ neighbor_timer_hook(timer * timer)
|
||||
struct ospf_iface *ifa = n->ifa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS,
|
||||
"Inactivity timer fired on interface %s for neighbor %I.",
|
||||
ifa->iface->name, n->ip);
|
||||
OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I",
|
||||
ifa->ifname, n->ip);
|
||||
ospf_neigh_remove(n);
|
||||
}
|
||||
|
||||
@ -568,9 +566,7 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
|
||||
|
||||
if (req->down)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s",
|
||||
n->ip, n->ifa->iface->name);
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s", n->ip, n->ifa->ifname);
|
||||
ospf_neigh_remove(n);
|
||||
}
|
||||
}
|
||||
@ -619,8 +615,7 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
|
||||
pos = "ptp ";
|
||||
|
||||
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
|
||||
ospf_ns[n->state], pos, etime,
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink" : ifa->iface->name), n->ip);
|
||||
ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -631,7 +626,7 @@ rxmt_timer_hook(timer * timer)
|
||||
struct top_hash_entry *en;
|
||||
|
||||
DBG("%s: RXMT timer fired on interface %s for neigh %I\n",
|
||||
p->name, n->ifa->iface->name, n->ip);
|
||||
p->name, n->ifa->ifname, n->ip);
|
||||
|
||||
switch (n->state)
|
||||
{
|
||||
|
@ -231,7 +231,6 @@ ospf_start(struct proto *p)
|
||||
struct ospf_area_config *ac;
|
||||
|
||||
po->router_id = proto_get_router_id(p->cf);
|
||||
po->last_vlink_id = 0x80000000;
|
||||
po->rfc1583 = c->rfc1583;
|
||||
po->stub_router = c->stub_router;
|
||||
po->ebit = 0;
|
||||
@ -257,10 +256,13 @@ ospf_start(struct proto *p)
|
||||
WALK_LIST(ac, c->area_list)
|
||||
ospf_area_add(po, ac, 0);
|
||||
|
||||
if (c->abr)
|
||||
ospf_open_vlink_sk(po);
|
||||
|
||||
/* Add all virtual links */
|
||||
struct ospf_iface_patt *ic;
|
||||
WALK_LIST(ic, c->vlink_list)
|
||||
ospf_iface_new(po->backbone, NULL, ic);
|
||||
ospf_iface_new_vlink(po, ic);
|
||||
|
||||
return PS_UP;
|
||||
}
|
||||
@ -276,7 +278,7 @@ ospf_dump(struct proto *p)
|
||||
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Interface: %s", (ifa->iface ? ifa->iface->name : "(null)"));
|
||||
OSPF_TRACE(D_EVENTS, "Interface: %s", ifa->ifname);
|
||||
OSPF_TRACE(D_EVENTS, "state: %u", ifa->state);
|
||||
OSPF_TRACE(D_EVENTS, "DR: %R", ifa->drid);
|
||||
OSPF_TRACE(D_EVENTS, "BDR: %R", ifa->bdrid);
|
||||
@ -381,7 +383,7 @@ schedule_net_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling network-LSA origination for iface %s", ifa->ifname);
|
||||
ifa->orignet = 1;
|
||||
}
|
||||
|
||||
@ -390,7 +392,7 @@ schedule_link_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->ifname);
|
||||
ifa->origlink = 1;
|
||||
}
|
||||
|
||||
@ -625,7 +627,7 @@ ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
|
||||
{
|
||||
char *type = "<bug>";
|
||||
|
||||
switch(rte->attrs->source)
|
||||
switch (rte->attrs->source)
|
||||
{
|
||||
case RTS_OSPF:
|
||||
type = "I";
|
||||
@ -763,7 +765,7 @@ ospf_reconfigure(struct proto *p, struct proto_config *c)
|
||||
if (ifa)
|
||||
ospf_iface_reconfigure(ifa, ip);
|
||||
else
|
||||
ospf_iface_new(po->backbone, NULL, ip);
|
||||
ospf_iface_new_vlink(po, ip);
|
||||
}
|
||||
|
||||
/* Delete remaining ifaces and areas */
|
||||
@ -802,7 +804,7 @@ ospf_sh_neigh(struct proto *p, char *iff)
|
||||
cli_msg(-1013, "%-12s\t%3s\t%-15s\t%-5s\t%-10s %-12s", "Router ID", "Pri",
|
||||
" State", "DTime", "Interface", "Router IP");
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
|
||||
if ((iff == NULL) || patmatch(iff, ifa->ifname))
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
ospf_sh_neigh_info(n);
|
||||
cli_msg(0, "");
|
||||
@ -911,7 +913,7 @@ ospf_sh_iface(struct proto *p, char *iff)
|
||||
|
||||
cli_msg(-1015, "%s:", p->name);
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
if ((iff == NULL) || patmatch(iff, ifa->iface->name))
|
||||
if ((iff == NULL) || patmatch(iff, ifa->ifname))
|
||||
ospf_iface_info(ifa);
|
||||
cli_msg(0, "");
|
||||
}
|
||||
|
@ -640,7 +640,6 @@ struct ospf_neighbor
|
||||
*/
|
||||
slist lsrtl; /* slist of struct top_hash_entry from n->lsrth */
|
||||
struct top_graph *lsrth;
|
||||
|
||||
timer *rxmt_timer; /* RXMT timer */
|
||||
list ackl[2];
|
||||
#define ACKL_DIRECT 0
|
||||
|
@ -37,14 +37,13 @@ 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;
|
||||
|
||||
/* For OSPFv2 */
|
||||
if (ifa->autype == OSPF_AUTH_CRYPT)
|
||||
headers += OSPF_AUTH_CRYPT_SIZE;
|
||||
|
||||
return mtu - headers;
|
||||
return ifa->tx_length - headers;
|
||||
}
|
||||
|
||||
|
||||
@ -323,25 +322,34 @@ ospf_rx_hook(sock *sk, int size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned plen = ntohs(pkt->length);
|
||||
if (plen < sizeof(struct ospf_packet))
|
||||
uint plen = ntohs(pkt->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, plen);
|
||||
log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((plen > size) || ((plen % 4) != 0))
|
||||
if (sk->flags & SKF_TRUNCATED)
|
||||
{
|
||||
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 (plen > size)
|
||||
{
|
||||
log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((unsigned) size > sk->rbsize)
|
||||
{
|
||||
log(L_ERR "%s%I - too large (%d vs %d)", mesg, sk->faddr, size, sk->rbsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pkt->version != ospf_get_version(po))
|
||||
{
|
||||
log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
|
||||
@ -350,8 +358,8 @@ ospf_rx_hook(sock *sk, int size)
|
||||
|
||||
if (ospf_is_v2(po) && ospf_pkt_get_autype(pkt) != OSPF_AUTH_CRYPT)
|
||||
{
|
||||
unsigned hlen = sizeof(struct ospf_packet) - sizeof(union ospf_auth);
|
||||
unsigned blen = plen - hlen;
|
||||
uint hlen = sizeof(struct ospf_packet) + sizeof(union ospf_auth);
|
||||
uint blen = plen - hlen;
|
||||
void *body = ((void *) pkt) + hlen;
|
||||
|
||||
if (! ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
|
||||
@ -443,7 +451,7 @@ ospf_rx_hook(sock *sk, int size)
|
||||
if (!n && (pkt->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;
|
||||
}
|
||||
|
||||
@ -490,20 +498,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
|
||||
@ -513,9 +531,6 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
|
||||
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
|
||||
int plen = ntohs(pkt->length);
|
||||
|
||||
if (sk->tbuf != sk->tpos)
|
||||
log(L_ERR "Aiee, old packet was overwritten in TX buffer");
|
||||
|
||||
if (ospf_is_v2(ifa->oa->po))
|
||||
{
|
||||
if (ifa->autype == OSPF_AUTH_CRYPT)
|
||||
@ -524,7 +539,9 @@ ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
|
||||
ospf_pkt_finalize(ifa, pkt);
|
||||
}
|
||||
|
||||
sk_send_to(sk, plen, dst, 0);
|
||||
int done = sk_send_to(sk, plen, dst, 0);
|
||||
if (!done)
|
||||
log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11,10 +11,11 @@
|
||||
#define _BIRD_OSPF_PACKET_H_
|
||||
|
||||
void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
|
||||
unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
|
||||
uint ospf_pkt_maxsize(struct ospf_iface *ifa);
|
||||
int ospf_rx_hook(sock * sk, int size);
|
||||
void ospf_tx_hook(sock * sk);
|
||||
// void ospf_tx_hook(sock * sk);
|
||||
void ospf_err_hook(sock * sk, int err);
|
||||
void ospf_verr_hook(sock *sk, int err);
|
||||
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
|
||||
|
||||
void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
|
||||
@ -42,12 +43,5 @@ static inline unsigned ospf_pkt_hdrlen(struct proto_ospf *po)
|
||||
static inline void * ospf_tx_buffer(struct ospf_iface *ifa)
|
||||
{ return ifa->sk->tbuf; }
|
||||
|
||||
static inline unsigned ospf_pkt_bufsize(struct ospf_iface *ifa)
|
||||
{
|
||||
/* Reserve buffer space for authentication footer */
|
||||
unsigned res_size = (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
|
||||
return ifa->sk->tbsize - res_size;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _BIRD_OSPF_PACKET_H_ */
|
||||
|
@ -986,44 +986,42 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf)
|
||||
static void
|
||||
ospf_check_vlinks(struct proto_ospf *po)
|
||||
{
|
||||
struct ospf_iface *iface;
|
||||
WALK_LIST(iface, po->iface_list)
|
||||
struct ospf_iface *ifa;
|
||||
WALK_LIST(ifa, po->iface_list)
|
||||
{
|
||||
if (iface->type == OSPF_IT_VLINK)
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
struct top_hash_entry *tmp;
|
||||
tmp = ospf_hash_find_rt(po->gr, iface->voa->areaid, iface->vid);
|
||||
tmp = ospf_hash_find_rt(po->gr, ifa->voa->areaid, ifa->vid);
|
||||
|
||||
if (tmp && (tmp->color == INSPF) && ipa_nonzero(tmp->lb) && tmp->nhs)
|
||||
{
|
||||
struct ospf_iface *nhi = ospf_iface_find(po, tmp->nhs->iface);
|
||||
|
||||
if ((iface->state != OSPF_IS_PTP)
|
||||
|| (iface->vifa != nhi)
|
||||
|| !ipa_equal(iface->vip, tmp->lb))
|
||||
if ((ifa->state != OSPF_IS_PTP)
|
||||
|| (ifa->vifa != nhi)
|
||||
|| !ipa_equal(ifa->vip, tmp->lb))
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Vlink peer %R found", tmp->lsa.id);
|
||||
ospf_iface_sm(iface, ISM_DOWN);
|
||||
iface->vifa = nhi;
|
||||
iface->iface = nhi->iface;
|
||||
iface->addr = nhi->addr;
|
||||
iface->sk = nhi->sk;
|
||||
iface->cost = tmp->dist;
|
||||
iface->vip = tmp->lb;
|
||||
ospf_iface_sm(iface, ISM_UP);
|
||||
ospf_iface_sm(ifa, ISM_DOWN);
|
||||
ifa->vifa = nhi;
|
||||
ifa->addr = nhi->addr;
|
||||
ifa->cost = tmp->dist;
|
||||
ifa->vip = tmp->lb;
|
||||
ospf_iface_sm(ifa, ISM_UP);
|
||||
}
|
||||
else if ((iface->state == OSPF_IS_PTP) && (iface->cost != tmp->dist))
|
||||
else if ((ifa->state == OSPF_IS_PTP) && (ifa->cost != tmp->dist))
|
||||
{
|
||||
iface->cost = tmp->dist;
|
||||
ifa->cost = tmp->dist;
|
||||
schedule_rt_lsa(po->backbone);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iface->state > OSPF_IS_DOWN)
|
||||
if (ifa->state > OSPF_IS_DOWN)
|
||||
{
|
||||
OSPF_TRACE(D_EVENTS, "Vlink peer %R lost", iface->vid);
|
||||
ospf_iface_sm(iface, ISM_DOWN);
|
||||
OSPF_TRACE(D_EVENTS, "Vlink peer %R lost", ifa->vid);
|
||||
ospf_iface_sm(ifa, ISM_DOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ prepare_rt2_lsa_body(struct proto_ospf *po, struct ospf_area *oa)
|
||||
break;
|
||||
|
||||
default:
|
||||
log("Unknown interface type %s", ifa->iface->name);
|
||||
log("Unknown interface type %s", ifa->ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -371,7 +371,7 @@ prepare_rt3_lsa_body(struct proto_ospf *po, struct ospf_area *oa)
|
||||
break;
|
||||
|
||||
default:
|
||||
log("Unknown interface type %s", ifa->iface->name);
|
||||
log("Unknown interface type %s", ifa->ifname);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -844,7 +844,10 @@ ospf_originate_link_lsa(struct ospf_iface *ifa)
|
||||
{
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
|
||||
/* FIXME check for vlink and skip that? */
|
||||
/* Vlinks do not have link-LSAs */
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
return;
|
||||
|
||||
struct ospf_lsa_new lsa = {
|
||||
.type = LSA_T_LINK,
|
||||
.dom = ifa->iface_id,
|
||||
@ -1674,8 +1677,7 @@ flush_net_lsa(struct ospf_iface *ifa)
|
||||
if (ifa->net_lsa == NULL)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s",
|
||||
ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Flushing network-LSA for iface %s", ifa->ifname);
|
||||
|
||||
ifa->net_lsa->lsa.sn += 1;
|
||||
ifa->net_lsa->lsa.age = LSA_MAXAGE;
|
||||
@ -1914,8 +1916,7 @@ flush_prefix_net_lsa(struct ospf_iface *ifa)
|
||||
if (en == NULL)
|
||||
return;
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Flushing network prefix-LSA for iface %s",
|
||||
ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Flushing network prefix-LSA for iface %s", ifa->ifname);
|
||||
|
||||
en->lsa.sn += 1;
|
||||
en->lsa.age = LSA_MAXAGE;
|
||||
@ -1945,14 +1946,14 @@ get_seqnum(struct top_hash_entry *en)
|
||||
|
||||
|
||||
OSPF_TRACE(D_EVENTS, "Originating router-LSA for area %R", oa->areaid);
|
||||
OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Originating network-LSA for iface %s", ifa->ifname);
|
||||
OSPF_TRACE(D_EVENTS, "Originating net-summary-LSA for %I/%d (metric %d)", fn->prefix, fn->pxlen, metric);
|
||||
OSPF_TRACE(D_EVENTS, "Originating rt-summary-LSA for %R (metric %d)", rid, metric);
|
||||
OSPF_TRACE(D_EVENTS, "Originating %s-LSA for %I/%d",
|
||||
nssa ? "NSSA" : "AS-external", fn->prefix, fn->pxlen);
|
||||
OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Originating link-LSA for iface %s", ifa->ifname);
|
||||
OSPF_TRACE(D_EVENTS, "Originating router prefix-LSA for area %R", oa->areaid);
|
||||
OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s", ifa->iface->name);
|
||||
OSPF_TRACE(D_EVENTS, "Originating network prefix-LSA for iface %s", ifa->ifname);
|
||||
|
||||
|
||||
en = ospf_hash_find(po->gr, lsa.dom, lsa.id, po->router_id, lsa.type);
|
||||
|
@ -404,7 +404,7 @@ radv_sk_open(struct radv_iface *ifa)
|
||||
sock *sk = sk_new(ifa->ra->p.pool);
|
||||
sk->type = SK_IP;
|
||||
sk->dport = ICMPV6_PROTO;
|
||||
sk->saddr = IPA_NONE;
|
||||
sk->saddr = ifa->addr->ip;
|
||||
|
||||
sk->ttl = 255; /* Mandatory for Neighbor Discovery packets */
|
||||
sk->rx_hook = radv_rx_hook;
|
||||
@ -419,8 +419,6 @@ radv_sk_open(struct radv_iface *ifa)
|
||||
if (sk_open(sk) != 0)
|
||||
goto err;
|
||||
|
||||
sk->saddr = ifa->addr->ip;
|
||||
|
||||
/* We want listen just to ICMPv6 messages of type RS and RA */
|
||||
if (sk_set_icmp6_filter(sk, ICMPV6_RS, ICMPV6_RA) < 0)
|
||||
goto err;
|
||||
|
@ -719,7 +719,6 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
||||
if (new) {
|
||||
if (new->addr->flags & IA_PEER)
|
||||
log( L_WARN "%s: rip is not defined over unnumbered links", p->name );
|
||||
rif->sock->saddr = IPA_NONE;
|
||||
if (rif->multicast) {
|
||||
rif->sock->daddr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
|
||||
} else {
|
||||
|
@ -64,7 +64,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
|
||||
DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
|
||||
|
||||
rta a = {
|
||||
.src = p->main_source;
|
||||
.src = p->main_source,
|
||||
.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC,
|
||||
.scope = SCOPE_UNIVERSE,
|
||||
.cast = RTC_UNICAST,
|
||||
|
@ -22,16 +22,12 @@
|
||||
#define TCP_MD5SIG TCP_SIGNATURE_ENABLE
|
||||
#endif
|
||||
|
||||
static inline char *
|
||||
sk_bind_to_iface(sock *s)
|
||||
{
|
||||
/* Unfortunately not available */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <netinet/in_systm.h> // Workaround for some BSDs
|
||||
#include <netinet/ip.h>
|
||||
|
||||
|
||||
/* BSD Multicast handling for IPv4 */
|
||||
|
||||
@ -60,7 +56,7 @@ sk_setup_multicast4(sock *s)
|
||||
static inline char *
|
||||
sk_join_group4(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
struct ip_mreq mreq;
|
||||
|
||||
bzero(&mreq, sizeof(mreq));
|
||||
ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip);
|
||||
@ -143,39 +139,52 @@ sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||
s->ttl = * (unsigned char *) CMSG_DATA(cm);
|
||||
}
|
||||
|
||||
|
||||
/* Unfortunately, IP_SENDSRCADDR does not work for raw IP sockets on BSD kernels */
|
||||
/*
|
||||
static void
|
||||
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
|
||||
static inline void
|
||||
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
#ifdef IP_SENDSRCADDR
|
||||
struct cmsghdr *cm;
|
||||
struct in_addr *sa;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_TX))
|
||||
return;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
||||
if (s->iface)
|
||||
{
|
||||
struct in_addr m;
|
||||
set_inaddr(&m, s->saddr);
|
||||
setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m));
|
||||
}
|
||||
|
||||
cm = CMSG_FIRSTHDR(msg);
|
||||
cm->cmsg_level = IPPROTO_IP;
|
||||
cm->cmsg_type = IP_SENDSRCADDR;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*sa));
|
||||
|
||||
sa = (struct in_addr *) CMSG_DATA(cm);
|
||||
set_inaddr(sa, s->saddr);
|
||||
ipa_put_in4(&sa, s->saddr);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sk_prepare_ip_header(sock *s, void *hdr, int dlen)
|
||||
{
|
||||
struct ip *ip = hdr;
|
||||
|
||||
bzero(ip, 20);
|
||||
|
||||
ip->ip_v = 4;
|
||||
ip->ip_hl = 5;
|
||||
ip->ip_tos = (s->tos < 0) ? 0 : s->tos;
|
||||
ip->ip_len = 20 + dlen;
|
||||
ip->ip_ttl = (s->ttl < 0) ? 64 : s->ttl;
|
||||
ip->ip_p = s->dport;
|
||||
ipa_put_in4(&ip->ip_src, s->saddr);
|
||||
ipa_put_in4(&ip->ip_dst, s->daddr);
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
/* OpenBSD expects ip_len in network order, other BSDs expect host order */
|
||||
ip->ip_len = htons(ip->ip_len);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
@ -8,6 +8,8 @@ CONFIG_ALL_TABLES_AT_ONCE Kernel scanner wants to process all tables at once
|
||||
|
||||
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
|
||||
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)
|
||||
CONFIG_NO_IFACE_BIND Bind to iface is not available, use workarounds (def for *BSD)
|
||||
CONFIG_UNIX_DONTROUTE Use setsockopts DONTROUTE (undef for *BSD)
|
||||
CONFIG_USE_HDRINCL Use IP_HDRINCL instead of control messages for source address on raw IP sockets.
|
||||
|
||||
CONFIG_RESTRICTED_PRIVILEGES Implements restricted privileges using drop_uid()
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#define CONFIG_SKIP_MC_BIND
|
||||
#define CONFIG_NO_IFACE_BIND
|
||||
#define CONFIG_USE_HDRINCL
|
||||
|
||||
/*
|
||||
Link: sysdep/unix
|
||||
|
@ -6,9 +6,6 @@
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include <linux/socket.h>
|
||||
#include <linux/tcp.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
|
||||
@ -19,19 +16,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static inline char *
|
||||
sk_bind_to_iface(sock *s)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
strcpy(ifr.ifr_name, s->iface->name);
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
||||
return "SO_BINDTODEVICE";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifndef HAVE_STRUCT_IP_MREQN
|
||||
/* Several versions of glibc don't define this structure, so we have to do it ourselves */
|
||||
struct ip_mreqn
|
||||
@ -43,11 +27,10 @@ struct ip_mreqn
|
||||
#endif
|
||||
|
||||
|
||||
static inline void fill_mreqn(struct ip_mreqn *m, struct iface *ifa, ip_addr saddr, ip_addr maddr)
|
||||
static inline void fill_mreqn(struct ip_mreqn *m, ip_addr maddr, struct iface *ifa)
|
||||
{
|
||||
bzero(m, sizeof(*m));
|
||||
m->imr_ifindex = ifa->index;
|
||||
ipa_put_in4(&m->imr_address, saddr);
|
||||
ipa_put_in4(&m->imr_multiaddr, maddr);
|
||||
}
|
||||
|
||||
@ -64,12 +47,11 @@ sk_setup_multicast4(sock *s)
|
||||
return "IP_MULTICAST_TTL";
|
||||
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
fill_mreqn(&m, s->iface, s->saddr, IPA_NONE);
|
||||
fill_mreqn(&m, IPA_NONE, s->iface);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
|
||||
/* Is this necessary? */
|
||||
return sk_bind_to_iface(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
@ -77,8 +59,7 @@ sk_join_group4(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ip_mreqn m;
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
fill_mreqn(&m, s->iface, s->saddr, maddr);
|
||||
fill_mreqn(&m, maddr, s->iface);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||
return "IP_ADD_MEMBERSHIP";
|
||||
|
||||
@ -90,8 +71,7 @@ sk_leave_group4(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ip_mreqn m;
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
fill_mreqn(&m, s->iface, s->saddr, maddr);
|
||||
fill_mreqn(&m, maddr, s->iface);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||
return "IP_DROP_MEMBERSHIP";
|
||||
|
||||
@ -99,8 +79,7 @@ sk_leave_group4(sock *s, ip_addr maddr)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For the case that we have older kernel headers */
|
||||
/* For the case that we have older libc headers */
|
||||
/* Copied from Linux kernel file include/linux/tcp.h */
|
||||
|
||||
#ifndef TCP_MD5SIG
|
||||
@ -140,7 +119,7 @@ sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd)
|
||||
memcpy(&md5.tcpm_key, passwd, len);
|
||||
}
|
||||
|
||||
int rv = setsockopt(s->fd, IPPROTO_TCP, TCP_MD5SIG, &md5, sizeof(md5));
|
||||
int rv = setsockopt(s->fd, SOL_TCP, TCP_MD5SIG, &md5, sizeof(md5));
|
||||
|
||||
if (rv < 0)
|
||||
{
|
||||
@ -164,7 +143,7 @@ sk_request_cmsg4_pktinfo(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IP, IP_PKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IP_PKTINFO";
|
||||
|
||||
return NULL;
|
||||
@ -189,7 +168,7 @@ sk_request_cmsg4_ttl(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IP, IP_RECVTTL, &ok, sizeof(ok)) < 0)
|
||||
return "IP_RECVTTL";
|
||||
|
||||
return NULL;
|
||||
@ -203,31 +182,28 @@ sk_process_cmsg4_ttl(sock *s, struct cmsghdr *cm)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void
|
||||
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
static inline void
|
||||
sk_prepare_cmsgs4(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in_pktinfo *pi;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_TX))
|
||||
return;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
||||
cm = CMSG_FIRSTHDR(msg);
|
||||
cm->cmsg_level = IPPROTO_IP;
|
||||
cm->cmsg_level = SOL_IP;
|
||||
cm->cmsg_type = IP_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
|
||||
|
||||
pi = (struct in_pktinfo *) CMSG_DATA(cm);
|
||||
set_inaddr(&pi->ipi_spec_dst, s->saddr);
|
||||
pi->ipi_ifindex = s->iface ? s->iface->index : 0;
|
||||
ipa_put_in4(&pi->ipi_spec_dst, s->saddr);
|
||||
ipa_put_in4(&pi->ipi_addr, IPA_NONE);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef IP_MINTTL
|
||||
@ -241,7 +217,7 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
static inline char *
|
||||
sk_set_min_ttl4(sock *s, int ttl)
|
||||
{
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||
return "IP_MINTTL";
|
||||
|
||||
return NULL;
|
||||
@ -250,7 +226,7 @@ sk_set_min_ttl4(sock *s, int ttl)
|
||||
static inline char *
|
||||
sk_set_min_ttl6(sock *s, int ttl)
|
||||
{
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
||||
return "IPV6_MINHOPCOUNT";
|
||||
|
||||
return NULL;
|
||||
|
316
sysdep/unix/io.c
316
sysdep/unix/io.c
@ -23,6 +23,8 @@
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
#include "nest/bird.h"
|
||||
@ -489,6 +491,11 @@ tm_format_datetime(char *x, struct timeformat *fmt_spec, bird_clock_t t)
|
||||
#define SOL_IPV6 IPPROTO_IPV6
|
||||
#endif
|
||||
|
||||
#ifndef SOL_ICMPV6
|
||||
#define SOL_ICMPV6 IPPROTO_ICMPV6
|
||||
#endif
|
||||
|
||||
|
||||
static list sock_list;
|
||||
static struct birdsock *current_sock;
|
||||
static struct birdsock *stored_sock;
|
||||
@ -552,6 +559,43 @@ sk_free(resource *r)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sk_set_rbsize(sock *s, uint val)
|
||||
{
|
||||
ASSERT(s->rbuf_alloc == s->rbuf);
|
||||
|
||||
if (s->rbsize == val)
|
||||
return;
|
||||
|
||||
s->rbsize = val;
|
||||
xfree(s->rbuf_alloc);
|
||||
s->rbuf_alloc = xmalloc(val);
|
||||
s->rpos = s->rbuf = s->rbuf_alloc;
|
||||
}
|
||||
|
||||
void
|
||||
sk_set_tbsize(sock *s, uint val)
|
||||
{
|
||||
ASSERT(s->tbuf_alloc == s->tbuf);
|
||||
|
||||
if (s->tbsize == val)
|
||||
return;
|
||||
|
||||
byte *old_tbuf = s->tbuf;
|
||||
|
||||
s->tbsize = val;
|
||||
s->tbuf = s->tbuf_alloc = xrealloc(s->tbuf_alloc, val);
|
||||
s->tpos = s->tbuf + (s->tpos - old_tbuf);
|
||||
s->ttx = s->tbuf + (s->ttx - old_tbuf);
|
||||
}
|
||||
|
||||
void
|
||||
sk_set_tbuf(sock *s, void *tbuf)
|
||||
{
|
||||
s->tbuf = tbuf ?: s->tbuf_alloc;
|
||||
s->ttx = s->tpos = s->tbuf;
|
||||
}
|
||||
|
||||
void
|
||||
sk_reallocate(sock *s)
|
||||
{
|
||||
@ -720,7 +764,7 @@ sk_request_cmsg6_pktinfo(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVPKTINFO, &ok, sizeof(ok)) < 0)
|
||||
return "IPV6_RECVPKTINFO";
|
||||
|
||||
return NULL;
|
||||
@ -745,7 +789,7 @@ sk_request_cmsg6_ttl(sock *s)
|
||||
{
|
||||
int ok = 1;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_RECVHOPLIMIT, &ok, sizeof(ok)) < 0)
|
||||
return "IPV6_RECVHOPLIMIT";
|
||||
|
||||
return NULL;
|
||||
@ -780,13 +824,13 @@ sk_process_cmsgs(sock *s, struct msghdr *msg)
|
||||
|
||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
||||
{
|
||||
if ((cm->cmsg_level == IPPROTO_IP) && sk_is_ipv4(s))
|
||||
if ((cm->cmsg_level == SOL_IP) && sk_is_ipv4(s))
|
||||
{
|
||||
sk_process_cmsg4_pktinfo(s, cm);
|
||||
sk_process_cmsg4_ttl(s, cm);
|
||||
}
|
||||
|
||||
if ((cm->cmsg_level == IPPROTO_IPV6) && sk_is_ipv6(s))
|
||||
if ((cm->cmsg_level == SOL_IPV6) && sk_is_ipv6(s))
|
||||
{
|
||||
sk_process_cmsg6_pktinfo(s, cm);
|
||||
sk_process_cmsg6_ttl(s, cm);
|
||||
@ -795,32 +839,36 @@ sk_process_cmsgs(sock *s, struct msghdr *msg)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static void
|
||||
sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
static inline void
|
||||
sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo *pi;
|
||||
|
||||
if (!(s->flags & SKF_LADDR_TX))
|
||||
return;
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
||||
cm = CMSG_FIRSTHDR(msg);
|
||||
cm->cmsg_level = IPPROTO_IPV6;
|
||||
cm->cmsg_level = SOL_IPV6;
|
||||
cm->cmsg_type = IPV6_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(*pi));
|
||||
|
||||
pi = (struct in6_pktinfo *) CMSG_DATA(cm);
|
||||
set_inaddr(&pi->ipi6_addr, s->saddr);
|
||||
pi->ipi6_ifindex = s->iface ? s->iface->index : 0;
|
||||
ipa_put_in6(&pi->ipi6_addr, s->saddr);
|
||||
|
||||
msg->msg_controllen = cm->cmsg_len;
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
sk_prepare_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
if (sk_is_ipv4(s))
|
||||
sk_prepare_cmsgs4(s, msg, cbuf, cbuflen);
|
||||
else
|
||||
sk_prepare_cmsgs6(s, msg, cbuf, cbuflen);
|
||||
}
|
||||
|
||||
|
||||
#define ERR(x) do { err = x; goto bad; } while(0)
|
||||
#define WARN(x) log(L_WARN "sk_setup: %s: %m", x)
|
||||
@ -838,20 +886,33 @@ sk_setup(sock *s)
|
||||
if (!s->af)
|
||||
return NULL;
|
||||
|
||||
if (sk_is_ipv4(s) && (s->tos >= 0))
|
||||
if (setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
|
||||
WARN("IP_TOS");
|
||||
if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
|
||||
s->flags |= SKF_PKTINFO;
|
||||
|
||||
if (sk_is_ipv6(s) && (s->tos >= 0))
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_TCLASS, &s->tos, sizeof(s->tos)) < 0)
|
||||
WARN("IPV6_TCLASS");
|
||||
#ifdef CONFIG_USE_HDRINCL
|
||||
if (sk_is_ipv4(s) && (s->type == SK_IP) && (s->flags & SKF_PKTINFO))
|
||||
{
|
||||
s->flags &= ~SKF_PKTINFO;
|
||||
s->flags |= SKF_HDRINCL;
|
||||
if (setsockopt(fd, SOL_IP, IP_HDRINCL, &one, sizeof(one)) < 0)
|
||||
ERR("IP_HDRINCL");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (sk_is_ipv6(s) && (s->flags & SKF_V6ONLY))
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0)
|
||||
WARN("IPV6_V6ONLY");
|
||||
if (s->iface)
|
||||
{
|
||||
#ifdef SO_BINDTODEVICE
|
||||
struct ifreq ifr;
|
||||
strcpy(ifr.ifr_name, s->iface->name);
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
||||
ERR("SO_BINDTODEVICE");
|
||||
#endif
|
||||
|
||||
if (s->priority >= 0)
|
||||
sk_set_priority(s, s->priority);
|
||||
#ifdef CONFIG_UNIX_DONTROUTE
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
||||
ERR("SO_DONTROUTE");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (s->ttl >= 0)
|
||||
if (sk_set_ttl(s, s->ttl) < 0)
|
||||
@ -875,9 +936,25 @@ sk_setup(sock *s)
|
||||
goto bad;
|
||||
|
||||
if (s->flags & SKF_TTL_RX)
|
||||
if (err = sk_request_cmsg6_ttl(s));
|
||||
if (err = sk_request_cmsg6_ttl(s))
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (sk_is_ipv4(s) && (s->tos >= 0))
|
||||
if (setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
|
||||
WARN("IP_TOS");
|
||||
|
||||
if (sk_is_ipv6(s) && (s->tos >= 0))
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_TCLASS, &s->tos, sizeof(s->tos)) < 0)
|
||||
WARN("IPV6_TCLASS");
|
||||
|
||||
if (sk_is_ipv6(s) && (s->flags & SKF_V6ONLY))
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &one, sizeof(one)) < 0)
|
||||
WARN("IPV6_V6ONLY");
|
||||
|
||||
if (s->priority >= 0)
|
||||
sk_set_priority(s, s->priority);
|
||||
|
||||
return NULL;
|
||||
|
||||
bad:
|
||||
@ -905,13 +982,6 @@ sk_set_ttl(sock *s, int ttl)
|
||||
{
|
||||
if (setsockopt(s->fd, SOL_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
ERR("IP_TTL");
|
||||
|
||||
#ifdef CONFIG_UNIX_DONTROUTE
|
||||
int one = 1;
|
||||
if (ttl == 1)
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
|
||||
ERR("SO_DONTROUTE");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1003,7 +1073,7 @@ sk_set_broadcast(sock *s, int enable)
|
||||
int
|
||||
sk_set_ipv6_checksum(sock *s, int offset)
|
||||
{
|
||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) < 0)
|
||||
{
|
||||
log(L_ERR "sk_set_ipv6_checksum: IPV6_CHECKSUM: %m");
|
||||
return -1;
|
||||
@ -1022,7 +1092,7 @@ sk_set_icmp6_filter(sock *s, int p1, int p2)
|
||||
ICMP6_FILTER_SETPASS(p1, &f);
|
||||
ICMP6_FILTER_SETPASS(p2, &f);
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
|
||||
if (setsockopt(s->fd, SOL_ICMPV6, ICMP6_FILTER, &f, sizeof(f)) < 0)
|
||||
{
|
||||
log(L_ERR "sk_set_icmp6_filter: ICMP6_FILTER: %m");
|
||||
return -1;
|
||||
@ -1031,18 +1101,16 @@ sk_set_icmp6_filter(sock *s, int p1, int p2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IPV6_GLIBC_20
|
||||
#define ipv6mr_interface ipv6mr_ifindex
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
fill_mreq6(struct ipv6_mreq *m, struct iface *ifa, ip_addr maddr)
|
||||
{
|
||||
bzero(m, sizeof(*m));
|
||||
|
||||
#ifdef CONFIG_IPV6_GLIBC_20
|
||||
m->ipv6mr_ifindex = ifa->index;
|
||||
#else
|
||||
m->ipv6mr_interface = ifa->index;
|
||||
#endif
|
||||
|
||||
ipa_put_in6(&m->ipv6mr_multiaddr, maddr);
|
||||
}
|
||||
|
||||
@ -1059,8 +1127,7 @@ sk_setup_multicast6(sock *s)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
|
||||
return "IPV6_MULTICAST_IF";
|
||||
|
||||
/* Is this necessary? */
|
||||
return sk_bind_to_iface(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
@ -1068,7 +1135,7 @@ sk_setup_multicast(sock *s)
|
||||
{
|
||||
char *err;
|
||||
|
||||
ASSERT(s->iface && s->iface->addr);
|
||||
ASSERT(s->iface);
|
||||
|
||||
if (sk_is_ipv4(s))
|
||||
err = sk_setup_multicast4(s);
|
||||
@ -1215,11 +1282,12 @@ sk_passive_connected(sock *s, struct sockaddr *sa, int sa_len, int type)
|
||||
int
|
||||
sk_open(sock *s)
|
||||
{
|
||||
int type = s->type;
|
||||
int has_src = ipa_nonzero(s->saddr) || s->sport;
|
||||
int do_bind = 0;
|
||||
int bind_port = 0;
|
||||
ip_addr bind_addr = IPA_NONE;
|
||||
char *err;
|
||||
|
||||
switch (type)
|
||||
switch (s->type)
|
||||
{
|
||||
case SK_TCP_ACTIVE:
|
||||
s->ttx = ""; /* Force s->ttx != s->tpos */
|
||||
@ -1227,22 +1295,35 @@ sk_open(sock *s)
|
||||
case SK_TCP_PASSIVE:
|
||||
s->af = (s->flags & SKF_V4ONLY) ? AF_INET : AF_INET6;
|
||||
s->fd = socket(s->af, SOCK_STREAM, IPPROTO_TCP);
|
||||
bind_port = s->sport;
|
||||
bind_addr = s->saddr;
|
||||
do_bind = bind_port || ipa_nonzero(bind_addr);
|
||||
break;
|
||||
case SK_UDP:
|
||||
|
||||
case SK_UDP:
|
||||
s->af = (s->flags & SKF_V4ONLY) ? AF_INET : AF_INET6;
|
||||
s->fd = socket(s->af, SOCK_DGRAM, IPPROTO_UDP);
|
||||
bind_port = s->sport;
|
||||
bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
|
||||
do_bind = 1;
|
||||
break;
|
||||
|
||||
case SK_IP:
|
||||
s->af = (s->flags & SKF_V4ONLY) ? AF_INET : AF_INET6;
|
||||
s->fd = socket(s->af, SOCK_RAW, s->dport);
|
||||
bind_port = 0;
|
||||
bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
|
||||
do_bind = ipa_nonzero(bind_addr);
|
||||
break;
|
||||
|
||||
case SK_MAGIC:
|
||||
if (err = sk_setup(s))
|
||||
goto bad;
|
||||
sk_insert(s);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
bug("sk_open() called for invalid sock type %d", type);
|
||||
bug("sk_open() called for invalid sock type %d", s->type);
|
||||
}
|
||||
|
||||
int fd = s->fd;
|
||||
@ -1254,23 +1335,18 @@ sk_open(sock *s)
|
||||
|
||||
SOCKADDR_DEFINE(sa, sa_len, s->af);
|
||||
|
||||
if (has_src)
|
||||
if (do_bind)
|
||||
{
|
||||
int port;
|
||||
|
||||
if (type == SK_IP)
|
||||
port = 0;
|
||||
else
|
||||
if (bind_port)
|
||||
{
|
||||
port = s->sport;
|
||||
|
||||
int one = 1;
|
||||
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
|
||||
ERR("SO_REUSEADDR");
|
||||
|
||||
|
||||
#ifdef CONFIG_NO_IFACE_BIND
|
||||
/* Workaround missing ability to bind to an iface */
|
||||
if ((type == SK_UDP) && s->iface && ipa_zero(s->saddr))
|
||||
if ((s->type == SK_UDP) && s->iface && ipa_zero(bind_addr))
|
||||
{
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) < 0)
|
||||
ERR("SO_REUSEPORT");
|
||||
@ -1278,17 +1354,18 @@ sk_open(sock *s)
|
||||
#endif
|
||||
}
|
||||
|
||||
sockaddr_fill(sa, s->saddr, s->iface, port);
|
||||
sockaddr_fill(sa, bind_addr, s->iface, bind_port);
|
||||
if (bind(fd, sa, sa_len) < 0)
|
||||
ERR("bind");
|
||||
}
|
||||
|
||||
sockaddr_fill(sa, s->daddr, s->iface, s->dport);
|
||||
|
||||
if (s->password)
|
||||
if (sk_set_md5_auth_int(s, sa, sa_len, s->password) < 0)
|
||||
goto bad_no_log;
|
||||
|
||||
switch (type)
|
||||
switch (s->type)
|
||||
{
|
||||
case SK_TCP_ACTIVE:
|
||||
if (connect(fd, sa, sa_len) >= 0)
|
||||
@ -1366,6 +1443,80 @@ sk_open_unix(sock *s, char *name)
|
||||
die("Unable to create control socket %s", name);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
sk_sendmsg(sock *s)
|
||||
{
|
||||
struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
|
||||
byte cmsg_buf[CMSG_TX_SPACE];
|
||||
|
||||
SOCKADDR_DEFINE(dst, dst_len, s->af);
|
||||
sockaddr_fill(dst, s->daddr, s->iface, s->dport);
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = dst,
|
||||
.msg_namelen = dst_len,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1
|
||||
};
|
||||
|
||||
#ifdef CONFIG_USE_HDRINCL
|
||||
byte hdr[20];
|
||||
struct iovec iov2[2] = { {hdr, 20}, iov };
|
||||
|
||||
if (s->flags & SKF_HDRINCL)
|
||||
{
|
||||
sk_prepare_ip_header(s, hdr, iov.iov_len);
|
||||
msg.msg_iov = iov2;
|
||||
msg.msg_iovlen = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->flags & SKF_PKTINFO)
|
||||
sk_prepare_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
|
||||
|
||||
return sendmsg(s->fd, &msg, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
sk_recvmsg(sock *s)
|
||||
{
|
||||
struct iovec iov = {s->rbuf, s->rbsize};
|
||||
byte cmsg_buf[CMSG_RX_SPACE];
|
||||
|
||||
SOCKADDR_DEFINE(src, src_len, s->af);
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = src,
|
||||
.msg_namelen = src_len,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsg_buf,
|
||||
.msg_controllen = sizeof(cmsg_buf),
|
||||
.msg_flags = 0
|
||||
};
|
||||
|
||||
int rv = recvmsg(s->fd, &msg, 0);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
//ifdef IPV4
|
||||
// if (cf_type == SK_IP)
|
||||
// rv = ipv4_skip_header(pbuf, rv);
|
||||
//endif
|
||||
|
||||
sockaddr_read(src, &s->faddr, NULL, &s->fport, 1);
|
||||
sk_process_cmsgs(s, &msg);
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC)
|
||||
s->flags |= SKF_TRUNCATED;
|
||||
else
|
||||
s->flags &= ~SKF_TRUNCATED;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
static inline void reset_tx_buffer(sock *s) { s->ttx = s->tpos = s->tbuf; }
|
||||
|
||||
static int
|
||||
@ -1381,6 +1532,7 @@ sk_maybe_write(sock *s)
|
||||
while (s->ttx != s->tpos)
|
||||
{
|
||||
e = write(s->fd, s->ttx, s->tpos - s->ttx);
|
||||
|
||||
if (e < 0)
|
||||
{
|
||||
if (errno != EINTR && errno != EAGAIN)
|
||||
@ -1402,20 +1554,7 @@ sk_maybe_write(sock *s)
|
||||
if (s->tbuf == s->tpos)
|
||||
return 1;
|
||||
|
||||
SOCKADDR_DEFINE(sa, sa_len, s->af);
|
||||
sockaddr_fill(sa, s->daddr, s->iface, s->dport);
|
||||
|
||||
struct iovec iov = {s->tbuf, s->tpos - s->tbuf};
|
||||
// byte cmsg_buf[CMSG_TX_SPACE];
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = sa,
|
||||
.msg_namelen = sa_len,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1};
|
||||
|
||||
// sysio_prepare_tx_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
|
||||
e = sendmsg(s->fd, &msg, 0);
|
||||
e = sk_sendmsg(s);
|
||||
|
||||
if (e < 0)
|
||||
{
|
||||
@ -1425,6 +1564,9 @@ sk_maybe_write(sock *s)
|
||||
s->err_hook(s, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!s->tx_hook)
|
||||
reset_tx_buffer(s);
|
||||
return 0;
|
||||
}
|
||||
reset_tx_buffer(s);
|
||||
@ -1487,12 +1629,15 @@ sk_send(sock *s, unsigned len)
|
||||
*
|
||||
* This is a sk_send() replacement for connection-less packet sockets
|
||||
* which allows destination of the packet to be chosen dynamically.
|
||||
* Raw IP sockets should use 0 for @port.
|
||||
*/
|
||||
int
|
||||
sk_send_to(sock *s, unsigned len, ip_addr addr, unsigned port)
|
||||
{
|
||||
s->daddr = addr;
|
||||
s->dport = port;
|
||||
if (port)
|
||||
s->dport = port;
|
||||
|
||||
s->ttx = s->tbuf;
|
||||
s->tpos = s->tbuf + len;
|
||||
return sk_maybe_write(s);
|
||||
@ -1558,22 +1703,7 @@ sk_read(sock *s)
|
||||
return s->rx_hook(s, 0);
|
||||
default:
|
||||
{
|
||||
SOCKADDR_DEFINE(sa, sa_len, s->af);
|
||||
int e;
|
||||
|
||||
struct iovec iov = {s->rbuf, s->rbsize};
|
||||
byte cmsg_buf[CMSG_RX_SPACE];
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = sa,
|
||||
.msg_namelen = sa_len,
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
.msg_control = cmsg_buf,
|
||||
.msg_controllen = sizeof(cmsg_buf),
|
||||
.msg_flags = 0};
|
||||
|
||||
e = recvmsg(s->fd, &msg, 0);
|
||||
int e = sk_recvmsg(s);
|
||||
|
||||
if (e < 0)
|
||||
{
|
||||
@ -1581,10 +1711,8 @@ sk_read(sock *s)
|
||||
s->err_hook(s, errno);
|
||||
return 0;
|
||||
}
|
||||
s->rpos = s->rbuf + e;
|
||||
sockaddr_read(sa, &s->faddr, NULL, &s->fport, 1);
|
||||
sk_process_cmsgs(s, &msg);
|
||||
|
||||
s->rpos = s->rbuf + e;
|
||||
s->rx_hook(s, e);
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user