From c6fa60aa685a4634ec9e78169886755c0ad2f223 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 29 Aug 2014 21:28:45 +0200 Subject: [PATCH] add pktinfo to rx path Signed-off-by: John Crispin --- interface.c | 45 +++++++++++++++++++++++++++++++++++++++------ service.c | 2 ++ 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/interface.c b/interface.c index 8df85bd..7f53653 100644 --- a/interface.c +++ b/interface.c @@ -136,7 +136,13 @@ read_socket(struct uloop_fd *u, unsigned int events) { struct interface *iface = container_of(u, struct interface, fd); static uint8_t buffer[8 * 1024]; - int len; + struct iovec iov[1]; + char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + struct cmsghdr *cmsgptr; + struct msghdr msg; + socklen_t len; + struct sockaddr_in6 from; + int flags = 0, ifindex = -1; if (u->eof) { interface_close(iface); @@ -144,14 +150,34 @@ read_socket(struct uloop_fd *u, unsigned int events) return; } - len = read(u->fd, buffer, sizeof(buffer)); - if (len < 1) { - if (errno != EAGAIN) - fprintf(stderr, "read failed: %s\n", strerror(errno)); + iov[0].iov_base = buffer; + iov[0].iov_len = sizeof(buffer); + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = (struct sockaddr *) &from; + msg.msg_namelen = (iface->v6) ? (sizeof(struct sockaddr_in6)) : (sizeof(struct sockaddr_in)); + msg.msg_iov = iov; + msg.msg_iovlen = 1; + msg.msg_control = &cmsg6; + msg.msg_controllen = sizeof(cmsg6); + + len = recvmsg(u->fd, &msg, flags); + if (len < 0) { + fprintf(stderr, "%s:%s[%d]\n", __FILE__, __func__, __LINE__); return; } + for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL && ifindex == -1; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { + void *c = CMSG_DATA(cmsgptr); - dns_handle_packet(iface, buffer, len); + if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) + ifindex = ((struct in_pktinfo *) c)->ipi_ifindex; + else if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO) + ifindex = ((struct in6_pktinfo *) c)->ipi6_ifindex; + } + if (ifindex) + dns_handle_packet(iface, buffer, len); + + printf("%d\n", ifindex); } static int @@ -324,6 +350,9 @@ get_iface_ipv4(struct interface *iface) struct ifreq ir; int sock, ret = -1; + if (cfg_proto && (cfg_proto != 4)) + return -1; + sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) return -1; @@ -350,6 +379,9 @@ get_iface_ipv6(struct interface *iface) socklen_t alen = sizeof(addr); int sock, ret = -1; + if (cfg_proto && (cfg_proto != 6)) + return -1; + addr.sin6_addr.s6_addr[0] = 0xff; addr.sin6_addr.s6_addr[1] = 0x02; addr.sin6_addr.s6_addr[15] = 0x01; @@ -403,6 +435,7 @@ int interface_add(const char *name) { int v4 = _interface_add(name, 0); int v6 = _interface_add(name, 1); + return v4 && v6; } diff --git a/service.c b/service.c index 71d987b..32c3d62 100644 --- a/service.c +++ b/service.c @@ -376,6 +376,8 @@ service_init_cb(struct ubus_request *req, int type, struct blob_attr *msg) void service_init(int announce) { + get_hostname(); + service_init_announce = announce; ubus_service_list(service_init_cb); } -- 2.11.0