// try connecting using the buf as the address char *try_address(char *d, char *buf, char *uq) { char *r = NULL; r = try_broadcast(d, buf, uq); if (r == NULL) { print_failed_address(); } return r; }
// if externalhost is found matching a hostname, // try connecting to this address char *try_external(char *d, char *buf, char *uq) { char *r = NULL; if (d && strcmp(d, na) != 0) { r = try_broadcast(d, buf, uq); if (r == NULL) { print_try_address(); } else { return r; } } else { print_failed_external(); } return r; }
/** Examine a datagram and determine what to do with it. * */ static int process_udp( n2n_sn_t * sss, const struct sockaddr_in * sender_sock, const uint8_t * udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; macstr_t mac_buf2; n2n_sock_str_t sockbuf; traceEvent( TRACE_DEBUG, "process_udp(%lu)", udp_size ); /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK * * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their * destination edge. If the destination is not known then PACKETs are * broadcast. */ rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ idx = 0; /* marches through packet header as parts are decoded. */ if ( decode_common(&cmn, udp_buf, &rem, &idx) < 0 ) { traceEvent( TRACE_ERROR, "Failed to decode common section" ); return -1; /* failed to decode packet */ } msg_type = cmn.pc; /* packet code */ from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if ( cmn.ttl < 1 ) { traceEvent( TRACE_WARNING, "Expired TTL" ); return 0; /* Don't process further */ } --(cmn.ttl); /* The value copied into all forwarded packets. */ if ( msg_type == MSG_TYPE_PACKET ) { /* PACKET from one edge to another edge via supernode. */ /* pkt will be modified in place and recoded to an output of potentially * different size due to addition of the socket.*/ n2n_PACKET_t pkt; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ const uint8_t * rec_buf; /* either udp_buf or encbuf */ sss->stats.last_fwd=now; decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); unicast = (0 == is_multi_broadcast(pkt.dstMac) ); traceEvent( TRACE_DEBUG, "Rx PACKET (%s) %s -> %s %s", (unicast?"unicast":"multicast"), macaddr_str( mac_buf, pkt.srcMac ), macaddr_str( mac_buf2, pkt.dstMac ), (from_supernode?"from sn":"local") ); if ( !from_supernode ) { memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; pkt.sock.family = AF_INET; pkt.sock.port = ntohs(sender_sock->sin_port); memcpy( pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); rec_buf = encbuf; /* Re-encode the header. */ encode_PACKET( encbuf, &encx, &cmn2, &pkt ); /* Copy the original payload unchanged */ encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ traceEvent( TRACE_DEBUG, "Rx PACKET fwd unmodified" ); rec_buf = udp_buf; encx = udp_size; } /* Common section to forward the final product. */ if ( unicast ) { try_forward( sss, &cmn, pkt.dstMac, rec_buf, encx ); } else { try_broadcast( sss, &cmn, pkt.srcMac, rec_buf, encx ); } }/* MSG_TYPE_PACKET */ else if ( msg_type == MSG_TYPE_REGISTER ) { /* Forwarding a REGISTER from one edge to the next */ n2n_REGISTER_t reg; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ const uint8_t * rec_buf; /* either udp_buf or encbuf */ sss->stats.last_fwd=now; decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); unicast = (0 == is_multi_broadcast(reg.dstMac) ); if ( unicast ) { traceEvent( TRACE_DEBUG, "Rx REGISTER %s -> %s %s", macaddr_str( mac_buf, reg.srcMac ), macaddr_str( mac_buf2, reg.dstMac ), ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local") ); if ( 0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ) { memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; reg.sock.family = AF_INET; reg.sock.port = ntohs(sender_sock->sin_port); memcpy( reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); rec_buf = encbuf; /* Re-encode the header. */ encode_REGISTER( encbuf, &encx, &cmn2, ® ); /* Copy the original payload unchanged */ encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ rec_buf = udp_buf; encx = udp_size; } try_forward( sss, &cmn, reg.dstMac, rec_buf, encx ); /* unicast only */ } else { traceEvent( TRACE_ERROR, "Rx REGISTER with multicast destination" ); } } else if ( msg_type == MSG_TYPE_REGISTER_ACK ) { traceEvent( TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode" ); } else if ( msg_type == MSG_TYPE_REGISTER_SUPER ) { n2n_REGISTER_SUPER_t reg; n2n_REGISTER_SUPER_ACK_t ack; n2n_common_t cmn2; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; /* Edge requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER( ®, &cmn, udp_buf, &rem, &idx ); cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_register_super_ack; cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); memcpy( &(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t) ); memcpy( ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t) ); ack.lifetime = reg_lifetime( sss ); ack.sock.family = AF_INET; ack.sock.port = ntohs(sender_sock->sin_port); memcpy( ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); ack.num_sn=0; /* No backup */ memset( &(ack.sn_bak), 0, sizeof(n2n_sock_t) ); traceEvent( TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", macaddr_str( mac_buf, reg.edgeMac ), sock_to_cstr( sockbuf, &(ack.sock) ) ); update_edge( sss, reg.edgeMac, cmn.community, &(ack.sock), now ); #ifdef N2N_MULTIPLE_SUPERNODES { struct comm_info *ci = comm_find(sss->communities.list_head, cmn.community, strlen((const char *) cmn.community)); if (ci) { ack.num_sn = ci->sn_num; memcpy(&ack.sn_bak, ci->sn_sock, ci->sn_num * sizeof(n2n_sock_t)); } } #endif encode_REGISTER_SUPER_ACK( ackbuf, &encx, &cmn2, &ack ); sendto( sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", macaddr_str( mac_buf, reg.edgeMac ), sock_to_cstr( sockbuf, &(ack.sock) ) ); } return 0; }