uint8_t OMMoCoNode::check() { uint8_t command = getPacket(); // no packet available if( command == 0 ) return(0); // command OM_SER_BASECOM is reserved for core protocol commands. // We handle these automatically for the node. if( ! isBroadcast() && command == OM_SER_BASECOM ) { _coreProtocol(this->buffer()); return(0); } else { // we have a command code which is higher than 1, // send to the supplied handler. if( f_bcastHandler != 0 && isBroadcast() ) { // a callback is assigned, and this is a // broadcast command f_bcastHandler(command, this->buffer()); } else if( f_cmdHandler != 0 && ! isBroadcast() ) { // a callback is assigned, call callback // with command code and payload f_cmdHandler(command, this->buffer()); } } return(command); }
Socket::Error UDPTransmit::connect(const IPV4Broadcast &subnet, tpport_t port) { if(!isBroadcast()) setBroadcast(true); return cConnect((IPV4Address)subnet,port); }
Socket::Error UDPTransmit::connect(const IPV4Host &ia, tpport_t port) { if(isBroadcast()) setBroadcast(false); return cConnect((IPV4Address)ia,port); }
bool ChannelData::canWrite() const { // Duplicated in Data::CanWriteValue(). return amIn() && (canPublish() || (!isBroadcast() && !restricted(Restriction::f_send_messages))); }
uint16_t Artnetnode::handleDMX(){ if(isBroadcast()){ return 0; } else{ // Get universe uint16_t universe = artnetPacket[14] | artnetPacket[15] << 8; // Get DMX frame length uint16_t dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8; for(int a = 0; a < DMX_MAX_OUTPUTS; a++){ if(DMXOutputs[a][1] == universe){ for (int i = 0 ; i < DMX_MAX_BUFFER ; i++){ if(i < dmxDataLength){ DMXBuffer[a][i] = artnetPacket[i+ARTNET_DMX_START_LOC]; } else{ DMXBuffer[a][i] = 0; } } } } return OpDmx; } }
uint16_t Artnetnode::handlePollRequest(){ if(isBroadcast()){ Udp.beginPacket(localBroadcast, ARTNET_PORT); Udp.write(PollReplyPacket.printPacket(), sizeof(PollReplyPacket.packet)); Udp.endPacket(); return OpPoll; } else{ return 0; } }
// get response with timeout -ignoring int OMMoCoMaster::_getResponse() { // if we sent a broadcast packet, do not look for a response if( isBroadcast() == true ) return(1); unsigned long cur_tm = millis(); // timeout if we don't get a response packet in // time uint8_t code = getPacket(); while (code == 0) { if (millis() - cur_tm > OM_SER_MASTER_TIMEOUT) return -1; code = getPacket(); } return code; }
bool Nequeo::Net::Sockets::IPAddress::isUnicast() const { return !isWildcard() && !isBroadcast() && !isMulticast(); }
bool IPAddress::isUnicast() const { return !isWildcard() && !isBroadcast() && !isMulticast(); }
void rxpacket(int sock) { Packet pkt; memset(&pkt, 0, sizeof(pkt)); // using recvmsg int size; // size of the received data struct msghdr msg; memset(&msg, 0, sizeof(msg)); struct sockaddr_in from; int fromlen=sizeof(from); msg.msg_name = &from; msg.msg_namelen = fromlen; char anciliary[2048]; msg.msg_control = anciliary; msg.msg_controllen = sizeof(anciliary); struct iovec iov[1]; memset(iov, 0, sizeof(iov)); iov[0].iov_base = &pkt.data; iov[0].iov_len = sizeof(pkt.data); msg.msg_iov = iov; msg.msg_iovlen = 1; struct cmsghdr *cmsg; unsigned int ifindex; // interface index struct in_addr hdraddr; // destination IP address in IP header size = recvmsg(sock, &msg, 0); if (size == -1) { ASSERT(0); rcpLog(muxsock, RCP_PROC_RIP, RLOG_ERR, RLOG_FC_RIP, "cannot read data on socket, attempting recovery..."); exit(1); } // verify packet size int sz = size - 4; if (sz<= 0 || (sz % sizeof(RipRoute)) != 0) { rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "Invalid RIP packet size"); return; } int routes = sz / sizeof(RipRoute); int found = 0; for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) { // struct in_pktinfo { // unsigned int ipi_ifindex; /* Interface index */ // struct in_addr ipi_spec_dst; /* Local address */ // struct in_addr ipi_addr; /* Header Destination // address */ // }; hdraddr = ((struct in_pktinfo*)CMSG_DATA(cmsg))->ipi_addr; ifindex = ((struct in_pktinfo*)CMSG_DATA(cmsg))->ipi_ifindex; found = 1; } } if (!found) return; pkt.ip_source = ntohl(from.sin_addr.s_addr); pkt.ip_dest = ntohl(hdraddr.s_addr); pkt.if_index = ifindex; // is the source ip address one of our addresses? RcpInterface *rxif = rcpFindInterface(shm, pkt.ip_source); if (rxif) { // on Linux, packets we send to the multicast group will be received back on the socket return; } char *cmd[] = {"", "request", "response"}; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "Receiving RIP packet of size %d, from %d.%d.%d.%d, destination %d.%d.%d.%d, RIP %s, protocol version %d", size, RCP_PRINT_IP(pkt.ip_source), RCP_PRINT_IP(pkt.ip_dest), cmd[(pkt.data.command <= 2) ? pkt.data.command: 0], pkt.data.version); // update neighbor list RipNeighbor *neigh = neighbors; while (neigh != NULL) { if (neigh->ip == pkt.ip_source) { neigh->rx_time = 0; break; } neigh = neigh->next; } if (neigh == NULL) { RipNeighbor *newneigh = malloc(sizeof(RipNeighbor)); if (newneigh != NULL) { memset(newneigh, 0, sizeof(RipNeighbor)); newneigh->ip = pkt.ip_source; newneigh->next = neighbors; neighbors = newneigh; neigh = newneigh; } else { ASSERT(0); rcpLog(muxsock, RCP_PROC_RIP, RLOG_ERR, RLOG_FC_RIP, "cannot allocate memory, attempting recovery..."); exit(1); } } // do we have a valid interface? rxif =rcpFindInterfaceByKIndex(shm, pkt.if_index); if (rxif == NULL) { neigh->errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid interface, dropping..."); return; } // do we have a configured neighbor? RcpRipPartner *rxnetwork = NULL; RcpRipPartner *net; int i; for (i = 0, net = shm->config.rip_neighbor; i < RCP_RIP_NEIGHBOR_LIMIT; i++, net++) { if (!net->valid) continue; // matching both source and destination addresses if (net->ip == pkt.ip_source && rxif->ip == pkt.ip_dest) { rxnetwork = net; break; } } // if no configured neighbor was found, try to find a configured network if (rxnetwork == NULL) rxnetwork = find_network_for_interface(rxif); // no network or neighbor configured, just drop the packet if (rxnetwork == NULL) { neigh->errors++; // the network can get disabled while receiving packets rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid network or neighbor, dropping..."); return; } // the source of the datagram must be on a directly-connected network if ((pkt.ip_source & rxif->mask) != (rxif->ip & rxif->mask)) { neigh->errors++; // interface ip addresses are changing dynamically via CLI rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid source IP address, dropping..."); return; } // drop invalid command packets if (pkt.data.command > 2) { neigh->errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid RIP command, dropping..."); return; } if (pkt.data.command == 1) { rxnetwork->req_rx++; // force a response in one second rxif->rip_timeout = 1; return; } else rxnetwork->resp_rx++; ASSERT(sizeof(RipAuthMd5) == sizeof(RipAuthSimple)); ASSERT(sizeof(RipAuthSimple) == sizeof(RipRoute)); RipRoute *ptr = &pkt.data.routes[0]; int rt = 0; // if md5 auth configured, and the packet is missing the auth header, drop the packet if (rxif->rip_passwd[0] != '\0') { if (ptr->family != 0xffff || ntohs(ptr->tag) != 3) { neigh->md5_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " missing MD5 authentication header"); return; } } // checking auth header and calculate md5 if (ptr->family == 0xffff) { // we don't care about simple auth if (ntohs(ptr->tag) == 3 && rxif->rip_passwd[0] != '\0') { RipAuthMd5 *md5 = (RipAuthMd5 *) ptr; uint16_t offset = ntohs(md5->offset); uint32_t seq = ntohl(md5->seq); rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " MD5 auth offset %u, key id %d, auth_len %d, seq %u", offset, md5->key_id, md5->auth_len, ntohl(md5->seq)); // check offset if ((offset + sizeof(RipRoute)) != size) { neigh->md5_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid offset"); return; } // check seq if (seq != 0 && seq < neigh->auth_seq) { neigh->md5_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid sequence number"); return; } neigh->auth_seq = seq; // calculate md5 uint8_t secret[16]; memset(secret, 0, 16); memcpy(secret, rxif->rip_passwd, strlen(rxif->rip_passwd)); MD5_CTX context; uint8_t digest[16]; MD5Init (&context); MD5Update (&context, (uint8_t *) &pkt, size - 16); MD5Update (&context, secret, 16); MD5Final (digest, &context); #if 0 { int i; uint8_t *p = digest; printf("rx digest:\n"); for (i = 0; i < 16; i++,p++) printf("%02x ", *p); printf("\n"); } #endif // compare md5 if (memcmp((uint8_t *) ptr + offset, digest, 16) != 0) { neigh->md5_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid MD5 digest"); return; } } ptr++; rt++; routes--; // the last route is the digest } // parsing routes while (rt < routes) { uint32_t metric = ntohl(ptr->metric); uint32_t mask = ntohl(ptr->mask); uint32_t ip = ntohl(ptr->ip); uint32_t gw = ntohl(ptr->gw); // if (trace_prefix == 0 || // (trace_prefix != 0 && trace_prefix == ip)) { // if (gw == 0) // rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, // " %d.%d.%d.%d/%d metric %u", // RCP_PRINT_IP(ip), // mask2bits(mask), // metric); // else // rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, // " %d.%d.%d.%d/%d metric %u next hop %d.%d.%d.%d", // RCP_PRINT_IP(ip), // mask2bits(mask), // metric, // RCP_PRINT_IP(gw)); // } // only AF_INET family is supported if (ntohs(ptr->family) != AF_INET) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid route family"); goto next_element; } // check destination for loopback addresses if (isLoopback(ip)) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid loopback route prefix"); goto next_element; } // check destination for broadcast addresses if (isBroadcast(ip)) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid broadcast route prefix"); goto next_element; } // check destination for multicast addresses if (isMulticast(ip)) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid multicast route prefix"); goto next_element; } // validate route metric else if (metric > 16 || metric == 0) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid metric"); goto next_element; } // validate route entry if (ip == 0 && mask == 0) { rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " received default route metric %d", metric); } else if (pkt.data.version == 2 && mask == 0) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid RIP route"); goto next_element; } else if (pkt.data.version == 1 && mask != 0) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid RIP route"); goto next_element; } // check if the mask is contiguous if (mask != 0 && !maskContiguous(mask)) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid mask"); goto next_element; } // validate next hop if (gw) { if (isLoopback(gw) || isMulticast(gw) || isBroadcast(gw)) { neigh->route_errors++; rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, " invalid next hop"); goto next_element; } } // manufacture mask for rip v1 if (pkt.data.version == 1) mask = classMask(ip); // RFC metric = metric + interface cost // we assume a cost of 1 for each interface metric++; // add the route in the database if (metric < 16) { //RFC //- Setting the destination address to the destination address in the // RTE // // - Setting the metric to the newly calculated metric (as described // above) // // - Set the next hop address to be the address of the router from which // the datagram came // // - Initialize the timeout for the route. If the garbage-collection // timer is running for this route, stop it (see section 3.6 for a // discussion of the timers) // // - Set the route change flag // // - Signal the output process to trigger an update (see section 3.8.1) // a next hop of 0 means send the packets to me if (gw == 0) gw = pkt.ip_source; ripdb_add(RCP_ROUTE_RIP, ip, mask, gw, metric, pkt.ip_source, rxif); } else { // a next hop of 0 means send the packets to me if (gw == 0) gw = pkt.ip_source; ripdb_delete(RCP_ROUTE_RIP, ip, mask, gw, pkt.ip_source); } next_element: ptr++; rt++; } }
bool IPEndpoint::V4::isPublic () const { return !isPrivate() && !isBroadcast() && !isMulticast(); }
RoutingDecision_e routePacket(MacInfo_t *info) { MosAddr *dst = &info->originalDst; // PRINTF("route: dst address=0x%04x, nexthop=0x%04x\n", dst->shortAddr, info->immedDst.shortAddr); // PRINTF(" localAddress=0x%04x\n", localAddress); if (IS_LOCAL(info)) { // fix root address if we are sending it to the root if (dst->shortAddr == MOS_ADDR_ROOT) { intToAddr(info->originalDst, rootAddress); // info->hoplimit = hopCountToRoot; info->hoplimit = MAX_HOP_COUNT; } } else { // PRINTF("route packet, addr=0x%04x port=%02x\n", dst->shortAddr, info->dstPort); uint8_t index = markAsSeen(info->immedSrc.shortAddr, false); if (index != 0xff) { uint32_t expectedTimeStart = 4000ul + MOTE_TIME_FULL * index + MOTE_TIME + (IS_ODD_COLLECTOR ? MOTE_TIME_FULL * MAX_MOTES : 0); uint32_t expectedTimeEnd = expectedTimeStart + MOTE_TIME; uint32_t now = timeSinceFrameStart(); if (now < expectedTimeStart || now > expectedTimeEnd) { TPRINTF("*** mote %#04x sends out of its time: expected at %lu (+0-512 ms), now %lu!\n", motes[index].address, expectedTimeStart, now); } } else { if (timeSinceFrameStart() > 4000) { TPRINTF("*** unregistered sender!\n"); } } } if (isLocalAddress(dst)) { INC_NETSTAT(NETSTAT_PACKETS_RECV, info->originalSrc.shortAddr); return RD_LOCAL; } if (isBroadcast(dst)) { fillLocalAddress(&info->immedSrc); // XXX if (!IS_LOCAL(info)){ INC_NETSTAT(NETSTAT_PACKETS_RECV, info->originalSrc.shortAddr); } // don't forward broadcast packets return IS_LOCAL(info) ? RD_BROADCAST : RD_LOCAL; } // check if hop limit allows the packet to be forwarded if (!checkHoplimit(info)) { PRINTF("hoplimit reached!\n"); return RD_DROP; } // fill address: may forward it fillLocalAddress(&info->immedSrc); if (dst->shortAddr == rootAddress) { if (isRoutingInfoValid()) { //PRINTF("using 0x%04x as nexthop to root\n", nexthopToRoot); if (!IS_LOCAL(info)) { #if PRECONFIGURED_NH_TO_ROOT if (info->immedDst.shortAddr != localAddress) { TPRINTF("Dropping, I'm not a nexthop for sender %#04x\n", info->originalSrc.shortAddr); INC_NETSTAT(NETSTAT_PACKETS_DROPPED_RX, EMPTY_ADDR); return RD_DROP; } #endif // if (info->hoplimit < hopCountToRoot){ // PRINTF("Dropping, can't reach host with left hopCounts\n"); // return RD_DROP; // } TPRINTF("****** Forwarding a packet to root for %#04x!\n", info->originalSrc.shortAddr); INC_NETSTAT(NETSTAT_PACKETS_FWD, nexthopToRoot); // delay a bit info->timeWhenSend = getSyncTimeMs() + randomNumberBounded(150); } else{ //INC_NETSTAT(NETSTAT_PACKETS_SENT, nexthopToRoot); // Done @ comm.c } info->immedDst.shortAddr = nexthopToRoot; return RD_UNICAST; } else { // PRINTF("root routing info not present or expired!\n"); TPRINTF("DROP\n"); return RD_DROP; } } if (IS_LOCAL(info)) { //INC_NETSTAT(NETSTAT_PACKETS_SENT, dst->shortAddr); // Done @ comm.c // send out even with an unknown nexthop, makes sense? return RD_UNICAST; } return RD_DROP; }