bool UdpSend( link_t *link, udp_hdr_t *udpHdr, ip_hdr_t *ipHdr, udp_descr_t *descr ) { bool success = FALSE; u8 *frame; static i8 UdpSendaddr[32]; i32 length; length = LinkLength(link); frame = (u8 *)x_malloc(length); if(frame!=0) { if(LinkCopy(link, frame, (u16)length)) { #ifdef XSTK_NUCNET #ifdef XLIB_XSNMP plist[0].charptr = (i8 *)Inet_NtoA(ipHdr->dst); plist[1].intval = udpHdr->dst; x_sprintf(UdpSendaddr,"udp:%s:%d"); #else sprintf(UdpSendaddr,"udp:%s:%d",Inet_NtoA(ipHdr->dst),udpHdr->dst); #endif #else #ifdef XLIB_XSNMP plist[0].charptr = (i8 *)Inet_NtoA(x_htonl(ipHdr->dst)); plist[1].intval = udpHdr->dst; x_sprintf(UdpSendaddr,"udp:%s:%d"); #else sprintf(UdpSendaddr,"udp:%s:%d",Inet_NtoA(x_htonl(ipHdr->dst)),udpHdr->dst); #endif #endif if(NwDgSendTo(UdpSendaddr, frame, length, udpHdr->src)) { success = TRUE; } else { } } x_free(frame); } if(success) { udpStat.outDatagrams++; } else { udpStat.outErrors++; } return success; }
stun_hdr_t * get_stun_full_request(const char *lufrag, const char *rufrag, const char *rpwd) { char fullfrag[128]; int i; uint32_t crc; char *ptr; stun_hdr_t *stn_req = NULL; stun_packet_t *stn_pkt = NULL; unsigned long int val; ENTER; TRACE("Generating stun packet for " "rufrag(%s),rpwd(%s),lufrag(%s)\n", rufrag, rpwd, lufrag); if (!lufrag || !rufrag || !rpwd) return NULL; x_sprintf(fullfrag, "%s:%s", rufrag, lufrag); stn_pkt = stun_pkt_new(); stun_set_attr_d(stn_pkt, STUN_PRIORITY, 4, (char *) &stn_pkt); val = random(); stun_set_attr_d(stn_pkt, STUN_ICE_CONTROLLED, 8, (char *) &val); stun_set_attr_d(stn_pkt, STUN_USERNAME, strlen(fullfrag), (char *) fullfrag); stn_req = stun_hdr_from_packet(stn_pkt); stn_req->mcookie = STUN_NET_M_COOKIE; stn_req->ver_type.raw = htons(STUN_REQ); // set transction id x_snprintf(stn_req->trans_id, sizeof(stn_req->trans_id), "%12d", (int) random()); stn_req = stun_add_integrity(stn_req, rpwd); // add CRC32 i = ntohs(stn_req->mlen) + sizeof(stun_hdr_t); stn_req = x_realloc(stn_req, i + 8); stn_req->mlen = htons(i + 8 - sizeof(stun_hdr_t)); crc = stun_get_fingerprint(stn_req); ptr = (char *) stn_req + i; *(uint16_t *) ptr = htons(STUN_FINGERPRINT); ptr += sizeof(uint16_t); *(uint16_t *) ptr = htons(4); ptr += sizeof(uint16_t); *(uint32_t *) ptr = htonl(crc ^ STUN_FINGERPRINT_XOR); stun_pkt_free(stn_pkt); EXIT; return stn_req; }
/* Returns a service name for a network port number */ char *dns_servfromport(int port) { struct servent *entry; char *str; entry = getservbyport(port, "tcp"); if (entry) { str = x_strdup(entry->s_name); } else { str = x_sprintf("%d", port); } return str; }
/* Called when a system call fails. Print it to stderr or syslog */ int syscall_fail(const char *function, const char *arg, const char *message) { char *msg; int err; err = errno; msg = x_sprintf("%s(%s) failed: %s", function, (arg ? arg : ""), (message ? message : strerror(err))); if (in_background) { syslog(LOG_NOTICE, "%s", msg); } else { #ifdef DEBUG fprintf(stderr, "%s: \033[33;1m%s\033[m\n", progname, msg); #else /* DEBUG */ fprintf(stderr, "%s: %s\n", progname, msg); #endif /* DEBUG */ } free(msg); return 0; }
/* We need this */ int main(int argc, char *argv[]) { int optc, show_help, show_version, show_usage; char *local_file, *cmd_listen_port, *cmd_pid_file; int inetd_mode, no_daemon; /* Set up some globals */ progname = argv[0]; listen_port = x_strdup(DEFAULT_LISTEN_PORT); pid_file = (DEFAULT_PID_FILE ? x_strdup(DEFAULT_PID_FILE) : 0); #ifndef DEBUG no_daemon = 0; #else /* DEBUG */ no_daemon = 1; #endif /* DEBUG */ local_file = cmd_listen_port = cmd_pid_file = 0; show_help = show_version = show_usage = inetd_mode = 0; while ((optc = getopt_long(argc, argv, GETOPTIONS, long_opts, NULL)) != -1) { switch (optc) { case 'h': show_help = 1; break; case 'v': show_version = 1; break; case 'D': #ifndef DEBUG no_daemon = 1; #else /* DEBUG */ no_daemon = 0; #endif /* DEBUG */ break; case 'I': inetd_mode = 1; break; case 'P': free(cmd_listen_port); cmd_listen_port = x_strdup(optarg); break; case 'p': free(cmd_pid_file); cmd_pid_file = x_strdup(optarg); break; case 'f': free(local_file); local_file = x_strdup(optarg); break; default: show_usage = 1; break; } } if (show_usage || (optind < argc)) { _print_usage(); return 1; } if (show_version) { _print_version(); if (!show_help) return 0; } if (show_help) { _print_help(); return 0; } /* If no -f was specified use the home directory */ if (!local_file && !inetd_mode) { struct stat statinfo; struct passwd *pw; pw = getpwuid(geteuid()); if (pw && pw->pw_dir) { local_file = x_sprintf("%s/%s", pw->pw_dir, USER_CONFIG_FILENAME); debug("Local config file: %s", local_file); if (!stat(local_file, &statinfo) && (statinfo.st_mode & 0077)) { fprintf(stderr, "%s: Permissions of %s must be 0700 or " "more restrictive\n", progname, local_file); free(local_file); return 2; } if (cfg_read(local_file, &listen_port, &pid_file, &g)) { /* If the local one didn't exist, set to 0 so we open global one */ free(local_file); local_file = 0; } else { config_file = x_strdup(local_file); } } } else if (local_file) { if (cfg_read(local_file, &listen_port, &pid_file, &g)) { /* This is fatal! */ fprintf(stderr, "%s: Couldn't read configuration from %s: %s\n", progname, local_file, strerror(errno)); free(local_file); return 2; } else { config_file = x_strdup(local_file); } } /* Read global config file if local one not found */ if (!local_file) { char *global_file; /* Not fatal if it doesn't exist */ global_file = x_sprintf("%s/%s", SYSCONFDIR, GLOBAL_CONFIG_FILENAME); debug("Global config file: %s", global_file); cfg_read(global_file, &listen_port, &pid_file, &g); config_file = x_strdup(global_file); free(global_file); } else { free(local_file); } /* Check we got some connection classes */ if (!connclasses) { fprintf(stderr, "%s: No connection classes have been defined.\n", progname); return 2; } /* -P overrides config file */ if (cmd_listen_port) { free(listen_port); listen_port = cmd_listen_port; } /* -p overrides pid file */ if (cmd_pid_file) { free(pid_file); pid_file = cmd_pid_file; } /* Set signal handlers */ signal(SIGTERM, _sig_term); signal(SIGINT, _sig_term); signal(SIGHUP, _sig_hup); signal(SIGCHLD, _sig_child); #ifdef DEBUG_MEMORY signal(SIGUSR1, _sig_usr); signal(SIGUSR2, _sig_usr); #endif /* DEBUG_MEMORY */ /* Broken Pipe? This means that someone disconnected while we were sending stuff. Naughty! */ signal(SIGPIPE, SIG_IGN); if (!inetd_mode) { debug("Ordinary console dodge-monkey mode"); /* Make listening socket before we fork */ if (ircnet_listen(listen_port)) { fprintf(stderr, "%s: Unable to establish listen port\n", progname); return 3; } /* go daemon here */ if (!no_daemon) { switch (go_daemon()) { case -1: return -1; case 0: break; default: return 0; } } } else { /* running under inetd means we are backgrounded right *now* */ in_background = 1; debug("Inetd SuperTed mode!"); /* Hook STDIN into a new proxy */ ircnet_hooksocket(STDIN_FILENO); } /* Open a connection to syslog if we're in the background */ if (in_background) openlog(PACKAGE, LOG_PID, LOG_USER); if (pid_file) { FILE *pidfile; pidfile = fopen(pid_file, "w"); if (pidfile) { fchmod(fileno(pidfile), 0600); fprintf(pidfile, "%d\n", getpid()); fclose(pidfile); } else { syscall_fail("fopen", pid_file, 0); } } /* Main loop! */ while (!stop_poll) { int ns, nt, status; pid_t pid; ircnet_expunge_proxies(); dccnet_expunge_proxies(); ns = net_poll(); nt = timer_poll(); /* Reap any children */ while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { debug("Reaped process %d, exit status %d", pid, status); /* Handle any DNS children */ dns_endrequest(pid, status); } /* Reload the configuration file? */ if (reload_config) { _reload_config(); reload_config = 0; } if (!ns && !nt) break; } if (pid_file) { unlink(pid_file); } /* Free up stuff */ ircnet_flush(); dccnet_flush(); dns_flush(); timer_flush(); /* Do a lingering close on all sockets */ net_closeall(); net_flush(); /* Close down and free up memory */ if (!inetd_mode && !no_daemon) closelog(); free(listen_port); free(pid_file); free(config_file); #ifdef DEBUG_MEMORY mem_report("termination"); #endif /* DEBUG_MEMORY */ return 0; }