int listall_node(json_t *jmsg) { char *uuid; char *network_uuid; char *response; size_t array_size; size_t i; static size_t total = 1; json_t *js_nodes; json_t *node; struct vnetwork *vnet; if ((js_nodes = json_object_get(jmsg, "nodes")) == NULL) { jlog(L_ERROR, "json_object_get failed"); return -1; } if ((array_size = json_array_size(js_nodes)) == 0) { jlog(L_ERROR, "json_array_size failed"); return -1; } for (i = 0; i < array_size; i++) { if ((node = json_array_get(js_nodes, i)) == NULL) { jlog(L_ERROR, "json_array_get failed"); return -1; } if (json_unpack(node, "{s:s}", "uuid", &uuid) == -1 || json_unpack(node, "{s:s}", "networkuuid", &network_uuid) == -1) { jlog(L_ERROR, "NULL parameter"); return -1; } if ((vnet = vnetwork_lookup(network_uuid)) != NULL) { ctable_insert(vnet->atable, uuid, vnet->access_session); } } if ((json_unpack(jmsg, "{s:s}", "response", &response)) == -1) { jlog(L_ERROR, "json_unpack failed"); return -1; } if (strcmp(response, "success") == 0) { jlog(L_DEBUG, "fetched %d node", total); return 0; } total++; return 1; }
RpcConnection rpc_connect(char *host, unsigned short port, char *svcName, unsigned long seqno) { ConnectPayload *buf; RpcEndpoint *nep; int len = sizeof(PayloadHeader) + 1; /* room for '\0' */ CRecord *cr; unsigned long subport; unsigned long states[2] = {ST_IDLE, ST_TIMEDOUT}; unsigned long id = 0; ctable_lock(); subport = ctable_newSubport(); nep = rpc_socket(host, port, subport); if (nep != NULL) { id = gen_conn_id(); len += strlen(svcName); /* room for svcName */ buf = (ConnectPayload *)malloc(len); cp_complete((ControlPayload *)buf, nep->subport, CONNECT, seqno, 1, 1); strcpy(buf->sname, svcName); cr = crecord_create(nep, seqno); crecord_setCID(cr, id); crecord_setPayload(cr, buf, len, ATTEMPTS, TICKS); #ifdef LOG dumpsockNpacket(&(nep->addr), (DataPayload *)buf, "rpc_connect"); #endif /* LOG */ (void) send_payload(nep, buf, len); crecord_setState(cr, ST_CONNECT_SENT); ctable_insert(cr); if (crecord_waitForState(cr, states, 2) == ST_TIMEDOUT) { ctable_remove(cr); crecord_destroy(cr); id = 0; } ctable_unlock(); } return (RpcConnection)id; }
/* Authentication Request from the node */ int authRequest(struct session *session, DNDSMessage_t *req_msg) { char *certName = NULL; size_t length = 0; struct session *old_session = NULL; if (session->state != SESSION_STATE_NOT_AUTHED) { jlog(L_WARNING, "authRequest duplicate"); return -1; } DNDSMessage_t *msg = NULL; DNDSMessage_new(&msg); DNDSMessage_set_channel(msg, 0); DNDSMessage_set_pdu(msg, pdu_PR_dnm); DNMessage_set_seqNumber(msg, 1); DNMessage_set_ackNumber(msg, 0); DNMessage_set_operation(msg, dnop_PR_authResponse); AuthRequest_get_certName(req_msg, &certName, &length); jlog(L_DEBUG, "URI:%s", certName); session->node_info = cn2node_info(certName); if (session->node_info == NULL) { jlog(L_WARNING, "cn2node_info failed"); DNDSMessage_del(msg); return -1; } // jlog(L_DEBUG, "type: %s", session->node_info->type); jlog(L_DEBUG, "uuid: %s", session->node_info->uuid); jlog(L_DEBUG, "network_uuid: %s", session->node_info->network_uuid); jlog(L_DEBUG, "network_id: %s", session->node_info->network_id); jlog(L_DEBUG, "v: %d", session->node_info->v); if (session->node_info->v == 1) { session->vnetwork = vnetwork_lookup_id(session->node_info->network_id); if (session->vnetwork != NULL) { strncpy(session->node_info->network_uuid, session->vnetwork->uuid, 36); session->node_info->network_uuid[36] = '\0'; } } else session->vnetwork = vnetwork_lookup(session->node_info->network_uuid); if (session->vnetwork == NULL) { AuthResponse_set_result(msg, DNDSResult_noRight); net_send_msg(session->netc, msg); DNDSMessage_del(msg); return -1; } /* check if the node's uuid is known if (ctable_find(session->context->atable, session->node_info->uuid) == NULL) { AuthResponse_set_result(msg, DNDSResult_noRight); net_send_msg(session->netc, msg); DNDSMessage_del(msg); jlog(L_ERROR, "authentication failed, invalid certificate"); return -1; } */ /* check if the node is already connected */ old_session = ctable_find(session->vnetwork->ctable, session->node_info->uuid); // if (old_session == NULL) { ctable_insert(session->vnetwork->ctable, session->node_info->uuid, session); /* } else { // that node is already connected, if the new session is from the same IP // disconnect the old session, and let this one connect if (old_session->ip == NULL) { net_disconnect(old_session->netc); ctable_insert(session->vnetwork->ctable, session->node_info->uuid, session); } else if (strcmp(old_session->ip, session->ip) == 0) { net_disconnect(old_session->netc); ctable_insert(session->vnetwork->ctable, session->node_info->uuid, session); } } */ session->cert_name = strdup(certName); if (session->netc->security_level == NET_UNSECURE) { AuthResponse_set_result(msg, DNDSResult_success); net_send_msg(session->netc, msg); session->state = SESSION_STATE_AUTHED; session->netc->on_secure(session->netc); } else { AuthResponse_set_result(msg, DNDSResult_secureStepUp); net_send_msg(session->netc, msg); krypt_add_passport(session->netc->kconn, session->vnetwork->passport); session->state = SESSION_STATE_WAIT_STEPUP; net_step_up(session->netc); } DNDSMessage_del(msg); return 0; }
/* continuously reads messages from UDP port */ static void *reader(UNUSED void *args) { DataPayload *dp; char buf[10240]; struct sockaddr_in c_addr; socklen_t len; int n; debugf("reader thread started\n"); for(;;) { unsigned short cmd; unsigned long sb; unsigned long seqno; unsigned char fnum; unsigned char nfrags; char *sp; unsigned short pt; RpcEndpoint ep; CRecord *cr; len = sizeof(c_addr); memset(&c_addr, 0, len); n = recvfrom(my_sock, buf, sizeof(buf), 0, (struct sockaddr *)&c_addr, &len); if (n < 0) continue; buf[n] = '\0'; dp = (DataPayload *)buf; cmd = ntohs(dp->hdr.command); sb = ntohl(dp->hdr.subport); seqno = ntohl(dp->hdr.seqno); fnum = dp->hdr.fnum; nfrags = dp->hdr.nfrags; sp = inet_ntoa(c_addr.sin_addr); pt = ntohs(c_addr.sin_port); if (cmd >= CMD_LOW && cmd <= CMD_HIGH) { logf("%s from %s:%05u:%08lx; seqno = %ld, frag/nfrag = %u/%u\n", cmdnames[cmd], sp, pt, sb, seqno, fnum, nfrags); } else { errorf("Illegal command received: %d\n", cmd); continue; } endpoint_complete(&ep, &c_addr, sb); ctable_lock(); cr = ctable_look_ep(&ep); switch (cmd) { case CONNECT: { RpcEndpoint *nep; ConnectPayload *conp = (ConnectPayload *)dp; ControlPayload *p; int newcr = 0; SRecord *sr; sr = stable_lookup(conp->sname); if (sr == NULL) break; if (cr == NULL) { nep = endpoint_duplicate(&ep); cr = crecord_create(nep, seqno); crecord_setCID(cr, gen_conn_id()); newcr = 1; } else if (cr->state != ST_IDLE) { fprintf(stderr, "%s from %s:%05u:%08lx; seqno = %ld, frag/nfrag = %u/%u\n", cmdnames[cmd], sp, pt, sb, seqno, fnum, nfrags); crecord_dump(cr, "connectrqst"); } if (newcr || cr->state == ST_IDLE) { if (newcr) { p = (ControlPayload *)malloc(CP_SIZE); cp_complete(p, nep->subport, CACK, seqno, 1, 1); crecord_setPayload(cr, p, CP_SIZE, ATTEMPTS, TICKS); } crecord_setService(cr, sr); (void) send_payload(cr->ep, cr->pl, cr->size); crecord_setState(cr, ST_IDLE); } if (newcr) ctable_insert(cr); break; } case CACK: { if ((cr != NULL)) { if (seqno == cr->seqno) crecord_setState(cr, ST_IDLE); } break; } #define NEW 2 #define OLD 1 #define ILL 0 case QUERY: { DataPayload *p = NULL; ControlPayload *cp = NULL; int dplen, cplen; unsigned long state; int accept = ILL; if (cr == NULL) break; state = cr->state; if ((seqno - cr->seqno) == 1 && (state == ST_IDLE || state == ST_RESPONSE_SENT)) { accept = NEW; cr->seqno = seqno; p = (DataPayload *)malloc(n); dplen = n; memcpy(p, buf, n); } else if (seqno == cr->seqno && state == ST_FACK_SENT && (fnum - cr->lastFrag) == 1 && fnum == nfrags) { void *tp; unsigned short flen = ntohs(dp->dhdr.flen); accept = NEW; p = (DataPayload *)cr->resp; dplen = sizeof(PayloadHeader) + sizeof(DataHeader) + ntohs(dp->dhdr.tlen); cr->resp = NULL; tp = (void *)&(p->data[FR_SIZE * (fnum - 1)]); memcpy(tp, dp->data, flen); } else if (seqno == cr->seqno && (state == ST_QACK_SENT || state == ST_RESPONSE_SENT)) { accept = OLD; } switch (accept) { case NEW: cplen = CP_SIZE; cp = (ControlPayload *)malloc(cplen); cp_complete(cp, ep.subport, QACK, seqno, fnum, nfrags); crecord_setPayload(cr, cp, cplen, ATTEMPTS, TICKS); (void)send_payload(cr->ep, cp, cplen); tsl_append(cr->svc->s_queue, cr->ep, p, dplen); crecord_setState(cr, ST_QACK_SENT); break; case OLD: (void)send_payload(cr->ep, cr->pl, cr->size); crecord_setState(cr, state); break; case ILL: break; } break; } case QACK: { if (cr != NULL) { if (seqno == cr->seqno) crecord_setState(cr, ST_AWAITING_RESPONSE); } break; } case RESPONSE: { DataPayload *p = NULL; ControlPayload *cp = NULL; int cplen; unsigned long st; unsigned short flen = ntohs(dp->dhdr.flen); if (cr == NULL || seqno != cr->seqno) break; st = cr->state; if (st == ST_QUERY_SENT || st == ST_AWAITING_RESPONSE) { p = (DataPayload *)malloc(n); memcpy(p, buf, n); cr->resp = p; } else if (st == ST_FACK_SENT && (fnum - cr->lastFrag) == 1 && fnum == nfrags) { p = (DataPayload *)cr->resp; memcpy(&(p->data[FR_SIZE * (fnum -1)]), dp->data, flen); cr->lastFrag = fnum; } else break; cplen = CP_SIZE; cp = (ControlPayload *)malloc(cplen); cp_complete(cp, ep.subport, RACK, seqno, fnum, nfrags); crecord_setPayload(cr, cp, cplen, ATTEMPTS, TICKS); (void)send_payload(cr->ep, cp, cplen); crecord_setState(cr, ST_IDLE); break; } case RACK: { if (cr != NULL) { if (seqno == cr->seqno) crecord_setState(cr, ST_IDLE); } break; } case DISCONNECT: { ControlPayload cp; /* always send a DACK */ cp_complete(&cp, ep.subport, DACK, seqno, 1, 1); (void)send_payload(&ep, &cp, CP_SIZE); if (cr != NULL) { crecord_setState(cr, ST_TIMEDOUT); } break; } case DACK: { if (cr != NULL) { if (seqno == cr->seqno) crecord_setState(cr, ST_TIMEDOUT); } break; } case FRAGMENT: { DataPayload *p = NULL; ControlPayload *cp = NULL; int dplen, cplen; unsigned long st; int accept = ILL; unsigned short tlen = ntohs(dp->dhdr.tlen); unsigned short flen = ntohs(dp->dhdr.flen); int isQ, isR; if (cr == NULL) break; st = cr->state; isQ = (st == ST_IDLE || st == ST_RESPONSE_SENT) && (seqno - cr->seqno) == 1 && fnum == 1; isR = (st == ST_QUERY_SENT || st == ST_AWAITING_RESPONSE) && seqno == cr->seqno && fnum == 1; if (isQ || isR) { accept = NEW; cr->seqno = seqno; dplen = sizeof(PayloadHeader) + sizeof(DataHeader) + tlen; cr->resp = malloc(dplen); p = (DataPayload *)cr->resp; memcpy(p, buf, n); } else if (seqno == cr->seqno && st == ST_FACK_SENT && (fnum - cr->lastFrag) == 1) { void *tp; accept = NEW; p = (DataPayload *)cr->resp; tp = (void *)&(p->data[FR_SIZE * (fnum - 1)]); memcpy(tp, dp->data, flen); } else if (seqno == cr->seqno && st == ST_FACK_SENT && fnum == cr->lastFrag) { accept = OLD; } switch (accept) { case NEW: cr->lastFrag = fnum; cplen = CP_SIZE; cp = (ControlPayload *)malloc(cplen); cp_complete(cp, ep.subport, FACK, seqno, fnum, nfrags); crecord_setPayload(cr, cp, cplen, ATTEMPTS, TICKS); (void)send_payload(cr->ep, cp, cplen); crecord_setState(cr, ST_FACK_SENT); break; case OLD: (void)send_payload(cr->ep, cr->pl, cr->size); crecord_setState(cr, st); break; case ILL: break; } break; } case FACK: { if (cr != NULL) { if (seqno == cr->seqno && cr->state == ST_FRAGMENT_SENT && fnum == cr->lastFrag) { crecord_setState(cr, ST_FACK_RECEIVED); } } break; } case PING: { ControlPayload cp; if (cr != NULL) { cp_complete(&cp, ep.subport, PACK, seqno, 1, 1); (void)send_payload(&ep, &cp, CP_SIZE); } break; } case PACK: { if (cr != NULL) { crecord_setState(cr, cr->state); /* resets ping data */ } break; } case SEQNO: { ControlPayload *cp; if (cr != NULL) { unsigned long st = cr->state; if (st == ST_IDLE || st == ST_RESPONSE_SENT) { cp = (ControlPayload *)malloc(CP_SIZE); cp_complete(cp, ep.subport, SACK, seqno, 1, 1); crecord_setPayload(cr, cp, CP_SIZE, ATTEMPTS, TICKS); (void)send_payload(cr->ep, cp, CP_SIZE); cr->seqno = seqno; crecord_setState(cr, ST_IDLE); } } break; } case SACK: { if (cr != NULL && cr->state == ST_SEQNO_SENT) { crecord_setState(cr, ST_IDLE); } break; } default: { break; } } ctable_unlock(); } return NULL; }