int join(struct sockaddr *sa) { int sockfd; int rc; sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd==-1){ cw_log(LOG_ERR,"Can't create socket: %s\n",strerror(errno)); return -1; } sock_set_recvtimeout(sockfd,1); rc = connect(sockfd,(struct sockaddr*)sa,sock_addrlen((struct sockaddr*)sa)); if (rc<0){ char str[100]; sock_addrtostr(sa,str,100); cw_log(LOG_ERR,"Can't connect to %s: %s\n",str,strerror(errno)); close(sockfd); return -1; } struct conn * conn = get_conn(); conn->sock=sockfd; sock_copyaddr(&conn->addr,sa); #ifdef WITH_DTLS cw_dbg (DBG_DTLS,"Establishing DTLS session with %s",sock_addr2str(sa)); /* #ifdef WITH_CW_LOG_DEBUG { char str[100]; sock_addrtostr(sa,str,100); cw_log_debug0("Establishing DTLS connection to %s",str); } #endif */ if (conf_dtls_psk){ conn->dtls_psk=conf_dtls_psk; conn->dtls_psk_len=strlen(conn->dtls_psk); conn->dtls_cipher=conf_dtls_cipher; } if (conf_sslkeyfilename && conf_sslcertfilename){ conn->dtls_key_file = conf_sslkeyfilename; conn->dtls_cert_file = conf_sslcertfilename; conn->dtls_key_pass = conf_sslkeypass; conn->dtls_cipher=conf_dtls_cipher; } rc = dtls_connect(conn); if (rc!=1){ dtls_shutdown(conn); char str[100]; sock_addrtostr(sa,str,100); cw_log(LOG_ERR,"Cant establish DTLS connection to %s",str); close(sockfd); return 0; } #endif cw_dbg (DBG_DTLS,"DTLS session established with %s, cipher=%s",sock_addr2str(sa),dtls_get_cipher(conn)); exit(0); #ifdef WITH_CW_LOG_DEBUG { char str[100]; sock_addrtostr(sa,str,100); cw_log_debug0("DTLS connection to %s established",str); } #endif join_state(conn); return 1; }
/** * Run discovery for on address (eg broadcast 255.255.255.255) */ static int cw_run_discovery(struct conn *conn, const char *acaddr) { /* get addr of destination */ struct addrinfo hints; struct addrinfo *res, *res0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; int rc = getaddrinfo(acaddr, conf_control_port, &hints, &res0); if (rc) { cw_log(LOG_ERR, "Can't connect to AC %s: %s", acaddr, gai_strerror(rc)); return 0; } for (res = res0; res; res = res->ai_next) { int sockfd; int opt; sockfd = socket(res->ai_family, SOCK_DGRAM, 0); if (sockfd == -1) { cw_log(LOG_ERR, "Can't create socket for %s: %s", acaddr, strerror(errno)); continue; } opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0) { cw_log(LOG_ERR, "Can't set broadcast sockopt"); } sock_set_recvtimeout(sockfd, 1); sock_set_dontfrag(sockfd, 0); sock_copyaddr(&conn->addr, res->ai_addr); if (conf_ip){ struct sockaddr bind_address; sock_strtoaddr(conf_ip,&bind_address); int brc = bind(sockfd,&bind_address,sock_addrlen(&bind_address)); if (brc<0) { cw_log(LOG_ERR,"Can't bind to %s",sock_addr2str(&bind_address)); return 0; } } conn->sock = sockfd; conn->readfrom = conn_recvfrom_packet; run_discovery(conn); conn->readfrom=NULL; close(sockfd); } freeaddrinfo(res0); return 0; }
ACIPLIST * do_discovery(const char *acaddr) { /* get an partially intialized connection object * (seqnum should be set) * */ struct conn * conn = get_conn(); if (!conn){ cw_log(LOG_ERR,"Can't create conn for %s: %s",acaddr,strerror(errno)); return 0; } /* get addr of destination */ struct addrinfo hints; struct addrinfo * res,*res0; memset(&hints,0,sizeof(hints)); hints.ai_socktype = SOCK_DGRAM; hints.ai_family = PF_UNSPEC; int rc = getaddrinfo(acaddr,conf_control_port,&hints,&res0); if(rc){ cw_log(LOG_ERR,"Can't connect to AC %s: %s",acaddr,gai_strerror(rc)); return 0; } struct discovery_info di; memset (&di,0,sizeof(struct discovery_info)); di.aciplist = aciplist_create(); di.response_count=0; for(res=res0; res; res=res->ai_next) { if ( discovery_count >= conf_max_discoveries){ sulking_state(); discovery_count=0; cw_log_debug0("Entering discovery state"); } discovery_count++; /* create socket */ int sockfd; int opt; sockfd=socket(res->ai_family,SOCK_DGRAM,0); if (sockfd == -1){ cw_log(LOG_ERR,"Can't create socket for %s: %s",acaddr,strerror(errno)); continue; } opt = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt))<0){ cw_log(LOG_ERR,"Cant set broadcast sockopt"); } sock_set_recvtimeout(sockfd,1); sock_set_dontfrag(sockfd,0); di.conn=conn; sock_copyaddr(&conn->addr,res->ai_addr); conn->sock=sockfd; do_discover_conn(conn,&di); close(sockfd); if ( di.aciplist->count != 0) break; } freeaddrinfo(res0); if (di.aciplist->count){ cw_log_debug2("Discover responses received: %i\n",di.response_count); return di.aciplist; } aciplist_destroy(di.aciplist); return 0; }