Commit 21fff6b7 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Fix error handling in interface_up.

Interface_up can be called before an IPv6 address has been assigned to
the interface.  In this case, we need to down the interface again, wait
for a few seconds, then attempt to up it again.
parent 6d7356dc
...@@ -198,14 +198,14 @@ interface_up(struct interface *ifp, int up) ...@@ -198,14 +198,14 @@ interface_up(struct interface *ifp, int up)
if(ifp->ifindex <= 0) { if(ifp->ifindex <= 0) {
fprintf(stderr, fprintf(stderr,
"Upping unknown interface %s.\n", ifp->name); "Upping unknown interface %s.\n", ifp->name);
return interface_up(ifp, 0); goto fail;
} }
rc = kernel_setup_interface(1, ifp->name, ifp->ifindex); rc = kernel_setup_interface(1, ifp->name, ifp->ifindex);
if(rc < 0) { if(rc < 0) {
fprintf(stderr, "kernel_setup_interface(%s, %d) failed.\n", fprintf(stderr, "kernel_setup_interface(%s, %d) failed.\n",
ifp->name, ifp->ifindex); ifp->name, ifp->ifindex);
return interface_up(ifp, 0); goto fail;
} }
mtu = kernel_interface_mtu(ifp->name, ifp->ifindex); mtu = kernel_interface_mtu(ifp->name, ifp->ifindex);
...@@ -234,7 +234,7 @@ interface_up(struct interface *ifp, int up) ...@@ -234,7 +234,7 @@ interface_up(struct interface *ifp, int up)
if(ifp->sendbuf == NULL) { if(ifp->sendbuf == NULL) {
fprintf(stderr, "Couldn't allocate sendbuf.\n"); fprintf(stderr, "Couldn't allocate sendbuf.\n");
ifp->bufsize = 0; ifp->bufsize = 0;
return interface_up(ifp, 0); goto fail;
} }
rc = resize_receive_buffer(mtu); rc = resize_receive_buffer(mtu);
...@@ -311,24 +311,21 @@ interface_up(struct interface *ifp, int up) ...@@ -311,24 +311,21 @@ interface_up(struct interface *ifp, int up)
memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16); memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
mreq.ipv6mr_interface = ifp->ifindex; mreq.ipv6mr_interface = ifp->ifindex;
rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char*)&mreq, sizeof(mreq));
if(rc < 0) {
perror("setsockopt(IPV6_JOIN_GROUP)");
/* This is probably due to a missing link-local address,
so down this interface, and wait until the main loop
tries to up it again. */
return interface_up(ifp, 0);
}
if(ifp->ll) if(ifp->ll)
free(ifp->ll); free(ifp->ll);
ifp->numll = 0; ifp->numll = 0;
ifp->ll = NULL; ifp->ll = NULL;
rc = kernel_addresses(ifp->name, ifp->ifindex, 1, ll, 32); rc = kernel_addresses(ifp->name, ifp->ifindex, 1, ll, 32);
if(rc < 0) { if(rc < 0) {
perror("kernel_ll_addresses"); perror("kernel_addresses(link local)");
} else if(rc > 0) { goto fail;
} else if(rc == 0) {
fprintf(stderr, "Interface %s has no link-local address.\n",
ifp->name);
/* Most probably DAD hasn't finished yet. Reschedule us
real soon. */
goto fail_retry;
} else {
ifp->ll = malloc(16 * rc); ifp->ll = malloc(16 * rc);
if(ifp->ll == NULL) { if(ifp->ll == NULL) {
perror("malloc(ll)"); perror("malloc(ll)");
...@@ -339,6 +336,14 @@ interface_up(struct interface *ifp, int up) ...@@ -339,6 +336,14 @@ interface_up(struct interface *ifp, int up)
ifp->numll = rc; ifp->numll = rc;
} }
} }
rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char*)&mreq, sizeof(mreq));
if(rc < 0) {
perror("setsockopt(IPV6_JOIN_GROUP)");
goto fail;
}
check_interface_channel(ifp); check_interface_channel(ifp);
update_interface_metric(ifp); update_interface_metric(ifp);
rc = check_interface_ipv4(ifp); rc = check_interface_ipv4(ifp);
...@@ -384,6 +389,13 @@ interface_up(struct interface *ifp, int up) ...@@ -384,6 +389,13 @@ interface_up(struct interface *ifp, int up)
} }
return 1; return 1;
fail_retry:
schedule_interfaces_check(2000, 0);
fail:
assert(up);
interface_up(ifp, 0);
return -1;
} }
int int
...@@ -428,6 +440,8 @@ check_interfaces(void) ...@@ -428,6 +440,8 @@ check_interfaces(void)
} }
if(if_up(ifp)) { if(if_up(ifp)) {
/* Bother, said Pooh. We should probably check for a change
in link-local and IPv4 addresses at this point. */
check_interface_channel(ifp); check_interface_channel(ifp);
rc = check_interface_ipv4(ifp); rc = check_interface_ipv4(ifp);
if(rc > 0) { if(rc > 0) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment