| /*@file lynq-ndis-uevent.c |
| * @brief adb default port is closed, The uevent event of NDIS is reported to switch port. |
| * @author dongyu |
| * @date 2022-10-14 |
| * @version V1.0 |
| * @copyright MobileTek |
| */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <sys/socket.h> |
| #include <linux/netlink.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include <stdlib.h> |
| #include <include/lynq_uci.h> |
| |
| #define _GNU_SOURCE |
| #define UEVENT_MSG_LEN 1024 |
| |
| #define LOG_UCI_FILE "lynq_uci" |
| #define LOG_UCI_MODULE "lynq_rndis" |
| |
| int rndis_initiate_mode = 0; |
| |
| struct uevent{ |
| const char *action; |
| const char *path; |
| const char *subsystem; |
| const char *firmware; |
| const char *calluser; |
| int major; |
| int minor; |
| }; |
| |
| static int lynq_open_uevent_socket(void) |
| { |
| struct sockaddr_nl addr; |
| int sz = 64*1024; |
| int on = 1; |
| int socketfd; |
| |
| memset(&addr, 0, sizeof(addr)); |
| addr.nl_family = AF_NETLINK; |
| addr.nl_pid = getpid(); |
| addr.nl_groups = 0xffffffff; |
| |
| socketfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); |
| if(socketfd < 0){ |
| return -1; |
| } |
| |
| setsockopt(socketfd, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)); |
| setsockopt(socketfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)); |
| |
| if(bind(socketfd, (struct sockaddr *) &addr, sizeof(addr)) < 0){ |
| close(socketfd); |
| return -1; |
| } |
| |
| return socketfd; |
| } |
| |
| static void lynq_parse_event(const char *msg, struct uevent *uevent) |
| { |
| uevent->action = ""; |
| uevent->path = ""; |
| uevent->subsystem = ""; |
| uevent->firmware = ""; |
| uevent->calluser = ""; |
| uevent->major = -1; |
| uevent->minor = -1; |
| |
| /* currently ignoring SEQNUM */ |
| while(*msg){ |
| printf("%s\n", msg); |
| if(!strncmp(msg, "ACTION=", 7)){ |
| msg += 7; |
| uevent->action = msg; |
| } else if(!strncmp(msg, "DEVPATH=", 8)){ |
| msg += 8; |
| uevent->path = msg; |
| } else if(!strncmp(msg, "SUBSYSTEM=", 10)){ |
| msg += 10; |
| uevent->subsystem = msg; |
| } else if(!strncmp(msg, "FIRMWARE=", 9)){ |
| msg += 9; |
| uevent->firmware = msg; |
| } else if(!strncmp(msg, "MAJOR=", 6)){ |
| msg += 6; |
| uevent->major = atoi(msg); |
| } else if(!strncmp(msg, "MINOR=", 6)){ |
| msg += 6; |
| uevent->minor = atoi(msg); |
| } else if(!strncmp(msg, "CALL_USER=", 10)){ |
| msg += 10; |
| uevent->calluser = msg; |
| } |
| |
| /* advance to after the next \0 */ |
| while(*msg++); |
| } |
| |
| printf("event { '%s', '%s', '%s', '%s', %d, %d }\n", |
| uevent->action, uevent->path, uevent->subsystem, |
| uevent->firmware, uevent->major, uevent->minor); |
| } |
| |
| void lynq_handle_device_fd(int fd) |
| { |
| printf("enter %s\n", __func__); |
| for(;;) { |
| char msg[UEVENT_MSG_LEN+2]; |
| char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; |
| struct iovec iov = {msg, sizeof(msg)}; |
| struct sockaddr_nl snl; |
| struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0}; |
| |
| ssize_t n = recvmsg(fd, &hdr, 0); |
| if (n <= 0){ |
| break; |
| } |
| |
| if ((snl.nl_groups != 1) || (snl.nl_pid != 0)){ |
| /* ignoring non-kernel netlink multicast message */ |
| continue; |
| } |
| |
| struct cmsghdr * cmsg = CMSG_FIRSTHDR(&hdr); |
| if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS){ |
| /* no sender credentials received, ignore message */ |
| continue; |
| } |
| |
| struct ucred * cred = (struct ucred *)CMSG_DATA(cmsg); |
| if (cred->uid != 0){ |
| /* message from non-root user, ignore */ |
| continue; |
| } |
| |
| if(n >= UEVENT_MSG_LEN){ |
| /* overflow -- discard */ |
| continue; |
| } |
| |
| msg[n] = '\0'; |
| msg[n+1] = '\0'; |
| |
| printf("2022 ::: msg = %s\n", msg); |
| struct uevent uevent; |
| lynq_parse_event(msg, &uevent); |
| |
| if(strcmp(uevent.path,"/devices/virtual/android_usb/android0") == 0 |
| && strcmp(uevent.calluser, "/usr/bin/usb uevent reporting") == 0){ |
| system("/usr/bin/usb_switch ets"); |
| printf("USB login port switch successfully!\n"); |
| while(1){ |
| sleep(1); |
| } |
| } |
| } |
| } |
| |
| int main(void) |
| { |
| int fd = 0; |
| char tmp[20]; |
| |
| fd = lynq_open_uevent_socket(); |
| if (fd < 0){ |
| printf("error!\n"); |
| return -1; |
| } |
| |
| lynq_get_value(LOG_UCI_FILE, LOG_UCI_MODULE, "initiate", tmp); |
| rndis_initiate_mode=atoi(tmp); |
| if(rndis_initiate_mode == 1){ |
| lynq_handle_device_fd(fd); |
| while(1){ |
| sleep(1); |
| } |
| } |
| else{ |
| while(1){ |
| sleep(1); |
| } |
| } |
| return 0; |
| } |