INT cd_multi(INT cmd, EQUIPMENT * pequipment) { INT status; switch (cmd) { case CMD_INIT: status = multi_init(pequipment); break; case CMD_EXIT: status = multi_exit(pequipment); break; case CMD_START: status = multi_start(pequipment); break; case CMD_STOP: status = multi_stop(pequipment); break; case CMD_IDLE: status = multi_idle(pequipment); break; default: cm_msg(MERROR, "Multimeter class driver", "Received unknown command %d", cmd); status = FE_ERR_DRIVER; break; } return status; }
int multi_fork( int n, struct multi_fork_status *p, time_t stoptime, int line ) { int i, result; for( i=0; i<n; i++ ) { p[i].state = MULTI_FORK_STATE_CRADLE; } cancel_hold(); result = multi_start(n,p,stoptime,line); if(result==MULTI_FORK_SUCCESS) { result = multi_wait(n,p,stoptime,line,1); if(result!=MULTI_FORK_SUCCESS) { multi_kill(n,p,stoptime,line); } } cancel_release(); return result; }
void multi_test_visible_loop(struct multi_config *mc){ uint8_t buf[MAX_BUFSIZE]; int32_t retval; int32_t i; int32_t netlink_sock = 0; uint32_t ifi_idx = 0; struct iface *ni = NULL; /* Needed to create the netlink messages */ struct sockaddr_nl src_addr, dest_addr; struct iovec iov; struct msghdr msg; /* Select is used for easier timeouts */ fd_set copy, master; int32_t fdmax; struct timeval tv; memset(buf, 0, MAX_BUFSIZE); /* Initialise list */ LIST_INIT(&iface_list); /* Define a private constant later! Needs to be set in netlink.h so that the * kernel will allow the socket to be created! */ if((netlink_sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_GENERIC)) < 0){ perror("Could not create netlink socket: "); exit(EXIT_FAILURE); } /* These are both constant! */ memset(&src_addr, 0, sizeof(src_addr)); memset(&dest_addr, 0, sizeof(dest_addr)); memset(&msg, 0, sizeof(msg)); src_addr.nl_family = AF_NETLINK; //If PID is set to zero, then the kernel assigns the unique value src_addr.nl_pid = 0; //This is the source, it only multicasts, so it does not have to be //member of any groups! src_addr.nl_groups = 0; if(bind(netlink_sock, (struct sockaddr *) &src_addr, sizeof(src_addr)) < 0){ perror("Could not bind netlink socket: "); exit(EXIT_FAILURE); } dest_addr.nl_family = AF_NETLINK; dest_addr.nl_pid = 0; dest_addr.nl_groups = 1; MULTI_DEBUG_PRINT(stderr, "Multi manager is ready! Netlink socket %d\n", netlink_sock); MULTI_DEBUG_PRINT(stderr, "M S\n"); //Look at the Wikipedia site for iovec and man(7) netlink for examples on //how to properly parse netlink and have multiple iovec-entries msg.msg_name = (void *) &dest_addr; //This is the message's destination msg.msg_namelen = sizeof(dest_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; //Initialise everything related to select FD_ZERO(&master); FD_ZERO(©); FD_SET(mc->socket_pipe[0], &master); fdmax = mc->socket_pipe[0]; tv.tv_sec = 30; tv.tv_usec = 0; pthread_t multi_thread = multi_start(mc); while(1){ copy = master; retval = select(fdmax + 1, ©, NULL, NULL, &tv); //Repeat every UP message if(retval == 0){ for(ni = iface_list.lh_first; ni != NULL; ni = ni->next.le_next){ printf("Hei\n"); iov.iov_base = (void *) ni->nlmsg; iov.iov_len = ni->nlmsg->nlmsg_len; sendmsg(netlink_sock, &msg, 0); } tv.tv_sec = 30; tv.tv_usec = 0; continue; } memset(buf, 0, MAX_BUFSIZE); //Sufficient to just memcpy this one and broadcast the netlink message retval = read(mc->socket_pipe[0], buf, MAX_BUFSIZE); if(retval == -1) perror("Failed to read from pipe"); else { memcpy(&ifi_idx, (buf+1), sizeof(uint32_t)); //This check needs to be performed irrespective of if link goes up //or down. LIST_FIND_CUSTOM(ni, &iface_list, next, &ifi_idx, multi_mc_cmp_ifi); if(buf[0] == LINK_UP){ //Sanity check. If the interface is already found, ignore the //announcement from MULTI. if(ni) continue; //Create a new iface, buffer the up message and add to list ni = (struct iface*) malloc(sizeof(struct iface)); ni->ifi_idx = ifi_idx; ni->nlmsg = (struct nlmsghdr *) malloc(NLMSG_SPACE(retval)); memset(ni->nlmsg, 0, NLMSG_SPACE(retval)); ni->nlmsg->nlmsg_pid = getpid(); ni->nlmsg->nlmsg_flags = 0; ni->nlmsg->nlmsg_len = NLMSG_SPACE(retval); memcpy(NLMSG_DATA(ni->nlmsg), buf, retval); LIST_INSERT_HEAD(&iface_list, ni, next); //Adjust the base pointer of the message and broadcast message iov.iov_base = (void *) ni->nlmsg; iov.iov_len = ni->nlmsg->nlmsg_len; retval = sendmsg(netlink_sock, &msg, 0); MULTI_DEBUG_PRINT(stderr,"Broadcasted %d bytes about an UP " "change in network state\n", retval); } else { if(ni){ //Forward message from MULTI ni->nlmsg->nlmsg_len = NLMSG_SPACE(retval); memcpy(NLMSG_DATA(ni->nlmsg), buf, retval); iov.iov_base = (void *) ni->nlmsg; iov.iov_len = ni->nlmsg->nlmsg_len; retval = sendmsg(netlink_sock, &msg, 0); MULTI_DEBUG_PRINT(stderr,"Broadcasted %d bytes about a " "DOWN change in network state\n", retval); LIST_REMOVE(ni, next); free(ni); } } } } }