Temporary OSPFv3 development commit (changing multicast support).
This commit is contained in:
parent
d2ceaf4ec8
commit
f9c799a00e
18 changed files with 412 additions and 336 deletions
12
lib/socket.h
12
lib/socket.h
|
@ -50,7 +50,15 @@ int sk_send_to(sock *, unsigned len, ip_addr to, unsigned port); /* sk_send to g
|
|||
void sk_reallocate(sock *); /* Free and allocate tbuf & rbuf */
|
||||
void sk_dump_all(void);
|
||||
int sk_set_ttl(sock *s, int ttl); /* Set TTL for given socket */
|
||||
int sk_set_md5_auth(sock *s, ip_addr a, char *passwd); /* Add or remove security associations for given passive socket */
|
||||
|
||||
/* Add or remove security associations for given passive socket */
|
||||
int sk_set_md5_auth(sock *s, ip_addr a, char *passwd);
|
||||
|
||||
/* Prepare UDP or IP socket to multicasting. s->iface and s->ttl must be set */
|
||||
int sk_setup_multicast(sock *s);
|
||||
int sk_join_group(sock *s, ip_addr maddr);
|
||||
int sk_leave_group(sock *s, ip_addr maddr);
|
||||
|
||||
|
||||
static inline int
|
||||
sk_send_buffer_empty(sock *sk)
|
||||
|
@ -72,9 +80,7 @@ sk_send_buffer_empty(sock *sk)
|
|||
#define SK_TCP_ACTIVE 1 /* ? ? * * - ? - */
|
||||
#define SK_TCP 2
|
||||
#define SK_UDP 3 /* ? ? - - - ? ? */
|
||||
#define SK_UDP_MC 4 /* ? ? * * * * - */
|
||||
#define SK_IP 5 /* ? - - * - ? ? */
|
||||
#define SK_IP_MC 6 /* ? - * * * * - */
|
||||
#define SK_MAGIC 7 /* Internal use by sysdep code */
|
||||
#define SK_UNIX_PASSIVE 8
|
||||
#define SK_UNIX 9
|
||||
|
|
|
@ -93,7 +93,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
|||
{
|
||||
case NEIGHBOR_EXSTART: /* Send empty packets */
|
||||
n->myimms.bit.i = 1;
|
||||
pkt = (struct ospf_dbdes_packet *) (ifa->ip_sk->tbuf);
|
||||
pkt = (struct ospf_dbdes_packet *) (ifa->sk->tbuf);
|
||||
op = (struct ospf_packet *) pkt;
|
||||
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
|
||||
pkt->iface_mtu = htons(ifa->iface->mtu);
|
||||
|
@ -104,7 +104,7 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
|||
op->length = htons(length);
|
||||
|
||||
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
ospf_send_to(ifa->ip_sk, n->ip, ifa);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
break;
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
|
@ -185,11 +185,11 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
|
|||
}
|
||||
|
||||
/* Copy last sent packet again */
|
||||
memcpy(ifa->ip_sk->tbuf, n->ldbdes, length);
|
||||
memcpy(ifa->sk->tbuf, n->ldbdes, length);
|
||||
|
||||
OSPF_PACKET(ospf_dump_dbdes, (struct ospf_dbdes_packet *) ifa->ip_sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_dbdes, (struct ospf_dbdes_packet *) ifa->sk->tbuf,
|
||||
"DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
|
||||
ospf_send_to(ifa->ip_sk, n->ip, n->ifa);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
|
||||
if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
||||
|
||||
#ifdef OSPFv2
|
||||
mask = ps->netmask;
|
||||
ip_addr mask = ps->netmask;
|
||||
ipa_ntoh(mask);
|
||||
if (ifa->type != OSPF_IT_VLINK)
|
||||
{
|
||||
|
@ -198,7 +198,7 @@ ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
|||
if (n->state >= NEIGHBOR_2WAY)
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
u32 rid = n->ip;
|
||||
u32 rid = ipa_to_u32(n->ip);
|
||||
#else /* OSPFv3 */
|
||||
u32 rid = p->cf->global->router_id;
|
||||
#endif
|
||||
|
@ -266,20 +266,12 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
|
|||
p = (struct proto *) (ifa->oa->po);
|
||||
DBG("%s: Hello/Poll timer fired on interface %s.\n",
|
||||
p->name, ifa->iface->name);
|
||||
/* Now we should send a hello packet */
|
||||
/* First a common packet header */
|
||||
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
|
||||
{
|
||||
pkt = (struct ospf_hello_packet *) (ifa->ip_sk->tbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
pkt = (struct ospf_hello_packet *) (ifa->hello_sk->tbuf);
|
||||
}
|
||||
|
||||
/* Now fill ospf_hello header */
|
||||
/* Now we should send a hello packet */
|
||||
pkt = (struct ospf_hello_packet *) (ifa->sk->tbuf);
|
||||
op = (struct ospf_packet *) pkt;
|
||||
|
||||
/* Now fill ospf_hello header */
|
||||
ospf_pkt_fill_hdr(ifa, pkt, HELLO_P);
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
@ -332,7 +324,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
|
|||
case OSPF_IT_NBMA:
|
||||
if (timer == NULL) /* Response to received hello */
|
||||
{
|
||||
ospf_send_to(ifa->ip_sk, dirn->ip, ifa);
|
||||
ospf_send_to(ifa, dirn->ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -357,7 +349,7 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
|
|||
if ((poll == 1) && (send))
|
||||
{
|
||||
if (toall || (meeli && nb->eligible))
|
||||
ospf_send_to(ifa->ip_sk, nb->ip, ifa);
|
||||
ospf_send_to(ifa, nb->ip);
|
||||
}
|
||||
}
|
||||
if (poll == 0)
|
||||
|
@ -366,16 +358,16 @@ ospf_hello_send(timer *timer, int poll, struct ospf_neighbor *dirn)
|
|||
{
|
||||
if (toall || (n1->rid == ifa->drid) || (n1->rid == ifa->bdrid) ||
|
||||
(meeli && (n1->priority > 0)))
|
||||
ospf_send_to(ifa->ip_sk, n1->ip, ifa);
|
||||
ospf_send_to(ifa, n1->ip);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OSPF_IT_VLINK:
|
||||
ospf_send_to(ifa->ip_sk, ifa->vip, ifa);
|
||||
ospf_send_to(ifa, ifa->vip);
|
||||
break;
|
||||
default:
|
||||
ospf_send_to(ifa->hello_sk, IPA_NONE, ifa);
|
||||
ospf_send_to(ifa, AllSPFRouters);
|
||||
}
|
||||
|
||||
OSPF_TRACE(D_PACKETS, "HELLO packet sent via %s%s",
|
||||
|
|
|
@ -59,7 +59,7 @@ rxbufsize(struct ospf_iface *ifa)
|
|||
}
|
||||
|
||||
static sock *
|
||||
ospf_open_ip_socket(struct ospf_iface *ifa)
|
||||
ospf_open_socket(struct ospf_iface *ifa, int mc)
|
||||
{
|
||||
sock *ipsk;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
|
@ -69,7 +69,8 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
|
|||
ipsk->dport = OSPF_PROTO;
|
||||
|
||||
#ifdef OSPFv2
|
||||
ipsk->saddr = ifa->iface->addr->ip;
|
||||
// ipsk->saddr = ifa->iface->addr->ip;
|
||||
ipsk->saddr = IPA_NONE;
|
||||
#else /* OSPFv3 */
|
||||
ipsk->saddr = ifa->lladdr;
|
||||
#endif
|
||||
|
@ -86,12 +87,22 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
|
|||
ipsk->tbsize = ifa->iface->mtu;
|
||||
ipsk->data = (void *) ifa;
|
||||
if (sk_open(ipsk) != 0)
|
||||
goto err;
|
||||
|
||||
if (mc)
|
||||
{
|
||||
DBG("%s: SK_OPEN: ip open failed.\n", p->name);
|
||||
return (NULL);
|
||||
if (sk_setup_multicast(ipsk) < 0)
|
||||
goto err;
|
||||
|
||||
if (sk_join_group(ipsk, AllSPFRouters) < 0)
|
||||
goto err;
|
||||
}
|
||||
DBG("%s: SK_OPEN: ip opened.\n", p->name);
|
||||
return (ipsk);
|
||||
|
||||
return ipsk;
|
||||
|
||||
err:
|
||||
rfree(ipsk);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +133,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
|||
ifa->vid, ospf_is[oldstate], ospf_is[state]);
|
||||
if (state == OSPF_IS_PTP)
|
||||
{
|
||||
ifa->ip_sk = ospf_open_ip_socket(ifa);
|
||||
ifa->sk = ospf_open_socket(ifa, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -132,43 +143,17 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
|
|||
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
|
||||
if (ifa->iface->flags & IF_MULTICAST)
|
||||
{
|
||||
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
|
||||
if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) &&
|
||||
((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)))
|
||||
{
|
||||
if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA))
|
||||
{
|
||||
DBG("%s: Adding new multicast socket for (B)DR\n", p->name);
|
||||
ifa->dr_sk = sk_new(p->pool);
|
||||
ifa->dr_sk->type = SK_IP_MC;
|
||||
ifa->dr_sk->sport = 0;
|
||||
ifa->dr_sk->dport = OSPF_PROTO;
|
||||
|
||||
#ifdef OSPFv2
|
||||
ifa->dr_sk->saddr = AllDRouters;
|
||||
#else /* OSPFv3 */
|
||||
// ifa->dr_sk->saddr = AllDRouters;
|
||||
ifa->dr_sk->saddr = ifa->lladdr;
|
||||
#endif
|
||||
|
||||
ifa->dr_sk->daddr = AllDRouters;
|
||||
ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
|
||||
ifa->dr_sk->ttl = 1;
|
||||
ifa->dr_sk->rx_hook = ospf_rx_hook;
|
||||
ifa->dr_sk->tx_hook = ospf_tx_hook;
|
||||
ifa->dr_sk->err_hook = ospf_err_hook;
|
||||
ifa->dr_sk->iface = ifa->iface;
|
||||
ifa->dr_sk->rbsize = rxbufsize(ifa);
|
||||
ifa->dr_sk->tbsize = ifa->iface->mtu;
|
||||
ifa->dr_sk->data = (void *) ifa;
|
||||
if (sk_open(ifa->dr_sk) != 0)
|
||||
{
|
||||
DBG("%s: SK_OPEN: new? mc open failed.\n", p->name);
|
||||
/* FIXME some error handing ? */
|
||||
sk_join_group(ifa->sk, AllDRouters);
|
||||
ifa->dr_up = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (ifa->dr_up)
|
||||
{
|
||||
rfree(ifa->dr_sk);
|
||||
ifa->dr_sk = NULL;
|
||||
sk_leave_group(ifa->sk, AllDRouters);
|
||||
ifa->dr_up = 0;
|
||||
}
|
||||
if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL))
|
||||
{
|
||||
|
@ -209,13 +194,12 @@ ospf_iface_down(struct ospf_iface *ifa)
|
|||
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
|
||||
ospf_neigh_remove(n);
|
||||
}
|
||||
rfree(ifa->hello_sk);
|
||||
rfree(ifa->dr_sk);
|
||||
rfree(ifa->ip_sk);
|
||||
|
||||
rfree(ifa->sk);
|
||||
ifa->sk = NULL;
|
||||
|
||||
if (ifa->type == OSPF_IT_VLINK)
|
||||
{
|
||||
ifa->ip_sk = NULL;
|
||||
ifa->iface = NULL;
|
||||
return;
|
||||
}
|
||||
|
@ -311,6 +295,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event)
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
static sock *
|
||||
ospf_open_mc_socket(struct ospf_iface *ifa)
|
||||
{
|
||||
|
@ -347,6 +332,7 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
|
|||
DBG("%s: SK_OPEN: mc opened.\n", p->name);
|
||||
return (mcsk);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8
|
||||
ospf_iface_clasify(struct iface * ifa)
|
||||
|
@ -383,20 +369,8 @@ ospf_iface_add(struct object_lock *lock)
|
|||
|
||||
ifa->ioprob = OSPF_I_OK;
|
||||
|
||||
if (ifa->type != OSPF_IT_NBMA)
|
||||
{
|
||||
if ((ifa->hello_sk = ospf_open_mc_socket(ifa)) == NULL)
|
||||
{
|
||||
log("%s: Huh? could not open mc socket on interface %s?", p->name,
|
||||
iface->name);
|
||||
log("%s: Declaring as stub.", p->name);
|
||||
ifa->stub = 1;
|
||||
ifa->ioprob += OSPF_I_MC;
|
||||
}
|
||||
ifa->dr_sk = NULL;
|
||||
}
|
||||
|
||||
if ((ifa->ip_sk = ospf_open_ip_socket(ifa)) == NULL)
|
||||
ifa->sk = ospf_open_socket(ifa, ifa->type != OSPF_IT_NBMA);
|
||||
if (ifa->sk == NULL)
|
||||
{
|
||||
log("%s: Huh? could not open ip socket on interface %s?", p->name,
|
||||
iface->name);
|
||||
|
@ -546,23 +520,12 @@ 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);
|
||||
if (ifa->hello_sk)
|
||||
|
||||
if (ifa->sk)
|
||||
{
|
||||
ifa->hello_sk->rbsize = rxbufsize(ifa);
|
||||
ifa->hello_sk->tbsize = ifa->iface->mtu;
|
||||
sk_reallocate(ifa->hello_sk);
|
||||
}
|
||||
if (ifa->dr_sk)
|
||||
{
|
||||
ifa->dr_sk->rbsize = rxbufsize(ifa);
|
||||
ifa->dr_sk->tbsize = ifa->iface->mtu;
|
||||
sk_reallocate(ifa->dr_sk);
|
||||
}
|
||||
if (ifa->ip_sk)
|
||||
{
|
||||
ifa->ip_sk->rbsize = rxbufsize(ifa);
|
||||
ifa->ip_sk->tbsize = ifa->iface->mtu;
|
||||
sk_reallocate(ifa->ip_sk);
|
||||
ifa->sk->rbsize = rxbufsize(ifa);
|
||||
ifa->sk->tbsize = ifa->iface->mtu;
|
||||
sk_reallocate(ifa->sk);
|
||||
}
|
||||
|
||||
WALK_LIST(n, ifa->neigh_list)
|
||||
|
|
|
@ -57,7 +57,6 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
{
|
||||
struct ospf_packet *op;
|
||||
struct ospf_lsack_packet *pk;
|
||||
sock *sk;
|
||||
u16 len, i = 0;
|
||||
struct ospf_lsa_header *h;
|
||||
struct lsah_n *no;
|
||||
|
@ -67,13 +66,8 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
if (EMPTY_LIST(n->ackl[queue]))
|
||||
return;
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
sk = ifa->hello_sk;
|
||||
else
|
||||
sk = ifa->ip_sk;
|
||||
|
||||
pk = (struct ospf_lsack_packet *) sk->tbuf;
|
||||
op = (struct ospf_packet *) sk->tbuf;
|
||||
pk = (struct ospf_lsack_packet *) ifa->sk->tbuf;
|
||||
op = (struct ospf_packet *) ifa->sk->tbuf;
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
||||
h = pk->lsh;
|
||||
|
@ -98,22 +92,22 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
op->length = htons(len);
|
||||
DBG("Sending and continuing! Len=%u\n", len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
|
||||
"LSACK packet sent via %s", ifa->iface->name);
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to(sk, AllSPFRouters, ifa);
|
||||
ospf_send_to(ifa, AllSPFRouters);
|
||||
else
|
||||
ospf_send_to(sk, AllDRouters, ifa);
|
||||
ospf_send_to(ifa, AllDRouters);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
ospf_send_to_bdr(sk, ifa);
|
||||
ospf_send_to_bdr(ifa);
|
||||
}
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSACK_P);
|
||||
|
@ -126,24 +120,18 @@ ospf_lsack_send(struct ospf_neighbor *n, int queue)
|
|||
op->length = htons(len);
|
||||
DBG("Sending! Len=%u\n", len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsack, (struct ospf_lsack_packet *) ifa->sk->tbuf,
|
||||
"LSACK packet sent via %s", ifa->iface->name);
|
||||
|
||||
if (ifa->type == OSPF_IT_BCAST)
|
||||
{
|
||||
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
|
||||
{
|
||||
ospf_send_to(sk, AllSPFRouters, ifa);
|
||||
ospf_send_to(ifa, AllSPFRouters);
|
||||
else
|
||||
ospf_send_to(ifa, AllDRouters);
|
||||
}
|
||||
else
|
||||
{
|
||||
ospf_send_to(sk, AllDRouters, ifa);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
|
||||
}
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -126,6 +126,7 @@ void
|
|||
htonlsab(void *h, void *n, u16 type, u16 len)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
|
@ -138,10 +139,9 @@ htonlsab(void *h, void *n, u16 type, u16 len)
|
|||
hrt = h;
|
||||
|
||||
#ifdef OSPFv2
|
||||
nrt->veb.byte = hrt->veb.byte;
|
||||
nrt->padding = 0;
|
||||
nrt->links = htons(hrt->links);
|
||||
links = hrt->links;
|
||||
nrt->options = htons(hrt->options);
|
||||
nrt->links = htons(hrt->links);
|
||||
#else /* OSPFv3 */
|
||||
nrt->options = htonl(hrt->options);
|
||||
links = (len - sizeof(struct ospf_lsa_rt)) /
|
||||
|
@ -211,8 +211,7 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
|
|||
hrt = h;
|
||||
|
||||
#ifdef OSPFv2
|
||||
hrt->veb.byte = nrt->veb.byte;
|
||||
hrt->padding = 0;
|
||||
hrt->options = ntohs(nrt->options);
|
||||
links = hrt->links = ntohs(nrt->links);
|
||||
#else /* OSPFv3 */
|
||||
hrt->options = ntohl(nrt->options);
|
||||
|
@ -308,19 +307,20 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
|
|||
u16 length = h->length;
|
||||
u16 type = h->type;
|
||||
|
||||
log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
|
||||
// log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
|
||||
htonlsah(h, h);
|
||||
|
||||
htonlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
|
||||
|
||||
/*
|
||||
char buf[1024];
|
||||
memcpy(buf, h, sizeof(struct ospf_lsa_header));
|
||||
memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header));
|
||||
buf_dump("CALC", buf, length);
|
||||
*/
|
||||
|
||||
(void) lsasum_check(h, body);
|
||||
|
||||
log(L_WARN "Checksum result %4x", h->checksum);
|
||||
// log(L_WARN "Checksum result %4x", h->checksum);
|
||||
|
||||
ntohlsah(h, h);
|
||||
ntohlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
|
||||
|
|
|
@ -28,8 +28,8 @@ static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
|
|||
sizeof(struct ospf_lsreq_header);
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
log(L_TRACE "%s: LSR Id: %R, Rt: %R, Type: %u", p->name,
|
||||
htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt), pkt->lsh[i].type);
|
||||
log(L_TRACE "%s: LSR Id: %R, Rt: %R, Type: 0x%x", p->name,
|
||||
htonl(pkt->lsh[i].id), htonl(pkt->lsh[i].rt), htonl(pkt->lsh[i].type));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -44,8 +44,8 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
|||
int i, j;
|
||||
struct proto *p = &n->ifa->oa->po->proto;
|
||||
|
||||
pk = (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf;
|
||||
op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
|
||||
pk = (struct ospf_lsreq_packet *) n->ifa->sk->tbuf;
|
||||
op = (struct ospf_packet *) n->ifa->sk->tbuf;
|
||||
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSREQ_P);
|
||||
|
||||
|
@ -82,9 +82,9 @@ ospf_lsreq_send(struct ospf_neighbor *n)
|
|||
i) * sizeof(struct ospf_lsreq_header);
|
||||
op->length = htons(length);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsreq, (struct ospf_lsreq_packet *) n->ifa->ip_sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsreq, (struct ospf_lsreq_packet *) n->ifa->sk->tbuf,
|
||||
"LSREQ packet sent to %I via %s", n->ip, n->ifa->iface->name);
|
||||
ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
|
||||
ospf_send_to(n->ifa, n->ip);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -21,7 +21,7 @@ void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
|
|||
struct ospf_lsa_header lsa;
|
||||
ntohlsah(lsa_n, &lsa);
|
||||
|
||||
log(L_TRACE "%s: LSA Id: %R, Rt: %R, Type: %u, Age: %u, Seqno: 0x%08x, Sum: %u",
|
||||
log(L_TRACE "%s: LSA Id: %R, Rt: %R, Type: 0x%04x, Age: %u, Seqno: 0x%08x, Sum: 0x%04x",
|
||||
p->name, lsa.id, lsa.rt, lsa.type, lsa.age, lsa.sn, lsa.checksum);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
|
|||
return 0;
|
||||
if (ifa->oa->stub)
|
||||
return 0;
|
||||
return 1
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return ifa->oa->areaid == domain;
|
||||
|
@ -262,19 +262,13 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
}
|
||||
|
||||
{
|
||||
sock *sk;
|
||||
u16 len, age;
|
||||
struct ospf_lsupd_packet *pk;
|
||||
struct ospf_packet *op;
|
||||
struct ospf_lsa_header *lh;
|
||||
|
||||
if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
|
||||
sk = ifa->ip_sk;
|
||||
else
|
||||
sk = ifa->hello_sk;
|
||||
|
||||
pk = (struct ospf_lsupd_packet *) sk->tbuf;
|
||||
op = (struct ospf_packet *) sk->tbuf;
|
||||
pk = (struct ospf_lsupd_packet *) ifa->sk->tbuf;
|
||||
op = (struct ospf_packet *) ifa->sk->tbuf;
|
||||
|
||||
ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
|
||||
pk->lsano = htonl(1);
|
||||
|
@ -308,28 +302,28 @@ ospf_lsupd_flood(struct proto_ospf *po,
|
|||
|
||||
op->length = htons(len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) ifa->sk->tbuf,
|
||||
"LSUPD packet flooded via %s", ifa->iface->name);
|
||||
|
||||
switch (ifa->type)
|
||||
{
|
||||
case OSPF_IT_NBMA:
|
||||
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
|
||||
ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
|
||||
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
|
||||
else
|
||||
ospf_send_to_bdr(sk, ifa);
|
||||
ospf_send_to_bdr(ifa);
|
||||
break;
|
||||
|
||||
case OSPF_IT_VLINK:
|
||||
ospf_send_to(sk, ifa->vip, ifa);
|
||||
ospf_send_to(ifa, ifa->vip);
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
|
||||
(ifa->type == OSPF_IT_PTP))
|
||||
ospf_send_to(sk, AllSPFRouters, ifa);
|
||||
ospf_send_to(ifa, AllSPFRouters);
|
||||
else
|
||||
ospf_send_to(sk, AllDRouters, ifa);
|
||||
ospf_send_to(ifa, AllDRouters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -353,8 +347,8 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
if (EMPTY_LIST(*l))
|
||||
return;
|
||||
|
||||
pk = (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf;
|
||||
op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
|
||||
pk = (struct ospf_lsupd_packet *) n->ifa->sk->tbuf;
|
||||
op = (struct ospf_packet *) n->ifa->sk->tbuf;
|
||||
|
||||
DBG("LSupd: 1st packet\n");
|
||||
|
||||
|
@ -378,9 +372,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
pk->lsano = htonl(lsano);
|
||||
op->length = htons(len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
|
||||
"LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
|
||||
ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
|
||||
ospf_send_to(n->ifa, n->ip);
|
||||
|
||||
DBG("LSupd: next packet\n");
|
||||
ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
|
||||
|
@ -401,9 +395,9 @@ ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
|
|||
pk->lsano = htonl(lsano);
|
||||
op->length = htons(len);
|
||||
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
|
||||
OSPF_PACKET(ospf_dump_lsupd, (struct ospf_lsupd_packet *) n->ifa->sk->tbuf,
|
||||
"LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
|
||||
ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
|
||||
ospf_send_to(n->ifa, n->ip);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -478,8 +478,8 @@ bdr_election(struct ospf_iface *ifa)
|
|||
|| ((ifa->bdrid != myid) && (nbdr == &me)))
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
me.dr = ndr ? ipa_to_u32(ndr->ip) : IPA_NONE;
|
||||
me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : IPA_NONE;
|
||||
me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
|
||||
me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
|
||||
#else /* OSPFv3 */
|
||||
me.dr = ndr ? ndr->rid : 0;
|
||||
me.bdr = nbdr ? nbdr->rid : 0;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* normally allocate 2*mtu - (I found one cisco
|
||||
* sending packets mtu+16)
|
||||
*/
|
||||
#define LOCAL_DEBUG 1
|
||||
#ifdef LOCAL_DEBUG
|
||||
#define OSPF_FORCE_DEBUG 1
|
||||
#else
|
||||
|
@ -161,9 +162,7 @@ struct ospf_iface
|
|||
struct iface *iface; /* Nest's iface */
|
||||
struct ospf_area *oa;
|
||||
struct object_lock *lock;
|
||||
sock *hello_sk; /* Hello socket */
|
||||
sock *dr_sk; /* For states DR or BACKUP */
|
||||
sock *ip_sk; /* IP socket (for DD ...) */
|
||||
sock *sk; /* IP socket (for DD ...) */
|
||||
list neigh_list; /* List of neigbours */
|
||||
u32 cost; /* Cost of iface */
|
||||
u32 waitint; /* number of sec before changing state from wait */
|
||||
|
@ -241,6 +240,7 @@ struct ospf_iface
|
|||
list nbma_list;
|
||||
u8 priority; /* A router priority for DR election */
|
||||
u8 ioprob;
|
||||
u8 dr_up; /* Socket is a member of DRouters group */
|
||||
u32 rxbuf;
|
||||
};
|
||||
|
||||
|
|
|
@ -437,26 +437,27 @@ ospf_err_hook(sock * sk, int err)
|
|||
}
|
||||
|
||||
void
|
||||
ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state)
|
||||
ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
|
||||
{
|
||||
struct ospf_neighbor *n;
|
||||
|
||||
WALK_LIST(n, ifa->neigh_list) if (n->state >= state)
|
||||
ospf_send_to(sk, n->ip, ifa);
|
||||
ospf_send_to(ifa, n->ip);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa)
|
||||
ospf_send_to_bdr(struct ospf_iface *ifa)
|
||||
{
|
||||
if (!ipa_equal(ifa->drip, IPA_NONE))
|
||||
ospf_send_to(sk, ifa->drip, ifa);
|
||||
ospf_send_to(ifa, ifa->drip);
|
||||
if (!ipa_equal(ifa->bdrip, IPA_NONE))
|
||||
ospf_send_to(sk, ifa->bdrip, ifa);
|
||||
ospf_send_to(ifa, ifa->bdrip);
|
||||
}
|
||||
|
||||
void
|
||||
ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa)
|
||||
ospf_send_to(struct ospf_iface *ifa, ip_addr ip)
|
||||
{
|
||||
sock *sk = ifa->sk;
|
||||
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
|
||||
int len = ntohs(pkt->length);
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
|
|||
int ospf_rx_hook(sock * sk, int size);
|
||||
void ospf_tx_hook(sock * sk);
|
||||
void ospf_err_hook(sock * sk, int err);
|
||||
void ospf_send_to_agt(sock * sk, struct ospf_iface *ifa, u8 state);
|
||||
void ospf_send_to_bdr(sock * sk, struct ospf_iface *ifa);
|
||||
void ospf_send_to(sock *sk, ip_addr ip, struct ospf_iface *ifa);
|
||||
void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
|
||||
void ospf_send_to_bdr(struct ospf_iface *ifa);
|
||||
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
|
||||
|
||||
|
||||
#endif /* _BIRD_OSPF_PACKET_H_ */
|
||||
|
|
|
@ -26,6 +26,8 @@ static void rt_sync(struct proto_ospf *po);
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef OSPFv3
|
||||
|
||||
static inline u32 *
|
||||
get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
|
||||
{
|
||||
|
@ -56,6 +58,9 @@ get_ipv6_addr(u32 *buf, ip_addr *addr)
|
|||
return buf + 4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
fill_ri(orta * orta)
|
||||
{
|
||||
|
@ -839,8 +844,8 @@ ospf_ext_spf(struct proto_ospf *po)
|
|||
if (en->lsa.rt == p->cf->global->router_id)
|
||||
continue;
|
||||
|
||||
DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u, Mask %I\n",
|
||||
p->name, en->lsa.id, en->lsa.rt, en->lsa.type, le->netmask);
|
||||
DBG("%s: Working on LSA. ID: %R, RT: %R, Type: %u\n",
|
||||
p->name, en->lsa.id, en->lsa.rt, en->lsa.type);
|
||||
|
||||
le = en->lsa_body;
|
||||
|
||||
|
@ -1056,7 +1061,7 @@ static inline int
|
|||
match_dr(struct ospf_iface *ifa, struct top_hash_entry *en)
|
||||
{
|
||||
#ifdef OSPFv2
|
||||
return (ifa->drid == en->lsa.rt) && (ifa->drip == ipa_from_u32(en->lsa.id));
|
||||
return (ifa->drid == en->lsa.rt) && (ipa_to_u32(ifa->drip) == en->lsa.id);
|
||||
#else /* OSPFv3 */
|
||||
return (ifa->drid == en->lsa.rt) && (ifa->dr_iface_id == en->lsa.id);
|
||||
#endif
|
||||
|
|
|
@ -174,7 +174,7 @@ originate_rt_lsa_body(struct ospf_area *oa, u16 *length)
|
|||
ASSERT(po->lsab_used == 0);
|
||||
rt = lsab_allocz(po, sizeof(struct ospf_lsa_rt));
|
||||
|
||||
rt->options = 0
|
||||
rt->options = 0;
|
||||
|
||||
if (po->areano > 1)
|
||||
rt->options |= OPT_RT_B;
|
||||
|
@ -445,7 +445,9 @@ update_rt_lsa(struct ospf_area *oa)
|
|||
*/
|
||||
|
||||
originate_rt_lsa(oa);
|
||||
#ifdef OSPFv3
|
||||
originate_prefix_rt_lsa(oa);
|
||||
#endif
|
||||
|
||||
schedule_rtcalc(po);
|
||||
oa->origrt = 0;
|
||||
|
@ -577,12 +579,16 @@ update_net_lsa(struct ospf_iface *ifa)
|
|||
if ((ifa->state != OSPF_IS_DR) || (ifa->fadj == 0))
|
||||
{
|
||||
flush_net_lsa(ifa);
|
||||
#ifdef OSPFv3
|
||||
flush_prefix_net_lsa(ifa);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
originate_net_lsa(ifa);
|
||||
#ifdef OSPFv3
|
||||
originate_prefix_net_lsa(ifa);
|
||||
#endif
|
||||
}
|
||||
|
||||
schedule_rtcalc(po);
|
||||
|
@ -1353,6 +1359,16 @@ ospf_top_rehash(struct top_graph *f, int step)
|
|||
ospf_top_ht_free(oldt);
|
||||
}
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
u32
|
||||
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
|
||||
{
|
||||
return (type == LSA_T_EXT) ? 0 : ifa->oa->areaid;
|
||||
}
|
||||
|
||||
#else /* OSPFv3 */
|
||||
|
||||
u32
|
||||
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
|
||||
{
|
||||
|
@ -1370,6 +1386,8 @@ ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
struct top_hash_entry *
|
||||
ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
|
||||
{
|
||||
|
|
|
@ -684,7 +684,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||
DBG( "Doing multicasts!\n" );
|
||||
|
||||
rif->sock = sk_new( p->pool );
|
||||
rif->sock->type = rif->multicast?SK_UDP_MC:SK_UDP;
|
||||
rif->sock->type = SK_UDP;
|
||||
rif->sock->sport = P_CF->port;
|
||||
rif->sock->rx_hook = rip_rx;
|
||||
rif->sock->data = rif;
|
||||
|
@ -721,7 +721,30 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||
if (!ipa_nonzero(rif->sock->daddr)) {
|
||||
if (rif->iface)
|
||||
log( L_WARN "%s: interface %s is too strange for me", p->name, rif->iface->name );
|
||||
} else if (sk_open(rif->sock)<0) {
|
||||
} else {
|
||||
|
||||
if (sk_open(rif->sock)<0)
|
||||
goto err;
|
||||
|
||||
if (rif->multicast)
|
||||
{
|
||||
if (sk_setup_multicast(rif->sock) < 0)
|
||||
goto err;
|
||||
if (sk_join_group(rif->sock, rif->sock->daddr) < 0)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sk_set_broadcast(rif->sock, 1) < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE(D_EVENTS, "Listening on %s, port %d, mode %s (%I)", rif->iface ? rif->iface->name : "(dummy)", P_CF->port, rif->multicast ? "multicast" : "broadcast", rif->sock->daddr );
|
||||
|
||||
return rif;
|
||||
|
||||
err:
|
||||
log( L_ERR "%s: could not create socket for %s", p->name, rif->iface ? rif->iface->name : "(dummy)" );
|
||||
if (rif->iface) {
|
||||
rfree(rif->sock);
|
||||
|
@ -731,11 +754,6 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
|
|||
/* On dummy, we just return non-working socket, so that user gets error every time anyone requests table */
|
||||
}
|
||||
|
||||
TRACE(D_EVENTS, "Listening on %s, port %d, mode %s (%I)", rif->iface ? rif->iface->name : "(dummy)", P_CF->port, rif->multicast ? "multicast" : "broadcast", rif->sock->daddr );
|
||||
|
||||
return rif;
|
||||
}
|
||||
|
||||
static void
|
||||
rip_real_if_add(struct object_lock *lock)
|
||||
{
|
||||
|
|
|
@ -27,48 +27,55 @@ set_inaddr(struct in_addr * ia, ip_addr a)
|
|||
}
|
||||
|
||||
static inline char *
|
||||
sysio_mcast_setup(sock * s)
|
||||
sysio_setup_multicast(sock *s)
|
||||
{
|
||||
struct in_addr m;
|
||||
u8 zero = 0;
|
||||
u8 one = 1;
|
||||
|
||||
if (ipa_nonzero(s->daddr)) {
|
||||
u8 ttl = s->ttl;
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||
return "IP_MULTICAST_LOOP";
|
||||
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &one, sizeof(one)) < 0)
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
|
||||
return "IP_MULTICAST_TTL";
|
||||
}
|
||||
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
set_inaddr(&m, s->iface->addr->ip);
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static inline char *
|
||||
sysio_mcast_join(sock * s)
|
||||
sysio_join_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct in_addr m;
|
||||
struct ip_mreq mreq;
|
||||
char *err;
|
||||
|
||||
set_inaddr(&m, s->iface->addr->ip );
|
||||
|
||||
bzero(&mreq, sizeof(mreq));
|
||||
set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
|
||||
set_inaddr(&mreq.imr_multiaddr, s->daddr);
|
||||
set_inaddr(&mreq.imr_multiaddr, maddr);
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
if (ipa_nonzero(s->daddr) &&
|
||||
setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return "IP_ADD_MEMBERSHIP";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
if (ipa_nonzero(s->daddr) && setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
static inline char *
|
||||
sysio_leave_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ip_mreq mreq;
|
||||
|
||||
if (err = sysio_mcast_setup(s))
|
||||
return err;
|
||||
bzero(&mreq, sizeof(mreq));
|
||||
set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
|
||||
set_inaddr(&mreq.imr_multiaddr, maddr);
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return "IP_DROP_MEMBERSHIP";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -38,27 +38,33 @@ set_inaddr(struct in_addr *ia, ip_addr a)
|
|||
* ways. Horrible.
|
||||
*/
|
||||
|
||||
static inline char *sysio_mcast_setup(sock *s)
|
||||
{
|
||||
int zero = 0;
|
||||
|
||||
if (ipa_nonzero(s->daddr))
|
||||
#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
|
||||
/*
|
||||
* Older kernels support only struct mreq which matches interfaces by their
|
||||
* addresses and thus fails on unnumbered devices. On newer 2.0 kernels
|
||||
* we can use SO_BINDTODEVICE to circumvent this problem.
|
||||
*/
|
||||
|
||||
#define MREQ_IFA struct in_addr
|
||||
#define MREQ_GRP struct ip_mreq
|
||||
static inline void fill_mreq_ifa(struct in_addr *m, struct iface *ifa, UNUSED ip_addr maddr)
|
||||
{
|
||||
if (
|
||||
#ifdef IP_DEFAULT_MULTICAST_TTL
|
||||
s->ttl != IP_DEFAULT_MULTICAST_TTL &&
|
||||
#endif
|
||||
setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
return "IP_MULTICAST_TTL";
|
||||
if (
|
||||
#ifdef IP_DEFAULT_MULTICAST_LOOP
|
||||
IP_DEFAULT_MULTICAST_LOOP &&
|
||||
#endif
|
||||
setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||
return "IP_MULTICAST_LOOP";
|
||||
set_inaddr(m, ifa->addr->ip);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
static inline void fill_mreq_grp(struct ip_mreq *m, struct iface *ifa, ip_addr maddr)
|
||||
{
|
||||
bzero(m, sizeof(*m));
|
||||
#ifdef CONFIG_LINUX_MC_MREQ_BIND
|
||||
m->imr_interface.s_addr = INADDR_ANY;
|
||||
#else
|
||||
set_inaddr(&m->imr_interface, ifa->addr->ip);
|
||||
#endif
|
||||
set_inaddr(&m->imr_multiaddr, maddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_LINUX_MC_MREQN
|
||||
/*
|
||||
|
@ -76,70 +82,78 @@ struct ip_mreqn
|
|||
};
|
||||
#endif
|
||||
|
||||
static inline char *sysio_mcast_join(sock *s)
|
||||
{
|
||||
struct ip_mreqn mreq;
|
||||
char *err;
|
||||
struct ifreq ifr;
|
||||
#define MREQ_IFA struct ip_mreqn
|
||||
#define MREQ_GRP struct ip_mreqn
|
||||
#define fill_mreq_ifa fill_mreq
|
||||
#define fill_mreq_grp fill_mreq
|
||||
|
||||
if (err = sysio_mcast_setup(s))
|
||||
return err;
|
||||
strcpy(ifr.ifr_name, s->iface->name);
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
|
||||
return "SO_BINDTODEVICE";
|
||||
mreq.imr_ifindex = s->iface->index;
|
||||
set_inaddr(&mreq.imr_address, s->iface->addr->ip);
|
||||
set_inaddr(&mreq.imr_multiaddr, s->daddr);
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
if (ipa_nonzero(s->daddr) && setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
if (ipa_nonzero(s->saddr) && setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return "IP_ADD_MEMBERSHIP";
|
||||
return NULL;
|
||||
static inline fill_mreq(struct ip_mreqn *m, struct iface *ifa, ip_addr maddr)
|
||||
{
|
||||
bzero(m, sizeof(*m));
|
||||
m->imr_ifindex = ifa->index;
|
||||
set_inaddr(&m->imr_address, ifa->addr->ip);
|
||||
set_inaddr(&m->imr_multiaddr, maddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LINUX_MC_MREQ) || defined(CONFIG_LINUX_MC_MREQ_BIND)
|
||||
/*
|
||||
* Older kernels support only struct mreq which matches interfaces by their
|
||||
* addresses and thus fails on unnumbered devices. On newer 2.0 kernels
|
||||
* we can use SO_BINDTODEVICE to circumvent this problem.
|
||||
*/
|
||||
|
||||
static inline char *sysio_mcast_join(sock *s)
|
||||
static inline char *
|
||||
sysio_setup_multicast(sock *s)
|
||||
{
|
||||
struct in_addr mreq;
|
||||
struct ip_mreq mreq_add;
|
||||
char *err;
|
||||
MREQ_IFA m;
|
||||
int zero = 0;
|
||||
|
||||
if (err = sysio_mcast_setup(s))
|
||||
return err;
|
||||
set_inaddr(&mreq, s->iface->addr->ip);
|
||||
#ifdef CONFIG_LINUX_MC_MREQ_BIND
|
||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||
return "IP_MULTICAST_LOOP";
|
||||
|
||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
return "IP_MULTICAST_TTL";
|
||||
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
fill_mreq_ifa(&m, s->iface, IPA_NONE);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
|
||||
#if defined(CONFIG_LINUX_MC_MREQ_BIND) || defined(CONFIG_LINUX_MC_MREQN)
|
||||
{
|
||||
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";
|
||||
mreq_add.imr_interface.s_addr = INADDR_ANY;
|
||||
}
|
||||
#else
|
||||
mreq_add.imr_interface = mreq;
|
||||
#endif
|
||||
set_inaddr(&mreq_add.imr_multiaddr, s->daddr);
|
||||
/* This defines where should we send _outgoing_ multicasts */
|
||||
if (ipa_nonzero(s->daddr) && setsockopt(s->fd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0)
|
||||
return "IP_MULTICAST_IF";
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
if (ipa_nonzero(s->saddr) && setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq_add, sizeof(mreq_add)) < 0)
|
||||
return "IP_ADD_MEMBERSHIP";
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
sysio_join_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
MREQ_GRP m;
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
fill_mreq_grp(&m, s->iface, maddr);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||
return "IP_ADD_MEMBERSHIP";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline char *
|
||||
sysio_leave_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
MREQ_GRP m;
|
||||
|
||||
/* And this one sets interface for _receiving_ multicasts from */
|
||||
fill_mreq_grp(&m, s->iface, maddr);
|
||||
if (setsockopt(s->fd, SOL_IP, IP_DROP_MEMBERSHIP, &m, sizeof(m)) < 0)
|
||||
return "IP_DROP_MEMBERSHIP";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include <linux/socket.h>
|
||||
#include <linux/tcp.h>
|
||||
|
||||
|
|
190
sysdep/unix/io.c
190
sysdep/unix/io.c
|
@ -690,8 +690,7 @@ sk_set_ttl_int(sock *s)
|
|||
{
|
||||
int one = 1;
|
||||
#ifdef IPV6
|
||||
if (s->type != SK_UDP_MC && s->type != SK_IP_MC &&
|
||||
setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
return "IPV6_UNICAST_HOPS";
|
||||
#else
|
||||
if (setsockopt(s->fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
|
@ -788,6 +787,134 @@ sk_set_md5_auth(sock *s, ip_addr a, char *passwd)
|
|||
return sk_set_md5_auth_int(s, &sa, passwd);
|
||||
}
|
||||
|
||||
int
|
||||
sk_set_broadcast(sock *s, int enable)
|
||||
{
|
||||
if (setsockopt(s->fd, SOL_SOCKET, SO_BROADCAST, &enable, sizeof(enable)) < 0)
|
||||
log(L_ERR "sk_set_broadcast: SO_BROADCAST: %m");
|
||||
}
|
||||
|
||||
|
||||
#ifdef IPV6
|
||||
|
||||
int
|
||||
sk_setup_multicast(sock *s)
|
||||
{
|
||||
char *err;
|
||||
int zero = 0;
|
||||
int index;
|
||||
|
||||
ASSERT(s->iface && s->iface->addr);
|
||||
|
||||
index = s->iface->index;
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
ERR("IPV6_MULTICAST_HOPS");
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||
ERR("IPV6_MULTICAST_LOOP");
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_MULTICAST_IF, &index, sizeof(index)) < 0)
|
||||
ERR("IPV6_MULTICAST_IF");
|
||||
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
log(L_ERR "sk_setup_multicast: %s: %m", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
sk_join_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ipv6_mreq mreq;
|
||||
|
||||
set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
|
||||
|
||||
#ifdef CONFIG_IPV6_GLIBC_20
|
||||
mreq.ipv6mr_ifindex = s->iface->index;
|
||||
#else
|
||||
mreq.ipv6mr_interface = s->iface->index;
|
||||
#endif
|
||||
|
||||
/* RFC 2553 says IPV6_JOIN_GROUP */
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
{
|
||||
log(L_ERR "sk_join_group: IPV6_ADD_MEMBERSHIP: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sk_leave_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
struct ipv6_mreq mreq;
|
||||
|
||||
set_inaddr(&mreq.ipv6mr_multiaddr, maddr);
|
||||
|
||||
#ifdef CONFIG_IPV6_GLIBC_20
|
||||
mreq.ipv6mr_ifindex = s->iface->index;
|
||||
#else
|
||||
mreq.ipv6mr_interface = s->iface->index;
|
||||
#endif
|
||||
|
||||
/* RFC 2553 says IPV6_LEAVE_GROUP */
|
||||
if (setsockopt(s->fd, SOL_IPV6, IPV6_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
{
|
||||
log(L_ERR "sk_leave_group: IPV6_DROP_MEMBERSHIP: %m");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* IPV4 */
|
||||
|
||||
int
|
||||
sk_setup_multicast(sock *s)
|
||||
{
|
||||
char *err;
|
||||
|
||||
ASSERT(s->iface && s->iface->addr);
|
||||
|
||||
if (err = sysio_setup_multicast(s))
|
||||
{
|
||||
log(L_ERR "sk_setup_multicast: %s: %m", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sk_join_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
char *err;
|
||||
|
||||
if (err = sysio_join_group(s, maddr))
|
||||
{
|
||||
log(L_ERR "sk_join_group: %s: %m", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sk_leave_group(sock *s, ip_addr maddr)
|
||||
{
|
||||
char *err;
|
||||
|
||||
if (err = sysio_leave_group(s, maddr))
|
||||
{
|
||||
log(L_ERR "sk_leave_group: %s: %m", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static void
|
||||
sk_tcp_connected(sock *s)
|
||||
|
@ -861,11 +988,9 @@ sk_open(sock *s)
|
|||
fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
|
||||
break;
|
||||
case SK_UDP:
|
||||
case SK_UDP_MC:
|
||||
fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
|
||||
break;
|
||||
case SK_IP:
|
||||
case SK_IP_MC:
|
||||
fd = socket(BIRD_PF, SOCK_RAW, s->dport);
|
||||
break;
|
||||
case SK_MAGIC:
|
||||
|
@ -881,59 +1006,11 @@ sk_open(sock *s)
|
|||
if (err = sk_setup(s))
|
||||
goto bad;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case SK_UDP:
|
||||
case SK_IP:
|
||||
#ifndef IPV6
|
||||
if (s->iface) /* It's a broadcast socket */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
|
||||
ERR("SO_BROADCAST");
|
||||
#endif
|
||||
break;
|
||||
case SK_UDP_MC:
|
||||
case SK_IP_MC:
|
||||
{
|
||||
#ifdef IPV6
|
||||
/* Fortunately, IPv6 socket interface is recent enough and therefore standardized */
|
||||
ASSERT(s->iface && s->iface->addr);
|
||||
if (ipa_nonzero(s->daddr))
|
||||
{
|
||||
int t = s->iface->index;
|
||||
int zero = 0;
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
|
||||
ERR("IPV6_MULTICAST_HOPS");
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
|
||||
ERR("IPV6_MULTICAST_LOOP");
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_IF, &t, sizeof(t)) < 0)
|
||||
ERR("IPV6_MULTICAST_IF");
|
||||
}
|
||||
if (has_src)
|
||||
{
|
||||
struct ipv6_mreq mreq;
|
||||
set_inaddr(&mreq.ipv6mr_multiaddr, s->daddr);
|
||||
#ifdef CONFIG_IPV6_GLIBC_20
|
||||
mreq.ipv6mr_ifindex = s->iface->index;
|
||||
#else
|
||||
mreq.ipv6mr_interface = s->iface->index;
|
||||
#endif /* CONFIG_IPV6_GLIBC_20 */
|
||||
if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
ERR("IPV6_ADD_MEMBERSHIP");
|
||||
}
|
||||
#else /* IPv4 */
|
||||
/* With IPv4 there are zillions of different socket interface variants. Ugh. */
|
||||
ASSERT(s->iface && s->iface->addr);
|
||||
if (err = sysio_mcast_join(s))
|
||||
goto bad;
|
||||
#endif /* IPV6 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_src)
|
||||
{
|
||||
int port;
|
||||
|
||||
if (type == SK_IP || type == SK_IP_MC)
|
||||
if (type == SK_IP)
|
||||
port = 0;
|
||||
else
|
||||
{
|
||||
|
@ -943,12 +1020,7 @@ sk_open(sock *s)
|
|||
}
|
||||
fill_in_sockaddr(&sa, s->saddr, port);
|
||||
fill_in_sockifa(&sa, s->iface);
|
||||
#ifdef CONFIG_SKIP_MC_BIND
|
||||
if ((type != SK_UDP_MC) && (type != SK_IP_MC) &&
|
||||
bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
|
||||
#else
|
||||
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
|
||||
#endif
|
||||
ERR("bind");
|
||||
}
|
||||
fill_in_sockaddr(&sa, s->daddr, s->dport);
|
||||
|
@ -1069,9 +1141,7 @@ sk_maybe_write(sock *s)
|
|||
s->ttx = s->tpos = s->tbuf;
|
||||
return 1;
|
||||
case SK_UDP:
|
||||
case SK_UDP_MC:
|
||||
case SK_IP:
|
||||
case SK_IP_MC:
|
||||
{
|
||||
sockaddr sa;
|
||||
|
||||
|
|
Loading…
Reference in a new issue