diff --git a/lib/socket.h b/lib/socket.h index cbef4fdc..353e9573 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -10,6 +10,7 @@ #define _BIRD_SOCKET_H_ #include +#include #include "lib/resource.h" diff --git a/nest/rt-table.c b/nest/rt-table.c index c93950c4..1cb25ab3 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1231,9 +1231,9 @@ rt_addrsize(int addr_type) switch (addr_type) { #ifdef MPLS_VPN - case RT_VPNV4: + case RT_VPN4: return sizeof(vpn4_addr); - case RT_VPNV6: + case RT_VPN6: return sizeof(vpn6_addr); #endif case RT_IPV4: diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 1b09984f..6aabef2b 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -65,6 +65,20 @@ krt_capable(rte *e) ); } +static int +rt_to_af(int rt) +{ + if (rt == RT_IPV4) + return AF_INET; + else if (rt == RT_IPV6) + return AF_INET6; + + /* RT_IP (0) maps to 0 (every AF) */ + + return 0; +} + + #define ROUNDUP(a) \ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) @@ -87,10 +101,10 @@ krt_sock_send(int cmd, rte *e) rta *a = e->attrs; static int msg_seq; struct iface *j, *i = a->iface; - int l; + int af = 0, l; struct ks_msg msg; char *body = (char *)msg.buf; - sockaddr gate, mask, dst; + struct sockaddr_in6 gate, mask, dst; ip_addr gw; DBG("krt-sock: send %F via %I\n", &net->n, a->gw); @@ -131,29 +145,43 @@ krt_sock_send(int cmd, rte *e) gw = a->gw; -#ifdef IPV6 - /* Embed interface ID to link-local address */ - if (ipa_has_link_scope(gw)) - _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); -#endif + switch (net->n.addr_type) + { + case RT_IPV4: + af = AF_INET; + dst.sin6_family = mask.sin6_family = gate.sin6_family = af; + sockaddr_fill((struct sockaddr *)&dst, *FPREFIX_IP(&net->n), NULL, 0); + sockaddr_fill((struct sockaddr *)&mask, ipa_mkmask(net->n.pxlen), NULL, 0); + sockaddr_fill((struct sockaddr *)&gate, gw, NULL, 0); - fill_in_sockaddr(&dst, net->n.prefix, NULL, 0); - fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0); - fill_in_sockaddr(&gate, gw, NULL, 0); - /* XXXX from patch - if (net->n.addr_type == RT_IP) - { - fill_in_sockaddr(&dst, *FPREFIX_IP(&net->n), 0); - fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0); + if (net->n.pxlen == MAX_PREFIX_LENGTH) + msg.rtm.rtm_flags |= RTF_HOST; + else + msg.rtm.rtm_addrs |= RTA_NETMASK; + break; - if (net->n.pxlen == MAX_PREFIX_LENGTH) - msg.rtm.rtm_flags |= RTF_HOST; - else - msg.rtm.rtm_addrs |= RTA_NETMASK; - } - */ - - + case RT_IPV6: + af = AF_INET6; + + /* Embed interface ID to link-local address */ + if (ipa_is_link_local(gw)) + _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff); + + dst.sin6_family = mask.sin6_family = gate.sin6_family = af; + sockaddr_fill((struct sockaddr *)&dst, *FPREFIX_IP(&net->n), NULL, 0); + sockaddr_fill((struct sockaddr *)&mask, ipa_mkmask(net->n.pxlen), NULL, 0); + sockaddr_fill((struct sockaddr *)&gate, gw, NULL, 0); + + if (net->n.pxlen == MAX_PREFIX_LENGTH) + msg.rtm.rtm_flags |= RTF_HOST; + else + msg.rtm.rtm_addrs |= RTA_NETMASK; + break; + + default: + log(L_ERR "Unsupported address family: %F", FPREFIX_IP(&net->n)); + return -1; + } switch (a->dest) { @@ -175,12 +203,13 @@ krt_sock_send(int cmd, rte *e) msg.rtm.rtm_flags |= RTF_CLONING; #endif + // XXXX: find proper IPv4 / IPv6 address ? if(!i->addr) { - log(L_ERR "KRT: interface %s has no IP addess", i->name); + log(L_ERR "KRT: interface %s has no IP address", i->name); return -1; } - fill_in_sockaddr(&gate, i->addr->ip, NULL, 0); + sockaddr_fill((struct sockaddr *)&gate, i->addr->ip, NULL, 0); msg.rtm.rtm_addrs |= RTA_GATEWAY; } break; @@ -230,15 +259,15 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) { rte *e; net *net; - sockaddr dst, gate, mask; + struct sockaddr_in6 dst, gate, mask; ip_addr idst, igate, imask; void *body = (char *)msg->buf; int new = (msg->rtm.rtm_type == RTM_ADD); - char *errmsg = "KRT: Invalid route received"; int flags = msg->rtm.rtm_flags; int addrs = msg->rtm.rtm_addrs; - int src; + int af, pxlen, src; byte src2; + char *errmsg = "KRT: Invalid route received"; if (!(flags & RTF_UP) && scan) SKIP("not up in scan\n"); @@ -253,26 +282,52 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) GETADDR(&gate, RTA_GATEWAY); GETADDR(&mask, RTA_NETMASK); - if (sa_family_check(&dst)) - get_sockaddr(&dst, &idst, NULL, NULL, 0); - else - SKIP("invalid DST"); + af = dst.sin6_family; + + /* XXX: AF_MPLS */ + + switch (af) + { + case AF_INET: + /* Silently discard */ + if (p->addr_type != RT_IPV4) + return; + break; + + case AF_INET6: + /* Silently discard */ + if (p->addr_type != RT_IPV6) + return; + break; + + default: + SKIP("Invalid DST"); + } + + sockaddr_read((struct sockaddr *)&dst, &idst, NULL, NULL, 1); /* We will check later whether we have valid gateway addr */ - if (sa_family_check(&gate)) - get_sockaddr(&gate, &igate, NULL, NULL, 0); + if (gate.sin6_family == af) + sockaddr_read((struct sockaddr *)&gate, &igate, NULL, NULL, 0); else igate = IPA_NONE; /* We do not test family for RTA_NETMASK, because BSD sends us some strange values, but interpreting them as IPv4/IPv6 works */ - get_sockaddr(&mask, &imask, NULL, NULL, 0); + mask.sin6_family = dst.sin6_family; + + sockaddr_read((struct sockaddr *)&mask, &imask, NULL, NULL, 1); int c = ipa_classify_net(idst); if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) SKIP("strange class/scope\n"); - int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_mklen(imask); + if (af == AF_INET6) + pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ip6_masklen(&imask); + else + pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : + (ip4_masklen(ipa_to_ip4(imask)) + 96); // XXXX: Hack + if (pxlen < 0) { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; } @@ -356,11 +411,12 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) a.dest = RTD_ROUTER; a.gw = igate; -#ifdef IPV6 - /* Clean up embedded interface ID returned in link-local address */ - if (ipa_has_link_scope(a.gw)) - _I0(a.gw) = 0xfe800000; -#endif + if (af == AF_INET6) + { + /* Clean up embedded interface ID returned in link-local address */ + if (ipa_is_link_local(a.gw)) + _I0(a.gw) = 0xfe800000; + } ng = neigh_find2(&p->p, &a.gw, a.iface, 0); if (!ng || (ng->scope == SCOPE_HOST)) @@ -503,13 +559,13 @@ krt_read_addr(struct ks_msg *msg) { struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm; void *body = (void *)(ifam + 1); - sockaddr addr, mask, brd; + struct sockaddr_in6 addr, mask, brd; struct iface *iface = NULL; struct ifa ifa; struct sockaddr null; ip_addr iaddr, imask, ibrd; int addrs = ifam->ifam_addrs; - int scope, masklen = -1; + int ipv4, scope, masklen = -1, maxlen; int new = (ifam->ifam_type == RTM_NEWADDR); /* Strange messages with zero (invalid) ifindex appear on OpenBSD */ @@ -531,20 +587,33 @@ krt_read_addr(struct ks_msg *msg) GETADDR (&null, RTA_AUTHOR); GETADDR (&brd, RTA_BRD); - /* Some other family address */ - if (!sa_family_check(&addr)) + /* Basic family check */ + if (addr.sin6_family != AF_INET && addr.sin6_family != AF_INET6) return; - get_sockaddr(&addr, &iaddr, NULL, NULL, 0); - get_sockaddr(&mask, &imask, NULL, NULL, 0); - get_sockaddr(&brd, &ibrd, NULL, NULL, 0); + ipv4 = (addr.sin6_family == AF_INET) ? 1 : 0; - if ((masklen = ipa_mklen(imask)) < 0) + /* + * Work around (Free?)BSD bug with netmask + * family not being filled in IPv6 case. + * FreeBSD fix: r250815. + */ + if (addr.sin6_family == AF_INET6 && mask.sin6_family == 0) + mask.sin6_family = AF_INET6; + + sockaddr_read((struct sockaddr *)&addr, &iaddr, NULL, NULL, 0); + sockaddr_read((struct sockaddr *)&mask, &imask, NULL, NULL, 0); + sockaddr_read((struct sockaddr *)&brd, &ibrd, NULL, NULL, 0); + + masklen = ipv4 ? (ip4_masklen(ipa_to_ip4(imask)) + 96) : ip6_masklen(&imask); // XXXX: Hack + if (masklen < 0) { log("Invalid masklen"); return; } + // log("got %I/%I (%d)", iaddr, imask, masklen); + bzero(&ifa, sizeof(ifa)); ifa.iface = iface; @@ -561,31 +630,25 @@ krt_read_addr(struct ks_msg *msg) } ifa.scope = scope & IADDR_SCOPE_MASK; -#ifdef IPV6 /* Clean up embedded interface ID returned in link-local address */ - if (ipa_has_link_scope(ifa.ip)) + if (scope & SCOPE_LINK) _I0(ifa.ip) = 0xfe800000; -#endif -#ifdef IPV6 - /* Why not the same check also for IPv4? */ - if ((iface->flags & IF_MULTIACCESS) || (masklen != BITS_PER_IP_ADDRESS)) -#else - if (iface->flags & IF_MULTIACCESS) -#endif + // maxlen = ipv4 ? BITS_PER_IP_ADDRESS4 : BITS_PER_IP_ADDRESS6; + maxlen = BITS_PER_IP_ADDRESS; // XXXX: Hack + + if ((iface->flags & IF_MULTIACCESS) || (masklen != maxlen)) { ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen)); - if (masklen == BITS_PER_IP_ADDRESS) + if (masklen == maxlen) ifa.flags |= IA_HOST; - if (masklen == (BITS_PER_IP_ADDRESS - 1)) + if (masklen == (maxlen - 1)) ifa.opposite = ipa_opposite_m1(ifa.ip); -#ifndef IPV6 - if (masklen == (BITS_PER_IP_ADDRESS - 2)) + if (ipv4 && masklen == (maxlen - 2)) ifa.opposite = ipa_opposite_m2(ifa.ip); -#endif } else /* PtP iface */ { @@ -627,7 +690,7 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan) } static void -krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) +krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd, int af) { byte *next; int mib[6]; @@ -638,7 +701,7 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd) mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; - mib[3] = BIRD_PF; + mib[3] = af; mib[4] = cmd; mib[5] = 0; @@ -686,7 +749,8 @@ static size_t kif_buflen = 4096; void krt_do_scan(struct krt_proto *p) { - krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP); + krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, + NET_RT_DUMP, rt_to_af(p->addr_type)); } void @@ -694,7 +758,7 @@ kif_do_scan(struct kif_proto *p) { struct proto *P = (struct proto *)p; if_start_update(); - krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST); + krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST, 0); if_end_update(); } @@ -747,6 +811,24 @@ krt_sys_shutdown(struct krt_proto *x UNUSED, int last UNUSED) krt_buffer = NULL; } +static u32 tables; + +void +krt_sys_preconfig(struct config *c UNUSED) +{ + tables = 0; +} + +void +krt_sys_postconfig(struct krt_config *x) +{ + u32 id = x->c.table->addr_type; + + if (tables & (1 << id)) + cf_error("Multiple kernel protocols defined for AF %d", id); + tables |= (1 << id); +} + void kif_sys_start(struct kif_proto *p UNUSED) diff --git a/sysdep/bsd/krt-sys.h b/sysdep/bsd/krt-sys.h index 88915dde..642f5593 100644 --- a/sysdep/bsd/krt-sys.h +++ b/sysdep/bsd/krt-sys.h @@ -40,8 +40,6 @@ struct krt_status { static inline void krt_sys_init(struct krt_proto *p UNUSED) { } static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; } -static inline void krt_sys_preconfig(struct config *c UNUSED) { } -static inline void krt_sys_postconfig(struct krt_config *c UNUSED) { } static inline void krt_sys_init_config(struct krt_config *c UNUSED) { } static inline void krt_sys_copy_config(struct krt_config *d UNUSED, struct krt_config *s UNUSED) { } diff --git a/sysdep/bsd/sysio.h b/sysdep/bsd/sysio.h index 4f91def5..607d28ff 100644 --- a/sysdep/bsd/sysio.h +++ b/sysdep/bsd/sysio.h @@ -9,54 +9,22 @@ #ifdef __DragonFly__ #define TCP_MD5SIG TCP_SIGNATURE_ENABLE #endif -#ifdef IPV6 - -static inline void -set_inaddr(struct in6_addr * ia, ip_addr a) -{ - ipa_hton(a); - memcpy(ia, &a, sizeof(a)); -} - -static inline void -get_inaddr(ip_addr *a, struct in6_addr *ia) -{ - memcpy(a, ia, sizeof(*a)); - ipa_ntoh(*a); -} static inline char * -sysio_bind_to_iface(sock *s) +sk_bind_to_iface(sock *s) { /* Unfortunately not available */ return NULL; } -#else - #include #include -static inline void -set_inaddr(struct in_addr * ia, ip_addr a) -{ - ipa_hton(a); - memcpy(&ia->s_addr, &a, sizeof(a)); -} - -static inline void -get_inaddr(ip_addr *a, struct in_addr *ia) -{ - memcpy(a, &ia->s_addr, sizeof(*a)); - ipa_ntoh(*a); -} - - /* BSD Multicast handling for IPv4 */ static inline char * -sysio_setup_multicast(sock *s) +sk_setup_multicast4(sock *s) { struct in_addr m; u8 zero = 0; @@ -69,7 +37,7 @@ sysio_setup_multicast(sock *s) return "IP_MULTICAST_TTL"; /* This defines where should we send _outgoing_ multicasts */ - set_inaddr(&m, s->iface->addr->ip); + ipa_put_in4(&m, s->iface->addr->ip); if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0) return "IP_MULTICAST_IF"; @@ -78,13 +46,13 @@ sysio_setup_multicast(sock *s) static inline char * -sysio_join_group(sock *s, ip_addr maddr) +sk_join_group4(sock *s, ip_addr maddr) { struct ip_mreq mreq; bzero(&mreq, sizeof(mreq)); - set_inaddr(&mreq.imr_interface, s->iface->addr->ip); - set_inaddr(&mreq.imr_multiaddr, maddr); + ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip); + ipa_put_in4(&mreq.imr_multiaddr, maddr); /* And this one sets interface for _receiving_ multicasts from */ if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) @@ -94,13 +62,13 @@ sysio_join_group(sock *s, ip_addr maddr) } static inline char * -sysio_leave_group(sock *s, ip_addr maddr) +sk_leave_group4(sock *s, ip_addr maddr) { struct ip_mreq mreq; bzero(&mreq, sizeof(mreq)); - set_inaddr(&mreq.imr_interface, s->iface->addr->ip); - set_inaddr(&mreq.imr_multiaddr, maddr); + ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip); + ipa_put_in4(&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) @@ -117,7 +85,7 @@ sysio_leave_group(sock *s, ip_addr maddr) #define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr)) static char * -sysio_register_cmsgs(sock *s) +sk_request_pktinfo4(sock *s) { int ok = 1; if (s->flags & SKF_LADDR_RX) @@ -133,29 +101,18 @@ sysio_register_cmsgs(sock *s) } static void -sysio_process_rx_cmsgs(sock *s, struct msghdr *msg) +sk_process_rx_cmsg4(sock *s, struct cmsghdr *cm) { - struct cmsghdr *cm; - - if (!(s->flags & SKF_LADDR_RX)) - return; - - s->laddr = IPA_NONE; - s->lifindex = 0; - - for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm)) + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) { - if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR) - { - struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm); - get_inaddr(&s->laddr, ra); - } + struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm); + s->laddr = ipa_get_in4(ra); + } - if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF) - { - struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm); - s->lifindex = ri->sdl_index; - } + if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF) + { + struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm); + s->lifindex = ri->sdl_index; } // log(L_WARN "RX %I %d", s->laddr, s->lifindex); @@ -194,8 +151,6 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) } */ -#endif - #include #ifndef TCP_KEYLEN_MAX @@ -212,7 +167,7 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) */ static int -sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd) +sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd) { int enable = 0; if (passwd) @@ -242,45 +197,32 @@ sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd) } -#ifndef IPV6 - #ifdef IP_MINTTL -static int +static inline char * sk_set_min_ttl4(sock *s, int ttl) { if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0) - { - if (errno == ENOPROTOOPT) - log(L_ERR "Kernel does not support IPv4 TTL security"); - else - log(L_ERR "sk_set_min_ttl4: setsockopt: %m"); + return "IP_MINTTL"; - return -1; - } - - return 0; + return NULL; } #else /* no IP_MINTTL */ -static int +static inline char * sk_set_min_ttl4(sock *s, int ttl) { - log(L_ERR "IPv4 TTL security not supported"); - return -1; + errno = ENOPROTOOPT; + return "IP_MINTTL"; } #endif -#else /* IPv6 */ - -static int +static inline char * sk_set_min_ttl6(sock *s, int ttl) { - log(L_ERR "IPv6 TTL security not supported"); - return -1; + errno = ENOPROTOOPT; + return "IP_MINTTL"; } -#endif - diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h index 90e164fb..e6daa31f 100644 --- a/sysdep/linux/sysio.h +++ b/sysdep/linux/sysio.h @@ -220,40 +220,22 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen) #define IPV6_MINHOPCOUNT 73 #endif - -// XXXX -#if 0 - -static int +static inline char * sk_set_min_ttl4(sock *s, int ttl) { if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0) - { - if (errno == ENOPROTOOPT) - log(L_ERR "Kernel does not support IPv4 TTL security"); - else - log(L_ERR "sk_set_min_ttl4: setsockopt: %m"); + return "IP_MINTTL"; - return -1; - } - - return 0; + return NULL; } -static int +static inline char * sk_set_min_ttl6(sock *s, int ttl) { if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0) - { - if (errno == ENOPROTOOPT) - log(L_ERR "Kernel does not support IPv6 TTL security"); - else - log(L_ERR "sk_set_min_ttl6: setsockopt: %m"); + return "IPV6_MINHOPCOUNT"; - return -1; - } - - return 0; + return NULL; } -#endif + diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c index eb103f1b..c45e5866 100644 --- a/sysdep/unix/io.c +++ b/sysdep/unix/io.c @@ -590,23 +590,29 @@ static inline int sockaddr_size(int af) static inline void sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, unsigned port) { - sa->sin_port = htons(port); + memset(sa, 0, sizeof(struct sockaddr_in)); #ifdef HAVE_SIN_LEN sa->sin_len = sizeof(struct sockaddr_in); #endif + sa->sin_family = AF_INET; + sa->sin_port = htons(port); ipa_put_in4(&sa->sin_addr, a); } static inline void sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, unsigned port) { - sa->sin6_port = htons(port); - sa->sin6_flowinfo = 0; + memset(sa, 0, sizeof(struct sockaddr_in6)); #ifdef SIN6_LEN sa->sin6_len = sizeof(struct sockaddr_in6); #endif + sa->sin6_family = AF_INET6; + sa->sin6_port = htons(port); + sa->sin6_flowinfo = 0; ipa_put_in6(&sa->sin6_addr, a); - sa->sin6_scope_id = (ifa && ipa_is_link_local(a)) ? ifa->index : 0; + + if (ifa && ipa_is_link_local(a)) + sa->sin6_scope_id = ifa->index; } void @@ -852,24 +858,21 @@ sk_set_min_ttl(sock *s, int ttl) char *err; if (sk_is_ipv4(s)) - { - if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0) - ERR("IP_MINTTL"); - } + err = sk_set_min_ttl4(s, ttl); else - { - if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0) - ERR("IPV6_MINHOPCOUNT"); - } + err = sk_set_min_ttl6(s, ttl); + + if (err) + { + if (errno == ENOPROTOOPT) + log(L_ERR "Kernel does not support %s TTL security", sk_is_ipv4(s) ? "IPv4" : "IPv6"); + else + log(L_ERR "sk_set_min_ttl: %s: %m", err); + + return -1; + } return 0; - - bad: - if (errno == ENOPROTOOPT) - log(L_ERR "Kernel does not support %s TTL security", sk_is_ipv4(s) ? "IPv4" : "IPv6"); - else - log(L_ERR "sk_set_min_ttl: %s: %m", err); - return -1; } diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index efcb87ea..34427847 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -1062,11 +1062,6 @@ krt_postconfig(struct proto_config *C) struct proto_config * krt_init_config(int class) { -#ifndef CONFIG_MULTIPLE_TABLES - if (krt_cf) - cf_error("Kernel protocol already defined"); -#endif - krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class); krt_cf->scan_time = 60; diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h index aca3cc77..52bb4fe6 100644 --- a/sysdep/unix/unix.h +++ b/sysdep/unix/unix.h @@ -33,10 +33,11 @@ volatile int async_config_flag; volatile int async_dump_flag; volatile int async_shutdown_flag; -// XXXX -#define BIRD_PF PF_INET6 -#define BIRD_AF AF_INET6 -static inline int sa_family_check(struct sockaddr *sa) { return sa->sa_family == AF_INET6; } +struct sockaddr; +struct iface; + +void sockaddr_fill(struct sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port); +void sockaddr_read(struct sockaddr *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check); #ifndef SUN_LEN