/* allocate buffer but free unless able to read and parse nlm fully */ static GOOD_OR_BAD Get_and_Parse_Pipe( FILE_DESCRIPTOR_OR_ERROR file_descriptor, struct netlink_parse * nlp ) { struct nlmsghdr peek_nlm ; struct nlmsghdr * nlm ; size_t payload_length ; // first read start of message to get length and details if ( read( file_descriptor, &peek_nlm, W1_NLM_LENGTH ) != W1_NLM_LENGTH ) { ERROR_DEBUG("Pipe (w1) read header error"); return gbBAD ; } LEVEL_DEBUG("Pipe header: len=%u type=%u seq=%u|%u pid=%u ",peek_nlm.nlmsg_len,peek_nlm.nlmsg_type,NL_BUS(peek_nlm.nlmsg_seq),NL_SEQ(peek_nlm.nlmsg_seq),peek_nlm.nlmsg_pid); // allocate space nlm = owmalloc( peek_nlm.nlmsg_len ) ; nlp->nlm = nlm ; if ( nlm == NULL ) { LEVEL_DEBUG("Netlink (w1) Cannot allocate %d byte buffer for data", peek_nlm.nlmsg_len ) ; return gbBAD ; } memcpy( nlm, &peek_nlm, W1_NLM_LENGTH ) ; // copy header // read rest of packet if ( peek_nlm.nlmsg_len <= W1_NLM_LENGTH ) { owfree(nlm) ; LEVEL_DEBUG( "W1 packet error. Length is too short." ) ; return gbBAD ; } payload_length = peek_nlm.nlmsg_len - W1_NLM_LENGTH ; if ( read( file_descriptor, NLMSG_DATA(nlm), payload_length ) != (ssize_t) payload_length ) { owfree(nlm) ; nlp->nlm = NULL ; ERROR_DEBUG("Pipe (w1) read payload error"); return gbBAD ; } if ( BAD( Netlink_Parse_Buffer( nlp )) ) { LEVEL_DEBUG("Buffer parsing error"); owfree(nlm) ; nlp->nlm = NULL ; return gbBAD ; } // Good, the receiving routine should owfree buffer LEVEL_DEBUG("Pipe read --------------------"); Netlink_Parse_Show( nlp ) ; return gbGOOD ; }
static ZERO_OR_ERROR OW_read_external_script( struct sensor_node * sensor_n, struct property_node * property_n, struct one_wire_query * owq ) { char cmd[PATH_MAX+1] ; struct parsedname * pn = PN(owq) ; FILE * script_f ; int snp_return ; ZERO_OR_ERROR zoe ; // load the command script and arguments if ( pn->sparse_name == NULL ) { // not a text sparse name snp_return = snprintf( cmd, PATH_MAX+1, "%s %s %s %d %s %d %d %s %s", property_n->read, // command sensor_n->name, // sensor name property_n->property, // property, pn->extension, // extension "read", // mode (int) OWQ_size(owq), // size (int) OWQ_offset(owq), // offset sensor_n->data, // sensor-specific data property_n->data // property-specific data ) ; } else { snp_return = snprintf( cmd, PATH_MAX+1, "%s %s %s %s %s %d %d %s %s", property_n->read, // command sensor_n->name, // sensor name property_n->property, // property, pn->sparse_name, // extension "read", // mode (int) OWQ_size(owq), // size (int) OWQ_offset(owq), // offset sensor_n->data, // sensor-specific data property_n->data // property-specific data ) ; } if ( snp_return < 0 ) { LEVEL_DEBUG("Problem creating script string for %s/%s",sensor_n->name,property_n->property) ; return -EINVAL ; } script_f = popen( cmd, "r" ) ; if ( script_f == NULL ) { ERROR_DEBUG("Cannot create external program link for reading %s/%s",sensor_n->name,property_n->property); return -EIO ; } zoe = OW_script_read( script_f, owq ) ; fclose( script_f ) ; return zoe ; }
static int Get_HA7_response( struct addrinfo *now, char * name ) { struct timeval tv = { 50, 0 }; FILE_DESCRIPTOR_OR_ERROR file_descriptor; struct HA7_response ha7_response ; struct sockaddr_in from ; socklen_t fromlen = sizeof(struct sockaddr_in) ; int on = 1; file_descriptor = socket(now->ai_family, now->ai_socktype, now->ai_protocol) ; if ( FILE_DESCRIPTOR_NOT_VALID(file_descriptor) ) { ERROR_DEBUG("Cannot get socket file descriptor for broadcast."); return 1; } // fcntl (file_descriptor, F_SETFD, FD_CLOEXEC); // for safe forking if (setsockopt(file_descriptor, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) == -1) { ERROR_DEBUG("Cannot set socket option for broadcast."); return 1; } if (sendto(file_descriptor, "HA\000\001", 4, 0, now->ai_addr, now->ai_addrlen) != 4) { ERROR_CONNECT("Trouble sending broadcast message"); return 1; } /* now read */ if ( udp_read(file_descriptor, &ha7_response, sizeof(struct HA7_response), &tv, &from, &fromlen) != sizeof(struct HA7_response) ) { LEVEL_CONNECT("HA7 response bad length"); return 1; } if ( Test_HA7_response( &ha7_response ) ) { return 1 ; } UCLIBCLOCK ; snprintf(name,INET_ADDRSTRLEN+20,"%s:%d",inet_ntoa(from.sin_addr),ntohs(ha7_response.port)); UCLIBCUNLOCK ; return 0 ; }
GOOD_OR_BAD W1_Browse( void ) { pthread_t thread_dispatch ; if ( pthread_create(&thread_dispatch, DEFAULT_THREAD_ATTR, W1_Dispatch, NULL ) != 0 ) { ERROR_DEBUG("Couldn't create netlink monitoring thread"); return gbBAD ; } return gbGOOD ; }
GOOD_OR_BAD Netlink_Parse_Get( struct netlink_parse * nlp ) { struct nlmsghdr peek_nlm ; // first peek at message to get length and details LEVEL_DEBUG("Wait to peek at message"); int recv_len = recv( Inbound_Control.w1_monitor->pown->file_descriptor, &peek_nlm, W1_NLM_LENGTH, MSG_PEEK ); // Set time of last read _MUTEX_LOCK(Inbound_Control.w1_monitor->master.w1_monitor.read_mutex) ; timernow( &(Inbound_Control.w1_monitor->master.w1_monitor.last_read) ); _MUTEX_UNLOCK(Inbound_Control.w1_monitor->master.w1_monitor.read_mutex) ; LEVEL_DEBUG("Pre-parse header: %u bytes len=%u type=%u seq=%u|%u pid=%u",recv_len,peek_nlm.nlmsg_len,peek_nlm.nlmsg_type,NL_BUS(peek_nlm.nlmsg_seq),NL_SEQ(peek_nlm.nlmsg_seq),peek_nlm.nlmsg_pid); if (recv_len < 0) { ERROR_DEBUG("Netlink (w1) recv header error"); return gbBAD ; } // allocate space nlp->nlm = owmalloc( peek_nlm.nlmsg_len ) ; if ( nlp->nlm == NULL ) { LEVEL_DEBUG("Netlink (w1) Cannot allocate %d byte buffer for data",peek_nlm.nlmsg_len) ; return gbBAD ; } // read whole packet recv_len = recv( Inbound_Control.w1_monitor->pown->file_descriptor, &(nlp->nlm[0]), peek_nlm.nlmsg_len, 0 ); if (recv_len == -1) { ERROR_DEBUG("Netlink (w1) recv body error"); return gbBAD ; } if ( GOOD( Netlink_Parse_Buffer( nlp )) ) { LEVEL_DEBUG("Netlink read -----------------"); Netlink_Parse_Show( nlp ) ; return gbGOOD ; } return gbBAD ; }
/* Device-specific functions */ GOOD_OR_BAD W1_monitor_detect(struct port_in *pin) { struct connection_in * in = pin->first ; struct timeval tvslack = { 1, 0 } ; // 1 second pin->file_descriptor = FILE_DESCRIPTOR_BAD; pin->type = ct_none ; in->iroutines.detect = W1_monitor_detect; in->Adapter = adapter_w1_monitor; /* OWFS assigned value */ in->iroutines.reset = NO_RESET_ROUTINE; in->iroutines.next_both = NO_NEXT_BOTH_ROUTINE; in->iroutines.PowerByte = NO_POWERBYTE_ROUTINE; in->iroutines.ProgramPulse = NO_PROGRAMPULSE_ROUTINE; in->iroutines.sendback_data = NO_SENDBACKDATA_ROUTINE; in->iroutines.sendback_bits = NO_SENDBACKBITS_ROUTINE; in->iroutines.select = NO_SELECT_ROUTINE; in->iroutines.select_and_sendback = NO_SELECTANDSENDBACK_ROUTINE; in->iroutines.set_config = NO_SET_CONFIG_ROUTINE; in->iroutines.get_config = NO_GET_CONFIG_ROUTINE; in->iroutines.reconnect = NO_RECONNECT_ROUTINE; in->iroutines.close = W1_monitor_close; in->iroutines.verify = NO_VERIFY_ROUTINE ; in->iroutines.flags = ADAP_FLAG_sham; in->adapter_name = "W1 monitor"; pin->busmode = bus_w1_monitor ; RETURN_BAD_IF_BAD( w1_monitor_in_use(in) ) ; // Initial setup Inbound_Control.w1_monitor = in ; // essentially a global pointer to the w1_monitor entry _MUTEX_INIT(in->master.w1_monitor.seq_mutex); _MUTEX_INIT(in->master.w1_monitor.read_mutex); timernow( &(in->master.w1_monitor.last_read) ); timeradd( &(in->master.w1_monitor.last_read), &tvslack, &(in->master.w1_monitor.last_read) ); in->master.w1_monitor.seq = SEQ_INIT ; in->master.w1_monitor.pid = 0 ; w1_bind(in) ; // sets in->file_descriptor if ( FILE_DESCRIPTOR_NOT_VALID( in->pown->file_descriptor ) ) { ERROR_DEBUG("Netlink problem -- are you root?"); Inbound_Control.w1_monitor = NO_CONNECTION ; return gbBAD ; } return W1_Browse() ; // creates thread that runs forever. }