/* * Execute nsupdate.pl with IP and HIT given as environment variables */ int run_nsupdate(char *ips, char *hit, int start) { struct sigaction act; pid_t child_pid; HIP_DEBUG("Updating dns records...\n"); act.sa_handler = sig_chld; /* We don't want to block any other signals */ sigemptyset(&act.sa_mask); /* * We're only interested in children that have terminated, not ones * which have been stopped (eg user pressing control-Z at terminal) */ act.sa_flags = SA_NOCLDSTOP | SA_RESTART; /* Make the handler effective */ if (sigaction(SIGCHLD, &act, NULL) < 0) { HIP_PERROR("sigaction"); return ERR; } /* Let us fork to execute nsupdate as a separate process */ child_pid=fork(); if (child_pid<0) { HIP_PERROR("fork"); return ERR; } else if (child_pid == 0) {// CHILD char start_str[2]; #if 0 /* Close open sockets since FD_CLOEXEC was not used */ close_all_fds_except_stdout_and_stderr(); #endif snprintf(start_str, sizeof(start_str), "%i", start); char *env_ips = make_env(VAR_IPS, ips); char *env_hit = make_env(VAR_HIT, hit); char *env_start = make_env(VAR_START, start_str); char *cmd[] = { NSUPDATE_ARG0, NULL }; char *env[] = { env_ips, env_hit, env_start, NULL }; HIP_DEBUG("Executing %s with %s; %s; %s\n", NSUPDATE_PL, env_hit, env_ips, env_start); execve (NSUPDATE_PL, cmd, env); /* Executed only if error */ HIP_PERROR("execve"); exit(1); // just in case } else {// PARENT /* We execute waitpid in SIGCHLD handler */ return OK; } }
/** * tell firewall to turn on or off the ESP relay mode * * @param action HIP_MSG_OFFER_FULLRELAY or HIP_MSG_CANCEL_FULLRELAY * * @return zero on success or negative on failure */ int hip_firewall_set_esp_relay(int action) { struct hip_common *msg = NULL; int err = 0; int sent; HIP_DEBUG("Setting ESP relay to %d\n", action); if (!(msg = hip_msg_alloc())) { return -ENOMEM; } HIP_IFEL(hip_build_user_hdr(msg, action ? HIP_MSG_OFFER_FULLRELAY : HIP_MSG_CANCEL_FULLRELAY, 0), -1, "Build header failed\n"); sent = hip_sendto_firewall(msg); if (sent < 0) { HIP_PERROR("Send to firewall failed: "); err = -1; goto out_err; } HIP_DEBUG("Sent %d bytes to firewall.\n", sent); out_err: free(msg); return err; }
int hip_read_user_control_msg(int socket, struct hip_common *hip_msg, struct sockaddr_in6 *saddr) { int err = 0, bytes, hdr_size = sizeof(struct hip_common), total; socklen_t len; memset(saddr, 0, sizeof(*saddr)); len = sizeof(*saddr); HIP_IFEL(((total = hip_peek_recv_total_len(socket, 0, HIP_DEFAULT_MSG_TIMEOUT)) <= 0), -1, "recv peek failed\n"); _HIP_DEBUG("msg total length = %d\n", total); /** @todo Compiler warning; warning: pointer targets in passing argument 6 of 'recvfrom' differ in signedness. */ HIP_IFEL(((bytes = recvfrom(socket, hip_msg, total, 0, (struct sockaddr *) saddr, &len)) != total), -1, "recv\n"); HIP_DEBUG("received user message from local port %d\n", ntohs(saddr->sin6_port)); _HIP_DEBUG("read_user_control_msg recv len=%d\n", len); _HIP_HEXDUMP("recv saddr ", saddr, sizeof(struct sockaddr_un)); _HIP_DEBUG("read %d bytes succesfully\n", bytes); out_err: if (bytes < 0 || err) HIP_PERROR("perror: "); return err; }
/* * Called from hip_for_each_hi */ int run_nsupdate_for_hit (struct hip_host_id_entry *entry, void *opaq) { int start = 0; char ip_str[40]; // buffer for one IP address char ips_str[1024] = ""; // list of IP addresses hip_list_t *item, *tmp_hip_list_t; int i; char hit[INET6_ADDRSTRLEN + 2]; if (opaq != NULL) start = * (int *) opaq; HIP_DEBUG("run_nsupdate_for_hit (start=%d)\n", start); hip_convert_hit_to_str(&entry->lhi.hit,NULL, hit); /* make space-separated list of IP addresses in ips_str */ list_for_each_safe(item, tmp_hip_list_t, addresses, i) { struct netdev_address *n = list_entry(item); if (netdev_address_to_str(n, ip_str, sizeof(ip_str))==NULL) HIP_PERROR("netdev_address_to_str"); else { if (ips_str[0]!=0) // not empty strncat(ips_str, " ", sizeof(ips_str)-strlen(ips_str)); strncat(ips_str, ip_str, sizeof(ips_str)-strlen(ips_str)); } } run_nsupdate(ips_str, hit, start); return 0; }
/** * init_dht_gateway_socket_gw - Initializes socket for the openDHT communications based on gateway address family * @param sockfd Socket descriptor to be initialized. * @param af Address family * * @return Returns positive if socket creation was ok negative on error. */ int init_dht_gateway_socket_gw(int sockfd, struct addrinfo *gateway) { //default address family int af = AF_INET; if(gateway) af = gateway->ai_family; if ((sockfd = socket(af, SOCK_STREAM, IPPROTO_TCP)) < 0) HIP_PERROR("OpenDHT socket\n"); return(sockfd); }
int opendht_send(int sockfd, void *packet) { int err = 0, len = strlen((char *)packet); _HIP_DEBUG("Packet: %s\n",put_packet); _HIP_DEBUG("OpenDHT send: packet length: %d\n", len); if (len > 0) err = send(sockfd, (char *) packet, len, 0); if (err < 1) HIP_PERROR("Error opendht_send: "); return 0; }
/* * returns string "name=value" * remember to free() */ char *make_env(char *name, char *value) { if ((name==NULL) || (value==NULL)) return NULL; char *result = malloc(strlen(name) + 1 + strlen(value) + 1); // name,'=',value,0 if (result == NULL) { HIP_PERROR("malloc"); return NULL; } strcpy(result, name); strcat(result, "="); strcat(result, value); return result; }
/* * Close file descriptors except for the standard output and the standard error */ int close_all_fds_except_stdout_and_stderr() { /* get maximum file descriptor number that can be opened */ struct rlimit rlim; if (getrlimit(RLIMIT_NOFILE, &rlim)!=0) { HIP_PERROR("getrlimit"); return ERR; } int fd; // no C99 :( for (fd = 0; fd < rlim.rlim_cur; fd++) switch (fd) { case STDOUT_FILENO: break; case STDERR_FILENO: break; default: close(fd); } return OK; }
/** * connect_dht_gateway - Connects to given v6 gateway * @param sockfd * @param addrinfo Address to connect to * @param blocking 1 for blocking connect 0 for nonblocking * * @return Returns 0 on success -1 otherwise, if nonblocking can return EINPRGORESS */ int connect_dht_gateway(int sockfd, struct addrinfo * gateway, int blocking){ int flags = 0, error = 0; struct sockaddr_in *sa_v4; struct sockaddr_in6 *sa_v6; struct sigaction act, oact; act.sa_handler = connect_alarm; sigemptyset(&act.sa_mask); act.sa_flags = 0; if(gateway == NULL){ HIP_ERROR("No OpenDHT Serving Gateway Address.\n"); return(-1); } if(blocking == 0) goto unblock; // blocking connect if(sigaction(SIGALRM, &act, &oact) < 0){ HIP_DEBUG("Signal error before OpenDHT connect, " "connecting without alarm\n"); error = connect(sockfd, gateway->ai_addr, gateway->ai_addrlen); }else { HIP_DEBUG("Connecting to OpenDHT with alarm\n"); if (alarm(DHT_CONNECT_TIMEOUT) != 0) HIP_DEBUG("Alarm was already set, connecting without\n"); error = connect(sockfd, gateway->ai_addr, gateway->ai_addrlen); alarm(0); if (sigaction(SIGALRM, &oact, &act) <0 ) HIP_DEBUG("Signal error after OpenDHT connect\n"); } if(error < 0){ HIP_PERROR("OpenDHT connect:"); if (errno == EINTR) HIP_DEBUG("Connect to OpenDHT timedout\n"); return(-1); }else{ if(gateway->ai_family == AF_INET){ sa_v4 = (struct sockaddr_in *)gateway->ai_addr; HIP_DEBUG_INADDR("Connected to OpenDHT v4 gateway", &(sa_v4->sin_addr)); } else if(gateway->ai_family == AF_INET6){ sa_v6 = (struct sockaddr_in6 *)gateway->ai_addr; HIP_DEBUG_IN6ADDR("Connected to OpenDHT v6 gateway", &(sa_v6->sin6_addr)); } else{ HIP_DEBUG("Wrong address family for OPENDHT gateway %d\n", gateway->ai_family); } return(0); } unblock: // unblocking connect flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); if(gateway->ai_family == AF_INET){ sa_v4 = (struct sockaddr_in *)gateway->ai_addr; HIP_DEBUG_INADDR("Connecting to OpenDHT v4 gateway", &(sa_v4->sin_addr)); } else if(gateway->ai_family == AF_INET6){ sa_v6 = (struct sockaddr_in6 *)gateway->ai_addr; HIP_DEBUG_IN6ADDR("Connecting to OpenDHT v6 gateway", &(sa_v6->sin6_addr)); } else{ HIP_DEBUG("Wrong address family for OPENDHT gateway %d\n", gateway->ai_family); } if(connect(sockfd, gateway->ai_addr, gateway->ai_addrlen) < 0){ if (errno == EINPROGRESS) return(EINPROGRESS); else{ HIP_PERROR("OpenDHT connect:"); return(-1); } }else{ // connect ok return(0); } }
/** * main_server_native - it handles the functionality of the client-native * @param socktype the type of socket * @param port_name the prot number * * @return 1 with success, 0 otherwise. */ int main_server_native(int socktype, char *port_name, char *name) { struct endpointinfo hints, *res = NULL; struct sockaddr_eid peer_eid; struct sockaddr_hip our_sockaddr, peer_sock; char mylovemostdata[IP_MAXPACKET]; int recvnum, sendnum, serversock = 0, sockfd = 0, err = 0, on = 1; int endpoint_family = PF_HIP; socklen_t peer_eid_len = sizeof(struct sockaddr_hip); /* recvmsg() stuff for UDP multihoming */ char control[CMSG_SPACE(40)]; struct cmsghdr *cmsg; struct inet6_pktinfo *pktinfo; struct iovec iov = { &mylovemostdata, sizeof(mylovemostdata) - 1 }; struct msghdr msg = { &peer_sock, sizeof(peer_sock), &iov, 1, &control, sizeof(control), 0 }; serversock = socket(endpoint_family, socktype, 0); if (serversock < 0) { HIP_PERROR("socket: "); err = 1; goto out_err; } setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (socktype == SOCK_DGRAM) setsockopt(serversock, IPPROTO_IPV6, IPV6_2292PKTINFO, &on, sizeof(on)); memset(&hints, 0, sizeof(struct endpointinfo)); hints.ei_family = endpoint_family; hints.ei_socktype = socktype; HIP_DEBUG("Native server calls getendpointinfo\n"); err = getendpointinfo(NULL, port_name, &hints, &res); if (err || !res) { HIP_ERROR("Resolving of peer identifiers failed (%d)\n", err); goto out_err; } memset(&our_sockaddr, 0, sizeof(struct sockaddr_hip)); if (name) { HIP_IFEL(inet_pton(AF_INET6, name, &our_sockaddr.ship_hit) != 1, 1, "Failed to parse HIT\n"); } our_sockaddr.ship_port = htons(atoi(port_name)); HIP_DEBUG("Binding to port %d\n", ntohs(our_sockaddr.ship_port)); our_sockaddr.ship_family = endpoint_family; if (bind(serversock, &our_sockaddr, sizeof(struct sockaddr_hip)) < 0) { HIP_PERROR("bind: "); err = 1; goto out_err; } HIP_DEBUG("Native server calls listen\n"); if (socktype == SOCK_STREAM && listen(serversock, 1) < 0) { HIP_PERROR("listen: "); err = 1; goto out_err; } HIP_DEBUG("Native server waits connection request\n"); while(1) { if (socktype == SOCK_STREAM) { sockfd = accept(serversock, (struct sockaddr *) &peer_sock, &peer_eid_len); if (sockfd < 0) { HIP_PERROR("accept: "); err = 1; goto out_err; } while((recvnum = recv(sockfd, mylovemostdata, sizeof(mylovemostdata), 0)) > 0 ) { mylovemostdata[recvnum] = '\0'; printf("%s", mylovemostdata); fflush(stdout); sendnum = send(sockfd, mylovemostdata, recvnum, 0); if (sendnum < 0) { HIP_PERROR("send: "); err = 1; goto out_err; } } } else { /* UDP */ sockfd = serversock; serversock = 0; while((recvnum = recvmsg(sockfd, &msg, 0)) > 0) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_2292PKTINFO) { pktinfo = CMSG_DATA(cmsg); break; } } HIP_DEBUG_HIT("localaddr", &pktinfo->ipi6_addr); iov.iov_len = strlen(mylovemostdata); /* ancillary data contains the src * and dst addresses */ sendnum = sendmsg(sockfd, &msg, 0); if (sendnum < 0) { HIP_PERROR("sendto: "); err = 1; goto out_err; } } } } out_err: if (res) free_endpointinfo(res); if (sockfd) close(sockfd); // discard errors if (serversock) close(serversock); // discard errors return err; }
/** * main_client_native - it handles the functionality of the client-native * @param proto type of protocol * @param socktype the type of socket * @param peer_name the peer name * @param peer_port_name the prot number * * @return 1 with success, 0 otherwise. */ int main_client_native(int socktype, char *peer_name, char *peer_port_name) { //struct endpointinfo hints, *epinfo = NULL, *res = NULL; //struct endpointinfo *epinfo; struct addrinfo hints, *res = NULL; struct timeval stats_before, stats_after; struct sockaddr_hip peer_sock; unsigned long stats_diff_sec, stats_diff_usec; char mylovemostdata[IP_MAXPACKET]; char receiveddata[IP_MAXPACKET]; int recvnum, sendnum; int datalen = 0; int datasent = 0; int datareceived = 0; int ch; int err = 0; int sockfd = -1; se_family_t endpoint_family; endpoint_family = PF_HIP; sockfd = socket(endpoint_family, socktype, 0); HIP_IFEL(sockfd < 0, 1, "creation of socket failed\n"); #if 0 /* set up host lookup information */ memset(&hints, 0, sizeof(hints)); //hints.ei_socktype = socktype; //hints.ei_family = endpoint_family; hints.ai_socktype = socktype; hints.ai_family = endpoint_family; /* Use the following flags to use only the kernel list for name resolution * hints.ei_flags = AI_HIP | AI_KERNEL_LIST; */ /* lookup host */ //err = getendpointinfo(peer_name, peer_port_name, &hints, &res); if (err) { HIP_ERROR("getendpointfo failed\n"); goto out_err; } //hints.ai_flags |= AI_EXTFLAGS; //hints.ai_eflags |= HIP_PREFER_ORCHID; err = getaddrinfo(peer_name, peer_port_name, &hints, &res); if (err) { HIP_ERROR("getaddrinfo failed (%d): %s\n", err, gepi_strerror(err)); goto out_err; } if (!res) { HIP_ERROR("NULL result, TODO\n"); goto out_err; } /* HIP_DEBUG("family=%d value=%d\n", res->ei_family, ntohs(((struct sockaddr_eid *) res->ei_endpoint)->eid_val)); */ #endif /* XX TODO: Do a proper getaddrinfo() */ memset(&peer_sock, 0, sizeof(peer_sock)); peer_sock.ship_family = PF_HIP; HIP_IFEL(inet_pton(AF_INET6, peer_name, &peer_sock.ship_hit) != 1, 1, "Failed to parse HIT\n"); peer_sock.ship_port = htons(atoi(peer_port_name)); HIP_DEBUG("Connecting to %s port %d\n", peer_name, peer_sock.ship_port); // data from stdin to buffer memset(receiveddata, 0, IP_MAXPACKET); memset(mylovemostdata, 0, IP_MAXPACKET); printf("Input some text, press enter and ctrl+d\n"); // horrible code while ((ch = fgetc(stdin)) != EOF && (datalen < IP_MAXPACKET)) { mylovemostdata[datalen] = (unsigned char) ch; datalen++; } gettimeofday(&stats_before, NULL); #if 0 epinfo = res; while(epinfo) { err = connect(sockfd, (struct sockaddr *) epinfo->ei_endpoint, epinfo->ei_endpointlen); //err = connect(sockfd, res->ai_addr, res->ai_addrlen); if (err) { HIP_PERROR("connect"); goto out_err; } epinfo = epinfo->ei_next; } #endif err = connect(sockfd, &peer_sock, sizeof(peer_sock)); if (err) { HIP_PERROR("connect: "); goto out_err; } gettimeofday(&stats_after, NULL); stats_diff_sec = (stats_after.tv_sec - stats_before.tv_sec) * 1000000; stats_diff_usec = stats_after.tv_usec - stats_before.tv_usec; HIP_DEBUG("connect took %.10f sec\n", (stats_diff_sec + stats_diff_usec) / 1000000.0); /* Send the data read from stdin to the server and read the response. The server should echo all the data received back to here. */ while((datasent < datalen) || (datareceived < datalen)) { if (datasent < datalen) { sendnum = send(sockfd, mylovemostdata + datasent, datalen - datasent, 0); if (sendnum < 0) { HIP_PERROR("send"); err = 1; goto out_err; } datasent += sendnum; } if (datareceived < datalen) { recvnum = recv(sockfd, receiveddata + datareceived, datalen-datareceived, 0); if (recvnum <= 0) { HIP_PERROR("recv"); err = 1; goto out_err; } datareceived += recvnum; } } HIP_IFEL(memcmp(mylovemostdata, receiveddata, IP_MAXPACKET), 1, "Sent and received data did not match\n"); out_err: /*if (res) //free_endpointinfo(res); freeaddrinfo(res);*/ if (sockfd > -1) close(sockfd); // discard errors HIP_INFO("Result of data transfer: %s.\n", (err ? "FAIL" : "OK")); return err; }