+void *udpdtlsserverrd(void *arg) {
+ int cnt, s = *(int *)arg;
+ unsigned char buf[4];
+ struct sockaddr_storage from;
+ socklen_t fromlen = sizeof(from);
+ struct clsrvconf *conf;
+ struct list_node *node;
+ struct client *client;
+ fd_set readfds;
+ pthread_t dtlsserverth;
+
+ for (;;) {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ if (select(s + 1, &readfds, NULL, NULL, NULL) < 1)
+ continue;
+ cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
+ if (cnt == -1) {
+ debug(DBG_WARN, "udpdtlsserverrd: recv failed");
+ continue;
+ }
+ conf = find_conf(RAD_DTLS, (struct sockaddr *)&from, clconfs, NULL);
+ if (!conf) {
+ debug(DBG_WARN, "udpdtlsserverrd: got packet from wrong or unknown DTLS peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen));
+ recv(s, buf, 4, 0);
+ continue;
+ }
+
+ node = list_first(conf->clients);
+ if (node)
+ client = (struct client *)node->data;
+ else {
+ client = addclient(conf);
+ if (!client) {
+ recv(s, buf, 4, 0);
+ continue;
+ }
+ client->sock = s;
+ memcpy(&client->addr, &from, fromlen);
+ if (pthread_create(&dtlsserverth, NULL, dtlsservernew, (void *)client)) {
+ debug(DBG_ERR, "udpdtlsserverrd: pthread_create failed");
+ removeclient(client);
+ recv(s, buf, 4, 0);
+ continue;
+ }
+ pthread_detach(dtlsserverth);
+ }
+ if (udp2bio(s, client->rbios, cnt))
+ debug(DBG_DBG, "udpdtlsserverrd: got DTLS in UDP from %s", addr2string((struct sockaddr *)&from, fromlen));
+ }
+}
+