main() { char *x; int udp53; x = env_get("IP"); if (!x) strerr_die2x(111,fatal,"$IP not set"); if (!ip4_scan(x,ip)) strerr_die3x(111,fatal,"unable to parse IP address ",x); udp53 = socket_udp(); if (udp53 == -1) strerr_die2sys(111,fatal,"unable to create UDP socket: "); if (socket_bind4_reuse(udp53,ip,53) == -1) strerr_die2sys(111,fatal,"unable to bind UDP socket: "); droproot(fatal); initialize(); ndelay_off(udp53); socket_tryreservein(udp53,65536); for (;;) { len = socket_recv4(udp53,buf,sizeof buf,ip,&port); if (len < 0) continue; if (!doit()) continue; if (response_len > 512) response_tc(); socket_send4(udp53,response,response_len,ip,port); /* may block for buffer space; if it fails, too bad */ } }
void u_new (void) { int i = 0, j = 0, len = 0; struct udpclient *x = NULL; static char *q = 0; char qtype[2], qclass[2]; for (j = 0; j < MAXUDP; j++) if (!u[j].active) break; if (j >= MAXUDP) { j = 0; for (i = 1; i < MAXUDP; i++) if (taia_less (&u[i].start, &u[j].start)) j = i; errno = error_timeout; u_drop (j); } x = u + j; taia_now (&x->start); len = socket_recv4 (udp53, buf, sizeof (buf), x->ip, &x->port, &odst); if (len == -1) return; if ((unsigned)len >= sizeof buf) return; if (x->port < 1024 && x->port != 53) return; if (!okclient (x->ip)) return; if (!packetquery (buf, len, &q, qtype, qclass, x->id)) return; x->active = ++numqueries; ++uactive; if (debug_level) log_query (x->active, x->ip, x->port, x->id, q, qtype); switch (query_start (&x->q, q, qtype, qclass, myipoutgoing)) { case -1: u_drop (j); return; case 1: u_respond (j); } }
static int receive_packet(uint32 type, int minlength, int maxlength) { int i; uint32 t; if ((i = socket_recv4(sock, rpacket.s, rpacket.size, &ip,&port)) < 0) REJECT1("Socket receive failed"); if (i < minlength) REJECT1("Received packet is too short"); if (maxlength > 0 && i > maxlength) REJECT1("Received packet is too long"); rpacket.len = i; pkt_get_u4(&rpacket, 0, &t); if (t != SRL2) REJECT1("Received packet format was not SRL2"); pkt_get_u4(&rpacket, 4, &t); if (t != type) REJECT1("Received incorrect packet type"); return 1; }
static void * livesync_worker( void * args ) { struct ot_workstruct ws; ot_ip6 in_ip; uint16_t in_port; (void)args; /* Initialize our "thread local storage" */ ws.inbuf = ws.request = malloc( LIVESYNC_INCOMING_BUFFSIZE ); ws.outbuf = ws.reply = 0; memcpy( in_ip, V4mappedprefix, sizeof( V4mappedprefix ) ); while( 1 ) { ws.request_size = socket_recv4(g_socket_in, (char*)ws.inbuf, LIVESYNC_INCOMING_BUFFSIZE, 12+(char*)in_ip, &in_port); /* Expect at least tracker id and packet type */ if( ws.request_size <= (ssize_t)(sizeof( g_tracker_id ) + sizeof( uint32_t )) ) continue; if( !accesslist_isblessed(in_ip, OT_PERMISSION_MAY_LIVESYNC)) continue; if( !memcmp( ws.inbuf, &g_tracker_id, sizeof( g_tracker_id ) ) ) { /* TODO: log packet coming from ourselves */ continue; } switch( uint32_read_big( sizeof( g_tracker_id ) + (char *)ws.inbuf ) ) { case OT_SYNC_PEER: livesync_handle_peersync( &ws ); break; default: break; } } /* Never returns. */ return NULL; }
int main (int argc, char *argv[]) { time_t t = 0; char *x = NULL; struct sigaction sa; iopause_fd *iop = NULL; int i = 0, n = 0, *udp53 = NULL; prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); i = check_option (argc, argv); argc -= i; argv += i; if (mode & DAEMON) { i = fork (); if (i == -1) err (-1, "could not fork a daemon process"); if (i > 0) return 0; } time (&t); memset (buf, 0, sizeof (buf)); strftime (buf, sizeof (buf), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting: %s\n", VERSION, buf); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); initialize (); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); if ((x = env_get ("DATALIMIT"))) { struct rlimit r; unsigned long dlimit = atol (x); if (getrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not get resource RLIMIT_DATA"); r.rlim_cur = (dlimit <= r.rlim_max) ? dlimit : r.rlim_max; if (setrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not set resource RLIMIT_DATA"); if (debug_level) warnx ("DATALIMIT set to `%ld' bytes", r.rlim_cur); } if (!(x = env_get ("IP"))) err (-1, "$IP not set"); for (i = 0; (unsigned)i < strlen (x); i++) n = (x[i] == ',') ? n+1 : n; if (!(udp53 = calloc (n+1, sizeof (int)))) err (-1, "could not allocate enough memory for udp53"); if (!(iop = calloc (n+1, sizeof (iopause_fd)))) err (-1, "could not allocate enough memory for iop"); i = n = 0; while (x[i]) { unsigned int l = 0; if (!(l = ip4_scan(x+i, ip))) errx (-1, "could not parse IP address `%s'", x + i); udp53[n] = socket_udp(); if (udp53[n] == -1) errx (-1, "could not open UDP socket"); if (socket_bind4_reuse (udp53[n], ip, server_port) == -1) errx (-1, "could not bind UDP socket"); ndelay_off (udp53[n]); socket_tryreservein (udp53[n], 65536); iop[n].fd = udp53[n]; iop[n].events = IOPAUSE_READ; n++; i += (x[i + l] == ',') ? l + 1 : l; } droproot (); while (1) { struct taia stamp; struct in_addr odst; /* original destination IP */ struct taia deadline; taia_now (&stamp); taia_uint (&deadline, 300); taia_add (&deadline, &deadline, &stamp); iopause (iop, n, &deadline, &stamp); for (i = 0; i < n; i++) { if (!iop[i].revents) continue; len = socket_recv4 (udp53[i], buf, sizeof (buf), ip, &port, &odst); if (len < 0) continue; if (!doit ()) continue; if (response_len > 512) response_tc (); /* may block for buffer space; if it fails, too bad */ len = socket_send4 (udp53[i], response, response_len, ip, port, &odst); if (len < 0) continue; if (debug_level > 1) log_querydone(qnum, response, response_len); } } return 0; }